F: Add schemas coloring option for TermGraph
This commit is contained in:
parent
d33f3e02b4
commit
0149f98c8b
|
@ -126,7 +126,7 @@ class InheritanceDataSerializer(serializers.Serializer):
|
|||
''' Serializer: inheritance data. '''
|
||||
child = serializers.IntegerField()
|
||||
child_source = serializers.IntegerField()
|
||||
parent = serializers.IntegerField()
|
||||
parent = serializers.IntegerField() # type: ignore
|
||||
parent_source = serializers.IntegerField()
|
||||
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ import TextURL from '@/components/ui/TextURL';
|
|||
import Tooltip, { PlacesType } from '@/components/ui/Tooltip';
|
||||
import { useConceptOptions } from '@/context/ConceptOptionsContext';
|
||||
import { HelpTopic } from '@/models/miscellaneous';
|
||||
import TopicPage from '@/pages/ManualsPage/TopicPage';
|
||||
|
||||
import TopicPage from '../../pages/ManualsPage/TopicPage';
|
||||
import { IconHelp } from '../Icons';
|
||||
import { CProps } from '../props';
|
||||
|
||||
|
|
|
@ -60,10 +60,14 @@ export class RSFormLoader {
|
|||
}
|
||||
|
||||
private inferCstAttributes() {
|
||||
const parent_schemas = new Map<ConstituentaID, LibraryItemID>();
|
||||
const schemaByCst = new Map<ConstituentaID, LibraryItemID>();
|
||||
const parents: LibraryItemID[] = [];
|
||||
this.schema.inheritance.forEach(item => {
|
||||
if (item.child_source === this.schema.id) {
|
||||
parent_schemas.set(item.child, item.parent_source);
|
||||
schemaByCst.set(item.child, item.parent_source);
|
||||
if (!parents.includes(item.parent_source)) {
|
||||
parents.push(item.parent_source);
|
||||
}
|
||||
}
|
||||
});
|
||||
const inherit_children = new Set(this.schema.inheritance.map(item => item.child));
|
||||
|
@ -75,7 +79,8 @@ export class RSFormLoader {
|
|||
cst.cst_class = inferClass(cst.cst_type, cst.is_template);
|
||||
cst.spawn = [];
|
||||
cst.spawn_alias = [];
|
||||
cst.parent_schema = parent_schemas.get(cst.id);
|
||||
cst.parent_schema = schemaByCst.get(cst.id);
|
||||
cst.parent_schema_index = cst.parent_schema ? parents.indexOf(cst.parent_schema) + 1 : 0;
|
||||
cst.is_inherited = inherit_children.has(cst.id);
|
||||
cst.has_inherited_children = inherit_parents.has(cst.id);
|
||||
cst.is_simple_expression = this.inferSimpleExpression(cst);
|
||||
|
|
|
@ -48,7 +48,7 @@ export interface OssNodeInternal {
|
|||
/**
|
||||
* Represents graph node coloring scheme.
|
||||
*/
|
||||
export type GraphColoring = 'none' | 'status' | 'type';
|
||||
export type GraphColoring = 'none' | 'status' | 'type' | 'schemas';
|
||||
|
||||
/**
|
||||
* Represents graph node sizing scheme.
|
||||
|
|
|
@ -111,6 +111,10 @@ export interface IConstituenta extends IConstituentaData {
|
|||
/** Indicates if this {@link IConstituenta} has a simple expression. */
|
||||
is_simple_expression: boolean;
|
||||
|
||||
/** Index of {@link LibraryItemID} that contains this cst (or inheritance parent).
|
||||
* 0 - not inherited, 1 - inherited by 1st schema, 2 - inherited by 2nd schema, etc.
|
||||
*/
|
||||
parent_schema_index: number;
|
||||
/** {@link LibraryItemID} that contains parent of this inherited {@link IConstituenta}. */
|
||||
parent_schema?: LibraryItemID;
|
||||
/** Indicates if this {@link IConstituenta} is inherited. */
|
||||
|
|
|
@ -132,6 +132,7 @@ export function createMockConstituenta(id: ConstituentaID, alias: string, commen
|
|||
definition_raw: '',
|
||||
definition_resolved: '',
|
||||
status: ExpressionStatus.INCORRECT,
|
||||
parent_schema_index: 0,
|
||||
is_template: false,
|
||||
is_inherited: false,
|
||||
has_inherited_children: false,
|
||||
|
|
|
@ -261,6 +261,7 @@ function EditorTermGraph({ onOpenEdit }: EditorTermGraphProps) {
|
|||
const selectors = useMemo(
|
||||
() => (
|
||||
<GraphSelectors
|
||||
schema={controller.schema}
|
||||
coloring={coloring}
|
||||
layout={layout}
|
||||
sizing={sizing}
|
||||
|
@ -269,7 +270,7 @@ function EditorTermGraph({ onOpenEdit }: EditorTermGraphProps) {
|
|||
setSizing={setSizing}
|
||||
/>
|
||||
),
|
||||
[coloring, layout, sizing, handleChangeLayout, setColoring, setSizing]
|
||||
[coloring, controller.schema, layout, sizing, handleChangeLayout, setColoring, setSizing]
|
||||
);
|
||||
const viewHidden = useMemo(
|
||||
() => (
|
||||
|
|
|
@ -3,10 +3,14 @@ import { GraphLayout } from '@/components/ui/GraphUI';
|
|||
import Overlay from '@/components/ui/Overlay';
|
||||
import SelectSingle from '@/components/ui/SelectSingle';
|
||||
import { GraphColoring, GraphSizing, HelpTopic } from '@/models/miscellaneous';
|
||||
import { IRSForm } from '@/models/rsform';
|
||||
import { mapLabelColoring, mapLabelLayout, mapLabelSizing } from '@/utils/labels';
|
||||
import { SelectorGraphColoring, SelectorGraphLayout, SelectorGraphSizing } from '@/utils/selectors';
|
||||
|
||||
import SchemasGuide from './SchemasGuide';
|
||||
|
||||
interface GraphSelectorsProps {
|
||||
schema?: IRSForm;
|
||||
coloring: GraphColoring;
|
||||
layout: GraphLayout;
|
||||
sizing: GraphSizing;
|
||||
|
@ -16,7 +20,7 @@ interface GraphSelectorsProps {
|
|||
setSizing: (newValue: GraphSizing) => void;
|
||||
}
|
||||
|
||||
function GraphSelectors({ coloring, setColoring, layout, setLayout, sizing, setSizing }: GraphSelectorsProps) {
|
||||
function GraphSelectors({ schema, coloring, setColoring, layout, setLayout, sizing, setSizing }: GraphSelectorsProps) {
|
||||
return (
|
||||
<div className='border rounded-b-none select-none clr-input rounded-t-md'>
|
||||
<SelectSingle
|
||||
|
@ -30,6 +34,7 @@ function GraphSelectors({ coloring, setColoring, layout, setLayout, sizing, setS
|
|||
<Overlay position='right-[2.5rem] top-[0.5rem]'>
|
||||
{coloring === 'status' ? <BadgeHelp topic={HelpTopic.UI_CST_STATUS} className='min-w-[25rem]' /> : null}
|
||||
{coloring === 'type' ? <BadgeHelp topic={HelpTopic.UI_CST_CLASS} className='min-w-[25rem]' /> : null}
|
||||
{coloring === 'schemas' && !!schema ? <SchemasGuide schema={schema} /> : null}
|
||||
</Overlay>
|
||||
<SelectSingle
|
||||
className='my-1'
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
import { useMemo } from 'react';
|
||||
|
||||
import { IconHelp } from '@/components/Icons';
|
||||
import Tooltip from '@/components/ui/Tooltip';
|
||||
import { useConceptOptions } from '@/context/ConceptOptionsContext';
|
||||
import { useLibrary } from '@/context/LibraryContext';
|
||||
import { LibraryItemID } from '@/models/library';
|
||||
import { IRSForm } from '@/models/rsform';
|
||||
import { colorBgSchemas } from '@/styling/color';
|
||||
import { globals, prefixes } from '@/utils/constants';
|
||||
|
||||
interface SchemasGuideProps {
|
||||
schema: IRSForm;
|
||||
}
|
||||
|
||||
function SchemasGuide({ schema }: SchemasGuideProps) {
|
||||
const { colors } = useConceptOptions();
|
||||
const library = useLibrary();
|
||||
|
||||
const schemas = useMemo(() => {
|
||||
const processed = new Set<LibraryItemID>();
|
||||
const aliases: string[] = [];
|
||||
const indexes: number[] = [];
|
||||
schema.items.forEach(cst => {
|
||||
if (cst.parent_schema && !processed.has(cst.parent_schema)) {
|
||||
const item = library.items.find(item => item.id === cst.parent_schema);
|
||||
if (item) {
|
||||
aliases.push(item.alias);
|
||||
} else {
|
||||
aliases.push(`Схема ${cst.parent_schema_index}`);
|
||||
}
|
||||
processed.add(cst.parent_schema);
|
||||
indexes.push(cst.parent_schema_index);
|
||||
}
|
||||
});
|
||||
const result: string[] = [];
|
||||
for (let i = 1; i <= aliases.length; i++) {
|
||||
const trueIndex = indexes.findIndex(index => index === i);
|
||||
result.push(aliases[trueIndex]);
|
||||
}
|
||||
return result;
|
||||
}, [schema, library.items]);
|
||||
|
||||
return (
|
||||
<div tabIndex={-1} id={globals.graph_schemas} className='p-1'>
|
||||
<IconHelp size='1.25rem' className='icon-primary' />
|
||||
<Tooltip
|
||||
anchorSelect={`#${globals.graph_schemas}`}
|
||||
layer='z-modalTooltip'
|
||||
place='right'
|
||||
className='max-w-[25rem] break-words text-base'
|
||||
>
|
||||
<div>
|
||||
<span
|
||||
className='min-w-[0.6rem] min-h-[0.6rem] border inline-block mr-1 rounded-full'
|
||||
style={{ backgroundColor: colorBgSchemas(0, colors) }}
|
||||
/>
|
||||
Текущая схема
|
||||
</div>
|
||||
{schemas.map((alias, index) => (
|
||||
<div key={`${prefixes.schemas_list}${index}`}>
|
||||
<span
|
||||
className='min-w-[0.6rem] min-h-[0.6rem] border inline-block mr-1 rounded-full'
|
||||
style={{ backgroundColor: colorBgSchemas(index + 1, colors) }}
|
||||
/>
|
||||
{alias}
|
||||
</div>
|
||||
))}
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default SchemasGuide;
|
|
@ -1,6 +1,6 @@
|
|||
'use client';
|
||||
|
||||
import { RefObject, useCallback, useLayoutEffect, useMemo } from 'react';
|
||||
import { RefObject, useCallback, useLayoutEffect } from 'react';
|
||||
|
||||
import GraphUI, {
|
||||
CollapseProps,
|
||||
|
@ -107,12 +107,8 @@ function TermGraph({
|
|||
setSelections(newSelections);
|
||||
}, [selectedIDs, setSelections, nodes]);
|
||||
|
||||
const canvasWidth = useMemo(() => {
|
||||
return 'calc(100vw - 1rem)';
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className='relative outline-none' style={{ width: canvasWidth, height: mainHeight }}>
|
||||
<div className='relative outline-none w-[100dvw]' style={{ height: mainHeight }}>
|
||||
<GraphUI
|
||||
nodes={nodes}
|
||||
edges={edges}
|
||||
|
|
|
@ -416,6 +416,23 @@ export function colorBgCstClass(cstClass: CstClass, colors: IColorTheme): string
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines background color for {@link IConstituenta} depending on its parent schema index.
|
||||
*/
|
||||
export function colorBgSchemas(schema_index: number, colors: IColorTheme): string {
|
||||
if (schema_index === 0) {
|
||||
return colors.bgGreen;
|
||||
}
|
||||
// prettier-ignore
|
||||
switch (schema_index % 4) {
|
||||
case 1: return colors.bgPurple;
|
||||
case 2: return colors.bgOrange;
|
||||
case 3: return colors.bgTeal;
|
||||
case 0: return colors.bgBlue;
|
||||
}
|
||||
return colors.bgBlue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines background color for {@link GramData}.
|
||||
*/
|
||||
|
@ -462,5 +479,8 @@ export function colorBgGraphNode(cst: IConstituenta, coloringScheme: GraphColori
|
|||
if (coloringScheme === 'status') {
|
||||
return colorBgCstStatus(cst.status, colors);
|
||||
}
|
||||
if (coloringScheme === 'schemas') {
|
||||
return colorBgSchemas(cst.parent_schema_index, colors);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
|
|
@ -143,7 +143,8 @@ export const globals = {
|
|||
email_tooltip: 'email_tooltip',
|
||||
main_scroll: 'main_scroll',
|
||||
library_item_editor: 'library_item_editor',
|
||||
constituenta_editor: 'constituenta_editor'
|
||||
constituenta_editor: 'constituenta_editor',
|
||||
graph_schemas: 'graph_schemas_tooltip'
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -165,6 +166,7 @@ export const prefixes = {
|
|||
cst_source_list: 'cst_source_list_',
|
||||
cst_delete_list: 'cst_delete_list_',
|
||||
cst_dependant_list: 'cst_dependant_list_',
|
||||
schemas_list: 'schemas_list_',
|
||||
operation_list: 'operation_list_',
|
||||
csttype_list: 'csttype_',
|
||||
policy_list: 'policy_list_',
|
||||
|
|
|
@ -315,7 +315,8 @@ export const mapLabelLayout = new Map<GraphLayout, string>([
|
|||
export const mapLabelColoring = new Map<GraphColoring, string>([
|
||||
['none', 'Цвет: Моно'],
|
||||
['status', 'Цвет: Статус'],
|
||||
['type', 'Цвет: Класс']
|
||||
['type', 'Цвет: Класс'],
|
||||
['schemas', 'Цвет: Схемы']
|
||||
]);
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue
Block a user