From 2fbbec04667d71b53b0eebd72b05d7c509da030b Mon Sep 17 00:00:00 2001 From: IRBorisov <8611739+IRBorisov@users.noreply.github.com> Date: Fri, 5 Apr 2024 20:04:12 +0300 Subject: [PATCH] Improve concept derivation UI --- .../src/components/info/InfoConstituenta.tsx | 12 +++++------ .../src/components/man/HelpConstituenta.tsx | 1 + .../frontend/src/dialogs/DlgGraphParams.tsx | 2 +- rsconcept/frontend/src/models/rsform.ts | 5 +++-- rsconcept/frontend/src/models/rsformAPI.ts | 7 +++++-- .../frontend/src/models/rslangAPI.test.ts | 2 ++ rsconcept/frontend/src/models/rslangAPI.ts | 2 +- .../EditorTermGraph/EditorTermGraph.tsx | 21 ++++++++++++------- .../EditorTermGraph/GraphToolbar.tsx | 2 +- .../RSFormPage/EditorTermGraph/TermGraph.tsx | 6 ++++-- .../EditorTermGraph/useGraphFilter.ts | 2 +- .../ViewConstituents/ConstituentsTable.tsx | 12 +++++++++++ rsconcept/frontend/src/styling/color.ts | 9 ++++++++ 13 files changed, 60 insertions(+), 23 deletions(-) diff --git a/rsconcept/frontend/src/components/info/InfoConstituenta.tsx b/rsconcept/frontend/src/components/info/InfoConstituenta.tsx index f43c4fcd..a6c5d14c 100644 --- a/rsconcept/frontend/src/components/info/InfoConstituenta.tsx +++ b/rsconcept/frontend/src/components/info/InfoConstituenta.tsx @@ -11,18 +11,18 @@ interface InfoConstituentaProps extends CProps.Div { function InfoConstituenta({ data, className, ...restProps }: InfoConstituentaProps) { return ( -
+

Конституента {data.alias}

- {data.derived_alias ? ( + {data.derived_from_alias ? (

- Основана на: - {data.derived_alias} + Основание: + {data.derived_from_alias}

) : null} - {data.derived_children.length > 0 ? ( + {data.derived_children_alias.length > 0 ? (

Порождает: - {data.derived_children.join(', ')} + {data.derived_children_alias.join(', ')}

) : null}

diff --git a/rsconcept/frontend/src/components/man/HelpConstituenta.tsx b/rsconcept/frontend/src/components/man/HelpConstituenta.tsx index 5d577dd4..f3238510 100644 --- a/rsconcept/frontend/src/components/man/HelpConstituenta.tsx +++ b/rsconcept/frontend/src/components/man/HelpConstituenta.tsx @@ -6,6 +6,7 @@ function HelpConstituenta() { return (

Редактор конституент

+

При выделении также подсвечиваются производные и основание

Сохранить изменения: Ctrl + S или клик по кнопке Сохранить

Формальное определение

- Ctrl + Пробел дополняет до незанятого имени

diff --git a/rsconcept/frontend/src/dialogs/DlgGraphParams.tsx b/rsconcept/frontend/src/dialogs/DlgGraphParams.tsx index dde5357f..3f04cf52 100644 --- a/rsconcept/frontend/src/dialogs/DlgGraphParams.tsx +++ b/rsconcept/frontend/src/dialogs/DlgGraphParams.tsx @@ -57,7 +57,7 @@ function DlgGraphParams({ hideWindow, initial, onConfirm }: DlgGraphParamsProps) /> updateParams({ foldDerived: value })} /> diff --git a/rsconcept/frontend/src/models/rsform.ts b/rsconcept/frontend/src/models/rsform.ts index 08924ea7..d066feff 100644 --- a/rsconcept/frontend/src/models/rsform.ts +++ b/rsconcept/frontend/src/models/rsform.ts @@ -97,8 +97,9 @@ export interface IConstituenta extends IConstituentaMeta { status: ExpressionStatus; is_template: boolean; derived_from: ConstituentaID; - derived_alias?: string; - derived_children: string[]; + derived_from_alias?: string; + derived_children: number[]; + derived_children_alias: string[]; parse: { status: ParsingStatus; valueClass: ValueClass; diff --git a/rsconcept/frontend/src/models/rsformAPI.ts b/rsconcept/frontend/src/models/rsformAPI.ts index 807352b4..05be1929 100644 --- a/rsconcept/frontend/src/models/rsformAPI.ts +++ b/rsconcept/frontend/src/models/rsformAPI.ts @@ -37,6 +37,7 @@ export function loadRSFormData(input: IRSFormData): IRSForm { derivationLookup.set(cst.id, cst.id); cst.derived_from = cst.id; cst.derived_children = []; + cst.derived_children_alias = []; cst.status = inferStatus(cst.parse.status, cst.parse.valueClass); cst.is_template = inferTemplate(cst.definition_formal); cst.cst_class = inferClass(cst.cst_type, cst.is_template); @@ -72,8 +73,9 @@ export function loadRSFormData(input: IRSFormData): IRSForm { if (resolvedInput.size === 1 && isSimpleExpression(definition)) { const parent = result.items.find(item => item.id === resolvedInput.values().next().value)!; cst.derived_from = parent.id; - cst.derived_alias = parent.alias; - parent.derived_children.push(cst.alias); + cst.derived_from_alias = parent.alias; + parent.derived_children_alias.push(cst.alias); + parent.derived_children.push(cst.id); derivationLookup.set(cst.id, parent.id); } }); @@ -208,6 +210,7 @@ export function createMockConstituenta(id: ConstituentaID, alias: string, commen id: id, derived_from: id, derived_children: [], + derived_children_alias: [], order: -1, schema: -1, alias: alias, diff --git a/rsconcept/frontend/src/models/rslangAPI.test.ts b/rsconcept/frontend/src/models/rslangAPI.test.ts index 32d61f1b..d1e7a483 100644 --- a/rsconcept/frontend/src/models/rslangAPI.test.ts +++ b/rsconcept/frontend/src/models/rslangAPI.test.ts @@ -19,6 +19,8 @@ const simpleExpressionData = [ ['pr1(S1)', 'true'], ['red(S1)', 'true'], ['red(Pr1(F1[α,σ]))', 'true'], + ['ℬℬ(X1)', 'false'], + ['ℬ(X1)', 'false'], ['D{(α,β)∈D6×D6 | α≠β & α∩β≠∅}', 'false'], ['I{(β,α) | α:∈D2; σ:=F5[α]; β:∈σ}', 'false'], ['∀σ∈S1 (F1[σ]×F1[σ])∩D11=∅', 'false'] diff --git a/rsconcept/frontend/src/models/rslangAPI.ts b/rsconcept/frontend/src/models/rslangAPI.ts index 2cadb795..854bd15f 100644 --- a/rsconcept/frontend/src/models/rslangAPI.ts +++ b/rsconcept/frontend/src/models/rslangAPI.ts @@ -24,7 +24,7 @@ export function extractGlobals(expression: string): Set { * Check if expression is simple derivation. */ export function isSimpleExpression(text: string): boolean { - return !COMPLEX_SYMBOLS_REGEXP.test(text); + return !text.match(COMPLEX_SYMBOLS_REGEXP); } /** diff --git a/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph/EditorTermGraph.tsx b/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph/EditorTermGraph.tsx index 74227e11..defe6c76 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph/EditorTermGraph.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph/EditorTermGraph.tsx @@ -92,7 +92,9 @@ function EditorTermGraph({ onOpenEdit }: EditorTermGraphProps) { result.push({ id: String(node.id), fill: colorBgGraphNode(cst, coloringScheme, colors), - label: cst.term_resolved && !filterParams.noText ? `${cst.alias}: ${cst.term_resolved}` : cst.alias + label: cst.alias, + subLabel: !filterParams.noText ? cst.term_resolved : undefined, + size: cst.derived_from_alias ? 1 : 2 }); } }); @@ -164,6 +166,16 @@ function EditorTermGraph({ onOpenEdit }: EditorTermGraphProps) { } } + const handleFoldDerived = useCallback(() => { + setFilterParams(prev => ({ + ...prev, + foldDerived: !prev.foldDerived + })); + setTimeout(() => { + setToggleResetView(prev => !prev); + }, TIMEOUT_GRAPH_REFRESH); + }, [setFilterParams, setToggleResetView]); + const graph = useMemo( () => ( setToggleResetView(prev => !prev)} toggleOrbit={() => setOrbit(prev => !prev)} - toggleFoldDerived={() => - setFilterParams(prev => ({ - ...prev, - foldDerived: !prev.foldDerived - })) - } + toggleFoldDerived={handleFoldDerived} toggleNoText={() => setFilterParams(prev => ({ ...prev, diff --git a/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph/GraphToolbar.tsx b/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph/GraphToolbar.tsx index 886e5829..35768021 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph/GraphToolbar.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph/GraphToolbar.tsx @@ -74,7 +74,7 @@ function GraphToolbar({ onClick={toggleNoText} /> diff --git a/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph/TermGraph.tsx b/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph/TermGraph.tsx index 769fa59f..3a1cfd77 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph/TermGraph.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph/TermGraph.tsx @@ -45,8 +45,8 @@ function TermGraph({ const { selections, setSelections } = useSelection({ ref: graphRef, - nodes, - edges, + nodes: nodes, + edges: edges, type: 'multi' }); @@ -110,6 +110,8 @@ function TermGraph({ onNodeClick={handleNodeClick} onNodePointerOver={handleHoverIn} onNodePointerOut={handleHoverOut} + minNodeSize={4} + maxNodeSize={8} cameraMode={orbit ? 'orbit' : is3D ? 'rotate' : 'pan'} layoutOverrides={ layout.includes('tree') ? { nodeLevelRatio: nodes.length < TREE_SIZE_MILESTONE ? 3 : 1 } : undefined diff --git a/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph/useGraphFilter.ts b/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph/useGraphFilter.ts index 1be288fe..38382b24 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph/useGraphFilter.ts +++ b/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph/useGraphFilter.ts @@ -48,7 +48,7 @@ function useGraphFilter(schema: IRSForm | undefined, params: GraphFilterParams) } if (params.foldDerived) { schema.items.forEach(cst => { - if (cst.derived_alias) { + if (cst.derived_from_alias) { graph.foldNode(cst.id); } }); diff --git a/rsconcept/frontend/src/pages/RSFormPage/ViewConstituents/ConstituentsTable.tsx b/rsconcept/frontend/src/pages/RSFormPage/ViewConstituents/ConstituentsTable.tsx index 50b021d2..18c5395a 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/ViewConstituents/ConstituentsTable.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/ViewConstituents/ConstituentsTable.tsx @@ -108,6 +108,18 @@ function ConstituentsTable({ items, activeID, onOpenEdit, maxHeight, denseThresh style: { backgroundColor: colors.bgSelected } + }, + { + when: (cst: IConstituenta) => cst.derived_from === activeID && cst.id !== activeID, + style: { + backgroundColor: colors.bgOrange50 + } + }, + { + when: (cst: IConstituenta) => activeID !== undefined && cst.derived_children.includes(activeID), + style: { + backgroundColor: colors.bgGreen50 + } } ], [activeID, colors] diff --git a/rsconcept/frontend/src/styling/color.ts b/rsconcept/frontend/src/styling/color.ts index 07ccb678..ee850cbd 100644 --- a/rsconcept/frontend/src/styling/color.ts +++ b/rsconcept/frontend/src/styling/color.ts @@ -35,6 +35,9 @@ export interface IColorTheme { bgTeal: string; bgOrange: string; + bgGreen50: string; + bgOrange50: string; + fgRed: string; fgGreen: string; fgBlue: string; @@ -72,6 +75,9 @@ export const lightT: IColorTheme = { bgTeal: 'hsl(192, 089%, 081%)', bgOrange: 'hsl(028, 100%, 075%)', + bgGreen50: 'hsl(100, 100%, 090%)', + bgOrange50: 'hsl(028, 100%, 095%)', + fgRed: 'hsl(000, 090%, 045%)', fgGreen: 'hsl(100, 090%, 035%)', fgBlue: 'hsl(235, 100%, 050%)', @@ -109,6 +115,9 @@ export const darkT: IColorTheme = { bgTeal: 'hsl(192, 080%, 030%)', bgOrange: 'hsl(035, 100%, 035%)', + bgGreen50: 'hsl(100, 080%, 017%)', + bgOrange50: 'hsl(035, 100%, 015%)', + fgRed: 'hsl(000, 080%, 045%)', fgGreen: 'hsl(100, 080%, 035%)', fgBlue: 'hsl(235, 100%, 080%)',