This commit is contained in:
DCCONSTRUCTIONS
2026-04-18 18:39:25 +03:00
commit 3ba092b60c
4944 changed files with 497564 additions and 0 deletions
+4
View File
@@ -0,0 +1,4 @@
# Copyright (c) 2023-present Plane Software, Inc. and contributors
# SPDX-License-Identifier: AGPL-3.0-only
# See the LICENSE file for details.
+9
View File
@@ -0,0 +1,9 @@
# Copyright (c) 2023-present Plane Software, Inc. and contributors
# SPDX-License-Identifier: AGPL-3.0-only
# See the LICENSE file for details.
from django.apps import AppConfig
class DbConfig(AppConfig):
name = "plane.db"
@@ -0,0 +1,4 @@
# Copyright (c) 2023-present Plane Software, Inc. and contributors
# SPDX-License-Identifier: AGPL-3.0-only
# See the LICENSE file for details.
@@ -0,0 +1,4 @@
# Copyright (c) 2023-present Plane Software, Inc. and contributors
# SPDX-License-Identifier: AGPL-3.0-only
# See the LICENSE file for details.
@@ -0,0 +1,38 @@
# Copyright (c) 2023-present Plane Software, Inc. and contributors
# SPDX-License-Identifier: AGPL-3.0-only
# See the LICENSE file for details.
# Django imports
from django.core.management import BaseCommand, CommandError
# Module imports
from plane.db.models import User
class Command(BaseCommand):
help = "Make the user with the given email active"
def add_arguments(self, parser):
# Positional argument
parser.add_argument("email", type=str, help="user email")
def handle(self, *args, **options):
# get the user email from console
email = options.get("email", False)
# raise error if email is not present
if not email:
raise CommandError("Error: Email is required")
# filter the user
user = User.objects.filter(email=email).first()
# Raise error if the user is not present
if not user:
raise CommandError(f"Error: User with {email} does not exists")
# Activate the user
user.is_active = True
user.save()
self.stdout.write(self.style.SUCCESS("User activated successfully"))
@@ -0,0 +1,30 @@
# Copyright (c) 2023-present Plane Software, Inc. and contributors
# SPDX-License-Identifier: AGPL-3.0-only
# See the LICENSE file for details.
# Django imports
from django.core.cache import cache
from django.core.management import BaseCommand
class Command(BaseCommand):
help = "Clear Cache before starting the server to remove stale values"
def add_arguments(self, parser):
# Positional argument
parser.add_argument("--key", type=str, nargs="?", help="Key to clear cache")
def handle(self, *args, **options):
try:
if options["key"]:
cache.delete(options["key"])
self.stdout.write(self.style.SUCCESS(f"Cache Cleared for key: {options['key']}"))
return
cache.clear()
self.stdout.write(self.style.SUCCESS("Cache Cleared"))
return
except Exception:
# Another ClientError occurred
self.stdout.write(self.style.ERROR("Failed to clear cache"))
return
@@ -0,0 +1,53 @@
# Copyright (c) 2023-present Plane Software, Inc. and contributors
# SPDX-License-Identifier: AGPL-3.0-only
# See the LICENSE file for details.
# Django imports
from django.core.management.base import BaseCommand
from django.db import transaction
# Module imports
from plane.db.models import Description
from plane.db.models import IssueComment
class Command(BaseCommand):
help = "Create Description records for existing IssueComment"
def handle(self, *args, **kwargs):
batch_size = 500
while True:
comments = list(
IssueComment.objects.filter(description_id__isnull=True).order_by("created_at")[:batch_size]
)
if not comments:
break
with transaction.atomic():
descriptions = [
Description(
created_at=comment.created_at,
updated_at=comment.updated_at,
description_json=comment.comment_json,
description_html=comment.comment_html,
description_stripped=comment.comment_stripped,
project_id=comment.project_id,
created_by_id=comment.created_by_id,
updated_by_id=comment.updated_by_id,
workspace_id=comment.workspace_id,
)
for comment in comments
]
created_descriptions = Description.objects.bulk_create(descriptions)
comments_to_update = []
for comment, description in zip(comments, created_descriptions):
comment.description_id = description.id
comments_to_update.append(comment)
IssueComment.objects.bulk_update(comments_to_update, ["description_id"])
self.stdout.write(self.style.SUCCESS("Successfully Copied IssueComment to Description"))
@@ -0,0 +1,61 @@
# Copyright (c) 2023-present Plane Software, Inc. and contributors
# SPDX-License-Identifier: AGPL-3.0-only
# See the LICENSE file for details.
# Python imports
import os
import boto3
from botocore.exceptions import ClientError
# Django imports
from django.core.management import BaseCommand
class Command(BaseCommand):
help = "Create the default bucket for the instance"
def handle(self, *args, **options):
# Create a session using the credentials from Django settings
try:
s3_client = boto3.client(
"s3",
endpoint_url=os.environ.get("AWS_S3_ENDPOINT_URL"), # MinIO endpoint
aws_access_key_id=os.environ.get("AWS_ACCESS_KEY_ID"), # MinIO access key
aws_secret_access_key=os.environ.get("AWS_SECRET_ACCESS_KEY"), # MinIO secret key
region_name=os.environ.get("AWS_REGION"), # MinIO region
config=boto3.session.Config(signature_version="s3v4"),
)
# Get the bucket name from the environment
bucket_name = os.environ.get("AWS_S3_BUCKET_NAME")
self.stdout.write(self.style.NOTICE("Checking bucket..."))
# Check if the bucket exists
s3_client.head_bucket(Bucket=bucket_name)
# If the bucket exists, print a success message
self.stdout.write(self.style.SUCCESS(f"Bucket '{bucket_name}' exists."))
return
except ClientError as e:
error_code = int(e.response["Error"]["Code"])
bucket_name = os.environ.get("AWS_S3_BUCKET_NAME")
if error_code == 404:
# Bucket does not exist, create it
self.stdout.write(self.style.WARNING(f"Bucket '{bucket_name}' does not exist. Creating bucket..."))
try:
s3_client.create_bucket(Bucket=bucket_name)
self.stdout.write(self.style.SUCCESS(f"Bucket '{bucket_name}' created successfully."))
# Handle the exception if the bucket creation fails
except ClientError as create_error:
self.stdout.write(self.style.ERROR(f"Failed to create bucket: {create_error}"))
# Handle the exception if access to the bucket is forbidden
elif error_code == 403:
# Access to the bucket is forbidden
self.stdout.write(
self.style.ERROR(f"Access to the bucket '{bucket_name}' is forbidden. Check permissions.")
)
else:
# Another ClientError occurred
self.stdout.write(self.style.ERROR(f"Failed to check bucket: {e}"))
except Exception as ex:
# Handle any other exception
self.stdout.write(self.style.ERROR(f"An error occurred: {ex}"))
@@ -0,0 +1,74 @@
# Copyright (c) 2023-present Plane Software, Inc. and contributors
# SPDX-License-Identifier: AGPL-3.0-only
# See the LICENSE file for details.
# Django imports
from typing import Any
from django.core.management.base import BaseCommand, CommandError
# Module imports
from plane.db.models import User, Workspace, WorkspaceMember
class Command(BaseCommand):
help = "Create dump issues, cycles etc. for a project in a given workspace"
def handle(self, *args: Any, **options: Any) -> str | None:
try:
workspace_name = input("Workspace Name: ")
workspace_slug = input("Workspace slug: ")
if workspace_slug == "":
raise CommandError("Workspace slug is required")
if Workspace.objects.filter(slug=workspace_slug).exists():
raise CommandError("Workspace already exists")
creator = input("Your email: ")
if creator == "" or not User.objects.filter(email=creator).exists():
raise CommandError("User email is required and should have signed in plane")
user = User.objects.get(email=creator)
members = input("Enter Member emails (comma separated): ")
members = members.split(",") if members != "" else []
# Create workspace
workspace = Workspace.objects.create(slug=workspace_slug, name=workspace_name, owner=user)
# Create workspace member
WorkspaceMember.objects.create(workspace=workspace, role=20, member=user)
user_ids = User.objects.filter(email__in=members)
_ = WorkspaceMember.objects.bulk_create(
[WorkspaceMember(workspace=workspace, member=user_id, role=20) for user_id in user_ids],
ignore_conflicts=True,
)
project_count = int(input("Number of projects to be created: "))
for i in range(project_count):
print(f"Please provide the following details for project {i + 1}:")
issue_count = int(input("Number of issues to be created: "))
cycle_count = int(input("Number of cycles to be created: "))
module_count = int(input("Number of modules to be created: "))
pages_count = int(input("Number of pages to be created: "))
intake_issue_count = int(input("Number of intake issues to be created: "))
from plane.bgtasks.dummy_data_task import create_dummy_data
create_dummy_data(
slug=workspace_slug,
email=creator,
members=members,
issue_count=issue_count,
cycle_count=cycle_count,
module_count=module_count,
pages_count=pages_count,
intake_issue_count=intake_issue_count,
)
self.stdout.write(self.style.SUCCESS("Data is pushed to the queue"))
return
except Exception as e:
self.stdout.write(self.style.ERROR(f"Command errored out {str(e)}"))
return
@@ -0,0 +1,43 @@
# Copyright (c) 2023-present Plane Software, Inc. and contributors
# SPDX-License-Identifier: AGPL-3.0-only
# See the LICENSE file for details.
# Django imports
from django.core.management.base import BaseCommand, CommandError
# Module imports
from plane.license.models import Instance, InstanceAdmin
from plane.db.models import User
class Command(BaseCommand):
help = "Add a new instance admin"
def add_arguments(self, parser):
# Positional argument
parser.add_argument("admin_email", type=str, help="Instance Admin Email")
def handle(self, *args, **options):
admin_email = options.get("admin_email", False)
if not admin_email:
raise CommandError("Please provide the email of the admin.")
user = User.objects.filter(email=admin_email).first()
if user is None:
raise CommandError("User with the provided email does not exist.")
try:
# Get the instance
instance = Instance.objects.last()
# Get or create an instance admin
_, created = InstanceAdmin.objects.get_or_create(user=user, instance=instance, role=20)
if not created:
raise CommandError("The provided email is already an instance admin.")
self.stdout.write(self.style.SUCCESS("Successfully created the admin"))
except Exception as e:
print(e)
raise CommandError("Failed to create the instance admin.")
@@ -0,0 +1,72 @@
# Copyright (c) 2023-present Plane Software, Inc. and contributors
# SPDX-License-Identifier: AGPL-3.0-only
# See the LICENSE file for details.
# Django imports
from typing import Any
from django.core.management import BaseCommand, CommandError
# Module imports
from plane.db.models import (
User,
WorkspaceMember,
ProjectMember,
Project,
ProjectUserProperty,
)
class Command(BaseCommand):
help = "Add a member to a project. If present in the workspace"
def add_arguments(self, parser):
# Positional argument
parser.add_argument("--project_id", type=str, nargs="?", help="Project ID")
parser.add_argument("--user_email", type=str, nargs="?", help="User Email")
parser.add_argument("--role", type=int, nargs="?", help="Role of the user in the project")
def handle(self, *args: Any, **options: Any):
try:
if not options["project_id"]:
raise CommandError("Project ID is required")
if not options["user_email"]:
raise CommandError("User Email is required")
project_id = options["project_id"]
user_email = options["user_email"]
role = options.get("role", 20)
print(f"Role: {role}")
user = User.objects.filter(email=user_email).first()
if not user:
raise CommandError("User not found")
# Check if the project exists
project = Project.objects.filter(pk=project_id).first()
if not project:
raise CommandError("Project not found")
# Check if the user exists in the workspace
if not WorkspaceMember.objects.filter(workspace=project.workspace, member=user, is_active=True).exists():
raise CommandError("User not member in workspace")
if ProjectMember.objects.filter(project=project, member=user).exists():
# Update the project member
ProjectMember.objects.filter(project=project, member=user).update(
is_active=True, role=role
)
else:
# Create the project member
ProjectMember.objects.create(project=project, member=user, role=role)
# Issue Property
ProjectUserProperty.objects.get_or_create(user=user, project=project)
# Success message
self.stdout.write(self.style.SUCCESS(f"User {user_email} added to project {project_id}"))
return
except CommandError as e:
self.stdout.write(self.style.ERROR(e))
return
@@ -0,0 +1,95 @@
# Copyright (c) 2023-present Plane Software, Inc. and contributors
# SPDX-License-Identifier: AGPL-3.0-only
# See the LICENSE file for details.
# Django imports
from django.core.management.base import BaseCommand, CommandError
from django.db.models import Max
from django.db import connection, transaction
# Module imports
from plane.db.models import Project, Issue, IssueSequence
from plane.utils.uuid import convert_uuid_to_integer
class Command(BaseCommand):
help = "Fix duplicate sequences"
def add_arguments(self, parser):
# Positional argument
parser.add_argument("issue_identifier", type=str, help="Issue Identifier")
def strict_str_to_int(self, s):
if not s.isdigit() and not (s.startswith("-") and s[1:].isdigit()):
raise ValueError("Invalid integer string")
return int(s)
def handle(self, *args, **options):
workspace_slug = input("Workspace slug: ")
if not workspace_slug:
raise CommandError("Workspace slug is required")
issue_identifier = options.get("issue_identifier", False)
# Validate issue_identifier
if not issue_identifier:
raise CommandError("Issue identifier is required")
# Validate issue identifier
try:
identifier = issue_identifier.split("-")
if len(identifier) != 2:
raise ValueError("Invalid issue identifier format")
project_identifier = identifier[0]
issue_sequence = self.strict_str_to_int(identifier[1])
# Fetch the project
project = Project.objects.get(identifier__iexact=project_identifier, workspace__slug=workspace_slug)
# Get the issues
issues = Issue.objects.filter(project=project, sequence_id=issue_sequence)
# Check if there are duplicate issues
if not issues.count() > 1:
raise CommandError("No duplicate issues found with the given identifier")
self.stdout.write(self.style.SUCCESS(f"{issues.count()} issues found with identifier {issue_identifier}"))
with transaction.atomic():
# This ensures only one transaction per project can execute this code at a time
lock_key = convert_uuid_to_integer(project.id)
# Acquire an exclusive lock using the project ID as the lock key
with connection.cursor() as cursor:
# Get an exclusive lock using the project ID as the lock key
cursor.execute("SELECT pg_advisory_xact_lock(%s)", [lock_key])
# Get the maximum sequence ID for the project
last_sequence = IssueSequence.objects.filter(project=project).aggregate(largest=Max("sequence"))[
"largest"
]
bulk_issues = []
bulk_issue_sequences = []
issue_sequence_map = {isq.issue_id: isq for isq in IssueSequence.objects.filter(project=project)}
# change the ids of duplicate issues
for index, issue in enumerate(issues[1:]):
updated_sequence_id = last_sequence + index + 1
issue.sequence_id = updated_sequence_id
bulk_issues.append(issue)
# Find the same issue sequence instance from the above queryset
sequence_identifier = issue_sequence_map.get(issue.id)
if sequence_identifier:
sequence_identifier.sequence = updated_sequence_id
bulk_issue_sequences.append(sequence_identifier)
Issue.objects.bulk_update(bulk_issues, ["sequence_id"])
IssueSequence.objects.bulk_update(bulk_issue_sequences, ["sequence"])
self.stdout.write(self.style.SUCCESS("Sequence IDs updated successfully"))
except Exception as e:
raise CommandError(str(e))
@@ -0,0 +1,64 @@
# Copyright (c) 2023-present Plane Software, Inc. and contributors
# SPDX-License-Identifier: AGPL-3.0-only
# See the LICENSE file for details.
# Python imports
import getpass
# Django imports
from django.core.management import BaseCommand, CommandError
# Module imports
from plane.authentication.utils.password_validation import is_password_policy_valid
from plane.db.models import User
class Command(BaseCommand):
help = "Reset password of the user with the given email"
def add_arguments(self, parser):
# Positional argument
parser.add_argument("email", type=str, help="user email")
def handle(self, *args, **options):
# get the user email from console
email = options.get("email", False)
# raise error if email is not present
if not email:
self.stderr.write("Error: Email is required")
return
# filter the user
user = User.objects.filter(email=email).first()
# Raise error if the user is not present
if not user:
self.stderr.write(f"Error: User with {email} does not exists")
return
# get password for the user
password = getpass.getpass("Password: ")
confirm_password = getpass.getpass("Password (again): ")
# If the passwords doesn't match raise error
if password != confirm_password:
self.stderr.write("Error: Your passwords didn't match.")
return
# Blank passwords should not be allowed
if password.strip() == "":
self.stderr.write("Error: Blank passwords aren't allowed.")
return
if not is_password_policy_valid(password):
raise CommandError(
"Password must be at least 8 characters long and include upper-case, lower-case, number, special character, and must not be predictable"
)
# Set user password
user.set_password(password)
user.is_password_autoset = False
user.save()
self.stdout.write(self.style.SUCCESS("User password updated successfully"))
@@ -0,0 +1,23 @@
# Copyright (c) 2023-present Plane Software, Inc. and contributors
# SPDX-License-Identifier: AGPL-3.0-only
# See the LICENSE file for details.
# Django imports
from django.core.management.base import BaseCommand
# Module imports
from plane.bgtasks.issue_description_version_sync import (
schedule_issue_description_version,
)
class Command(BaseCommand):
help = "Creates IssueDescriptionVersion records for existing Issues in batches"
def handle(self, *args, **options):
batch_size = input("Enter the batch size: ")
batch_countdown = input("Enter the batch countdown: ")
schedule_issue_description_version.delay(batch_size=batch_size, countdown=int(batch_countdown))
self.stdout.write(self.style.SUCCESS("Successfully created issue description version task"))
@@ -0,0 +1,21 @@
# Copyright (c) 2023-present Plane Software, Inc. and contributors
# SPDX-License-Identifier: AGPL-3.0-only
# See the LICENSE file for details.
# Django imports
from django.core.management.base import BaseCommand
# Module imports
from plane.bgtasks.issue_version_sync import schedule_issue_version
class Command(BaseCommand):
help = "Creates IssueVersion records for existing Issues in batches"
def handle(self, *args, **options):
batch_size = input("Enter the batch size: ")
batch_countdown = input("Enter the batch countdown: ")
schedule_issue_version.delay(batch_size=batch_size, countdown=int(batch_countdown))
self.stdout.write(self.style.SUCCESS("Successfully created issue version task"))
@@ -0,0 +1,67 @@
# Copyright (c) 2023-present Plane Software, Inc. and contributors
# SPDX-License-Identifier: AGPL-3.0-only
# See the LICENSE file for details.
from django.core.mail import EmailMultiAlternatives, get_connection
from django.core.management import BaseCommand, CommandError
from django.template.loader import render_to_string
from django.utils.html import strip_tags
# Module imports
from plane.license.utils.instance_value import get_email_configuration
class Command(BaseCommand):
"""Django command to pause execution until db is available"""
def add_arguments(self, parser):
# Positional argument
parser.add_argument("to_email", type=str, help="receiver's email")
def handle(self, *args, **options):
receiver_email = options.get("to_email")
if not receiver_email:
raise CommandError("Receiver email is required")
(
EMAIL_HOST,
EMAIL_HOST_USER,
EMAIL_HOST_PASSWORD,
EMAIL_PORT,
EMAIL_USE_TLS,
EMAIL_USE_SSL,
EMAIL_FROM,
) = get_email_configuration()
connection = get_connection(
host=EMAIL_HOST,
port=int(EMAIL_PORT),
username=EMAIL_HOST_USER,
password=EMAIL_HOST_PASSWORD,
use_tls=EMAIL_USE_TLS == "1",
use_ssl=EMAIL_USE_SSL == "1",
timeout=30,
)
# Prepare email details
subject = "Test email from Plane"
html_content = render_to_string("emails/test_email.html")
text_content = strip_tags(html_content)
self.stdout.write(self.style.SUCCESS("Trying to send test email..."))
# Send the email
try:
msg = EmailMultiAlternatives(
subject=subject,
body=text_content,
from_email=EMAIL_FROM,
to=[receiver_email],
connection=connection,
)
msg.attach_alternative(html_content, "text/html")
msg.send()
self.stdout.write(self.style.SUCCESS("Email successfully sent"))
except Exception as e:
self.stdout.write(self.style.ERROR(f"Error: Email could not be delivered due to {e}"))
@@ -0,0 +1,187 @@
# Copyright (c) 2023-present Plane Software, Inc. and contributors
# SPDX-License-Identifier: AGPL-3.0-only
# See the LICENSE file for details.
# Python imports
import os
import boto3
from botocore.exceptions import ClientError
import json
# Django imports
from django.core.management import BaseCommand
class Command(BaseCommand):
help = "Create the default bucket for the instance"
def get_s3_client(self):
s3_client = boto3.client(
"s3",
endpoint_url=os.environ.get("AWS_S3_ENDPOINT_URL"), # MinIO endpoint
aws_access_key_id=os.environ.get("AWS_ACCESS_KEY_ID"), # MinIO access key
aws_secret_access_key=os.environ.get("AWS_SECRET_ACCESS_KEY"), # MinIO secret key
region_name=os.environ.get("AWS_REGION"), # MinIO region
config=boto3.session.Config(signature_version="s3v4"),
)
return s3_client
# Check if the access key has the required permissions
def check_s3_permissions(self, bucket_name):
s3_client = self.get_s3_client()
permissions = {
"s3:GetObject": False,
"s3:ListBucket": False,
"s3:PutBucketPolicy": False,
"s3:PutObject": False,
}
# 1. Test s3:ListBucket (attempt to list the bucket contents)
try:
s3_client.list_objects_v2(Bucket=bucket_name)
permissions["s3:ListBucket"] = True
except ClientError as e:
if e.response["Error"]["Code"] == "AccessDenied":
self.stdout.write("ListBucket permission denied.")
else:
self.stdout.write(f"Error in ListBucket: {e}")
# 2. Test s3:GetObject (attempt to get a specific object)
try:
response = s3_client.list_objects_v2(Bucket=bucket_name)
if "Contents" in response:
test_object_key = response["Contents"][0]["Key"]
s3_client.get_object(Bucket=bucket_name, Key=test_object_key)
permissions["s3:GetObject"] = True
except ClientError as e:
if e.response["Error"]["Code"] == "AccessDenied":
self.stdout.write("GetObject permission denied.")
else:
self.stdout.write(f"Error in GetObject: {e}")
# 3. Test s3:PutObject (attempt to upload an object)
try:
s3_client.put_object(Bucket=bucket_name, Key="test_permission_check.txt", Body=b"Test")
permissions["s3:PutObject"] = True
# Clean up
except ClientError as e:
if e.response["Error"]["Code"] == "AccessDenied":
self.stdout.write("PutObject permission denied.")
else:
self.stdout.write(f"Error in PutObject: {e}")
# Clean up
try:
s3_client.delete_object(Bucket=bucket_name, Key="test_permission_check.txt")
except ClientError:
self.stdout.write("Couldn't delete test object")
# 4. Test s3:PutBucketPolicy (attempt to put a bucket policy)
try:
policy = {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": f"arn:aws:s3:::{bucket_name}/*",
}
],
}
s3_client.put_bucket_policy(Bucket=bucket_name, Policy=json.dumps(policy))
permissions["s3:PutBucketPolicy"] = True
except ClientError as e:
if e.response["Error"]["Code"] == "AccessDenied":
self.stdout.write("PutBucketPolicy permission denied.")
else:
self.stdout.write(f"Error in PutBucketPolicy: {e}")
return permissions
def generate_bucket_policy(self, bucket_name):
s3_client = self.get_s3_client()
response = s3_client.list_objects_v2(Bucket=bucket_name)
public_object_resource = []
if "Contents" in response:
for obj in response["Contents"]:
object_key = obj["Key"]
public_object_resource.append(f"arn:aws:s3:::{bucket_name}/{object_key}")
bucket_policy = {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": public_object_resource,
}
],
}
return bucket_policy
def make_objects_public(self, bucket_name):
# Initialize S3 client
s3_client = self.get_s3_client()
# Get the bucket policy
bucket_policy = self.generate_bucket_policy(bucket_name)
# Apply the policy to the bucket
s3_client.put_bucket_policy(Bucket=bucket_name, Policy=json.dumps(bucket_policy))
# Print a success message
self.stdout.write("Bucket is private, but existing objects remain public.")
return
def handle(self, *args, **options):
# Create a session using the credentials from Django settings
# Check if the bucket exists
s3_client = self.get_s3_client()
# Get the bucket name from the environment
bucket_name = os.environ.get("AWS_S3_BUCKET_NAME")
if not bucket_name:
self.stdout.write(self.style.ERROR("Please set the AWS_S3_BUCKET_NAME environment variable."))
return
self.stdout.write(self.style.NOTICE("Checking bucket..."))
# Check if the bucket exists
try:
s3_client.head_bucket(Bucket=bucket_name)
except ClientError as e:
error_code = e.response["Error"]["Code"]
if error_code == "404":
self.stdout.write(self.style.ERROR(f"Bucket '{bucket_name}' does not exist."))
return
else:
self.stdout.write(f"Error: {e}")
# If the bucket exists, print a success message
self.stdout.write(self.style.SUCCESS(f"Bucket '{bucket_name}' exists."))
try:
# Check the permissions of the access key
permissions = self.check_s3_permissions(bucket_name)
except ClientError as e:
self.stdout.write(f"Error: {e}")
except Exception as e:
self.stdout.write(f"Error: {e}")
# If the access key has the required permissions
try:
if all(permissions.values()):
self.stdout.write(self.style.SUCCESS("Access key has the required permissions."))
# Making the existing objects public
self.make_objects_public(bucket_name)
return
except Exception as e:
self.stdout.write(f"Error: {e}")
# write the bucket policy to a file
self.stdout.write(self.style.WARNING("Generating permissions.json for manual bucket policy update."))
try:
# Writing to a file
with open("permissions.json", "w") as f:
f.write(json.dumps(self.generate_bucket_policy(bucket_name)))
self.stdout.write(self.style.WARNING("Permissions have been written to permissions.json."))
return
except IOError as e:
self.stdout.write(f"Error writing permissions.json: {e}")
return
@@ -0,0 +1,71 @@
# Copyright (c) 2023-present Plane Software, Inc. and contributors
# SPDX-License-Identifier: AGPL-3.0-only
# See the LICENSE file for details.
from django.core.management.base import BaseCommand
from django.db import transaction
from plane.db.models import Workspace
class Command(BaseCommand):
help = "Updates the slug of a soft-deleted workspace by appending the epoch timestamp"
def add_arguments(self, parser):
parser.add_argument(
"slug",
type=str,
help="The slug of the workspace to update",
)
parser.add_argument(
"--dry-run",
action="store_true",
help="Run the command without making any changes",
)
def handle(self, *args, **options):
slug = options["slug"]
dry_run = options["dry_run"]
# Get the workspace with the specified slug
try:
workspace = Workspace.all_objects.get(slug=slug)
except Workspace.DoesNotExist:
self.stdout.write(self.style.ERROR(f"Workspace with slug '{slug}' not found."))
return
# Check if the workspace is soft-deleted
if workspace.deleted_at is None:
self.stdout.write(
self.style.WARNING(f"Workspace '{workspace.name}' (slug: {workspace.slug}) is not deleted.")
)
return
# Check if the slug already has a timestamp appended
if "__" in workspace.slug and workspace.slug.split("__")[-1].isdigit():
self.stdout.write(
self.style.WARNING(
f"Workspace '{workspace.name}' (slug: {workspace.slug}) already has a timestamp appended."
)
)
return
# Get the deletion timestamp
deletion_timestamp = int(workspace.deleted_at.timestamp())
# Create the new slug with the deletion timestamp
new_slug = f"{workspace.slug}__{deletion_timestamp}"
if dry_run:
self.stdout.write(f"Would update workspace '{workspace.name}' slug from '{workspace.slug}' to '{new_slug}'")
else:
try:
with transaction.atomic():
workspace.slug = new_slug
workspace.save(update_fields=["slug"])
self.stdout.write(
self.style.SUCCESS(
f"Updated workspace '{workspace.name}' slug from '{workspace.slug}' to '{new_slug}'"
)
)
except Exception as e:
self.stdout.write(self.style.ERROR(f"Error updating workspace '{workspace.name}': {str(e)}"))
@@ -0,0 +1,24 @@
# Copyright (c) 2023-present Plane Software, Inc. and contributors
# SPDX-License-Identifier: AGPL-3.0-only
# See the LICENSE file for details.
import time
from django.db import connections
from django.db.utils import OperationalError
from django.core.management import BaseCommand
class Command(BaseCommand):
"""Django command to pause execution until db is available"""
def handle(self, *args, **options):
self.stdout.write("Waiting for database...")
db_conn = None
while not db_conn:
try:
db_conn = connections["default"]
except OperationalError:
self.stdout.write("Database unavailable, waititng 1 second...")
time.sleep(1)
self.stdout.write(self.style.SUCCESS("Database available!"))
@@ -0,0 +1,26 @@
# Copyright (c) 2023-present Plane Software, Inc. and contributors
# SPDX-License-Identifier: AGPL-3.0-only
# See the LICENSE file for details.
# wait_for_migrations.py
import time
from django.core.management.base import BaseCommand
from django.db.migrations.executor import MigrationExecutor
from django.db import connections, DEFAULT_DB_ALIAS
class Command(BaseCommand):
help = "Wait for database migrations to complete before starting Celery worker/beat"
def handle(self, *args, **kwargs):
while self._pending_migrations():
self.stdout.write("Waiting for database migrations to complete...")
time.sleep(10) # wait for 10 seconds before checking again
self.stdout.write(self.style.SUCCESS("No migrations Pending. Starting processes ..."))
def _pending_migrations(self):
connection = connections[DEFAULT_DB_ALIAS]
executor = MigrationExecutor(connection)
targets = executor.loader.graph.leaf_nodes()
return bool(executor.migration_plan(targets))
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,71 @@
# Generated by Django 3.2.14 on 2022-11-04 17:09
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("db", "0001_initial"),
]
operations = [
migrations.AlterModelOptions(
name="state",
options={
"ordering": ("sequence",),
"verbose_name": "State",
"verbose_name_plural": "States",
},
),
migrations.RenameField(
model_name="project",
old_name="description_rt",
new_name="description_text",
),
migrations.AddField(
model_name="issueactivity",
name="actor",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="issue_activities",
to=settings.AUTH_USER_MODEL,
),
),
migrations.AddField(
model_name="issuecomment",
name="actor",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="comments",
to=settings.AUTH_USER_MODEL,
),
),
migrations.AddField(
model_name="state",
name="sequence",
field=models.PositiveIntegerField(default=65535),
),
migrations.AddField(
model_name="workspace",
name="company_size",
field=models.PositiveIntegerField(default=10),
),
migrations.AddField(
model_name="workspacemember",
name="company_role",
field=models.TextField(blank=True, null=True),
),
migrations.AlterField(
model_name="cycleissue",
name="issue",
field=models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE,
related_name="issue_cycle",
to="db.issue",
),
),
]
@@ -0,0 +1,27 @@
# Generated by Django 3.2.14 on 2022-11-09 17:50
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("db", "0002_auto_20221104_2239"),
]
operations = [
migrations.AlterField(
model_name="issueproperty",
name="user",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="issue_property_user",
to=settings.AUTH_USER_MODEL,
),
),
migrations.AlterUniqueTogether(
name="issueproperty",
unique_together={("user", "project")},
),
]
@@ -0,0 +1,17 @@
# Generated by Django 3.2.14 on 2022-11-10 19:46
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("db", "0003_auto_20221109_2320"),
]
operations = [
migrations.AlterField(
model_name="state",
name="sequence",
field=models.FloatField(default=65535),
),
]
@@ -0,0 +1,26 @@
# Generated by Django 3.2.14 on 2022-11-14 15:57
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("db", "0004_alter_state_sequence"),
]
operations = [
migrations.AlterField(
model_name="cycle",
name="end_date",
field=models.DateField(
blank=True, null=True, verbose_name="End Date"
),
),
migrations.AlterField(
model_name="cycle",
name="start_date",
field=models.DateField(
blank=True, null=True, verbose_name="Start Date"
),
),
]
@@ -0,0 +1,26 @@
# Generated by Django 3.2.14 on 2022-11-16 14:54
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("db", "0005_auto_20221114_2127"),
]
operations = [
migrations.AlterField(
model_name="cycle",
name="status",
field=models.CharField(
choices=[
("draft", "Draft"),
("started", "Started"),
("completed", "Completed"),
],
default="draft",
max_length=255,
verbose_name="Cycle Status",
),
),
]
@@ -0,0 +1,24 @@
# Generated by Django 3.2.14 on 2022-11-28 20:00
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("db", "0006_alter_cycle_status"),
]
operations = [
migrations.AddField(
model_name="label",
name="parent",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="parent_label",
to="db.label",
),
),
]
@@ -0,0 +1,17 @@
# Generated by Django 3.2.14 on 2022-11-29 19:15
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("db", "0007_label_parent"),
]
operations = [
migrations.AddField(
model_name="label",
name="colour",
field=models.CharField(blank=True, max_length=255),
),
]
@@ -0,0 +1,32 @@
# Generated by Django 3.2.14 on 2022-12-13 17:58
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("db", "0008_label_colour"),
]
operations = [
migrations.AddField(
model_name="projectmember",
name="view_props",
field=models.JSONField(null=True),
),
migrations.AddField(
model_name="state",
name="group",
field=models.CharField(
choices=[
("backlog", "Backlog"),
("unstarted", "Unstarted"),
("started", "Started"),
("completed", "Completed"),
("cancelled", "Cancelled"),
],
default="backlog",
max_length=20,
),
),
]
@@ -0,0 +1,41 @@
# Generated by Django 3.2.14 on 2022-12-13 18:18
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("db", "0009_auto_20221208_0310"),
]
operations = [
migrations.AddField(
model_name="projectidentifier",
name="workspace",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="project_identifiers",
to="db.workspace",
),
),
migrations.AlterField(
model_name="project",
name="identifier",
field=models.CharField(
max_length=5, verbose_name="Project Identifier"
),
),
migrations.AlterUniqueTogether(
name="project",
unique_together={
("name", "workspace"),
("identifier", "workspace"),
},
),
migrations.AlterUniqueTogether(
name="projectidentifier",
unique_together={("name", "workspace")},
),
]
@@ -0,0 +1,348 @@
# Generated by Django 3.2.14 on 2022-12-22 18:27
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import plane.db.models.project
import uuid
class Migration(migrations.Migration):
dependencies = [
("db", "0010_auto_20221213_0037"),
]
operations = [
migrations.CreateModel(
name="Module",
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, verbose_name="Module Name"
),
),
(
"description",
models.TextField(
blank=True, verbose_name="Module Description"
),
),
(
"description_text",
models.JSONField(
blank=True,
null=True,
verbose_name="Module Description RT",
),
),
(
"description_html",
models.JSONField(
blank=True,
null=True,
verbose_name="Module Description HTML",
),
),
("start_date", models.DateField(null=True)),
("target_date", models.DateField(null=True)),
(
"status",
models.CharField(
choices=[
("backlog", "Backlog"),
("planned", "Planned"),
("in-progress", "In Progress"),
("paused", "Paused"),
("completed", "Completed"),
("cancelled", "Cancelled"),
],
default="planned",
max_length=20,
),
),
],
options={
"verbose_name": "Module",
"verbose_name_plural": "Modules",
"db_table": "module",
"ordering": ("-created_at",),
},
),
migrations.AddField(
model_name="project",
name="icon",
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name="projectmember",
name="default_props",
field=models.JSONField(
default=plane.db.models.project.get_default_props
),
),
migrations.AddField(
model_name="user",
name="my_issues_prop",
field=models.JSONField(null=True),
),
migrations.CreateModel(
name="ModuleMember",
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,
),
),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="modulemember_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"member",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to=settings.AUTH_USER_MODEL,
),
),
(
"module",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="db.module",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_modulemember",
to="db.project",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="modulemember_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_modulemember",
to="db.workspace",
),
),
],
options={
"verbose_name": "Module Member",
"verbose_name_plural": "Module Members",
"db_table": "module_member",
"ordering": ("-created_at",),
"unique_together": {("module", "member")},
},
),
migrations.AddField(
model_name="module",
name="created_by",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="module_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
migrations.AddField(
model_name="module",
name="lead",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="module_leads",
to=settings.AUTH_USER_MODEL,
),
),
migrations.AddField(
model_name="module",
name="members",
field=models.ManyToManyField(
blank=True,
related_name="module_members",
through="db.ModuleMember",
to=settings.AUTH_USER_MODEL,
),
),
migrations.AddField(
model_name="module",
name="project",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_module",
to="db.project",
),
),
migrations.AddField(
model_name="module",
name="updated_by",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="module_updated_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Last Modified By",
),
),
migrations.AddField(
model_name="module",
name="workspace",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="workspace_module",
to="db.workspace",
),
),
migrations.CreateModel(
name="ModuleIssue",
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,
),
),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="moduleissue_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"issue",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="issue_module",
to="db.issue",
),
),
(
"module",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="issue_module",
to="db.module",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_moduleissue",
to="db.project",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="moduleissue_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_moduleissue",
to="db.workspace",
),
),
],
options={
"verbose_name": "Module Issue",
"verbose_name_plural": "Module Issues",
"db_table": "module_issues",
"ordering": ("-created_at",),
"unique_together": {("module", "issue")},
},
),
migrations.AlterUniqueTogether(
name="module",
unique_together={("name", "project")},
),
]
@@ -0,0 +1,234 @@
# Generated by Django 3.2.16 on 2023-01-03 19:47
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
("db", "0011_auto_20221222_2357"),
]
operations = [
migrations.AddField(
model_name="issueactivity",
name="new_identifier",
field=models.UUIDField(null=True),
),
migrations.AddField(
model_name="issueactivity",
name="old_identifier",
field=models.UUIDField(null=True),
),
migrations.AlterField(
model_name="moduleissue",
name="issue",
field=models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE,
related_name="issue_module",
to="db.issue",
),
),
migrations.AlterUniqueTogether(
name="moduleissue",
unique_together=set(),
),
migrations.AlterModelTable(
name="cycle",
table="cycles",
),
migrations.AlterModelTable(
name="cycleissue",
table="cycle_issues",
),
migrations.AlterModelTable(
name="fileasset",
table="file_assets",
),
migrations.AlterModelTable(
name="issue",
table="issues",
),
migrations.AlterModelTable(
name="issueactivity",
table="issue_activities",
),
migrations.AlterModelTable(
name="issueassignee",
table="issue_assignees",
),
migrations.AlterModelTable(
name="issueblocker",
table="issue_blockers",
),
migrations.AlterModelTable(
name="issuecomment",
table="issue_comments",
),
migrations.AlterModelTable(
name="issuelabel",
table="issue_labels",
),
migrations.AlterModelTable(
name="issueproperty",
table="issue_properties",
),
migrations.AlterModelTable(
name="issuesequence",
table="issue_sequences",
),
migrations.AlterModelTable(
name="label",
table="labels",
),
migrations.AlterModelTable(
name="module",
table="modules",
),
migrations.AlterModelTable(
name="modulemember",
table="module_members",
),
migrations.AlterModelTable(
name="project",
table="projects",
),
migrations.AlterModelTable(
name="projectidentifier",
table="project_identifiers",
),
migrations.AlterModelTable(
name="projectmember",
table="project_members",
),
migrations.AlterModelTable(
name="projectmemberinvite",
table="project_member_invites",
),
migrations.AlterModelTable(
name="shortcut",
table="shortcuts",
),
migrations.AlterModelTable(
name="socialloginconnection",
table="social_login_connections",
),
migrations.AlterModelTable(
name="state",
table="states",
),
migrations.AlterModelTable(
name="team",
table="teams",
),
migrations.AlterModelTable(
name="teammember",
table="team_members",
),
migrations.AlterModelTable(
name="timelineissue",
table="issue_timelines",
),
migrations.AlterModelTable(
name="user",
table="users",
),
migrations.AlterModelTable(
name="view",
table="views",
),
migrations.AlterModelTable(
name="workspace",
table="workspaces",
),
migrations.AlterModelTable(
name="workspacemember",
table="workspace_members",
),
migrations.AlterModelTable(
name="workspacememberinvite",
table="workspace_member_invites",
),
migrations.CreateModel(
name="ModuleLink",
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,
),
),
("title", models.CharField(max_length=255, null=True)),
("url", models.URLField()),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="modulelink_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"module",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="link_module",
to="db.module",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_modulelink",
to="db.project",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="modulelink_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_modulelink",
to="db.workspace",
),
),
],
options={
"verbose_name": "Module Link",
"verbose_name_plural": "Module Links",
"db_table": "module_links",
"ordering": ("-created_at",),
},
),
]
@@ -0,0 +1,37 @@
# Generated by Django 3.2.16 on 2023-01-06 19:11
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("db", "0012_auto_20230104_0117"),
]
operations = [
migrations.AddField(
model_name="issue",
name="description_html",
field=models.TextField(blank=True),
),
migrations.AddField(
model_name="issue",
name="description_stripped",
field=models.TextField(blank=True),
),
migrations.AddField(
model_name="user",
name="role",
field=models.CharField(blank=True, max_length=300, null=True),
),
migrations.AddField(
model_name="workspacemember",
name="view_props",
field=models.JSONField(blank=True, null=True),
),
migrations.AlterField(
model_name="issue",
name="description",
field=models.JSONField(blank=True),
),
]
@@ -0,0 +1,16 @@
# Generated by Django 3.2.16 on 2023-01-07 05:41
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("db", "0013_auto_20230107_0041"),
]
operations = [
migrations.AlterUniqueTogether(
name="workspacememberinvite",
unique_together={("email", "workspace")},
),
]
@@ -0,0 +1,27 @@
# Generated by Django 3.2.16 on 2023-01-07 11:06
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("db", "0014_alter_workspacememberinvite_unique_together"),
]
operations = [
migrations.RenameField(
model_name="issuecomment",
old_name="comment",
new_name="comment_stripped",
),
migrations.AddField(
model_name="issuecomment",
name="comment_html",
field=models.TextField(blank=True),
),
migrations.AddField(
model_name="issuecomment",
name="comment_json",
field=models.JSONField(blank=True, null=True),
),
]
@@ -0,0 +1,32 @@
# Generated by Django 3.2.16 on 2023-01-07 12:05
from django.db import migrations, models
import django.db.models.deletion
import plane.db.models.asset
class Migration(migrations.Migration):
dependencies = [
("db", "0015_auto_20230107_1636"),
]
operations = [
migrations.AddField(
model_name="fileasset",
name="workspace",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="assets",
to="db.workspace",
),
),
migrations.AlterField(
model_name="fileasset",
name="asset",
field=models.FileField(
upload_to=plane.db.models.asset.get_upload_path,
validators=[plane.db.models.asset.file_size],
),
),
]
@@ -0,0 +1,16 @@
# Generated by Django 3.2.16 on 2023-01-07 17:49
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("db", "0016_auto_20230107_1735"),
]
operations = [
migrations.AlterUniqueTogether(
name="workspace",
unique_together=set(),
),
]
@@ -0,0 +1,119 @@
# Generated by Django 3.2.16 on 2023-01-29 19:49
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import plane.db.models.api
import uuid
class Migration(migrations.Migration):
dependencies = [
("db", "0017_alter_workspace_unique_together"),
]
operations = [
migrations.AddField(
model_name="user",
name="is_bot",
field=models.BooleanField(default=False),
),
migrations.AlterField(
model_name="issue",
name="description",
field=models.JSONField(blank=True, null=True),
),
migrations.AlterField(
model_name="issue",
name="description_html",
field=models.TextField(blank=True, null=True),
),
migrations.AlterField(
model_name="issue",
name="description_stripped",
field=models.TextField(blank=True, null=True),
),
migrations.CreateModel(
name="APIToken",
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,
),
),
(
"token",
models.CharField(
default=plane.db.models.api.generate_token,
max_length=255,
unique=True,
),
),
(
"label",
models.CharField(
default=plane.db.models.api.generate_label_token,
max_length=255,
),
),
(
"user_type",
models.PositiveSmallIntegerField(
choices=[(0, "Human"), (1, "Bot")], default=0
),
),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="apitoken_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="apitoken_updated_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Last Modified By",
),
),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="bot_tokens",
to=settings.AUTH_USER_MODEL,
),
),
],
options={
"verbose_name": "API Token",
"verbose_name_plural": "API Tokems",
"db_table": "api_tokens",
"ordering": ("-created_at",),
},
),
]
@@ -0,0 +1,26 @@
# Generated by Django 3.2.16 on 2023-01-30 19:19
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("db", "0018_auto_20230130_0119"),
]
operations = [
migrations.AlterField(
model_name="issueactivity",
name="new_value",
field=models.TextField(
blank=True, null=True, verbose_name="New Value"
),
),
migrations.AlterField(
model_name="issueactivity",
name="old_value",
field=models.TextField(
blank=True, null=True, verbose_name="Old Value"
),
),
]
@@ -0,0 +1,73 @@
# Generated by Django 3.2.16 on 2023-02-13 19:48
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("db", "0019_auto_20230131_0049"),
]
operations = [
migrations.RenameField(
model_name="label",
old_name="colour",
new_name="color",
),
migrations.AddField(
model_name="apitoken",
name="workspace",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="api_tokens",
to="db.workspace",
),
),
migrations.AddField(
model_name="issue",
name="completed_at",
field=models.DateTimeField(null=True),
),
migrations.AddField(
model_name="issue",
name="sort_order",
field=models.FloatField(default=65535),
),
migrations.AddField(
model_name="project",
name="cycle_view",
field=models.BooleanField(default=True),
),
migrations.AddField(
model_name="project",
name="module_view",
field=models.BooleanField(default=True),
),
migrations.AddField(
model_name="state",
name="default",
field=models.BooleanField(default=False),
),
migrations.AlterField(
model_name="issue",
name="description",
field=models.JSONField(blank=True, default=dict),
),
migrations.AlterField(
model_name="issue",
name="description_html",
field=models.TextField(blank=True, default="<p></p>"),
),
migrations.AlterField(
model_name="issuecomment",
name="comment_html",
field=models.TextField(blank=True, default="<p></p>"),
),
migrations.AlterField(
model_name="issuecomment",
name="comment_json",
field=models.JSONField(blank=True, default=dict),
),
]
@@ -0,0 +1,622 @@
# Generated by Django 3.2.16 on 2023-02-22 19:34
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
("db", "0020_auto_20230214_0118"),
]
operations = [
migrations.CreateModel(
name="GithubRepository",
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=500)),
("url", models.URLField(null=True)),
("config", models.JSONField(default=dict)),
("repository_id", models.BigIntegerField()),
("owner", models.CharField(max_length=500)),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="githubrepository_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_githubrepository",
to="db.project",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="githubrepository_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_githubrepository",
to="db.workspace",
),
),
],
options={
"verbose_name": "Repository",
"verbose_name_plural": "Repositories",
"db_table": "github_repositories",
"ordering": ("-created_at",),
},
),
migrations.CreateModel(
name="Integration",
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,
),
),
("title", models.CharField(max_length=400)),
("provider", models.CharField(max_length=400, unique=True)),
(
"network",
models.PositiveIntegerField(
choices=[(1, "Private"), (2, "Public")], default=1
),
),
("description", models.JSONField(default=dict)),
("author", models.CharField(blank=True, max_length=400)),
("webhook_url", models.TextField(blank=True)),
("webhook_secret", models.TextField(blank=True)),
("redirect_url", models.TextField(blank=True)),
("metadata", models.JSONField(default=dict)),
("verified", models.BooleanField(default=False)),
("avatar_url", models.URLField(blank=True, null=True)),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="integration_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="integration_updated_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Last Modified By",
),
),
],
options={
"verbose_name": "Integration",
"verbose_name_plural": "Integrations",
"db_table": "integrations",
"ordering": ("-created_at",),
},
),
migrations.AlterField(
model_name="issueactivity",
name="issue",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="issue_activity",
to="db.issue",
),
),
migrations.CreateModel(
name="WorkspaceIntegration",
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,
),
),
("metadata", models.JSONField(default=dict)),
("config", models.JSONField(default=dict)),
(
"actor",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="integrations",
to=settings.AUTH_USER_MODEL,
),
),
(
"api_token",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="integrations",
to="db.apitoken",
),
),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="workspaceintegration_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"integration",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="integrated_workspaces",
to="db.integration",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="workspaceintegration_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_integrations",
to="db.workspace",
),
),
],
options={
"verbose_name": "Workspace Integration",
"verbose_name_plural": "Workspace Integrations",
"db_table": "workspace_integrations",
"ordering": ("-created_at",),
"unique_together": {("workspace", "integration")},
},
),
migrations.CreateModel(
name="IssueLink",
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,
),
),
("title", models.CharField(max_length=255, null=True)),
("url", models.URLField()),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="issuelink_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"issue",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="issue_link",
to="db.issue",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_issuelink",
to="db.project",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="issuelink_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_issuelink",
to="db.workspace",
),
),
],
options={
"verbose_name": "Issue Link",
"verbose_name_plural": "Issue Links",
"db_table": "issue_links",
"ordering": ("-created_at",),
},
),
migrations.CreateModel(
name="GithubRepositorySync",
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,
),
),
("credentials", models.JSONField(default=dict)),
(
"actor",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="user_syncs",
to=settings.AUTH_USER_MODEL,
),
),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="githubrepositorysync_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"label",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="repo_syncs",
to="db.label",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_githubrepositorysync",
to="db.project",
),
),
(
"repository",
models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE,
related_name="syncs",
to="db.githubrepository",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="githubrepositorysync_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_githubrepositorysync",
to="db.workspace",
),
),
(
"workspace_integration",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="github_syncs",
to="db.workspaceintegration",
),
),
],
options={
"verbose_name": "Github Repository Sync",
"verbose_name_plural": "Github Repository Syncs",
"db_table": "github_repository_syncs",
"ordering": ("-created_at",),
"unique_together": {("project", "repository")},
},
),
migrations.CreateModel(
name="GithubIssueSync",
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,
),
),
("repo_issue_id", models.BigIntegerField()),
("github_issue_id", models.BigIntegerField()),
("issue_url", models.URLField()),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="githubissuesync_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"issue",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="github_syncs",
to="db.issue",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_githubissuesync",
to="db.project",
),
),
(
"repository_sync",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="issue_syncs",
to="db.githubrepositorysync",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="githubissuesync_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_githubissuesync",
to="db.workspace",
),
),
],
options={
"verbose_name": "Github Issue Sync",
"verbose_name_plural": "Github Issue Syncs",
"db_table": "github_issue_syncs",
"ordering": ("-created_at",),
"unique_together": {("repository_sync", "issue")},
},
),
migrations.CreateModel(
name="GithubCommentSync",
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,
),
),
("repo_comment_id", models.BigIntegerField()),
(
"comment",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="comment_syncs",
to="db.issuecomment",
),
),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="githubcommentsync_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"issue_sync",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="comment_syncs",
to="db.githubissuesync",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_githubcommentsync",
to="db.project",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="githubcommentsync_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_githubcommentsync",
to="db.workspace",
),
),
],
options={
"verbose_name": "Github Comment Sync",
"verbose_name_plural": "Github Comment Syncs",
"db_table": "github_comment_syncs",
"ordering": ("-created_at",),
"unique_together": {("issue_sync", "comment")},
},
),
]
@@ -0,0 +1,291 @@
# Generated by Django 3.2.16 on 2023-03-06 21:34
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
("db", "0021_auto_20230223_0104"),
]
operations = [
migrations.RemoveField(
model_name="cycle",
name="status",
),
migrations.RemoveField(
model_name="project",
name="slug",
),
migrations.AddField(
model_name="issuelink",
name="metadata",
field=models.JSONField(default=dict),
),
migrations.AddField(
model_name="modulelink",
name="metadata",
field=models.JSONField(default=dict),
),
migrations.AddField(
model_name="project",
name="cover_image",
field=models.URLField(blank=True, null=True),
),
migrations.CreateModel(
name="ProjectFavorite",
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,
),
),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="projectfavorite_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_projectfavorite",
to="db.project",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="projectfavorite_updated_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Last Modified By",
),
),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_favorites",
to=settings.AUTH_USER_MODEL,
),
),
(
"workspace",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="workspace_projectfavorite",
to="db.workspace",
),
),
],
options={
"verbose_name": "Project Favorite",
"verbose_name_plural": "Project Favorites",
"db_table": "project_favorites",
"ordering": ("-created_at",),
"unique_together": {("project", "user")},
},
),
migrations.CreateModel(
name="ModuleFavorite",
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,
),
),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="modulefavorite_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"module",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="module_favorites",
to="db.module",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_modulefavorite",
to="db.project",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="modulefavorite_updated_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Last Modified By",
),
),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="module_favorites",
to=settings.AUTH_USER_MODEL,
),
),
(
"workspace",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="workspace_modulefavorite",
to="db.workspace",
),
),
],
options={
"verbose_name": "Module Favorite",
"verbose_name_plural": "Module Favorites",
"db_table": "module_favorites",
"ordering": ("-created_at",),
"unique_together": {("module", "user")},
},
),
migrations.CreateModel(
name="CycleFavorite",
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,
),
),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="cyclefavorite_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"cycle",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="cycle_favorites",
to="db.cycle",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_cyclefavorite",
to="db.project",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="cyclefavorite_updated_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Last Modified By",
),
),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="cycle_favorites",
to=settings.AUTH_USER_MODEL,
),
),
(
"workspace",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="workspace_cyclefavorite",
to="db.workspace",
),
),
],
options={
"verbose_name": "Cycle Favorite",
"verbose_name_plural": "Cycle Favorites",
"db_table": "cycle_favorites",
"ordering": ("-created_at",),
"unique_together": {("cycle", "user")},
},
),
]
@@ -0,0 +1,305 @@
# Generated by Django 3.2.16 on 2023-03-15 19:10
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
("db", "0022_auto_20230307_0304"),
]
operations = [
migrations.CreateModel(
name="Importer",
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,
),
),
(
"service",
models.CharField(
choices=[("github", "GitHub")], max_length=50
),
),
(
"status",
models.CharField(
choices=[
("queued", "Queued"),
("processing", "Processing"),
("completed", "Completed"),
("failed", "Failed"),
],
default="queued",
max_length=50,
),
),
("metadata", models.JSONField(default=dict)),
("config", models.JSONField(default=dict)),
("data", models.JSONField(default=dict)),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="importer_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"initiated_by",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="imports",
to=settings.AUTH_USER_MODEL,
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_importer",
to="db.project",
),
),
(
"token",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="importer",
to="db.apitoken",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="importer_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_importer",
to="db.workspace",
),
),
],
options={
"verbose_name": "Importer",
"verbose_name_plural": "Importers",
"db_table": "importers",
"ordering": ("-created_at",),
},
),
migrations.CreateModel(
name="IssueView",
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, verbose_name="View Name"),
),
(
"description",
models.TextField(
blank=True, verbose_name="View Description"
),
),
("query", models.JSONField(verbose_name="View Query")),
(
"access",
models.PositiveSmallIntegerField(
choices=[(0, "Private"), (1, "Public")], default=1
),
),
("query_data", models.JSONField(default=dict)),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="issueview_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_issueview",
to="db.project",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="issueview_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_issueview",
to="db.workspace",
),
),
],
options={
"verbose_name": "Issue View",
"verbose_name_plural": "Issue Views",
"db_table": "issue_views",
"ordering": ("-created_at",),
},
),
migrations.CreateModel(
name="IssueViewFavorite",
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,
),
),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="issueviewfavorite_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_issueviewfavorite",
to="db.project",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="issueviewfavorite_updated_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Last Modified By",
),
),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="user_view_favorites",
to=settings.AUTH_USER_MODEL,
),
),
(
"view",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="view_favorites",
to="db.issueview",
),
),
(
"workspace",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="workspace_issueviewfavorite",
to="db.workspace",
),
),
],
options={
"verbose_name": "View Favorite",
"verbose_name_plural": "View Favorites",
"db_table": "view_favorites",
"ordering": ("-created_at",),
"unique_together": {("view", "user")},
},
),
migrations.AlterUniqueTogether(
name="label",
unique_together={("name", "project")},
),
migrations.DeleteModel(
name="View",
),
]
@@ -0,0 +1,314 @@
# Generated by Django 3.2.16 on 2023-03-21 20:08
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
("db", "0023_auto_20230316_0040"),
]
operations = [
migrations.CreateModel(
name="Page",
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.JSONField(blank=True, default=dict)),
(
"description_html",
models.TextField(blank=True, default="<p></p>"),
),
(
"description_stripped",
models.TextField(blank=True, null=True),
),
(
"access",
models.PositiveSmallIntegerField(
choices=[(0, "Public"), (1, "Private")], default=0
),
),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="page_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"owned_by",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="pages",
to=settings.AUTH_USER_MODEL,
),
),
],
options={
"verbose_name": "Page",
"verbose_name_plural": "Pages",
"db_table": "pages",
"ordering": ("-created_at",),
},
),
migrations.AddField(
model_name="project",
name="issue_views_view",
field=models.BooleanField(default=True),
),
migrations.AlterField(
model_name="importer",
name="service",
field=models.CharField(
choices=[("github", "GitHub"), ("jira", "Jira")], max_length=50
),
),
migrations.AlterField(
model_name="project",
name="cover_image",
field=models.URLField(blank=True, max_length=800, null=True),
),
migrations.CreateModel(
name="PageBlock",
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.JSONField(blank=True, default=dict)),
(
"description_html",
models.TextField(blank=True, default="<p></p>"),
),
(
"description_stripped",
models.TextField(blank=True, null=True),
),
("completed_at", models.DateTimeField(null=True)),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="pageblock_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"issue",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="blocks",
to="db.issue",
),
),
(
"page",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="blocks",
to="db.page",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_pageblock",
to="db.project",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="pageblock_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_pageblock",
to="db.workspace",
),
),
],
options={
"verbose_name": "Page Block",
"verbose_name_plural": "Page Blocks",
"db_table": "page_blocks",
"ordering": ("-created_at",),
},
),
migrations.AddField(
model_name="page",
name="project",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_page",
to="db.project",
),
),
migrations.AddField(
model_name="page",
name="updated_by",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="page_updated_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Last Modified By",
),
),
migrations.AddField(
model_name="page",
name="workspace",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="workspace_page",
to="db.workspace",
),
),
migrations.CreateModel(
name="PageFavorite",
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,
),
),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="pagefavorite_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"page",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="page_favorites",
to="db.page",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_pagefavorite",
to="db.project",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="pagefavorite_updated_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Last Modified By",
),
),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="page_favorites",
to=settings.AUTH_USER_MODEL,
),
),
(
"workspace",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="workspace_pagefavorite",
to="db.workspace",
),
),
],
options={
"verbose_name": "Page Favorite",
"verbose_name_plural": "Page Favorites",
"db_table": "page_favorites",
"ordering": ("-created_at",),
"unique_together": {("page", "user")},
},
),
]
@@ -0,0 +1,131 @@
# Generated by Django 3.2.18 on 2023-03-30 20:33
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
("db", "0024_auto_20230322_0138"),
]
operations = [
migrations.AddField(
model_name="page",
name="color",
field=models.CharField(blank=True, max_length=255),
),
migrations.AddField(
model_name="pageblock",
name="sort_order",
field=models.FloatField(default=65535),
),
migrations.AddField(
model_name="pageblock",
name="sync",
field=models.BooleanField(default=True),
),
migrations.AddField(
model_name="project",
name="page_view",
field=models.BooleanField(default=True),
),
migrations.CreateModel(
name="PageLabel",
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,
),
),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="pagelabel_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"label",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="page_labels",
to="db.label",
),
),
(
"page",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="page_labels",
to="db.page",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_pagelabel",
to="db.project",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="pagelabel_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_pagelabel",
to="db.workspace",
),
),
],
options={
"verbose_name": "Page Label",
"verbose_name_plural": "Page Labels",
"db_table": "page_labels",
"ordering": ("-created_at",),
},
),
migrations.AddField(
model_name="page",
name="labels",
field=models.ManyToManyField(
blank=True,
related_name="pages",
through="db.PageLabel",
to="db.Label",
),
),
]
@@ -0,0 +1,20 @@
# Generated by Django 3.2.18 on 2023-04-04 21:50
from django.db import migrations, models
import plane.db.models.project
class Migration(migrations.Migration):
dependencies = [
("db", "0025_auto_20230331_0203"),
]
operations = [
migrations.AlterField(
model_name="projectmember",
name="view_props",
field=models.JSONField(
default=plane.db.models.project.get_default_props
),
),
]
@@ -0,0 +1,297 @@
# Generated by Django 3.2.18 on 2023-04-08 21:42
from django.conf import settings
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
import plane.db.models.issue
import uuid
class Migration(migrations.Migration):
dependencies = [
("db", "0026_alter_projectmember_view_props"),
]
operations = [
migrations.CreateModel(
name="Estimate",
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, verbose_name="Estimate Description"
),
),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="estimate_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_estimate",
to="db.project",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="estimate_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_estimate",
to="db.workspace",
),
),
],
options={
"verbose_name": "Estimate",
"verbose_name_plural": "Estimates",
"db_table": "estimates",
"ordering": ("name",),
"unique_together": {("name", "project")},
},
),
migrations.RemoveField(
model_name="issue",
name="attachments",
),
migrations.AddField(
model_name="issue",
name="estimate_point",
field=models.IntegerField(
default=0,
validators=[
django.core.validators.MinValueValidator(0),
django.core.validators.MaxValueValidator(7),
],
),
),
migrations.CreateModel(
name="IssueAttachment",
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,
),
),
("attributes", models.JSONField(default=dict)),
(
"asset",
models.FileField(
upload_to=plane.db.models.issue.get_upload_path,
validators=[plane.db.models.issue.file_size],
),
),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="issueattachment_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"issue",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="issue_attachment",
to="db.issue",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_issueattachment",
to="db.project",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="issueattachment_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_issueattachment",
to="db.workspace",
),
),
],
options={
"verbose_name": "Issue Attachment",
"verbose_name_plural": "Issue Attachments",
"db_table": "issue_attachments",
"ordering": ("-created_at",),
},
),
migrations.AddField(
model_name="project",
name="estimate",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="projects",
to="db.estimate",
),
),
migrations.CreateModel(
name="EstimatePoint",
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,
),
),
(
"key",
models.IntegerField(
default=0,
validators=[
django.core.validators.MinValueValidator(0),
django.core.validators.MaxValueValidator(7),
],
),
),
("description", models.TextField(blank=True)),
("value", models.CharField(max_length=20)),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="estimatepoint_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"estimate",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="points",
to="db.estimate",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_estimatepoint",
to="db.project",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="estimatepoint_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_estimatepoint",
to="db.workspace",
),
),
],
options={
"verbose_name": "Estimate Point",
"verbose_name_plural": "Estimate Points",
"db_table": "estimate_points",
"ordering": ("value",),
"unique_together": {("value", "estimate")},
},
),
]
@@ -0,0 +1,106 @@
# Generated by Django 3.2.18 on 2023-04-14 11:33
from django.conf import settings
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
("db", "0027_auto_20230409_0312"),
]
operations = [
migrations.AddField(
model_name="user",
name="theme",
field=models.JSONField(default=dict),
),
migrations.AlterField(
model_name="issue",
name="estimate_point",
field=models.IntegerField(
blank=True,
null=True,
validators=[
django.core.validators.MinValueValidator(0),
django.core.validators.MaxValueValidator(7),
],
),
),
migrations.CreateModel(
name="WorkspaceTheme",
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=300)),
("colors", models.JSONField(default=dict)),
(
"actor",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="themes",
to=settings.AUTH_USER_MODEL,
),
),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="workspacetheme_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="workspacetheme_updated_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Last Modified By",
),
),
(
"workspace",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="themes",
to="db.workspace",
),
),
],
options={
"verbose_name": "Workspace Theme",
"verbose_name_plural": "Workspace Themes",
"db_table": "workspace_themes",
"ordering": ("-created_at",),
"unique_together": {("workspace", "name")},
},
),
]
@@ -0,0 +1,116 @@
# Generated by Django 3.2.18 on 2023-05-01 19:56
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
("db", "0028_auto_20230414_1703"),
]
operations = [
migrations.AddField(
model_name="cycle",
name="view_props",
field=models.JSONField(default=dict),
),
migrations.AddField(
model_name="importer",
name="imported_data",
field=models.JSONField(null=True),
),
migrations.AddField(
model_name="module",
name="view_props",
field=models.JSONField(default=dict),
),
migrations.CreateModel(
name="SlackProjectSync",
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,
),
),
("access_token", models.CharField(max_length=300)),
("scopes", models.TextField()),
("bot_user_id", models.CharField(max_length=50)),
("webhook_url", models.URLField(max_length=1000)),
("data", models.JSONField(default=dict)),
("team_id", models.CharField(max_length=30)),
("team_name", models.CharField(max_length=300)),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="slackprojectsync_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_slackprojectsync",
to="db.project",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="slackprojectsync_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_slackprojectsync",
to="db.workspace",
),
),
(
"workspace_integration",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="slack_syncs",
to="db.workspaceintegration",
),
),
],
options={
"verbose_name": "Slack Project Sync",
"verbose_name_plural": "Slack Project Syncs",
"db_table": "slack_project_syncs",
"ordering": ("-created_at",),
"unique_together": {("team_id", "project")},
},
),
]
@@ -0,0 +1,16 @@
# Generated by Django 3.2.18 on 2023-05-05 14:17
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("db", "0029_auto_20230502_0126"),
]
operations = [
migrations.AlterUniqueTogether(
name="estimatepoint",
unique_together=set(),
),
]
@@ -0,0 +1,81 @@
# Generated by Django 3.2.18 on 2023-05-12 11:31
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
("db", "0030_alter_estimatepoint_unique_together"),
]
operations = [
migrations.CreateModel(
name="AnalyticView",
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)),
("query", models.JSONField()),
("query_dict", models.JSONField(default=dict)),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="analyticview_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="analyticview_updated_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Last Modified By",
),
),
(
"workspace",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="analytics",
to="db.workspace",
),
),
],
options={
"verbose_name": "Analytic",
"verbose_name_plural": "Analytics",
"db_table": "analytic_views",
"ordering": ("-created_at",),
},
),
]
@@ -0,0 +1,22 @@
# Generated by Django 3.2.19 on 2023-05-20 14:45
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("db", "0031_analyticview"),
]
operations = [
migrations.RenameField(
model_name="project",
old_name="icon",
new_name="emoji",
),
migrations.AddField(
model_name="project",
name="icon_prop",
field=models.JSONField(null=True),
),
]
@@ -0,0 +1,216 @@
# Generated by Django 3.2.19 on 2023-06-18 15:55
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
("db", "0032_auto_20230520_2015"),
]
operations = [
migrations.CreateModel(
name="Inbox",
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, verbose_name="Inbox Description"
),
),
("is_default", models.BooleanField(default=False)),
("view_props", models.JSONField(default=dict)),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="inbox_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
],
options={
"verbose_name": "Inbox",
"verbose_name_plural": "Inboxes",
"db_table": "inboxes",
"ordering": ("name",),
},
),
migrations.AddField(
model_name="project",
name="inbox_view",
field=models.BooleanField(default=False),
),
migrations.CreateModel(
name="InboxIssue",
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,
),
),
(
"status",
models.IntegerField(
choices=[
(-2, "Pending"),
(-1, "Rejected"),
(0, "Snoozed"),
(1, "Accepted"),
(2, "Duplicate"),
],
default=-2,
),
),
("snoozed_till", models.DateTimeField(null=True)),
("source", models.TextField(blank=True, null=True)),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="inboxissue_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"duplicate_to",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="inbox_duplicate",
to="db.issue",
),
),
(
"inbox",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="issue_inbox",
to="db.inbox",
),
),
(
"issue",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="issue_inbox",
to="db.issue",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_inboxissue",
to="db.project",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="inboxissue_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_inboxissue",
to="db.workspace",
),
),
],
options={
"verbose_name": "InboxIssue",
"verbose_name_plural": "InboxIssues",
"db_table": "inbox_issues",
"ordering": ("-created_at",),
},
),
migrations.AddField(
model_name="inbox",
name="project",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_inbox",
to="db.project",
),
),
migrations.AddField(
model_name="inbox",
name="updated_by",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="inbox_updated_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Last Modified By",
),
),
migrations.AddField(
model_name="inbox",
name="workspace",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="workspace_inbox",
to="db.workspace",
),
),
migrations.AlterUniqueTogether(
name="inbox",
unique_together={("name", "project")},
),
]
@@ -0,0 +1,38 @@
# Generated by Django 3.2.19 on 2023-06-28 05:16
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("db", "0033_auto_20230618_2125"),
]
operations = [
migrations.RemoveField(
model_name="timelineissue",
name="created_by",
),
migrations.RemoveField(
model_name="timelineissue",
name="issue",
),
migrations.RemoveField(
model_name="timelineissue",
name="project",
),
migrations.RemoveField(
model_name="timelineissue",
name="updated_by",
),
migrations.RemoveField(
model_name="timelineissue",
name="workspace",
),
migrations.DeleteModel(
name="Shortcut",
),
migrations.DeleteModel(
name="TimelineIssue",
),
]
@@ -0,0 +1,46 @@
# Generated by Django 3.2.19 on 2023-07-04 16:55
from django.db import migrations, models
def update_company_organization_size(apps, schema_editor):
Model = apps.get_model("db", "Workspace")
updated_size = []
for obj in Model.objects.all():
obj.organization_size = str(obj.company_size)
updated_size.append(obj)
Model.objects.bulk_update(
updated_size, ["organization_size"], batch_size=100
)
class Migration(migrations.Migration):
dependencies = [
("db", "0034_auto_20230628_1046"),
]
operations = [
migrations.AddField(
model_name="workspace",
name="organization_size",
field=models.CharField(default="2-10", max_length=20),
),
migrations.RunPython(update_company_organization_size),
migrations.AlterField(
model_name="workspace",
name="name",
field=models.CharField(
max_length=80, verbose_name="Workspace Name"
),
),
migrations.AlterField(
model_name="workspace",
name="slug",
field=models.SlugField(max_length=48, unique=True),
),
migrations.RemoveField(
model_name="workspace",
name="company_size",
),
]
@@ -0,0 +1,17 @@
# Generated by Django 3.2.19 on 2023-07-05 07:59
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("db", "0035_auto_20230704_2225"),
]
operations = [
migrations.AlterField(
model_name="workspace",
name="organization_size",
field=models.CharField(max_length=20),
),
]
@@ -0,0 +1,276 @@
# Generated by Django 4.2.3 on 2023-07-19 06:52
from django.conf import settings
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
import plane.db.models.user
import uuid
def onboarding_default_steps(apps, schema_editor):
default_onboarding_schema = {
"workspace_join": True,
"profile_complete": True,
"workspace_create": True,
"workspace_invite": True,
}
Model = apps.get_model("db", "User")
updated_user = []
for obj in Model.objects.filter(is_onboarded=True):
obj.onboarding_step = default_onboarding_schema
obj.is_tour_completed = True
updated_user.append(obj)
Model.objects.bulk_update(
updated_user, ["onboarding_step", "is_tour_completed"], batch_size=100
)
class Migration(migrations.Migration):
dependencies = [
("db", "0036_alter_workspace_organization_size"),
]
operations = [
migrations.AddField(
model_name="issue",
name="archived_at",
field=models.DateField(null=True),
),
migrations.AddField(
model_name="project",
name="archive_in",
field=models.IntegerField(
default=0,
validators=[
django.core.validators.MinValueValidator(0),
django.core.validators.MaxValueValidator(12),
],
),
),
migrations.AddField(
model_name="project",
name="close_in",
field=models.IntegerField(
default=0,
validators=[
django.core.validators.MinValueValidator(0),
django.core.validators.MaxValueValidator(12),
],
),
),
migrations.AddField(
model_name="project",
name="default_state",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="default_state",
to="db.state",
),
),
migrations.AddField(
model_name="user",
name="is_tour_completed",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="user",
name="onboarding_step",
field=models.JSONField(
default=plane.db.models.user.get_default_onboarding
),
),
migrations.RunPython(onboarding_default_steps),
migrations.CreateModel(
name="Notification",
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,
),
),
("data", models.JSONField(null=True)),
("entity_identifier", models.UUIDField(null=True)),
("entity_name", models.CharField(max_length=255)),
("title", models.TextField()),
("message", models.JSONField(null=True)),
(
"message_html",
models.TextField(blank=True, default="<p></p>"),
),
("message_stripped", models.TextField(blank=True, null=True)),
("sender", models.CharField(max_length=255)),
("read_at", models.DateTimeField(null=True)),
("snoozed_till", models.DateTimeField(null=True)),
("archived_at", models.DateTimeField(null=True)),
(
"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="notifications",
to="db.project",
),
),
(
"receiver",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="received_notifications",
to=settings.AUTH_USER_MODEL,
),
),
(
"triggered_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="triggered_notifications",
to=settings.AUTH_USER_MODEL,
),
),
(
"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="notifications",
to="db.workspace",
),
),
],
options={
"verbose_name": "Notification",
"verbose_name_plural": "Notifications",
"db_table": "notifications",
"ordering": ("-created_at",),
},
),
migrations.CreateModel(
name="IssueSubscriber",
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,
),
),
(
"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",
),
),
(
"issue",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="issue_subscribers",
to="db.issue",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_%(class)s",
to="db.project",
),
),
(
"subscriber",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="issue_subscribers",
to=settings.AUTH_USER_MODEL,
),
),
(
"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 Subscriber",
"verbose_name_plural": "Issue Subscribers",
"db_table": "issue_subscribers",
"ordering": ("-created_at",),
"unique_together": {("issue", "subscriber")},
},
),
]
@@ -0,0 +1,31 @@
# Generated by Django 4.2.3 on 2023-07-20 09:35
from django.db import migrations
def restructure_theming(apps, schema_editor):
Model = apps.get_model("db", "User")
updated_user = []
for obj in Model.objects.exclude(theme={}).all():
current_theme = obj.theme
updated_theme = {
"primary": current_theme.get("accent", ""),
"background": current_theme.get("bgBase", ""),
"sidebarBackground": current_theme.get("sidebar", ""),
"text": current_theme.get("textBase", ""),
"sidebarText": current_theme.get("textBase", ""),
"palette": f"""{current_theme.get("bgBase","")},{current_theme.get("textBase", "")},{current_theme.get("accent", "")},{current_theme.get("sidebar","")},{current_theme.get("textBase", "")}""",
"darkPalette": current_theme.get("darkPalette", ""),
}
obj.theme = updated_theme
updated_user.append(obj)
Model.objects.bulk_update(updated_user, ["theme"], batch_size=100)
class Migration(migrations.Migration):
dependencies = [
("db", "0037_issue_archived_at_project_archive_in_and_more"),
]
operations = [migrations.RunPython(restructure_theming)]
@@ -0,0 +1,105 @@
# Generated by Django 4.2.3 on 2023-07-23 16:33
import random
from django.db import migrations, models
import plane.db.models.workspace
def rename_field(apps, schema_editor):
Model = apps.get_model("db", "IssueActivity")
updated_activity = []
for obj in Model.objects.filter(field="assignee"):
obj.field = "assignees"
updated_activity.append(obj)
Model.objects.bulk_update(updated_activity, ["field"], batch_size=100)
def update_workspace_member_props(apps, schema_editor):
Model = apps.get_model("db", "WorkspaceMember")
updated_workspace_member = []
for obj in Model.objects.all():
if obj.view_props is None:
obj.view_props = {
"filters": {"type": None},
"groupByProperty": None,
"issueView": "list",
"orderBy": "-created_at",
"properties": {
"assignee": True,
"due_date": True,
"key": True,
"labels": True,
"priority": True,
"state": True,
"sub_issue_count": True,
"attachment_count": True,
"link": True,
"estimate": True,
"created_on": True,
"updated_on": True,
},
"showEmptyGroups": True,
}
else:
current_view_props = obj.view_props
obj.view_props = {
"filters": {"type": None},
"groupByProperty": None,
"issueView": "list",
"orderBy": "-created_at",
"showEmptyGroups": True,
"properties": current_view_props,
}
updated_workspace_member.append(obj)
Model.objects.bulk_update(
updated_workspace_member, ["view_props"], batch_size=100
)
def update_project_member_sort_order(apps, schema_editor):
Model = apps.get_model("db", "ProjectMember")
updated_project_members = []
for obj in Model.objects.all():
obj.sort_order = random.randint(1, 65536)
updated_project_members.append(obj)
Model.objects.bulk_update(
updated_project_members, ["sort_order"], batch_size=100
)
class Migration(migrations.Migration):
dependencies = [
("db", "0038_auto_20230720_1505"),
]
operations = [
migrations.RunPython(rename_field),
migrations.RunPython(update_workspace_member_props),
migrations.AlterField(
model_name="workspacemember",
name="view_props",
field=models.JSONField(
default=plane.db.models.workspace.get_default_props
),
),
migrations.AddField(
model_name="workspacemember",
name="default_props",
field=models.JSONField(
default=plane.db.models.workspace.get_default_props
),
),
migrations.AddField(
model_name="projectmember",
name="sort_order",
field=models.FloatField(default=65535),
),
migrations.RunPython(update_project_member_sort_order),
]
@@ -0,0 +1,216 @@
# Generated by Django 4.2.3 on 2023-08-01 06:02
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import plane.db.models.project
import uuid
class Migration(migrations.Migration):
dependencies = [
("db", "0039_auto_20230723_2203"),
]
operations = [
migrations.AddField(
model_name="projectmember",
name="preferences",
field=models.JSONField(
default=plane.db.models.project.get_default_preferences
),
),
migrations.AddField(
model_name="user",
name="cover_image",
field=models.URLField(blank=True, max_length=800, null=True),
),
migrations.CreateModel(
name="IssueReaction",
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,
),
),
("reaction", models.CharField(max_length=20)),
(
"actor",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="issue_reactions",
to=settings.AUTH_USER_MODEL,
),
),
(
"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",
),
),
(
"issue",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="issue_reactions",
to="db.issue",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_%(class)s",
to="db.project",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="%(class)s_updated_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Last Modified By",
),
),
(
"workspace",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="workspace_%(class)s",
to="db.workspace",
),
),
],
options={
"verbose_name": "Issue Reaction",
"verbose_name_plural": "Issue Reactions",
"db_table": "issue_reactions",
"ordering": ("-created_at",),
"unique_together": {("issue", "actor", "reaction")},
},
),
migrations.CreateModel(
name="CommentReaction",
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,
),
),
("reaction", models.CharField(max_length=20)),
(
"actor",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="comment_reactions",
to=settings.AUTH_USER_MODEL,
),
),
(
"comment",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="comment_reactions",
to="db.issuecomment",
),
),
(
"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(
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": "Comment Reaction",
"verbose_name_plural": "Comment Reactions",
"db_table": "comment_reactions",
"ordering": ("-created_at",),
"unique_together": {("comment", "actor", "reaction")},
},
),
migrations.AlterField(
model_name="project",
name="identifier",
field=models.CharField(
max_length=12, verbose_name="Project Identifier"
),
),
migrations.AlterField(
model_name="projectidentifier",
name="name",
field=models.CharField(max_length=12),
),
]
@@ -0,0 +1,498 @@
# Generated by Django 4.2.3 on 2023-08-14 07:12
from django.conf import settings
import django.contrib.postgres.fields
from django.db import migrations, models
import django.db.models.deletion
import plane.db.models.exporter
import plane.db.models.project
import uuid
import random
import string
def generate_display_name(apps, schema_editor):
UserModel = apps.get_model("db", "User")
updated_users = []
for obj in UserModel.objects.all():
obj.display_name = (
obj.email.split("@")[0]
if len(obj.email.split("@"))
else "".join(random.choice(string.ascii_letters) for _ in range(6))
)
updated_users.append(obj)
UserModel.objects.bulk_update(
updated_users, ["display_name"], batch_size=100
)
def rectify_field_issue_activity(apps, schema_editor):
Model = apps.get_model("db", "IssueActivity")
updated_activity = []
for obj in Model.objects.filter(field="assignee"):
obj.field = "assignees"
updated_activity.append(obj)
Model.objects.bulk_update(updated_activity, ["field"], batch_size=100)
def update_assignee_issue_activity(apps, schema_editor):
Model = apps.get_model("db", "IssueActivity")
updated_activity = []
# Get all the users
User = apps.get_model("db", "User")
users = User.objects.values("id", "email", "display_name")
for obj in Model.objects.filter(field="assignees"):
if bool(obj.new_value) and not bool(obj.old_value):
# Get user from list
assigned_user = [
user for user in users if user.get("email") == obj.new_value
]
if assigned_user:
obj.new_value = assigned_user[0].get("display_name")
obj.new_identifier = assigned_user[0].get("id")
# Update the comment
words = obj.comment.split()
words[-1] = assigned_user[0].get("display_name")
obj.comment = " ".join(words)
if bool(obj.old_value) and not bool(obj.new_value):
# Get user from list
assigned_user = [
user for user in users if user.get("email") == obj.old_value
]
if assigned_user:
obj.old_value = assigned_user[0].get("display_name")
obj.old_identifier = assigned_user[0].get("id")
# Update the comment
words = obj.comment.split()
words[-1] = assigned_user[0].get("display_name")
obj.comment = " ".join(words)
updated_activity.append(obj)
Model.objects.bulk_update(
updated_activity,
[
"old_value",
"new_value",
"old_identifier",
"new_identifier",
"comment",
],
batch_size=200,
)
def update_name_activity(apps, schema_editor):
Model = apps.get_model("db", "IssueActivity")
update_activity = []
for obj in Model.objects.filter(field="name"):
obj.comment = obj.comment.replace("start date", "name")
update_activity.append(obj)
Model.objects.bulk_update(update_activity, ["comment"], batch_size=1000)
def random_cycle_order(apps, schema_editor):
CycleModel = apps.get_model("db", "Cycle")
updated_cycles = []
for obj in CycleModel.objects.all():
obj.sort_order = random.randint(1, 65536)
updated_cycles.append(obj)
CycleModel.objects.bulk_update(
updated_cycles, ["sort_order"], batch_size=100
)
def random_module_order(apps, schema_editor):
ModuleModel = apps.get_model("db", "Module")
updated_modules = []
for obj in ModuleModel.objects.all():
obj.sort_order = random.randint(1, 65536)
updated_modules.append(obj)
ModuleModel.objects.bulk_update(
updated_modules, ["sort_order"], batch_size=100
)
def update_user_issue_properties(apps, schema_editor):
IssuePropertyModel = apps.get_model("db", "IssueProperty")
updated_issue_properties = []
for obj in IssuePropertyModel.objects.all():
obj.properties["start_date"] = True
updated_issue_properties.append(obj)
IssuePropertyModel.objects.bulk_update(
updated_issue_properties, ["properties"], batch_size=100
)
def workspace_member_properties(apps, schema_editor):
WorkspaceMemberModel = apps.get_model("db", "WorkspaceMember")
updated_workspace_members = []
for obj in WorkspaceMemberModel.objects.all():
obj.view_props["properties"]["start_date"] = True
obj.default_props["properties"]["start_date"] = True
updated_workspace_members.append(obj)
WorkspaceMemberModel.objects.bulk_update(
updated_workspace_members,
["view_props", "default_props"],
batch_size=100,
)
class Migration(migrations.Migration):
dependencies = [
("db", "0040_projectmember_preferences_user_cover_image_and_more"),
]
operations = [
migrations.AddField(
model_name="cycle",
name="sort_order",
field=models.FloatField(default=65535),
),
migrations.AddField(
model_name="issuecomment",
name="access",
field=models.CharField(
choices=[("INTERNAL", "INTERNAL"), ("EXTERNAL", "EXTERNAL")],
default="INTERNAL",
max_length=100,
),
),
migrations.AddField(
model_name="module",
name="sort_order",
field=models.FloatField(default=65535),
),
migrations.AddField(
model_name="user",
name="display_name",
field=models.CharField(default="", max_length=255),
),
migrations.CreateModel(
name="ExporterHistory",
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,
),
),
(
"project",
django.contrib.postgres.fields.ArrayField(
base_field=models.UUIDField(default=uuid.uuid4),
blank=True,
null=True,
size=None,
),
),
(
"provider",
models.CharField(
choices=[
("json", "json"),
("csv", "csv"),
("xlsx", "xlsx"),
],
max_length=50,
),
),
(
"status",
models.CharField(
choices=[
("queued", "Queued"),
("processing", "Processing"),
("completed", "Completed"),
("failed", "Failed"),
],
default="queued",
max_length=50,
),
),
("reason", models.TextField(blank=True)),
("key", models.TextField(blank=True)),
(
"url",
models.URLField(blank=True, max_length=800, null=True),
),
(
"token",
models.CharField(
default=plane.db.models.exporter.generate_token,
max_length=255,
unique=True,
),
),
(
"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",
),
),
(
"initiated_by",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="workspace_exporters",
to=settings.AUTH_USER_MODEL,
),
),
(
"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_exporters",
to="db.workspace",
),
),
],
options={
"verbose_name": "Exporter",
"verbose_name_plural": "Exporters",
"db_table": "exporters",
"ordering": ("-created_at",),
},
),
migrations.CreateModel(
name="ProjectDeployBoard",
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,
),
),
(
"anchor",
models.CharField(
db_index=True,
default=plane.db.models.project.get_anchor,
max_length=255,
unique=True,
),
),
("comments", models.BooleanField(default=False)),
("reactions", models.BooleanField(default=False)),
("votes", models.BooleanField(default=False)),
(
"views",
models.JSONField(
default=plane.db.models.project.get_default_views
),
),
(
"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",
),
),
(
"inbox",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="bord_inbox",
to="db.inbox",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_%(class)s",
to="db.project",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="%(class)s_updated_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Last Modified By",
),
),
(
"workspace",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="workspace_%(class)s",
to="db.workspace",
),
),
],
options={
"verbose_name": "Project Deploy Board",
"verbose_name_plural": "Project Deploy Boards",
"db_table": "project_deploy_boards",
"ordering": ("-created_at",),
"unique_together": {("project", "anchor")},
},
),
migrations.CreateModel(
name="IssueVote",
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,
),
),
(
"vote",
models.IntegerField(
choices=[(-1, "DOWNVOTE"), (1, "UPVOTE")]
),
),
(
"actor",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="votes",
to=settings.AUTH_USER_MODEL,
),
),
(
"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",
),
),
(
"issue",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="votes",
to="db.issue",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_%(class)s",
to="db.project",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="%(class)s_updated_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Last Modified By",
),
),
(
"workspace",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="workspace_%(class)s",
to="db.workspace",
),
),
],
options={
"verbose_name": "Issue Vote",
"verbose_name_plural": "Issue Votes",
"db_table": "issue_votes",
"ordering": ("-created_at",),
"unique_together": {("issue", "actor")},
},
),
migrations.AlterField(
model_name="modulelink",
name="title",
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.RunPython(generate_display_name),
migrations.RunPython(rectify_field_issue_activity),
migrations.RunPython(update_assignee_issue_activity),
migrations.RunPython(update_name_activity),
migrations.RunPython(random_cycle_order),
migrations.RunPython(random_module_order),
migrations.RunPython(update_user_issue_properties),
migrations.RunPython(workspace_member_properties),
]
@@ -0,0 +1,766 @@
# Generated by Django 4.2.3 on 2023-08-29 06:26
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import uuid
def update_user_timezones(apps, schema_editor):
UserModel = apps.get_model("db", "User")
updated_users = []
for obj in UserModel.objects.all():
obj.user_timezone = "UTC"
updated_users.append(obj)
UserModel.objects.bulk_update(
updated_users, ["user_timezone"], batch_size=100
)
class Migration(migrations.Migration):
dependencies = [
("db", "0041_cycle_sort_order_issuecomment_access_and_more"),
]
operations = [
migrations.AlterField(
model_name="user",
name="user_timezone",
field=models.CharField(
choices=[
("Africa/Abidjan", "Africa/Abidjan"),
("Africa/Accra", "Africa/Accra"),
("Africa/Addis_Ababa", "Africa/Addis_Ababa"),
("Africa/Algiers", "Africa/Algiers"),
("Africa/Asmara", "Africa/Asmara"),
("Africa/Asmera", "Africa/Asmera"),
("Africa/Bamako", "Africa/Bamako"),
("Africa/Bangui", "Africa/Bangui"),
("Africa/Banjul", "Africa/Banjul"),
("Africa/Bissau", "Africa/Bissau"),
("Africa/Blantyre", "Africa/Blantyre"),
("Africa/Brazzaville", "Africa/Brazzaville"),
("Africa/Bujumbura", "Africa/Bujumbura"),
("Africa/Cairo", "Africa/Cairo"),
("Africa/Casablanca", "Africa/Casablanca"),
("Africa/Ceuta", "Africa/Ceuta"),
("Africa/Conakry", "Africa/Conakry"),
("Africa/Dakar", "Africa/Dakar"),
("Africa/Dar_es_Salaam", "Africa/Dar_es_Salaam"),
("Africa/Djibouti", "Africa/Djibouti"),
("Africa/Douala", "Africa/Douala"),
("Africa/El_Aaiun", "Africa/El_Aaiun"),
("Africa/Freetown", "Africa/Freetown"),
("Africa/Gaborone", "Africa/Gaborone"),
("Africa/Harare", "Africa/Harare"),
("Africa/Johannesburg", "Africa/Johannesburg"),
("Africa/Juba", "Africa/Juba"),
("Africa/Kampala", "Africa/Kampala"),
("Africa/Khartoum", "Africa/Khartoum"),
("Africa/Kigali", "Africa/Kigali"),
("Africa/Kinshasa", "Africa/Kinshasa"),
("Africa/Lagos", "Africa/Lagos"),
("Africa/Libreville", "Africa/Libreville"),
("Africa/Lome", "Africa/Lome"),
("Africa/Luanda", "Africa/Luanda"),
("Africa/Lubumbashi", "Africa/Lubumbashi"),
("Africa/Lusaka", "Africa/Lusaka"),
("Africa/Malabo", "Africa/Malabo"),
("Africa/Maputo", "Africa/Maputo"),
("Africa/Maseru", "Africa/Maseru"),
("Africa/Mbabane", "Africa/Mbabane"),
("Africa/Mogadishu", "Africa/Mogadishu"),
("Africa/Monrovia", "Africa/Monrovia"),
("Africa/Nairobi", "Africa/Nairobi"),
("Africa/Ndjamena", "Africa/Ndjamena"),
("Africa/Niamey", "Africa/Niamey"),
("Africa/Nouakchott", "Africa/Nouakchott"),
("Africa/Ouagadougou", "Africa/Ouagadougou"),
("Africa/Porto-Novo", "Africa/Porto-Novo"),
("Africa/Sao_Tome", "Africa/Sao_Tome"),
("Africa/Timbuktu", "Africa/Timbuktu"),
("Africa/Tripoli", "Africa/Tripoli"),
("Africa/Tunis", "Africa/Tunis"),
("Africa/Windhoek", "Africa/Windhoek"),
("America/Adak", "America/Adak"),
("America/Anchorage", "America/Anchorage"),
("America/Anguilla", "America/Anguilla"),
("America/Antigua", "America/Antigua"),
("America/Araguaina", "America/Araguaina"),
(
"America/Argentina/Buenos_Aires",
"America/Argentina/Buenos_Aires",
),
(
"America/Argentina/Catamarca",
"America/Argentina/Catamarca",
),
(
"America/Argentina/ComodRivadavia",
"America/Argentina/ComodRivadavia",
),
("America/Argentina/Cordoba", "America/Argentina/Cordoba"),
("America/Argentina/Jujuy", "America/Argentina/Jujuy"),
(
"America/Argentina/La_Rioja",
"America/Argentina/La_Rioja",
),
("America/Argentina/Mendoza", "America/Argentina/Mendoza"),
(
"America/Argentina/Rio_Gallegos",
"America/Argentina/Rio_Gallegos",
),
("America/Argentina/Salta", "America/Argentina/Salta"),
(
"America/Argentina/San_Juan",
"America/Argentina/San_Juan",
),
(
"America/Argentina/San_Luis",
"America/Argentina/San_Luis",
),
("America/Argentina/Tucuman", "America/Argentina/Tucuman"),
("America/Argentina/Ushuaia", "America/Argentina/Ushuaia"),
("America/Aruba", "America/Aruba"),
("America/Asuncion", "America/Asuncion"),
("America/Atikokan", "America/Atikokan"),
("America/Atka", "America/Atka"),
("America/Bahia", "America/Bahia"),
("America/Bahia_Banderas", "America/Bahia_Banderas"),
("America/Barbados", "America/Barbados"),
("America/Belem", "America/Belem"),
("America/Belize", "America/Belize"),
("America/Blanc-Sablon", "America/Blanc-Sablon"),
("America/Boa_Vista", "America/Boa_Vista"),
("America/Bogota", "America/Bogota"),
("America/Boise", "America/Boise"),
("America/Buenos_Aires", "America/Buenos_Aires"),
("America/Cambridge_Bay", "America/Cambridge_Bay"),
("America/Campo_Grande", "America/Campo_Grande"),
("America/Cancun", "America/Cancun"),
("America/Caracas", "America/Caracas"),
("America/Catamarca", "America/Catamarca"),
("America/Cayenne", "America/Cayenne"),
("America/Cayman", "America/Cayman"),
("America/Chicago", "America/Chicago"),
("America/Chihuahua", "America/Chihuahua"),
("America/Ciudad_Juarez", "America/Ciudad_Juarez"),
("America/Coral_Harbour", "America/Coral_Harbour"),
("America/Cordoba", "America/Cordoba"),
("America/Costa_Rica", "America/Costa_Rica"),
("America/Creston", "America/Creston"),
("America/Cuiaba", "America/Cuiaba"),
("America/Curacao", "America/Curacao"),
("America/Danmarkshavn", "America/Danmarkshavn"),
("America/Dawson", "America/Dawson"),
("America/Dawson_Creek", "America/Dawson_Creek"),
("America/Denver", "America/Denver"),
("America/Detroit", "America/Detroit"),
("America/Dominica", "America/Dominica"),
("America/Edmonton", "America/Edmonton"),
("America/Eirunepe", "America/Eirunepe"),
("America/El_Salvador", "America/El_Salvador"),
("America/Ensenada", "America/Ensenada"),
("America/Fort_Nelson", "America/Fort_Nelson"),
("America/Fort_Wayne", "America/Fort_Wayne"),
("America/Fortaleza", "America/Fortaleza"),
("America/Glace_Bay", "America/Glace_Bay"),
("America/Godthab", "America/Godthab"),
("America/Goose_Bay", "America/Goose_Bay"),
("America/Grand_Turk", "America/Grand_Turk"),
("America/Grenada", "America/Grenada"),
("America/Guadeloupe", "America/Guadeloupe"),
("America/Guatemala", "America/Guatemala"),
("America/Guayaquil", "America/Guayaquil"),
("America/Guyana", "America/Guyana"),
("America/Halifax", "America/Halifax"),
("America/Havana", "America/Havana"),
("America/Hermosillo", "America/Hermosillo"),
(
"America/Indiana/Indianapolis",
"America/Indiana/Indianapolis",
),
("America/Indiana/Knox", "America/Indiana/Knox"),
("America/Indiana/Marengo", "America/Indiana/Marengo"),
(
"America/Indiana/Petersburg",
"America/Indiana/Petersburg",
),
("America/Indiana/Tell_City", "America/Indiana/Tell_City"),
("America/Indiana/Vevay", "America/Indiana/Vevay"),
("America/Indiana/Vincennes", "America/Indiana/Vincennes"),
("America/Indiana/Winamac", "America/Indiana/Winamac"),
("America/Indianapolis", "America/Indianapolis"),
("America/Inuvik", "America/Inuvik"),
("America/Iqaluit", "America/Iqaluit"),
("America/Jamaica", "America/Jamaica"),
("America/Jujuy", "America/Jujuy"),
("America/Juneau", "America/Juneau"),
(
"America/Kentucky/Louisville",
"America/Kentucky/Louisville",
),
(
"America/Kentucky/Monticello",
"America/Kentucky/Monticello",
),
("America/Knox_IN", "America/Knox_IN"),
("America/Kralendijk", "America/Kralendijk"),
("America/La_Paz", "America/La_Paz"),
("America/Lima", "America/Lima"),
("America/Los_Angeles", "America/Los_Angeles"),
("America/Louisville", "America/Louisville"),
("America/Lower_Princes", "America/Lower_Princes"),
("America/Maceio", "America/Maceio"),
("America/Managua", "America/Managua"),
("America/Manaus", "America/Manaus"),
("America/Marigot", "America/Marigot"),
("America/Martinique", "America/Martinique"),
("America/Matamoros", "America/Matamoros"),
("America/Mazatlan", "America/Mazatlan"),
("America/Mendoza", "America/Mendoza"),
("America/Menominee", "America/Menominee"),
("America/Merida", "America/Merida"),
("America/Metlakatla", "America/Metlakatla"),
("America/Mexico_City", "America/Mexico_City"),
("America/Miquelon", "America/Miquelon"),
("America/Moncton", "America/Moncton"),
("America/Monterrey", "America/Monterrey"),
("America/Montevideo", "America/Montevideo"),
("America/Montreal", "America/Montreal"),
("America/Montserrat", "America/Montserrat"),
("America/Nassau", "America/Nassau"),
("America/New_York", "America/New_York"),
("America/Nipigon", "America/Nipigon"),
("America/Nome", "America/Nome"),
("America/Noronha", "America/Noronha"),
(
"America/North_Dakota/Beulah",
"America/North_Dakota/Beulah",
),
(
"America/North_Dakota/Center",
"America/North_Dakota/Center",
),
(
"America/North_Dakota/New_Salem",
"America/North_Dakota/New_Salem",
),
("America/Nuuk", "America/Nuuk"),
("America/Ojinaga", "America/Ojinaga"),
("America/Panama", "America/Panama"),
("America/Pangnirtung", "America/Pangnirtung"),
("America/Paramaribo", "America/Paramaribo"),
("America/Phoenix", "America/Phoenix"),
("America/Port-au-Prince", "America/Port-au-Prince"),
("America/Port_of_Spain", "America/Port_of_Spain"),
("America/Porto_Acre", "America/Porto_Acre"),
("America/Porto_Velho", "America/Porto_Velho"),
("America/Puerto_Rico", "America/Puerto_Rico"),
("America/Punta_Arenas", "America/Punta_Arenas"),
("America/Rainy_River", "America/Rainy_River"),
("America/Rankin_Inlet", "America/Rankin_Inlet"),
("America/Recife", "America/Recife"),
("America/Regina", "America/Regina"),
("America/Resolute", "America/Resolute"),
("America/Rio_Branco", "America/Rio_Branco"),
("America/Rosario", "America/Rosario"),
("America/Santa_Isabel", "America/Santa_Isabel"),
("America/Santarem", "America/Santarem"),
("America/Santiago", "America/Santiago"),
("America/Santo_Domingo", "America/Santo_Domingo"),
("America/Sao_Paulo", "America/Sao_Paulo"),
("America/Scoresbysund", "America/Scoresbysund"),
("America/Shiprock", "America/Shiprock"),
("America/Sitka", "America/Sitka"),
("America/St_Barthelemy", "America/St_Barthelemy"),
("America/St_Johns", "America/St_Johns"),
("America/St_Kitts", "America/St_Kitts"),
("America/St_Lucia", "America/St_Lucia"),
("America/St_Thomas", "America/St_Thomas"),
("America/St_Vincent", "America/St_Vincent"),
("America/Swift_Current", "America/Swift_Current"),
("America/Tegucigalpa", "America/Tegucigalpa"),
("America/Thule", "America/Thule"),
("America/Thunder_Bay", "America/Thunder_Bay"),
("America/Tijuana", "America/Tijuana"),
("America/Toronto", "America/Toronto"),
("America/Tortola", "America/Tortola"),
("America/Vancouver", "America/Vancouver"),
("America/Virgin", "America/Virgin"),
("America/Whitehorse", "America/Whitehorse"),
("America/Winnipeg", "America/Winnipeg"),
("America/Yakutat", "America/Yakutat"),
("America/Yellowknife", "America/Yellowknife"),
("Antarctica/Casey", "Antarctica/Casey"),
("Antarctica/Davis", "Antarctica/Davis"),
("Antarctica/DumontDUrville", "Antarctica/DumontDUrville"),
("Antarctica/Macquarie", "Antarctica/Macquarie"),
("Antarctica/Mawson", "Antarctica/Mawson"),
("Antarctica/McMurdo", "Antarctica/McMurdo"),
("Antarctica/Palmer", "Antarctica/Palmer"),
("Antarctica/Rothera", "Antarctica/Rothera"),
("Antarctica/South_Pole", "Antarctica/South_Pole"),
("Antarctica/Syowa", "Antarctica/Syowa"),
("Antarctica/Troll", "Antarctica/Troll"),
("Antarctica/Vostok", "Antarctica/Vostok"),
("Arctic/Longyearbyen", "Arctic/Longyearbyen"),
("Asia/Aden", "Asia/Aden"),
("Asia/Almaty", "Asia/Almaty"),
("Asia/Amman", "Asia/Amman"),
("Asia/Anadyr", "Asia/Anadyr"),
("Asia/Aqtau", "Asia/Aqtau"),
("Asia/Aqtobe", "Asia/Aqtobe"),
("Asia/Ashgabat", "Asia/Ashgabat"),
("Asia/Ashkhabad", "Asia/Ashkhabad"),
("Asia/Atyrau", "Asia/Atyrau"),
("Asia/Baghdad", "Asia/Baghdad"),
("Asia/Bahrain", "Asia/Bahrain"),
("Asia/Baku", "Asia/Baku"),
("Asia/Bangkok", "Asia/Bangkok"),
("Asia/Barnaul", "Asia/Barnaul"),
("Asia/Beirut", "Asia/Beirut"),
("Asia/Bishkek", "Asia/Bishkek"),
("Asia/Brunei", "Asia/Brunei"),
("Asia/Calcutta", "Asia/Calcutta"),
("Asia/Chita", "Asia/Chita"),
("Asia/Choibalsan", "Asia/Choibalsan"),
("Asia/Chongqing", "Asia/Chongqing"),
("Asia/Chungking", "Asia/Chungking"),
("Asia/Colombo", "Asia/Colombo"),
("Asia/Dacca", "Asia/Dacca"),
("Asia/Damascus", "Asia/Damascus"),
("Asia/Dhaka", "Asia/Dhaka"),
("Asia/Dili", "Asia/Dili"),
("Asia/Dubai", "Asia/Dubai"),
("Asia/Dushanbe", "Asia/Dushanbe"),
("Asia/Famagusta", "Asia/Famagusta"),
("Asia/Gaza", "Asia/Gaza"),
("Asia/Harbin", "Asia/Harbin"),
("Asia/Hebron", "Asia/Hebron"),
("Asia/Ho_Chi_Minh", "Asia/Ho_Chi_Minh"),
("Asia/Hong_Kong", "Asia/Hong_Kong"),
("Asia/Hovd", "Asia/Hovd"),
("Asia/Irkutsk", "Asia/Irkutsk"),
("Asia/Istanbul", "Asia/Istanbul"),
("Asia/Jakarta", "Asia/Jakarta"),
("Asia/Jayapura", "Asia/Jayapura"),
("Asia/Jerusalem", "Asia/Jerusalem"),
("Asia/Kabul", "Asia/Kabul"),
("Asia/Kamchatka", "Asia/Kamchatka"),
("Asia/Karachi", "Asia/Karachi"),
("Asia/Kashgar", "Asia/Kashgar"),
("Asia/Kathmandu", "Asia/Kathmandu"),
("Asia/Katmandu", "Asia/Katmandu"),
("Asia/Khandyga", "Asia/Khandyga"),
("Asia/Kolkata", "Asia/Kolkata"),
("Asia/Krasnoyarsk", "Asia/Krasnoyarsk"),
("Asia/Kuala_Lumpur", "Asia/Kuala_Lumpur"),
("Asia/Kuching", "Asia/Kuching"),
("Asia/Kuwait", "Asia/Kuwait"),
("Asia/Macao", "Asia/Macao"),
("Asia/Macau", "Asia/Macau"),
("Asia/Magadan", "Asia/Magadan"),
("Asia/Makassar", "Asia/Makassar"),
("Asia/Manila", "Asia/Manila"),
("Asia/Muscat", "Asia/Muscat"),
("Asia/Nicosia", "Asia/Nicosia"),
("Asia/Novokuznetsk", "Asia/Novokuznetsk"),
("Asia/Novosibirsk", "Asia/Novosibirsk"),
("Asia/Omsk", "Asia/Omsk"),
("Asia/Oral", "Asia/Oral"),
("Asia/Phnom_Penh", "Asia/Phnom_Penh"),
("Asia/Pontianak", "Asia/Pontianak"),
("Asia/Pyongyang", "Asia/Pyongyang"),
("Asia/Qatar", "Asia/Qatar"),
("Asia/Qostanay", "Asia/Qostanay"),
("Asia/Qyzylorda", "Asia/Qyzylorda"),
("Asia/Rangoon", "Asia/Rangoon"),
("Asia/Riyadh", "Asia/Riyadh"),
("Asia/Saigon", "Asia/Saigon"),
("Asia/Sakhalin", "Asia/Sakhalin"),
("Asia/Samarkand", "Asia/Samarkand"),
("Asia/Seoul", "Asia/Seoul"),
("Asia/Shanghai", "Asia/Shanghai"),
("Asia/Singapore", "Asia/Singapore"),
("Asia/Srednekolymsk", "Asia/Srednekolymsk"),
("Asia/Taipei", "Asia/Taipei"),
("Asia/Tashkent", "Asia/Tashkent"),
("Asia/Tbilisi", "Asia/Tbilisi"),
("Asia/Tehran", "Asia/Tehran"),
("Asia/Tel_Aviv", "Asia/Tel_Aviv"),
("Asia/Thimbu", "Asia/Thimbu"),
("Asia/Thimphu", "Asia/Thimphu"),
("Asia/Tokyo", "Asia/Tokyo"),
("Asia/Tomsk", "Asia/Tomsk"),
("Asia/Ujung_Pandang", "Asia/Ujung_Pandang"),
("Asia/Ulaanbaatar", "Asia/Ulaanbaatar"),
("Asia/Ulan_Bator", "Asia/Ulan_Bator"),
("Asia/Urumqi", "Asia/Urumqi"),
("Asia/Ust-Nera", "Asia/Ust-Nera"),
("Asia/Vientiane", "Asia/Vientiane"),
("Asia/Vladivostok", "Asia/Vladivostok"),
("Asia/Yakutsk", "Asia/Yakutsk"),
("Asia/Yangon", "Asia/Yangon"),
("Asia/Yekaterinburg", "Asia/Yekaterinburg"),
("Asia/Yerevan", "Asia/Yerevan"),
("Atlantic/Azores", "Atlantic/Azores"),
("Atlantic/Bermuda", "Atlantic/Bermuda"),
("Atlantic/Canary", "Atlantic/Canary"),
("Atlantic/Cape_Verde", "Atlantic/Cape_Verde"),
("Atlantic/Faeroe", "Atlantic/Faeroe"),
("Atlantic/Faroe", "Atlantic/Faroe"),
("Atlantic/Jan_Mayen", "Atlantic/Jan_Mayen"),
("Atlantic/Madeira", "Atlantic/Madeira"),
("Atlantic/Reykjavik", "Atlantic/Reykjavik"),
("Atlantic/South_Georgia", "Atlantic/South_Georgia"),
("Atlantic/St_Helena", "Atlantic/St_Helena"),
("Atlantic/Stanley", "Atlantic/Stanley"),
("Australia/ACT", "Australia/ACT"),
("Australia/Adelaide", "Australia/Adelaide"),
("Australia/Brisbane", "Australia/Brisbane"),
("Australia/Broken_Hill", "Australia/Broken_Hill"),
("Australia/Canberra", "Australia/Canberra"),
("Australia/Currie", "Australia/Currie"),
("Australia/Darwin", "Australia/Darwin"),
("Australia/Eucla", "Australia/Eucla"),
("Australia/Hobart", "Australia/Hobart"),
("Australia/LHI", "Australia/LHI"),
("Australia/Lindeman", "Australia/Lindeman"),
("Australia/Lord_Howe", "Australia/Lord_Howe"),
("Australia/Melbourne", "Australia/Melbourne"),
("Australia/NSW", "Australia/NSW"),
("Australia/North", "Australia/North"),
("Australia/Perth", "Australia/Perth"),
("Australia/Queensland", "Australia/Queensland"),
("Australia/South", "Australia/South"),
("Australia/Sydney", "Australia/Sydney"),
("Australia/Tasmania", "Australia/Tasmania"),
("Australia/Victoria", "Australia/Victoria"),
("Australia/West", "Australia/West"),
("Australia/Yancowinna", "Australia/Yancowinna"),
("Brazil/Acre", "Brazil/Acre"),
("Brazil/DeNoronha", "Brazil/DeNoronha"),
("Brazil/East", "Brazil/East"),
("Brazil/West", "Brazil/West"),
("CET", "CET"),
("CST6CDT", "CST6CDT"),
("Canada/Atlantic", "Canada/Atlantic"),
("Canada/Central", "Canada/Central"),
("Canada/Eastern", "Canada/Eastern"),
("Canada/Mountain", "Canada/Mountain"),
("Canada/Newfoundland", "Canada/Newfoundland"),
("Canada/Pacific", "Canada/Pacific"),
("Canada/Saskatchewan", "Canada/Saskatchewan"),
("Canada/Yukon", "Canada/Yukon"),
("Chile/Continental", "Chile/Continental"),
("Chile/EasterIsland", "Chile/EasterIsland"),
("Cuba", "Cuba"),
("EET", "EET"),
("EST", "EST"),
("EST5EDT", "EST5EDT"),
("Egypt", "Egypt"),
("Eire", "Eire"),
("Etc/GMT", "Etc/GMT"),
("Etc/GMT+0", "Etc/GMT+0"),
("Etc/GMT+1", "Etc/GMT+1"),
("Etc/GMT+10", "Etc/GMT+10"),
("Etc/GMT+11", "Etc/GMT+11"),
("Etc/GMT+12", "Etc/GMT+12"),
("Etc/GMT+2", "Etc/GMT+2"),
("Etc/GMT+3", "Etc/GMT+3"),
("Etc/GMT+4", "Etc/GMT+4"),
("Etc/GMT+5", "Etc/GMT+5"),
("Etc/GMT+6", "Etc/GMT+6"),
("Etc/GMT+7", "Etc/GMT+7"),
("Etc/GMT+8", "Etc/GMT+8"),
("Etc/GMT+9", "Etc/GMT+9"),
("Etc/GMT-0", "Etc/GMT-0"),
("Etc/GMT-1", "Etc/GMT-1"),
("Etc/GMT-10", "Etc/GMT-10"),
("Etc/GMT-11", "Etc/GMT-11"),
("Etc/GMT-12", "Etc/GMT-12"),
("Etc/GMT-13", "Etc/GMT-13"),
("Etc/GMT-14", "Etc/GMT-14"),
("Etc/GMT-2", "Etc/GMT-2"),
("Etc/GMT-3", "Etc/GMT-3"),
("Etc/GMT-4", "Etc/GMT-4"),
("Etc/GMT-5", "Etc/GMT-5"),
("Etc/GMT-6", "Etc/GMT-6"),
("Etc/GMT-7", "Etc/GMT-7"),
("Etc/GMT-8", "Etc/GMT-8"),
("Etc/GMT-9", "Etc/GMT-9"),
("Etc/GMT0", "Etc/GMT0"),
("Etc/Greenwich", "Etc/Greenwich"),
("Etc/UCT", "Etc/UCT"),
("Etc/UTC", "Etc/UTC"),
("Etc/Universal", "Etc/Universal"),
("Etc/Zulu", "Etc/Zulu"),
("Europe/Amsterdam", "Europe/Amsterdam"),
("Europe/Andorra", "Europe/Andorra"),
("Europe/Astrakhan", "Europe/Astrakhan"),
("Europe/Athens", "Europe/Athens"),
("Europe/Belfast", "Europe/Belfast"),
("Europe/Belgrade", "Europe/Belgrade"),
("Europe/Berlin", "Europe/Berlin"),
("Europe/Bratislava", "Europe/Bratislava"),
("Europe/Brussels", "Europe/Brussels"),
("Europe/Bucharest", "Europe/Bucharest"),
("Europe/Budapest", "Europe/Budapest"),
("Europe/Busingen", "Europe/Busingen"),
("Europe/Chisinau", "Europe/Chisinau"),
("Europe/Copenhagen", "Europe/Copenhagen"),
("Europe/Dublin", "Europe/Dublin"),
("Europe/Gibraltar", "Europe/Gibraltar"),
("Europe/Guernsey", "Europe/Guernsey"),
("Europe/Helsinki", "Europe/Helsinki"),
("Europe/Isle_of_Man", "Europe/Isle_of_Man"),
("Europe/Istanbul", "Europe/Istanbul"),
("Europe/Jersey", "Europe/Jersey"),
("Europe/Kaliningrad", "Europe/Kaliningrad"),
("Europe/Kiev", "Europe/Kiev"),
("Europe/Kirov", "Europe/Kirov"),
("Europe/Kyiv", "Europe/Kyiv"),
("Europe/Lisbon", "Europe/Lisbon"),
("Europe/Ljubljana", "Europe/Ljubljana"),
("Europe/London", "Europe/London"),
("Europe/Luxembourg", "Europe/Luxembourg"),
("Europe/Madrid", "Europe/Madrid"),
("Europe/Malta", "Europe/Malta"),
("Europe/Mariehamn", "Europe/Mariehamn"),
("Europe/Minsk", "Europe/Minsk"),
("Europe/Monaco", "Europe/Monaco"),
("Europe/Moscow", "Europe/Moscow"),
("Europe/Nicosia", "Europe/Nicosia"),
("Europe/Oslo", "Europe/Oslo"),
("Europe/Paris", "Europe/Paris"),
("Europe/Podgorica", "Europe/Podgorica"),
("Europe/Prague", "Europe/Prague"),
("Europe/Riga", "Europe/Riga"),
("Europe/Rome", "Europe/Rome"),
("Europe/Samara", "Europe/Samara"),
("Europe/San_Marino", "Europe/San_Marino"),
("Europe/Sarajevo", "Europe/Sarajevo"),
("Europe/Saratov", "Europe/Saratov"),
("Europe/Simferopol", "Europe/Simferopol"),
("Europe/Skopje", "Europe/Skopje"),
("Europe/Sofia", "Europe/Sofia"),
("Europe/Stockholm", "Europe/Stockholm"),
("Europe/Tallinn", "Europe/Tallinn"),
("Europe/Tirane", "Europe/Tirane"),
("Europe/Tiraspol", "Europe/Tiraspol"),
("Europe/Ulyanovsk", "Europe/Ulyanovsk"),
("Europe/Uzhgorod", "Europe/Uzhgorod"),
("Europe/Vaduz", "Europe/Vaduz"),
("Europe/Vatican", "Europe/Vatican"),
("Europe/Vienna", "Europe/Vienna"),
("Europe/Vilnius", "Europe/Vilnius"),
("Europe/Volgograd", "Europe/Volgograd"),
("Europe/Warsaw", "Europe/Warsaw"),
("Europe/Zagreb", "Europe/Zagreb"),
("Europe/Zaporozhye", "Europe/Zaporozhye"),
("Europe/Zurich", "Europe/Zurich"),
("GB", "GB"),
("GB-Eire", "GB-Eire"),
("GMT", "GMT"),
("GMT+0", "GMT+0"),
("GMT-0", "GMT-0"),
("GMT0", "GMT0"),
("Greenwich", "Greenwich"),
("HST", "HST"),
("Hongkong", "Hongkong"),
("Iceland", "Iceland"),
("Indian/Antananarivo", "Indian/Antananarivo"),
("Indian/Chagos", "Indian/Chagos"),
("Indian/Christmas", "Indian/Christmas"),
("Indian/Cocos", "Indian/Cocos"),
("Indian/Comoro", "Indian/Comoro"),
("Indian/Kerguelen", "Indian/Kerguelen"),
("Indian/Mahe", "Indian/Mahe"),
("Indian/Maldives", "Indian/Maldives"),
("Indian/Mauritius", "Indian/Mauritius"),
("Indian/Mayotte", "Indian/Mayotte"),
("Indian/Reunion", "Indian/Reunion"),
("Iran", "Iran"),
("Israel", "Israel"),
("Jamaica", "Jamaica"),
("Japan", "Japan"),
("Kwajalein", "Kwajalein"),
("Libya", "Libya"),
("MET", "MET"),
("MST", "MST"),
("MST7MDT", "MST7MDT"),
("Mexico/BajaNorte", "Mexico/BajaNorte"),
("Mexico/BajaSur", "Mexico/BajaSur"),
("Mexico/General", "Mexico/General"),
("NZ", "NZ"),
("NZ-CHAT", "NZ-CHAT"),
("Navajo", "Navajo"),
("PRC", "PRC"),
("PST8PDT", "PST8PDT"),
("Pacific/Apia", "Pacific/Apia"),
("Pacific/Auckland", "Pacific/Auckland"),
("Pacific/Bougainville", "Pacific/Bougainville"),
("Pacific/Chatham", "Pacific/Chatham"),
("Pacific/Chuuk", "Pacific/Chuuk"),
("Pacific/Easter", "Pacific/Easter"),
("Pacific/Efate", "Pacific/Efate"),
("Pacific/Enderbury", "Pacific/Enderbury"),
("Pacific/Fakaofo", "Pacific/Fakaofo"),
("Pacific/Fiji", "Pacific/Fiji"),
("Pacific/Funafuti", "Pacific/Funafuti"),
("Pacific/Galapagos", "Pacific/Galapagos"),
("Pacific/Gambier", "Pacific/Gambier"),
("Pacific/Guadalcanal", "Pacific/Guadalcanal"),
("Pacific/Guam", "Pacific/Guam"),
("Pacific/Honolulu", "Pacific/Honolulu"),
("Pacific/Johnston", "Pacific/Johnston"),
("Pacific/Kanton", "Pacific/Kanton"),
("Pacific/Kiritimati", "Pacific/Kiritimati"),
("Pacific/Kosrae", "Pacific/Kosrae"),
("Pacific/Kwajalein", "Pacific/Kwajalein"),
("Pacific/Majuro", "Pacific/Majuro"),
("Pacific/Marquesas", "Pacific/Marquesas"),
("Pacific/Midway", "Pacific/Midway"),
("Pacific/Nauru", "Pacific/Nauru"),
("Pacific/Niue", "Pacific/Niue"),
("Pacific/Norfolk", "Pacific/Norfolk"),
("Pacific/Noumea", "Pacific/Noumea"),
("Pacific/Pago_Pago", "Pacific/Pago_Pago"),
("Pacific/Palau", "Pacific/Palau"),
("Pacific/Pitcairn", "Pacific/Pitcairn"),
("Pacific/Pohnpei", "Pacific/Pohnpei"),
("Pacific/Ponape", "Pacific/Ponape"),
("Pacific/Port_Moresby", "Pacific/Port_Moresby"),
("Pacific/Rarotonga", "Pacific/Rarotonga"),
("Pacific/Saipan", "Pacific/Saipan"),
("Pacific/Samoa", "Pacific/Samoa"),
("Pacific/Tahiti", "Pacific/Tahiti"),
("Pacific/Tarawa", "Pacific/Tarawa"),
("Pacific/Tongatapu", "Pacific/Tongatapu"),
("Pacific/Truk", "Pacific/Truk"),
("Pacific/Wake", "Pacific/Wake"),
("Pacific/Wallis", "Pacific/Wallis"),
("Pacific/Yap", "Pacific/Yap"),
("Poland", "Poland"),
("Portugal", "Portugal"),
("ROC", "ROC"),
("ROK", "ROK"),
("Singapore", "Singapore"),
("Turkey", "Turkey"),
("UCT", "UCT"),
("US/Alaska", "US/Alaska"),
("US/Aleutian", "US/Aleutian"),
("US/Arizona", "US/Arizona"),
("US/Central", "US/Central"),
("US/East-Indiana", "US/East-Indiana"),
("US/Eastern", "US/Eastern"),
("US/Hawaii", "US/Hawaii"),
("US/Indiana-Starke", "US/Indiana-Starke"),
("US/Michigan", "US/Michigan"),
("US/Mountain", "US/Mountain"),
("US/Pacific", "US/Pacific"),
("US/Samoa", "US/Samoa"),
("UTC", "UTC"),
("Universal", "Universal"),
("W-SU", "W-SU"),
("WET", "WET"),
("Zulu", "Zulu"),
],
default="UTC",
max_length=255,
),
),
migrations.AlterField(
model_name="issuelink",
name="title",
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.RunPython(update_user_timezones),
migrations.AlterField(
model_name="issuevote",
name="vote",
field=models.IntegerField(
choices=[(-1, "DOWNVOTE"), (1, "UPVOTE")], default=1
),
),
migrations.CreateModel(
name="ProjectPublicMember",
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,
),
),
(
"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",
),
),
(
"member",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="public_project_members",
to=settings.AUTH_USER_MODEL,
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_%(class)s",
to="db.project",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="%(class)s_updated_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Last Modified By",
),
),
(
"workspace",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="workspace_%(class)s",
to="db.workspace",
),
),
],
options={
"verbose_name": "Project Public Member",
"verbose_name_plural": "Project Public Members",
"db_table": "project_public_members",
"ordering": ("-created_at",),
"unique_together": {("project", "member")},
},
),
]
@@ -0,0 +1,173 @@
# Generated by Django 4.2.3 on 2023-09-12 07:29
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import uuid
def create_issue_relation(apps, schema_editor):
try:
IssueBlockerModel = apps.get_model("db", "IssueBlocker")
IssueRelation = apps.get_model("db", "IssueRelation")
updated_issue_relation = []
for blocked_issue in IssueBlockerModel.objects.all():
updated_issue_relation.append(
IssueRelation(
issue_id=blocked_issue.block_id,
related_issue_id=blocked_issue.blocked_by_id,
relation_type="blocked_by",
project_id=blocked_issue.project_id,
workspace_id=blocked_issue.workspace_id,
created_by_id=blocked_issue.created_by_id,
updated_by_id=blocked_issue.updated_by_id,
)
)
IssueRelation.objects.bulk_create(
updated_issue_relation, batch_size=100
)
except Exception as e:
print(e)
def update_issue_priority_choice(apps, schema_editor):
IssueModel = apps.get_model("db", "Issue")
updated_issues = []
for obj in IssueModel.objects.filter(priority=None):
obj.priority = "none"
updated_issues.append(obj)
IssueModel.objects.bulk_update(
updated_issues, ["priority"], batch_size=100
)
class Migration(migrations.Migration):
dependencies = [
("db", "0042_alter_analyticview_created_by_and_more"),
]
operations = [
migrations.CreateModel(
name="IssueRelation",
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,
),
),
(
"relation_type",
models.CharField(
choices=[
("duplicate", "Duplicate"),
("relates_to", "Relates To"),
("blocked_by", "Blocked By"),
],
default="blocked_by",
max_length=20,
verbose_name="Issue Relation Type",
),
),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="%(class)s_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"issue",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="issue_relation",
to="db.issue",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_%(class)s",
to="db.project",
),
),
(
"related_issue",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="issue_related",
to="db.issue",
),
),
(
"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 Relation",
"verbose_name_plural": "Issue Relations",
"db_table": "issue_relations",
"ordering": ("-created_at",),
"unique_together": {("issue", "related_issue")},
},
),
migrations.AddField(
model_name="issue",
name="is_draft",
field=models.BooleanField(default=False),
),
migrations.AlterField(
model_name="issue",
name="priority",
field=models.CharField(
choices=[
("urgent", "Urgent"),
("high", "High"),
("medium", "Medium"),
("low", "Low"),
("none", "None"),
],
default="none",
max_length=30,
verbose_name="Issue Priority",
),
),
migrations.RunPython(create_issue_relation),
migrations.RunPython(update_issue_priority_choice),
]
@@ -0,0 +1,172 @@
# Generated by Django 4.2.3 on 2023-09-13 07:09
from django.db import migrations
def workspace_member_props(old_props):
new_props = {
"filters": {
"priority": old_props.get("filters", {}).get("priority", None),
"state": old_props.get("filters", {}).get("state", None),
"state_group": old_props.get("filters", {}).get(
"state_group", None
),
"assignees": old_props.get("filters", {}).get("assignees", None),
"created_by": old_props.get("filters", {}).get("created_by", None),
"labels": old_props.get("filters", {}).get("labels", None),
"start_date": old_props.get("filters", {}).get("start_date", None),
"target_date": old_props.get("filters", {}).get(
"target_date", None
),
"subscriber": old_props.get("filters", {}).get("subscriber", None),
},
"display_filters": {
"group_by": old_props.get("groupByProperty", None),
"order_by": old_props.get("orderBy", "-created_at"),
"type": old_props.get("filters", {}).get("type", None),
"sub_issue": old_props.get("showSubIssues", True),
"show_empty_groups": old_props.get("showEmptyGroups", True),
"layout": old_props.get("issueView", "list"),
"calendar_date_range": old_props.get("calendarDateRange", ""),
},
"display_properties": {
"assignee": old_props.get("properties", {}).get("assignee", True),
"attachment_count": old_props.get("properties", {}).get(
"attachment_count", True
),
"created_on": old_props.get("properties", {}).get(
"created_on", True
),
"due_date": old_props.get("properties", {}).get("due_date", True),
"estimate": old_props.get("properties", {}).get("estimate", True),
"key": old_props.get("properties", {}).get("key", True),
"labels": old_props.get("properties", {}).get("labels", True),
"link": old_props.get("properties", {}).get("link", True),
"priority": old_props.get("properties", {}).get("priority", True),
"start_date": old_props.get("properties", {}).get(
"start_date", True
),
"state": old_props.get("properties", {}).get("state", True),
"sub_issue_count": old_props.get("properties", {}).get(
"sub_issue_count", True
),
"updated_on": old_props.get("properties", {}).get(
"updated_on", True
),
},
}
return new_props
def project_member_props(old_props):
new_props = {
"filters": {
"priority": old_props.get("filters", {}).get("priority", None),
"state": old_props.get("filters", {}).get("state", None),
"state_group": old_props.get("filters", {}).get(
"state_group", None
),
"assignees": old_props.get("filters", {}).get("assignees", None),
"created_by": old_props.get("filters", {}).get("created_by", None),
"labels": old_props.get("filters", {}).get("labels", None),
"start_date": old_props.get("filters", {}).get("start_date", None),
"target_date": old_props.get("filters", {}).get(
"target_date", None
),
"subscriber": old_props.get("filters", {}).get("subscriber", None),
},
"display_filters": {
"group_by": old_props.get("groupByProperty", None),
"order_by": old_props.get("orderBy", "-created_at"),
"type": old_props.get("filters", {}).get("type", None),
"sub_issue": old_props.get("showSubIssues", True),
"show_empty_groups": old_props.get("showEmptyGroups", True),
"layout": old_props.get("issueView", "list"),
"calendar_date_range": old_props.get("calendarDateRange", ""),
},
}
return new_props
def cycle_module_props(old_props):
new_props = {
"filters": {
"priority": old_props.get("filters", {}).get("priority", None),
"state": old_props.get("filters", {}).get("state", None),
"state_group": old_props.get("filters", {}).get(
"state_group", None
),
"assignees": old_props.get("filters", {}).get("assignees", None),
"created_by": old_props.get("filters", {}).get("created_by", None),
"labels": old_props.get("filters", {}).get("labels", None),
"start_date": old_props.get("filters", {}).get("start_date", None),
"target_date": old_props.get("filters", {}).get(
"target_date", None
),
"subscriber": old_props.get("filters", {}).get("subscriber", None),
},
}
return new_props
def update_workspace_member_view_props(apps, schema_editor):
WorkspaceMemberModel = apps.get_model("db", "WorkspaceMember")
updated_workspace_member = []
for obj in WorkspaceMemberModel.objects.all():
obj.view_props = workspace_member_props(obj.view_props)
obj.default_props = workspace_member_props(obj.default_props)
updated_workspace_member.append(obj)
WorkspaceMemberModel.objects.bulk_update(
updated_workspace_member,
["view_props", "default_props"],
batch_size=100,
)
def update_project_member_view_props(apps, schema_editor):
ProjectMemberModel = apps.get_model("db", "ProjectMember")
updated_project_member = []
for obj in ProjectMemberModel.objects.all():
obj.view_props = project_member_props(obj.view_props)
obj.default_props = project_member_props(obj.default_props)
updated_project_member.append(obj)
ProjectMemberModel.objects.bulk_update(
updated_project_member, ["view_props", "default_props"], batch_size=100
)
def update_cycle_props(apps, schema_editor):
CycleModel = apps.get_model("db", "Cycle")
updated_cycle = []
for obj in CycleModel.objects.all():
if "filter" in obj.view_props:
obj.view_props = cycle_module_props(obj.view_props)
updated_cycle.append(obj)
CycleModel.objects.bulk_update(
updated_cycle, ["view_props"], batch_size=100
)
def update_module_props(apps, schema_editor):
ModuleModel = apps.get_model("db", "Module")
updated_module = []
for obj in ModuleModel.objects.all():
if "filter" in obj.view_props:
obj.view_props = cycle_module_props(obj.view_props)
updated_module.append(obj)
ModuleModel.objects.bulk_update(
updated_module, ["view_props"], batch_size=100
)
class Migration(migrations.Migration):
dependencies = [
("db", "0043_alter_analyticview_created_by_and_more"),
]
operations = [
migrations.RunPython(update_workspace_member_view_props),
migrations.RunPython(update_project_member_view_props),
migrations.RunPython(update_cycle_props),
migrations.RunPython(update_module_props),
]
@@ -0,0 +1,140 @@
# Generated by Django 4.2.5 on 2023-09-29 10:14
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import plane.db.models.workspace
import uuid
def update_issue_activity_priority(apps, schema_editor):
IssueActivity = apps.get_model("db", "IssueActivity")
updated_issue_activity = []
for obj in IssueActivity.objects.filter(field="priority"):
# Set the old and new value to none if it is empty for Priority
obj.new_value = obj.new_value or "none"
obj.old_value = obj.old_value or "none"
updated_issue_activity.append(obj)
IssueActivity.objects.bulk_update(
updated_issue_activity,
["new_value", "old_value"],
batch_size=2000,
)
def update_issue_activity_blocked(apps, schema_editor):
IssueActivity = apps.get_model("db", "IssueActivity")
updated_issue_activity = []
for obj in IssueActivity.objects.filter(field="blocks"):
# Set the field to blocked_by
obj.field = "blocked_by"
updated_issue_activity.append(obj)
IssueActivity.objects.bulk_update(
updated_issue_activity,
["field"],
batch_size=1000,
)
class Migration(migrations.Migration):
dependencies = [
("db", "0044_auto_20230913_0709"),
]
operations = [
migrations.CreateModel(
name="GlobalView",
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, verbose_name="View Name"),
),
(
"description",
models.TextField(
blank=True, verbose_name="View Description"
),
),
("query", models.JSONField(verbose_name="View Query")),
(
"access",
models.PositiveSmallIntegerField(
choices=[(0, "Private"), (1, "Public")], default=1
),
),
("query_data", 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",
),
),
(
"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="global_views",
to="db.workspace",
),
),
],
options={
"verbose_name": "Global View",
"verbose_name_plural": "Global Views",
"db_table": "global_views",
"ordering": ("-created_at",),
},
),
migrations.AddField(
model_name="workspacemember",
name="issue_props",
field=models.JSONField(
default=plane.db.models.workspace.get_issue_props
),
),
migrations.AddField(
model_name="issueactivity",
name="epoch",
field=models.FloatField(null=True),
),
migrations.RunPython(update_issue_activity_priority),
migrations.RunPython(update_issue_activity_blocked),
]
@@ -0,0 +1,296 @@
# Generated by Django 4.2.5 on 2023-11-15 11:20
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import plane.db.models.api
import plane.db.models.webhook
import uuid
class Migration(migrations.Migration):
dependencies = [
("db", "0046_label_sort_order_alter_analyticview_created_by_and_more"),
]
operations = [
migrations.CreateModel(
name="Webhook",
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,
),
),
(
"url",
models.URLField(
validators=[
plane.db.models.webhook.validate_schema,
plane.db.models.webhook.validate_domain,
]
),
),
("is_active", models.BooleanField(default=True)),
(
"secret_key",
models.CharField(
default=plane.db.models.webhook.generate_token,
max_length=255,
),
),
("project", models.BooleanField(default=False)),
("issue", models.BooleanField(default=False)),
("module", models.BooleanField(default=False)),
("cycle", models.BooleanField(default=False)),
("issue_comment", models.BooleanField(default=False)),
(
"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",
),
),
(
"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_webhooks",
to="db.workspace",
),
),
],
options={
"verbose_name": "Webhook",
"verbose_name_plural": "Webhooks",
"db_table": "webhooks",
"ordering": ("-created_at",),
"unique_together": {("workspace", "url")},
},
),
migrations.AddField(
model_name="apitoken",
name="description",
field=models.TextField(blank=True),
),
migrations.AddField(
model_name="apitoken",
name="expired_at",
field=models.DateTimeField(blank=True, null=True),
),
migrations.AddField(
model_name="apitoken",
name="is_active",
field=models.BooleanField(default=True),
),
migrations.AddField(
model_name="apitoken",
name="last_used",
field=models.DateTimeField(null=True),
),
migrations.AddField(
model_name="projectmember",
name="is_active",
field=models.BooleanField(default=True),
),
migrations.AddField(
model_name="workspacemember",
name="is_active",
field=models.BooleanField(default=True),
),
migrations.AlterField(
model_name="apitoken",
name="token",
field=models.CharField(
db_index=True,
default=plane.db.models.api.generate_token,
max_length=255,
unique=True,
),
),
migrations.CreateModel(
name="WebhookLog",
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,
),
),
(
"event_type",
models.CharField(blank=True, max_length=255, null=True),
),
(
"request_method",
models.CharField(blank=True, max_length=10, null=True),
),
("request_headers", models.TextField(blank=True, null=True)),
("request_body", models.TextField(blank=True, null=True)),
("response_status", models.TextField(blank=True, null=True)),
("response_headers", models.TextField(blank=True, null=True)),
("response_body", models.TextField(blank=True, null=True)),
("retry_count", models.PositiveSmallIntegerField(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",
),
),
(
"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",
),
),
(
"webhook",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="logs",
to="db.webhook",
),
),
(
"workspace",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="webhook_logs",
to="db.workspace",
),
),
],
options={
"verbose_name": "Webhook Log",
"verbose_name_plural": "Webhook Logs",
"db_table": "webhook_logs",
"ordering": ("-created_at",),
},
),
migrations.CreateModel(
name="APIActivityLog",
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,
),
),
("token_identifier", models.CharField(max_length=255)),
("path", models.CharField(max_length=255)),
("method", models.CharField(max_length=10)),
("query_params", models.TextField(blank=True, null=True)),
("headers", models.TextField(blank=True, null=True)),
("body", models.TextField(blank=True, null=True)),
("response_code", models.PositiveIntegerField()),
("response_body", models.TextField(blank=True, null=True)),
(
"ip_address",
models.GenericIPAddressField(blank=True, null=True),
),
(
"user_agent",
models.CharField(blank=True, max_length=512, null=True),
),
(
"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",
),
),
(
"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",
),
),
],
options={
"verbose_name": "API Activity Log",
"verbose_name_plural": "API Activity Logs",
"db_table": "api_activity_logs",
"ordering": ("-created_at",),
},
),
]
@@ -0,0 +1,141 @@
# Generated by Django 4.2.5 on 2023-11-13 12:53
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
(
"db",
"0047_webhook_apitoken_description_apitoken_expired_at_and_more",
),
]
operations = [
migrations.CreateModel(
name="PageLog",
fields=[
(
"created_at",
models.DateTimeField(
auto_now_add=True, verbose_name="Created At"
),
),
(
"updated_at",
models.DateTimeField(
auto_now=True, verbose_name="Last Modified At"
),
),
(
"id",
models.UUIDField(
db_index=True,
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
unique=True,
),
),
("transaction", models.UUIDField(default=uuid.uuid4)),
("entity_identifier", models.UUIDField(null=True)),
(
"entity_name",
models.CharField(
choices=[
("to_do", "To Do"),
("issue", "issue"),
("image", "Image"),
("video", "Video"),
("file", "File"),
("link", "Link"),
("cycle", "Cycle"),
("module", "Module"),
("back_link", "Back Link"),
("forward_link", "Forward Link"),
("page_mention", "Page Mention"),
("user_mention", "User Mention"),
],
max_length=30,
verbose_name="Transaction Type",
),
),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="%(class)s_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"page",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="page_log",
to="db.page",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_%(class)s",
to="db.project",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="%(class)s_updated_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Last Modified By",
),
),
(
"workspace",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="workspace_%(class)s",
to="db.workspace",
),
),
],
options={
"verbose_name": "Page Log",
"verbose_name_plural": "Page Logs",
"db_table": "page_logs",
"ordering": ("-created_at",),
"unique_together": {("page", "transaction")},
},
),
migrations.AddField(
model_name="page",
name="archived_at",
field=models.DateField(null=True),
),
migrations.AddField(
model_name="page",
name="is_locked",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="page",
name="parent",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="child_page",
to="db.page",
),
),
]
@@ -0,0 +1,74 @@
# Generated by Django 4.2.5 on 2023-11-15 09:16
# Python imports
import uuid
from django.db import migrations
def update_pages(apps, schema_editor):
try:
Page = apps.get_model("db", "Page")
PageBlock = apps.get_model("db", "PageBlock")
PageLog = apps.get_model("db", "PageLog")
updated_pages = []
page_logs = []
# looping through all the pages
for page in Page.objects.all():
page_blocks = PageBlock.objects.filter(
page_id=page.id,
project_id=page.project_id,
workspace_id=page.workspace_id,
).order_by("sort_order")
if page_blocks:
# looping through all the page blocks in a page
for page_block in page_blocks:
if page_block.issue is not None:
project_identifier = page.project.identifier
sequence_id = page_block.issue.sequence_id
transaction = uuid.uuid4().hex
embed_component = f'<issue-embed-component id="{transaction}" entity_name="issue" entity_identifier="{page_block.issue_id}" sequence_id="{sequence_id}" project_identifier="{project_identifier}" title="{page_block.name}"></issue-embed-component>'
page.description_html += embed_component
# create the page transaction for the issue
page_logs.append(
PageLog(
page_id=page_block.page_id,
transaction=transaction,
entity_identifier=page_block.issue_id,
entity_name="issue",
project_id=page.project_id,
workspace_id=page.workspace_id,
created_by_id=page_block.created_by_id,
updated_by_id=page_block.updated_by_id,
)
)
else:
# adding the page block name and description to the page description
page.description_html += f"<h2>{page_block.name}</h2>"
page.description_html += page_block.description_html
updated_pages.append(page)
Page.objects.bulk_update(
updated_pages,
["description_html"],
batch_size=100,
)
PageLog.objects.bulk_create(page_logs, batch_size=100)
except Exception as e:
print(e)
class Migration(migrations.Migration):
dependencies = [
("db", "0048_auto_20231116_0713"),
]
operations = [
migrations.RunPython(update_pages),
]
@@ -0,0 +1,43 @@
# Generated by Django 4.2.5 on 2023-11-17 08:48
from django.db import migrations, models
import plane.db.models.workspace
def user_password_autoset(apps, schema_editor):
User = apps.get_model("db", "User")
User.objects.update(is_password_autoset=True)
class Migration(migrations.Migration):
dependencies = [
("db", "0049_auto_20231116_0713"),
]
operations = [
migrations.AddField(
model_name="user",
name="use_case",
field=models.TextField(blank=True, null=True),
),
migrations.AlterField(
model_name="workspace",
name="organization_size",
field=models.CharField(blank=True, max_length=20, null=True),
),
migrations.AddField(
model_name="fileasset",
name="is_deleted",
field=models.BooleanField(default=False),
),
migrations.AlterField(
model_name="workspace",
name="slug",
field=models.SlugField(
max_length=48,
unique=True,
validators=[plane.db.models.workspace.slug_validator],
),
),
migrations.RunPython(user_password_autoset),
]
@@ -0,0 +1,82 @@
# Generated by Django 4.2.7 on 2023-12-29 10:20
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("db", "0050_user_use_case_alter_workspace_organization_size"),
]
operations = [
migrations.AddField(
model_name="cycle",
name="external_id",
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name="cycle",
name="external_source",
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name="inboxissue",
name="external_id",
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name="inboxissue",
name="external_source",
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name="issue",
name="external_id",
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name="issue",
name="external_source",
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name="issuecomment",
name="external_id",
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name="issuecomment",
name="external_source",
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name="label",
name="external_id",
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name="label",
name="external_source",
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name="module",
name="external_id",
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name="module",
name="external_source",
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name="state",
name="external_id",
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name="state",
name="external_source",
field=models.CharField(blank=True, max_length=255, null=True),
),
]
@@ -0,0 +1,379 @@
# Generated by Django 4.2.7 on 2023-12-20 11:14
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import plane.db.models.cycle
import plane.db.models.issue
import plane.db.models.module
import plane.db.models.view
import plane.db.models.workspace
import uuid
class Migration(migrations.Migration):
dependencies = [
("db", "0051_cycle_external_id_cycle_external_source_and_more"),
]
operations = [
migrations.RenameField(
model_name="issueview",
old_name="query_data",
new_name="filters",
),
migrations.RenameField(
model_name="issueproperty",
old_name="properties",
new_name="display_properties",
),
migrations.AlterField(
model_name="issueproperty",
name="display_properties",
field=models.JSONField(
default=plane.db.models.issue.get_default_display_properties
),
),
migrations.AddField(
model_name="issueproperty",
name="display_filters",
field=models.JSONField(
default=plane.db.models.issue.get_default_display_filters
),
),
migrations.AddField(
model_name="issueproperty",
name="filters",
field=models.JSONField(
default=plane.db.models.issue.get_default_filters
),
),
migrations.AddField(
model_name="issueview",
name="display_filters",
field=models.JSONField(
default=plane.db.models.view.get_default_display_filters
),
),
migrations.AddField(
model_name="issueview",
name="display_properties",
field=models.JSONField(
default=plane.db.models.view.get_default_display_properties
),
),
migrations.AddField(
model_name="issueview",
name="sort_order",
field=models.FloatField(default=65535),
),
migrations.AlterField(
model_name="issueview",
name="project",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="project_%(class)s",
to="db.project",
),
),
migrations.CreateModel(
name="WorkspaceUserProperties",
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,
),
),
(
"filters",
models.JSONField(
default=plane.db.models.workspace.get_default_filters
),
),
(
"display_filters",
models.JSONField(
default=plane.db.models.workspace.get_default_display_filters
),
),
(
"display_properties",
models.JSONField(
default=plane.db.models.workspace.get_default_display_properties
),
),
(
"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",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="%(class)s_updated_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Last Modified By",
),
),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="workspace_user_properties",
to=settings.AUTH_USER_MODEL,
),
),
(
"workspace",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="workspace_user_properties",
to="db.workspace",
),
),
],
options={
"verbose_name": "Workspace User Property",
"verbose_name_plural": "Workspace User Property",
"db_table": "workspace_user_properties",
"ordering": ("-created_at",),
"unique_together": {("workspace", "user")},
},
),
migrations.CreateModel(
name="ModuleUserProperties",
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,
),
),
(
"filters",
models.JSONField(
default=plane.db.models.module.get_default_filters
),
),
(
"display_filters",
models.JSONField(
default=plane.db.models.module.get_default_display_filters
),
),
(
"display_properties",
models.JSONField(
default=plane.db.models.module.get_default_display_properties
),
),
(
"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",
),
),
(
"module",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="module_user_properties",
to="db.module",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_%(class)s",
to="db.project",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="%(class)s_updated_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Last Modified By",
),
),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="module_user_properties",
to=settings.AUTH_USER_MODEL,
),
),
(
"workspace",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="workspace_%(class)s",
to="db.workspace",
),
),
],
options={
"verbose_name": "Module User Property",
"verbose_name_plural": "Module User Property",
"db_table": "module_user_properties",
"ordering": ("-created_at",),
"unique_together": {("module", "user")},
},
),
migrations.CreateModel(
name="CycleUserProperties",
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,
),
),
(
"filters",
models.JSONField(
default=plane.db.models.cycle.get_default_filters
),
),
(
"display_filters",
models.JSONField(
default=plane.db.models.cycle.get_default_display_filters
),
),
(
"display_properties",
models.JSONField(
default=plane.db.models.cycle.get_default_display_properties
),
),
(
"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",
),
),
(
"cycle",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="cycle_user_properties",
to="db.cycle",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_%(class)s",
to="db.project",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="%(class)s_updated_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Last Modified By",
),
),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="cycle_user_properties",
to=settings.AUTH_USER_MODEL,
),
),
(
"workspace",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="workspace_%(class)s",
to="db.workspace",
),
),
],
options={
"verbose_name": "Cycle User Property",
"verbose_name_plural": "Cycle User Properties",
"db_table": "cycle_user_properties",
"ordering": ("-created_at",),
"unique_together": {("cycle", "user")},
},
),
]
@@ -0,0 +1,82 @@
# Generated by Django 4.2.7 on 2024-01-02 13:15
from django.db import migrations
def workspace_user_properties(apps, schema_editor):
WorkspaceMember = apps.get_model("db", "WorkspaceMember")
WorkspaceUserProperties = apps.get_model("db", "WorkspaceUserProperties")
updated_workspace_user_properties = []
for workspace_members in WorkspaceMember.objects.all():
updated_workspace_user_properties.append(
WorkspaceUserProperties(
user_id=workspace_members.member_id,
display_filters=workspace_members.view_props.get(
"display_filters"
),
display_properties=workspace_members.view_props.get(
"display_properties"
),
workspace_id=workspace_members.workspace_id,
)
)
WorkspaceUserProperties.objects.bulk_create(
updated_workspace_user_properties,
batch_size=2000,
)
def project_user_properties(apps, schema_editor):
IssueProperty = apps.get_model("db", "IssueProperty")
ProjectMember = apps.get_model("db", "ProjectMember")
updated_issue_user_properties = []
for issue_property in IssueProperty.objects.all():
project_member = ProjectMember.objects.filter(
project_id=issue_property.project_id,
member_id=issue_property.user_id,
).first()
if project_member:
issue_property.filters = project_member.view_props.get("filters")
issue_property.display_filters = project_member.view_props.get(
"display_filters"
)
updated_issue_user_properties.append(issue_property)
IssueProperty.objects.bulk_update(
updated_issue_user_properties,
["filters", "display_filters"],
batch_size=2000,
)
def issue_view(apps, schema_editor):
GlobalView = apps.get_model("db", "GlobalView")
IssueView = apps.get_model("db", "IssueView")
updated_issue_views = []
for global_view in GlobalView.objects.all():
updated_issue_views.append(
IssueView(
workspace_id=global_view.workspace_id,
name=global_view.name,
description=global_view.description,
query=global_view.query,
access=global_view.access,
filters=global_view.query_data.get("filters", {}),
sort_order=global_view.sort_order,
created_by_id=global_view.created_by_id,
updated_by_id=global_view.updated_by_id,
)
)
IssueView.objects.bulk_create(updated_issue_views, batch_size=100)
class Migration(migrations.Migration):
dependencies = [
("db", "0052_auto_20231220_1141"),
]
operations = [
migrations.RunPython(workspace_user_properties),
migrations.RunPython(project_user_properties),
migrations.RunPython(issue_view),
]
@@ -0,0 +1,210 @@
# Generated by Django 4.2.7 on 2024-01-08 06:47
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
("db", "0053_auto_20240102_1315"),
]
operations = [
migrations.CreateModel(
name="Dashboard",
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_html",
models.TextField(blank=True, default="<p></p>"),
),
("identifier", models.UUIDField(null=True)),
("is_default", models.BooleanField(default=False)),
(
"type_identifier",
models.CharField(
choices=[
("workspace", "Workspace"),
("project", "Project"),
("home", "Home"),
("team", "Team"),
("user", "User"),
],
default="home",
max_length=30,
verbose_name="Dashboard Type",
),
),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="%(class)s_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"owned_by",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="dashboards",
to=settings.AUTH_USER_MODEL,
),
),
(
"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",
),
),
],
options={
"verbose_name": "Dashboard",
"verbose_name_plural": "Dashboards",
"db_table": "dashboards",
"ordering": ("-created_at",),
},
),
migrations.CreateModel(
name="Widget",
fields=[
(
"id",
models.UUIDField(
db_index=True,
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
unique=True,
),
),
(
"created_at",
models.DateTimeField(
auto_now_add=True, verbose_name="Created At"
),
),
(
"updated_at",
models.DateTimeField(
auto_now=True, verbose_name="Last Modified At"
),
),
("key", models.CharField(max_length=255)),
("filters", models.JSONField(default=dict)),
],
options={
"verbose_name": "Widget",
"verbose_name_plural": "Widgets",
"db_table": "widgets",
"ordering": ("-created_at",),
},
),
migrations.CreateModel(
name="DashboardWidget",
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,
),
),
("is_visible", models.BooleanField(default=True)),
("sort_order", models.FloatField(default=65535)),
("filters", models.JSONField(default=dict)),
("properties", models.JSONField(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",
),
),
(
"dashboard",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="dashboard_widgets",
to="db.dashboard",
),
),
(
"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",
),
),
(
"widget",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="dashboard_widgets",
to="db.widget",
),
),
],
options={
"verbose_name": "Dashboard Widget",
"verbose_name_plural": "Dashboard Widgets",
"db_table": "dashboard_widgets",
"ordering": ("-created_at",),
"unique_together": {("widget", "dashboard")},
},
),
]
@@ -0,0 +1,99 @@
# Generated by Django 4.2.7 on 2024-01-08 06:48
from django.db import migrations
def create_widgets(apps, schema_editor):
Widget = apps.get_model("db", "Widget")
widgets_list = [
{"key": "overview_stats", "filters": {}},
{
"key": "assigned_issues",
"filters": {
"duration": "this_week",
"tab": "upcoming",
},
},
{
"key": "created_issues",
"filters": {
"duration": "this_week",
"tab": "upcoming",
},
},
{
"key": "issues_by_state_groups",
"filters": {
"duration": "this_week",
},
},
{
"key": "issues_by_priority",
"filters": {
"duration": "this_week",
},
},
{"key": "recent_activity", "filters": {}},
{"key": "recent_projects", "filters": {}},
{"key": "recent_collaborators", "filters": {}},
]
Widget.objects.bulk_create(
[
Widget(
key=widget["key"],
filters=widget["filters"],
)
for widget in widgets_list
],
batch_size=10,
)
def create_dashboards(apps, schema_editor):
Dashboard = apps.get_model("db", "Dashboard")
User = apps.get_model("db", "User")
Dashboard.objects.bulk_create(
[
Dashboard(
name="Home dashboard",
description_html="<p></p>",
identifier=None,
owned_by_id=user_id,
type_identifier="home",
is_default=True,
)
for user_id in User.objects.values_list("id", flat=True)
],
batch_size=2000,
)
def create_dashboard_widgets(apps, schema_editor):
Widget = apps.get_model("db", "Widget")
Dashboard = apps.get_model("db", "Dashboard")
DashboardWidget = apps.get_model("db", "DashboardWidget")
updated_dashboard_widget = [
DashboardWidget(
widget_id=widget_id,
dashboard_id=dashboard_id,
)
for widget_id in Widget.objects.values_list("id", flat=True)
for dashboard_id in Dashboard.objects.values_list("id", flat=True)
]
DashboardWidget.objects.bulk_create(
updated_dashboard_widget, batch_size=2000
)
class Migration(migrations.Migration):
dependencies = [
("db", "0054_dashboard_widget_dashboardwidget"),
]
operations = [
migrations.RunPython(create_widgets),
migrations.RunPython(create_dashboards),
migrations.RunPython(create_dashboard_widgets),
]
@@ -0,0 +1,184 @@
# Generated by Django 4.2.7 on 2024-01-22 08:55
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
("db", "0055_auto_20240108_0648"),
]
operations = [
migrations.CreateModel(
name="UserNotificationPreference",
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,
),
),
("property_change", models.BooleanField(default=True)),
("state_change", models.BooleanField(default=True)),
("comment", models.BooleanField(default=True)),
("mention", models.BooleanField(default=True)),
("issue_completed", models.BooleanField(default=True)),
(
"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_notification_preferences",
to="db.project",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="%(class)s_updated_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Last Modified By",
),
),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="notification_preferences",
to=settings.AUTH_USER_MODEL,
),
),
(
"workspace",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="workspace_notification_preferences",
to="db.workspace",
),
),
],
options={
"verbose_name": "UserNotificationPreference",
"verbose_name_plural": "UserNotificationPreferences",
"db_table": "user_notification_preferences",
"ordering": ("-created_at",),
},
),
migrations.CreateModel(
name="EmailNotificationLog",
fields=[
(
"created_at",
models.DateTimeField(
auto_now_add=True, verbose_name="Created At"
),
),
(
"updated_at",
models.DateTimeField(
auto_now=True, verbose_name="Last Modified At"
),
),
(
"id",
models.UUIDField(
db_index=True,
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
unique=True,
),
),
("entity_identifier", models.UUIDField(null=True)),
("entity_name", models.CharField(max_length=255)),
("data", models.JSONField(null=True)),
("processed_at", models.DateTimeField(null=True)),
("sent_at", models.DateTimeField(null=True)),
("entity", models.CharField(max_length=200)),
(
"old_value",
models.CharField(blank=True, max_length=300, null=True),
),
(
"new_value",
models.CharField(blank=True, max_length=300, null=True),
),
(
"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",
),
),
(
"receiver",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="email_notifications",
to=settings.AUTH_USER_MODEL,
),
),
(
"triggered_by",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="triggered_emails",
to=settings.AUTH_USER_MODEL,
),
),
(
"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",
),
),
],
options={
"verbose_name": "Email Notification Log",
"verbose_name_plural": "Email Notification Logs",
"db_table": "email_notification_logs",
"ordering": ("-created_at",),
},
),
]
@@ -0,0 +1,32 @@
# Generated by Django 4.2.7 on 2024-01-22 09:01
from django.db import migrations
def create_notification_preferences(apps, schema_editor):
UserNotificationPreference = apps.get_model(
"db", "UserNotificationPreference"
)
User = apps.get_model("db", "User")
bulk_notification_preferences = []
for user_id in User.objects.filter(is_bot=False).values_list(
"id", flat=True
):
bulk_notification_preferences.append(
UserNotificationPreference(
user_id=user_id,
created_by_id=user_id,
)
)
UserNotificationPreference.objects.bulk_create(
bulk_notification_preferences, batch_size=1000, ignore_conflicts=True
)
class Migration(migrations.Migration):
dependencies = [
("db", "0056_usernotificationpreference_emailnotificationlog"),
]
operations = [migrations.RunPython(create_notification_preferences)]
@@ -0,0 +1,26 @@
# Generated by Django 4.2.7 on 2024-01-24 18:55
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("db", "0057_auto_20240122_0901"),
]
operations = [
migrations.AlterField(
model_name="moduleissue",
name="issue",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="issue_module",
to="db.issue",
),
),
migrations.AlterUniqueTogether(
name="moduleissue",
unique_together={("issue", "module")},
),
]
@@ -0,0 +1,32 @@
# Generated by Django 4.2.7 on 2024-02-08 09:57
from django.db import migrations
def widgets_filter_change(apps, schema_editor):
Widget = apps.get_model("db", "Widget")
widgets_to_update = []
# Define the filter dictionaries for each widget key
filters_mapping = {
"assigned_issues": {"duration": "none", "tab": "pending"},
"created_issues": {"duration": "none", "tab": "pending"},
"issues_by_state_groups": {"duration": "none"},
"issues_by_priority": {"duration": "none"},
}
# Iterate over widgets and update filters if applicable
for widget in Widget.objects.all():
if widget.key in filters_mapping:
widget.filters = filters_mapping[widget.key]
widgets_to_update.append(widget)
# Bulk update the widgets
Widget.objects.bulk_update(widgets_to_update, ["filters"], batch_size=10)
class Migration(migrations.Migration):
dependencies = [
("db", "0058_alter_moduleissue_issue_and_more"),
]
operations = [migrations.RunPython(widgets_filter_change)]
@@ -0,0 +1,17 @@
# Generated by Django 4.2.7 on 2024-02-08 09:18
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("db", "0059_auto_20240208_0957"),
]
operations = [
migrations.AddField(
model_name="cycle",
name="progress_snapshot",
field=models.JSONField(default=dict),
),
]
@@ -0,0 +1,54 @@
# Generated by Django 4.2.7 on 2024-03-03 16:25
from django.db import migrations, models
class Migration(migrations.Migration):
def update_project_logo_props(apps, schema_editor):
Project = apps.get_model("db", "Project")
bulk_update_project_logo = []
# Iterate through projects and update logo_props
for project in Project.objects.all():
project.logo_props["in_use"] = "emoji" if project.emoji else "icon"
project.logo_props["emoji"] = {
"value": project.emoji if project.emoji else "",
"url": "",
}
project.logo_props["icon"] = {
"name": (
project.icon_prop.get("name", "")
if project.icon_prop
else ""
),
"color": (
project.icon_prop.get("color", "")
if project.icon_prop
else ""
),
}
bulk_update_project_logo.append(project)
# Bulk update logo_props for all projects
Project.objects.bulk_update(
bulk_update_project_logo, ["logo_props"], batch_size=1000
)
dependencies = [
("db", "0060_cycle_progress_snapshot"),
]
operations = [
migrations.AlterField(
model_name="issuelink",
name="url",
field=models.TextField(),
),
migrations.AddField(
model_name="project",
name="logo_props",
field=models.JSONField(default=dict),
),
migrations.RunPython(update_project_logo_props),
]
@@ -0,0 +1,41 @@
# Generated by Django 4.2.7 on 2024-03-19 08:28
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('db', '0061_project_logo_props'),
]
operations = [
migrations.AddField(
model_name="cycle",
name="archived_at",
field=models.DateTimeField(null=True),
),
migrations.AddField(
model_name="module",
name="archived_at",
field=models.DateTimeField(null=True),
),
migrations.AddField(
model_name="project",
name="archived_at",
field=models.DateTimeField(null=True),
),
migrations.AlterField(
model_name="socialloginconnection",
name="medium",
field=models.CharField(
choices=[
("Google", "google"),
("Github", "github"),
("Jira", "jira"),
],
default=None,
max_length=20,
),
),
]
@@ -0,0 +1,44 @@
# Generated by Django 4.2.10 on 2024-04-02 12:18
from django.db import migrations, models
def update_project_state_group(apps, schema_editor):
State = apps.get_model("db", "State")
# Update states in bulk
State.objects.filter(group="backlog", name="Triage").update(
is_triage=True, group="triage"
)
class Migration(migrations.Migration):
dependencies = [
("db", "0062_cycle_archived_at_module_archived_at_and_more"),
]
operations = [
migrations.AddField(
model_name="state",
name="is_triage",
field=models.BooleanField(default=False),
),
migrations.AlterField(
model_name="state",
name="group",
field=models.CharField(
choices=[
("backlog", "Backlog"),
("unstarted", "Unstarted"),
("started", "Started"),
("completed", "Completed"),
("cancelled", "Cancelled"),
("triage", "Triage"),
],
default="backlog",
max_length=20,
),
),
migrations.RunPython(update_project_state_group),
]
@@ -0,0 +1,20 @@
# Generated by Django 4.2.10 on 2024-04-09 11:34
from django.db import migrations, models
import plane.db.models.page
class Migration(migrations.Migration):
dependencies = [
('db', '0063_state_is_triage_alter_state_group'),
]
operations = [
migrations.AddField(
model_name="page",
name="view_props",
field=models.JSONField(
default=plane.db.models.page.get_view_props
),
),
]
@@ -0,0 +1,462 @@
# Generated by Django 4.2.10 on 2024-04-04 08:47
import uuid
import django.db.models.deletion
import django.utils.timezone
from django.conf import settings
from django.db import migrations, models
import plane.db.models.user
def migrate_user_profile(apps, schema_editor):
Profile = apps.get_model("db", "Profile")
User = apps.get_model("db", "User")
Profile.objects.bulk_create(
[
Profile(
user_id=user.get("id"),
theme=user.get("theme"),
is_tour_completed=user.get("is_tour_completed"),
use_case=user.get("use_case"),
is_onboarded=user.get("is_onboarded"),
last_workspace_id=user.get("last_workspace_id"),
billing_address_country=user.get("billing_address_country"),
billing_address=user.get("billing_address"),
has_billing_address=user.get("has_billing_address"),
)
for user in User.objects.values(
"id",
"theme",
"is_tour_completed",
"onboarding_step",
"use_case",
"role",
"is_onboarded",
"last_workspace_id",
"billing_address_country",
"billing_address",
"has_billing_address",
)
],
batch_size=1000,
)
def user_favorite_migration(apps, schema_editor):
# Import the models
CycleFavorite = apps.get_model("db", "CycleFavorite")
ModuleFavorite = apps.get_model("db", "ModuleFavorite")
ProjectFavorite = apps.get_model("db", "ProjectFavorite")
PageFavorite = apps.get_model("db", "PageFavorite")
IssueViewFavorite = apps.get_model("db", "IssueViewFavorite")
UserFavorite = apps.get_model("db", "UserFavorite")
# List of source models
source_models = [
CycleFavorite,
ModuleFavorite,
ProjectFavorite,
PageFavorite,
IssueViewFavorite,
]
entity_mapper = {
"CycleFavorite": "cycle",
"ModuleFavorite": "module",
"ProjectFavorite": "project",
"PageFavorite": "page",
"IssueViewFavorite": "view",
}
for source_model in source_models:
entity_type = entity_mapper[source_model.__name__]
UserFavorite.objects.bulk_create(
[
UserFavorite(
user_id=obj.user_id,
entity_type=entity_type,
entity_identifier=str(getattr(obj, entity_type).id),
project_id=obj.project_id,
workspace_id=obj.workspace_id,
created_by_id=obj.created_by_id,
updated_by_id=obj.updated_by_id,
)
for obj in source_model.objects.all().iterator()
],
batch_size=1000,
)
class Migration(migrations.Migration):
dependencies = [
("db", "0064_auto_20240409_1134"),
]
operations = [
migrations.AlterField(
model_name="user",
name="avatar",
field=models.TextField(blank=True),
),
migrations.CreateModel(
name="Session",
fields=[
(
"session_data",
models.TextField(verbose_name="session data"),
),
(
"expire_date",
models.DateTimeField(
db_index=True, verbose_name="expire date"
),
),
(
"device_info",
models.JSONField(blank=True, default=None, null=True),
),
(
"session_key",
models.CharField(
max_length=128, primary_key=True, serialize=False
),
),
("user_id", models.CharField(max_length=50, null=True)),
],
options={
"verbose_name": "session",
"verbose_name_plural": "sessions",
"db_table": "sessions",
"abstract": False,
},
),
migrations.CreateModel(
name="Profile",
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,
),
),
("theme", models.JSONField(default=dict)),
("is_tour_completed", models.BooleanField(default=False)),
(
"onboarding_step",
models.JSONField(
default=plane.db.models.user.get_default_onboarding
),
),
("use_case", models.TextField(blank=True, null=True)),
(
"role",
models.CharField(blank=True, max_length=300, null=True),
),
("is_onboarded", models.BooleanField(default=False)),
("last_workspace_id", models.UUIDField(null=True)),
(
"billing_address_country",
models.CharField(default="INDIA", max_length=255),
),
("billing_address", models.JSONField(null=True)),
("has_billing_address", models.BooleanField(default=False)),
("company_name", models.CharField(blank=True, max_length=255)),
(
"user",
models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE,
related_name="profile",
to=settings.AUTH_USER_MODEL,
),
),
],
options={
"verbose_name": "Profile",
"verbose_name_plural": "Profiles",
"db_table": "profiles",
"ordering": ("-created_at",),
},
),
migrations.CreateModel(
name="Account",
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,
),
),
("provider_account_id", models.CharField(max_length=255)),
(
"provider",
models.CharField(
choices=[("google", "Google"), ("github", "Github")]
),
),
("access_token", models.TextField()),
("access_token_expired_at", models.DateTimeField(null=True)),
("refresh_token", models.TextField(blank=True, null=True)),
("refresh_token_expired_at", models.DateTimeField(null=True)),
(
"last_connected_at",
models.DateTimeField(default=django.utils.timezone.now),
),
("metadata", models.JSONField(default=dict)),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="accounts",
to=settings.AUTH_USER_MODEL,
),
),
],
options={
"verbose_name": "Account",
"verbose_name_plural": "Accounts",
"db_table": "accounts",
"ordering": ("-created_at",),
"unique_together": {("provider", "provider_account_id")},
},
),
migrations.RunPython(migrate_user_profile),
migrations.RemoveField(
model_name="user",
name="billing_address",
),
migrations.RemoveField(
model_name="user",
name="billing_address_country",
),
migrations.RemoveField(
model_name="user",
name="has_billing_address",
),
migrations.RemoveField(
model_name="user",
name="is_onboarded",
),
migrations.RemoveField(
model_name="user",
name="is_tour_completed",
),
migrations.RemoveField(
model_name="user",
name="last_workspace_id",
),
migrations.RemoveField(
model_name="user",
name="my_issues_prop",
),
migrations.RemoveField(
model_name="user",
name="onboarding_step",
),
migrations.RemoveField(
model_name="user",
name="role",
),
migrations.RemoveField(
model_name="user",
name="theme",
),
migrations.RemoveField(
model_name="user",
name="use_case",
),
migrations.AddField(
model_name="globalview",
name="logo_props",
field=models.JSONField(default=dict),
),
# Pages
migrations.AddField(
model_name="page",
name="logo_props",
field=models.JSONField(default=dict),
),
migrations.AddField(
model_name="page",
name="description_binary",
field=models.BinaryField(null=True),
),
migrations.AlterField(
model_name="page",
name="name",
field=models.CharField(blank=True, max_length=255),
),
# Estimates
migrations.AddField(
model_name="estimate",
name="type",
field=models.CharField(default="Categories", max_length=255),
),
migrations.AlterField(
model_name="estimatepoint",
name="key",
field=models.IntegerField(
default=0,
validators=[
django.core.validators.MinValueValidator(0),
django.core.validators.MaxValueValidator(12),
],
),
),
migrations.AlterField(
model_name="issue",
name="estimate_point",
field=models.IntegerField(
blank=True,
null=True,
validators=[
django.core.validators.MinValueValidator(0),
django.core.validators.MaxValueValidator(12),
],
),
),
# workspace user properties
migrations.AlterModelTable(
name="workspaceuserproperties",
table="workspace_user_properties",
),
# Favorites
migrations.CreateModel(
name="UserFavorite",
fields=[
(
"created_at",
models.DateTimeField(
auto_now_add=True, verbose_name="Created At"
),
),
(
"updated_at",
models.DateTimeField(
auto_now=True, verbose_name="Last Modified At"
),
),
(
"id",
models.UUIDField(
db_index=True,
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
unique=True,
),
),
("entity_type", models.CharField(max_length=100)),
("entity_identifier", models.UUIDField(blank=True, null=True)),
(
"name",
models.CharField(blank=True, max_length=255, null=True),
),
("is_folder", models.BooleanField(default=False)),
("sequence", models.IntegerField(default=65535)),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="%(class)s_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"parent",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="parent_folder",
to="db.userfavorite",
),
),
(
"project",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="project_%(class)s",
to="db.project",
),
),
(
"updated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="%(class)s_updated_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Last Modified By",
),
),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="favorites",
to=settings.AUTH_USER_MODEL,
),
),
(
"workspace",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="workspace_%(class)s",
to="db.workspace",
),
),
],
options={
"verbose_name": "User Favorite",
"verbose_name_plural": "User Favorites",
"db_table": "user_favorites",
"ordering": ("-created_at",),
"unique_together": {
("entity_type", "user", "entity_identifier")
},
},
),
migrations.RunPython(user_favorite_migration),
]
@@ -0,0 +1,58 @@
# Generated by Django 4.2.11 on 2024-05-22 15:04
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("db", "0065_auto_20240415_0937"),
]
operations = [
migrations.AddField(
model_name="account",
name="id_token",
field=models.TextField(blank=True),
),
migrations.AddField(
model_name="cycle",
name="logo_props",
field=models.JSONField(default=dict),
),
migrations.AddField(
model_name="module",
name="logo_props",
field=models.JSONField(default=dict),
),
migrations.AddField(
model_name="issueview",
name="logo_props",
field=models.JSONField(default=dict),
),
migrations.AddField(
model_name="inbox",
name="logo_props",
field=models.JSONField(default=dict),
),
migrations.AddField(
model_name="dashboard",
name="logo_props",
field=models.JSONField(default=dict),
),
migrations.AddField(
model_name="widget",
name="logo_props",
field=models.JSONField(default=dict),
),
migrations.AddField(
model_name="issue",
name="description_binary",
field=models.BinaryField(null=True),
),
migrations.AddField(
model_name="team",
name="logo_props",
field=models.JSONField(default=dict),
),
]
@@ -0,0 +1,260 @@
# # Generated by Django 4.2.7 on 2024-05-24 09:47
# Python imports
import uuid
from uuid import uuid4
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
import plane.db.models.deploy_board
def issue_estimate_point(apps, schema_editor):
Issue = apps.get_model("db", "Issue")
Project = apps.get_model("db", "Project")
EstimatePoint = apps.get_model("db", "EstimatePoint")
IssueActivity = apps.get_model("db", "IssueActivity")
updated_estimate_point = []
updated_issue_activity = []
# loop through all the projects
for project in Project.objects.filter(estimate__isnull=False):
estimate_points = EstimatePoint.objects.filter(
estimate=project.estimate, project=project
)
for issue_activity in IssueActivity.objects.filter(
field="estimate_point", project=project
):
if issue_activity.new_value:
new_identifier = estimate_points.filter(
key=issue_activity.new_value
).first().id
issue_activity.new_identifier = new_identifier
new_value = estimate_points.filter(
key=issue_activity.new_value
).first().value
issue_activity.new_value = new_value
if issue_activity.old_value:
old_identifier = estimate_points.filter(
key=issue_activity.old_value
).first().id
issue_activity.old_identifier = old_identifier
old_value = estimate_points.filter(
key=issue_activity.old_value
).first().value
issue_activity.old_value = old_value
updated_issue_activity.append(issue_activity)
for issue in Issue.objects.filter(
point__isnull=False, project=project
):
# get the estimate id for the corresponding estimate point in the issue
estimate = estimate_points.filter(key=issue.point).first()
issue.estimate_point = estimate
updated_estimate_point.append(issue)
Issue.objects.bulk_update(
updated_estimate_point, ["estimate_point"], batch_size=1000
)
IssueActivity.objects.bulk_update(
updated_issue_activity,
["new_value", "old_value", "new_identifier", "old_identifier"],
batch_size=1000,
)
def last_used_estimate(apps, schema_editor):
Project = apps.get_model("db", "Project")
Estimate = apps.get_model("db", "Estimate")
# Get all estimate ids used in projects
estimate_ids = Project.objects.filter(estimate__isnull=False).values_list(
"estimate", flat=True
)
# Update all matching estimates
Estimate.objects.filter(id__in=estimate_ids).update(last_used=True)
def populate_deploy_board(apps, schema_editor):
DeployBoard = apps.get_model("db", "DeployBoard")
ProjectDeployBoard = apps.get_model("db", "ProjectDeployBoard")
DeployBoard.objects.bulk_create(
[
DeployBoard(
entity_identifier=deploy_board.project_id,
project_id=deploy_board.project_id,
entity_name="project",
anchor=uuid4().hex,
is_comments_enabled=deploy_board.comments,
is_reactions_enabled=deploy_board.reactions,
inbox=deploy_board.inbox,
is_votes_enabled=deploy_board.votes,
view_props=deploy_board.views,
workspace_id=deploy_board.workspace_id,
created_at=deploy_board.created_at,
updated_at=deploy_board.updated_at,
created_by_id=deploy_board.created_by_id,
updated_by_id=deploy_board.updated_by_id,
)
for deploy_board in ProjectDeployBoard.objects.all()
],
batch_size=100,
)
class Migration(migrations.Migration):
dependencies = [
("db", "0066_account_id_token_cycle_logo_props_module_logo_props"),
]
operations = [
migrations.CreateModel(
name="DeployBoard",
fields=[
(
"created_at",
models.DateTimeField(
auto_now_add=True, verbose_name="Created At"
),
),
(
"updated_at",
models.DateTimeField(
auto_now=True, verbose_name="Last Modified At"
),
),
(
"id",
models.UUIDField(
db_index=True,
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
unique=True,
),
),
("entity_identifier", models.UUIDField(null=True)),
(
"entity_name",
models.CharField(
choices=[
("project", "Project"),
("issue", "Issue"),
("module", "Module"),
("cycle", "Task"),
("page", "Page"),
("view", "View"),
],
max_length=30,
),
),
(
"anchor",
models.CharField(
db_index=True,
default=plane.db.models.deploy_board.get_anchor,
max_length=255,
unique=True,
),
),
("is_comments_enabled", models.BooleanField(default=False)),
("is_reactions_enabled", models.BooleanField(default=False)),
("is_votes_enabled", models.BooleanField(default=False)),
("view_props", models.JSONField(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",
),
),
(
"inbox",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="board_inbox",
to="db.inbox",
),
),
(
"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": "Deploy Board",
"verbose_name_plural": "Deploy Boards",
"db_table": "deploy_boards",
"ordering": ("-created_at",),
"unique_together": {("entity_name", "entity_identifier")},
},
),
migrations.AddField(
model_name="estimate",
name="last_used",
field=models.BooleanField(default=False),
),
# Rename the existing field
migrations.RenameField(
model_name="issue",
old_name="estimate_point",
new_name="point",
),
# Add a new field with the original name as a foreign key
migrations.AddField(
model_name="issue",
name="estimate_point",
field=models.ForeignKey(
on_delete=django.db.models.deletion.SET_NULL,
related_name="issue_estimates",
to="db.EstimatePoint",
blank=True,
null=True,
),
),
migrations.AlterField(
model_name="estimate",
name="type",
field=models.CharField(default="categories", max_length=255),
),
migrations.AlterField(
model_name="estimatepoint",
name="value",
field=models.CharField(max_length=255),
),
migrations.RunPython(issue_estimate_point),
migrations.RunPython(last_used_estimate),
migrations.RunPython(populate_deploy_board),
]
@@ -0,0 +1,257 @@
# Generated by Django 4.2.11 on 2024-06-07 12:04
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import uuid
def migrate_pages(apps, schema_editor):
ProjectPage = apps.get_model("db", "ProjectPage")
Page = apps.get_model("db", "Page")
ProjectPage.objects.bulk_create(
[
ProjectPage(
workspace_id=page.get("workspace_id"),
project_id=page.get("project_id"),
page_id=page.get("id"),
created_by_id=page.get("created_by_id"),
updated_by_id=page.get("updated_by_id"),
)
for page in Page.objects.values(
"workspace_id",
"project_id",
"id",
"created_by_id",
"updated_by_id",
)
],
batch_size=1000,
)
class Migration(migrations.Migration):
dependencies = [
("db", "0067_issue_estimate"),
]
operations = [
migrations.AddField(
model_name="page",
name="is_global",
field=models.BooleanField(default=False),
),
migrations.CreateModel(
name="ProjectPage",
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,
),
),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="%(class)s_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"page",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_pages",
to="db.page",
),
),
(
"project",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_pages",
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="project_pages",
to="db.workspace",
),
),
],
options={
"verbose_name": "Project Page",
"verbose_name_plural": "Project Pages",
"db_table": "project_pages",
"ordering": ("-created_at",),
"unique_together": {("project", "page")},
},
),
migrations.CreateModel(
name="TeamPage",
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,
),
),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="%(class)s_created_by",
to=settings.AUTH_USER_MODEL,
verbose_name="Created By",
),
),
(
"page",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="team_pages",
to="db.page",
),
),
(
"team",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="team_pages",
to="db.team",
),
),
(
"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="team_pages",
to="db.workspace",
),
),
],
options={
"verbose_name": "Team Page",
"verbose_name_plural": "Team Pages",
"db_table": "team_pages",
"ordering": ("-created_at",),
"unique_together": {("team", "page")},
},
),
migrations.AddField(
model_name="page",
name="projects",
field=models.ManyToManyField(
related_name="pages", through="db.ProjectPage", to="db.project"
),
),
migrations.AddField(
model_name="page",
name="teams",
field=models.ManyToManyField(
related_name="pages", through="db.TeamPage", to="db.team"
),
),
migrations.RunPython(migrate_pages),
migrations.RemoveField(
model_name="page",
name="project",
),
migrations.AlterField(
model_name="page",
name="workspace",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="pages",
to="db.workspace",
),
),
migrations.RemoveField(
model_name="pagelabel",
name="project",
),
migrations.RemoveField(
model_name="pagelog",
name="project",
),
migrations.AlterField(
model_name="pagelabel",
name="workspace",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="workspace_page_label",
to="db.workspace",
),
),
migrations.AlterField(
model_name="pagelog",
name="workspace",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="workspace_page_log",
to="db.workspace",
),
),
]
@@ -0,0 +1,73 @@
# Generated by Django 4.2.11 on 2024-06-03 17:16
from django.db import migrations, models
from django.conf import settings
from django.db.models import F
import django.db.models.deletion
def populate_views_owned_by(apps, schema_editor):
IssueView = apps.get_model("db", "IssueView")
# update all existing views to be owned by the user who created them
IssueView.objects.update(owned_by_id=F("created_by_id"))
class Migration(migrations.Migration):
dependencies = [
('db', '0068_remove_pagelabel_project_remove_pagelog_project_and_more'),
]
operations = [
migrations.AlterField(
model_name="account",
name="provider",
field=models.CharField(
choices=[
("google", "Google"),
("github", "Github"),
("gitlab", "GitLab"),
]
),
),
migrations.AlterField(
model_name="socialloginconnection",
name="medium",
field=models.CharField(
choices=[
("Google", "google"),
("Github", "github"),
("GitLab", "gitlab"),
("Jira", "jira"),
],
default=None,
max_length=20,
),
),
migrations.AddField(
model_name="issueview",
name="is_locked",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="issueview",
name="owned_by",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="views",
to=settings.AUTH_USER_MODEL,
null=True,
),
),
migrations.RunPython(populate_views_owned_by),
migrations.AlterField(
model_name="issueview",
name="owned_by",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="views",
to=settings.AUTH_USER_MODEL,
),
),
]
@@ -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'),
),
]
@@ -0,0 +1,44 @@
# Generated by Django 4.2.11 on 2024-07-15 06:07
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("db", "0070_apitoken_is_service_exporterhistory_filters_and_more"),
]
operations = [
migrations.RenameModel(
old_name="IssueProperty",
new_name="IssueUserProperty",
),
migrations.AlterModelOptions(
name="issueuserproperty",
options={
"ordering": ("-created_at",),
"verbose_name": "Issue User Property",
"verbose_name_plural": "Issue User Properties",
},
),
migrations.AlterModelTable(
name="issueuserproperty",
table="issue_user_properties",
),
migrations.AddField(
model_name="issuetype",
name="is_active",
field=models.BooleanField(default=True),
),
migrations.AddField(
model_name="project",
name="is_issue_type_enabled",
field=models.BooleanField(default=False),
),
migrations.AlterField(
model_name="issuetype",
name="is_default",
field=models.BooleanField(default=False),
),
]
@@ -0,0 +1,145 @@
# Generated by Django 4.2.14 on 2024-07-22 13:22
from django.db import migrations, models
from django.conf import settings
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
("db", "0071_rename_issueproperty_issueuserproperty_and_more"),
]
operations = [
migrations.AddField(
model_name="issueattachment",
name="external_id",
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name="issueattachment",
name="external_source",
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.CreateModel(
name="UserRecentVisit",
fields=[
(
"created_at",
models.DateTimeField(
auto_now_add=True, verbose_name="Created At"
),
),
(
"updated_at",
models.DateTimeField(
auto_now=True, verbose_name="Last Modified At"
),
),
(
"id",
models.UUIDField(
db_index=True,
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
unique=True,
),
),
("entity_identifier", models.UUIDField(null=True)),
(
"entity_name",
models.CharField(
choices=[
("VIEW", "View"),
("PAGE", "Page"),
("ISSUE", "Issue"),
("CYCLE", "Cycle"),
("MODULE", "Module"),
("PROJECT", "Project"),
],
max_length=30,
),
),
("visited_at", models.DateTimeField(auto_now=True)),
(
"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",
),
),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="user_recent_visit",
to=settings.AUTH_USER_MODEL,
),
),
(
"workspace",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="workspace_%(class)s",
to="db.workspace",
),
),
],
options={
"verbose_name": "User Recent Visit",
"verbose_name_plural": "User Recent Visits",
"db_table": "user_recent_visits",
"ordering": ("-created_at",),
},
),
migrations.RemoveField(
model_name="project",
name="start_date",
),
migrations.RemoveField(
model_name="project",
name="target_date",
),
migrations.AlterField(
model_name="issuesequence",
name="sequence",
field=models.PositiveBigIntegerField(db_index=True, default=1),
),
migrations.AlterField(
model_name="project",
name="identifier",
field=models.CharField(
db_index=True, max_length=12, verbose_name="Project Identifier"
),
),
migrations.AlterField(
model_name="projectidentifier",
name="name",
field=models.CharField(db_index=True, max_length=12),
),
]
@@ -0,0 +1,203 @@
# Generated by Django 4.2.11 on 2024-08-13 16:21
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
("db", "0073_alter_commentreaction_unique_together_and_more"),
]
operations = [
migrations.AddField(
model_name="deployboard",
name="is_activity_enabled",
field=models.BooleanField(default=True),
),
migrations.AddField(
model_name="fileasset",
name="is_archived",
field=models.BooleanField(default=False),
),
migrations.AlterField(
model_name="userfavorite",
name="sequence",
field=models.FloatField(default=65535),
),
migrations.CreateModel(
name="ProjectIssueType",
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"
),
),
(
"deleted_at",
models.DateTimeField(
blank=True, null=True, verbose_name="Deleted At"
),
),
(
"id",
models.UUIDField(
db_index=True,
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
unique=True,
),
),
("level", models.PositiveIntegerField(default=0)),
("is_default", models.BooleanField(default=False)),
],
options={
"verbose_name": "Project Issue Type",
"verbose_name_plural": "Project Issue Types",
"db_table": "project_issue_types",
"ordering": ("project", "issue_type"),
},
),
migrations.AlterModelOptions(
name="issuetype",
options={
"verbose_name": "Issue Type",
"verbose_name_plural": "Issue Types",
},
),
migrations.RemoveConstraint(
model_name="issuetype",
name="issue_type_unique_name_project_when_deleted_at_null",
),
migrations.AlterUniqueTogether(
name="issuetype",
unique_together=set(),
),
migrations.AlterField(
model_name="issuetype",
name="workspace",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="issue_types",
to="db.workspace",
),
),
migrations.AlterUniqueTogether(
name="issuetype",
unique_together={("workspace", "name", "deleted_at")},
),
migrations.AddConstraint(
model_name="issuetype",
constraint=models.UniqueConstraint(
condition=models.Q(("deleted_at__isnull", True)),
fields=("name", "workspace"),
name="issue_type_unique_name_workspace_when_deleted_at_null",
),
),
migrations.AddField(
model_name="projectissuetype",
name="created_by",
field=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",
),
),
migrations.AddField(
model_name="projectissuetype",
name="issue_type",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_issue_types",
to="db.issuetype",
),
),
migrations.AddField(
model_name="projectissuetype",
name="project",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="project_%(class)s",
to="db.project",
),
),
migrations.AddField(
model_name="projectissuetype",
name="updated_by",
field=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",
),
),
migrations.AddField(
model_name="projectissuetype",
name="workspace",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="workspace_%(class)s",
to="db.workspace",
),
),
migrations.RemoveField(
model_name="issuetype",
name="is_default",
),
migrations.RemoveField(
model_name="issuetype",
name="project",
),
migrations.RemoveField(
model_name="issuetype",
name="sort_order",
),
migrations.RemoveField(
model_name="issuetype",
name="weight",
),
migrations.AddConstraint(
model_name="projectissuetype",
constraint=models.UniqueConstraint(
condition=models.Q(("deleted_at__isnull", True)),
fields=("project", "issue_type"),
name="project_issue_type_unique_project_issue_type_when_deleted_at_null",
),
),
migrations.AlterUniqueTogether(
name="projectissuetype",
unique_together={("project", "issue_type", "deleted_at")},
),
migrations.AddField(
model_name="issuetype",
name="is_default",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="issuetype",
name="level",
field=models.PositiveIntegerField(default=0),
),
migrations.AlterUniqueTogether(
name="issuetype",
unique_together=set(),
),
migrations.RemoveConstraint(
model_name="issuetype",
name="issue_type_unique_name_workspace_when_deleted_at_null",
),
]
@@ -0,0 +1,28 @@
# Generated by Django 4.2.11 on 2024-08-29 09:40
import django.core.validators
from django.db import migrations, models
import plane.db.models.asset
class Migration(migrations.Migration):
dependencies = [
("db", "0074_deploy_board_and_project_issues"),
]
operations = [
migrations.AlterField(
model_name="fileasset",
name="asset",
field=models.FileField(
upload_to=plane.db.models.asset.get_upload_path,
validators=[
django.core.validators.FileExtensionValidator(
allowed_extensions=["jpg", "jpeg", "png"]
),
plane.db.models.asset.file_size,
],
),
),
]
@@ -0,0 +1,60 @@
# Generated by Django 4.2.15 on 2024-08-30 07:34
from django.db import migrations, models
def update_workspace_project_member_role(apps, schema_editor):
WorkspaceMember = apps.get_model("db", "WorkspaceMember")
ProjectMember = apps.get_model("db", "ProjectMember")
# update all existing members with role 10 to role 5
WorkspaceMember.objects.filter(role=10).update(role=5)
ProjectMember.objects.filter(role=10).update(role=5)
class Migration(migrations.Migration):
dependencies = [
("db", "0075_alter_fileasset_asset"),
]
operations = [
migrations.AlterField(
model_name="projectmember",
name="role",
field=models.PositiveSmallIntegerField(
choices=[(20, "Admin"), (15, "Member"), (5, "Guest")],
default=5,
),
),
migrations.AlterField(
model_name="projectmemberinvite",
name="role",
field=models.PositiveSmallIntegerField(
choices=[(20, "Admin"), (15, "Member"), (5, "Guest")],
default=5,
),
),
migrations.AlterField(
model_name="workspacemember",
name="role",
field=models.PositiveSmallIntegerField(
choices=[(20, "Admin"), (15, "Member"), (5, "Guest")],
default=5,
),
),
migrations.AlterField(
model_name="workspacememberinvite",
name="role",
field=models.PositiveSmallIntegerField(
choices=[(20, "Admin"), (15, "Member"), (5, "Guest")],
default=5,
),
),
migrations.AddField(
model_name="project",
name="guest_view_all_features",
field=models.BooleanField(default=False),
),
migrations.RunPython(update_workspace_project_member_role),
]
@@ -0,0 +1,179 @@
# Generated by Django 4.2.15 on 2024-10-09 06:19
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import plane.db.models.asset
class Migration(migrations.Migration):
dependencies = [
(
"db",
"0077_draftissue_cycle_user_timezone_project_user_timezone_and_more",
),
]
operations = [
migrations.AddField(
model_name="fileasset",
name="comment",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="assets",
to="db.issuecomment",
),
),
migrations.AddField(
model_name="fileasset",
name="entity_type",
field=models.CharField(
blank=True,
choices=[
("ISSUE_ATTACHMENT", "Issue Attachment"),
("ISSUE_DESCRIPTION", "Issue Description"),
("COMMENT_DESCRIPTION", "Comment Description"),
("PAGE_DESCRIPTION", "Page Description"),
("USER_COVER", "User Cover"),
("USER_AVATAR", "User Avatar"),
("WORKSPACE_LOGO", "Workspace Logo"),
("PROJECT_COVER", "Project Cover"),
],
max_length=255,
null=True,
),
),
migrations.AddField(
model_name="fileasset",
name="external_id",
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name="fileasset",
name="external_source",
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name="fileasset",
name="is_uploaded",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="fileasset",
name="issue",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="assets",
to="db.issue",
),
),
migrations.AddField(
model_name="fileasset",
name="page",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="assets",
to="db.page",
),
),
migrations.AddField(
model_name="fileasset",
name="project",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="assets",
to="db.project",
),
),
migrations.AddField(
model_name="fileasset",
name="size",
field=models.FloatField(default=0),
),
migrations.AddField(
model_name="fileasset",
name="storage_metadata",
field=models.JSONField(blank=True, default=dict, null=True),
),
migrations.AddField(
model_name="fileasset",
name="user",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="assets",
to=settings.AUTH_USER_MODEL,
),
),
migrations.AddField(
model_name="project",
name="cover_image_asset",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="project_cover_image",
to="db.fileasset",
),
),
migrations.AddField(
model_name="user",
name="avatar_asset",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="user_avatar",
to="db.fileasset",
),
),
migrations.AddField(
model_name="user",
name="cover_image_asset",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="user_cover_image",
to="db.fileasset",
),
),
migrations.AddField(
model_name="workspace",
name="logo_asset",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="workspace_logo",
to="db.fileasset",
),
),
migrations.AlterField(
model_name="fileasset",
name="asset",
field=models.FileField(
max_length=800, upload_to=plane.db.models.asset.get_upload_path
),
),
migrations.AlterField(
model_name="integration",
name="avatar_url",
field=models.TextField(blank=True, null=True),
),
migrations.AlterField(
model_name="project",
name="cover_image",
field=models.TextField(blank=True, null=True),
),
migrations.AlterField(
model_name="workspace",
name="logo",
field=models.TextField(blank=True, null=True, verbose_name="Logo"),
),
]
@@ -0,0 +1,64 @@
# Generated by Django 4.2.15 on 2024-10-09 06:19
from django.db import migrations
def move_attachment_to_fileasset(apps, schema_editor):
FileAsset = apps.get_model("db", "FileAsset")
IssueAttachment = apps.get_model("db", "IssueAttachment")
bulk_issue_attachment = []
for issue_attachment in IssueAttachment.objects.values(
"issue_id",
"project_id",
"workspace_id",
"asset",
"attributes",
"external_source",
"external_id",
"deleted_at",
"created_by_id",
"updated_by_id",
):
bulk_issue_attachment.append(
FileAsset(
issue_id=issue_attachment["issue_id"],
entity_type="ISSUE_ATTACHMENT",
project_id=issue_attachment["project_id"],
workspace_id=issue_attachment["workspace_id"],
attributes=issue_attachment["attributes"],
asset=issue_attachment["asset"],
external_source=issue_attachment["external_source"],
external_id=issue_attachment["external_id"],
deleted_at=issue_attachment["deleted_at"],
created_by_id=issue_attachment["created_by_id"],
updated_by_id=issue_attachment["updated_by_id"],
size=issue_attachment["attributes"].get("size", 0),
)
)
FileAsset.objects.bulk_create(bulk_issue_attachment, batch_size=1000)
def mark_existing_file_uploads(apps, schema_editor):
FileAsset = apps.get_model("db", "FileAsset")
# Mark all existing file uploads as uploaded
FileAsset.objects.update(is_uploaded=True)
class Migration(migrations.Migration):
dependencies = [
("db", "0078_fileasset_comment_fileasset_entity_type_and_more"),
]
operations = [
migrations.RunPython(
move_attachment_to_fileasset,
reverse_code=migrations.RunPython.noop,
),
migrations.RunPython(
mark_existing_file_uploads,
reverse_code=migrations.RunPython.noop,
),
]
@@ -0,0 +1,45 @@
# Generated by Django 4.2.15 on 2024-10-12 18:45
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("db", "0079_auto_20241009_0619"),
]
operations = [
migrations.AddField(
model_name="fileasset",
name="draft_issue",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="assets",
to="db.draftissue",
),
),
migrations.AlterField(
model_name="fileasset",
name="entity_type",
field=models.CharField(
blank=True,
choices=[
("ISSUE_ATTACHMENT", "Issue Attachment"),
("ISSUE_DESCRIPTION", "Issue Description"),
("COMMENT_DESCRIPTION", "Comment Description"),
("PAGE_DESCRIPTION", "Page Description"),
("USER_COVER", "User Cover"),
("USER_AVATAR", "User Avatar"),
("WORKSPACE_LOGO", "Workspace Logo"),
("PROJECT_COVER", "Project Cover"),
("DRAFT_ISSUE_ATTACHMENT", "Draft Issue Attachment"),
("DRAFT_ISSUE_DESCRIPTION", "Draft Issue Description"),
],
max_length=255,
null=True,
),
),
]

Some files were not shown because too many files have changed in this diff Show More