mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 13:00:39 +03:00
Refactor constituenta move functionality
This commit is contained in:
parent
2b7a4c04ce
commit
a5f3539798
|
@ -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>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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)}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user