mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 04:50:36 +03:00
Refactor dialogs
This commit is contained in:
parent
4f45b9978e
commit
44cc9371e4
|
@ -7,25 +7,24 @@ import SubmitButton from '../../components/Common/SubmitButton';
|
|||
import TextArea from '../../components/Common/TextArea';
|
||||
import { DumpBinIcon, SaveIcon, SmallPlusIcon } from '../../components/Icons';
|
||||
import { useRSForm } from '../../context/RSFormContext';
|
||||
import { type CstType, EditMode, type ICstCreateData, ICstUpdateData, SyntaxTree } from '../../utils/models';
|
||||
import { createAliasFor, getCstTypeLabel } from '../../utils/staticUI';
|
||||
import DlgCreateCst from './DlgCreateCst';
|
||||
import { type CstType, EditMode, ICstUpdateData, SyntaxTree } from '../../utils/models';
|
||||
import { getCstTypeLabel } from '../../utils/staticUI';
|
||||
import EditorRSExpression from './EditorRSExpression';
|
||||
import ViewSideConstituents from './elements/ViewSideConstituents';
|
||||
import { RSTabsList } from './RSTabs';
|
||||
|
||||
interface EditorConstituentaProps {
|
||||
onShowAST: (ast: SyntaxTree) => void
|
||||
onShowCreateCst: (position: number | undefined, type: CstType | undefined) => void
|
||||
}
|
||||
|
||||
function EditorConstituenta({onShowAST}: EditorConstituentaProps) {
|
||||
function EditorConstituenta({ onShowAST, onShowCreateCst }: EditorConstituentaProps) {
|
||||
const navigate = useNavigate();
|
||||
const {
|
||||
activeCst, activeID, schema, setActiveID, processing, isEditable,
|
||||
cstDelete, cstUpdate, cstCreate
|
||||
cstDelete, cstUpdate
|
||||
} = useRSForm();
|
||||
|
||||
const [showCstModal, setShowCstModal] = useState(false);
|
||||
const [isModified, setIsModified] = useState(false);
|
||||
const [editMode, setEditMode] = useState(EditMode.TEXT);
|
||||
|
||||
|
@ -107,24 +106,12 @@ function EditorConstituenta({onShowAST}: EditorConstituentaProps) {
|
|||
}, [activeID, schema, cstDelete, navigate]);
|
||||
|
||||
const handleAddNew = useCallback(
|
||||
(type?: CstType) => {
|
||||
if (!activeID || !schema?.items) {
|
||||
() => {
|
||||
if (!activeID || !schema) {
|
||||
return;
|
||||
}
|
||||
if (!type) {
|
||||
setShowCstModal(true);
|
||||
} else {
|
||||
const data: ICstCreateData = {
|
||||
cst_type: type,
|
||||
alias: createAliasFor(type, schema),
|
||||
insert_after: activeID
|
||||
}
|
||||
cstCreate(data, newCst => {
|
||||
navigate(`/rsforms/${schema.id}?tab=${RSTabsList.CST_EDIT}&active=${newCst.id}`);
|
||||
toast.success(`Конституента добавлена: ${newCst.alias}`);
|
||||
});
|
||||
}
|
||||
}, [activeID, schema, cstCreate, navigate]);
|
||||
onShowCreateCst(activeID, activeCst?.cstType);
|
||||
}, [activeID, activeCst?.cstType, schema, onShowCreateCst]);
|
||||
|
||||
const handleRename = useCallback(() => {
|
||||
toast.info('Переименование в разработке');
|
||||
|
@ -136,11 +123,6 @@ function EditorConstituenta({onShowAST}: EditorConstituentaProps) {
|
|||
|
||||
return (
|
||||
<div className='flex items-start w-full gap-2'>
|
||||
{showCstModal && <DlgCreateCst
|
||||
hideWindow={() => { setShowCstModal(false); }}
|
||||
onCreate={handleAddNew}
|
||||
defaultType={activeCst?.cstType as CstType}
|
||||
/>}
|
||||
<form onSubmit={handleSubmit} className='flex-grow min-w-[50rem] max-w-min px-4 py-2 border'>
|
||||
<div className='flex items-start justify-between'>
|
||||
<button type='submit'
|
||||
|
@ -176,7 +158,7 @@ function EditorConstituenta({onShowAST}: EditorConstituentaProps) {
|
|||
<MiniButton
|
||||
tooltip='Создать конституенты после данной'
|
||||
disabled={!isEnabled}
|
||||
onClick={() => { handleAddNew(); }}
|
||||
onClick={handleAddNew}
|
||||
icon={<SmallPlusIcon size={5} color={isEnabled ? 'text-green' : ''} />}
|
||||
/>
|
||||
<MiniButton
|
||||
|
|
|
@ -7,24 +7,23 @@ import Divider from '../../components/Common/Divider';
|
|||
import { ArrowDownIcon, ArrowsRotateIcon, ArrowUpIcon, DumpBinIcon, SmallPlusIcon } from '../../components/Icons';
|
||||
import { useRSForm } from '../../context/RSFormContext';
|
||||
import { useConceptTheme } from '../../context/ThemeContext';
|
||||
import { CstType, type IConstituenta, type ICstCreateData, ICstMovetoData,inferStatus, ParsingStatus, ValueClass } from '../../utils/models'
|
||||
import { createAliasFor, getCstTypePrefix, getCstTypeShortcut, getStatusInfo, getTypeLabel } from '../../utils/staticUI';
|
||||
import DlgCreateCst from './DlgCreateCst';
|
||||
import { CstType, type IConstituenta, ICstMovetoData, inferStatus, ParsingStatus, ValueClass } from '../../utils/models'
|
||||
import { getCstTypePrefix, getCstTypeShortcut, getStatusInfo, getTypeLabel } from '../../utils/staticUI';
|
||||
|
||||
interface EditorItemsProps {
|
||||
onOpenEdit: (cst: IConstituenta) => void
|
||||
onShowCreateCst: (position: number | undefined, type: CstType | undefined, skipDialog?: boolean) => void
|
||||
}
|
||||
|
||||
function EditorItems({ onOpenEdit }: EditorItemsProps) {
|
||||
function EditorItems({ onOpenEdit, onShowCreateCst }: EditorItemsProps) {
|
||||
const {
|
||||
schema, isEditable,
|
||||
cstCreate, cstDelete, cstMoveTo, resetAliases
|
||||
cstDelete, cstMoveTo, resetAliases
|
||||
} = useRSForm();
|
||||
const { noNavigation } = useConceptTheme();
|
||||
const [selected, setSelected] = useState<number[]>([]);
|
||||
const nothingSelected = useMemo(() => selected.length === 0, [selected]);
|
||||
|
||||
const [showCstModal, setShowCstModal] = useState(false);
|
||||
const [toggledClearRows, setToggledClearRows] = useState(false);
|
||||
|
||||
const handleRowClicked = useCallback(
|
||||
|
@ -112,25 +111,18 @@ function EditorItems({ onOpenEdit }: EditorItemsProps) {
|
|||
}, [resetAliases]);
|
||||
|
||||
// Add new constituent
|
||||
const handleAddNew = useCallback((type?: CstType) => {
|
||||
const handleAddNew = useCallback(
|
||||
(type?: CstType) => {
|
||||
if (!schema) {
|
||||
return;
|
||||
}
|
||||
if (!type) {
|
||||
setShowCstModal(true);
|
||||
} else {
|
||||
const selectedPosition = selected.reduce((prev, cstID) => {
|
||||
const position = schema.items.findIndex(cst => cst.id === cstID);
|
||||
return Math.max(position, prev);
|
||||
}, -1) + 1;
|
||||
const data: ICstCreateData = {
|
||||
cst_type: type,
|
||||
alias: createAliasFor(type, schema),
|
||||
insert_after: selectedPosition > 0 ? selectedPosition : null
|
||||
}
|
||||
cstCreate(data, new_cst => toast.success(`Добавлена конституента ${new_cst.alias}`));
|
||||
}
|
||||
}, [schema, selected, cstCreate]);
|
||||
const insert_where = selectedPosition > 0 ? selectedPosition : undefined;
|
||||
onShowCreateCst(insert_where, type, type !== undefined);
|
||||
}, [schema, onShowCreateCst, selected]);
|
||||
|
||||
// Implement hotkeys for working with constituents table
|
||||
function handleTableKey(event: React.KeyboardEvent<HTMLDivElement>) {
|
||||
|
@ -283,11 +275,7 @@ function EditorItems({ onOpenEdit }: EditorItemsProps) {
|
|||
], []
|
||||
);
|
||||
|
||||
return (<>
|
||||
{showCstModal && <DlgCreateCst
|
||||
hideWindow={() => { setShowCstModal(false); }}
|
||||
onCreate={handleAddNew}
|
||||
/>}
|
||||
return (
|
||||
<div className='w-full'>
|
||||
<div
|
||||
className={'flex justify-start w-full gap-1 px-2 py-1 border-y items-center h-[2.2rem] clr-app' +
|
||||
|
@ -376,7 +364,7 @@ function EditorItems({ onOpenEdit }: EditorItemsProps) {
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
</>);
|
||||
);
|
||||
}
|
||||
|
||||
export default EditorItems;
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
import { useCallback, useEffect, useLayoutEffect, useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { TabList, TabPanel, Tabs } from 'react-tabs';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import BackendError from '../../components/BackendError';
|
||||
import ConceptTab from '../../components/Common/ConceptTab';
|
||||
import { Loader } from '../../components/Common/Loader';
|
||||
import { useRSForm } from '../../context/RSFormContext';
|
||||
import useLocalStorage from '../../hooks/useLocalStorage';
|
||||
import { type IConstituenta,SyntaxTree } from '../../utils/models';
|
||||
import { CstType,type IConstituenta, ICstCreateData, SyntaxTree } from '../../utils/models';
|
||||
import { createAliasFor } from '../../utils/staticUI';
|
||||
import DlgCloneRSForm from './DlgCloneRSForm';
|
||||
import DlgCreateCst from './DlgCreateCst';
|
||||
import DlgShowAST from './DlgShowAST';
|
||||
import DlgUploadRSForm from './DlgUploadRSForm';
|
||||
import EditorConstituenta from './EditorConstituenta';
|
||||
|
@ -23,28 +27,64 @@ export enum RSTabsList {
|
|||
}
|
||||
|
||||
function RSTabs() {
|
||||
const { setActiveID, activeID, error, schema, loading } = useRSForm();
|
||||
const [tabIndex, setTabIndex] = useLocalStorage('rsform_edit_tab', RSTabsList.CARD);
|
||||
const navigate = useNavigate();
|
||||
const { setActiveID, activeID, error, schema, loading, cstCreate } = useRSForm();
|
||||
const [activeTab, setActiveTab] = useLocalStorage('rsform_edit_tab', RSTabsList.CARD);
|
||||
const [init, setInit] = useState(false);
|
||||
|
||||
const [showUpload, setShowUpload] = useState(false);
|
||||
|
||||
const [showClone, setShowClone] = useState(false);
|
||||
|
||||
const [syntaxTree, setSyntaxTree] = useState<SyntaxTree>([]);
|
||||
const [showAST, setShowAST] = useState(false);
|
||||
|
||||
const [defaultType, setDefaultType] = useState<CstType | undefined>(undefined);
|
||||
const [insertPosition, setInsertPosition] = useState<number | undefined>(undefined);
|
||||
const [showCreateCst, setShowCreateCst] = useState(false);
|
||||
|
||||
const handleAddNew = useCallback(
|
||||
(type: CstType) => {
|
||||
if (!schema?.items) {
|
||||
return;
|
||||
}
|
||||
const data: ICstCreateData = {
|
||||
cst_type: type,
|
||||
alias: createAliasFor(type, schema),
|
||||
insert_after: insertPosition ?? null
|
||||
}
|
||||
cstCreate(data, newCst => {
|
||||
toast.success(`Конституента добавлена: ${newCst.alias}`);
|
||||
if (activeTab === RSTabsList.CST_EDIT) {
|
||||
navigate(`/rsforms/${schema.id}?tab=${RSTabsList.CST_EDIT}&active=${newCst.id}`);
|
||||
}
|
||||
});
|
||||
}, [schema, cstCreate, insertPosition, navigate, activeTab]);
|
||||
|
||||
const onShowCreateCst = useCallback(
|
||||
(position: number | undefined, type: CstType | undefined, skipDialog?: boolean) => {
|
||||
if (skipDialog && type) {
|
||||
handleAddNew(type);
|
||||
} else {
|
||||
setDefaultType(type);
|
||||
setInsertPosition(position);
|
||||
setShowCreateCst(true);
|
||||
}
|
||||
}, [handleAddNew]);
|
||||
|
||||
const onShowAST = useCallback(
|
||||
(ast: SyntaxTree) => {
|
||||
setSyntaxTree(ast);
|
||||
setShowAST(true);
|
||||
}, [])
|
||||
}, []);
|
||||
|
||||
const onEditCst = (cst: IConstituenta) => {
|
||||
setActiveID(cst.id);
|
||||
setTabIndex(RSTabsList.CST_EDIT)
|
||||
setActiveTab(RSTabsList.CST_EDIT)
|
||||
};
|
||||
|
||||
const onSelectTab = (index: number) => {
|
||||
setTabIndex(index);
|
||||
setActiveTab(index);
|
||||
};
|
||||
|
||||
useLayoutEffect(() => {
|
||||
|
@ -66,17 +106,17 @@ function RSTabs() {
|
|||
useEffect(() => {
|
||||
const url = new URL(window.location.href);
|
||||
const tabQuery = url.searchParams.get('tab');
|
||||
setTabIndex(Number(tabQuery) || RSTabsList.CARD);
|
||||
}, [setTabIndex]);
|
||||
setActiveTab(Number(tabQuery) || RSTabsList.CARD);
|
||||
}, [setActiveTab]);
|
||||
|
||||
useEffect(() => {
|
||||
if (init) {
|
||||
const url = new URL(window.location.href);
|
||||
const currentActive = url.searchParams.get('active');
|
||||
const currentTab = url.searchParams.get('tab');
|
||||
const saveHistory = tabIndex === RSTabsList.CST_EDIT && currentActive !== String(activeID);
|
||||
if (currentTab !== String(tabIndex)) {
|
||||
url.searchParams.set('tab', String(tabIndex));
|
||||
const saveHistory = activeTab === RSTabsList.CST_EDIT && currentActive !== String(activeID);
|
||||
if (currentTab !== String(activeTab)) {
|
||||
url.searchParams.set('tab', String(activeTab));
|
||||
}
|
||||
if (activeID) {
|
||||
if (currentActive !== String(activeID)) {
|
||||
|
@ -91,7 +131,7 @@ function RSTabs() {
|
|||
window.history.replaceState(null, '', url.toString());
|
||||
}
|
||||
}
|
||||
}, [tabIndex, activeID, init]);
|
||||
}, [activeTab, activeID, init]);
|
||||
|
||||
return (
|
||||
<div className='w-full'>
|
||||
|
@ -101,9 +141,19 @@ function RSTabs() {
|
|||
<>
|
||||
{showUpload && <DlgUploadRSForm hideWindow={() => { setShowUpload(false); }}/>}
|
||||
{showClone && <DlgCloneRSForm hideWindow={() => { setShowClone(false); }}/>}
|
||||
{showAST && <DlgShowAST syntaxTree={syntaxTree} hideWindow={() => { setShowAST(false); }}/>}
|
||||
{showAST &&
|
||||
<DlgShowAST
|
||||
syntaxTree={syntaxTree}
|
||||
hideWindow={() => { setShowAST(false); }}
|
||||
/>}
|
||||
{showCreateCst &&
|
||||
<DlgCreateCst
|
||||
hideWindow={() => { setShowCreateCst(false); }}
|
||||
onCreate={handleAddNew}
|
||||
defaultType={defaultType}
|
||||
/>}
|
||||
<Tabs
|
||||
selectedIndex={tabIndex}
|
||||
selectedIndex={activeTab}
|
||||
onSelect={onSelectTab}
|
||||
defaultFocus={true}
|
||||
selectedTabClassName='font-bold'
|
||||
|
@ -127,13 +177,14 @@ function RSTabs() {
|
|||
</TabPanel>
|
||||
|
||||
<TabPanel className='w-full'>
|
||||
<EditorItems onOpenEdit={onEditCst} />
|
||||
<EditorItems onOpenEdit={onEditCst} onShowCreateCst={onShowCreateCst} />
|
||||
</TabPanel>
|
||||
|
||||
<TabPanel>
|
||||
<EditorConstituenta onShowAST={onShowAST} />
|
||||
<EditorConstituenta onShowAST={onShowAST} onShowCreateCst={onShowCreateCst} />
|
||||
</TabPanel>
|
||||
</Tabs></>
|
||||
</Tabs>
|
||||
</>
|
||||
}
|
||||
</div>);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user