mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
dev: sites and workspaces
This commit is contained in:
parent
ccf87cc478
commit
afc2d5a235
@ -257,4 +257,87 @@ class Migration(migrations.Migration):
|
|||||||
model_name="user",
|
model_name="user",
|
||||||
name="use_case",
|
name="use_case",
|
||||||
),
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="Site",
|
||||||
|
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=80)),
|
||||||
|
("description", models.TextField(blank=True)),
|
||||||
|
("use_case", models.TextField(blank=True)),
|
||||||
|
("domain", models.TextField(blank=True)),
|
||||||
|
("user_count", models.IntegerField(default=1)),
|
||||||
|
(
|
||||||
|
"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",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"owner",
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="sites",
|
||||||
|
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={
|
||||||
|
"abstract": False,
|
||||||
|
"verbose_name": "Site",
|
||||||
|
"verbose_name_plural": "Sites",
|
||||||
|
"db_table": "sites",
|
||||||
|
"ordering": ("-created_at",),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="workspace",
|
||||||
|
name="site",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="workspaces",
|
||||||
|
to="db.site",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="workspace",
|
||||||
|
name="is_primary",
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
@ -75,6 +75,7 @@ from .workspace import (
|
|||||||
WorkspaceMemberInvite,
|
WorkspaceMemberInvite,
|
||||||
WorkspaceTheme,
|
WorkspaceTheme,
|
||||||
WorkspaceUserProperties,
|
WorkspaceUserProperties,
|
||||||
|
Site,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .importer import Importer
|
from .importer import Importer
|
||||||
|
@ -144,6 +144,12 @@ class Site(BaseModel):
|
|||||||
"""Return name of site"""
|
"""Return name of site"""
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = "Site"
|
||||||
|
verbose_name_plural = "Sites"
|
||||||
|
db_table = "sites"
|
||||||
|
ordering = ("-created_at",)
|
||||||
|
|
||||||
|
|
||||||
class Workspace(BaseModel):
|
class Workspace(BaseModel):
|
||||||
name = models.CharField(max_length=80, verbose_name="Workspace Name")
|
name = models.CharField(max_length=80, verbose_name="Workspace Name")
|
||||||
@ -163,13 +169,24 @@ class Workspace(BaseModel):
|
|||||||
)
|
)
|
||||||
organization_size = models.CharField(max_length=20, blank=True, null=True)
|
organization_size = models.CharField(max_length=20, blank=True, null=True)
|
||||||
site = models.ForeignKey(
|
site = models.ForeignKey(
|
||||||
"db.Site", on_delete=models.CASCADE, related_name="workspaces"
|
"db.Site",
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
related_name="workspaces",
|
||||||
|
null=True,
|
||||||
)
|
)
|
||||||
|
is_primary = models.BooleanField(default=False)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"""Return name of the Workspace"""
|
"""Return name of the Workspace"""
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
if self.is_primary:
|
||||||
|
Workspace.objects.filter(site_id=self.site_id).update(
|
||||||
|
is_primary=False
|
||||||
|
)
|
||||||
|
super(Workspace, self).save(*args, **kwargs)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = "Workspace"
|
verbose_name = "Workspace"
|
||||||
verbose_name_plural = "Workspaces"
|
verbose_name_plural = "Workspaces"
|
||||||
|
@ -16,4 +16,6 @@ from .admin import (
|
|||||||
InstanceAdminSignUpEndpoint,
|
InstanceAdminSignUpEndpoint,
|
||||||
InstanceAdminUserMeEndpoint,
|
InstanceAdminUserMeEndpoint,
|
||||||
InstanceAdminSignOutEndpoint,
|
InstanceAdminSignOutEndpoint,
|
||||||
|
InstanceWorkspacesEndpoint,
|
||||||
|
PrimaryWorkspaceEndpoint,
|
||||||
)
|
)
|
||||||
|
@ -25,7 +25,7 @@ from plane.license.api.serializers import (
|
|||||||
InstanceAdminSerializer,
|
InstanceAdminSerializer,
|
||||||
)
|
)
|
||||||
from plane.license.models import Instance, InstanceAdmin
|
from plane.license.models import Instance, InstanceAdmin
|
||||||
from plane.db.models import User, Profile
|
from plane.db.models import User, Profile, Workspace, Site
|
||||||
from plane.utils.cache import cache_response, invalidate_cache
|
from plane.utils.cache import cache_response, invalidate_cache
|
||||||
from plane.authentication.utils.login import user_login
|
from plane.authentication.utils.login import user_login
|
||||||
from plane.authentication.utils.host import base_host
|
from plane.authentication.utils.host import base_host
|
||||||
@ -392,3 +392,58 @@ class InstanceAdminSignOutEndpoint(View):
|
|||||||
"god-mode/login?" + urlencode({"success": "true"}),
|
"god-mode/login?" + urlencode({"success": "true"}),
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
|
||||||
|
class InstanceWorkspacesEndpoint(BaseAPIView):
|
||||||
|
permission_classes = [
|
||||||
|
InstanceAdminPermission,
|
||||||
|
]
|
||||||
|
|
||||||
|
def get(self, request):
|
||||||
|
workspace = Workspace.objects.values()
|
||||||
|
return Response(workspace, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
|
class PrimaryWorkspaceEndpoint(BaseAPIView):
|
||||||
|
|
||||||
|
permission_classes = [
|
||||||
|
InstanceAdminPermission,
|
||||||
|
]
|
||||||
|
|
||||||
|
def post(self, request):
|
||||||
|
# Get the id of the primary workspace
|
||||||
|
primary_workspace_id = request.data.get("primary_workspace_id", False)
|
||||||
|
|
||||||
|
# Throw error is the primary workspace is not specified
|
||||||
|
if not primary_workspace_id:
|
||||||
|
return Response(
|
||||||
|
{"error": "Primary workspace id is required"},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Get the primary workspace
|
||||||
|
primary_workspace = Workspace.objects.get(pk=primary_workspace_id)
|
||||||
|
|
||||||
|
# Check if the site exists or not
|
||||||
|
site = Site.objects.first()
|
||||||
|
if not site:
|
||||||
|
# Create a Site
|
||||||
|
site = Site.objects.create(
|
||||||
|
name=primary_workspace.name,
|
||||||
|
owner=primary_workspace.owner,
|
||||||
|
domain=f"{request.get_host()}",
|
||||||
|
user_count=User.objects.count(),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Attach this site to all workspaces
|
||||||
|
Workspace.objects.update(site=site, is_primary=False)
|
||||||
|
|
||||||
|
# Update the primary workspace
|
||||||
|
primary_workspace.is_primary = True
|
||||||
|
primary_workspace.site = site
|
||||||
|
primary_workspace.save()
|
||||||
|
|
||||||
|
return Response(
|
||||||
|
{"message": "Primary workspace created succesfully"},
|
||||||
|
status=status.HTTP_200_OK,
|
||||||
|
)
|
||||||
|
@ -155,6 +155,9 @@ class InstanceEndpoint(BaseAPIView):
|
|||||||
)
|
)
|
||||||
instance_data = serializer.data
|
instance_data = serializer.data
|
||||||
instance_data["workspaces_exist"] = Workspace.objects.count() > 1
|
instance_data["workspaces_exist"] = Workspace.objects.count() > 1
|
||||||
|
instance_data["primary_workspace"] = Workspace.objects.filter(
|
||||||
|
is_primary=True
|
||||||
|
).exists()
|
||||||
|
|
||||||
response_data = {"config": data, "instance": instance_data}
|
response_data = {"config": data, "instance": instance_data}
|
||||||
return Response(response_data, status=status.HTTP_200_OK)
|
return Response(response_data, status=status.HTTP_200_OK)
|
||||||
|
@ -10,6 +10,8 @@ from plane.license.api.views import (
|
|||||||
SignUpScreenVisitedEndpoint,
|
SignUpScreenVisitedEndpoint,
|
||||||
InstanceAdminUserMeEndpoint,
|
InstanceAdminUserMeEndpoint,
|
||||||
InstanceAdminSignOutEndpoint,
|
InstanceAdminSignOutEndpoint,
|
||||||
|
InstanceWorkspacesEndpoint,
|
||||||
|
PrimaryWorkspaceEndpoint,
|
||||||
)
|
)
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
@ -63,4 +65,14 @@ urlpatterns = [
|
|||||||
EmailCredentialCheckEndpoint.as_view(),
|
EmailCredentialCheckEndpoint.as_view(),
|
||||||
name="email-credential-check",
|
name="email-credential-check",
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"workspaces/",
|
||||||
|
InstanceWorkspacesEndpoint.as_view(),
|
||||||
|
name="instance-workspaces",
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"primary-workspace/",
|
||||||
|
PrimaryWorkspaceEndpoint.as_view(),
|
||||||
|
name="primary-workspace",
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
Loading…
Reference in New Issue
Block a user