F: Rework constituenta editing endpoints
This commit is contained in:
parent
087ec8cf56
commit
d46fa536e6
|
@ -112,18 +112,6 @@ class TestChangeConstituents(EndpointTester):
|
|||
self.assertEqual(inherited_cst.definition_formal, 'X1 = X2')
|
||||
|
||||
|
||||
@decl_endpoint('/api/rsforms/{schema}/rename-cst', method='patch')
|
||||
def test_rename_constituenta(self):
|
||||
data = {'target': self.ks1X1.pk, 'alias': 'D21', 'cst_type': CstType.TERM}
|
||||
response = self.executeOK(data=data, schema=self.ks1.model.pk)
|
||||
self.ks1X1.refresh_from_db()
|
||||
inherited_cst = Constituenta.objects.get(as_child__parent_id=self.ks1X1.pk)
|
||||
self.assertEqual(self.ks1X1.alias, data['alias'])
|
||||
self.assertEqual(self.ks1X1.cst_type, data['cst_type'])
|
||||
self.assertEqual(inherited_cst.alias, 'D2')
|
||||
self.assertEqual(inherited_cst.cst_type, data['cst_type'])
|
||||
|
||||
|
||||
@decl_endpoint('/api/rsforms/{schema}/update-cst', method='patch')
|
||||
def test_update_constituenta(self):
|
||||
d2 = self.ks3.insert_new('D2', cst_type=CstType.TERM, definition_raw='@{X1|sing,nomn}')
|
||||
|
|
|
@ -16,7 +16,6 @@ from .data_access import (
|
|||
CstInfoSerializer,
|
||||
CstListSerializer,
|
||||
CstMoveSerializer,
|
||||
CstRenameSerializer,
|
||||
CstSubstituteSerializer,
|
||||
CstTargetSerializer,
|
||||
CstUpdateSerializer,
|
||||
|
|
|
@ -45,11 +45,12 @@ class CstUpdateSerializer(serializers.Serializer):
|
|||
class Meta:
|
||||
''' serializer metadata. '''
|
||||
model = Constituenta
|
||||
fields = 'convention', 'definition_formal', 'definition_raw', 'term_raw', 'term_forms'
|
||||
fields = 'alias', 'cst_type', 'convention', 'definition_formal', 'definition_raw', 'term_raw', 'term_forms'
|
||||
|
||||
target = PKField(
|
||||
many=False,
|
||||
queryset=Constituenta.objects.all().only('convention', 'definition_formal', 'definition_raw', 'term_raw')
|
||||
queryset=Constituenta.objects.all().only(
|
||||
'alias', 'cst_type', 'convention', 'definition_formal', 'definition_raw', 'term_raw')
|
||||
)
|
||||
item_data = ConstituentaUpdateData()
|
||||
|
||||
|
@ -60,6 +61,12 @@ class CstUpdateSerializer(serializers.Serializer):
|
|||
raise serializers.ValidationError({
|
||||
f'{cst.pk}': msg.constituentaNotInRSform(schema.title)
|
||||
})
|
||||
if 'alias' in attrs['item_data']:
|
||||
new_alias = attrs['item_data']['alias']
|
||||
if cst.alias != new_alias and RSForm(schema).constituents().filter(alias=new_alias).exists():
|
||||
raise serializers.ValidationError({
|
||||
'alias': msg.aliasTaken(new_alias)
|
||||
})
|
||||
return attrs
|
||||
|
||||
|
||||
|
@ -258,32 +265,6 @@ class CstTargetSerializer(serializers.Serializer):
|
|||
return attrs
|
||||
|
||||
|
||||
class CstRenameSerializer(serializers.Serializer):
|
||||
''' Serializer: Constituenta renaming. '''
|
||||
target = PKField(many=False, queryset=Constituenta.objects.only('alias', 'cst_type', 'schema'))
|
||||
alias = serializers.CharField()
|
||||
cst_type = serializers.CharField()
|
||||
|
||||
def validate(self, attrs):
|
||||
attrs = super().validate(attrs)
|
||||
schema = cast(LibraryItem, self.context['schema'])
|
||||
cst = cast(Constituenta, attrs['target'])
|
||||
if cst.schema_id != schema.pk:
|
||||
raise serializers.ValidationError({
|
||||
f'{cst.pk}': msg.constituentaNotInRSform(schema.title)
|
||||
})
|
||||
new_alias = self.initial_data['alias']
|
||||
if cst.alias == new_alias:
|
||||
raise serializers.ValidationError({
|
||||
'alias': msg.renameTrivial(new_alias)
|
||||
})
|
||||
if RSForm(schema).constituents().filter(alias=new_alias).exists():
|
||||
raise serializers.ValidationError({
|
||||
'alias': msg.aliasTaken(new_alias)
|
||||
})
|
||||
return attrs
|
||||
|
||||
|
||||
class CstListSerializer(serializers.Serializer):
|
||||
''' Serializer: List of constituents from one origin. '''
|
||||
items = PKField(many=True, queryset=Constituenta.objects.all().only('schema_id'))
|
||||
|
|
|
@ -244,56 +244,6 @@ class TestRSFormViewset(EndpointTester):
|
|||
self.assertEqual(response.data['new_cst']['alias'], data['alias'])
|
||||
|
||||
|
||||
@decl_endpoint('/api/rsforms/{item}/rename-cst', method='patch')
|
||||
def test_rename_constituenta(self):
|
||||
x1 = self.owned.insert_new(
|
||||
alias='X1',
|
||||
convention='Test',
|
||||
term_raw='Test1',
|
||||
term_resolved='Test1',
|
||||
term_forms=[{'text': 'form1', 'tags': 'sing,datv'}]
|
||||
)
|
||||
x2_2 = self.unowned.insert_new('X2')
|
||||
x3 = self.owned.insert_new(
|
||||
alias='X3',
|
||||
term_raw='Test3',
|
||||
term_resolved='Test3',
|
||||
definition_raw='Test1',
|
||||
definition_resolved='Test2'
|
||||
)
|
||||
|
||||
data = {'target': x2_2.pk, 'alias': 'D2', 'cst_type': CstType.TERM}
|
||||
self.executeForbidden(data=data, item=self.unowned_id)
|
||||
self.executeBadData(data=data, item=self.owned_id)
|
||||
|
||||
data = {'target': x1.pk, 'alias': x1.alias, 'cst_type': CstType.TERM}
|
||||
self.executeBadData(data=data, item=self.owned_id)
|
||||
|
||||
data = {'target': x1.pk, 'alias': x3.alias}
|
||||
self.executeBadData(data=data, item=self.owned_id)
|
||||
|
||||
d1 = self.owned.insert_new(
|
||||
alias='D1',
|
||||
term_raw='@{X1|plur}',
|
||||
definition_formal='X1'
|
||||
)
|
||||
self.assertEqual(x1.order, 0)
|
||||
self.assertEqual(x1.alias, 'X1')
|
||||
self.assertEqual(x1.cst_type, CstType.BASE)
|
||||
|
||||
data = {'target': x1.pk, 'alias': 'D2', 'cst_type': CstType.TERM}
|
||||
response = self.executeOK(data=data, item=self.owned_id)
|
||||
self.assertEqual(response.data['new_cst']['alias'], 'D2')
|
||||
self.assertEqual(response.data['new_cst']['cst_type'], CstType.TERM)
|
||||
d1.refresh_from_db()
|
||||
x1.refresh_from_db()
|
||||
self.assertEqual(d1.term_resolved, '')
|
||||
self.assertEqual(d1.term_raw, '@{D2|plur}')
|
||||
self.assertEqual(x1.order, 0)
|
||||
self.assertEqual(x1.alias, 'D2')
|
||||
self.assertEqual(x1.cst_type, CstType.TERM)
|
||||
|
||||
|
||||
@decl_endpoint('/api/rsforms/{item}/substitute', method='patch')
|
||||
def test_substitute_multiple(self):
|
||||
self.set_params(item=self.owned_id)
|
||||
|
@ -507,12 +457,14 @@ class TestConstituentaAPI(EndpointTester):
|
|||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.rsform_owned = RSForm.create(title='Test', alias='T1', owner=self.user)
|
||||
self.rsform_unowned = RSForm.create(title='Test2', alias='T2')
|
||||
self.owned = RSForm.create(title='Test', alias='T1', owner=self.user)
|
||||
self.owned_id = self.owned.model.pk
|
||||
self.unowned = RSForm.create(title='Test2', alias='T2')
|
||||
self.unowned_id = self.unowned.model.pk
|
||||
self.cst1 = Constituenta.objects.create(
|
||||
alias='X1',
|
||||
cst_type=CstType.BASE,
|
||||
schema=self.rsform_owned.model,
|
||||
schema=self.owned.model,
|
||||
order=0,
|
||||
convention='Test',
|
||||
term_raw='Test1',
|
||||
|
@ -521,7 +473,7 @@ class TestConstituentaAPI(EndpointTester):
|
|||
self.cst2 = Constituenta.objects.create(
|
||||
alias='X2',
|
||||
cst_type=CstType.BASE,
|
||||
schema=self.rsform_unowned.model,
|
||||
schema=self.unowned.model,
|
||||
order=0,
|
||||
convention='Test1',
|
||||
term_raw='Test2',
|
||||
|
@ -529,7 +481,7 @@ class TestConstituentaAPI(EndpointTester):
|
|||
)
|
||||
self.cst3 = Constituenta.objects.create(
|
||||
alias='X3',
|
||||
schema=self.rsform_owned.model,
|
||||
schema=self.owned.model,
|
||||
order=1,
|
||||
term_raw='Test3',
|
||||
term_resolved='Test3',
|
||||
|
@ -541,18 +493,42 @@ class TestConstituentaAPI(EndpointTester):
|
|||
@decl_endpoint('/api/rsforms/{schema}/update-cst', method='patch')
|
||||
def test_partial_update(self):
|
||||
data = {'target': self.cst1.pk, 'item_data': {'convention': 'tt'}}
|
||||
self.executeForbidden(data=data, schema=self.rsform_unowned.model.pk)
|
||||
self.executeForbidden(data=data, schema=self.unowned_id)
|
||||
|
||||
self.logout()
|
||||
self.executeForbidden(data=data, schema=self.rsform_owned.model.pk)
|
||||
self.executeForbidden(data=data, schema=self.owned_id)
|
||||
|
||||
self.login()
|
||||
response = self.executeOK(data=data, schema=self.rsform_owned.model.pk)
|
||||
self.executeOK(data=data, schema=self.owned_id)
|
||||
self.cst1.refresh_from_db()
|
||||
self.assertEqual(response.data['convention'], 'tt')
|
||||
self.assertEqual(self.cst1.convention, 'tt')
|
||||
|
||||
self.executeOK(data=data, schema=self.rsform_owned.model.pk)
|
||||
self.executeOK(data=data, schema=self.owned_id)
|
||||
|
||||
|
||||
@decl_endpoint('/api/rsforms/{schema}/update-cst', method='patch')
|
||||
def test_partial_update_rename(self):
|
||||
data = {'target': self.cst1.pk, 'item_data': {'alias': self.cst3.alias}}
|
||||
self.executeBadData(data=data, schema=self.owned_id)
|
||||
|
||||
d1 = self.owned.insert_new(
|
||||
alias='D1',
|
||||
term_raw='@{X1|plur}',
|
||||
definition_formal='X1'
|
||||
)
|
||||
self.assertEqual(self.cst1.order, 0)
|
||||
self.assertEqual(self.cst1.alias, 'X1')
|
||||
self.assertEqual(self.cst1.cst_type, CstType.BASE)
|
||||
|
||||
data = {'target': self.cst1.pk, 'item_data': {'alias': 'D2', 'cst_type': CstType.TERM}}
|
||||
self.executeOK(data=data, schema=self.owned_id)
|
||||
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, 0)
|
||||
self.assertEqual(self.cst1.alias, 'D2')
|
||||
self.assertEqual(self.cst1.cst_type, CstType.TERM)
|
||||
|
||||
|
||||
@decl_endpoint('/api/rsforms/{schema}/update-cst', method='patch')
|
||||
|
@ -564,11 +540,9 @@ class TestConstituentaAPI(EndpointTester):
|
|||
'definition_raw': 'New def'
|
||||
}
|
||||
}
|
||||
response = self.executeOK(data=data, schema=self.rsform_owned.model.pk)
|
||||
self.executeOK(data=data, schema=self.owned_id)
|
||||
self.cst3.refresh_from_db()
|
||||
self.assertEqual(response.data['term_resolved'], 'New term')
|
||||
self.assertEqual(self.cst3.term_resolved, 'New term')
|
||||
self.assertEqual(response.data['definition_resolved'], 'New def')
|
||||
self.assertEqual(self.cst3.definition_resolved, 'New def')
|
||||
|
||||
|
||||
|
@ -581,12 +555,10 @@ class TestConstituentaAPI(EndpointTester):
|
|||
'definition_raw': '@{X1|nomn,sing} @{X1|sing,datv}'
|
||||
}
|
||||
}
|
||||
response = self.executeOK(data=data, schema=self.rsform_owned.model.pk)
|
||||
self.executeOK(data=data, schema=self.owned_id)
|
||||
self.cst3.refresh_from_db()
|
||||
self.assertEqual(self.cst3.term_resolved, self.cst1.term_resolved)
|
||||
self.assertEqual(response.data['term_resolved'], self.cst1.term_resolved)
|
||||
self.assertEqual(self.cst3.definition_resolved, f'{self.cst1.term_resolved} form1')
|
||||
self.assertEqual(response.data['definition_resolved'], f'{self.cst1.term_resolved} form1')
|
||||
|
||||
@decl_endpoint('/api/rsforms/{schema}/update-cst', method='patch')
|
||||
def test_update_term_forms(self):
|
||||
|
@ -597,25 +569,10 @@ class TestConstituentaAPI(EndpointTester):
|
|||
'term_forms': [{'text': 'form1', 'tags': 'sing,datv'}]
|
||||
}
|
||||
}
|
||||
response = self.executeOK(data=data, schema=self.rsform_owned.model.pk)
|
||||
self.executeOK(data=data, schema=self.owned_id)
|
||||
self.cst3.refresh_from_db()
|
||||
self.assertEqual(self.cst3.definition_resolved, 'form1')
|
||||
self.assertEqual(response.data['definition_resolved'], 'form1')
|
||||
self.assertEqual(self.cst3.term_forms, data['item_data']['term_forms'])
|
||||
self.assertEqual(response.data['term_forms'], data['item_data']['term_forms'])
|
||||
|
||||
|
||||
@decl_endpoint('/api/rsforms/{schema}/update-cst', method='patch')
|
||||
def test_readonly_cst_fields(self):
|
||||
data = {
|
||||
'target': self.cst1.pk,
|
||||
'item_data': {
|
||||
'alias': 'X33'
|
||||
}
|
||||
}
|
||||
response = self.executeOK(data=data, schema=self.rsform_owned.model.pk)
|
||||
self.assertEqual(response.data['alias'], 'X1')
|
||||
self.assertEqual(response.data['alias'], self.cst1.alias)
|
||||
|
||||
|
||||
class TestInlineSynthesis(EndpointTester):
|
||||
|
|
|
@ -41,7 +41,6 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
|||
if self.action in [
|
||||
'load_trs',
|
||||
'create_cst',
|
||||
'rename_cst',
|
||||
'update_cst',
|
||||
'move_cst',
|
||||
'delete_multiple_cst',
|
||||
|
@ -102,7 +101,7 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
|||
tags=['RSForm'],
|
||||
request=s.CstUpdateSerializer,
|
||||
responses={
|
||||
c.HTTP_200_OK: s.CstInfoSerializer,
|
||||
c.HTTP_200_OK: s.RSFormParseSerializer,
|
||||
c.HTTP_400_BAD_REQUEST: None,
|
||||
c.HTTP_403_FORBIDDEN: None,
|
||||
c.HTTP_404_NOT_FOUND: None
|
||||
|
@ -120,9 +119,22 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
|||
with transaction.atomic():
|
||||
old_data = schema.update_cst(cst, data)
|
||||
PropagationFacade.after_update_cst(schema, cst, data, old_data)
|
||||
if 'alias' in data and data['alias'] != cst.alias:
|
||||
cst.refresh_from_db()
|
||||
changed_type = 'cst_type' in data and cst.cst_type != data['cst_type']
|
||||
mapping = {cst.alias: data['alias']}
|
||||
cst.alias = data['alias']
|
||||
if changed_type:
|
||||
cst.cst_type = data['cst_type']
|
||||
cst.save()
|
||||
schema.apply_mapping(mapping=mapping, change_aliases=False)
|
||||
schema.save()
|
||||
cst.refresh_from_db()
|
||||
if changed_type:
|
||||
PropagationFacade.after_change_cst_type(schema, cst)
|
||||
return Response(
|
||||
status=c.HTTP_200_OK,
|
||||
data=s.CstInfoSerializer(m.Constituenta.objects.get(pk=request.data['target'])).data
|
||||
data=s.RSFormParseSerializer(schema.model).data
|
||||
)
|
||||
|
||||
@extend_schema(
|
||||
|
@ -169,43 +181,6 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
|||
}
|
||||
)
|
||||
|
||||
@extend_schema(
|
||||
summary='rename constituenta',
|
||||
tags=['Constituenta'],
|
||||
request=s.CstRenameSerializer,
|
||||
responses={
|
||||
c.HTTP_200_OK: s.NewCstResponse,
|
||||
c.HTTP_400_BAD_REQUEST: None,
|
||||
c.HTTP_403_FORBIDDEN: None,
|
||||
c.HTTP_404_NOT_FOUND: None
|
||||
}
|
||||
)
|
||||
@action(detail=True, methods=['patch'], url_path='rename-cst')
|
||||
def rename_cst(self, request: Request, pk) -> HttpResponse:
|
||||
''' Rename constituenta possibly changing type. '''
|
||||
model = self._get_item()
|
||||
serializer = s.CstRenameSerializer(data=request.data, context={'schema': model})
|
||||
serializer.is_valid(raise_exception=True)
|
||||
cst = cast(m.Constituenta, serializer.validated_data['target'])
|
||||
changed_type = cst.cst_type != serializer.validated_data['cst_type']
|
||||
mapping = {cst.alias: serializer.validated_data['alias']}
|
||||
schema = m.RSForm(model)
|
||||
with transaction.atomic():
|
||||
cst.alias = serializer.validated_data['alias']
|
||||
cst.cst_type = serializer.validated_data['cst_type']
|
||||
cst.save()
|
||||
schema.apply_mapping(mapping=mapping, change_aliases=False)
|
||||
schema.save()
|
||||
cst.refresh_from_db()
|
||||
if changed_type:
|
||||
PropagationFacade.after_change_cst_type(schema, cst)
|
||||
return Response(
|
||||
status=c.HTTP_200_OK,
|
||||
data={
|
||||
'new_cst': s.CstInfoSerializer(cst).data,
|
||||
'schema': s.RSFormParseSerializer(schema.model).data
|
||||
}
|
||||
)
|
||||
|
||||
@extend_schema(
|
||||
summary='execute substitutions',
|
||||
|
|
|
@ -27,7 +27,7 @@ export function ApplicationLayout() {
|
|||
<NavigationState>
|
||||
<div className='min-w-80 antialiased h-full max-w-480 mx-auto'>
|
||||
<ToasterThemed
|
||||
className={clsx('sm:text-[14px]/[20px] text-[12px]/[16px]', noNavigationAnimation ? 'mt-6' : 'mt-14')}
|
||||
className={clsx('sm:text-[14px]/[20px] text-[12px]/[16px]', noNavigationAnimation ? 'mt-10' : 'mt-18')}
|
||||
aria-label='Оповещения'
|
||||
autoClose={3000}
|
||||
draggable={false}
|
||||
|
|
|
@ -8,7 +8,15 @@ import { generateAlias } from '@/features/rsform/models/rsform-api';
|
|||
import { useCstSearchStore } from '@/features/rsform/stores/cst-search';
|
||||
|
||||
import { MiniButton } from '@/components/control';
|
||||
import { IconClone, IconDestroy, IconMoveDown, IconMoveUp, IconNewItem, IconRSForm } from '@/components/icons';
|
||||
import {
|
||||
IconClone,
|
||||
IconDestroy,
|
||||
IconEdit2,
|
||||
IconMoveDown,
|
||||
IconMoveUp,
|
||||
IconNewItem,
|
||||
IconRSForm
|
||||
} from '@/components/icons';
|
||||
import { cn } from '@/components/utils';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { PARAMETER, prefixes } from '@/utils/constants';
|
||||
|
@ -20,6 +28,7 @@ interface ToolbarConstituentsProps {
|
|||
activeCst: IConstituenta | null;
|
||||
setActive: (cstID: number) => void;
|
||||
resetActive: () => void;
|
||||
onEditActive: () => void;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
|
@ -28,6 +37,7 @@ export function ToolbarConstituents({
|
|||
activeCst,
|
||||
setActive,
|
||||
resetActive,
|
||||
onEditActive,
|
||||
isMutable,
|
||||
className
|
||||
}: ToolbarConstituentsProps) {
|
||||
|
@ -160,6 +170,13 @@ export function ToolbarConstituents({
|
|||
onClick={navigateRSForm}
|
||||
/>
|
||||
|
||||
<MiniButton
|
||||
title='Редактировать конституенту'
|
||||
icon={<IconEdit2 size='1rem' className='icon-primary' />}
|
||||
onClick={onEditActive}
|
||||
disabled={!isMutable || isProcessing || !activeCst}
|
||||
/>
|
||||
|
||||
<MiniButton
|
||||
title='Создать конституенту'
|
||||
icon={<IconNewItem size='1rem' className='icon-green' />}
|
||||
|
|
|
@ -5,6 +5,7 @@ import { RSFormStats } from '@/features/rsform/components/rsform-stats';
|
|||
import { ViewConstituents } from '@/features/rsform/components/view-constituents';
|
||||
|
||||
import { useFitHeight } from '@/stores/app-layout';
|
||||
import { notImplemented } from '@/utils/utils';
|
||||
|
||||
import { ToolbarConstituents } from './toolbar-constituents';
|
||||
|
||||
|
@ -27,6 +28,7 @@ export function ViewSchema({ schemaID, isMutable }: ViewSchemaProps) {
|
|||
schema={schema}
|
||||
activeCst={activeCst}
|
||||
isMutable={isMutable}
|
||||
onEditActive={notImplemented}
|
||||
setActive={setActiveID}
|
||||
resetActive={() => setActiveID(null)}
|
||||
/>
|
||||
|
|
|
@ -6,7 +6,6 @@ import { infoMsg } from '@/utils/labels';
|
|||
|
||||
import {
|
||||
type ICheckConstituentaDTO,
|
||||
type IConstituentaBasicsDTO,
|
||||
type IConstituentaCreatedResponse,
|
||||
type IConstituentaList,
|
||||
type ICreateConstituentaDTO,
|
||||
|
@ -14,12 +13,10 @@ import {
|
|||
type IInlineSynthesisDTO,
|
||||
type IMoveConstituentsDTO,
|
||||
type IProduceStructureResponse,
|
||||
type IRenameConstituentaDTO,
|
||||
type IRSFormDTO,
|
||||
type IRSFormUploadDTO,
|
||||
type ISubstitutionsDTO,
|
||||
type IUpdateConstituentaDTO,
|
||||
schemaConstituentaBasics,
|
||||
schemaConstituentaCreatedResponse,
|
||||
schemaExpressionParse,
|
||||
schemaProduceStructureResponse,
|
||||
|
@ -74,8 +71,8 @@ export const rsformsApi = {
|
|||
}
|
||||
}),
|
||||
updateConstituenta: ({ itemID, data }: { itemID: number; data: IUpdateConstituentaDTO }) =>
|
||||
axiosPatch<IUpdateConstituentaDTO, IConstituentaBasicsDTO>({
|
||||
schema: schemaConstituentaBasics,
|
||||
axiosPatch<IUpdateConstituentaDTO, IRSFormDTO>({
|
||||
schema: schemaRSForm,
|
||||
endpoint: `/api/rsforms/${itemID}/update-cst`,
|
||||
request: {
|
||||
data: data,
|
||||
|
@ -91,15 +88,6 @@ export const rsformsApi = {
|
|||
successMessage: infoMsg.constituentsDestroyed(data.items.length)
|
||||
}
|
||||
}),
|
||||
renameConstituenta: ({ itemID, data }: { itemID: number; data: IRenameConstituentaDTO }) =>
|
||||
axiosPatch<IRenameConstituentaDTO, IConstituentaCreatedResponse>({
|
||||
schema: schemaConstituentaCreatedResponse,
|
||||
endpoint: `/api/rsforms/${itemID}/rename-cst`,
|
||||
request: {
|
||||
data: data,
|
||||
successMessage: infoMsg.changesSaved
|
||||
}
|
||||
}),
|
||||
substituteConstituents: ({ itemID, data }: { itemID: number; data: ISubstitutionsDTO }) =>
|
||||
axiosPatch<ISubstitutionsDTO, IRSFormDTO>({
|
||||
schema: schemaRSForm,
|
||||
|
|
|
@ -64,9 +64,6 @@ export type IConstituentaCreatedResponse = z.infer<typeof schemaConstituentaCrea
|
|||
/** Represents data, used in updating persistent attributes in {@link IConstituenta}. */
|
||||
export type IUpdateConstituentaDTO = z.infer<typeof schemaUpdateConstituenta>;
|
||||
|
||||
/** Represents data, used in renaming {@link IConstituenta}. */
|
||||
export type IRenameConstituentaDTO = z.infer<typeof schemaRenameConstituenta>;
|
||||
|
||||
/** Represents data, used in ordering a list of {@link IConstituenta}. */
|
||||
export interface IMoveConstituentsDTO {
|
||||
items: number[];
|
||||
|
@ -344,6 +341,8 @@ export const schemaConstituentaCreatedResponse = z.strictObject({
|
|||
export const schemaUpdateConstituenta = z.strictObject({
|
||||
target: z.number(),
|
||||
item_data: z.strictObject({
|
||||
alias: z.string().optional(),
|
||||
cst_type: schemaCstType.optional(),
|
||||
convention: z.string().optional(),
|
||||
definition_formal: z.string().optional(),
|
||||
definition_raw: z.string().optional(),
|
||||
|
@ -352,12 +351,6 @@ export const schemaUpdateConstituenta = z.strictObject({
|
|||
})
|
||||
});
|
||||
|
||||
export const schemaRenameConstituenta = z.strictObject({
|
||||
target: z.number(),
|
||||
alias: z.string(),
|
||||
cst_type: schemaCstType
|
||||
});
|
||||
|
||||
export const schemaProduceStructureResponse = z.strictObject({
|
||||
cst_list: z.array(z.number()),
|
||||
schema: schemaRSForm
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
import { useUpdateTimestamp } from '@/features/library/backend/use-update-timestamp';
|
||||
|
||||
import { KEYS } from '@/backend/configuration';
|
||||
|
||||
import { rsformsApi } from './api';
|
||||
import { type IRenameConstituentaDTO } from './types';
|
||||
|
||||
export const useRenameConstituenta = () => {
|
||||
const client = useQueryClient();
|
||||
const { updateTimestamp } = useUpdateTimestamp();
|
||||
const mutation = useMutation({
|
||||
mutationKey: [KEYS.global_mutation, rsformsApi.baseKey, 'rename-constituenta'],
|
||||
mutationFn: rsformsApi.renameConstituenta,
|
||||
onSuccess: async data => {
|
||||
client.setQueryData(rsformsApi.getRSFormQueryOptions({ itemID: data.schema.id }).queryKey, data.schema);
|
||||
updateTimestamp(data.schema.id);
|
||||
|
||||
await Promise.allSettled([
|
||||
client.invalidateQueries({ queryKey: [KEYS.oss] }),
|
||||
client.invalidateQueries({
|
||||
queryKey: [rsformsApi.baseKey],
|
||||
predicate: query => query.queryKey.length > 2 && query.queryKey[2] !== String(data.schema.id)
|
||||
})
|
||||
]);
|
||||
},
|
||||
onError: () => client.invalidateQueries()
|
||||
});
|
||||
return {
|
||||
renameConstituenta: (data: { itemID: number; data: IRenameConstituentaDTO }) => mutation.mutateAsync(data)
|
||||
};
|
||||
};
|
|
@ -13,12 +13,16 @@ export const useUpdateConstituenta = () => {
|
|||
const mutation = useMutation({
|
||||
mutationKey: [KEYS.global_mutation, rsformsApi.baseKey, 'update-constituenta'],
|
||||
mutationFn: rsformsApi.updateConstituenta,
|
||||
onSuccess: async (_, variables) => {
|
||||
updateTimestamp(variables.itemID);
|
||||
onSuccess: async (data, _) => {
|
||||
client.setQueryData(rsformsApi.getRSFormQueryOptions({ itemID: data.id }).queryKey, data);
|
||||
updateTimestamp(data.id);
|
||||
|
||||
await Promise.allSettled([
|
||||
client.invalidateQueries({ queryKey: [KEYS.oss] }),
|
||||
client.invalidateQueries({ queryKey: [rsformsApi.baseKey] })
|
||||
client.invalidateQueries({
|
||||
queryKey: [rsformsApi.baseKey],
|
||||
predicate: query => query.queryKey.length > 2 && query.queryKey[2] !== String(data.id)
|
||||
})
|
||||
]);
|
||||
},
|
||||
onError: () => client.invalidateQueries()
|
||||
|
|
|
@ -9,8 +9,8 @@ import { TextInput } from '@/components/input';
|
|||
import { ModalForm } from '@/components/modal';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
|
||||
import { type CstType, type IRenameConstituentaDTO, schemaRenameConstituenta } from '../backend/types';
|
||||
import { useRenameConstituenta } from '../backend/use-rename-constituenta';
|
||||
import { type CstType, type IUpdateConstituentaDTO, schemaUpdateConstituenta } from '../backend/types';
|
||||
import { useUpdateConstituenta } from '../backend/use-update-constituenta';
|
||||
import { SelectCstType } from '../components/select-cst-type';
|
||||
import { type IConstituenta, type IRSForm } from '../models/rsform';
|
||||
import { generateAlias, validateNewAlias } from '../models/rsform-api';
|
||||
|
@ -22,27 +22,29 @@ export interface DlgRenameCstProps {
|
|||
|
||||
export function DlgRenameCst() {
|
||||
const { schema, target } = useDialogsStore(state => state.props as DlgRenameCstProps);
|
||||
const { renameConstituenta: cstRename } = useRenameConstituenta();
|
||||
const { updateConstituenta: cstUpdate } = useUpdateConstituenta();
|
||||
|
||||
const { register, setValue, handleSubmit, control } = useForm<IRenameConstituentaDTO>({
|
||||
resolver: zodResolver(schemaRenameConstituenta),
|
||||
const { register, setValue, handleSubmit, control } = useForm<IUpdateConstituentaDTO>({
|
||||
resolver: zodResolver(schemaUpdateConstituenta),
|
||||
defaultValues: {
|
||||
target: target.id,
|
||||
alias: target.alias,
|
||||
cst_type: target.cst_type
|
||||
item_data: {
|
||||
alias: target.alias,
|
||||
cst_type: target.cst_type
|
||||
}
|
||||
}
|
||||
});
|
||||
const alias = useWatch({ control, name: 'alias' });
|
||||
const cst_type = useWatch({ control, name: 'cst_type' });
|
||||
const alias = useWatch({ control, name: 'item_data.alias' })!;
|
||||
const cst_type = useWatch({ control, name: 'item_data.cst_type' })!;
|
||||
const isValid = alias !== target.alias && validateNewAlias(alias, cst_type, schema);
|
||||
|
||||
function onSubmit(data: IRenameConstituentaDTO) {
|
||||
return cstRename({ itemID: schema.id, data: data });
|
||||
function onSubmit(data: IUpdateConstituentaDTO) {
|
||||
return cstUpdate({ itemID: schema.id, data: data });
|
||||
}
|
||||
|
||||
function handleChangeType(newType: CstType) {
|
||||
setValue('cst_type', newType);
|
||||
setValue('alias', generateAlias(newType, schema), { shouldValidate: true });
|
||||
setValue('item_data.cst_type', newType);
|
||||
setValue('item_data.alias', generateAlias(newType, schema), { shouldValidate: true });
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -63,7 +65,7 @@ export function DlgRenameCst() {
|
|||
/>
|
||||
<TextInput
|
||||
id='dlg_cst_alias' //
|
||||
{...register('alias')}
|
||||
{...register('item_data.alias')}
|
||||
dense
|
||||
label='Имя'
|
||||
className='w-28'
|
||||
|
|
Loading…
Reference in New Issue
Block a user