mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 21:10:38 +03:00
M: Improve graph UI
This commit is contained in:
parent
673ed0a9cb
commit
ceba6b882f
|
@ -11,7 +11,15 @@ export default [
|
||||||
...typescriptPlugin.configs.recommendedTypeChecked,
|
...typescriptPlugin.configs.recommendedTypeChecked,
|
||||||
...typescriptPlugin.configs.stylisticTypeChecked,
|
...typescriptPlugin.configs.stylisticTypeChecked,
|
||||||
{
|
{
|
||||||
ignores: ['**/parser.ts', '**/node_modules/**', '**/public/**', 'eslint.config.js']
|
ignores: [
|
||||||
|
'**/parser.ts',
|
||||||
|
'**/node_modules/**',
|
||||||
|
'**/public/**',
|
||||||
|
'**/dist/**',
|
||||||
|
'eslint.config.js',
|
||||||
|
'tailwind.config.js',
|
||||||
|
'postcss.config.js'
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
languageOptions: {
|
languageOptions: {
|
||||||
|
|
|
@ -119,6 +119,7 @@ export { BiCollapse as IconGraphCollapse } from 'react-icons/bi';
|
||||||
export { BiExpand as IconGraphExpand } from 'react-icons/bi';
|
export { BiExpand as IconGraphExpand } from 'react-icons/bi';
|
||||||
export { LuMaximize as IconGraphMaximize } from 'react-icons/lu';
|
export { LuMaximize as IconGraphMaximize } from 'react-icons/lu';
|
||||||
export { BiGitBranch as IconGraphInputs } from 'react-icons/bi';
|
export { BiGitBranch as IconGraphInputs } from 'react-icons/bi';
|
||||||
|
export { TbEarScan as IconGraphInverse } from 'react-icons/tb';
|
||||||
export { BiGitMerge as IconGraphOutputs } from 'react-icons/bi';
|
export { BiGitMerge as IconGraphOutputs } from 'react-icons/bi';
|
||||||
export { LuAtom as IconGraphCore } from 'react-icons/lu';
|
export { LuAtom as IconGraphCore } from 'react-icons/lu';
|
||||||
export { LuRotate3D as IconRotate3D } from 'react-icons/lu';
|
export { LuRotate3D as IconRotate3D } from 'react-icons/lu';
|
||||||
|
|
|
@ -82,7 +82,8 @@ function PickMultiConstituenta({ id, schema, prefixID, rows, selected, setSelect
|
||||||
{schema ? (
|
{schema ? (
|
||||||
<ToolbarGraphSelection
|
<ToolbarGraphSelection
|
||||||
graph={schema.graph}
|
graph={schema.graph}
|
||||||
core={schema.items.filter(cst => isBasicConcept(cst.cst_type)).map(cst => cst.id)}
|
isCore={cstID => isBasicConcept(schema.cstByID.get(cstID)?.cst_type)}
|
||||||
|
isOwned={cstID => !schema.cstByID.get(cstID)?.is_inherited ?? false}
|
||||||
setSelected={setSelected}
|
setSelected={setSelected}
|
||||||
emptySelection={selected.length === 0}
|
emptySelection={selected.length === 0}
|
||||||
className='w-full ml-8'
|
className='w-full ml-8'
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
import { Graph } from '@/models/Graph';
|
import { Graph } from '@/models/Graph';
|
||||||
|
|
||||||
|
@ -7,8 +8,10 @@ import {
|
||||||
IconGraphCore,
|
IconGraphCore,
|
||||||
IconGraphExpand,
|
IconGraphExpand,
|
||||||
IconGraphInputs,
|
IconGraphInputs,
|
||||||
|
IconGraphInverse,
|
||||||
IconGraphMaximize,
|
IconGraphMaximize,
|
||||||
IconGraphOutputs,
|
IconGraphOutputs,
|
||||||
|
IconPredecessor,
|
||||||
IconReset
|
IconReset
|
||||||
} from '../Icons';
|
} from '../Icons';
|
||||||
import { CProps } from '../props';
|
import { CProps } from '../props';
|
||||||
|
@ -16,7 +19,8 @@ import MiniButton from '../ui/MiniButton';
|
||||||
|
|
||||||
interface ToolbarGraphSelectionProps extends CProps.Styling {
|
interface ToolbarGraphSelectionProps extends CProps.Styling {
|
||||||
graph: Graph;
|
graph: Graph;
|
||||||
core: number[];
|
isCore: (item: number) => boolean;
|
||||||
|
isOwned: (item: number) => boolean;
|
||||||
setSelected: React.Dispatch<React.SetStateAction<number[]>>;
|
setSelected: React.Dispatch<React.SetStateAction<number[]>>;
|
||||||
emptySelection?: boolean;
|
emptySelection?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -24,11 +28,27 @@ interface ToolbarGraphSelectionProps extends CProps.Styling {
|
||||||
function ToolbarGraphSelection({
|
function ToolbarGraphSelection({
|
||||||
className,
|
className,
|
||||||
graph,
|
graph,
|
||||||
core,
|
isCore,
|
||||||
|
isOwned,
|
||||||
setSelected,
|
setSelected,
|
||||||
emptySelection,
|
emptySelection,
|
||||||
...restProps
|
...restProps
|
||||||
}: ToolbarGraphSelectionProps) {
|
}: ToolbarGraphSelectionProps) {
|
||||||
|
const handleSelectCore = useCallback(() => {
|
||||||
|
const core = [...graph.nodes.keys()].filter(isCore);
|
||||||
|
setSelected([...core, ...graph.expandInputs(core)]);
|
||||||
|
}, [setSelected, graph, isCore]);
|
||||||
|
|
||||||
|
const handleSelectOwned = useCallback(
|
||||||
|
() => setSelected([...graph.nodes.keys()].filter(isOwned)),
|
||||||
|
[setSelected, graph, isOwned]
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleInvertSelection = useCallback(
|
||||||
|
() => setSelected(prev => [...graph.nodes.keys()].filter(item => !prev.includes(item))),
|
||||||
|
[setSelected, graph]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={clsx('cc-icons', className)} {...restProps}>
|
<div className={clsx('cc-icons', className)} {...restProps}>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
|
@ -67,10 +87,20 @@ function ToolbarGraphSelection({
|
||||||
onClick={() => setSelected(prev => [...prev, ...graph.expandOutputs(prev)])}
|
onClick={() => setSelected(prev => [...prev, ...graph.expandOutputs(prev)])}
|
||||||
disabled={emptySelection}
|
disabled={emptySelection}
|
||||||
/>
|
/>
|
||||||
|
<MiniButton
|
||||||
|
titleHtml='Инвертировать'
|
||||||
|
icon={<IconGraphInverse size='1.25rem' className='icon-primary' />}
|
||||||
|
onClick={handleInvertSelection}
|
||||||
|
/>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
titleHtml='Выделить ядро'
|
titleHtml='Выделить ядро'
|
||||||
icon={<IconGraphCore size='1.25rem' className='icon-primary' />}
|
icon={<IconGraphCore size='1.25rem' className='icon-primary' />}
|
||||||
onClick={() => setSelected([...core, ...graph.expandInputs(core)])}
|
onClick={handleSelectCore}
|
||||||
|
/>
|
||||||
|
<MiniButton
|
||||||
|
titleHtml='Выделить собственные'
|
||||||
|
icon={<IconPredecessor size='1.25rem' className='icon-primary' />}
|
||||||
|
onClick={handleSelectOwned}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -202,7 +202,7 @@ export function guessCstType(hint: string, defaultType: CstType = CstType.TERM):
|
||||||
/**
|
/**
|
||||||
* Evaluate if {@link CstType} is basic concept.
|
* Evaluate if {@link CstType} is basic concept.
|
||||||
*/
|
*/
|
||||||
export function isBasicConcept(type: CstType): boolean {
|
export function isBasicConcept(type?: CstType): boolean {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case CstType.BASE: return true;
|
case CstType.BASE: return true;
|
||||||
|
@ -213,6 +213,7 @@ export function isBasicConcept(type: CstType): boolean {
|
||||||
case CstType.FUNCTION: return false;
|
case CstType.FUNCTION: return false;
|
||||||
case CstType.PREDICATE: return false;
|
case CstType.PREDICATE: return false;
|
||||||
case CstType.THEOREM: return false;
|
case CstType.THEOREM: return false;
|
||||||
|
case undefined: return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { IconRSForm } from '@/components/Icons';
|
import { IconChild, IconPredecessor, IconRSForm } from '@/components/Icons';
|
||||||
import LinkTopic from '@/components/ui/LinkTopic';
|
import LinkTopic from '@/components/ui/LinkTopic';
|
||||||
import { HelpTopic } from '@/models/miscellaneous';
|
import { HelpTopic } from '@/models/miscellaneous';
|
||||||
|
|
||||||
|
@ -17,8 +17,8 @@ function HelpThesaurus() {
|
||||||
<h2>Концептуальная схема</h2>
|
<h2>Концептуальная схема</h2>
|
||||||
<p>
|
<p>
|
||||||
<IconRSForm size='1rem' className='inline-icon' />{' '}
|
<IconRSForm size='1rem' className='inline-icon' />{' '}
|
||||||
<LinkTopic text='Концептуальная схема' topic={HelpTopic.CC_SYSTEM} /> (система определений, КС) – совокупность
|
<LinkTopic text='Концептуальная схема' topic={HelpTopic.CC_SYSTEM} /> (<i>система определений, КС</i>) –
|
||||||
отдельных понятий и утверждений, а также связей между ними, задаваемых определениями.
|
совокупность отдельных понятий и утверждений, а также связей между ними, задаваемых определениями.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Экспликация КС – изложение (процесс и результат) концептуальной схемы с помощью заданного языка описания –
|
Экспликация КС – изложение (процесс и результат) концептуальной схемы с помощью заданного языка описания –
|
||||||
|
@ -30,7 +30,82 @@ function HelpThesaurus() {
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2>Конституента</h2>
|
<h2>Конституента</h2>
|
||||||
<p>Раздел в разработке...</p>
|
<p>
|
||||||
|
Конституента – это выделенная часть КС, являющаяся отдельным понятием, схемой построения понятия, либо
|
||||||
|
утверждением, связывающим введенные понятия.{' '}
|
||||||
|
<LinkTopic text='Аттрибутами конституенты' topic={HelpTopic.CC_CONSTITUENTA} /> в родоструктурной экспликации
|
||||||
|
являются Термин, Конвенция, Типизация (Структура), Формальное определение, Текстовое определение, Комментарий.
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
По <b>наличию формального определения в рамках КС</b> выделены:
|
||||||
|
<li>
|
||||||
|
базовое понятие (<i>неопределяемое понятие</i>) не имеет определения и задано конвенцией и аксиомами;
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
производное понятие (<i>выводимое понятие</i>) имеет определение.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
Для описания <b>тесно связанных понятий</b> введены следующие термины:
|
||||||
|
<li>
|
||||||
|
порождающее выражение – формальное определение, основанное на одной внешней конституенте и использующее только
|
||||||
|
формальное разворачивание (не вводит нового предметного содержания);
|
||||||
|
</li>
|
||||||
|
<li>основа данного понятия – понятие, на котором основано порождающее выражение данной конституенты;</li>
|
||||||
|
<li>
|
||||||
|
порожденное понятие данным понятием – понятие, определение которого является порождающим выражением,
|
||||||
|
основанным на данном понятии.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
Для описания <b>отождествления</b> введены:
|
||||||
|
<li>отождествляемые конституенты – конституенты, состоящие в отождествлении;</li>
|
||||||
|
<li>удаляемая конституента – конституента, удаляемая в ходе отождествления;</li>
|
||||||
|
<li>
|
||||||
|
замещающая конституента – конституента, обозначение которой замещает обозначение удаляемой конституенты в
|
||||||
|
формальных выражениях иных конституент в ходе отождествления;
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
Для описания <b>наследования</b> конституент в рамках ОСС введены:
|
||||||
|
<li>
|
||||||
|
<IconChild size='1rem' className='inline-icon' /> наследованная конституента – конституента, перенесенная из
|
||||||
|
другой КС в рамках операции синтеза;
|
||||||
|
</li>
|
||||||
|
<li>собственная конституента – конституента, не являющаяся наследником других конституент;</li>
|
||||||
|
<li>
|
||||||
|
<IconPredecessor size='1rem' className='inline-icon' /> исходная конституента для данной конституенты –
|
||||||
|
собственная конституента, прямым или опосредованным наследником которой является данная конституента.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
По <b>назначению</b> выделены:
|
||||||
|
<li>
|
||||||
|
базисное множество (X1) задает неопределяемое понятие, представленное структурой множества, чьи элементы
|
||||||
|
различимы и не сравнимы с элементами других базисных множеств;
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
константное множество (C1) задает неопределяемое понятие, моделируемое термом теории множеств, который
|
||||||
|
поддерживает ряд формальных операций над его элементами;
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
родовая структура (S1) задает неопределяемое понятие, имеющее определенную структуру, построенную на базисных
|
||||||
|
множествах и константных множеств. Содержание родовой структуры формируется{' '}
|
||||||
|
<LinkTopic text='отношением типизации' topic={HelpTopic.RSL_TYPES} />, аксиомами и конвенцией;
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
<h2>Операционная схема синтеза</h2>
|
<h2>Операционная схема синтеза</h2>
|
||||||
<p>Раздел в разработке...</p>
|
<p>Раздел в разработке...</p>
|
||||||
|
|
|
@ -37,7 +37,7 @@ function ControlsOverlay({ constituenta, disabled, modified, processing, onRenam
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<span>Имя </span>
|
<span>Имя </span>
|
||||||
<span className='ml-1'>{constituenta.alias}</span>
|
<span className='ml-1'>{constituenta?.alias ?? ''}</span>
|
||||||
</div>
|
</div>
|
||||||
{!disabled || processing ? (
|
{!disabled || processing ? (
|
||||||
<MiniButton
|
<MiniButton
|
||||||
|
|
|
@ -324,7 +324,8 @@ function EditorTermGraph({ onOpenEdit }: EditorTermGraphProps) {
|
||||||
{!focusCst ? (
|
{!focusCst ? (
|
||||||
<ToolbarGraphSelection
|
<ToolbarGraphSelection
|
||||||
graph={controller.schema!.graph}
|
graph={controller.schema!.graph}
|
||||||
core={controller.schema!.items.filter(cst => isBasicConcept(cst.cst_type)).map(cst => cst.id)}
|
isCore={cstID => isBasicConcept(controller.schema?.cstByID.get(cstID)?.cst_type)}
|
||||||
|
isOwned={cstID => !controller.schema?.cstByID.get(cstID)?.is_inherited ?? false}
|
||||||
setSelected={controller.setSelected}
|
setSelected={controller.setSelected}
|
||||||
emptySelection={controller.selected.length === 0}
|
emptySelection={controller.selected.length === 0}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -114,8 +114,7 @@ function TermGraph({
|
||||||
const canvasHeight = useMemo(() => calculateHeight('1.75rem + 4px'), [calculateHeight]);
|
const canvasHeight = useMemo(() => calculateHeight('1.75rem + 4px'), [calculateHeight]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='outline-none'>
|
<div className='relative outline-none' style={{ width: canvasWidth, height: canvasHeight }}>
|
||||||
<div className='relative' style={{ width: canvasWidth, height: canvasHeight }}>
|
|
||||||
<GraphUI
|
<GraphUI
|
||||||
nodes={nodes}
|
nodes={nodes}
|
||||||
edges={edges}
|
edges={edges}
|
||||||
|
@ -138,7 +137,6 @@ function TermGraph({
|
||||||
theme={darkMode ? graphDarkT : graphLightT}
|
theme={darkMode ? graphDarkT : graphLightT}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user