Skip to content
Merged
57 changes: 57 additions & 0 deletions apps/api/plane/db/migrations/0113_webhook_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Generated by Django 4.2.26 on 2025-12-15 10:29

from django.db import migrations, models
import plane.db.models.workspace


def get_default_product_tour():
return {
"work_items": True,
"cycles": True,
"modules": True,
"intake": True,
"pages": True,
}


def populate_product_tour(apps, _schema_editor):
WorkspaceUserProperties = apps.get_model('db', 'WorkspaceUserProperties')
default_value = get_default_product_tour()
# Use bulk update for better performance
WorkspaceUserProperties.objects.all().update(product_tour=default_value)


class Migration(migrations.Migration):

dependencies = [
('db', '0112_auto_20251124_0603'),
]

operations = [
migrations.AddField(
model_name='webhook',
name='version',
field=models.CharField(default='v1', max_length=50),
),
migrations.AddField(
model_name='profile',
name='is_navigation_tour_completed',
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='workspaceuserproperties',
name='product_tour',
field=models.JSONField(default=plane.db.models.workspace.get_default_product_tour),
),
migrations.AddField(
model_name='apitoken',
name='allowed_rate_limit',
field=models.CharField(default='60/min', max_length=255),
),
migrations.AddField(
model_name='profile',
name='is_subscribed_to_changelog',
field=models.BooleanField(default=False),
),
migrations.RunPython(populate_product_tour, reverse_code=migrations.RunPython.noop),
]
1 change: 1 addition & 0 deletions apps/api/plane/db/models/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class APIToken(BaseModel):
workspace = models.ForeignKey("db.Workspace", related_name="api_tokens", on_delete=models.CASCADE, null=True)
expired_at = models.DateTimeField(blank=True, null=True)
is_service = models.BooleanField(default=False)
allowed_rate_limit = models.CharField(max_length=255, default="60/min")

class Meta:
verbose_name = "API Token"
Expand Down
4 changes: 4 additions & 0 deletions apps/api/plane/db/models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,8 +233,12 @@ class Profile(TimeAuditModel):
goals = models.JSONField(default=dict)
background_color = models.CharField(max_length=255, default=get_random_color)

# navigation tour
is_navigation_tour_completed = models.BooleanField(default=False)

# marketing
has_marketing_email_consent = models.BooleanField(default=False)
is_subscribed_to_changelog = models.BooleanField(default=False)

class Meta:
verbose_name = "Profile"
Expand Down
1 change: 1 addition & 0 deletions apps/api/plane/db/models/webhook.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class Webhook(BaseModel):
cycle = models.BooleanField(default=False)
issue_comment = models.BooleanField(default=False)
is_internal = models.BooleanField(default=False)
version = models.CharField(default="v1", max_length=50)

def __str__(self):
return f"{self.workspace.slug} {self.url}"
Expand Down
11 changes: 11 additions & 0 deletions apps/api/plane/db/models/workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,16 @@ def slug_validator(value):
raise ValidationError("Slug is not valid")


def get_default_product_tour():
return {
"work_items": False,
"cycles": False,
"modules": False,
"intake": False,
"pages": False,
}


class Workspace(BaseModel):
TIMEZONE_CHOICES = tuple(zip(pytz.common_timezones, pytz.common_timezones))

Expand Down Expand Up @@ -325,6 +335,7 @@ class NavigationControlPreference(models.TextChoices):
choices=NavigationControlPreference.choices,
default=NavigationControlPreference.ACCORDION,
)
product_tour = models.JSONField(default=get_default_product_tour)

class Meta:
unique_together = ["workspace", "user", "deleted_at"]
Expand Down
Loading