mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-08-14 12:50:37 +03:00
Implement CstRename
This commit is contained in:
parent
24da53bf40
commit
375bac2a52
|
@ -241,7 +241,7 @@ class RSForm(Model):
|
|||
def reset_aliases(self):
|
||||
''' Recreate all aliases based on cst order. '''
|
||||
mapping = self._create_reset_mapping()
|
||||
self._apply_mapping(mapping)
|
||||
self.apply_mapping(mapping, change_aliases=True)
|
||||
|
||||
def _create_reset_mapping(self) -> dict[str, str]:
|
||||
bases = cast(dict[str, int], {})
|
||||
|
@ -257,11 +257,12 @@ class RSForm(Model):
|
|||
return mapping
|
||||
|
||||
@transaction.atomic
|
||||
def _apply_mapping(self, mapping: dict[str, str]):
|
||||
def apply_mapping(self, mapping: dict[str, str], change_aliases: bool = False):
|
||||
''' Apply rename mapping. '''
|
||||
cst_list = self.constituents().order_by('order')
|
||||
for cst in cst_list:
|
||||
modified = False
|
||||
if cst.alias in mapping:
|
||||
if change_aliases and cst.alias in mapping:
|
||||
modified = True
|
||||
cst.alias = mapping[cst.alias]
|
||||
expression = apply_mapping_pattern(cst.definition_formal, mapping, _GLOBAL_ID_PATTERN)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
''' Serializers for conceptual schema API. '''
|
||||
from typing import Optional
|
||||
from typing import Optional, cast
|
||||
from rest_framework import serializers
|
||||
from django.db import transaction
|
||||
|
||||
|
@ -264,6 +264,30 @@ class CstCreateSerializer(serializers.ModelSerializer):
|
|||
fields = 'alias', 'cst_type', 'convention', 'term_raw', 'definition_raw', 'definition_formal', 'insert_after'
|
||||
|
||||
|
||||
class CstRenameSerializer(serializers.ModelSerializer):
|
||||
''' Serializer: Constituenta renaming. '''
|
||||
class Meta:
|
||||
''' serializer metadata. '''
|
||||
model = Constituenta
|
||||
fields = 'id', 'alias', 'cst_type'
|
||||
|
||||
def validate(self, attrs):
|
||||
schema = cast(RSForm, self.context['schema'])
|
||||
old_cst = Constituenta.objects.get(pk=self.initial_data['id'])
|
||||
if old_cst.schema != schema:
|
||||
raise serializers.ValidationError({
|
||||
'id': f'Изменяемая конституента должна относиться к изменяемой схеме: {schema.title}'
|
||||
})
|
||||
if old_cst.alias == self.initial_data['alias']:
|
||||
raise serializers.ValidationError({
|
||||
'alias': f'Имя конституенты должно отличаться от текущего: {self.initial_data["alias"]}'
|
||||
})
|
||||
self.instance = old_cst
|
||||
attrs['schema'] = schema
|
||||
attrs['id'] = self.initial_data['id']
|
||||
return attrs
|
||||
|
||||
|
||||
class CstListSerlializer(serializers.Serializer):
|
||||
''' Serializer: List of constituents from one origin. '''
|
||||
items = serializers.ListField(
|
||||
|
|
|
@ -246,6 +246,56 @@ class TestRSFormViewset(APITestCase):
|
|||
x4 = Constituenta.objects.get(alias=response.data['new_cst']['alias'])
|
||||
self.assertEqual(x4.order, 3)
|
||||
|
||||
def test_rename_constituenta(self):
|
||||
self.cst1 = Constituenta.objects.create(
|
||||
alias='X1', schema=self.rsform_owned, order=1, convention='Test',
|
||||
term_raw='Test1', term_resolved='Test1',
|
||||
term_forms=[{'text':'form1', 'tags':'sing,datv'}])
|
||||
self.cst2 = Constituenta.objects.create(
|
||||
alias='X2', schema=self.rsform_unowned, order=1, convention='Test1',
|
||||
term_raw='Test2', term_resolved='Test2')
|
||||
self.cst3 = Constituenta.objects.create(
|
||||
alias='X3', schema=self.rsform_owned, order=2,
|
||||
term_raw='Test3', term_resolved='Test3',
|
||||
definition_raw='Test1', definition_resolved='Test2')
|
||||
|
||||
data = json.dumps({'alias': 'D2', 'cst_type': 'term', 'id': self.cst2.pk})
|
||||
response = self.client.patch(f'/api/rsforms/{self.rsform_unowned.id}/cst-rename/',
|
||||
data=data, content_type='application/json')
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
response = self.client.patch(f'/api/rsforms/{self.rsform_owned.id}/cst-rename/',
|
||||
data=data, content_type='application/json')
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
data = json.dumps({'alias': self.cst1.alias, 'cst_type': 'term', 'id': self.cst1.pk})
|
||||
response = self.client.patch(f'/api/rsforms/{self.rsform_owned.id}/cst-rename/',
|
||||
data=data, content_type='application/json')
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
data = json.dumps({'alias': 'D2', 'cst_type': 'term', 'id': self.cst1.pk})
|
||||
schema = self.rsform_owned
|
||||
d1 = Constituenta.objects.create(schema=schema, alias='D1', cst_type='term', order=4)
|
||||
d1.term_raw = '@{X1|plur}'
|
||||
d1.definition_formal = 'X1'
|
||||
d1.save()
|
||||
|
||||
self.assertEqual(self.cst1.order, 1)
|
||||
self.assertEqual(self.cst1.alias, 'X1')
|
||||
self.assertEqual(self.cst1.cst_type, CstType.BASE)
|
||||
response = self.client.patch(f'/api/rsforms/{schema.id}/cst-rename/',
|
||||
data=data, content_type='application/json')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.data['new_cst']['alias'], 'D2')
|
||||
self.assertEqual(response.data['new_cst']['cst_type'], 'term')
|
||||
d1.refresh_from_db()
|
||||
self.cst1.refresh_from_db()
|
||||
self.assertEqual(d1.term_resolved, '')
|
||||
self.assertEqual(d1.term_raw, '@{D2|plur}')
|
||||
self.assertEqual(self.cst1.order, 2)
|
||||
self.assertEqual(self.cst1.alias, 'D2')
|
||||
self.assertEqual(self.cst1.cst_type, CstType.TERM)
|
||||
|
||||
def test_create_constituenta_data(self):
|
||||
data = json.dumps({
|
||||
'alias': 'X3',
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
''' REST API: RSForms for conceptual schemas. '''
|
||||
import json
|
||||
from django.db import transaction
|
||||
from django.http import HttpResponse
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
from django.db.models import Q
|
||||
|
@ -63,7 +64,7 @@ class RSFormViewSet(viewsets.ModelViewSet):
|
|||
|
||||
def get_permissions(self):
|
||||
if self.action in ['update', 'destroy', 'partial_update', 'load_trs',
|
||||
'cst_create', 'cst_multidelete', 'reset_aliases']:
|
||||
'cst_create', 'cst_multidelete', 'reset_aliases', 'cst_rename']:
|
||||
permission_classes = [utils.ObjectOwnerOrAdmin]
|
||||
elif self.action in ['create', 'claim', 'clone']:
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
|
@ -87,6 +88,25 @@ class RSFormViewSet(viewsets.ModelViewSet):
|
|||
response['Location'] = new_cst.get_absolute_url()
|
||||
return response
|
||||
|
||||
@transaction.atomic
|
||||
@action(detail=True, methods=['patch'], url_path='cst-rename')
|
||||
def cst_rename(self, request, pk):
|
||||
''' Rename constituenta possibly changing type. '''
|
||||
schema = self._get_schema()
|
||||
serializer = serializers.CstRenameSerializer(data=request.data, context={'schema': schema})
|
||||
serializer.is_valid(raise_exception=True)
|
||||
old_alias = models.Constituenta.objects.get(pk=request.data['id']).alias
|
||||
serializer.save()
|
||||
mapping = { old_alias: serializer.validated_data['alias'] }
|
||||
schema.apply_mapping(mapping, change_aliases=False)
|
||||
schema.update_order()
|
||||
schema.refresh_from_db()
|
||||
cst = models.Constituenta.objects.get(pk=serializer.validated_data['id'])
|
||||
return Response(status=200, data={
|
||||
'new_cst': serializers.ConstituentaSerializer(cst).data,
|
||||
'schema': models.PyConceptAdapter(schema).full()
|
||||
})
|
||||
|
||||
@action(detail=True, methods=['patch'], url_path='cst-multidelete')
|
||||
def cst_multidelete(self, request, pk):
|
||||
''' Endpoint: Delete multiple constituents. '''
|
||||
|
|
|
@ -227,10 +227,11 @@ export const RSFormState = ({ schemaID, children }: RSFormStateProps) => {
|
|||
setLoading: setProcessing,
|
||||
onError: error => setError(error),
|
||||
onSuccess: newData => {
|
||||
reload(setProcessing, () => { if (callback) callback(newData); })
|
||||
setSchema(newData.schema);
|
||||
if (callback) callback(newData.new_cst);
|
||||
}
|
||||
});
|
||||
}, [setError, reload, schemaID]);
|
||||
}, [setError, setSchema, schemaID]);
|
||||
|
||||
const cstMoveTo = useCallback(
|
||||
(data: ICstMovetoData, callback?: () => void) => {
|
||||
|
|
|
@ -210,7 +210,7 @@ export function patchConstituenta(target: string, request: FrontExchange<ICstUpd
|
|||
});
|
||||
}
|
||||
|
||||
export function patchRenameConstituenta(schema: string, request: FrontExchange<ICstRenameData, IConstituentaMeta>) {
|
||||
export function patchRenameConstituenta(schema: string, request: FrontExchange<ICstRenameData, ICstCreatedResponse>) {
|
||||
AxiosPatch({
|
||||
title: `Renaming constituenta id=${request.data.id} for schema id=${schema}`,
|
||||
endpoint: `/api/rsforms/${schema}/cst-rename/`,
|
||||
|
|
Loading…
Reference in New Issue
Block a user