R: Rework constituenta editing endpoints + small ui fix
Some checks failed
Frontend CI / build (22.x) (push) Waiting to run
Frontend CI / notify-failure (push) Blocked by required conditions
Backend CI / build (3.12) (push) Has been cancelled
Backend CI / notify-failure (push) Has been cancelled

This commit is contained in:
Ivan 2025-07-08 18:28:33 +03:00
parent 6f7b1a357c
commit c7afd4b065
13 changed files with 111 additions and 238 deletions

View File

@ -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}')

View File

@ -16,7 +16,6 @@ from .data_access import (
CstInfoSerializer,
CstListSerializer,
CstMoveSerializer,
CstRenameSerializer,
CstSubstituteSerializer,
CstTargetSerializer,
CstUpdateSerializer,

View File

@ -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'))

View File

@ -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):

View File

@ -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',

View File

@ -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}

View File

@ -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' />}

View File

@ -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)}
/>

View File

@ -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,

View File

@ -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

View File

@ -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)
};
};

View File

@ -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()

View File

@ -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'