Refactor constituenta move functionality

This commit is contained in:
IRBorisov 2024-02-03 15:49:23 +03:00
parent 2b7a4c04ce
commit a5f3539798
4 changed files with 97 additions and 58 deletions

View File

@ -1,7 +1,7 @@
'use client'; 'use client';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { BiDuplicate, BiPlusCircle, BiReset, BiTrash } from 'react-icons/bi'; import { BiDownvote, BiDuplicate, BiPlusCircle, BiReset, BiTrash, BiUpvote } from 'react-icons/bi';
import { FiSave } from 'react-icons/fi'; import { FiSave } from 'react-icons/fi';
import HelpButton from '@/components/Help/HelpButton'; import HelpButton from '@/components/Help/HelpButton';
@ -16,6 +16,8 @@ interface ConstituentaToolbarProps {
onSubmit: () => void; onSubmit: () => void;
onReset: () => void; onReset: () => void;
onMoveUp: () => void;
onMoveDown: () => void;
onDelete: () => void; onDelete: () => void;
onClone: () => void; onClone: () => void;
onCreate: () => void; onCreate: () => void;
@ -26,6 +28,8 @@ function ConstituentaToolbar({
isModified, isModified,
onSubmit, onSubmit,
onReset, onReset,
onMoveUp,
onMoveDown,
onDelete, onDelete,
onClone, onClone,
onCreate onCreate
@ -63,6 +67,18 @@ function ConstituentaToolbar({
onClick={onDelete} onClick={onDelete}
icon={<BiTrash size='1.25rem' className={isMutable ? 'clr-text-warning' : ''} />} icon={<BiTrash size='1.25rem' className={isMutable ? 'clr-text-warning' : ''} />}
/> />
<MiniButton
title='Переместить вверх [Alt + вверх]'
icon={<BiUpvote size='1.25rem' className={isMutable ? 'clr-text-primary' : ''} />}
disabled={!isMutable}
onClick={onMoveUp}
/>
<MiniButton
title='Переместить вниз [Alt + вниз]'
icon={<BiDownvote size='1.25rem' className={isMutable ? 'clr-text-primary' : ''} />}
disabled={!isMutable}
onClick={onMoveDown}
/>
<HelpButton topic={HelpTopic.CONSTITUENTA} offset={4} /> <HelpButton topic={HelpTopic.CONSTITUENTA} offset={4} />
</Overlay> </Overlay>
); );

View File

@ -26,6 +26,8 @@ interface EditorConstituentaProps {
isModified: boolean; isModified: boolean;
setIsModified: React.Dispatch<React.SetStateAction<boolean>>; setIsModified: React.Dispatch<React.SetStateAction<boolean>>;
onMoveUp: () => void;
onMoveDown: () => void;
onOpenEdit: (cstID: number) => void; onOpenEdit: (cstID: number) => void;
onClone: () => void; onClone: () => void;
onCreate: (type?: CstType) => void; onCreate: (type?: CstType) => void;
@ -40,11 +42,13 @@ function EditorConstituenta({
isModified, isModified,
setIsModified, setIsModified,
activeCst, activeCst,
onEditTerm, onMoveUp,
onMoveDown,
onOpenEdit,
onClone, onClone,
onCreate, onCreate,
onRename, onRename,
onOpenEdit, onEditTerm,
onDelete onDelete
}: EditorConstituentaProps) { }: EditorConstituentaProps) {
const windowSize = useWindowSize(); const windowSize = useWindowSize();
@ -99,6 +103,8 @@ function EditorConstituenta({
<ConstituentaToolbar <ConstituentaToolbar
isMutable={!disabled} isMutable={!disabled}
isModified={isModified} isModified={isModified}
onMoveUp={onMoveUp}
onMoveDown={onMoveDown}
onSubmit={initiateSubmit} onSubmit={initiateSubmit}
onReset={() => setToggleReset(prev => !prev)} onReset={() => setToggleReset(prev => !prev)}
onDelete={onDelete} onDelete={onDelete}

View File

@ -4,16 +4,18 @@ import { useLayoutEffect, useState } from 'react';
import { type RowSelectionState } from '@/components/DataTable'; import { type RowSelectionState } from '@/components/DataTable';
import SelectedCounter from '@/components/SelectedCounter'; import SelectedCounter from '@/components/SelectedCounter';
import { useRSForm } from '@/context/RSFormContext'; import { CstType, IRSForm } from '@/models/rsform';
import { CstType, ICstMovetoData } from '@/models/rsform';
import RSListToolbar from './RSListToolbar'; import RSListToolbar from './RSListToolbar';
import RSTable from './RSTable'; import RSTable from './RSTable';
interface EditorRSListProps { interface EditorRSListProps {
schema?: IRSForm;
isMutable: boolean; isMutable: boolean;
selected: number[]; selected: number[];
setSelected: React.Dispatch<React.SetStateAction<number[]>>; setSelected: React.Dispatch<React.SetStateAction<number[]>>;
onMoveUp: () => void;
onMoveDown: () => void;
onOpenEdit: (cstID: number) => void; onOpenEdit: (cstID: number) => void;
onClone: () => void; onClone: () => void;
onCreate: (type?: CstType) => void; onCreate: (type?: CstType) => void;
@ -21,16 +23,17 @@ interface EditorRSListProps {
} }
function EditorRSList({ function EditorRSList({
schema,
selected, selected,
setSelected, setSelected,
isMutable, isMutable,
onMoveUp,
onMoveDown,
onOpenEdit, onOpenEdit,
onClone, onClone,
onCreate, onCreate,
onDelete onDelete
}: EditorRSListProps) { }: EditorRSListProps) {
const { schema, cstMoveTo } = useRSForm();
const [rowSelection, setRowSelection] = useState<RowSelectionState>({}); const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
useLayoutEffect(() => { useLayoutEffect(() => {
@ -60,52 +63,6 @@ function EditorRSList({
} }
} }
// Move selected cst up
function handleMoveUp() {
if (!schema?.items || selected.length === 0) {
return;
}
const currentIndex = schema.items.reduce((prev, cst, index) => {
if (!selected.includes(cst.id)) {
return prev;
} else if (prev === -1) {
return index;
}
return Math.min(prev, index);
}, -1);
const target = Math.max(0, currentIndex - 1) + 1;
const data = {
items: selected,
move_to: target
};
cstMoveTo(data);
}
// Move selected cst down
function handleMoveDown() {
if (!schema?.items || selected.length === 0) {
return;
}
let count = 0;
const currentIndex = schema.items.reduce((prev, cst, index) => {
if (!selected.includes(cst.id)) {
return prev;
} else {
count += 1;
if (prev === -1) {
return index;
}
return Math.max(prev, index);
}
}, -1);
const target = Math.min(schema.items.length - 1, currentIndex - count + 2) + 1;
const data: ICstMovetoData = {
items: selected,
move_to: target
};
cstMoveTo(data);
}
// Implement hotkeys for working with constituents table // Implement hotkeys for working with constituents table
function handleTableKey(event: React.KeyboardEvent<HTMLDivElement>) { function handleTableKey(event: React.KeyboardEvent<HTMLDivElement>) {
if (!isMutable) { if (!isMutable) {
@ -129,8 +86,8 @@ function EditorRSList({
if (selected.length > 0) { if (selected.length > 0) {
// prettier-ignore // prettier-ignore
switch (code) { switch (code) {
case 'ArrowUp': handleMoveUp(); return true; case 'ArrowUp': onMoveUp(); return true;
case 'ArrowDown': handleMoveDown(); return true; case 'ArrowDown': onMoveDown(); return true;
case 'KeyV': onClone(); return true; case 'KeyV': onClone(); return true;
} }
} }
@ -161,8 +118,8 @@ function EditorRSList({
<RSListToolbar <RSListToolbar
selectedCount={selected.length} selectedCount={selected.length}
isMutable={isMutable} isMutable={isMutable}
onMoveUp={handleMoveUp} onMoveUp={onMoveUp}
onMoveDown={handleMoveDown} onMoveDown={onMoveDown}
onClone={onClone} onClone={onClone}
onCreate={onCreate} onCreate={onCreate}
onDelete={onDelete} onDelete={onDelete}

View File

@ -28,7 +28,15 @@ import DlgRenameCst from '@/dialogs/DlgRenameCst';
import DlgUploadRSForm from '@/dialogs/DlgUploadRSForm'; import DlgUploadRSForm from '@/dialogs/DlgUploadRSForm';
import useQueryStrings from '@/hooks/useQueryStrings'; import useQueryStrings from '@/hooks/useQueryStrings';
import { UserAccessMode } from '@/models/miscellaneous'; import { UserAccessMode } from '@/models/miscellaneous';
import { CstType, IConstituenta, ICstCreateData, ICstRenameData, ICstUpdateData, TermForm } from '@/models/rsform'; import {
CstType,
IConstituenta,
ICstCreateData,
ICstMovetoData,
ICstRenameData,
ICstUpdateData,
TermForm
} from '@/models/rsform';
import { generateAlias } from '@/models/rsformAPI'; import { generateAlias } from '@/models/rsformAPI';
import { EXTEOR_TRS_FILE, prefixes, TIMEOUT_UI_REFRESH } from '@/utils/constants'; import { EXTEOR_TRS_FILE, prefixes, TIMEOUT_UI_REFRESH } from '@/utils/constants';
@ -66,6 +74,7 @@ function RSTabs() {
subscribe, subscribe,
unsubscribe, unsubscribe,
cstUpdate, cstUpdate,
cstMoveTo,
resetAliases resetAliases
} = useRSForm(); } = useRSForm();
const { destroyItem } = useLibrary(); const { destroyItem } = useLibrary();
@ -262,6 +271,52 @@ function RSTabs() {
const onReindex = useCallback(() => resetAliases(() => toast.success('Имена конституент обновлены')), [resetAliases]); const onReindex = useCallback(() => resetAliases(() => toast.success('Имена конституент обновлены')), [resetAliases]);
// Move selected cst up
function handleMoveUp() {
if (!schema?.items || selected.length === 0) {
return;
}
const currentIndex = schema.items.reduce((prev, cst, index) => {
if (!selected.includes(cst.id)) {
return prev;
} else if (prev === -1) {
return index;
}
return Math.min(prev, index);
}, -1);
const target = Math.max(0, currentIndex - 1) + 1;
const data = {
items: selected,
move_to: target
};
cstMoveTo(data);
}
// Move selected cst down
function handleMoveDown() {
if (!schema?.items || selected.length === 0) {
return;
}
let count = 0;
const currentIndex = schema.items.reduce((prev, cst, index) => {
if (!selected.includes(cst.id)) {
return prev;
} else {
count += 1;
if (prev === -1) {
return index;
}
return Math.max(prev, index);
}
}, -1);
const target = Math.min(schema.items.length - 1, currentIndex - count + 2) + 1;
const data: ICstMovetoData = {
items: selected,
move_to: target
};
cstMoveTo(data);
}
const handleDeleteCst = useCallback( const handleDeleteCst = useCallback(
(deleted: number[]) => { (deleted: number[]) => {
if (!schema) { if (!schema) {
@ -479,9 +534,12 @@ function RSTabs() {
<TabPanel forceRender style={{ display: activeTab === RSTabID.CST_LIST ? '' : 'none' }}> <TabPanel forceRender style={{ display: activeTab === RSTabID.CST_LIST ? '' : 'none' }}>
<EditorRSList <EditorRSList
schema={schema}
selected={selected} selected={selected}
setSelected={setSelected} setSelected={setSelected}
isMutable={isMutable} isMutable={isMutable}
onMoveUp={handleMoveUp}
onMoveDown={handleMoveDown}
onOpenEdit={onOpenCst} onOpenEdit={onOpenCst}
onClone={handleCloneCst} onClone={handleCloneCst}
onCreate={type => promptCreateCst(type, type !== undefined)} onCreate={type => promptCreateCst(type, type !== undefined)}
@ -496,6 +554,8 @@ function RSTabs() {
isModified={isModified} isModified={isModified}
setIsModified={setIsModified} setIsModified={setIsModified}
activeCst={activeCst} activeCst={activeCst}
onMoveUp={handleMoveUp}
onMoveDown={handleMoveDown}
onOpenEdit={onOpenCst} onOpenEdit={onOpenCst}
onClone={handleCloneCst} onClone={handleCloneCst}
onCreate={type => promptCreateCst(type, false)} onCreate={type => promptCreateCst(type, false)}