F: Improve constituent relocation in OSS

This commit is contained in:
Ivan 2025-07-25 13:12:26 +03:00
parent e00b8da6ee
commit 98f811e252
5 changed files with 34 additions and 14 deletions

View File

@ -1,3 +1,5 @@
import { globalIDs } from '@/utils/constants';
import { type Button } from '../props';
import { cn } from '../utils';
@ -15,7 +17,17 @@ interface SubmitButtonProps extends Button {
/**
* Displays submit type button with icon and text.
*/
export function SubmitButton({ text = 'ОК', icon, disabled, loading, className, ...restProps }: SubmitButtonProps) {
export function SubmitButton({
text = 'ОК',
icon,
title,
titleHtml,
hideTitle,
disabled,
loading,
className,
...restProps
}: SubmitButtonProps) {
return (
<button
type='submit'
@ -28,6 +40,10 @@ export function SubmitButton({ text = 'ОК', icon, disabled, loading, className
loading && 'cursor-progress',
className
)}
data-tooltip-id={!!title || !!titleHtml ? globalIDs.tooltip : undefined}
data-tooltip-html={titleHtml}
data-tooltip-content={title}
data-tooltip-hidden={hideTitle}
disabled={disabled || loading}
{...restProps}
>

View File

@ -180,8 +180,7 @@ export const ossApi = {
}),
relocateConstituents: (data: IRelocateConstituentsDTO) =>
axiosPost<IRelocateConstituentsDTO, IOperationSchemaDTO>({
schema: schemaOperationSchema,
axiosPost<IRelocateConstituentsDTO>({
endpoint: `/api/oss/relocate-constituents`,
request: {
data: data,

View File

@ -10,8 +10,7 @@ export const useRelocateConstituents = () => {
const mutation = useMutation({
mutationKey: [KEYS.global_mutation, ossApi.baseKey, 'relocate-constituents'],
mutationFn: ossApi.relocateConstituents,
onSuccess: async data => {
client.setQueryData(ossApi.getOssQueryOptions({ itemID: data.id }).queryKey, data);
onSuccess: async () => {
await Promise.allSettled([
client.invalidateQueries({ queryKey: KEYS.composite.libraryList }),
client.invalidateQueries({ queryKey: [KEYS.rsform] })

View File

@ -35,18 +35,14 @@ export function DlgRelocateConstituents() {
const { updateLayout: updatePositions } = useUpdateLayout();
const { relocateConstituents } = useRelocateConstituents();
const {
handleSubmit,
control,
setValue,
formState: { isValid }
} = useForm<IRelocateConstituentsDTO>({
const { handleSubmit, control, setValue } = useForm<IRelocateConstituentsDTO>({
resolver: zodResolver(schemaRelocateConstituents),
defaultValues: {
items: []
},
mode: 'onChange'
});
const selected = useWatch({ control, name: 'items' });
const destination = useWatch({ control, name: 'destination' });
const destinationItem = destination ? libraryItems.find(item => item.id === destination) ?? null : null;
@ -77,6 +73,11 @@ export function DlgRelocateConstituents() {
return getRelocateCandidates(operation.id, destinationOperation!.id, sourceData.schema, oss);
})();
const moveTarget = filteredConstituents
.filter(item => !item.is_inherited && selected.includes(item.id))
.map(item => item.id);
const isValid = moveTarget.length > 0;
function toggleDirection() {
setDirectionUp(prev => !prev);
setValue('destination', null);
@ -98,6 +99,7 @@ export function DlgRelocateConstituents() {
}
function onSubmit(data: IRelocateConstituentsDTO) {
data.items = moveTarget;
if (!layout || JSON.stringify(layout) === JSON.stringify(oss.layout)) {
return relocateConstituents(data);
} else {
@ -114,6 +116,7 @@ export function DlgRelocateConstituents() {
header='Перенос конституент'
submitText='Переместить'
canSubmit={isValid && destinationItem !== undefined}
submitInvalidTooltip='Необходимо выбрать хотя бы одну собственную конституенту'
onSubmit={event => void handleSubmit(onSubmit)(event)}
className='w-160 h-132 py-3 px-6'
helpTopic={HelpTopic.UI_RELOCATE_CST}

View File

@ -446,11 +446,12 @@ export function getRelocateCandidates(
return [];
}
const addedCst = schema.items.filter(item => !item.is_inherited);
if (node.outputs.includes(destination)) {
return addedCst;
return schema.items;
}
const addedCst = schema.items.filter(item => !item.is_inherited).map(cst => cst.id);
const unreachableBases: number[] = [];
for (const cst of schema.items.filter(item => item.is_inherited)) {
if (cst.parent_schema == destinationSchema) {
@ -466,5 +467,7 @@ export function getRelocateCandidates(
unreachableBases.push(cst.id);
}
const unreachable = schema.graph.expandAllOutputs(unreachableBases);
return addedCst.filter(cst => !unreachable.includes(cst.id));
return schema.items.filter(
cst => cst.parent_schema === destinationSchema || (addedCst.includes(cst.id) && !unreachable.includes(cst.id))
);
}