mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 13:00:39 +03:00
Optimize performance through memoization
This commit is contained in:
parent
ee9db2fb05
commit
266db4933a
|
@ -1,7 +1,7 @@
|
|||
'use client';
|
||||
|
||||
import clsx from 'clsx';
|
||||
import { useLayoutEffect, useState } from 'react';
|
||||
import { useLayoutEffect, useMemo, useState } from 'react';
|
||||
import { TabList, TabPanel, Tabs } from 'react-tabs';
|
||||
|
||||
import BadgeHelp from '@/components/man/BadgeHelp';
|
||||
|
@ -100,6 +100,28 @@ function DlgConstituentaTemplate({ hideWindow, schema, onCreate, insertAfter }:
|
|||
});
|
||||
}, [substitutes.arguments, template.prototype, updateConstituenta, updateSubstitutes]);
|
||||
|
||||
const templatePanel = useMemo(
|
||||
() => <TemplateTab state={template} partialUpdate={updateTemplate} />,
|
||||
[template, updateTemplate]
|
||||
);
|
||||
|
||||
const argumentsPanel = useMemo(
|
||||
() => <ArgumentsTab schema={schema} state={substitutes} partialUpdate={updateSubstitutes} />,
|
||||
[schema, substitutes, updateSubstitutes]
|
||||
);
|
||||
|
||||
const editorPanel = useMemo(
|
||||
() => (
|
||||
<FormCreateCst
|
||||
state={constituenta}
|
||||
partialUpdate={updateConstituenta}
|
||||
schema={schema}
|
||||
setValidated={setValidated}
|
||||
/>
|
||||
),
|
||||
[constituenta, updateConstituenta, schema]
|
||||
);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
header='Создание конституенты из шаблона'
|
||||
|
@ -125,21 +147,12 @@ function DlgConstituentaTemplate({ hideWindow, schema, onCreate, insertAfter }:
|
|||
<TabLabel label='Конституента' title='Редактирование атрибутов конституенты' className='w-[8rem]' />
|
||||
</TabList>
|
||||
|
||||
<TabPanel style={{ display: activeTab === TabID.TEMPLATE ? '' : 'none' }}>
|
||||
<TemplateTab state={template} partialUpdate={updateTemplate} />
|
||||
</TabPanel>
|
||||
<TabPanel style={{ display: activeTab === TabID.TEMPLATE ? '' : 'none' }}>{templatePanel}</TabPanel>
|
||||
|
||||
<TabPanel style={{ display: activeTab === TabID.ARGUMENTS ? '' : 'none' }}>
|
||||
<ArgumentsTab schema={schema} state={substitutes} partialUpdate={updateSubstitutes} />
|
||||
</TabPanel>
|
||||
<TabPanel style={{ display: activeTab === TabID.ARGUMENTS ? '' : 'none' }}>{argumentsPanel}</TabPanel>
|
||||
|
||||
<TabPanel className='cc-column' style={{ display: activeTab === TabID.CONSTITUENTA ? '' : 'none' }}>
|
||||
<FormCreateCst
|
||||
state={constituenta}
|
||||
partialUpdate={updateConstituenta}
|
||||
schema={schema}
|
||||
setValidated={setValidated}
|
||||
/>
|
||||
{editorPanel}
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
</Modal>
|
||||
|
|
|
@ -64,13 +64,8 @@ function DlgEditVersions({ hideWindow, versions, onDelete, onUpdate }: DlgEditVe
|
|||
setDescription(selected?.description ?? '');
|
||||
}, [selected]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
readonly
|
||||
header='Редактирование версий'
|
||||
hideWindow={hideWindow}
|
||||
className='flex flex-col w-[40rem] px-6 gap-3 pb-6'
|
||||
>
|
||||
const versionsTable = useMemo(
|
||||
() => (
|
||||
<VersionsTable
|
||||
processing={processing}
|
||||
items={versions}
|
||||
|
@ -78,6 +73,18 @@ function DlgEditVersions({ hideWindow, versions, onDelete, onUpdate }: DlgEditVe
|
|||
onSelect={versionID => setSelected(versions.find(ver => ver.id === versionID))}
|
||||
selected={selected?.id}
|
||||
/>
|
||||
),
|
||||
[processing, versions, onDelete, selected?.id]
|
||||
);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
readonly
|
||||
header='Редактирование версий'
|
||||
hideWindow={hideWindow}
|
||||
className='flex flex-col w-[40rem] px-6 gap-3 pb-6'
|
||||
>
|
||||
{versionsTable}
|
||||
<div className='flex'>
|
||||
<TextInput
|
||||
id='dlg_version'
|
||||
|
|
|
@ -58,6 +58,27 @@ function DlgInlineSynthesis({ hideWindow, receiver, onInlineSynthesis }: DlgInli
|
|||
setSubstitutions([]);
|
||||
}, [source.schema]);
|
||||
|
||||
const schemaPanel = useMemo(() => <SchemaTab selected={donorID} setSelected={setDonorID} />, [donorID]);
|
||||
const itemsPanel = useMemo(
|
||||
() => (
|
||||
<ConstituentsTab schema={source.schema} loading={source.loading} selected={selected} setSelected={setSelected} />
|
||||
),
|
||||
[source.schema, source.loading, selected]
|
||||
);
|
||||
const substitutesPanel = useMemo(
|
||||
() => (
|
||||
<SubstitutionsTab
|
||||
receiver={receiver}
|
||||
source={source.schema}
|
||||
selected={selected}
|
||||
loading={source.loading}
|
||||
substitutions={substitutions}
|
||||
setSubstitutions={setSubstitutions}
|
||||
/>
|
||||
),
|
||||
[source.schema, source.loading, receiver, selected, substitutions]
|
||||
);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
header='Импорт концептуальной схем'
|
||||
|
@ -80,29 +101,9 @@ function DlgInlineSynthesis({ hideWindow, receiver, onInlineSynthesis }: DlgInli
|
|||
<TabLabel label='Отождествления' title='Таблица отождествлений' className='w-[8rem]' />
|
||||
</TabList>
|
||||
|
||||
<TabPanel style={{ display: activeTab === TabID.SCHEMA ? '' : 'none' }}>
|
||||
<SchemaTab selected={donorID} setSelected={setDonorID} />
|
||||
</TabPanel>
|
||||
|
||||
<TabPanel style={{ display: activeTab === TabID.SELECTIONS ? '' : 'none' }}>
|
||||
<ConstituentsTab
|
||||
schema={source.schema}
|
||||
loading={source.loading}
|
||||
selected={selected}
|
||||
setSelected={setSelected}
|
||||
/>
|
||||
</TabPanel>
|
||||
|
||||
<TabPanel style={{ display: activeTab === TabID.SUBSTITUTIONS ? '' : 'none' }}>
|
||||
<SubstitutionsTab
|
||||
receiver={receiver}
|
||||
source={source.schema}
|
||||
selected={selected}
|
||||
loading={source.loading}
|
||||
substitutions={substitutions}
|
||||
setSubstitutions={setSubstitutions}
|
||||
/>
|
||||
</TabPanel>
|
||||
<TabPanel style={{ display: activeTab === TabID.SCHEMA ? '' : 'none' }}>{schemaPanel}</TabPanel>
|
||||
<TabPanel style={{ display: activeTab === TabID.SELECTIONS ? '' : 'none' }}>{itemsPanel}</TabPanel>
|
||||
<TabPanel style={{ display: activeTab === TabID.SUBSTITUTIONS ? '' : 'none' }}>{substitutesPanel}</TabPanel>
|
||||
</Tabs>
|
||||
</Modal>
|
||||
);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use client';
|
||||
|
||||
import { useCallback, useLayoutEffect, useState } from 'react';
|
||||
import { useCallback, useLayoutEffect, useMemo, useState } from 'react';
|
||||
|
||||
import { urls } from '@/app/urls';
|
||||
import DataLoader from '@/components/wrap/DataLoader';
|
||||
|
@ -61,6 +61,16 @@ function LibraryPage() {
|
|||
setFilter({});
|
||||
}, []);
|
||||
|
||||
const view = useMemo(
|
||||
() => (
|
||||
<ViewLibrary
|
||||
resetQuery={resetQuery} //
|
||||
items={items}
|
||||
/>
|
||||
),
|
||||
[resetQuery, items]
|
||||
);
|
||||
|
||||
return (
|
||||
<DataLoader
|
||||
id='library-page' //
|
||||
|
@ -76,10 +86,7 @@ function LibraryPage() {
|
|||
filtered={items.length}
|
||||
setFilter={setFilter}
|
||||
/>
|
||||
<ViewLibrary
|
||||
resetQuery={resetQuery} //
|
||||
items={items}
|
||||
/>
|
||||
{view}
|
||||
</DataLoader>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import { ReactCodeMirrorRef } from '@uiw/react-codemirror';
|
||||
import { AnimatePresence } from 'framer-motion';
|
||||
import { useCallback, useLayoutEffect, useRef, useState } from 'react';
|
||||
import { useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
||||
import { FaRegKeyboard } from 'react-icons/fa6';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
|
@ -152,6 +152,17 @@ function EditorRSExpression({
|
|||
setMathFont(mathFont === 'math' ? 'math2' : 'math');
|
||||
}
|
||||
|
||||
const controls = useMemo(
|
||||
() => (
|
||||
<RSEditorControls
|
||||
isOpen={showControls && (!disabled || model.processing)}
|
||||
disabled={disabled}
|
||||
onEdit={handleEdit}
|
||||
/>
|
||||
),
|
||||
[showControls, disabled, model.processing, handleEdit]
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<AnimatePresence>
|
||||
|
@ -208,11 +219,7 @@ function EditorRSExpression({
|
|||
{...restProps}
|
||||
/>
|
||||
|
||||
<RSEditorControls
|
||||
isOpen={showControls && (!disabled || model.processing)}
|
||||
disabled={disabled}
|
||||
onEdit={handleEdit}
|
||||
/>
|
||||
{controls}
|
||||
|
||||
<ParsingResult
|
||||
isOpen={!!parser.parseData && parser.parseData.errors.length > 0}
|
||||
|
|
|
@ -164,6 +164,30 @@ function RSTabs() {
|
|||
|
||||
const panelHeight = useMemo(() => calculateHeight('1.75rem + 4px'), [calculateHeight]);
|
||||
|
||||
const cardPanel = useMemo(
|
||||
() => (
|
||||
<EditorRSForm
|
||||
isModified={isModified} // prettier: split lines
|
||||
setIsModified={setIsModified}
|
||||
onDestroy={onDestroySchema}
|
||||
/>
|
||||
),
|
||||
[isModified, onDestroySchema]
|
||||
);
|
||||
|
||||
const listPanel = useMemo(() => <EditorRSList onOpenEdit={onOpenCst} />, [onOpenCst]);
|
||||
const editorPanel = useMemo(
|
||||
() => (
|
||||
<EditorConstituenta
|
||||
isModified={isModified}
|
||||
setIsModified={setIsModified}
|
||||
activeCst={activeCst}
|
||||
onOpenEdit={onOpenCst}
|
||||
/>
|
||||
),
|
||||
[isModified, setIsModified, activeCst, onOpenCst]
|
||||
);
|
||||
|
||||
return (
|
||||
<RSEditState
|
||||
selected={selected}
|
||||
|
@ -198,24 +222,15 @@ function RSTabs() {
|
|||
|
||||
<AnimateFade className='overflow-y-auto' style={{ maxHeight: panelHeight }}>
|
||||
<TabPanel forceRender style={{ display: activeTab === RSTabID.CARD ? '' : 'none' }}>
|
||||
<EditorRSForm
|
||||
isModified={isModified} // prettier: split lines
|
||||
setIsModified={setIsModified}
|
||||
onDestroy={onDestroySchema}
|
||||
/>
|
||||
{cardPanel}
|
||||
</TabPanel>
|
||||
|
||||
<TabPanel forceRender style={{ display: activeTab === RSTabID.CST_LIST ? '' : 'none' }}>
|
||||
<EditorRSList onOpenEdit={onOpenCst} />
|
||||
{listPanel}
|
||||
</TabPanel>
|
||||
|
||||
<TabPanel forceRender style={{ display: activeTab === RSTabID.CST_EDIT ? '' : 'none' }}>
|
||||
<EditorConstituenta
|
||||
isModified={isModified}
|
||||
setIsModified={setIsModified}
|
||||
activeCst={activeCst}
|
||||
onOpenEdit={onOpenCst}
|
||||
/>
|
||||
{editorPanel}
|
||||
</TabPanel>
|
||||
|
||||
<TabPanel style={{ display: activeTab === RSTabID.TERM_GRAPH ? '' : 'none' }}>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import clsx from 'clsx';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useState } from 'react';
|
||||
import { useMemo, useState } from 'react';
|
||||
|
||||
import { useConceptOptions } from '@/context/OptionsContext';
|
||||
import { ConstituentaID, IConstituenta, IRSForm } from '@/models/rsform';
|
||||
|
@ -27,6 +27,19 @@ function ViewConstituents({ expression, schema, activeID, isBottom, onOpenEdit }
|
|||
|
||||
const [filteredData, setFilteredData] = useState<IConstituenta[]>(schema?.items ?? []);
|
||||
|
||||
const table = useMemo(
|
||||
() => (
|
||||
<ConstituentsTable
|
||||
maxHeight={isBottom ? '12rem' : calculateHeight('8.2rem')}
|
||||
items={filteredData}
|
||||
activeID={activeID}
|
||||
onOpenEdit={onOpenEdit}
|
||||
denseThreshold={COLUMN_EXPRESSION_HIDE_THRESHOLD}
|
||||
/>
|
||||
),
|
||||
[isBottom, filteredData, activeID, onOpenEdit, calculateHeight]
|
||||
);
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
className={clsx(
|
||||
|
@ -46,13 +59,7 @@ function ViewConstituents({ expression, schema, activeID, isBottom, onOpenEdit }
|
|||
activeExpression={expression}
|
||||
setFiltered={setFilteredData}
|
||||
/>
|
||||
<ConstituentsTable
|
||||
maxHeight={isBottom ? '12rem' : calculateHeight('8.2rem')}
|
||||
items={filteredData}
|
||||
activeID={activeID}
|
||||
onOpenEdit={onOpenEdit}
|
||||
denseThreshold={COLUMN_EXPRESSION_HIDE_THRESHOLD}
|
||||
/>
|
||||
{table}
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user