From cefd0d3c4077ccacf0c9806a3dea807bf643437e Mon Sep 17 00:00:00 2001 From: IRBorisov <8611739+IRBorisov@users.noreply.github.com> Date: Mon, 6 Nov 2023 02:20:16 +0300 Subject: [PATCH] Implement TemplateExpression editing --- .../src/components/Common/ConceptSearch.tsx | 30 ++++ .../src/components/Common/ConceptTab.tsx | 6 +- .../frontend/src/components/Common/Modal.tsx | 10 +- .../src/components/Common/SubmitButton.tsx | 17 +- .../src/components/Common/SwitchButton.tsx | 19 +-- .../src/components/DataTable/index.tsx | 8 +- .../frontend/src/components/RSInput/index.tsx | 13 +- .../src/components/RefsInput/index.tsx | 13 +- .../DlgConstituentaTemplate/ArgumentsTab.tsx | 35 ++++ .../ConstituentaTab.tsx | 5 +- .../TemplateTab.tsx | 35 ++-- .../dialogs/DlgConstituentaTemplate/index.tsx | 156 ++++++++++++++++++ .../frontend/src/dialogs/DlgCreateCst.tsx | 1 - .../src/dialogs/DlgEditReference/index.tsx | 53 +++--- .../frontend/src/dialogs/DlgEditWordForms.tsx | 2 +- .../src/dialogs/DlgTemplates/index.tsx | 121 -------------- .../frontend/src/hooks/useCheckExpression.ts | 4 +- rsconcept/frontend/src/models/rsform.ts | 4 +- rsconcept/frontend/src/models/rslang.ts | 9 +- .../pages/RSFormPage/EditorConstituenta.tsx | 4 +- .../pages/RSFormPage/EditorRSExpression.tsx | 2 +- .../frontend/src/pages/RSFormPage/RSTabs.tsx | 22 +-- rsconcept/frontend/src/utils/labels.ts | 4 +- rsconcept/frontend/src/utils/utils.tsx | 12 -- 24 files changed, 332 insertions(+), 253 deletions(-) create mode 100644 rsconcept/frontend/src/components/Common/ConceptSearch.tsx create mode 100644 rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/ArgumentsTab.tsx rename rsconcept/frontend/src/dialogs/{DlgTemplates => DlgConstituentaTemplate}/ConstituentaTab.tsx (96%) rename rsconcept/frontend/src/dialogs/{DlgTemplates => DlgConstituentaTemplate}/TemplateTab.tsx (88%) create mode 100644 rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/index.tsx delete mode 100644 rsconcept/frontend/src/dialogs/DlgTemplates/index.tsx diff --git a/rsconcept/frontend/src/components/Common/ConceptSearch.tsx b/rsconcept/frontend/src/components/Common/ConceptSearch.tsx new file mode 100644 index 00000000..f023da6f --- /dev/null +++ b/rsconcept/frontend/src/components/Common/ConceptSearch.tsx @@ -0,0 +1,30 @@ +import { MagnifyingGlassIcon } from '../Icons'; +import TextInput from './TextInput'; + +interface ConceptSearchProps { + value: string + onChange?: (newValue: string) => void + dense?: boolean +} + +function ConceptSearch({ value, onChange, dense }: ConceptSearchProps) { + const borderClass = dense ? 'border-t border-x': ''; + return ( +
+
+ +
+ onChange && onChange(event.target.value)} + /> +
); +} + +export default ConceptSearch; + + diff --git a/rsconcept/frontend/src/components/Common/ConceptTab.tsx b/rsconcept/frontend/src/components/Common/ConceptTab.tsx index 1251fb4f..bb0755bc 100644 --- a/rsconcept/frontend/src/components/Common/ConceptTab.tsx +++ b/rsconcept/frontend/src/components/Common/ConceptTab.tsx @@ -2,14 +2,16 @@ import type { TabProps } from 'react-tabs'; import { Tab } from 'react-tabs'; interface ConceptTabProps -extends Omit { +extends Omit { className?: string + tooltip?: string } -function ConceptTab({ children, className, ...otherProps }: ConceptTabProps) { +function ConceptTab({ children, tooltip, className, ...otherProps }: ConceptTabProps) { return ( {children} diff --git a/rsconcept/frontend/src/components/Common/Modal.tsx b/rsconcept/frontend/src/components/Common/Modal.tsx index d6fdbce7..64e24f5f 100644 --- a/rsconcept/frontend/src/components/Common/Modal.tsx +++ b/rsconcept/frontend/src/components/Common/Modal.tsx @@ -40,18 +40,18 @@ function Modal({
- { title &&

{title}

} + { title &&

{title}

}
{children}
-
+
{!readonly &&
diff --git a/rsconcept/frontend/src/components/Common/SubmitButton.tsx b/rsconcept/frontend/src/components/Common/SubmitButton.tsx index 12b143ca..52bd23d8 100644 --- a/rsconcept/frontend/src/components/Common/SubmitButton.tsx +++ b/rsconcept/frontend/src/components/Common/SubmitButton.tsx @@ -12,15 +12,14 @@ function SubmitButton({ dimensions = 'w-fit h-fit' }: SubmitButtonProps) { return ( - - ) + ); } export default SubmitButton; diff --git a/rsconcept/frontend/src/components/Common/SwitchButton.tsx b/rsconcept/frontend/src/components/Common/SwitchButton.tsx index 801d3d07..1489c189 100644 --- a/rsconcept/frontend/src/components/Common/SwitchButton.tsx +++ b/rsconcept/frontend/src/components/Common/SwitchButton.tsx @@ -16,16 +16,15 @@ function SwitchButton({ isSelected, onSelect, ...props }: SwitchButtonProps) { return ( - - ); + ); } export default SwitchButton; diff --git a/rsconcept/frontend/src/components/DataTable/index.tsx b/rsconcept/frontend/src/components/DataTable/index.tsx index 1de9ef18..33a5dc69 100644 --- a/rsconcept/frontend/src/components/DataTable/index.tsx +++ b/rsconcept/frontend/src/components/DataTable/index.tsx @@ -27,7 +27,8 @@ extends Pick, > { dense?: boolean headPosition?: string - noFooter?: boolean // Disables footer rendering + noHeader?: boolean + noFooter?: boolean conditionalRowStyles?: IConditionalStyle[] onRowClicked?: (rowData: TData, event: React.MouseEvent) => void onRowDoubleClicked?: (rowData: TData, event: React.MouseEvent) => void @@ -55,7 +56,7 @@ extends Pick, * No sticky header if omitted */ export default function DataTable({ - dense, headPosition, conditionalRowStyles, noFooter, + dense, headPosition, conditionalRowStyles, noFooter, noHeader, onRowClicked, onRowDoubleClicked, noDataComponent, enableRowSelection, @@ -112,6 +113,7 @@ export default function DataTable({
+ { !noHeader && ({ ))} ))} - + } {tableImpl.getRowModel().rows.map( diff --git a/rsconcept/frontend/src/components/RSInput/index.tsx b/rsconcept/frontend/src/components/RSInput/index.tsx index 7ad1d681..c6de3578 100644 --- a/rsconcept/frontend/src/components/RSInput/index.tsx +++ b/rsconcept/frontend/src/components/RSInput/index.tsx @@ -45,15 +45,16 @@ const editorSetup: BasicSetupOptions = { interface RSInputProps extends Pick { label?: string + disabled?: boolean innerref?: RefObject | undefined onChange?: (newValue: string) => void } function RSInput({ - id, label, innerref, onChange, editable, + id, label, innerref, onChange, disabled, ...props }: RSInputProps) { const { darkMode, colors } = useConceptTheme(); @@ -65,13 +66,13 @@ function RSInput({ return innerref ?? internalRef; }, [internalRef, innerref]); - const cursor = useMemo(() => editable ? 'cursor-text': 'cursor-default', [editable]); + const cursor = useMemo(() => !disabled ? 'cursor-text': 'cursor-default', [disabled]); const customTheme: Extension = useMemo( () => createTheme({ theme: darkMode ? 'dark' : 'light', settings: { fontFamily: 'inherit', - background: editable ? colors.bgInput : colors.bgDefault, + background: !disabled ? colors.bgInput : colors.bgDefault, foreground: colors.fgDefault, selection: colors.bgHover }, @@ -84,7 +85,7 @@ function RSInput({ { tag: tags.controlKeyword, fontWeight: '500'}, // R | I | D { tag: tags.unit, fontSize: '0.75rem' }, // indicies ] - }), [editable, colors, darkMode]); + }), [disabled, colors, darkMode]); const editorExtensions = useMemo( () => [ @@ -139,7 +140,7 @@ function RSInput({ extensions={editorExtensions} indentWithTab={false} onChange={onChange} - editable={editable} + editable={!disabled} onKeyDown={handleInput} {...props} /> diff --git a/rsconcept/frontend/src/components/RefsInput/index.tsx b/rsconcept/frontend/src/components/RefsInput/index.tsx index 711d0399..59ad6def 100644 --- a/rsconcept/frontend/src/components/RefsInput/index.tsx +++ b/rsconcept/frontend/src/components/RefsInput/index.tsx @@ -50,12 +50,13 @@ const editorSetup: BasicSetupOptions = { interface RefsInputInputProps extends Pick { label?: string innerref?: RefObject | undefined onChange?: (newValue: string) => void items?: IConstituenta[] + disabled?: boolean initialValue?: string value?: string @@ -63,7 +64,7 @@ extends Pick editable ? 'cursor-text': 'cursor-default', [editable]); + const cursor = useMemo(() => !disabled ? 'cursor-text': 'cursor-default', [disabled]); const customTheme: Extension = useMemo( () => createTheme({ theme: darkMode ? 'dark' : 'light', settings: { fontFamily: 'inherit', - background: editable ? colors.bgInput : colors.bgDefault, + background: !disabled ? colors.bgInput : colors.bgDefault, foreground: colors.fgDefault, selection: colors.bgHover }, @@ -104,7 +105,7 @@ function RefsInput({ { tag: tags.literal, color: colors.fgTeal, cursor: 'default' }, // SyntacticReference { tag: tags.comment, color: colors.fgRed }, // Error ] - }), [editable, colors, darkMode]); + }), [disabled, colors, darkMode]); const editorExtensions = useMemo( () => [ @@ -216,7 +217,7 @@ function RefsInput({ indentWithTab={false} onChange={handleChange} - editable={editable} + editable={!disabled} onKeyDown={handleInput} onFocus={handleFocusIn} onBlur={handleFocusOut} diff --git a/rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/ArgumentsTab.tsx b/rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/ArgumentsTab.tsx new file mode 100644 index 00000000..a4bd9a8e --- /dev/null +++ b/rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/ArgumentsTab.tsx @@ -0,0 +1,35 @@ +import { Dispatch } from 'react'; + +import ConceptSearch from '../../components/Common/ConceptSearch'; +import RSInput from '../../components/RSInput'; +import { IArgumentValue } from '../../models/rslang'; + +interface ArgumentsTabProps { + state: IArgumentsState + partialUpdate: Dispatch> +} + +export interface IArgumentsState { + arguments?: IArgumentValue[] + filterText: string + definition: string +} + +function ArgumentsTab({state, partialUpdate}: ArgumentsTabProps) { + return ( +
+ partialUpdate({ filterText: newValue} )} + dense + /> + +
); +} + +export default ArgumentsTab; diff --git a/rsconcept/frontend/src/dialogs/DlgTemplates/ConstituentaTab.tsx b/rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/ConstituentaTab.tsx similarity index 96% rename from rsconcept/frontend/src/dialogs/DlgTemplates/ConstituentaTab.tsx rename to rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/ConstituentaTab.tsx index 8fd6748c..abf1ee07 100644 --- a/rsconcept/frontend/src/dialogs/DlgTemplates/ConstituentaTab.tsx +++ b/rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/ConstituentaTab.tsx @@ -15,10 +15,10 @@ interface ConstituentaTabProps { function ConstituentaTab({state, partialUpdate}: ConstituentaTabProps) { return ( -
+
partialUpdate({definition_formal: value})} diff --git a/rsconcept/frontend/src/dialogs/DlgTemplates/TemplateTab.tsx b/rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/TemplateTab.tsx similarity index 88% rename from rsconcept/frontend/src/dialogs/DlgTemplates/TemplateTab.tsx rename to rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/TemplateTab.tsx index 5c00f504..a6adb22a 100644 --- a/rsconcept/frontend/src/dialogs/DlgTemplates/TemplateTab.tsx +++ b/rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/TemplateTab.tsx @@ -1,11 +1,10 @@ import { Dispatch, useEffect, useMemo, useState } from 'react'; +import ConceptSearch from '../../components/Common/ConceptSearch'; import SelectSingle from '../../components/Common/SelectSingle'; import TextArea from '../../components/Common/TextArea'; -import TextInput from '../../components/Common/TextInput'; import DataTable, { createColumnHelper,IConditionalStyle } from '../../components/DataTable'; import ConstituentaTooltip from '../../components/Help/ConstituentaTooltip'; -import { MagnifyingGlassIcon } from '../../components/Icons'; import RSInput from '../../components/RSInput'; import { useLibrary } from '../../context/LibraryContext'; import { useConceptTheme } from '../../context/ThemeContext'; @@ -106,7 +105,6 @@ function TemplateTab({ state, partialUpdate }: TemplateTabProps) { () => [ constituentaHelper.accessor('alias', { id: 'alias', - header: 'Имя', size: 65, minSize: 65, cell: props => { @@ -130,7 +128,6 @@ function TemplateTab({ state, partialUpdate }: TemplateTabProps) { }), constituentaHelper.accessor('term_resolved', { id: 'term', - header: 'Термин', size: 600, minSize: 350, maxSize: 600 @@ -148,8 +145,8 @@ function TemplateTab({ state, partialUpdate }: TemplateTabProps) { ], [state.prototype, colors]); return ( -
-
+
+
-
-
- -
- partialUpdate({ filterText: event.target.value} )} - /> -
- -
+ partialUpdate({ filterText: newValue} )} + dense + /> +
@@ -204,7 +193,7 @@ function TemplateTab({ state, partialUpdate }: TemplateTabProps) {