mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 13:00:39 +03:00
This commit is contained in:
parent
3f97562fae
commit
72fe4a461f
|
@ -72,6 +72,11 @@ function TooltipOperation({ node, anchor }: TooltipOperationProps) {
|
||||||
<b>КС не принадлежит ОСС</b>
|
<b>КС не принадлежит ОСС</b>
|
||||||
</p>
|
</p>
|
||||||
) : null}
|
) : null}
|
||||||
|
{node.data.operation.is_consolidation ? (
|
||||||
|
<p>
|
||||||
|
<b>Ромбовидный синтез</b>
|
||||||
|
</p>
|
||||||
|
) : null}
|
||||||
{node.data.operation.title ? (
|
{node.data.operation.title ? (
|
||||||
<p>
|
<p>
|
||||||
<b>Название: </b>
|
<b>Название: </b>
|
||||||
|
|
|
@ -62,6 +62,7 @@ export class OssLoader {
|
||||||
this.graph.topologicalOrder().forEach(operationID => {
|
this.graph.topologicalOrder().forEach(operationID => {
|
||||||
const operation = this.operationByID.get(operationID)!;
|
const operation = this.operationByID.get(operationID)!;
|
||||||
const schema = this.items.find(item => item.id === operation.result);
|
const schema = this.items.find(item => item.id === operation.result);
|
||||||
|
operation.is_consolidation = this.inferConsolidation(operationID);
|
||||||
operation.is_owned = !schema || (schema.owner === this.oss.owner && schema.location === this.oss.location);
|
operation.is_owned = !schema || (schema.owner === this.oss.owner && schema.location === this.oss.location);
|
||||||
operation.substitutions = this.oss.substitutions.filter(item => item.operation === operationID);
|
operation.substitutions = this.oss.substitutions.filter(item => item.operation === operationID);
|
||||||
operation.arguments = this.oss.arguments
|
operation.arguments = this.oss.arguments
|
||||||
|
@ -70,6 +71,19 @@ export class OssLoader {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private inferConsolidation(operationID: OperationID): boolean {
|
||||||
|
const inputs = this.graph.expandInputs([operationID]);
|
||||||
|
if (inputs.length === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const ancestors = [...inputs];
|
||||||
|
inputs.forEach(input => {
|
||||||
|
ancestors.push(...this.graph.expandAllInputs([input]));
|
||||||
|
});
|
||||||
|
const unique = new Set(ancestors);
|
||||||
|
return unique.size < ancestors.length;
|
||||||
|
}
|
||||||
|
|
||||||
private calculateStats(): IOperationSchemaStats {
|
private calculateStats(): IOperationSchemaStats {
|
||||||
const items = this.oss.items;
|
const items = this.oss.items;
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -37,6 +37,7 @@ export interface IOperation {
|
||||||
result: LibraryItemID | null;
|
result: LibraryItemID | null;
|
||||||
|
|
||||||
is_owned: boolean;
|
is_owned: boolean;
|
||||||
|
is_consolidation: boolean; // aka 'diamond synthesis'
|
||||||
substitutions: ICstSubstituteEx[];
|
substitutions: ICstSubstituteEx[];
|
||||||
arguments: OperationID[];
|
arguments: OperationID[];
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,7 +148,7 @@ function TableLibraryItems({ items, resetQuery, folderMode, toggleFolderMode }:
|
||||||
{
|
{
|
||||||
when: (item: ILibraryItem) => item.item_type === LibraryItemType.OSS,
|
when: (item: ILibraryItem) => item.item_type === LibraryItemType.OSS,
|
||||||
style: {
|
style: {
|
||||||
backgroundColor: colors.bgGreen50
|
color: colors.fgGreen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,24 +1,37 @@
|
||||||
|
import { IconOSS, IconPredecessor } 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';
|
||||||
|
|
||||||
function HelpConceptOSS() {
|
function HelpConceptOSS() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className='text-justify'>
|
||||||
<h1>Операционная схема синтеза</h1>
|
<h1>Операционная схема синтеза</h1>
|
||||||
<p>
|
<p>
|
||||||
Работа со сложными предметными областями требует многократного{' '}
|
Работа со сложными предметными областями требует многократного{' '}
|
||||||
<LinkTopic text='синтеза' topic={HelpTopic.CC_SYNTHESIS} /> для построения целевых понятий. Последовательность
|
<LinkTopic text='синтеза' topic={HelpTopic.CC_SYNTHESIS} /> для построения целевых понятий. Последовательность
|
||||||
синтезов концептуальных схем задается с помощью <b>Операционной схемы синтеза (ОСС)</b> в форме Графа синтеза.
|
синтезов задается с помощью{' '}
|
||||||
|
<span className='text-nowrap'>
|
||||||
|
<IconOSS className='inline-icon' /> <b>Операционной схемы синтеза (ОСС)</b>
|
||||||
|
</span>{' '}
|
||||||
|
и отображается в форме <LinkTopic text='Графа синтеза' topic={HelpTopic.UI_OSS_GRAPH} />.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Отдельные операции в рамках ОСС задаются <b>таблицами отождествлений</b> понятий из синтезируемых схем. Таким
|
Отдельные операции в рамках ОСС задаются <b>таблицами отождествлений</b> понятий из синтезируемых схем. Таким
|
||||||
образом <LinkTopic text='конституенты' topic={HelpTopic.CC_CONSTITUENTA} /> в каждой КС разделяются на
|
образом <LinkTopic text='конституенты' topic={HelpTopic.CC_CONSTITUENTA} /> в каждой КС разделяются на исходные
|
||||||
наследованные, отождествленные и дописанные.
|
(дописанные), наследованные, отождествленные (удаляемые).
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Портал поддерживает <b>сквозные изменения</b> в рамках ОСС. Изменения, внесенные в исходные концептуальные схемы
|
Портал поддерживает <b>сквозные изменения</b> в рамках ОСС. Изменения, внесенные в исходные концептуальные схемы
|
||||||
автоматически проносятся через граф синтеза (путем обновления наследованных конституент). Формальные определения
|
автоматически проносятся через граф синтеза (путем обновления наследованных конституент). Формальные определения
|
||||||
наследованных конституент можно редактировать только путем изменения исходных конституент.
|
наследованных конституент можно редактировать только путем изменения{' '}
|
||||||
|
<span className='text-nowrap'>
|
||||||
|
<IconPredecessor className='inline-icon' /> исходных конституент.
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<b>Ромбовидным синтезом</b> называется операция, где используются КС, имеющие общих предков. При таком синтезе
|
||||||
|
могут возникать дубликаты и неоднозначности в результате. Необходимо внимательно формировать таблицу
|
||||||
|
отождествлений, добавляя дублирующиеся понятия из синтезируемых схем.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -40,8 +40,8 @@ function HelpConceptSynthesis() {
|
||||||
<LinkTopic text='разделе Операции' topic={HelpTopic.RSL_OPERATIONS} />
|
<LinkTopic text='разделе Операции' topic={HelpTopic.RSL_OPERATIONS} />
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Для управления совокупностью синтезов используются <b>операционные схемы синтеза</b>. В данный момент этот
|
Для управления совокупностью синтезов используются{' '}
|
||||||
функционал еще не реализован в Портале.
|
<LinkTopic text='операционные схемы синтеза' topic={HelpTopic.CC_OSS} />.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,18 +5,28 @@ import {
|
||||||
IconFolderEmpty,
|
IconFolderEmpty,
|
||||||
IconFolderOpened,
|
IconFolderOpened,
|
||||||
IconFolderTree,
|
IconFolderTree,
|
||||||
|
IconOSS,
|
||||||
|
IconRSForm,
|
||||||
IconSearch,
|
IconSearch,
|
||||||
IconShow,
|
IconShow,
|
||||||
IconSortAsc,
|
IconSortAsc,
|
||||||
IconSortDesc
|
IconSortDesc
|
||||||
} from '@/components/Icons';
|
} from '@/components/Icons';
|
||||||
|
import { useConceptOptions } from '@/context/ConceptOptionsContext';
|
||||||
|
|
||||||
function HelpLibrary() {
|
function HelpLibrary() {
|
||||||
|
const { colors } = useConceptOptions();
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h1>Библиотека схем</h1>
|
<h1>Библиотека схем</h1>
|
||||||
<p>В библиотеке собраны концептуальные схемы, эксплицированные в родоструктурном аппарате</p>
|
<p>
|
||||||
|
В библиотеке собраны <IconRSForm size='1rem' className='inline-icon' /> системы определений (КС) <br />и
|
||||||
|
<IconOSS size='1rem' className='inline-icon' /> операционные схемы синтеза (ОСС).
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<span style={{ color: colors.fgGreen }}>зеленым текстом</span> выделены ОСС
|
||||||
|
</li>
|
||||||
<li>клик по строке - переход к редактированию схемы</li>
|
<li>клик по строке - переход к редактированию схемы</li>
|
||||||
<li>Ctrl + клик по строке откроет схему в новой вкладке</li>
|
<li>Ctrl + клик по строке откроет схему в новой вкладке</li>
|
||||||
<li>Фильтры атрибутов три позиции: да/нет/не применять</li>
|
<li>Фильтры атрибутов три позиции: да/нет/не применять</li>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import {
|
import {
|
||||||
|
IconAlert,
|
||||||
IconAnimation,
|
IconAnimation,
|
||||||
IconAnimationOff,
|
IconAnimationOff,
|
||||||
IconConnect,
|
IconConnect,
|
||||||
|
@ -23,7 +24,7 @@ import { HelpTopic } from '@/models/miscellaneous';
|
||||||
function HelpOssGraph() {
|
function HelpOssGraph() {
|
||||||
return (
|
return (
|
||||||
<div className='flex flex-col'>
|
<div className='flex flex-col'>
|
||||||
<h1>Граф синтеза</h1>
|
<h1 className='sm:pr-[6rem]'>Граф синтеза</h1>
|
||||||
<div className='flex flex-col sm:flex-row'>
|
<div className='flex flex-col sm:flex-row'>
|
||||||
<div className='w-full sm:w-[14rem]'>
|
<div className='w-full sm:w-[14rem]'>
|
||||||
<h1>Настройка графа</h1>
|
<h1>Настройка графа</h1>
|
||||||
|
@ -50,7 +51,10 @@ function HelpOssGraph() {
|
||||||
<li>Клик на операцию – выделение</li>
|
<li>Клик на операцию – выделение</li>
|
||||||
<li>Esc – сбросить выделение</li>
|
<li>Esc – сбросить выделение</li>
|
||||||
<li>
|
<li>
|
||||||
<IconEdit2 className='inline-icon' /> Двойной клик – редактирование
|
Двойной клик – переход к связанной <LinkTopic text='КС' topic={HelpTopic.CC_SYSTEM} />
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<IconEdit2 className='inline-icon' /> Редактирование операции
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<IconNewItem className='inline-icon icon-green' /> Новая операция
|
<IconNewItem className='inline-icon icon-green' /> Новая операция
|
||||||
|
@ -73,7 +77,7 @@ function HelpOssGraph() {
|
||||||
<IconSave className='inline-icon' /> Сохранить положения
|
<IconSave className='inline-icon' /> Сохранить положения
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<IconImage className='inline-icon' /> Сохранить в формат SVG
|
<IconImage className='inline-icon' /> Сохранить в SVG
|
||||||
</li>
|
</li>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -82,9 +86,12 @@ function HelpOssGraph() {
|
||||||
<div className='dense w-[21rem]'>
|
<div className='dense w-[21rem]'>
|
||||||
<h1>Контекстное меню</h1>
|
<h1>Контекстное меню</h1>
|
||||||
<li>
|
<li>
|
||||||
<IconRSForm className='inline-icon icon-green' /> Переход к связанной{' '}
|
<IconRSForm className='inline-icon icon-green' /> Статус связанной{' '}
|
||||||
<LinkTopic text='КС' topic={HelpTopic.CC_SYSTEM} />
|
<LinkTopic text='КС' topic={HelpTopic.CC_SYSTEM} />
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<IconAlert className='inline-icon' /> <LinkTopic text='Ромбовидный синтез' topic={HelpTopic.CC_OSS} />
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<IconNewRSForm className='inline-icon icon-green' /> Создать пустую КС для загрузки
|
<IconNewRSForm className='inline-icon icon-green' /> Создать пустую КС для загрузки
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -21,11 +21,12 @@ function InputNode(node: OssNodeInternal) {
|
||||||
<>
|
<>
|
||||||
<Handle type='source' position={Position.Bottom} />
|
<Handle type='source' position={Position.Bottom} />
|
||||||
|
|
||||||
<Overlay position='top-[-0.2rem] right-[-0.2rem]'>
|
<Overlay position='top-0 right-0' className='flex'>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
icon={<IconRSForm className={hasFile ? 'clr-text-green' : 'clr-text-red'} size='0.75rem' />}
|
icon={<IconRSForm className={hasFile ? 'clr-text-green' : 'clr-text-red'} size='0.75rem' />}
|
||||||
noHover
|
noHover
|
||||||
title='Связанная КС'
|
noPadding
|
||||||
|
title={hasFile ? 'Связанная КС' : 'Нет связанной КС'}
|
||||||
hideTitle={!controller.showTooltip}
|
hideTitle={!controller.showTooltip}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleOpenSchema();
|
handleOpenSchema();
|
||||||
|
|
|
@ -105,7 +105,7 @@ function NodeContextMenu({
|
||||||
<Dropdown isOpen={isOpen} stretchLeft={cursorX >= window.innerWidth - PARAMETER.ossContextMenuWidth}>
|
<Dropdown isOpen={isOpen} stretchLeft={cursorX >= window.innerWidth - PARAMETER.ossContextMenuWidth}>
|
||||||
<DropdownButton
|
<DropdownButton
|
||||||
text='Редактировать'
|
text='Редактировать'
|
||||||
titleHtml={prepareTooltip('Редактировать операцию', 'Двойной клик')}
|
title='Редактировать операцию'
|
||||||
icon={<IconEdit2 size='1rem' className='icon-primary' />}
|
icon={<IconEdit2 size='1rem' className='icon-primary' />}
|
||||||
disabled={controller.isProcessing}
|
disabled={controller.isProcessing}
|
||||||
onClick={handleEditOperation}
|
onClick={handleEditOperation}
|
||||||
|
@ -113,7 +113,7 @@ function NodeContextMenu({
|
||||||
|
|
||||||
{operation.result ? (
|
{operation.result ? (
|
||||||
<DropdownButton
|
<DropdownButton
|
||||||
text='Открыть схему'
|
text={prepareTooltip('Открыть схему', 'Двойной клик')}
|
||||||
title='Открыть привязанную КС'
|
title='Открыть привязанную КС'
|
||||||
icon={<IconRSForm size='1rem' className='icon-green' />}
|
icon={<IconRSForm size='1rem' className='icon-green' />}
|
||||||
disabled={controller.isProcessing}
|
disabled={controller.isProcessing}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Handle, Position } from 'reactflow';
|
import { Handle, Position } from 'reactflow';
|
||||||
|
|
||||||
import { IconRSForm } from '@/components/Icons';
|
import { IconAlert, IconRSForm } from '@/components/Icons';
|
||||||
import TooltipOperation from '@/components/info/TooltipOperation';
|
import TooltipOperation from '@/components/info/TooltipOperation';
|
||||||
import MiniButton from '@/components/ui/MiniButton.tsx';
|
import MiniButton from '@/components/ui/MiniButton.tsx';
|
||||||
import Overlay from '@/components/ui/Overlay';
|
import Overlay from '@/components/ui/Overlay';
|
||||||
|
@ -22,15 +22,31 @@ function OperationNode(node: OssNodeInternal) {
|
||||||
<>
|
<>
|
||||||
<Handle type='source' position={Position.Bottom} />
|
<Handle type='source' position={Position.Bottom} />
|
||||||
|
|
||||||
<Overlay position='top-[-0.2rem] right-[-0.2rem]'>
|
<Overlay position='top-0 right-0' className='flex flex-col gap-1'>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
icon={<IconRSForm className={hasFile ? 'clr-text-green' : 'clr-text-red'} size='0.75rem' />}
|
icon={
|
||||||
|
<IconRSForm
|
||||||
|
className={hasFile ? 'clr-text-green' : 'clr-text-red'}
|
||||||
|
size={node.data.operation.is_consolidation ? '0.6rem' : '0.75rem'}
|
||||||
|
/>
|
||||||
|
}
|
||||||
noHover
|
noHover
|
||||||
title='Связанная КС'
|
noPadding
|
||||||
|
title={hasFile ? 'Связанная КС' : 'Нет связанной КС'}
|
||||||
hideTitle={!controller.showTooltip}
|
hideTitle={!controller.showTooltip}
|
||||||
onClick={handleOpenSchema}
|
onClick={handleOpenSchema}
|
||||||
disabled={!hasFile}
|
disabled={!hasFile}
|
||||||
/>
|
/>
|
||||||
|
{node.data.operation.is_consolidation ? (
|
||||||
|
<MiniButton
|
||||||
|
icon={<IconAlert className='clr-text-primary' size='0.6rem' />}
|
||||||
|
disabled
|
||||||
|
noPadding
|
||||||
|
noHover
|
||||||
|
title='Внимание! Ромбовидный синтез'
|
||||||
|
hideTitle={!controller.showTooltip}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
</Overlay>
|
</Overlay>
|
||||||
|
|
||||||
{!node.data.operation.is_owned ? (
|
{!node.data.operation.is_owned ? (
|
||||||
|
|
|
@ -299,9 +299,13 @@ function OssFlow({ isModified, setIsModified }: OssFlowProps) {
|
||||||
(event: CProps.EventMouse, node: OssNode) => {
|
(event: CProps.EventMouse, node: OssNode) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
handleEditOperation(Number(node.id));
|
if (node.data.operation.result) {
|
||||||
|
controller.openOperationSchema(Number(node.id));
|
||||||
|
} else {
|
||||||
|
handleEditOperation(Number(node.id));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
[handleEditOperation]
|
[handleEditOperation, controller.openOperationSchema]
|
||||||
);
|
);
|
||||||
|
|
||||||
function handleKeyDown(event: React.KeyboardEvent<HTMLDivElement>) {
|
function handleKeyDown(event: React.KeyboardEvent<HTMLDivElement>) {
|
||||||
|
|
|
@ -89,16 +89,14 @@ function EditorLibraryItem({ item, isModified, controller }: EditorLibraryItemPr
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{accessLevel >= UserLevel.OWNER ? (
|
{accessLevel >= UserLevel.OWNER ? (
|
||||||
<Overlay position='top-[-0.5rem] left-[5.5rem] cc-icons'>
|
<Overlay position='top-[-0.5rem] left-[5.5rem]' className='cc-icons'>
|
||||||
<div className='flex items-start'>
|
<MiniButton
|
||||||
<MiniButton
|
title='Изменить редакторов'
|
||||||
title='Изменить редакторов'
|
noHover
|
||||||
noHover
|
onClick={() => controller.promptEditors()}
|
||||||
onClick={() => controller.promptEditors()}
|
icon={<IconEdit size='1rem' className='mt-1 icon-primary' />}
|
||||||
icon={<IconEdit size='1rem' className='mt-1 icon-primary' />}
|
disabled={isModified || controller.isProcessing}
|
||||||
disabled={isModified || controller.isProcessing}
|
/>
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Overlay>
|
</Overlay>
|
||||||
) : null}
|
) : null}
|
||||||
<LabeledValue
|
<LabeledValue
|
||||||
|
|
Loading…
Reference in New Issue
Block a user