ConceptPortal-public/rsconcept/backend/apps/rsform/views/rsforms.py

649 lines
24 KiB
Python
Raw Normal View History

''' Endpoints for RSForm. '''
2023-07-15 17:46:19 +03:00
import json
2024-05-24 18:31:14 +03:00
from typing import Union, cast
import pyconcept
2023-08-23 12:15:16 +03:00
from django.db import transaction
2023-07-15 17:46:19 +03:00
from django.http import HttpResponse
2023-09-21 23:09:51 +03:00
from drf_spectacular.utils import extend_schema, extend_schema_view
2024-05-25 17:20:22 +03:00
from rest_framework import generics
from rest_framework import status as c
2024-05-24 18:31:14 +03:00
from rest_framework import views, viewsets
from rest_framework.decorators import action, api_view
from rest_framework.request import Request
from rest_framework.response import Response
2024-07-31 14:02:33 +03:00
from rest_framework.serializers import ValidationError
2023-07-15 17:46:19 +03:00
from apps.library.models import AccessPolicy, LibraryItem, LibraryItemType, LocationHead
from apps.library.serializers import LibraryItemSerializer
2024-08-11 12:38:08 +03:00
from apps.oss.models import PropagationFacade
from apps.users.models import User
2024-07-19 19:29:27 +03:00
from shared import messages as msg
from shared import permissions, utility
2024-07-19 19:29:27 +03:00
from .. import models as m
from .. import serializers as s
from .. import utils
2023-08-26 17:26:49 +03:00
2023-08-25 22:51:20 +03:00
2023-09-21 23:09:51 +03:00
@extend_schema(tags=['RSForm'])
@extend_schema_view()
2023-08-25 22:51:20 +03:00
class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.RetrieveAPIView):
''' Endpoint: RSForm operations. '''
queryset = LibraryItem.objects.filter(item_type=LibraryItemType.RSFORM)
serializer_class = LibraryItemSerializer
2023-08-25 22:51:20 +03:00
def _get_item(self) -> LibraryItem:
return cast(LibraryItem, self.get_object())
2023-08-25 22:51:20 +03:00
def get_permissions(self):
''' Determine permission class. '''
if self.action in [
2024-07-19 19:29:27 +03:00
'load_trs',
'create_cst',
'rename_cst',
2024-08-10 11:41:52 +03:00
'update_cst',
'move_cst',
2024-08-10 11:41:52 +03:00
'delete_multiple_cst',
'substitute',
'restore_order',
2024-07-19 19:29:27 +03:00
'reset_aliases',
2024-07-31 14:02:33 +03:00
'produce_structure',
]:
2024-06-03 01:17:27 +03:00
permission_list = [permissions.ItemEditor]
2024-07-19 19:29:27 +03:00
elif self.action in [
'contents',
'details',
'export_trs',
'resolve',
'check_expression',
'check_constituenta'
2024-07-19 19:29:27 +03:00
]:
2024-06-03 01:17:27 +03:00
permission_list = [permissions.ItemAnyone]
2023-07-15 17:46:19 +03:00
else:
2024-05-25 17:20:22 +03:00
permission_list = [permissions.Anyone]
2024-03-04 15:26:23 +03:00
return [permission() for permission in permission_list]
2023-07-15 17:46:19 +03:00
2023-09-21 23:09:51 +03:00
@extend_schema(
summary='create constituenta',
tags=['Constituenta'],
request=s.CstCreateSerializer,
responses={
c.HTTP_201_CREATED: s.NewCstResponse,
2024-07-19 19:29:27 +03:00
c.HTTP_400_BAD_REQUEST: None,
c.HTTP_403_FORBIDDEN: None,
c.HTTP_404_NOT_FOUND: None
}
2023-09-21 23:09:51 +03:00
)
@action(detail=True, methods=['post'], url_path='create-cst')
2024-08-07 21:54:50 +03:00
def create_cst(self, request: Request, pk) -> HttpResponse:
''' Create new constituenta. '''
2023-08-25 22:51:20 +03:00
serializer = s.CstCreateSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
data = serializer.validated_data
2024-08-07 21:54:50 +03:00
if 'insert_after' not in data:
2024-07-15 12:36:18 +03:00
insert_after = None
2024-08-07 21:54:50 +03:00
else:
insert_after = data['insert_after']
2024-08-10 11:41:52 +03:00
schema = m.RSForm(self._get_item())
2024-08-07 21:54:50 +03:00
with transaction.atomic():
new_cst = schema.create_cst(data, insert_after)
2024-08-16 20:57:37 +03:00
PropagationFacade.after_create_cst(schema, [new_cst])
2024-07-31 14:02:33 +03:00
return Response(
status=c.HTTP_201_CREATED,
data={
2024-05-18 19:22:26 +03:00
'new_cst': s.CstSerializer(new_cst).data,
'schema': s.RSFormParseSerializer(schema.model).data
}
)
2024-07-31 14:02:33 +03:00
@extend_schema(
summary='update persistent attributes of a given constituenta',
tags=['RSForm'],
2024-08-10 11:41:52 +03:00
request=s.CstUpdateSerializer,
2024-07-31 14:02:33 +03:00
responses={
c.HTTP_200_OK: s.CstSerializer,
c.HTTP_400_BAD_REQUEST: None,
c.HTTP_403_FORBIDDEN: None,
c.HTTP_404_NOT_FOUND: None
}
)
@action(detail=True, methods=['patch'], url_path='update-cst')
2024-08-07 21:54:50 +03:00
def update_cst(self, request: Request, pk) -> HttpResponse:
2024-07-31 14:02:33 +03:00
''' Update persistent attributes of a given constituenta. '''
2024-08-10 11:41:52 +03:00
model = self._get_item()
serializer = s.CstUpdateSerializer(data=request.data, partial=True, context={'schema': model})
2024-07-31 14:02:33 +03:00
serializer.is_valid(raise_exception=True)
2024-08-10 11:41:52 +03:00
cst = cast(m.Constituenta, serializer.validated_data['target'])
schema = m.RSForm(model)
data = serializer.validated_data['item_data']
with transaction.atomic():
2024-08-10 11:41:52 +03:00
old_data = schema.update_cst(cst, data)
2024-08-16 20:57:37 +03:00
PropagationFacade.after_update_cst(schema, cst, data, old_data)
2024-07-31 14:02:33 +03:00
return Response(
status=c.HTTP_200_OK,
2024-08-10 11:41:52 +03:00
data=s.CstSerializer(m.Constituenta.objects.get(pk=request.data['target'])).data
2024-07-31 14:02:33 +03:00
)
@extend_schema(
summary='produce the structure of a given constituenta',
tags=['RSForm'],
request=s.CstTargetSerializer,
responses={
c.HTTP_200_OK: s.NewMultiCstResponse,
2024-07-19 19:29:27 +03:00
c.HTTP_400_BAD_REQUEST: None,
c.HTTP_403_FORBIDDEN: None,
c.HTTP_404_NOT_FOUND: None
}
)
@action(detail=True, methods=['patch'], url_path='produce-structure')
2024-08-07 21:54:50 +03:00
def produce_structure(self, request: Request, pk) -> HttpResponse:
''' Produce a term for every element of the target constituenta typification. '''
model = self._get_item()
serializer = s.CstTargetSerializer(data=request.data, context={'schema': model})
serializer.is_valid(raise_exception=True)
cst = cast(m.Constituenta, serializer.validated_data['target'])
if cst.cst_type not in [m.CstType.FUNCTION, m.CstType.STRUCTURED, m.CstType.TERM]:
raise ValidationError({
f'{cst.pk}': msg.constituentaNoStructure()
})
schema_details = s.RSFormParseSerializer(model).data['items']
cst_parse = next(item for item in schema_details if item['id'] == cst.pk)['parse']
if not cst_parse['typification']:
return Response(
status=c.HTTP_400_BAD_REQUEST,
data={f'{cst.pk}': msg.constituentaNoStructure()}
)
2024-08-11 12:38:08 +03:00
schema = m.RSForm(model)
2024-08-07 21:54:50 +03:00
with transaction.atomic():
2024-08-11 21:23:45 +03:00
new_cst = schema.produce_structure(cst, cst_parse)
2024-08-16 20:57:37 +03:00
PropagationFacade.after_create_cst(schema, new_cst)
return Response(
status=c.HTTP_200_OK,
data={
2024-08-11 21:23:45 +03:00
'cst_list': [cst.pk for cst in new_cst],
2024-08-11 12:38:08 +03:00
'schema': s.RSFormParseSerializer(schema.model).data
}
)
2023-09-21 23:09:51 +03:00
@extend_schema(
summary='rename constituenta',
tags=['Constituenta'],
request=s.CstRenameSerializer,
responses={
c.HTTP_200_OK: s.NewCstResponse,
2024-07-19 19:29:27 +03:00
c.HTTP_400_BAD_REQUEST: None,
c.HTTP_403_FORBIDDEN: None,
c.HTTP_404_NOT_FOUND: None
}
2023-09-21 23:09:51 +03:00
)
@action(detail=True, methods=['patch'], url_path='rename-cst')
2024-08-07 21:54:50 +03:00
def rename_cst(self, request: Request, pk) -> HttpResponse:
2023-08-23 12:15:16 +03:00
''' Rename constituenta possibly changing type. '''
model = self._get_item()
serializer = s.CstRenameSerializer(data=request.data, context={'schema': model})
2023-08-23 12:15:16 +03:00
serializer.is_valid(raise_exception=True)
cst = cast(m.Constituenta, serializer.validated_data['target'])
changed_type = cst.cst_type != serializer.validated_data['cst_type']
2024-08-07 21:54:50 +03:00
mapping = {cst.alias: serializer.validated_data['alias']}
schema = m.RSForm(model)
2024-07-19 19:29:27 +03:00
with transaction.atomic():
2024-08-11 12:38:08 +03:00
cst.alias = serializer.validated_data['alias']
cst.cst_type = serializer.validated_data['cst_type']
2024-07-19 19:29:27 +03:00
cst.save()
schema.apply_mapping(mapping=mapping, change_aliases=False)
2024-08-12 16:52:06 +03:00
schema.save()
cst.refresh_from_db()
if changed_type:
2024-08-16 20:57:37 +03:00
PropagationFacade.after_change_cst_type(schema, cst)
return Response(
status=c.HTTP_200_OK,
data={
2024-05-18 19:22:26 +03:00
'new_cst': s.CstSerializer(cst).data,
2024-08-11 12:38:08 +03:00
'schema': s.RSFormParseSerializer(schema.model).data
}
)
2023-08-23 12:15:16 +03:00
@extend_schema(
summary='execute substitutions',
tags=['RSForm'],
request=s.CstSubstituteSerializer,
responses={
c.HTTP_200_OK: s.RSFormParseSerializer,
2024-07-19 19:29:27 +03:00
c.HTTP_400_BAD_REQUEST: None,
c.HTTP_403_FORBIDDEN: None,
c.HTTP_404_NOT_FOUND: None
}
)
@action(detail=True, methods=['patch'], url_path='substitute')
2024-08-07 21:54:50 +03:00
def substitute(self, request: Request, pk) -> HttpResponse:
''' Substitute occurrences of constituenta with another one. '''
model = self._get_item()
serializer = s.CstSubstituteSerializer(
data=request.data,
context={'schema': model}
)
serializer.is_valid(raise_exception=True)
2024-08-11 12:38:08 +03:00
schema = m.RSForm(model)
substitutions: list[tuple[m.Constituenta, m.Constituenta]] = []
2024-07-19 19:29:27 +03:00
with transaction.atomic():
for substitution in serializer.validated_data['substitutions']:
original = cast(m.Constituenta, substitution['original'])
replacement = cast(m.Constituenta, substitution['substitution'])
substitutions.append((original, replacement))
2024-08-16 20:57:37 +03:00
PropagationFacade.before_substitute(schema, substitutions)
2024-08-11 12:38:08 +03:00
schema.substitute(substitutions)
return Response(
status=c.HTTP_200_OK,
2024-08-11 12:38:08 +03:00
data=s.RSFormParseSerializer(schema.model).data
)
2023-09-21 23:09:51 +03:00
@extend_schema(
summary='delete constituents',
tags=['RSForm'],
request=s.CstListSerializer,
responses={
c.HTTP_200_OK: s.RSFormParseSerializer,
2024-07-19 19:29:27 +03:00
c.HTTP_400_BAD_REQUEST: None,
c.HTTP_403_FORBIDDEN: None,
c.HTTP_404_NOT_FOUND: None
}
2023-09-21 23:09:51 +03:00
)
@action(detail=True, methods=['patch'], url_path='delete-multiple-cst')
2024-08-07 21:54:50 +03:00
def delete_multiple_cst(self, request: Request, pk) -> HttpResponse:
''' Endpoint: Delete multiple constituents. '''
model = self._get_item()
2023-09-25 14:17:52 +03:00
serializer = s.CstListSerializer(
data=request.data,
context={'schema': model}
2023-09-25 14:17:52 +03:00
)
serializer.is_valid(raise_exception=True)
2024-08-11 12:38:08 +03:00
cst_list: list[m.Constituenta] = serializer.validated_data['items']
schema = m.RSForm(model)
2024-08-07 21:54:50 +03:00
with transaction.atomic():
2024-08-16 20:57:37 +03:00
PropagationFacade.before_delete_cst(schema, cst_list)
2024-08-11 12:38:08 +03:00
schema.delete_cst(cst_list)
return Response(
status=c.HTTP_200_OK,
2024-08-11 12:38:08 +03:00
data=s.RSFormParseSerializer(schema.model).data
)
2023-09-21 23:09:51 +03:00
@extend_schema(
summary='move constituenta',
tags=['RSForm'],
request=s.CstMoveSerializer,
responses={
c.HTTP_200_OK: s.RSFormParseSerializer,
2024-07-19 19:29:27 +03:00
c.HTTP_400_BAD_REQUEST: None,
c.HTTP_403_FORBIDDEN: None,
c.HTTP_404_NOT_FOUND: None
}
2023-09-21 23:09:51 +03:00
)
@action(detail=True, methods=['patch'], url_path='move-cst')
2024-08-07 21:54:50 +03:00
def move_cst(self, request: Request, pk) -> HttpResponse:
''' Endpoint: Move multiple constituents. '''
model = self._get_item()
2023-09-25 14:17:52 +03:00
serializer = s.CstMoveSerializer(
data=request.data,
context={'schema': model}
2023-09-25 14:17:52 +03:00
)
serializer.is_valid(raise_exception=True)
2024-08-07 21:54:50 +03:00
with transaction.atomic():
m.RSForm(model).move_cst(
2024-08-07 21:54:50 +03:00
target=serializer.validated_data['items'],
destination=serializer.validated_data['move_to']
)
return Response(
status=c.HTTP_200_OK,
data=s.RSFormParseSerializer(model).data
)
2023-09-21 23:09:51 +03:00
@extend_schema(
summary='reset aliases, update expressions and references',
tags=['RSForm'],
request=None,
responses={
c.HTTP_200_OK: s.RSFormParseSerializer,
c.HTTP_403_FORBIDDEN: None,
c.HTTP_404_NOT_FOUND: None
}
2023-09-21 23:09:51 +03:00
)
2023-07-27 22:04:25 +03:00
@action(detail=True, methods=['patch'], url_path='reset-aliases')
2024-08-07 21:54:50 +03:00
def reset_aliases(self, request: Request, pk) -> HttpResponse:
''' Endpoint: Recreate all aliases based on order. '''
model = self._get_item()
2024-08-12 16:52:06 +03:00
schema = m.RSForm(model)
schema.reset_aliases()
return Response(
status=c.HTTP_200_OK,
data=s.RSFormParseSerializer(model).data
)
2024-04-24 10:27:17 +03:00
@extend_schema(
summary='restore order based on types and term graph',
tags=['RSForm'],
request=None,
responses={
c.HTTP_200_OK: s.RSFormParseSerializer,
c.HTTP_403_FORBIDDEN: None,
c.HTTP_404_NOT_FOUND: None
}
)
@action(detail=True, methods=['patch'], url_path='restore-order')
2024-08-07 21:54:50 +03:00
def restore_order(self, request: Request, pk) -> HttpResponse:
2024-04-24 10:27:17 +03:00
''' Endpoint: Restore order based on types and term graph. '''
model = self._get_item()
m.RSForm(model).restore_order()
2024-04-24 10:27:17 +03:00
return Response(
status=c.HTTP_200_OK,
data=s.RSFormParseSerializer(model).data
2024-04-24 10:27:17 +03:00
)
2023-07-27 22:04:25 +03:00
2023-09-21 23:09:51 +03:00
@extend_schema(
summary='load data from TRS file',
tags=['RSForm'],
request=s.RSFormUploadSerializer,
responses={
c.HTTP_200_OK: s.RSFormParseSerializer,
2024-07-19 19:29:27 +03:00
c.HTTP_400_BAD_REQUEST: None,
c.HTTP_403_FORBIDDEN: None,
c.HTTP_404_NOT_FOUND: None
}
2023-09-21 23:09:51 +03:00
)
2023-07-27 22:04:25 +03:00
@action(detail=True, methods=['patch'], url_path='load-trs')
2024-08-07 21:54:50 +03:00
def load_trs(self, request: Request, pk) -> HttpResponse:
''' Endpoint: Load data from file and replace current schema. '''
input_serializer = s.RSFormUploadSerializer(data=request.data)
input_serializer.is_valid(raise_exception=True)
model = self._get_item()
load_metadata = input_serializer.validated_data['load_metadata']
data = utility.read_zipped_json(request.FILES['file'].file, utils.EXTEOR_INNER_FILENAME)
if data is None:
return Response(
status=c.HTTP_400_BAD_REQUEST,
data={'file': msg.exteorFileCorrupted()}
)
data['id'] = model.pk
2023-09-25 14:17:52 +03:00
serializer = s.RSFormTRSSerializer(
data=data,
context={'load_meta': load_metadata}
)
serializer.is_valid(raise_exception=True)
result: m.RSForm = serializer.save()
return Response(
status=c.HTTP_200_OK,
data=s.RSFormParseSerializer(result.model).data
)
2023-07-15 17:46:19 +03:00
2023-09-21 23:09:51 +03:00
@extend_schema(
summary='get all constituents data from DB',
tags=['RSForm'],
request=None,
responses={
c.HTTP_200_OK: s.RSFormSerializer,
c.HTTP_404_NOT_FOUND: None
}
2023-09-21 23:09:51 +03:00
)
2024-07-15 12:36:18 +03:00
@action(detail=True, methods=['get'], url_path='contents')
2024-08-07 21:54:50 +03:00
def contents(self, request: Request, pk) -> HttpResponse:
''' Endpoint: View schema db contents (including constituents). '''
serializer = s.RSFormSerializer(self.get_object())
return Response(
status=c.HTTP_200_OK,
data=serializer.data
)
2023-07-15 17:46:19 +03:00
2023-09-21 23:09:51 +03:00
@extend_schema(
summary='get all constituents data and parses',
tags=['RSForm'],
request=None,
responses={
c.HTTP_200_OK: s.RSFormParseSerializer,
c.HTTP_404_NOT_FOUND: None
}
2023-09-21 23:09:51 +03:00
)
2024-07-15 12:36:18 +03:00
@action(detail=True, methods=['get'], url_path='details')
2024-08-07 21:54:50 +03:00
def details(self, request: Request, pk) -> HttpResponse:
''' Endpoint: Detailed schema view including statuses and parse. '''
serializer = s.RSFormParseSerializer(self.get_object())
return Response(
status=c.HTTP_200_OK,
data=serializer.data
)
2023-07-15 17:46:19 +03:00
2023-09-21 23:09:51 +03:00
@extend_schema(
summary='check RSLang expression',
tags=['RSForm', 'FormalLanguage'],
request=s.ExpressionSerializer,
responses={
c.HTTP_200_OK: s.ExpressionParseSerializer,
c.HTTP_404_NOT_FOUND: None
},
2023-09-21 23:09:51 +03:00
)
@action(detail=True, methods=['post'], url_path='check-expression')
def check_expression(self, request: Request, pk) -> HttpResponse:
''' Endpoint: Check RSLang expression against schema context. '''
2023-08-25 22:51:20 +03:00
serializer = s.ExpressionSerializer(data=request.data)
2023-07-15 17:46:19 +03:00
serializer.is_valid(raise_exception=True)
expression = serializer.validated_data['expression']
pySchema = s.PyConceptAdapter(m.RSForm(self.get_object()))
result = pyconcept.check_expression(json.dumps(pySchema.data), expression)
return Response(
status=c.HTTP_200_OK,
data=json.loads(result)
)
2023-08-23 23:19:43 +03:00
@extend_schema(
summary='check expression for specific CstType',
tags=['RSForm', 'FormalLanguage'],
request=s.ConstituentaCheckSerializer,
responses={
c.HTTP_200_OK: s.ExpressionParseSerializer,
c.HTTP_404_NOT_FOUND: None
},
)
@action(detail=True, methods=['post'], url_path='check-constituenta')
def check_constituenta(self, request: Request, pk) -> HttpResponse:
''' Endpoint: Check RSLang expression against schema context. '''
serializer = s.ConstituentaCheckSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
expression = serializer.validated_data['definition_formal']
alias = serializer.validated_data['alias']
cst_type = cast(m.CstType, serializer.validated_data['cst_type'])
pySchema = s.PyConceptAdapter(m.RSForm(self.get_object()))
result = pyconcept.check_constituenta(json.dumps(pySchema.data), alias, expression, cst_type)
return Response(
status=c.HTTP_200_OK,
data=json.loads(result)
)
2023-09-21 23:09:51 +03:00
@extend_schema(
summary='resolve text with references',
tags=['RSForm', 'NaturalLanguage'],
request=s.TextSerializer,
responses={
c.HTTP_200_OK: s.ResolverSerializer,
c.HTTP_404_NOT_FOUND: None
}
2023-09-21 23:09:51 +03:00
)
2024-07-15 12:36:18 +03:00
@action(detail=True, methods=['post'], url_path='resolve')
2024-08-07 21:54:50 +03:00
def resolve(self, request: Request, pk) -> HttpResponse:
2023-12-26 14:23:51 +03:00
''' Endpoint: Resolve references in text against schema terms context. '''
2023-08-25 22:51:20 +03:00
serializer = s.TextSerializer(data=request.data)
2023-08-23 22:57:25 +03:00
serializer.is_valid(raise_exception=True)
text = serializer.validated_data['text']
resolver = m.RSForm(self.get_object()).resolver()
2023-08-23 22:57:25 +03:00
resolver.resolve(text)
return Response(
status=c.HTTP_200_OK,
data=s.ResolverSerializer(resolver).data
)
2023-07-15 17:46:19 +03:00
2023-09-21 23:09:51 +03:00
@extend_schema(
summary='export as TRS file',
tags=['RSForm'],
request=None,
responses={
(c.HTTP_200_OK, 'application/zip'): bytes,
c.HTTP_404_NOT_FOUND: None
}
2023-09-21 23:09:51 +03:00
)
2023-07-15 17:46:19 +03:00
@action(detail=True, methods=['get'], url_path='export-trs')
2024-08-07 21:54:50 +03:00
def export_trs(self, request: Request, pk) -> HttpResponse:
''' Endpoint: Download Exteor compatible file. '''
model = self._get_item()
data = s.RSFormTRSSerializer(m.RSForm(model)).data
file = utility.write_zipped_json(data, utils.EXTEOR_INNER_FILENAME)
filename = utils.filename_for_schema(model.alias)
2024-03-07 15:22:50 +03:00
response = HttpResponse(file, content_type='application/zip')
2023-07-15 17:46:19 +03:00
response['Content-Disposition'] = f'attachment; filename={filename}'
return response
class TrsImportView(views.APIView):
''' Endpoint: Upload RS form in Exteor format. '''
2023-08-25 22:51:20 +03:00
serializer_class = s.FileSerializer
2024-05-25 17:20:22 +03:00
permission_classes = [permissions.GlobalUser]
2023-07-15 17:46:19 +03:00
2023-09-21 23:09:51 +03:00
@extend_schema(
summary='import TRS file into RSForm',
tags=['RSForm'],
request=s.FileSerializer,
responses={
c.HTTP_201_CREATED: LibraryItemSerializer,
c.HTTP_400_BAD_REQUEST: None,
c.HTTP_403_FORBIDDEN: None
}
2023-09-21 23:09:51 +03:00
)
2024-08-07 21:54:50 +03:00
def post(self, request: Request) -> HttpResponse:
data = utility.read_zipped_json(request.FILES['file'].file, utils.EXTEOR_INNER_FILENAME)
if data is None:
return Response(
status=c.HTTP_400_BAD_REQUEST,
data={'file': msg.exteorFileCorrupted()}
)
owner = cast(User, self.request.user)
_prepare_rsform_data(data, request, owner)
2023-09-25 14:17:52 +03:00
serializer = s.RSFormTRSSerializer(
data=data,
context={'load_meta': True}
)
serializer.is_valid(raise_exception=True)
schema: m.RSForm = serializer.save()
return Response(
status=c.HTTP_201_CREATED,
data=LibraryItemSerializer(schema.model).data
)
2023-07-15 17:46:19 +03:00
2023-09-21 23:09:51 +03:00
@extend_schema(
summary='create new RSForm empty or from file',
tags=['RSForm'],
request=LibraryItemSerializer,
responses={
c.HTTP_201_CREATED: LibraryItemSerializer,
c.HTTP_400_BAD_REQUEST: None,
c.HTTP_403_FORBIDDEN: None
}
2023-09-21 23:09:51 +03:00
)
2023-07-15 17:46:19 +03:00
@api_view(['POST'])
2024-08-07 21:54:50 +03:00
def create_rsform(request: Request) -> HttpResponse:
''' Endpoint: Create RSForm from user input and/or trs file. '''
owner = cast(User, request.user) if not request.user.is_anonymous else None
if 'file' not in request.FILES:
return Response(
status=c.HTTP_400_BAD_REQUEST,
2024-06-04 11:26:20 +03:00
data={'file': msg.missingFile()}
2023-07-15 17:46:19 +03:00
)
data = utility.read_zipped_json(request.FILES['file'].file, utils.EXTEOR_INNER_FILENAME)
if data is None:
return Response(
status=c.HTTP_400_BAD_REQUEST,
data={'file': msg.exteorFileCorrupted()}
)
_prepare_rsform_data(data, request, owner)
serializer_rsform = s.RSFormTRSSerializer(data=data, context={'load_meta': True})
serializer_rsform.is_valid(raise_exception=True)
schema: m.RSForm = serializer_rsform.save()
return Response(
status=c.HTTP_201_CREATED,
data=LibraryItemSerializer(schema.model).data
)
2023-07-15 17:46:19 +03:00
def _prepare_rsform_data(data: dict, request: Request, owner: Union[User, None]):
2023-08-25 22:51:20 +03:00
data['owner'] = owner
if 'title' in request.data and request.data['title'] != '':
data['title'] = request.data['title']
if data['title'] == '':
data['title'] = 'Без названия ' + request.FILES['file'].fileName
if 'alias' in request.data and request.data['alias'] != '':
data['alias'] = request.data['alias']
if 'comment' in request.data and request.data['comment'] != '':
data['comment'] = request.data['comment']
2023-08-25 22:51:20 +03:00
visible = True
if 'visible' in request.data:
visible = request.data['visible'] == 'true'
data['visible'] = visible
2023-08-25 22:51:20 +03:00
read_only = False
if 'read_only' in request.data:
read_only = request.data['read_only'] == 'true'
data['read_only'] = read_only
data['access_policy'] = request.data.get('access_policy', AccessPolicy.PUBLIC)
data['location'] = request.data.get('location', LocationHead.USER)
2024-07-31 14:02:33 +03:00
@extend_schema(
summary='Inline synthesis: merge one schema into another',
tags=['Operations'],
request=s.InlineSynthesisSerializer,
responses={c.HTTP_200_OK: s.RSFormParseSerializer}
)
@api_view(['PATCH'])
2024-08-07 21:54:50 +03:00
def inline_synthesis(request: Request) -> HttpResponse:
2024-07-31 14:02:33 +03:00
''' Endpoint: Inline synthesis. '''
serializer = s.InlineSynthesisSerializer(
data=request.data,
context={'user': request.user}
)
serializer.is_valid(raise_exception=True)
receiver = m.RSForm(serializer.validated_data['receiver'])
items = cast(list[m.Constituenta], serializer.validated_data['items'])
with transaction.atomic():
new_items = receiver.insert_copy(items)
2024-08-16 20:57:37 +03:00
PropagationFacade.after_create_cst(receiver, new_items)
2024-08-11 21:23:45 +03:00
substitutions: list[tuple[m.Constituenta, m.Constituenta]] = []
2024-07-31 14:02:33 +03:00
for substitution in serializer.validated_data['substitutions']:
original = cast(m.Constituenta, substitution['original'])
replacement = cast(m.Constituenta, substitution['substitution'])
if original in items:
2024-08-07 21:54:50 +03:00
index = next(i for (i, cst) in enumerate(items) if cst.pk == original.pk)
2024-07-31 14:02:33 +03:00
original = new_items[index]
else:
2024-08-07 21:54:50 +03:00
index = next(i for (i, cst) in enumerate(items) if cst.pk == replacement.pk)
2024-07-31 14:02:33 +03:00
replacement = new_items[index]
substitutions.append((original, replacement))
2024-08-11 21:23:45 +03:00
2024-08-16 20:57:37 +03:00
PropagationFacade.before_substitute(receiver, substitutions)
receiver.substitute(substitutions)
2024-08-11 21:23:45 +03:00
2024-07-31 14:02:33 +03:00
receiver.restore_order()
return Response(
status=c.HTTP_200_OK,
data=s.RSFormParseSerializer(receiver.model).data
)