mirror of
https://github.com/makeplane/plane.git
synced 2026-02-09 07:38:52 -06:00
chore: page version migrations (#5103)
* chore: rewrite page version migration to remove data back migration * dev: rename exporter history choice field * dev: update migration
This commit is contained in:
@@ -11,7 +11,6 @@ from rest_framework import serializers
|
||||
# Module imports
|
||||
from plane.db.models import (
|
||||
Issue,
|
||||
IssueType,
|
||||
IssueActivity,
|
||||
IssueAssignee,
|
||||
IssueAttachment,
|
||||
@@ -132,15 +131,9 @@ class IssueSerializer(BaseSerializer):
|
||||
workspace_id = self.context["workspace_id"]
|
||||
default_assignee_id = self.context["default_assignee_id"]
|
||||
|
||||
# Get the issue type from the project
|
||||
issue_type = (
|
||||
IssueType.objects.filter(project_id=project_id)
|
||||
.order_by("created_at")
|
||||
.first()
|
||||
)
|
||||
|
||||
issue = Issue.objects.create(
|
||||
**validated_data, project_id=project_id, type=issue_type
|
||||
**validated_data,
|
||||
project_id=project_id,
|
||||
)
|
||||
|
||||
# Issue Audit Users
|
||||
|
||||
@@ -16,7 +16,6 @@ from plane.app.permissions import ProjectLitePermission
|
||||
from plane.bgtasks.issue_activites_task import issue_activity
|
||||
from plane.db.models import (
|
||||
Inbox,
|
||||
IssueType,
|
||||
InboxIssue,
|
||||
Issue,
|
||||
Project,
|
||||
@@ -142,12 +141,6 @@ class InboxIssueAPIEndpoint(BaseAPIView):
|
||||
color="#ff7700",
|
||||
is_triage=True,
|
||||
)
|
||||
# Get the issue type
|
||||
issue_type = (
|
||||
IssueType.objects.filter(project_id=project_id)
|
||||
.order_by("created_at")
|
||||
.first()
|
||||
)
|
||||
|
||||
# create an issue
|
||||
issue = Issue.objects.create(
|
||||
@@ -159,7 +152,6 @@ class InboxIssueAPIEndpoint(BaseAPIView):
|
||||
priority=request.data.get("issue", {}).get("priority", "none"),
|
||||
project_id=project_id,
|
||||
state=state,
|
||||
type=issue_type,
|
||||
)
|
||||
|
||||
# create an inbox issue
|
||||
|
||||
@@ -26,7 +26,6 @@ from plane.db.models import (
|
||||
ProjectMember,
|
||||
State,
|
||||
Workspace,
|
||||
IssueType,
|
||||
)
|
||||
from plane.bgtasks.webhook_task import model_activity
|
||||
from .base import BaseAPIView
|
||||
@@ -242,13 +241,6 @@ class ProjectAPIEndpoint(BaseAPIView):
|
||||
.first()
|
||||
)
|
||||
|
||||
# Create the Issue Types
|
||||
IssueType.objects.create(
|
||||
name="Task",
|
||||
description="A task that needs to be done",
|
||||
project_id=project.id,
|
||||
)
|
||||
|
||||
# Model activity
|
||||
model_activity.delay(
|
||||
model_name="project",
|
||||
|
||||
@@ -33,7 +33,6 @@ from plane.db.models import (
|
||||
IssueVote,
|
||||
IssueRelation,
|
||||
State,
|
||||
IssueType,
|
||||
)
|
||||
|
||||
|
||||
@@ -136,15 +135,10 @@ class IssueCreateSerializer(BaseSerializer):
|
||||
workspace_id = self.context["workspace_id"]
|
||||
default_assignee_id = self.context["default_assignee_id"]
|
||||
|
||||
# Get Issue Type
|
||||
issue_type = (
|
||||
IssueType.objects.filter(project_id=project_id)
|
||||
.order_by("created_at")
|
||||
.first()
|
||||
)
|
||||
# Create Issue
|
||||
issue = Issue.objects.create(
|
||||
**validated_data, project_id=project_id, type=issue_type
|
||||
**validated_data,
|
||||
project_id=project_id,
|
||||
)
|
||||
|
||||
# Issue Audit Users
|
||||
|
||||
@@ -47,7 +47,6 @@ from plane.db.models import (
|
||||
ProjectMember,
|
||||
State,
|
||||
Workspace,
|
||||
IssueType,
|
||||
)
|
||||
from plane.utils.cache import cache_response
|
||||
from plane.bgtasks.webhook_task import model_activity
|
||||
@@ -343,13 +342,7 @@ class ProjectViewSet(BaseViewSet):
|
||||
.first()
|
||||
)
|
||||
|
||||
# Create the issue type
|
||||
IssueType.objects.create(
|
||||
name="Task",
|
||||
description="A task that needs to be done",
|
||||
project_id=project.id,
|
||||
)
|
||||
|
||||
# Create the model activity
|
||||
model_activity.delay(
|
||||
model_name="project",
|
||||
model_id=str(project.id),
|
||||
|
||||
@@ -21,7 +21,6 @@ from plane.db.models import (
|
||||
Cycle,
|
||||
Module,
|
||||
Issue,
|
||||
IssueType,
|
||||
IssueSequence,
|
||||
IssueAssignee,
|
||||
IssueLabel,
|
||||
@@ -337,12 +336,6 @@ def create_issues(workspace, project, user_id, issue_count):
|
||||
65535 if largest_sort_order is None else largest_sort_order + 10000
|
||||
)
|
||||
|
||||
issue_type = IssueType.objects.create(
|
||||
name="Task",
|
||||
description="A task that needs to be completed.",
|
||||
project=project,
|
||||
)
|
||||
|
||||
for _ in range(0, issue_count):
|
||||
start_date = [None, fake.date_this_year()][random.randint(0, 1)]
|
||||
end_date = (
|
||||
@@ -371,7 +364,6 @@ def create_issues(workspace, project, user_id, issue_count):
|
||||
random.randint(0, 4)
|
||||
],
|
||||
created_by_id=creators[random.randint(0, len(creators) - 1)],
|
||||
type=issue_type,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
# Third party imports
|
||||
from celery import shared_task
|
||||
|
||||
# Django imports
|
||||
from django.utils import timezone
|
||||
|
||||
# Module imports
|
||||
from plane.db.models import PageVersion, IssueType, Issue
|
||||
|
||||
|
||||
@shared_task
|
||||
def backfill_issue_type_task(projects):
|
||||
# Create the issue types for all projects
|
||||
IssueType.objects.bulk_create(
|
||||
[
|
||||
IssueType(
|
||||
name="Task",
|
||||
description="A task that needs to be completed.",
|
||||
project_id=project["id"],
|
||||
workspace_id=project["workspace_id"],
|
||||
)
|
||||
for project in projects
|
||||
],
|
||||
batch_size=1000,
|
||||
)
|
||||
|
||||
# Update the issue type for all existing issues
|
||||
issue_types = {
|
||||
str(issue_type["project_id"]): str(issue_type["id"])
|
||||
for issue_type in IssueType.objects.filter(
|
||||
project_id__in=[project["id"] for project in projects]
|
||||
).values("id", "project_id")
|
||||
}
|
||||
# Update the issue type for all existing issues
|
||||
bulk_issues = []
|
||||
for issue in Issue.objects.filter(
|
||||
project_id__in=[project["id"] for project in projects]
|
||||
):
|
||||
issue.type_id = issue_types[str(issue.project_id)]
|
||||
bulk_issues.append(issue)
|
||||
|
||||
# Update the issue type for all existing issues
|
||||
Issue.objects.bulk_update(bulk_issues, ["type_id"], batch_size=1000)
|
||||
|
||||
|
||||
@shared_task
|
||||
def backfill_page_versions_task(pages):
|
||||
# Create the page versions for all pages
|
||||
PageVersion.objects.bulk_create(
|
||||
[
|
||||
PageVersion(
|
||||
page_id=page["id"],
|
||||
workspace_id=page["workspace_id"],
|
||||
last_saved_at=timezone.now(),
|
||||
owned_by_id=page["owned_by_id"],
|
||||
description_binary=page["description_binary"],
|
||||
description_html=page["description_html"],
|
||||
description_stripped=page["description_stripped"],
|
||||
)
|
||||
for page in pages
|
||||
],
|
||||
batch_size=1000,
|
||||
)
|
||||
@@ -0,0 +1,106 @@
|
||||
# Generated by Django 4.2.11 on 2024-07-10 13:59
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('db', '0069_alter_account_provider_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='apitoken',
|
||||
name='is_service',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='exporterhistory',
|
||||
name='filters',
|
||||
field=models.JSONField(blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='exporterhistory',
|
||||
name='name',
|
||||
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='Exporter Name'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='exporterhistory',
|
||||
name='type',
|
||||
field=models.CharField(choices=[('issue_exports', 'Issue Exports'), ('issue_worklogs', 'Issue Worklogs')], default='issue_exports', max_length=50),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='project',
|
||||
name='is_time_tracking_enabled',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='project',
|
||||
name='start_date',
|
||||
field=models.DateTimeField(blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='project',
|
||||
name='target_date',
|
||||
field=models.DateTimeField(blank=True, null=True),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='PageVersion',
|
||||
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)),
|
||||
('last_saved_at', models.DateTimeField(default=django.utils.timezone.now)),
|
||||
('description_binary', models.BinaryField(null=True)),
|
||||
('description_html', models.TextField(blank=True, default='<p></p>')),
|
||||
('description_stripped', models.TextField(blank=True, null=True)),
|
||||
('description_json', models.JSONField(blank=True, default=dict)),
|
||||
('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')),
|
||||
('owned_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='page_versions', to=settings.AUTH_USER_MODEL)),
|
||||
('page', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='page_versions', to='db.page')),
|
||||
('updated_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_updated_by', to=settings.AUTH_USER_MODEL, verbose_name='Last Modified By')),
|
||||
('workspace', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='page_versions', to='db.workspace')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Page Version',
|
||||
'verbose_name_plural': 'Page Versions',
|
||||
'db_table': 'page_versions',
|
||||
'ordering': ('-created_at',),
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='IssueType',
|
||||
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)),
|
||||
('name', models.CharField(max_length=255)),
|
||||
('description', models.TextField(blank=True)),
|
||||
('logo_props', models.JSONField(default=dict)),
|
||||
('sort_order', models.FloatField(default=65535)),
|
||||
('is_default', models.BooleanField(default=True)),
|
||||
('weight', models.PositiveIntegerField(default=0)),
|
||||
('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')),
|
||||
('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')),
|
||||
('workspace', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='workspace_%(class)s', to='db.workspace')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Issue Type',
|
||||
'verbose_name_plural': 'Issue Types',
|
||||
'db_table': 'issue_types',
|
||||
'ordering': ('sort_order',),
|
||||
'unique_together': {('project', 'name')},
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='issue',
|
||||
name='type',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='issue_type', to='db.issuetype'),
|
||||
),
|
||||
]
|
||||
@@ -1,311 +0,0 @@
|
||||
# Generated by Django 4.2.11 on 2024-07-01 06:10
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import uuid
|
||||
from apiserver.plane.db.backfills.backfill_0070_page_versions import (
|
||||
backfill_issue_type_task,
|
||||
backfill_page_versions_task,
|
||||
)
|
||||
|
||||
CHUNK_SIZE = 100 # Initial Delay in seconds
|
||||
INITIAL_DELAY = 30 # Initial delay in seconds
|
||||
INCREMENT_DELAY = 1 # Increment delay in seconds
|
||||
|
||||
|
||||
def backfill_issue_types(apps, schema_editor):
|
||||
start = 0
|
||||
end = CHUNK_SIZE
|
||||
|
||||
Project = apps.get_model("db", "Project")
|
||||
|
||||
total = Project.objects.count()
|
||||
delay_increment = INITIAL_DELAY
|
||||
|
||||
while start < total:
|
||||
projects = list(
|
||||
Project.objects.values("id", "workspace_id")[start:end]
|
||||
)
|
||||
backfill_issue_type_task.apply_async(
|
||||
(projects,), countdown=delay_increment
|
||||
)
|
||||
delay_increment += (
|
||||
INCREMENT_DELAY # Increment delay for the next batch
|
||||
)
|
||||
start += CHUNK_SIZE
|
||||
end += CHUNK_SIZE
|
||||
|
||||
|
||||
def backfill_page_versions(apps, schema_editor):
|
||||
start = 0
|
||||
end = CHUNK_SIZE
|
||||
|
||||
Page = apps.get_model("db", "Page")
|
||||
|
||||
total = Page.objects.count()
|
||||
delay_increment = INITIAL_DELAY
|
||||
|
||||
while start < total:
|
||||
pages = list(
|
||||
Page.objects.values(
|
||||
"id",
|
||||
"workspace_id",
|
||||
"owned_by_id",
|
||||
"description_binary",
|
||||
"description_html",
|
||||
"description_stripped",
|
||||
)[start:end]
|
||||
)
|
||||
backfill_page_versions_task.apply_async(
|
||||
(pages,), countdown=delay_increment
|
||||
)
|
||||
delay_increment += (
|
||||
INCREMENT_DELAY # Increment delay for the next batch
|
||||
)
|
||||
start += CHUNK_SIZE
|
||||
end += CHUNK_SIZE
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("db", "0069_alter_account_provider_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="IssueType",
|
||||
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,
|
||||
),
|
||||
),
|
||||
("name", models.CharField(max_length=255)),
|
||||
("description", models.TextField(blank=True)),
|
||||
("logo_props", models.JSONField(default=dict)),
|
||||
("sort_order", models.FloatField(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",
|
||||
),
|
||||
),
|
||||
(
|
||||
"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",
|
||||
),
|
||||
),
|
||||
(
|
||||
"workspace",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="workspace_%(class)s",
|
||||
to="db.workspace",
|
||||
),
|
||||
),
|
||||
(
|
||||
"is_default",
|
||||
models.BooleanField(default=True),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "Issue Type",
|
||||
"verbose_name_plural": "Issue Types",
|
||||
"db_table": "issue_types",
|
||||
"ordering": ("sort_order",),
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="issue",
|
||||
name="type",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name="issue_type",
|
||||
to="db.issuetype",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="apitoken",
|
||||
name="is_service",
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="PageVersion",
|
||||
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,
|
||||
),
|
||||
),
|
||||
(
|
||||
"last_saved_at",
|
||||
models.DateTimeField(default=django.utils.timezone.now),
|
||||
),
|
||||
("description_binary", models.BinaryField(null=True)),
|
||||
(
|
||||
"description_html",
|
||||
models.TextField(blank=True, default="<p></p>"),
|
||||
),
|
||||
(
|
||||
"description_stripped",
|
||||
models.TextField(blank=True, null=True),
|
||||
),
|
||||
(
|
||||
"description_json",
|
||||
models.JSONField(blank=True, default=dict),
|
||||
),
|
||||
(
|
||||
"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",
|
||||
),
|
||||
),
|
||||
(
|
||||
"owned_by",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="page_versions",
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
(
|
||||
"page",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="page_versions",
|
||||
to="db.page",
|
||||
),
|
||||
),
|
||||
(
|
||||
"updated_by",
|
||||
models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name="%(class)s_updated_by",
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
verbose_name="Last Modified By",
|
||||
),
|
||||
),
|
||||
(
|
||||
"workspace",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="page_versions",
|
||||
to="db.workspace",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "Page Version",
|
||||
"verbose_name_plural": "Page Versions",
|
||||
"db_table": "page_versions",
|
||||
"ordering": ("-created_at",),
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="exporterhistory",
|
||||
name="filters",
|
||||
field=models.JSONField(blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="exporterhistory",
|
||||
name="name",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
max_length=255,
|
||||
null=True,
|
||||
verbose_name="Exporter Name",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="exporterhistory",
|
||||
name="type",
|
||||
field=models.CharField(
|
||||
choices=[
|
||||
("issue_exports", "Issue Exports"),
|
||||
("issue_work_logs", "Issue Work Logs"),
|
||||
],
|
||||
default="issue_exports",
|
||||
max_length=50,
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="project",
|
||||
name="is_time_tracking_enabled",
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="project",
|
||||
name="start_date",
|
||||
field=models.DateTimeField(blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="project",
|
||||
name="target_date",
|
||||
field=models.DateTimeField(blank=True, null=True),
|
||||
),
|
||||
migrations.RunPython(backfill_issue_types),
|
||||
migrations.RunPython(backfill_page_versions),
|
||||
]
|
||||
@@ -26,7 +26,7 @@ class ExporterHistory(BaseModel):
|
||||
default="issue_exports",
|
||||
choices=(
|
||||
("issue_exports", "Issue Exports"),
|
||||
("issue_work_logs", "Issue Work Logs"),
|
||||
("issue_worklogs", "Issue Worklogs"),
|
||||
),
|
||||
)
|
||||
workspace = models.ForeignKey(
|
||||
|
||||
@@ -11,8 +11,10 @@ class IssueType(WorkspaceBaseModel):
|
||||
logo_props = models.JSONField(default=dict)
|
||||
sort_order = models.FloatField(default=65535)
|
||||
is_default = models.BooleanField(default=True)
|
||||
weight = models.PositiveIntegerField(default=0)
|
||||
|
||||
class Meta:
|
||||
unique_together = ["project", "name"]
|
||||
verbose_name = "Issue Type"
|
||||
verbose_name_plural = "Issue Types"
|
||||
db_table = "issue_types"
|
||||
|
||||
Reference in New Issue
Block a user