[WEB-5044] fix: ruff lint and format errors (#7868)

* fix: lint errors

* fix: file formatting

* fix: code refactor
This commit is contained in:
sriram veeraghanta 2025-09-29 19:15:32 +05:30 committed by GitHub
parent 1fb22bd252
commit 9237f568dd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
261 changed files with 2199 additions and 6378 deletions

View file

@ -84,4 +84,4 @@ from .device import Device, DeviceSession
from .sticky import Sticky
from .description import Description, DescriptionVersion
from .description import Description, DescriptionVersion

View file

@ -5,9 +5,7 @@ from .base import BaseModel
class AnalyticView(BaseModel):
workspace = models.ForeignKey(
"db.Workspace", related_name="analytics", on_delete=models.CASCADE
)
workspace = models.ForeignKey("db.Workspace", related_name="analytics", on_delete=models.CASCADE)
name = models.CharField(max_length=255)
description = models.TextField(blank=True)
query = models.JSONField()

View file

@ -24,20 +24,12 @@ class APIToken(BaseModel):
last_used = models.DateTimeField(null=True)
# Token
token = models.CharField(
max_length=255, unique=True, default=generate_token, db_index=True
)
token = models.CharField(max_length=255, unique=True, default=generate_token, db_index=True)
# User Information
user = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="bot_tokens"
)
user_type = models.PositiveSmallIntegerField(
choices=((0, "Human"), (1, "Bot")), default=0
)
workspace = models.ForeignKey(
"db.Workspace", related_name="api_tokens", on_delete=models.CASCADE, null=True
)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="bot_tokens")
user_type = models.PositiveSmallIntegerField(choices=((0, "Human"), (1, "Bot")), default=0)
workspace = models.ForeignKey("db.Workspace", related_name="api_tokens", on_delete=models.CASCADE, null=True)
expired_at = models.DateTimeField(blank=True, null=True)
is_service = models.BooleanField(default=False)

View file

@ -40,27 +40,13 @@ class FileAsset(BaseModel):
attributes = models.JSONField(default=dict)
asset = models.FileField(upload_to=get_upload_path, max_length=800)
user = models.ForeignKey(
"db.User", on_delete=models.CASCADE, null=True, related_name="assets"
)
workspace = models.ForeignKey(
"db.Workspace", on_delete=models.CASCADE, null=True, related_name="assets"
)
draft_issue = models.ForeignKey(
"db.DraftIssue", on_delete=models.CASCADE, null=True, related_name="assets"
)
project = models.ForeignKey(
"db.Project", on_delete=models.CASCADE, null=True, related_name="assets"
)
issue = models.ForeignKey(
"db.Issue", on_delete=models.CASCADE, null=True, related_name="assets"
)
comment = models.ForeignKey(
"db.IssueComment", on_delete=models.CASCADE, null=True, related_name="assets"
)
page = models.ForeignKey(
"db.Page", on_delete=models.CASCADE, null=True, related_name="assets"
)
user = models.ForeignKey("db.User", on_delete=models.CASCADE, null=True, related_name="assets")
workspace = models.ForeignKey("db.Workspace", on_delete=models.CASCADE, null=True, related_name="assets")
draft_issue = models.ForeignKey("db.DraftIssue", on_delete=models.CASCADE, null=True, related_name="assets")
project = models.ForeignKey("db.Project", on_delete=models.CASCADE, null=True, related_name="assets")
issue = models.ForeignKey("db.Issue", on_delete=models.CASCADE, null=True, related_name="assets")
comment = models.ForeignKey("db.IssueComment", on_delete=models.CASCADE, null=True, related_name="assets")
page = models.ForeignKey("db.Page", on_delete=models.CASCADE, null=True, related_name="assets")
entity_type = models.CharField(max_length=255, null=True, blank=True)
entity_identifier = models.CharField(max_length=255, null=True, blank=True)
is_deleted = models.BooleanField(default=False)
@ -78,12 +64,8 @@ class FileAsset(BaseModel):
ordering = ("-created_at",)
indexes = [
models.Index(fields=["entity_type"], name="asset_entity_type_idx"),
models.Index(
fields=["entity_identifier"], name="asset_entity_identifier_idx"
),
models.Index(
fields=["entity_type", "entity_identifier"], name="asset_entity_idx"
),
models.Index(fields=["entity_identifier"], name="asset_entity_identifier_idx"),
models.Index(fields=["entity_type", "entity_identifier"], name="asset_entity_idx"),
]
def __str__(self):
@ -100,7 +82,7 @@ class FileAsset(BaseModel):
return f"/api/assets/v2/static/{self.id}/"
if self.entity_type == self.EntityTypeContext.ISSUE_ATTACHMENT:
return f"/api/assets/v2/workspaces/{self.workspace.slug}/projects/{self.project_id}/issues/{self.issue_id}/attachments/{self.id}/"
return f"/api/assets/v2/workspaces/{self.workspace.slug}/projects/{self.project_id}/issues/{self.issue_id}/attachments/{self.id}/" # noqa: E501
if self.entity_type in [
self.EntityTypeContext.ISSUE_DESCRIPTION,

View file

@ -11,9 +11,7 @@ from ..mixins import AuditModel
class BaseModel(AuditModel):
id = models.UUIDField(
default=uuid.uuid4, unique=True, editable=False, db_index=True, primary_key=True
)
id = models.UUIDField(default=uuid.uuid4, unique=True, editable=False, db_index=True, primary_key=True)
class Meta:
abstract = True

View file

@ -102,12 +102,8 @@ class CycleIssue(ProjectBaseModel):
Cycle Issues
"""
issue = models.ForeignKey(
"db.Issue", on_delete=models.CASCADE, related_name="issue_cycle"
)
cycle = models.ForeignKey(
Cycle, on_delete=models.CASCADE, related_name="issue_cycle"
)
issue = models.ForeignKey("db.Issue", on_delete=models.CASCADE, related_name="issue_cycle")
cycle = models.ForeignKey(Cycle, on_delete=models.CASCADE, related_name="issue_cycle")
class Meta:
unique_together = ["issue", "cycle", "deleted_at"]
@ -128,9 +124,7 @@ class CycleIssue(ProjectBaseModel):
class CycleUserProperties(ProjectBaseModel):
cycle = models.ForeignKey(
"db.Cycle", on_delete=models.CASCADE, related_name="cycle_user_properties"
)
cycle = models.ForeignKey("db.Cycle", on_delete=models.CASCADE, related_name="cycle_user_properties")
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,

View file

@ -25,14 +25,10 @@ class DeployBoard(WorkspaceBaseModel):
entity_identifier = models.UUIDField(null=True)
entity_name = models.CharField(max_length=30, null=True, blank=True)
anchor = models.CharField(
max_length=255, default=get_anchor, unique=True, db_index=True
)
anchor = models.CharField(max_length=255, default=get_anchor, unique=True, db_index=True)
is_comments_enabled = models.BooleanField(default=False)
is_reactions_enabled = models.BooleanField(default=False)
intake = models.ForeignKey(
"db.Intake", related_name="publish_intake", on_delete=models.SET_NULL, null=True
)
intake = models.ForeignKey("db.Intake", related_name="publish_intake", on_delete=models.SET_NULL, null=True)
is_votes_enabled = models.BooleanField(default=False)
view_props = models.JSONField(default=dict)
is_activity_enabled = models.BooleanField(default=True)

View file

@ -4,8 +4,6 @@ from .workspace import WorkspaceBaseModel
class Description(WorkspaceBaseModel):
description_json = models.JSONField(default=dict, blank=True)
description_html = models.TextField(blank=True, default="<p></p>")
description_binary = models.BinaryField(null=True)
@ -32,9 +30,7 @@ class DescriptionVersion(WorkspaceBaseModel):
DescriptionVersion is a model used to store historical versions of a Description.
"""
description = models.ForeignKey(
"db.Description", on_delete=models.CASCADE, related_name="versions"
)
description = models.ForeignKey("db.Description", on_delete=models.CASCADE, related_name="versions")
description_json = models.JSONField(default=dict, blank=True)
description_html = models.TextField(blank=True, default="<p></p>")
description_binary = models.BinaryField(null=True)

View file

@ -11,9 +11,7 @@ class Device(BaseModel):
WEB = "WEB", "Web"
DESKTOP = "DESKTOP", "Desktop"
user = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="devices"
)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="devices")
device_id = models.CharField(max_length=255, blank=True, null=True)
device_type = models.CharField(max_length=255, choices=DeviceType.choices)
push_token = models.CharField(max_length=255, blank=True, null=True)
@ -26,12 +24,8 @@ class Device(BaseModel):
class DeviceSession(BaseModel):
device = models.ForeignKey(
Device, on_delete=models.CASCADE, related_name="sessions"
)
session = models.ForeignKey(
"db.Session", on_delete=models.CASCADE, related_name="device_sessions"
)
device = models.ForeignKey(Device, on_delete=models.CASCADE, related_name="sessions")
session = models.ForeignKey("db.Session", on_delete=models.CASCADE, related_name="device_sessions")
is_active = models.BooleanField(default=True)
user_agent = models.CharField(max_length=255, null=True, blank=True)
ip_address = models.GenericIPAddressField(null=True, blank=True)

View file

@ -38,9 +38,7 @@ class DraftIssue(WorkspaceBaseModel):
null=True,
blank=True,
)
name = models.CharField(
max_length=255, verbose_name="Issue Name", blank=True, null=True
)
name = models.CharField(max_length=255, verbose_name="Issue Name", blank=True, null=True)
description = models.JSONField(blank=True, default=dict)
description_html = models.TextField(blank=True, default="<p></p>")
description_stripped = models.TextField(blank=True, null=True)
@ -60,9 +58,7 @@ class DraftIssue(WorkspaceBaseModel):
through="DraftIssueAssignee",
through_fields=("draft_issue", "assignee"),
)
labels = models.ManyToManyField(
"db.Label", blank=True, related_name="draft_labels", through="DraftIssueLabel"
)
labels = models.ManyToManyField("db.Label", blank=True, related_name="draft_labels", through="DraftIssueLabel")
sort_order = models.FloatField(default=65535)
completed_at = models.DateTimeField(null=True)
external_source = models.CharField(max_length=255, null=True, blank=True)
@ -90,9 +86,7 @@ class DraftIssue(WorkspaceBaseModel):
~models.Q(is_triage=True), project=self.project, default=True
).first()
if default_state is None:
random_state = State.objects.filter(
~models.Q(is_triage=True), project=self.project
).first()
random_state = State.objects.filter(~models.Q(is_triage=True), project=self.project).first()
self.state = random_state
else:
self.state = default_state
@ -116,9 +110,9 @@ class DraftIssue(WorkspaceBaseModel):
if (self.description_html == "" or self.description_html is None)
else strip_tags(self.description_html)
)
largest_sort_order = DraftIssue.objects.filter(
project=self.project, state=self.state
).aggregate(largest=models.Max("sort_order"))["largest"]
largest_sort_order = DraftIssue.objects.filter(project=self.project, state=self.state).aggregate(
largest=models.Max("sort_order")
)["largest"]
if largest_sort_order is not None:
self.sort_order = largest_sort_order + 10000
@ -139,9 +133,7 @@ class DraftIssue(WorkspaceBaseModel):
class DraftIssueAssignee(WorkspaceBaseModel):
draft_issue = models.ForeignKey(
DraftIssue, on_delete=models.CASCADE, related_name="draft_issue_assignee"
)
draft_issue = models.ForeignKey(DraftIssue, on_delete=models.CASCADE, related_name="draft_issue_assignee")
assignee = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
@ -167,12 +159,8 @@ class DraftIssueAssignee(WorkspaceBaseModel):
class DraftIssueLabel(WorkspaceBaseModel):
draft_issue = models.ForeignKey(
"db.DraftIssue", on_delete=models.CASCADE, related_name="draft_label_issue"
)
label = models.ForeignKey(
"db.Label", on_delete=models.CASCADE, related_name="draft_label_issue"
)
draft_issue = models.ForeignKey("db.DraftIssue", on_delete=models.CASCADE, related_name="draft_label_issue")
label = models.ForeignKey("db.Label", on_delete=models.CASCADE, related_name="draft_label_issue")
class Meta:
verbose_name = "Draft Issue Label"
@ -185,12 +173,8 @@ class DraftIssueLabel(WorkspaceBaseModel):
class DraftIssueModule(WorkspaceBaseModel):
module = models.ForeignKey(
"db.Module", on_delete=models.CASCADE, related_name="draft_issue_module"
)
draft_issue = models.ForeignKey(
"db.DraftIssue", on_delete=models.CASCADE, related_name="draft_issue_module"
)
module = models.ForeignKey("db.Module", on_delete=models.CASCADE, related_name="draft_issue_module")
draft_issue = models.ForeignKey("db.DraftIssue", on_delete=models.CASCADE, related_name="draft_issue_module")
class Meta:
unique_together = ["draft_issue", "module", "deleted_at"]
@ -215,12 +199,8 @@ class DraftIssueCycle(WorkspaceBaseModel):
Draft Issue Cycles
"""
draft_issue = models.ForeignKey(
"db.DraftIssue", on_delete=models.CASCADE, related_name="draft_issue_cycle"
)
cycle = models.ForeignKey(
"db.Cycle", on_delete=models.CASCADE, related_name="draft_issue_cycle"
)
draft_issue = models.ForeignKey("db.DraftIssue", on_delete=models.CASCADE, related_name="draft_issue_cycle")
cycle = models.ForeignKey("db.Cycle", on_delete=models.CASCADE, related_name="draft_issue_cycle")
class Meta:
unique_together = ["draft_issue", "cycle", "deleted_at"]

View file

@ -33,12 +33,8 @@ class Estimate(ProjectBaseModel):
class EstimatePoint(ProjectBaseModel):
estimate = models.ForeignKey(
"db.Estimate", on_delete=models.CASCADE, related_name="points"
)
key = models.IntegerField(
default=0, validators=[MinValueValidator(0), MaxValueValidator(12)]
)
estimate = models.ForeignKey("db.Estimate", on_delete=models.CASCADE, related_name="points")
key = models.IntegerField(default=0, validators=[MinValueValidator(0), MaxValueValidator(12)])
description = models.TextField(blank=True)
value = models.CharField(max_length=255)

View file

@ -18,9 +18,7 @@ def generate_token():
class ExporterHistory(BaseModel):
name = models.CharField(
max_length=255, verbose_name="Exporter Name", null=True, blank=True
)
name = models.CharField(max_length=255, verbose_name="Exporter Name", null=True, blank=True)
type = models.CharField(
max_length=50,
default="issue_exports",
@ -29,13 +27,9 @@ class ExporterHistory(BaseModel):
("issue_worklogs", "Issue Worklogs"),
),
)
workspace = models.ForeignKey(
"db.WorkSpace", on_delete=models.CASCADE, related_name="workspace_exporters"
)
workspace = models.ForeignKey("db.WorkSpace", on_delete=models.CASCADE, related_name="workspace_exporters")
project = ArrayField(models.UUIDField(default=uuid.uuid4), blank=True, null=True)
provider = models.CharField(
max_length=50, choices=(("json", "json"), ("csv", "csv"), ("xlsx", "xlsx"))
)
provider = models.CharField(max_length=50, choices=(("json", "json"), ("csv", "csv"), ("xlsx", "xlsx")))
status = models.CharField(
max_length=50,
choices=(

View file

@ -12,9 +12,7 @@ class UserFavorite(WorkspaceBaseModel):
UserFavorite (model): To store all the favorites of the user
"""
user = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="favorites"
)
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)
@ -43,24 +41,20 @@ class UserFavorite(WorkspaceBaseModel):
ordering = ("-created_at",)
indexes = [
models.Index(fields=["entity_type"], name="fav_entity_type_idx"),
models.Index(
fields=["entity_identifier"], name="fav_entity_identifier_idx"
),
models.Index(
fields=["entity_type", "entity_identifier"], name="fav_entity_idx"
),
models.Index(fields=["entity_identifier"], name="fav_entity_identifier_idx"),
models.Index(fields=["entity_type", "entity_identifier"], name="fav_entity_idx"),
]
def save(self, *args, **kwargs):
if self._state.adding:
if self.project:
largest_sequence = UserFavorite.objects.filter(
workspace=self.project.workspace
).aggregate(largest=models.Max("sequence"))["largest"]
largest_sequence = UserFavorite.objects.filter(workspace=self.project.workspace).aggregate(
largest=models.Max("sequence")
)["largest"]
else:
largest_sequence = UserFavorite.objects.filter(
workspace=self.workspace
).aggregate(largest=models.Max("sequence"))["largest"]
largest_sequence = UserFavorite.objects.filter(workspace=self.workspace).aggregate(
largest=models.Max("sequence")
)["largest"]
if largest_sequence is not None:
self.sequence = largest_sequence + 10000

View file

@ -7,9 +7,7 @@ from .project import ProjectBaseModel
class Importer(ProjectBaseModel):
service = models.CharField(
max_length=50, choices=(("github", "GitHub"), ("jira", "Jira"))
)
service = models.CharField(max_length=50, choices=(("github", "GitHub"), ("jira", "Jira")))
status = models.CharField(
max_length=50,
choices=(
@ -20,15 +18,11 @@ class Importer(ProjectBaseModel):
),
default="queued",
)
initiated_by = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="imports"
)
initiated_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="imports")
metadata = models.JSONField(default=dict)
config = models.JSONField(default=dict)
data = models.JSONField(default=dict)
token = models.ForeignKey(
"db.APIToken", on_delete=models.CASCADE, related_name="importer"
)
token = models.ForeignKey("db.APIToken", on_delete=models.CASCADE, related_name="importer")
imported_data = models.JSONField(null=True)
class Meta:

View file

@ -44,12 +44,8 @@ class IntakeIssueStatus(models.IntegerChoices):
class IntakeIssue(ProjectBaseModel):
intake = models.ForeignKey(
"db.Intake", related_name="issue_intake", on_delete=models.CASCADE
)
issue = models.ForeignKey(
"db.Issue", related_name="issue_intake", on_delete=models.CASCADE
)
intake = models.ForeignKey("db.Intake", related_name="issue_intake", on_delete=models.CASCADE)
issue = models.ForeignKey("db.Issue", related_name="issue_intake", on_delete=models.CASCADE)
status = models.IntegerField(
choices=(
(-2, "Pending"),

View file

@ -10,14 +10,10 @@ from plane.db.mixins import AuditModel
class Integration(AuditModel):
id = models.UUIDField(
default=uuid.uuid4, unique=True, editable=False, db_index=True, primary_key=True
)
id = models.UUIDField(default=uuid.uuid4, unique=True, editable=False, db_index=True, primary_key=True)
title = models.CharField(max_length=400)
provider = models.CharField(max_length=400, unique=True)
network = models.PositiveIntegerField(
default=1, choices=((1, "Private"), (2, "Public"))
)
network = models.PositiveIntegerField(default=1, choices=((1, "Private"), (2, "Public")))
description = models.JSONField(default=dict)
author = models.CharField(max_length=400, blank=True)
webhook_url = models.TextField(blank=True)
@ -39,19 +35,11 @@ class Integration(AuditModel):
class WorkspaceIntegration(BaseModel):
workspace = models.ForeignKey(
"db.Workspace", related_name="workspace_integrations", on_delete=models.CASCADE
)
workspace = models.ForeignKey("db.Workspace", related_name="workspace_integrations", on_delete=models.CASCADE)
# Bot user
actor = models.ForeignKey(
"db.User", related_name="integrations", on_delete=models.CASCADE
)
integration = models.ForeignKey(
"db.Integration", related_name="integrated_workspaces", on_delete=models.CASCADE
)
api_token = models.ForeignKey(
"db.APIToken", related_name="integrations", on_delete=models.CASCADE
)
actor = models.ForeignKey("db.User", related_name="integrations", on_delete=models.CASCADE)
integration = models.ForeignKey("db.Integration", related_name="integrated_workspaces", on_delete=models.CASCADE)
api_token = models.ForeignKey("db.APIToken", related_name="integrations", on_delete=models.CASCADE)
metadata = models.JSONField(default=dict)
config = models.JSONField(default=dict)

View file

@ -26,20 +26,14 @@ class GithubRepository(ProjectBaseModel):
class GithubRepositorySync(ProjectBaseModel):
repository = models.OneToOneField(
"db.GithubRepository", on_delete=models.CASCADE, related_name="syncs"
)
repository = models.OneToOneField("db.GithubRepository", on_delete=models.CASCADE, related_name="syncs")
credentials = models.JSONField(default=dict)
# Bot user
actor = models.ForeignKey(
"db.User", related_name="user_syncs", on_delete=models.CASCADE
)
actor = models.ForeignKey("db.User", related_name="user_syncs", on_delete=models.CASCADE)
workspace_integration = models.ForeignKey(
"db.WorkspaceIntegration", related_name="github_syncs", on_delete=models.CASCADE
)
label = models.ForeignKey(
"db.Label", on_delete=models.SET_NULL, null=True, related_name="repo_syncs"
)
label = models.ForeignKey("db.Label", on_delete=models.SET_NULL, null=True, related_name="repo_syncs")
def __str__(self):
"""Return the repo sync"""
@ -57,12 +51,8 @@ class GithubIssueSync(ProjectBaseModel):
repo_issue_id = models.BigIntegerField()
github_issue_id = models.BigIntegerField()
issue_url = models.URLField(blank=False)
issue = models.ForeignKey(
"db.Issue", related_name="github_syncs", on_delete=models.CASCADE
)
repository_sync = models.ForeignKey(
"db.GithubRepositorySync", related_name="issue_syncs", on_delete=models.CASCADE
)
issue = models.ForeignKey("db.Issue", related_name="github_syncs", on_delete=models.CASCADE)
repository_sync = models.ForeignKey("db.GithubRepositorySync", related_name="issue_syncs", on_delete=models.CASCADE)
def __str__(self):
"""Return the github issue sync"""
@ -78,12 +68,8 @@ class GithubIssueSync(ProjectBaseModel):
class GithubCommentSync(ProjectBaseModel):
repo_comment_id = models.BigIntegerField()
comment = models.ForeignKey(
"db.IssueComment", related_name="comment_syncs", on_delete=models.CASCADE
)
issue_sync = models.ForeignKey(
"db.GithubIssueSync", related_name="comment_syncs", on_delete=models.CASCADE
)
comment = models.ForeignKey("db.IssueComment", related_name="comment_syncs", on_delete=models.CASCADE)
issue_sync = models.ForeignKey("db.GithubIssueSync", related_name="comment_syncs", on_delete=models.CASCADE)
def __str__(self):
"""Return the github issue sync"""

View file

@ -123,9 +123,7 @@ class Issue(ProjectBaseModel):
blank=True,
related_name="state_issue",
)
point = models.IntegerField(
validators=[MinValueValidator(0), MaxValueValidator(12)], null=True, blank=True
)
point = models.IntegerField(validators=[MinValueValidator(0), MaxValueValidator(12)], null=True, blank=True)
estimate_point = models.ForeignKey(
"db.EstimatePoint",
on_delete=models.SET_NULL,
@ -154,9 +152,7 @@ class Issue(ProjectBaseModel):
through_fields=("issue", "assignee"),
)
sequence_id = models.IntegerField(default=1, verbose_name="Issue Sequence ID")
labels = models.ManyToManyField(
"db.Label", blank=True, related_name="labels", through="IssueLabel"
)
labels = models.ManyToManyField("db.Label", blank=True, related_name="labels", through="IssueLabel")
sort_order = models.FloatField(default=65535)
completed_at = models.DateTimeField(null=True)
archived_at = models.DateField(null=True)
@ -188,9 +184,7 @@ class Issue(ProjectBaseModel):
~models.Q(is_triage=True), project=self.project, default=True
).first()
if default_state is None:
random_state = State.objects.filter(
~models.Q(is_triage=True), project=self.project
).first()
random_state = State.objects.filter(~models.Q(is_triage=True), project=self.project).first()
self.state = random_state
else:
self.state = default_state
@ -219,29 +213,25 @@ class Issue(ProjectBaseModel):
try:
# Get the last sequence for the project
last_sequence = IssueSequence.objects.filter(
project=self.project
).aggregate(largest=models.Max("sequence"))["largest"]
last_sequence = IssueSequence.objects.filter(project=self.project).aggregate(
largest=models.Max("sequence")
)["largest"]
self.sequence_id = last_sequence + 1 if last_sequence else 1
# Strip the html tags using html parser
self.description_stripped = (
None
if (
self.description_html == "" or self.description_html is None
)
if (self.description_html == "" or self.description_html is None)
else strip_tags(self.description_html)
)
largest_sort_order = Issue.objects.filter(
project=self.project, state=self.state
).aggregate(largest=models.Max("sort_order"))["largest"]
largest_sort_order = Issue.objects.filter(project=self.project, state=self.state).aggregate(
largest=models.Max("sort_order")
)["largest"]
if largest_sort_order is not None:
self.sort_order = largest_sort_order + 10000
super(Issue, self).save(*args, **kwargs)
IssueSequence.objects.create(
issue=self, sequence=self.sequence_id, project=self.project
)
IssueSequence.objects.create(issue=self, sequence=self.sequence_id, project=self.project)
finally:
# Release the lock
with connection.cursor() as cursor:
@ -261,12 +251,8 @@ class Issue(ProjectBaseModel):
class IssueBlocker(ProjectBaseModel):
block = models.ForeignKey(
Issue, related_name="blocker_issues", on_delete=models.CASCADE
)
blocked_by = models.ForeignKey(
Issue, related_name="blocked_issues", on_delete=models.CASCADE
)
block = models.ForeignKey(Issue, related_name="blocker_issues", on_delete=models.CASCADE)
blocked_by = models.ForeignKey(Issue, related_name="blocked_issues", on_delete=models.CASCADE)
class Meta:
verbose_name = "Issue Blocker"
@ -288,12 +274,8 @@ class IssueRelationChoices(models.TextChoices):
class IssueRelation(ProjectBaseModel):
issue = models.ForeignKey(
Issue, related_name="issue_relation", on_delete=models.CASCADE
)
related_issue = models.ForeignKey(
Issue, related_name="issue_related", on_delete=models.CASCADE
)
issue = models.ForeignKey(Issue, related_name="issue_relation", on_delete=models.CASCADE)
related_issue = models.ForeignKey(Issue, related_name="issue_related", on_delete=models.CASCADE)
relation_type = models.CharField(
max_length=20,
verbose_name="Issue Relation Type",
@ -319,12 +301,8 @@ class IssueRelation(ProjectBaseModel):
class IssueMention(ProjectBaseModel):
issue = models.ForeignKey(
Issue, on_delete=models.CASCADE, related_name="issue_mention"
)
mention = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="issue_mention"
)
issue = models.ForeignKey(Issue, on_delete=models.CASCADE, related_name="issue_mention")
mention = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="issue_mention")
class Meta:
unique_together = ["issue", "mention", "deleted_at"]
@ -345,9 +323,7 @@ class IssueMention(ProjectBaseModel):
class IssueAssignee(ProjectBaseModel):
issue = models.ForeignKey(
Issue, on_delete=models.CASCADE, related_name="issue_assignee"
)
issue = models.ForeignKey(Issue, on_delete=models.CASCADE, related_name="issue_assignee")
assignee = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
@ -375,9 +351,7 @@ class IssueAssignee(ProjectBaseModel):
class IssueLink(ProjectBaseModel):
title = models.CharField(max_length=255, null=True, blank=True)
url = models.TextField()
issue = models.ForeignKey(
"db.Issue", on_delete=models.CASCADE, related_name="issue_link"
)
issue = models.ForeignKey("db.Issue", on_delete=models.CASCADE, related_name="issue_link")
metadata = models.JSONField(default=dict)
class Meta:
@ -403,9 +377,7 @@ def file_size(value):
class IssueAttachment(ProjectBaseModel):
attributes = models.JSONField(default=dict)
asset = models.FileField(upload_to=get_upload_path, validators=[file_size])
issue = models.ForeignKey(
"db.Issue", on_delete=models.CASCADE, related_name="issue_attachment"
)
issue = models.ForeignKey("db.Issue", on_delete=models.CASCADE, related_name="issue_attachment")
external_source = models.CharField(max_length=255, null=True, blank=True)
external_id = models.CharField(max_length=255, blank=True, null=True)
@ -420,13 +392,9 @@ class IssueAttachment(ProjectBaseModel):
class IssueActivity(ProjectBaseModel):
issue = models.ForeignKey(
Issue, on_delete=models.SET_NULL, null=True, related_name="issue_activity"
)
issue = models.ForeignKey(Issue, on_delete=models.SET_NULL, null=True, related_name="issue_activity")
verb = models.CharField(max_length=255, verbose_name="Action", default="created")
field = models.CharField(
max_length=255, verbose_name="Field Name", blank=True, null=True
)
field = models.CharField(max_length=255, verbose_name="Field Name", blank=True, null=True)
old_value = models.TextField(verbose_name="Old Value", blank=True, null=True)
new_value = models.TextField(verbose_name="New Value", blank=True, null=True)
@ -464,9 +432,7 @@ class IssueComment(ProjectBaseModel):
comment_json = models.JSONField(blank=True, default=dict)
comment_html = models.TextField(blank=True, default="<p></p>")
attachments = ArrayField(models.URLField(), size=10, blank=True, default=list)
issue = models.ForeignKey(
Issue, on_delete=models.CASCADE, related_name="issue_comments"
)
issue = models.ForeignKey(Issue, on_delete=models.CASCADE, related_name="issue_comments")
# System can also create comment
actor = models.ForeignKey(
settings.AUTH_USER_MODEL,
@ -484,9 +450,7 @@ class IssueComment(ProjectBaseModel):
edited_at = models.DateTimeField(null=True, blank=True)
def save(self, *args, **kwargs):
self.comment_stripped = (
strip_tags(self.comment_html) if self.comment_html != "" else ""
)
self.comment_stripped = strip_tags(self.comment_html) if self.comment_html != "" else ""
return super(IssueComment, self).save(*args, **kwargs)
class Meta:
@ -531,12 +495,8 @@ class IssueUserProperty(ProjectBaseModel):
class IssueLabel(ProjectBaseModel):
issue = models.ForeignKey(
"db.Issue", on_delete=models.CASCADE, related_name="label_issue"
)
label = models.ForeignKey(
"db.Label", on_delete=models.CASCADE, related_name="label_issue"
)
issue = models.ForeignKey("db.Issue", on_delete=models.CASCADE, related_name="label_issue")
label = models.ForeignKey("db.Label", on_delete=models.CASCADE, related_name="label_issue")
class Meta:
verbose_name = "Issue Label"
@ -566,9 +526,7 @@ class IssueSequence(ProjectBaseModel):
class IssueSubscriber(ProjectBaseModel):
issue = models.ForeignKey(
Issue, on_delete=models.CASCADE, related_name="issue_subscribers"
)
issue = models.ForeignKey(Issue, on_delete=models.CASCADE, related_name="issue_subscribers")
subscriber = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
@ -599,9 +557,7 @@ class IssueReaction(ProjectBaseModel):
on_delete=models.CASCADE,
related_name="issue_reactions",
)
issue = models.ForeignKey(
Issue, on_delete=models.CASCADE, related_name="issue_reactions"
)
issue = models.ForeignKey(Issue, on_delete=models.CASCADE, related_name="issue_reactions")
reaction = models.TextField()
class Meta:
@ -628,9 +584,7 @@ class CommentReaction(ProjectBaseModel):
on_delete=models.CASCADE,
related_name="comment_reactions",
)
comment = models.ForeignKey(
IssueComment, on_delete=models.CASCADE, related_name="comment_reactions"
)
comment = models.ForeignKey(IssueComment, on_delete=models.CASCADE, related_name="comment_reactions")
reaction = models.TextField()
class Meta:
@ -653,9 +607,7 @@ class CommentReaction(ProjectBaseModel):
class IssueVote(ProjectBaseModel):
issue = models.ForeignKey(Issue, on_delete=models.CASCADE, related_name="votes")
actor = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="votes"
)
actor = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="votes")
vote = models.IntegerField(choices=((-1, "DOWNVOTE"), (1, "UPVOTE")), default=1)
class Meta:
@ -713,9 +665,7 @@ class IssueVersion(ProjectBaseModel):
meta = models.JSONField(default=dict) # issue meta
last_saved_at = models.DateTimeField(default=timezone.now)
issue = models.ForeignKey(
"db.Issue", on_delete=models.CASCADE, related_name="versions"
)
issue = models.ForeignKey("db.Issue", on_delete=models.CASCADE, related_name="versions")
activity = models.ForeignKey(
"db.IssueActivity",
on_delete=models.SET_NULL,
@ -760,17 +710,9 @@ class IssueVersion(ProjectBaseModel):
priority=issue.priority,
start_date=issue.start_date,
target_date=issue.target_date,
assignees=list(
IssueAssignee.objects.filter(issue=issue).values_list(
"assignee_id", flat=True
)
),
assignees=list(IssueAssignee.objects.filter(issue=issue).values_list("assignee_id", flat=True)),
sequence_id=issue.sequence_id,
labels=list(
IssueLabel.objects.filter(issue=issue).values_list(
"label_id", flat=True
)
),
labels=list(IssueLabel.objects.filter(issue=issue).values_list("label_id", flat=True)),
sort_order=issue.sort_order,
completed_at=issue.completed_at,
archived_at=issue.archived_at,
@ -779,9 +721,7 @@ class IssueVersion(ProjectBaseModel):
external_id=issue.external_id,
type=issue.type_id,
cycle=cycle_issue.cycle_id if cycle_issue else None,
modules=list(
Module.objects.filter(issue=issue).values_list("id", flat=True)
),
modules=list(Module.objects.filter(issue=issue).values_list("id", flat=True)),
properties={},
meta={},
last_saved_at=timezone.now(),
@ -794,9 +734,7 @@ class IssueVersion(ProjectBaseModel):
class IssueDescriptionVersion(ProjectBaseModel):
issue = models.ForeignKey(
"db.Issue", on_delete=models.CASCADE, related_name="description_versions"
)
issue = models.ForeignKey("db.Issue", on_delete=models.CASCADE, related_name="description_versions")
description_binary = models.BinaryField(null=True)
description_html = models.TextField(blank=True, default="<p></p>")
description_stripped = models.TextField(blank=True, null=True)

View file

@ -8,9 +8,7 @@ from .base import BaseModel
class IssueType(BaseModel):
workspace = models.ForeignKey(
"db.Workspace", related_name="issue_types", on_delete=models.CASCADE
)
workspace = models.ForeignKey("db.Workspace", related_name="issue_types", on_delete=models.CASCADE)
name = models.CharField(max_length=255)
description = models.TextField(blank=True)
logo_props = models.JSONField(default=dict)
@ -31,9 +29,7 @@ class IssueType(BaseModel):
class ProjectIssueType(ProjectBaseModel):
issue_type = models.ForeignKey(
"db.IssueType", related_name="project_issue_types", on_delete=models.CASCADE
)
issue_type = models.ForeignKey("db.IssueType", related_name="project_issue_types", on_delete=models.CASCADE)
level = models.PositiveIntegerField(default=0)
is_default = models.BooleanField(default=False)

View file

@ -42,9 +42,7 @@ class Label(WorkspaceBaseModel):
def save(self, *args, **kwargs):
if self._state.adding:
# Get the maximum sequence value from the database
last_id = Label.objects.filter(project=self.project).aggregate(
largest=models.Max("sort_order")
)["largest"]
last_id = Label.objects.filter(project=self.project).aggregate(largest=models.Max("sort_order"))["largest"]
# if last_id is not None
if last_id is not None:
self.sort_order = last_id + 10000

View file

@ -63,12 +63,8 @@ class ModuleStatus(models.TextChoices):
class Module(ProjectBaseModel):
name = models.CharField(max_length=255, verbose_name="Module Name")
description = models.TextField(verbose_name="Module Description", blank=True)
description_text = models.JSONField(
verbose_name="Module Description RT", blank=True, null=True
)
description_html = models.JSONField(
verbose_name="Module Description HTML", blank=True, null=True
)
description_text = models.JSONField(verbose_name="Module Description RT", blank=True, null=True)
description_html = models.JSONField(verbose_name="Module Description HTML", blank=True, null=True)
start_date = models.DateField(null=True)
target_date = models.DateField(null=True)
status = models.CharField(
@ -83,9 +79,7 @@ class Module(ProjectBaseModel):
default="planned",
max_length=20,
)
lead = models.ForeignKey(
"db.User", on_delete=models.SET_NULL, related_name="module_leads", null=True
)
lead = models.ForeignKey("db.User", on_delete=models.SET_NULL, related_name="module_leads", null=True)
members = models.ManyToManyField(
settings.AUTH_USER_MODEL,
blank=True,
@ -152,12 +146,8 @@ class ModuleMember(ProjectBaseModel):
class ModuleIssue(ProjectBaseModel):
module = models.ForeignKey(
"db.Module", on_delete=models.CASCADE, related_name="issue_module"
)
issue = models.ForeignKey(
"db.Issue", on_delete=models.CASCADE, related_name="issue_module"
)
module = models.ForeignKey("db.Module", on_delete=models.CASCADE, related_name="issue_module")
issue = models.ForeignKey("db.Issue", on_delete=models.CASCADE, related_name="issue_module")
class Meta:
unique_together = ["issue", "module", "deleted_at"]
@ -180,9 +170,7 @@ class ModuleIssue(ProjectBaseModel):
class ModuleLink(ProjectBaseModel):
title = models.CharField(max_length=255, blank=True, null=True)
url = models.URLField()
module = models.ForeignKey(
Module, on_delete=models.CASCADE, related_name="link_module"
)
module = models.ForeignKey(Module, on_delete=models.CASCADE, related_name="link_module")
metadata = models.JSONField(default=dict)
class Meta:
@ -196,9 +184,7 @@ class ModuleLink(ProjectBaseModel):
class ModuleUserProperties(ProjectBaseModel):
module = models.ForeignKey(
"db.Module", on_delete=models.CASCADE, related_name="module_user_properties"
)
module = models.ForeignKey("db.Module", on_delete=models.CASCADE, related_name="module_user_properties")
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,

View file

@ -7,12 +7,8 @@ from .base import BaseModel
class Notification(BaseModel):
workspace = models.ForeignKey(
"db.Workspace", related_name="notifications", on_delete=models.CASCADE
)
project = models.ForeignKey(
"db.Project", related_name="notifications", on_delete=models.CASCADE, null=True
)
workspace = models.ForeignKey("db.Workspace", related_name="notifications", on_delete=models.CASCADE)
project = models.ForeignKey("db.Project", related_name="notifications", on_delete=models.CASCADE, null=True)
data = models.JSONField(null=True)
entity_identifier = models.UUIDField(null=True)
entity_name = models.CharField(max_length=255)
@ -27,9 +23,7 @@ class Notification(BaseModel):
on_delete=models.SET_NULL,
null=True,
)
receiver = models.ForeignKey(
"db.User", related_name="received_notifications", on_delete=models.CASCADE
)
receiver = models.ForeignKey("db.User", related_name="received_notifications", on_delete=models.CASCADE)
read_at = models.DateTimeField(null=True)
snoozed_till = models.DateTimeField(null=True)
archived_at = models.DateTimeField(null=True)
@ -40,9 +34,7 @@ class Notification(BaseModel):
db_table = "notifications"
ordering = ("-created_at",)
indexes = [
models.Index(
fields=["entity_identifier"], name="notif_entity_identifier_idx"
),
models.Index(fields=["entity_identifier"], name="notif_entity_identifier_idx"),
models.Index(fields=["entity_name"], name="notif_entity_name_idx"),
models.Index(fields=["read_at"], name="notif_read_at_idx"),
models.Index(fields=["receiver", "read_at"], name="notif_entity_idx"),

View file

@ -23,24 +23,16 @@ class Page(BaseModel):
ACCESS_CHOICES = ((PRIVATE_ACCESS, "Private"), (PUBLIC_ACCESS, "Public"))
workspace = models.ForeignKey(
"db.Workspace", on_delete=models.CASCADE, related_name="pages"
)
workspace = models.ForeignKey("db.Workspace", on_delete=models.CASCADE, related_name="pages")
name = models.TextField(blank=True)
description = models.JSONField(default=dict, blank=True)
description_binary = models.BinaryField(null=True)
description_html = models.TextField(blank=True, default="<p></p>")
description_stripped = models.TextField(blank=True, null=True)
owned_by = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="pages"
)
access = models.PositiveSmallIntegerField(
choices=((0, "Public"), (1, "Private")), default=0
)
owned_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="pages")
access = models.PositiveSmallIntegerField(choices=((0, "Public"), (1, "Private")), default=0)
color = models.CharField(max_length=255, blank=True)
labels = models.ManyToManyField(
"db.Label", blank=True, related_name="pages", through="db.PageLabel"
)
labels = models.ManyToManyField("db.Label", blank=True, related_name="pages", through="db.PageLabel")
parent = models.ForeignKey(
"self",
on_delete=models.CASCADE,
@ -53,9 +45,7 @@ class Page(BaseModel):
view_props = models.JSONField(default=get_view_props)
logo_props = models.JSONField(default=dict)
is_global = models.BooleanField(default=False)
projects = models.ManyToManyField(
"db.Project", related_name="pages", through="db.ProjectPage"
)
projects = models.ManyToManyField("db.Project", related_name="pages", through="db.ProjectPage")
moved_to_page = models.UUIDField(null=True, blank=True)
moved_to_project = models.UUIDField(null=True, blank=True)
sort_order = models.FloatField(default=DEFAULT_SORT_ORDER)
@ -102,12 +92,8 @@ class PageLog(BaseModel):
page = models.ForeignKey(Page, related_name="page_log", on_delete=models.CASCADE)
entity_identifier = models.UUIDField(null=True, blank=True)
entity_name = models.CharField(max_length=30, verbose_name="Transaction Type")
entity_type = models.CharField(
max_length=30, verbose_name="Entity Type", null=True, blank=True
)
workspace = models.ForeignKey(
"db.Workspace", on_delete=models.CASCADE, related_name="workspace_page_log"
)
entity_type = models.CharField(max_length=30, verbose_name="Entity Type", null=True, blank=True)
workspace = models.ForeignKey("db.Workspace", on_delete=models.CASCADE, related_name="workspace_page_log")
class Meta:
unique_together = ["page", "transaction"]
@ -119,12 +105,8 @@ class PageLog(BaseModel):
models.Index(fields=["entity_type"], name="pagelog_entity_type_idx"),
models.Index(fields=["entity_identifier"], name="pagelog_entity_id_idx"),
models.Index(fields=["entity_name"], name="pagelog_entity_name_idx"),
models.Index(
fields=["entity_type", "entity_identifier"], name="pagelog_type_id_idx"
),
models.Index(
fields=["entity_name", "entity_identifier"], name="pagelog_name_id_idx"
),
models.Index(fields=["entity_type", "entity_identifier"], name="pagelog_type_id_idx"),
models.Index(fields=["entity_name", "entity_identifier"], name="pagelog_name_id_idx"),
]
def __str__(self):
@ -132,15 +114,9 @@ class PageLog(BaseModel):
class PageLabel(BaseModel):
label = models.ForeignKey(
"db.Label", on_delete=models.CASCADE, related_name="page_labels"
)
page = models.ForeignKey(
"db.Page", on_delete=models.CASCADE, related_name="page_labels"
)
workspace = models.ForeignKey(
"db.Workspace", on_delete=models.CASCADE, related_name="workspace_page_label"
)
label = models.ForeignKey("db.Label", on_delete=models.CASCADE, related_name="page_labels")
page = models.ForeignKey("db.Page", on_delete=models.CASCADE, related_name="page_labels")
workspace = models.ForeignKey("db.Workspace", on_delete=models.CASCADE, related_name="workspace_page_label")
class Meta:
verbose_name = "Page Label"
@ -153,15 +129,9 @@ class PageLabel(BaseModel):
class ProjectPage(BaseModel):
project = models.ForeignKey(
"db.Project", on_delete=models.CASCADE, related_name="project_pages"
)
page = models.ForeignKey(
"db.Page", on_delete=models.CASCADE, related_name="project_pages"
)
workspace = models.ForeignKey(
"db.Workspace", on_delete=models.CASCADE, related_name="project_pages"
)
project = models.ForeignKey("db.Project", on_delete=models.CASCADE, related_name="project_pages")
page = models.ForeignKey("db.Page", on_delete=models.CASCADE, related_name="project_pages")
workspace = models.ForeignKey("db.Workspace", on_delete=models.CASCADE, related_name="project_pages")
class Meta:
unique_together = ["project", "page", "deleted_at"]
@ -182,16 +152,10 @@ class ProjectPage(BaseModel):
class PageVersion(BaseModel):
workspace = models.ForeignKey(
"db.Workspace", on_delete=models.CASCADE, related_name="page_versions"
)
page = models.ForeignKey(
"db.Page", on_delete=models.CASCADE, related_name="page_versions"
)
workspace = models.ForeignKey("db.Workspace", on_delete=models.CASCADE, related_name="page_versions")
page = models.ForeignKey("db.Page", on_delete=models.CASCADE, related_name="page_versions")
last_saved_at = models.DateTimeField(default=timezone.now)
owned_by = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="page_versions"
)
owned_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="page_versions")
description_binary = models.BinaryField(null=True)
description_html = models.TextField(blank=True, default="<p></p>")
description_stripped = models.TextField(blank=True, null=True)

View file

@ -66,19 +66,11 @@ class Project(BaseModel):
NETWORK_CHOICES = ((0, "Secret"), (2, "Public"))
name = models.CharField(max_length=255, verbose_name="Project Name")
description = models.TextField(verbose_name="Project Description", blank=True)
description_text = models.JSONField(
verbose_name="Project Description RT", blank=True, null=True
)
description_html = models.JSONField(
verbose_name="Project Description HTML", blank=True, null=True
)
description_text = models.JSONField(verbose_name="Project Description RT", blank=True, null=True)
description_html = models.JSONField(verbose_name="Project Description HTML", blank=True, null=True)
network = models.PositiveSmallIntegerField(default=2, choices=NETWORK_CHOICES)
workspace = models.ForeignKey(
"db.WorkSpace", on_delete=models.CASCADE, related_name="workspace_project"
)
identifier = models.CharField(
max_length=12, verbose_name="Project Identifier", db_index=True
)
workspace = models.ForeignKey("db.WorkSpace", on_delete=models.CASCADE, related_name="workspace_project")
identifier = models.CharField(max_length=12, verbose_name="Project Identifier", db_index=True)
default_assignee = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
@ -111,19 +103,11 @@ class Project(BaseModel):
blank=True,
related_name="project_cover_image",
)
estimate = models.ForeignKey(
"db.Estimate", on_delete=models.SET_NULL, related_name="projects", null=True
)
archive_in = models.IntegerField(
default=0, validators=[MinValueValidator(0), MaxValueValidator(12)]
)
close_in = models.IntegerField(
default=0, validators=[MinValueValidator(0), MaxValueValidator(12)]
)
estimate = models.ForeignKey("db.Estimate", on_delete=models.SET_NULL, related_name="projects", null=True)
archive_in = models.IntegerField(default=0, validators=[MinValueValidator(0), MaxValueValidator(12)])
close_in = models.IntegerField(default=0, validators=[MinValueValidator(0), MaxValueValidator(12)])
logo_props = models.JSONField(default=dict)
default_state = models.ForeignKey(
"db.State", on_delete=models.SET_NULL, null=True, related_name="default_state"
)
default_state = models.ForeignKey("db.State", on_delete=models.SET_NULL, null=True, related_name="default_state")
archived_at = models.DateTimeField(null=True)
# timezone
TIMEZONE_CHOICES = tuple(zip(pytz.common_timezones, pytz.common_timezones))
@ -176,12 +160,8 @@ class Project(BaseModel):
class ProjectBaseModel(BaseModel):
project = models.ForeignKey(
Project, on_delete=models.CASCADE, related_name="project_%(class)s"
)
workspace = models.ForeignKey(
"db.Workspace", on_delete=models.CASCADE, related_name="workspace_%(class)s"
)
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="project_%(class)s")
workspace = models.ForeignKey("db.Workspace", on_delete=models.CASCADE, related_name="workspace_%(class)s")
class Meta:
abstract = True
@ -258,12 +238,8 @@ class ProjectMember(ProjectBaseModel):
# TODO: Remove workspace relation later
class ProjectIdentifier(AuditModel):
workspace = models.ForeignKey(
"db.Workspace", models.CASCADE, related_name="project_identifiers", null=True
)
project = models.OneToOneField(
Project, on_delete=models.CASCADE, related_name="project_identifier"
)
workspace = models.ForeignKey("db.Workspace", models.CASCADE, related_name="project_identifiers", null=True)
project = models.OneToOneField(Project, on_delete=models.CASCADE, related_name="project_identifier")
name = models.CharField(max_length=12, db_index=True)
class Meta:
@ -298,14 +274,10 @@ def get_default_views():
# DEPRECATED TODO:
# used to get the old anchors for the project deploy boards
class ProjectDeployBoard(ProjectBaseModel):
anchor = models.CharField(
max_length=255, default=get_anchor, unique=True, db_index=True
)
anchor = models.CharField(max_length=255, default=get_anchor, unique=True, db_index=True)
comments = models.BooleanField(default=False)
reactions = models.BooleanField(default=False)
intake = models.ForeignKey(
"db.Intake", related_name="board_intake", on_delete=models.SET_NULL, null=True
)
intake = models.ForeignKey("db.Intake", related_name="board_intake", on_delete=models.SET_NULL, null=True)
votes = models.BooleanField(default=False)
views = models.JSONField(default=get_default_views)

View file

@ -52,9 +52,7 @@ class State(ProjectBaseModel):
self.slug = slugify(self.name)
if self._state.adding:
# Get the maximum sequence value from the database
last_id = State.objects.filter(project=self.project).aggregate(
largest=models.Max("sequence")
)["largest"]
last_id = State.objects.filter(project=self.project).aggregate(largest=models.Max("sequence"))["largest"]
# if last_id is not None
if last_id is not None:
self.sequence = last_id + 15000

View file

@ -21,12 +21,8 @@ class Sticky(BaseModel):
color = models.CharField(max_length=255, blank=True, null=True)
background_color = models.CharField(max_length=255, blank=True, null=True)
workspace = models.ForeignKey(
"db.Workspace", on_delete=models.CASCADE, related_name="stickies"
)
owner = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="stickies"
)
workspace = models.ForeignKey("db.Workspace", on_delete=models.CASCADE, related_name="stickies")
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="stickies")
sort_order = models.FloatField(default=65535)
class Meta:
@ -44,9 +40,9 @@ class Sticky(BaseModel):
)
if self._state.adding:
# Get the maximum sequence value from the database
last_id = Sticky.objects.filter(workspace=self.workspace).aggregate(
largest=models.Max("sort_order")
)["largest"]
last_id = Sticky.objects.filter(workspace=self.workspace).aggregate(largest=models.Max("sort_order"))[
"largest"
]
# if last_id is not None
if last_id is not None:
self.sort_order = last_id + 10000

View file

@ -36,9 +36,7 @@ def get_mobile_default_onboarding():
class User(AbstractBaseUser, PermissionsMixin):
id = models.UUIDField(
default=uuid.uuid4, unique=True, editable=False, db_index=True, primary_key=True
)
id = models.UUIDField(default=uuid.uuid4, unique=True, editable=False, db_index=True, primary_key=True)
username = models.CharField(max_length=128, unique=True)
# user fields
mobile_number = models.CharField(max_length=255, blank=True, null=True)
@ -97,15 +95,11 @@ class User(AbstractBaseUser, PermissionsMixin):
# my_issues_prop = models.JSONField(null=True)
is_bot = models.BooleanField(default=False)
bot_type = models.CharField(
max_length=30, verbose_name="Bot Type", blank=True, null=True
)
bot_type = models.CharField(max_length=30, verbose_name="Bot Type", blank=True, null=True)
# timezone
USER_TIMEZONE_CHOICES = tuple(zip(pytz.common_timezones, pytz.common_timezones))
user_timezone = models.CharField(
max_length=255, default="UTC", choices=USER_TIMEZONE_CHOICES
)
user_timezone = models.CharField(max_length=255, default="UTC", choices=USER_TIMEZONE_CHOICES)
# email validation
is_email_valid = models.BooleanField(default=False)
@ -189,13 +183,9 @@ class Profile(TimeAuditModel):
(SATURDAY, "Saturday"),
)
id = models.UUIDField(
default=uuid.uuid4, unique=True, editable=False, db_index=True, primary_key=True
)
id = models.UUIDField(default=uuid.uuid4, unique=True, editable=False, db_index=True, primary_key=True)
# User
user = models.OneToOneField(
"db.User", on_delete=models.CASCADE, related_name="profile"
)
user = models.OneToOneField("db.User", on_delete=models.CASCADE, related_name="profile")
# General
theme = models.JSONField(default=dict)
is_app_rail_docked = models.BooleanField(default=True)
@ -220,9 +210,7 @@ class Profile(TimeAuditModel):
mobile_timezone_auto_set = models.BooleanField(default=False)
# language
language = models.CharField(max_length=255, default="en")
start_of_the_week = models.PositiveSmallIntegerField(
choices=START_OF_THE_WEEK_CHOICES, default=SUNDAY
)
start_of_the_week = models.PositiveSmallIntegerField(choices=START_OF_THE_WEEK_CHOICES, default=SUNDAY)
goals = models.JSONField(default=dict)
background_color = models.CharField(max_length=255, default=get_random_color)
@ -243,12 +231,8 @@ class Account(TimeAuditModel):
("gitlab", "GitLab"),
)
id = models.UUIDField(
default=uuid.uuid4, unique=True, editable=False, db_index=True, primary_key=True
)
user = models.ForeignKey(
"db.User", on_delete=models.CASCADE, related_name="accounts"
)
id = models.UUIDField(default=uuid.uuid4, unique=True, editable=False, db_index=True, primary_key=True)
user = models.ForeignKey("db.User", on_delete=models.CASCADE, related_name="accounts")
provider_account_id = models.CharField(max_length=255)
provider = models.CharField(choices=PROVIDER_CHOICES)
access_token = models.TextField()

View file

@ -59,14 +59,10 @@ class IssueView(WorkspaceBaseModel):
display_filters = models.JSONField(default=get_default_display_filters)
display_properties = models.JSONField(default=get_default_display_properties)
rich_filters = models.JSONField(default=dict)
access = models.PositiveSmallIntegerField(
default=1, choices=((0, "Private"), (1, "Public"))
)
access = models.PositiveSmallIntegerField(default=1, choices=((0, "Private"), (1, "Public")))
sort_order = models.FloatField(default=65535)
logo_props = models.JSONField(default=dict)
owned_by = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="views"
)
owned_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="views")
is_locked = models.BooleanField(default=False)
class Meta:
@ -81,13 +77,13 @@ class IssueView(WorkspaceBaseModel):
if self._state.adding:
if self.project:
largest_sort_order = IssueView.objects.filter(
project=self.project
).aggregate(largest=models.Max("sort_order"))["largest"]
largest_sort_order = IssueView.objects.filter(project=self.project).aggregate(
largest=models.Max("sort_order")
)["largest"]
else:
largest_sort_order = IssueView.objects.filter(
workspace=self.workspace, project__isnull=True
).aggregate(largest=models.Max("sort_order"))["largest"]
largest_sort_order = IssueView.objects.filter(workspace=self.workspace, project__isnull=True).aggregate(
largest=models.Max("sort_order")
)["largest"]
if largest_sort_order is not None:
self.sort_order = largest_sort_order + 10000

View file

@ -28,12 +28,8 @@ def validate_domain(value):
class Webhook(BaseModel):
workspace = models.ForeignKey(
"db.Workspace", on_delete=models.CASCADE, related_name="workspace_webhooks"
)
url = models.URLField(
validators=[validate_schema, validate_domain], max_length=1024
)
workspace = models.ForeignKey("db.Workspace", on_delete=models.CASCADE, related_name="workspace_webhooks")
url = models.URLField(validators=[validate_schema, validate_domain], max_length=1024)
is_active = models.BooleanField(default=True)
secret_key = models.CharField(max_length=255, default=generate_token)
project = models.BooleanField(default=False)
@ -62,9 +58,7 @@ class Webhook(BaseModel):
class WebhookLog(BaseModel):
workspace = models.ForeignKey(
"db.Workspace", on_delete=models.CASCADE, related_name="webhook_logs"
)
workspace = models.ForeignKey("db.Workspace", on_delete=models.CASCADE, related_name="webhook_logs")
# Associated webhook
webhook = models.UUIDField()
@ -92,11 +86,8 @@ class WebhookLog(BaseModel):
return f"{self.event_type} {str(self.webhook)}"
class ProjectWebhook(ProjectBaseModel):
webhook = models.ForeignKey(
"db.Webhook", on_delete=models.CASCADE, related_name="project_webhooks"
)
webhook = models.ForeignKey("db.Webhook", on_delete=models.CASCADE, related_name="project_webhooks")
class Meta:
unique_together = ["project", "webhook", "deleted_at"]
@ -110,4 +101,4 @@ class ProjectWebhook(ProjectBaseModel):
verbose_name = "Project Webhook"
verbose_name_plural = "Project Webhooks"
db_table = "project_webhooks"
ordering = ("-created_at",)
ordering = ("-created_at",)

View file

@ -129,9 +129,7 @@ class Workspace(BaseModel):
on_delete=models.CASCADE,
related_name="owner_workspace",
)
slug = models.SlugField(
max_length=48, db_index=True, unique=True, validators=[slug_validator]
)
slug = models.SlugField(max_length=48, db_index=True, unique=True, validators=[slug_validator])
organization_size = models.CharField(max_length=20, blank=True, null=True)
timezone = models.CharField(max_length=255, default="UTC", choices=TIMEZONE_CHOICES)
background_color = models.CharField(max_length=255, default=get_random_color)
@ -151,9 +149,7 @@ class Workspace(BaseModel):
return self.logo
return None
def delete(
self, using: Optional[str] = None, soft: bool = True, *args: Any, **kwargs: Any
):
def delete(self, using: Optional[str] = None, soft: bool = True, *args: Any, **kwargs: Any):
"""
Override the delete method to append epoch timestamp to the slug when soft deleting.
@ -183,12 +179,8 @@ class Workspace(BaseModel):
class WorkspaceBaseModel(BaseModel):
workspace = models.ForeignKey(
"db.Workspace", models.CASCADE, related_name="workspace_%(class)s"
)
project = models.ForeignKey(
"db.Project", models.CASCADE, related_name="project_%(class)s", null=True
)
workspace = models.ForeignKey("db.Workspace", models.CASCADE, related_name="workspace_%(class)s")
project = models.ForeignKey("db.Project", models.CASCADE, related_name="project_%(class)s", null=True)
class Meta:
abstract = True
@ -200,9 +192,7 @@ class WorkspaceBaseModel(BaseModel):
class WorkspaceMember(BaseModel):
workspace = models.ForeignKey(
"db.Workspace", on_delete=models.CASCADE, related_name="workspace_member"
)
workspace = models.ForeignKey("db.Workspace", on_delete=models.CASCADE, related_name="workspace_member")
member = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
@ -235,9 +225,7 @@ class WorkspaceMember(BaseModel):
class WorkspaceMemberInvite(BaseModel):
workspace = models.ForeignKey(
"db.Workspace", on_delete=models.CASCADE, related_name="workspace_member_invite"
)
workspace = models.ForeignKey("db.Workspace", on_delete=models.CASCADE, related_name="workspace_member_invite")
email = models.CharField(max_length=255)
accepted = models.BooleanField(default=False)
token = models.CharField(max_length=255)
@ -266,9 +254,7 @@ class WorkspaceMemberInvite(BaseModel):
class Team(BaseModel):
name = models.CharField(max_length=255, verbose_name="Team Name")
description = models.TextField(verbose_name="Team Description", blank=True)
workspace = models.ForeignKey(
Workspace, on_delete=models.CASCADE, related_name="workspace_team"
)
workspace = models.ForeignKey(Workspace, on_delete=models.CASCADE, related_name="workspace_team")
logo_props = models.JSONField(default=dict)
def __str__(self):
@ -291,13 +277,9 @@ class Team(BaseModel):
class WorkspaceTheme(BaseModel):
workspace = models.ForeignKey(
"db.Workspace", on_delete=models.CASCADE, related_name="themes"
)
workspace = models.ForeignKey("db.Workspace", on_delete=models.CASCADE, related_name="themes")
name = models.CharField(max_length=300)
actor = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="themes"
)
actor = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="themes")
colors = models.JSONField(default=dict)
def __str__(self):