|
13 | 13 | from rest_framework.response import Response
|
14 | 14 | from rest_framework.viewsets import ReadOnlyModelViewSet
|
15 | 15 |
|
16 |
| -from multinet.api.auth.decorators import require_workspace_ownership, require_workspace_permission |
17 |
| -from multinet.api.models import Workspace, WorkspaceRole, WorkspaceRoleChoice |
| 16 | +from multinet.api.auth.decorators import ( |
| 17 | + require_workspace_ownership, |
| 18 | + require_workspace_permission, |
| 19 | +) |
| 20 | +from multinet.api.models import ( |
| 21 | + Network, |
| 22 | + Table, |
| 23 | + TableTypeAnnotation, |
| 24 | + Workspace, |
| 25 | + WorkspaceRole, |
| 26 | + WorkspaceRoleChoice, |
| 27 | +) |
18 | 28 | from multinet.api.utils.arango import ArangoQuery
|
19 | 29 | from multinet.api.views.serializers import (
|
20 | 30 | AqlQuerySerializer,
|
@@ -93,6 +103,47 @@ def create(self, request):
|
93 | 103 | workspace.save()
|
94 | 104 | return Response(WorkspaceSerializer(workspace).data, status=status.HTTP_200_OK)
|
95 | 105 |
|
| 106 | + @swagger_auto_schema( |
| 107 | + responses={200: WorkspaceSerializer()}, |
| 108 | + ) |
| 109 | + @action(detail=True, url_path='fork', methods=['POST']) |
| 110 | + def fork(self, request, name) -> Workspace: |
| 111 | + """ |
| 112 | + Fork this workspace, creating a new workspace with the same tables and networks. |
| 113 | +
|
| 114 | + The new workspace will be private by default and the name will be: |
| 115 | + 'Fork of {original workspace name}' |
| 116 | + """ |
| 117 | + workspace: Workspace = get_object_or_404(Workspace, name=name) |
| 118 | + |
| 119 | + new_name = f'Fork of {workspace.name}' |
| 120 | + # if the new name is not unique, append a number to the end |
| 121 | + i = 1 |
| 122 | + while Workspace.objects.filter(name=new_name).exists(): |
| 123 | + new_name = f'Fork of {workspace.name} ({i})' |
| 124 | + i += 1 |
| 125 | + |
| 126 | + new_workspace = Workspace.objects.create(name=new_name, owner=request.user, public=False) |
| 127 | + |
| 128 | + # Copy the tables and permissions from the original workspace |
| 129 | + for table in Table.objects.filter(workspace=workspace): |
| 130 | + new_table = table.copy(new_workspace) |
| 131 | + # Copy the type annotations |
| 132 | + for type_annotation in TableTypeAnnotation.objects.filter(table=new_table): |
| 133 | + TableTypeAnnotation.objects.create( |
| 134 | + table=new_table, type=type_annotation.type, column=type_annotation.column |
| 135 | + ) |
| 136 | + new_table.save() |
| 137 | + |
| 138 | + # Copy the networks and their permissions from the original workspace |
| 139 | + for network in Network.objects.filter(workspace=workspace): |
| 140 | + new_network = network.copy(new_workspace) |
| 141 | + new_network.save() |
| 142 | + |
| 143 | + new_workspace.save() |
| 144 | + |
| 145 | + return Response(WorkspaceSerializer(new_workspace).data, status=status.HTTP_200_OK) |
| 146 | + |
96 | 147 | @swagger_auto_schema(
|
97 | 148 | request_body=WorkspaceRenameSerializer(),
|
98 | 149 | responses={200: WorkspaceSerializer()},
|
|
0 commit comments