mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-08-14 21:00:37 +03:00
Implement GraphEditor params
This commit is contained in:
parent
162191040c
commit
ecea364d69
29
rsconcept/frontend/src/components/Help/CstClassInfo.tsx
Normal file
29
rsconcept/frontend/src/components/Help/CstClassInfo.tsx
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import { prefixes } from '../../utils/constants';
|
||||||
|
import { mapCstClassInfo } from '../../utils/staticUI';
|
||||||
|
|
||||||
|
interface CstClassInfoProps {
|
||||||
|
title?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
function CstClassInfo({ title }: CstClassInfoProps) {
|
||||||
|
return (
|
||||||
|
<div className='flex flex-col gap-1'>
|
||||||
|
{ title && <h1>{title}</h1>}
|
||||||
|
{ [... mapCstClassInfo.values()].map(
|
||||||
|
(info, index) => {
|
||||||
|
return (
|
||||||
|
<p key={`${prefixes.cst_status_list}${index}`}>
|
||||||
|
<span className={`px-1 inline-block font-semibold min-w-[6.5rem] text-center border ${info.color}`}>
|
||||||
|
{info.text}
|
||||||
|
</span>
|
||||||
|
<span> - </span>
|
||||||
|
<span>
|
||||||
|
{info.tooltip}
|
||||||
|
</span>
|
||||||
|
</p>);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CstClassInfo;
|
|
@ -7,13 +7,13 @@ interface CstStatusInfoProps {
|
||||||
|
|
||||||
function CstStatusInfo({ title }: CstStatusInfoProps) {
|
function CstStatusInfo({ title }: CstStatusInfoProps) {
|
||||||
return (
|
return (
|
||||||
<>
|
<div className='flex flex-col gap-1'>
|
||||||
{ title && <h1>{title}</h1>}
|
{ title && <h1>{title}</h1>}
|
||||||
{ [... mapStatusInfo.values()].map(
|
{ [... mapStatusInfo.values()].map(
|
||||||
(info, index) => {
|
(info, index) => {
|
||||||
return (
|
return (
|
||||||
<p className='py-1' key={`${prefixes.cst_status_list}${index}`}>
|
<p key={`${prefixes.cst_status_list}${index}`}>
|
||||||
<span className={`inline-block font-semibold min-w-[4rem] text-center border ${info.color}`}>
|
<span className={`px-1 inline-block font-semibold min-w-[4rem] text-center border ${info.color}`}>
|
||||||
{info.text}
|
{info.text}
|
||||||
</span>
|
</span>
|
||||||
<span> - </span>
|
<span> - </span>
|
||||||
|
@ -22,7 +22,7 @@ function CstStatusInfo({ title }: CstStatusInfoProps) {
|
||||||
</span>
|
</span>
|
||||||
</p>);
|
</p>);
|
||||||
})}
|
})}
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
144
rsconcept/frontend/src/pages/RSFormPage/DlgGraphOptions.tsx
Normal file
144
rsconcept/frontend/src/pages/RSFormPage/DlgGraphOptions.tsx
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
import { useLayoutEffect, useState } from 'react';
|
||||||
|
|
||||||
|
import Checkbox from '../../components/Common/Checkbox';
|
||||||
|
import Modal from '../../components/Common/Modal';
|
||||||
|
import { CstType } from '../../utils/models';
|
||||||
|
import { getCstTypeLabel } from '../../utils/staticUI';
|
||||||
|
import { GraphEditorParams } from './EditorTermGraph';
|
||||||
|
|
||||||
|
interface DlgGraphOptionsProps {
|
||||||
|
hideWindow: () => void
|
||||||
|
initial: GraphEditorParams
|
||||||
|
onConfirm: (params: GraphEditorParams) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
function DlgGraphOptions({ hideWindow, initial, onConfirm }:DlgGraphOptionsProps) {
|
||||||
|
const [ noHermits, setNoHermits ] = useState(true);
|
||||||
|
const [ noTransitive, setNoTransitive ] = useState(false);
|
||||||
|
const [ noTemplates, setNoTemplates ] = useState(true);
|
||||||
|
|
||||||
|
const [ allowBase, setAllowBase ] = useState(true);
|
||||||
|
const [ allowStruct, setAllowStruct ] = useState(true);
|
||||||
|
const [ allowTerm, setAllowTerm ] = useState(true);
|
||||||
|
const [ allowAxiom, setAllowAxiom ] = useState(true);
|
||||||
|
const [ allowFunction, setAllowFunction ] = useState(true);
|
||||||
|
const [ allowPredicate, setAllowPredicate ] = useState(true);
|
||||||
|
const [ allowConstant, setAllowConstant ] = useState(true);
|
||||||
|
const [ allowTheorem, setAllowTheorem ] = useState(true);
|
||||||
|
|
||||||
|
function getParams() {
|
||||||
|
return {
|
||||||
|
noHermits: noHermits,
|
||||||
|
noTransitive: noTransitive,
|
||||||
|
noTemplates: noTemplates,
|
||||||
|
|
||||||
|
allowBase: allowBase,
|
||||||
|
allowStruct: allowStruct,
|
||||||
|
allowTerm: allowTerm,
|
||||||
|
allowAxiom: allowAxiom,
|
||||||
|
allowFunction: allowFunction,
|
||||||
|
allowPredicate: allowPredicate,
|
||||||
|
allowConstant: allowConstant,
|
||||||
|
allowTheorem: allowTheorem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSubmit = () => {
|
||||||
|
hideWindow();
|
||||||
|
onConfirm(getParams());
|
||||||
|
};
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
setNoHermits(initial.noHermits);
|
||||||
|
setNoTransitive(initial.noTransitive);
|
||||||
|
setNoTemplates(initial.noTemplates);
|
||||||
|
|
||||||
|
setAllowBase(initial.allowBase);
|
||||||
|
setAllowStruct(initial.allowStruct);
|
||||||
|
setAllowTerm(initial.allowTerm);
|
||||||
|
setAllowAxiom(initial.allowAxiom);
|
||||||
|
setAllowFunction(initial.allowFunction);
|
||||||
|
setAllowPredicate(initial.allowPredicate);
|
||||||
|
setAllowConstant(initial.allowConstant);
|
||||||
|
setAllowTheorem(initial.allowTheorem);
|
||||||
|
}, [initial]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
hideWindow={hideWindow}
|
||||||
|
title='Настройки графа термов'
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
canSubmit
|
||||||
|
submitText='Применить'
|
||||||
|
>
|
||||||
|
<div className='flex gap-2'>
|
||||||
|
<div className='flex flex-col'>
|
||||||
|
<h1>Преобразования</h1>
|
||||||
|
<Checkbox
|
||||||
|
label='Скрыть несвязанные'
|
||||||
|
tooltip='Неиспользуемые конституенты'
|
||||||
|
value={noHermits}
|
||||||
|
onChange={ event => setNoHermits(event.target.checked) }
|
||||||
|
/>
|
||||||
|
<Checkbox
|
||||||
|
label='Скрыть шаблоны'
|
||||||
|
tooltip='Терм-функции и предикат-функции с параметризованными аргументами'
|
||||||
|
value={noTemplates}
|
||||||
|
onChange={ event => setNoTemplates(event.target.checked) }
|
||||||
|
/>
|
||||||
|
<Checkbox
|
||||||
|
label='Транзитивная редукция'
|
||||||
|
tooltip='Удалить связи, образующие транзитивные пути в графе'
|
||||||
|
value={noTransitive}
|
||||||
|
onChange={ event => setNoTransitive(event.target.checked) }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className='flex flex-col'>
|
||||||
|
<h1>Типы конституент</h1>
|
||||||
|
<Checkbox
|
||||||
|
label={getCstTypeLabel(CstType.BASE)}
|
||||||
|
value={allowBase}
|
||||||
|
onChange={ event => setAllowBase(event.target.checked) }
|
||||||
|
/>
|
||||||
|
<Checkbox
|
||||||
|
label={getCstTypeLabel(CstType.STRUCTURED)}
|
||||||
|
value={allowStruct}
|
||||||
|
onChange={ event => setAllowStruct(event.target.checked) }
|
||||||
|
/>
|
||||||
|
<Checkbox
|
||||||
|
label={getCstTypeLabel(CstType.TERM)}
|
||||||
|
value={allowTerm}
|
||||||
|
onChange={ event => setAllowTerm(event.target.checked) }
|
||||||
|
/>
|
||||||
|
<Checkbox
|
||||||
|
label={getCstTypeLabel(CstType.AXIOM)}
|
||||||
|
value={allowAxiom}
|
||||||
|
onChange={ event => setAllowAxiom(event.target.checked) }
|
||||||
|
/>
|
||||||
|
<Checkbox
|
||||||
|
label={getCstTypeLabel(CstType.FUNCTION)}
|
||||||
|
value={allowFunction}
|
||||||
|
onChange={ event => setAllowFunction(event.target.checked) }
|
||||||
|
/>
|
||||||
|
<Checkbox
|
||||||
|
label={getCstTypeLabel(CstType.PREDICATE)}
|
||||||
|
value={allowPredicate}
|
||||||
|
onChange={ event => setAllowPredicate(event.target.checked) }
|
||||||
|
/>
|
||||||
|
<Checkbox
|
||||||
|
label={getCstTypeLabel(CstType.CONSTANT)}
|
||||||
|
value={allowConstant}
|
||||||
|
onChange={ event => setAllowConstant(event.target.checked) }
|
||||||
|
/>
|
||||||
|
<Checkbox
|
||||||
|
label={getCstTypeLabel(CstType.THEOREM)}
|
||||||
|
value={allowTheorem}
|
||||||
|
onChange={ event => setAllowTheorem(event.target.checked) }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DlgGraphOptions;
|
|
@ -157,8 +157,8 @@ function EditorItems({ onOpenEdit, onCreateCst, onDeleteCst }: EditorItemsProps)
|
||||||
setSelected(selectedRows.map(cst => cst.id));
|
setSelected(selectedRows.map(cst => cst.id));
|
||||||
}, [setSelected]);
|
}, [setSelected]);
|
||||||
|
|
||||||
const columns = useMemo(() =>
|
const columns = useMemo(
|
||||||
[
|
() => [
|
||||||
{
|
{
|
||||||
name: 'ID',
|
name: 'ID',
|
||||||
id: 'id',
|
id: 'id',
|
||||||
|
@ -242,8 +242,7 @@ function EditorItems({ onOpenEdit, onCreateCst, onDeleteCst }: EditorItemsProps)
|
||||||
reorder: true,
|
reorder: true,
|
||||||
hide: 1800
|
hide: 1800
|
||||||
}
|
}
|
||||||
], []
|
], []);
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='w-full'>
|
<div className='w-full'>
|
||||||
|
|
|
@ -8,19 +8,22 @@ import Checkbox from '../../components/Common/Checkbox';
|
||||||
import ConceptSelect from '../../components/Common/ConceptSelect';
|
import ConceptSelect from '../../components/Common/ConceptSelect';
|
||||||
import ConceptTooltip from '../../components/Common/ConceptTooltip';
|
import ConceptTooltip from '../../components/Common/ConceptTooltip';
|
||||||
import Divider from '../../components/Common/Divider';
|
import Divider from '../../components/Common/Divider';
|
||||||
|
import MiniButton from '../../components/Common/MiniButton';
|
||||||
import ConstituentaInfo from '../../components/Help/ConstituentaInfo';
|
import ConstituentaInfo from '../../components/Help/ConstituentaInfo';
|
||||||
|
import CstClassInfo from '../../components/Help/CstClassInfo';
|
||||||
import CstStatusInfo from '../../components/Help/CstStatusInfo';
|
import CstStatusInfo from '../../components/Help/CstStatusInfo';
|
||||||
import { ArrowsRotateIcon, HelpIcon } from '../../components/Icons';
|
import { ArrowsRotateIcon, FilterCogIcon, HelpIcon } from '../../components/Icons';
|
||||||
import { useRSForm } from '../../context/RSFormContext';
|
import { useRSForm } from '../../context/RSFormContext';
|
||||||
import { useConceptTheme } from '../../context/ThemeContext';
|
import { useConceptTheme } from '../../context/ThemeContext';
|
||||||
import useLocalStorage from '../../hooks/useLocalStorage';
|
import useLocalStorage from '../../hooks/useLocalStorage';
|
||||||
import { prefixes, resources } from '../../utils/constants';
|
import { prefixes, resources } from '../../utils/constants';
|
||||||
import { Graph } from '../../utils/Graph';
|
import { Graph } from '../../utils/Graph';
|
||||||
import { IConstituenta } from '../../utils/models';
|
import { CstType, IConstituenta } from '../../utils/models';
|
||||||
import { getCstStatusColor, getCstTypeColor,
|
import { getCstClassColor, getCstStatusColor,
|
||||||
GraphColoringSelector, GraphLayoutSelector,
|
GraphColoringSelector, GraphLayoutSelector,
|
||||||
mapColoringLabels, mapLayoutLabels, mapStatusInfo
|
mapColoringLabels, mapLayoutLabels
|
||||||
} from '../../utils/staticUI';
|
} from '../../utils/staticUI';
|
||||||
|
import DlgGraphOptions from './DlgGraphOptions';
|
||||||
import ConstituentaTooltip from './elements/ConstituentaTooltip';
|
import ConstituentaTooltip from './elements/ConstituentaTooltip';
|
||||||
|
|
||||||
export type ColoringScheme = 'none' | 'status' | 'type';
|
export type ColoringScheme = 'none' | 'status' | 'type';
|
||||||
|
@ -28,12 +31,27 @@ const TREE_SIZE_MILESTONE = 50;
|
||||||
|
|
||||||
function getCstNodeColor(cst: IConstituenta, coloringScheme: ColoringScheme, darkMode: boolean): string {
|
function getCstNodeColor(cst: IConstituenta, coloringScheme: ColoringScheme, darkMode: boolean): string {
|
||||||
if (coloringScheme === 'type') {
|
if (coloringScheme === 'type') {
|
||||||
return getCstTypeColor(cst.cstType, darkMode);
|
return getCstClassColor(cst.cstClass, darkMode);
|
||||||
}
|
}
|
||||||
if (coloringScheme === 'status') {
|
if (coloringScheme === 'status') {
|
||||||
return getCstStatusColor(cst.status, darkMode);
|
return getCstStatusColor(cst.status, darkMode);
|
||||||
}
|
}
|
||||||
return '';
|
return (darkMode ? '#7a8c9e' :'#7ca0ab');
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GraphEditorParams {
|
||||||
|
noHermits: boolean
|
||||||
|
noTransitive: boolean
|
||||||
|
noTemplates: boolean
|
||||||
|
|
||||||
|
allowBase: boolean
|
||||||
|
allowStruct: boolean
|
||||||
|
allowTerm: boolean
|
||||||
|
allowAxiom: boolean
|
||||||
|
allowFunction: boolean
|
||||||
|
allowPredicate: boolean
|
||||||
|
allowConstant: boolean
|
||||||
|
allowTheorem: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
interface EditorTermGraphProps {
|
interface EditorTermGraphProps {
|
||||||
|
@ -49,13 +67,24 @@ function EditorTermGraph({ onOpenEdit }: EditorTermGraphProps) {
|
||||||
const [ layout, setLayout ] = useLocalStorage<LayoutTypes>('graph_layout', 'treeTd2d');
|
const [ layout, setLayout ] = useLocalStorage<LayoutTypes>('graph_layout', 'treeTd2d');
|
||||||
const [ coloringScheme, setColoringScheme ] = useLocalStorage<ColoringScheme>('graph_coloring', 'none');
|
const [ coloringScheme, setColoringScheme ] = useLocalStorage<ColoringScheme>('graph_coloring', 'none');
|
||||||
const [ orbit, setOrbit ] = useState(false);
|
const [ orbit, setOrbit ] = useState(false);
|
||||||
|
|
||||||
const [ noHermits, setNoHermits ] = useLocalStorage('graph_no_hermits', true);
|
const [ noHermits, setNoHermits ] = useLocalStorage('graph_no_hermits', true);
|
||||||
const [ noTransitive, setNoTransitive ] = useLocalStorage('graph_no_transitive', false);
|
const [ noTransitive, setNoTransitive ] = useLocalStorage('graph_no_transitive', false);
|
||||||
|
const [ noTemplates, setNoTemplates ] = useLocalStorage('graph_no_templates', false);
|
||||||
|
const [ allowBase, setAllowBase ] = useLocalStorage('graph_allow_base', true);
|
||||||
|
const [ allowStruct, setAllowStruct ] = useLocalStorage('graph_allow_struct', true);
|
||||||
|
const [ allowTerm, setAllowTerm ] = useLocalStorage('graph_allow_term', true);
|
||||||
|
const [ allowAxiom, setAllowAxiom ] = useLocalStorage('graph_allow_axiom', true);
|
||||||
|
const [ allowFunction, setAllowFunction ] = useLocalStorage('function', true);
|
||||||
|
const [ allowPredicate, setAllowPredicate ] = useLocalStorage('graph_allow_predicate', true);
|
||||||
|
const [ allowConstant, setAllowConstant ] = useLocalStorage('graph_allow_constant', true);
|
||||||
|
const [ allowTheorem, setAllowTheorem ] = useLocalStorage('graph_allow_theorem', true);
|
||||||
|
|
||||||
const [ filtered, setFiltered ] = useState<Graph>(new Graph());
|
const [ filtered, setFiltered ] = useState<Graph>(new Graph());
|
||||||
const [ dismissed, setDismissed ] = useState<number[]>([]);
|
const [ dismissed, setDismissed ] = useState<number[]>([]);
|
||||||
const [ selectedDismissed, setSelectedDismissed ] = useState<number[]>([]);
|
const [ selectedDismissed, setSelectedDismissed ] = useState<number[]>([]);
|
||||||
const graphRef = useRef<GraphCanvasRef | null>(null);
|
const graphRef = useRef<GraphCanvasRef | null>(null);
|
||||||
|
const [showOptions, setShowOptions] = useState(false);
|
||||||
|
|
||||||
const [hoverID, setHoverID] = useState<string | undefined>(undefined);
|
const [hoverID, setHoverID] = useState<string | undefined>(undefined);
|
||||||
const hoverCst = useMemo(
|
const hoverCst = useMemo(
|
||||||
|
@ -64,6 +93,19 @@ function EditorTermGraph({ onOpenEdit }: EditorTermGraphProps) {
|
||||||
}, [schema?.items, hoverID]);
|
}, [schema?.items, hoverID]);
|
||||||
|
|
||||||
const is3D = useMemo(() => layout.includes('3d'), [layout]);
|
const is3D = useMemo(() => layout.includes('3d'), [layout]);
|
||||||
|
const allowedTypes: CstType[] = useMemo(
|
||||||
|
() => {
|
||||||
|
const result: CstType[] = [];
|
||||||
|
if (allowBase) result.push(CstType.BASE);
|
||||||
|
if (allowStruct) result.push(CstType.STRUCTURED);
|
||||||
|
if (allowTerm) result.push(CstType.TERM);
|
||||||
|
if (allowAxiom) result.push(CstType.AXIOM);
|
||||||
|
if (allowFunction) result.push(CstType.FUNCTION);
|
||||||
|
if (allowPredicate) result.push(CstType.PREDICATE);
|
||||||
|
if (allowConstant) result.push(CstType.CONSTANT);
|
||||||
|
if (allowTheorem) result.push(CstType.THEOREM);
|
||||||
|
return result;
|
||||||
|
}, [allowBase, allowStruct, allowTerm, allowAxiom, allowFunction, allowPredicate, allowConstant, allowTheorem]);
|
||||||
|
|
||||||
useEffect(
|
useEffect(
|
||||||
() => {
|
() => {
|
||||||
|
@ -78,6 +120,20 @@ function EditorTermGraph({ onOpenEdit }: EditorTermGraphProps) {
|
||||||
if (noTransitive) {
|
if (noTransitive) {
|
||||||
graph.transitiveReduction();
|
graph.transitiveReduction();
|
||||||
}
|
}
|
||||||
|
if (noTemplates) {
|
||||||
|
schema.items.forEach(cst => {
|
||||||
|
if (cst.isTemplate) {
|
||||||
|
graph.foldNode(cst.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (allowedTypes.length < Object.values(CstType).length) {
|
||||||
|
schema.items.forEach(cst => {
|
||||||
|
if (!allowedTypes.includes(cst.cstType)) {
|
||||||
|
graph.foldNode(cst.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
const newDismissed: number[] = [];
|
const newDismissed: number[] = [];
|
||||||
schema.items.forEach(cst => {
|
schema.items.forEach(cst => {
|
||||||
if (!graph.nodes.has(cst.id)) {
|
if (!graph.nodes.has(cst.id)) {
|
||||||
|
@ -88,7 +144,7 @@ function EditorTermGraph({ onOpenEdit }: EditorTermGraphProps) {
|
||||||
setDismissed(newDismissed);
|
setDismissed(newDismissed);
|
||||||
setSelectedDismissed([]);
|
setSelectedDismissed([]);
|
||||||
setHoverID(undefined);
|
setHoverID(undefined);
|
||||||
}, [schema, noHermits, noTransitive]);
|
}, [schema, noHermits, noTransitive, noTemplates, allowedTypes]);
|
||||||
|
|
||||||
function toggleDismissed(cstID: number) {
|
function toggleDismissed(cstID: number) {
|
||||||
setSelectedDismissed(prev => {
|
setSelectedDismissed(prev => {
|
||||||
|
@ -153,7 +209,7 @@ function EditorTermGraph({ onOpenEdit }: EditorTermGraphProps) {
|
||||||
focusOnSelect: false
|
focusOnSelect: false
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleCenter = useCallback(
|
const handleRecreate = useCallback(
|
||||||
() => {
|
() => {
|
||||||
graphRef.current?.resetControls();
|
graphRef.current?.resetControls();
|
||||||
graphRef.current?.centerGraph();
|
graphRef.current?.centerGraph();
|
||||||
|
@ -180,6 +236,41 @@ function EditorTermGraph({ onOpenEdit }: EditorTermGraphProps) {
|
||||||
if (onNodeClick) onNodeClick(node);
|
if (onNodeClick) onNodeClick(node);
|
||||||
}, [onNodeClick, selections, onOpenEdit]);
|
}, [onNodeClick, selections, onOpenEdit]);
|
||||||
|
|
||||||
|
function getOptions() {
|
||||||
|
return {
|
||||||
|
noHermits: noHermits,
|
||||||
|
noTemplates: noTemplates,
|
||||||
|
noTransitive: noTransitive,
|
||||||
|
|
||||||
|
allowBase: allowBase,
|
||||||
|
allowStruct: allowStruct,
|
||||||
|
allowTerm: allowTerm,
|
||||||
|
allowAxiom: allowAxiom,
|
||||||
|
allowFunction: allowFunction,
|
||||||
|
allowPredicate: allowPredicate,
|
||||||
|
allowConstant: allowConstant,
|
||||||
|
allowTheorem: allowTheorem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleChangeOptions = useCallback(
|
||||||
|
(params: GraphEditorParams) => {
|
||||||
|
setNoHermits(params.noHermits);
|
||||||
|
setNoTransitive(params.noTransitive);
|
||||||
|
setNoTemplates(params.noTemplates);
|
||||||
|
|
||||||
|
setAllowBase(params.allowBase);
|
||||||
|
setAllowStruct(params.allowStruct);
|
||||||
|
setAllowTerm(params.allowTerm);
|
||||||
|
setAllowAxiom(params.allowAxiom);
|
||||||
|
setAllowFunction(params.allowFunction);
|
||||||
|
setAllowPredicate(params.allowPredicate);
|
||||||
|
setAllowConstant(params.allowConstant);
|
||||||
|
setAllowTheorem(params.allowTheorem);
|
||||||
|
}, [setNoHermits, setNoTransitive, setNoTemplates,
|
||||||
|
setAllowBase, setAllowStruct, setAllowTerm, setAllowAxiom, setAllowFunction,
|
||||||
|
setAllowPredicate, setAllowConstant, setAllowTheorem]);
|
||||||
|
|
||||||
const canvasWidth = useMemo(
|
const canvasWidth = useMemo(
|
||||||
() => {
|
() => {
|
||||||
return 'calc(100vw - 14.6rem)';
|
return 'calc(100vw - 14.6rem)';
|
||||||
|
@ -199,6 +290,12 @@ function EditorTermGraph({ onOpenEdit }: EditorTermGraphProps) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex justify-between w-full'>
|
<div className='flex justify-between w-full'>
|
||||||
|
{showOptions &&
|
||||||
|
<DlgGraphOptions
|
||||||
|
hideWindow={() => setShowOptions(false)}
|
||||||
|
initial={getOptions()}
|
||||||
|
onConfirm={handleChangeOptions}
|
||||||
|
/>}
|
||||||
<div className='flex flex-col py-2 border-t border-r w-[14.7rem] pr-2 text-sm' style={{height: canvasHeight}}>
|
<div className='flex flex-col py-2 border-t border-r w-[14.7rem] pr-2 text-sm' style={{height: canvasHeight}}>
|
||||||
{hoverCst &&
|
{hoverCst &&
|
||||||
<div className='relative'>
|
<div className='relative'>
|
||||||
|
@ -209,11 +306,11 @@ function EditorTermGraph({ onOpenEdit }: EditorTermGraphProps) {
|
||||||
</div>}
|
</div>}
|
||||||
<div className='flex items-center w-full gap-1'>
|
<div className='flex items-center w-full gap-1'>
|
||||||
<Button
|
<Button
|
||||||
icon={<ArrowsRotateIcon size={7} />}
|
icon={<FilterCogIcon size={7} />}
|
||||||
dense
|
dense
|
||||||
tooltip='Центрировать изображение'
|
tooltip='Настройки фильтрации узлов и связей'
|
||||||
widthClass='h-full'
|
widthClass='h-full'
|
||||||
onClick={handleCenter}
|
onClick={() => setShowOptions(true)}
|
||||||
/>
|
/>
|
||||||
<ConceptSelect
|
<ConceptSelect
|
||||||
className='min-w-[9.3rem]'
|
className='min-w-[9.3rem]'
|
||||||
|
@ -239,11 +336,6 @@ function EditorTermGraph({ onOpenEdit }: EditorTermGraphProps) {
|
||||||
value={orbit}
|
value={orbit}
|
||||||
onChange={ event => setOrbit(event.target.checked) }
|
onChange={ event => setOrbit(event.target.checked) }
|
||||||
/>
|
/>
|
||||||
<Checkbox
|
|
||||||
label='Удалить несвязанные'
|
|
||||||
value={noHermits}
|
|
||||||
onChange={ event => setNoHermits(event.target.checked) }
|
|
||||||
/>
|
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label='Транзитивная редукция'
|
label='Транзитивная редукция'
|
||||||
value={noTransitive}
|
value={noTransitive}
|
||||||
|
@ -257,13 +349,13 @@ function EditorTermGraph({ onOpenEdit }: EditorTermGraphProps) {
|
||||||
<div className='flex flex-wrap justify-center gap-2 py-2'>
|
<div className='flex flex-wrap justify-center gap-2 py-2'>
|
||||||
{dismissed.map(cstID => {
|
{dismissed.map(cstID => {
|
||||||
const cst = schema!.items.find(cst => cst.id === cstID)!;
|
const cst = schema!.items.find(cst => cst.id === cstID)!;
|
||||||
const info = mapStatusInfo.get(cst.status)!;
|
const adjustedColoring = coloringScheme === 'none' ? 'status': coloringScheme;
|
||||||
return (<>
|
return (<>
|
||||||
<div
|
<div
|
||||||
key={`${cst.alias}`}
|
key={`${cst.alias}`}
|
||||||
id={`${prefixes.cst_list}${cst.alias}`}
|
id={`${prefixes.cst_list}${cst.alias}`}
|
||||||
className={`w-fit min-w-[3rem] rounded-md text-center cursor-pointer ${info.color}`}
|
className='w-fit min-w-[3rem] rounded-md text-center cursor-pointer]'
|
||||||
style={dismissedStyle(cstID)}
|
style={ { backgroundColor: getCstNodeColor(cst, adjustedColoring, darkMode), ...dismissedStyle(cstID) }}
|
||||||
onClick={() => toggleDismissed(cstID)}
|
onClick={() => toggleDismissed(cstID)}
|
||||||
onDoubleClick={() => onOpenEdit(cstID)}
|
onDoubleClick={() => onOpenEdit(cstID)}
|
||||||
>
|
>
|
||||||
|
@ -283,28 +375,31 @@ function EditorTermGraph({ onOpenEdit }: EditorTermGraphProps) {
|
||||||
className='relative border-t border-r'
|
className='relative border-t border-r'
|
||||||
style={{width: canvasWidth, height: canvasHeight, borderBottomWidth: noNavigation ? '1px': ''}}
|
style={{width: canvasWidth, height: canvasHeight, borderBottomWidth: noNavigation ? '1px': ''}}
|
||||||
>
|
>
|
||||||
<div id='items-graph-help' className='relative top-0 right-0 z-10 m-2'>
|
<div className='relative top-0 right-0 z-10 flex m-2 flex-start'>
|
||||||
|
<div className='px-1 py-1' id='items-graph-help' >
|
||||||
<HelpIcon color='text-primary' size={6} />
|
<HelpIcon color='text-primary' size={6} />
|
||||||
</div>
|
</div>
|
||||||
|
<MiniButton
|
||||||
|
icon={<ArrowsRotateIcon size={6} />}
|
||||||
|
tooltip='Пересоздать граф'
|
||||||
|
onClick={handleRecreate}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<ConceptTooltip anchorSelect='#items-graph-help'>
|
<ConceptTooltip anchorSelect='#items-graph-help'>
|
||||||
<div>
|
<div>
|
||||||
<h1>Настройка графа</h1>
|
<h1>Настройка графа</h1>
|
||||||
<p><b>Цвет</b> - выбор правила покраски узлов</p>
|
<p><b>Цвет</b> - выбор правила покраски узлов</p>
|
||||||
<p><i>Скрытые конституенты окрашены в цвет статуса</i></p>
|
|
||||||
<p><b>Граф</b> - выбор модели расположения узлов</p>
|
<p><b>Граф</b> - выбор модели расположения узлов</p>
|
||||||
<p><b>Удалить несвязанные</b> - в графе не отображаются одинокие вершины</p>
|
<p><b>Удалить несвязанные</b> - в графе не отображаются одинокие вершины</p>
|
||||||
<p><b>Транзитивная редукция</b> - в графе устраняются транзитивные пути</p>
|
<p><b>Транзитивная редукция</b> - в графе устраняются транзитивные пути</p>
|
||||||
|
|
||||||
<Divider margins='mt-2' />
|
<Divider margins='mt-2' />
|
||||||
|
|
||||||
<h1>Горячие клавиши</h1>
|
<CstClassInfo title='Классы конституент' />
|
||||||
<p><b>Двойной клик</b> - редактирование конституенты</p>
|
|
||||||
<p><b>Delete</b> - удаление конституент</p>
|
|
||||||
<p><b>Alt + 1-6,Q,W</b> - добавление конституент</p>
|
|
||||||
|
|
||||||
<Divider margins='mt-2' />
|
<Divider margins='mt-2' />
|
||||||
|
|
||||||
<CstStatusInfo title='Статусы' />
|
<CstStatusInfo title='Статусы конституент' />
|
||||||
</div>
|
</div>
|
||||||
</ConceptTooltip>
|
</ConceptTooltip>
|
||||||
<GraphCanvas
|
<GraphCanvas
|
||||||
|
@ -321,7 +416,7 @@ function EditorTermGraph({ onOpenEdit }: EditorTermGraphProps) {
|
||||||
onNodePointerOut={handleHoverOut}
|
onNodePointerOut={handleHoverOut}
|
||||||
cameraMode={ orbit ? 'orbit' : is3D ? 'rotate' : 'pan'}
|
cameraMode={ orbit ? 'orbit' : is3D ? 'rotate' : 'pan'}
|
||||||
layoutOverrides={
|
layoutOverrides={
|
||||||
layout.includes('tree') ? { nodeLevelRatio: schema && schema?.items.length < TREE_SIZE_MILESTONE ? 3 : 1 }
|
layout.includes('tree') ? { nodeLevelRatio: filtered.nodes.size < TREE_SIZE_MILESTONE ? 3 : 1 }
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
labelFontUrl={resources.graph_font}
|
labelFontUrl={resources.graph_font}
|
||||||
|
|
|
@ -45,6 +45,16 @@ describe('Testing Graph editing', () => {
|
||||||
expect(graph.hasEdge(4, 1)).toBeFalsy();
|
expect(graph.hasEdge(4, 1)).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('folding node redirectes edges', () => {
|
||||||
|
const graph = new Graph([[1, 3], [2, 3], [3, 4], [3, 5], [3, 3]]);
|
||||||
|
graph.foldNode(3);
|
||||||
|
expect(graph.hasNode(3)).toBeFalsy();
|
||||||
|
expect(graph.hasEdge(1, 4)).toBeTruthy();
|
||||||
|
expect(graph.hasEdge(1, 5)).toBeTruthy();
|
||||||
|
expect(graph.hasEdge(2, 4)).toBeTruthy();
|
||||||
|
expect(graph.hasEdge(2, 5)).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
test('removing isolated nodes', () => {
|
test('removing isolated nodes', () => {
|
||||||
const graph = new Graph([[9, 1], [9, 2], [2, 1], [4, 3], [5, 9], [7], [8]]);
|
const graph = new Graph([[9, 1], [9, 2], [2, 1], [4, 3], [5, 9], [7], [8]]);
|
||||||
graph.removeIsolated()
|
graph.removeIsolated()
|
||||||
|
@ -53,7 +63,7 @@ describe('Testing Graph editing', () => {
|
||||||
|
|
||||||
test('transitive reduction', () => {
|
test('transitive reduction', () => {
|
||||||
const graph = new Graph([[1, 3], [1, 2], [2, 3]]);
|
const graph = new Graph([[1, 3], [1, 2], [2, 3]]);
|
||||||
graph.transitiveReduction()
|
graph.transitiveReduction();
|
||||||
expect(graph.hasEdge(1, 2)).toBeTruthy();
|
expect(graph.hasEdge(1, 2)).toBeTruthy();
|
||||||
expect(graph.hasEdge(2, 3)).toBeTruthy();
|
expect(graph.hasEdge(2, 3)).toBeTruthy();
|
||||||
expect(graph.hasEdge(1, 3)).toBeFalsy();
|
expect(graph.hasEdge(1, 3)).toBeFalsy();
|
||||||
|
|
|
@ -67,6 +67,10 @@ export class Graph {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hasNode(target: number): boolean {
|
||||||
|
return !!this.nodes.get(target);
|
||||||
|
}
|
||||||
|
|
||||||
removeNode(target: number): GraphNode | null {
|
removeNode(target: number): GraphNode | null {
|
||||||
const nodeToRemove = this.nodes.get(target);
|
const nodeToRemove = this.nodes.get(target);
|
||||||
if (!nodeToRemove) {
|
if (!nodeToRemove) {
|
||||||
|
@ -80,6 +84,19 @@ export class Graph {
|
||||||
return nodeToRemove;
|
return nodeToRemove;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foldNode(target: number): GraphNode | null {
|
||||||
|
const nodeToRemove = this.nodes.get(target);
|
||||||
|
if (!nodeToRemove) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
nodeToRemove.inputs.forEach(input => {
|
||||||
|
nodeToRemove.outputs.forEach(output => {
|
||||||
|
this.addEdge(input, output);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
return this.removeNode(target);
|
||||||
|
}
|
||||||
|
|
||||||
removeIsolated(): GraphNode[] {
|
removeIsolated(): GraphNode[] {
|
||||||
const result: GraphNode[] = [];
|
const result: GraphNode[] = [];
|
||||||
this.nodes.forEach(node => {
|
this.nodes.forEach(node => {
|
||||||
|
|
|
@ -101,6 +101,13 @@ export enum CstType {
|
||||||
THEOREM = 'theorem'
|
THEOREM = 'theorem'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum CstClass {
|
||||||
|
BASIC = 'basic',
|
||||||
|
DERIVED = 'derived',
|
||||||
|
STATEMENT = 'statement',
|
||||||
|
TEMPLATE = 'template'
|
||||||
|
}
|
||||||
|
|
||||||
export interface IConstituenta {
|
export interface IConstituenta {
|
||||||
id: number
|
id: number
|
||||||
alias: string
|
alias: string
|
||||||
|
@ -118,7 +125,9 @@ export interface IConstituenta {
|
||||||
resolved: string
|
resolved: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
cstClass: CstClass
|
||||||
status: ExpressionStatus
|
status: ExpressionStatus
|
||||||
|
isTemplate: boolean
|
||||||
parse: {
|
parse: {
|
||||||
status: ParsingStatus
|
status: ParsingStatus
|
||||||
valueClass: ValueClass
|
valueClass: ValueClass
|
||||||
|
@ -230,12 +239,12 @@ export enum EditMode {
|
||||||
|
|
||||||
// RSExpression status
|
// RSExpression status
|
||||||
export enum ExpressionStatus {
|
export enum ExpressionStatus {
|
||||||
UNDEFINED = 0,
|
UNDEFINED = 'undefined',
|
||||||
UNKNOWN,
|
UNKNOWN = 'unknown',
|
||||||
INCORRECT,
|
INCORRECT = 'incorrect',
|
||||||
INCALCULABLE,
|
INCALCULABLE = 'incalculable',
|
||||||
PROPERTY,
|
PROPERTY = 'property',
|
||||||
VERIFIED
|
VERIFIED = 'verified'
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dependency mode for schema analysis
|
// Dependency mode for schema analysis
|
||||||
|
@ -274,7 +283,28 @@ export function inferStatus(parse?: ParsingStatus, value?: ValueClass): Expressi
|
||||||
if (value === ValueClass.PROPERTY) {
|
if (value === ValueClass.PROPERTY) {
|
||||||
return ExpressionStatus.PROPERTY;
|
return ExpressionStatus.PROPERTY;
|
||||||
}
|
}
|
||||||
return ExpressionStatus.VERIFIED
|
return ExpressionStatus.VERIFIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function inferTemplate(expression: string): boolean {
|
||||||
|
const match = expression.match(/R\d+/g);
|
||||||
|
return (match && match?.length > 0) ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function inferClass(type: CstType, isTemplate: boolean): CstClass {
|
||||||
|
if (isTemplate) {
|
||||||
|
return CstClass.TEMPLATE;
|
||||||
|
}
|
||||||
|
switch (type) {
|
||||||
|
case CstType.BASE: return CstClass.BASIC;
|
||||||
|
case CstType.CONSTANT: return CstClass.BASIC;
|
||||||
|
case CstType.STRUCTURED: return CstClass.BASIC;
|
||||||
|
case CstType.TERM: return CstClass.DERIVED;
|
||||||
|
case CstType.FUNCTION: return CstClass.DERIVED;
|
||||||
|
case CstType.AXIOM: return CstClass.STATEMENT;
|
||||||
|
case CstType.PREDICATE: return CstClass.DERIVED;
|
||||||
|
case CstType.THEOREM: return CstClass.STATEMENT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function extractGlobals(expression: string): Set<string> {
|
export function extractGlobals(expression: string): Set<string> {
|
||||||
|
@ -336,6 +366,8 @@ export function LoadRSFormData(schema: IRSFormData): IRSForm {
|
||||||
}
|
}
|
||||||
result.items.forEach(cst => {
|
result.items.forEach(cst => {
|
||||||
cst.status = inferStatus(cst.parse.status, cst.parse.valueClass);
|
cst.status = inferStatus(cst.parse.status, cst.parse.valueClass);
|
||||||
|
cst.isTemplate = inferTemplate(cst.definition.formal);
|
||||||
|
cst.cstClass = inferClass(cst.cstType, cst.isTemplate);
|
||||||
result.graph.addNode(cst.id);
|
result.graph.addNode(cst.id);
|
||||||
const dependencies = extractGlobals(cst.definition.formal);
|
const dependencies = extractGlobals(cst.definition.formal);
|
||||||
dependencies.forEach(value => {
|
dependencies.forEach(value => {
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { LayoutTypes } from 'reagraph';
|
||||||
|
|
||||||
import { ColoringScheme } from '../pages/RSFormPage/EditorTermGraph';
|
import { ColoringScheme } from '../pages/RSFormPage/EditorTermGraph';
|
||||||
import { resolveErrorClass,RSErrorClass, RSErrorType, TokenID } from './enums';
|
import { resolveErrorClass,RSErrorClass, RSErrorType, TokenID } from './enums';
|
||||||
import { CstMatchMode, CstType, DependencyMode,ExpressionStatus, IConstituenta,
|
import { CstClass, CstMatchMode, CstType, DependencyMode, ExpressionStatus, IConstituenta,
|
||||||
IFunctionArg,IRSErrorDescription, IRSForm,
|
IFunctionArg,IRSErrorDescription, IRSForm,
|
||||||
ISyntaxTreeNode, ParsingStatus, ValueClass
|
ISyntaxTreeNode, ParsingStatus, ValueClass
|
||||||
} from './models';
|
} from './models';
|
||||||
|
@ -12,7 +12,7 @@ export interface IRSButtonData {
|
||||||
tooltip: string
|
tooltip: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IStatusInfo {
|
export interface IFormatInfo {
|
||||||
text: string
|
text: string
|
||||||
color: string
|
color: string
|
||||||
tooltip: string
|
tooltip: string
|
||||||
|
@ -245,10 +245,6 @@ export function getCstTypeShortcut(type: CstType) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mapCstTypeColors: Map<CstType, string> = new Map([
|
|
||||||
[CstType.BASE, 'Атлас 2D'],
|
|
||||||
]);
|
|
||||||
|
|
||||||
export const CstTypeSelector = (Object.values(CstType)).map(
|
export const CstTypeSelector = (Object.values(CstType)).map(
|
||||||
(typeStr) => {
|
(typeStr) => {
|
||||||
const type = typeStr as CstType;
|
const type = typeStr as CstType;
|
||||||
|
@ -311,28 +307,15 @@ export const mapLayoutLabels: Map<string, string> = new Map([
|
||||||
export const mapColoringLabels: Map<string, string> = new Map([
|
export const mapColoringLabels: Map<string, string> = new Map([
|
||||||
['none', 'Цвет: моно'],
|
['none', 'Цвет: моно'],
|
||||||
['status', 'Цвет: статус'],
|
['status', 'Цвет: статус'],
|
||||||
['type', 'Цвет: тип'],
|
['type', 'Цвет: класс'],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const GraphColoringSelector: {value: ColoringScheme, label: string}[] = [
|
export const GraphColoringSelector: {value: ColoringScheme, label: string}[] = [
|
||||||
{ value: 'none', label: 'Цвет: моно'},
|
{ value: 'none', label: 'Цвет: моно'},
|
||||||
{ value: 'status', label: 'Цвет: статус'},
|
{ value: 'status', label: 'Цвет: статус'},
|
||||||
{ value: 'type', label: 'Цвет: тип'},
|
{ value: 'type', label: 'Цвет: класс'},
|
||||||
];
|
];
|
||||||
|
|
||||||
export function getCstTypeColor(type: CstType, darkMode: boolean): string {
|
|
||||||
switch (type) {
|
|
||||||
case CstType.BASE: return darkMode ? '#2b8000': '#aaff80';
|
|
||||||
case CstType.CONSTANT: return darkMode ? '#2b8000': '#aaff80';
|
|
||||||
case CstType.STRUCTURED: return darkMode ? '#2b8000': '#aaff80';
|
|
||||||
case CstType.TERM: return darkMode ? '#1e00b3': '#b3bdff';
|
|
||||||
case CstType.FUNCTION: return darkMode ? '#1e00b3': '#b3bdff';
|
|
||||||
case CstType.AXIOM: return darkMode ? '#592b2b': '#ffc9c9';
|
|
||||||
case CstType.PREDICATE: return darkMode ? '#1e00b3': '#b3bdff';
|
|
||||||
case CstType.THEOREM: return darkMode ? '#592b2b': '#ffc9c9';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getCstStatusColor(status: ExpressionStatus, darkMode: boolean): string {
|
export function getCstStatusColor(status: ExpressionStatus, darkMode: boolean): string {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case ExpressionStatus.VERIFIED: return darkMode ? '#2b8000': '#aaff80';
|
case ExpressionStatus.VERIFIED: return darkMode ? '#2b8000': '#aaff80';
|
||||||
|
@ -344,7 +327,7 @@ export function getCstStatusColor(status: ExpressionStatus, darkMode: boolean):
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mapStatusInfo: Map<ExpressionStatus, IStatusInfo> = new Map([
|
export const mapStatusInfo: Map<ExpressionStatus, IFormatInfo> = new Map([
|
||||||
[ ExpressionStatus.VERIFIED, {
|
[ ExpressionStatus.VERIFIED, {
|
||||||
text: 'ок',
|
text: 'ок',
|
||||||
color: 'bg-[#aaff80] dark:bg-[#2b8000]',
|
color: 'bg-[#aaff80] dark:bg-[#2b8000]',
|
||||||
|
@ -377,6 +360,38 @@ export const mapStatusInfo: Map<ExpressionStatus, IStatusInfo> = new Map([
|
||||||
}],
|
}],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
export function getCstClassColor(cstClass: CstClass, darkMode: boolean): string {
|
||||||
|
switch (cstClass) {
|
||||||
|
case CstClass.TEMPLATE: return darkMode ? '#36899e': '#a5e9fa';
|
||||||
|
case CstClass.BASIC: return darkMode ? '#2b8000': '#aaff80';
|
||||||
|
case CstClass.DERIVED: return darkMode ? '#1e00b3': '#b3bdff';
|
||||||
|
case CstClass.STATEMENT: return darkMode ? '#592b2b': '#ffc9c9';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const mapCstClassInfo: Map<CstClass, IFormatInfo> = new Map([
|
||||||
|
[ CstClass.BASIC, {
|
||||||
|
text: 'базовый',
|
||||||
|
color: 'bg-[#aaff80] dark:bg-[#2b8000]',
|
||||||
|
tooltip: 'неопределяемое понятие, требует конвенции'
|
||||||
|
}],
|
||||||
|
[ CstClass.DERIVED, {
|
||||||
|
text: 'производный',
|
||||||
|
color: 'bg-[#b3bdff] dark:bg-[#1e00b3]',
|
||||||
|
tooltip: 'выводимое понятие, задаваемое определением'
|
||||||
|
}],
|
||||||
|
[ CstClass.STATEMENT, {
|
||||||
|
text: 'утверждение',
|
||||||
|
color: 'bg-[#ffc9c9] dark:bg-[#592b2b]',
|
||||||
|
tooltip: 'неопределяемое понятие, требует конвенции'
|
||||||
|
}],
|
||||||
|
[ CstClass.TEMPLATE, {
|
||||||
|
text: 'шаблон',
|
||||||
|
color: 'bg-[#a5e9fa] dark:bg-[#36899e]',
|
||||||
|
tooltip: 'параметризованный шаблон определения'
|
||||||
|
}],
|
||||||
|
]);
|
||||||
|
|
||||||
export function createAliasFor(type: CstType, schema: IRSForm): string {
|
export function createAliasFor(type: CstType, schema: IRSForm): string {
|
||||||
const prefix = getCstTypePrefix(type);
|
const prefix = getCstTypePrefix(type);
|
||||||
if (!schema.items || schema.items.length <= 0) {
|
if (!schema.items || schema.items.length <= 0) {
|
||||||
|
@ -411,6 +426,8 @@ export function getMockConstituenta(id: number, alias: string, type: CstType, co
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
status: ExpressionStatus.INCORRECT,
|
status: ExpressionStatus.INCORRECT,
|
||||||
|
isTemplate: false,
|
||||||
|
cstClass: CstClass.DERIVED,
|
||||||
parse: {
|
parse: {
|
||||||
status: ParsingStatus.INCORRECT,
|
status: ParsingStatus.INCORRECT,
|
||||||
valueClass: ValueClass.INVALID,
|
valueClass: ValueClass.INVALID,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user