diff --git a/rsconcept/frontend/src/App.tsx b/rsconcept/frontend/src/App.tsx index f30332b9..69dc1016 100644 --- a/rsconcept/frontend/src/App.tsx +++ b/rsconcept/frontend/src/App.tsx @@ -2,7 +2,7 @@ import { createBrowserRouter, Outlet, RouterProvider } from 'react-router-dom'; import ConceptToaster from './components/ConceptToaster'; import Footer from './components/Footer'; -import Navigation from './components/Navigation/Navigation'; +import Navigation from './components/Navigation'; import { NavigationState } from './context/NagivationContext'; import { useConceptTheme } from './context/ThemeContext'; import CreateRSFormPage from './pages/CreateRSFormPage'; diff --git a/rsconcept/frontend/src/components/BackendError.tsx b/rsconcept/frontend/src/components/BackendError.tsx index 95c66e2a..cbcb2af7 100644 --- a/rsconcept/frontend/src/components/BackendError.tsx +++ b/rsconcept/frontend/src/components/BackendError.tsx @@ -1,6 +1,6 @@ import axios, { type AxiosError,AxiosHeaderValue } from 'axios'; -import PrettyJson from './Common/PrettyJSON'; +import PrettyJson from './common/PrettyJSON'; export type ErrorInfo = string | Error | AxiosError | undefined; diff --git a/rsconcept/frontend/src/components/DataTable/DataTable.tsx b/rsconcept/frontend/src/components/DataTable/DataTable.tsx new file mode 100644 index 00000000..33a5dc69 --- /dev/null +++ b/rsconcept/frontend/src/components/DataTable/DataTable.tsx @@ -0,0 +1,216 @@ +import { + Cell, ColumnSort, + createColumnHelper, flexRender, getCoreRowModel, + getPaginationRowModel, getSortedRowModel, Header, HeaderGroup, + PaginationState, Row, RowData, type RowSelectionState, + SortingState, TableOptions, useReactTable, type VisibilityState +} from '@tanstack/react-table'; +import { useState } from 'react'; + +import DefaultNoData from './DefaultNoData'; +import PaginationTools from './PaginationTools'; +import SelectAll from './SelectAll'; +import SelectRow from './SelectRow'; +import SortingIcon from './SortingIcon'; + +export { createColumnHelper, type ColumnSort, type RowSelectionState, type VisibilityState }; + +export interface IConditionalStyle { + when: (rowData: TData) => boolean + style: React.CSSProperties +} + +export interface DataTableProps +extends Pick, + 'data' | 'columns' | + 'onRowSelectionChange' | 'onColumnVisibilityChange' +> { + dense?: boolean + headPosition?: string + noHeader?: boolean + noFooter?: boolean + conditionalRowStyles?: IConditionalStyle[] + onRowClicked?: (rowData: TData, event: React.MouseEvent) => void + onRowDoubleClicked?: (rowData: TData, event: React.MouseEvent) => void + noDataComponent?: React.ReactNode + + enableRowSelection?: boolean + rowSelection?: RowSelectionState + + enableHiding?: boolean + columnVisibility?: VisibilityState + + enablePagination?: boolean + paginationPerPage?: number + paginationOptions?: number[] + onChangePaginationOption?: (newValue: number) => void + + enableSorting?: boolean + initialSorting?: ColumnSort +} + +/** + * UI element: data representation as a table. + * + * @param headPosition - Top position of sticky header (0 if no other sticky elements are present). + * No sticky header if omitted +*/ +export default function DataTable({ + dense, headPosition, conditionalRowStyles, noFooter, noHeader, + onRowClicked, onRowDoubleClicked, noDataComponent, + + enableRowSelection, + rowSelection, + + enableHiding, + columnVisibility, + + enableSorting, + initialSorting, + + enablePagination, + paginationPerPage=10, + paginationOptions=[10, 20, 30, 40, 50], + onChangePaginationOption, + + ...options +}: DataTableProps) { + const [sorting, setSorting] = useState(initialSorting ? [initialSorting] : []); + + const [pagination, setPagination] = useState({ + pageIndex: 0, + pageSize: paginationPerPage, + }); + + const tableImpl = useReactTable({ + getCoreRowModel: getCoreRowModel(), + getSortedRowModel: enableSorting ? getSortedRowModel() : undefined, + getPaginationRowModel: enablePagination ? getPaginationRowModel() : undefined, + + state: { + pagination: pagination, + sorting: sorting, + rowSelection: rowSelection ?? {}, + columnVisibility: columnVisibility ?? {} + }, + enableHiding: enableHiding, + onPaginationChange: enablePagination ? setPagination : undefined, + onSortingChange: enableSorting ? setSorting : undefined, + enableMultiRowSelection: enableRowSelection, + ...options + }); + + const isEmpty = tableImpl.getRowModel().rows.length === 0; + + function getRowStyles(row: Row) { + return {...conditionalRowStyles! + .filter(item => item.when(row.original)) + .reduce((prev, item) => ({...prev, ...item.style}), {}) + }; + } + + return ( +
+
+ + { !noHeader && + + {tableImpl.getHeaderGroups().map( + (headerGroup: HeaderGroup) => ( + + {enableRowSelection && + } + {headerGroup.headers.map( + (header: Header) => ( + + ))} + + ))} + } + + + {tableImpl.getRowModel().rows.map( + (row: Row, index) => ( + + {enableRowSelection && + } + {row.getVisibleCells().map( + (cell: Cell) => ( + + ))} + + ))} + + + {!noFooter && + + {tableImpl.getFooterGroups().map( + (footerGroup: HeaderGroup) => ( + + {footerGroup.headers.map( + (header: Header) => ( + + ))} + + ))} + } +
+ + 100 ? 'left': 'center', + width: header.getSize(), + cursor: enableSorting && header.column.getCanSort() ? 'pointer': 'auto', + }} + onClick={enableSorting ? header.column.getToggleSortingHandler() : undefined} + > + {header.isPlaceholder ? null : ( +
+ {flexRender(header.column.columnDef.header, header.getContext())} + {enableSorting && header.column.getCanSort() && } +
)} +
+ + onRowClicked && onRowClicked(row.original, event)} + onDoubleClick={event => onRowDoubleClicked && onRowDoubleClicked(row.original, event)} + > + {flexRender(cell.column.columnDef.cell, cell.getContext())} +
+ {header.isPlaceholder ? null + : flexRender(header.column.columnDef.footer, header.getContext()) + } +
+ + {enablePagination && !isEmpty && + } +
+ {isEmpty && (noDataComponent ?? )} +
); +} diff --git a/rsconcept/frontend/src/components/DataTable/SelectAll.tsx b/rsconcept/frontend/src/components/DataTable/SelectAll.tsx index 78f0587b..db1b7260 100644 --- a/rsconcept/frontend/src/components/DataTable/SelectAll.tsx +++ b/rsconcept/frontend/src/components/DataTable/SelectAll.tsx @@ -1,6 +1,6 @@ import { Table } from '@tanstack/react-table'; -import Tristate from '../Common/Tristate'; +import Tristate from '../common/Tristate'; interface SelectAllProps { table: Table diff --git a/rsconcept/frontend/src/components/DataTable/SelectRow.tsx b/rsconcept/frontend/src/components/DataTable/SelectRow.tsx index 1e8e8345..2fd5658e 100644 --- a/rsconcept/frontend/src/components/DataTable/SelectRow.tsx +++ b/rsconcept/frontend/src/components/DataTable/SelectRow.tsx @@ -1,6 +1,6 @@ import { Row } from '@tanstack/react-table'; -import Checkbox from '../Common/Checkbox'; +import Checkbox from '../common/Checkbox'; interface SelectRowProps { row: Row diff --git a/rsconcept/frontend/src/components/DataTable/index.tsx b/rsconcept/frontend/src/components/DataTable/index.tsx index 33a5dc69..71f18549 100644 --- a/rsconcept/frontend/src/components/DataTable/index.tsx +++ b/rsconcept/frontend/src/components/DataTable/index.tsx @@ -1,216 +1,5 @@ -import { - Cell, ColumnSort, - createColumnHelper, flexRender, getCoreRowModel, - getPaginationRowModel, getSortedRowModel, Header, HeaderGroup, - PaginationState, Row, RowData, type RowSelectionState, - SortingState, TableOptions, useReactTable, type VisibilityState -} from '@tanstack/react-table'; -import { useState } from 'react'; - -import DefaultNoData from './DefaultNoData'; -import PaginationTools from './PaginationTools'; -import SelectAll from './SelectAll'; -import SelectRow from './SelectRow'; -import SortingIcon from './SortingIcon'; - -export { createColumnHelper, type ColumnSort, type RowSelectionState, type VisibilityState }; - -export interface IConditionalStyle { - when: (rowData: TData) => boolean - style: React.CSSProperties -} - -export interface DataTableProps -extends Pick, - 'data' | 'columns' | - 'onRowSelectionChange' | 'onColumnVisibilityChange' -> { - dense?: boolean - headPosition?: string - noHeader?: boolean - noFooter?: boolean - conditionalRowStyles?: IConditionalStyle[] - onRowClicked?: (rowData: TData, event: React.MouseEvent) => void - onRowDoubleClicked?: (rowData: TData, event: React.MouseEvent) => void - noDataComponent?: React.ReactNode - - enableRowSelection?: boolean - rowSelection?: RowSelectionState - - enableHiding?: boolean - columnVisibility?: VisibilityState - - enablePagination?: boolean - paginationPerPage?: number - paginationOptions?: number[] - onChangePaginationOption?: (newValue: number) => void - - enableSorting?: boolean - initialSorting?: ColumnSort -} - -/** - * UI element: data representation as a table. - * - * @param headPosition - Top position of sticky header (0 if no other sticky elements are present). - * No sticky header if omitted -*/ -export default function DataTable({ - dense, headPosition, conditionalRowStyles, noFooter, noHeader, - onRowClicked, onRowDoubleClicked, noDataComponent, - - enableRowSelection, - rowSelection, - - enableHiding, - columnVisibility, - - enableSorting, - initialSorting, - - enablePagination, - paginationPerPage=10, - paginationOptions=[10, 20, 30, 40, 50], - onChangePaginationOption, - - ...options -}: DataTableProps) { - const [sorting, setSorting] = useState(initialSorting ? [initialSorting] : []); - - const [pagination, setPagination] = useState({ - pageIndex: 0, - pageSize: paginationPerPage, - }); - - const tableImpl = useReactTable({ - getCoreRowModel: getCoreRowModel(), - getSortedRowModel: enableSorting ? getSortedRowModel() : undefined, - getPaginationRowModel: enablePagination ? getPaginationRowModel() : undefined, - - state: { - pagination: pagination, - sorting: sorting, - rowSelection: rowSelection ?? {}, - columnVisibility: columnVisibility ?? {} - }, - enableHiding: enableHiding, - onPaginationChange: enablePagination ? setPagination : undefined, - onSortingChange: enableSorting ? setSorting : undefined, - enableMultiRowSelection: enableRowSelection, - ...options - }); - - const isEmpty = tableImpl.getRowModel().rows.length === 0; - - function getRowStyles(row: Row) { - return {...conditionalRowStyles! - .filter(item => item.when(row.original)) - .reduce((prev, item) => ({...prev, ...item.style}), {}) - }; - } - - return ( -
-
- - { !noHeader && - - {tableImpl.getHeaderGroups().map( - (headerGroup: HeaderGroup) => ( - - {enableRowSelection && - } - {headerGroup.headers.map( - (header: Header) => ( - - ))} - - ))} - } - - - {tableImpl.getRowModel().rows.map( - (row: Row, index) => ( - - {enableRowSelection && - } - {row.getVisibleCells().map( - (cell: Cell) => ( - - ))} - - ))} - - - {!noFooter && - - {tableImpl.getFooterGroups().map( - (footerGroup: HeaderGroup) => ( - - {footerGroup.headers.map( - (header: Header) => ( - - ))} - - ))} - } -
- - 100 ? 'left': 'center', - width: header.getSize(), - cursor: enableSorting && header.column.getCanSort() ? 'pointer': 'auto', - }} - onClick={enableSorting ? header.column.getToggleSortingHandler() : undefined} - > - {header.isPlaceholder ? null : ( -
- {flexRender(header.column.columnDef.header, header.getContext())} - {enableSorting && header.column.getCanSort() && } -
)} -
- - onRowClicked && onRowClicked(row.original, event)} - onDoubleClick={event => onRowDoubleClicked && onRowDoubleClicked(row.original, event)} - > - {flexRender(cell.column.columnDef.cell, cell.getContext())} -
- {header.isPlaceholder ? null - : flexRender(header.column.columnDef.footer, header.getContext()) - } -
- - {enablePagination && !isEmpty && - } -
- {isEmpty && (noDataComponent ?? )} -
); -} +export { + default, + createColumnHelper, type IConditionalStyle, + type RowSelectionState, type VisibilityState +} from './DataTable'; \ No newline at end of file diff --git a/rsconcept/frontend/src/components/ErrorFallback.tsx b/rsconcept/frontend/src/components/ErrorFallback.tsx index 9dc874cc..c3ddbc82 100644 --- a/rsconcept/frontend/src/components/ErrorFallback.tsx +++ b/rsconcept/frontend/src/components/ErrorFallback.tsx @@ -1,6 +1,6 @@ import { type FallbackProps } from 'react-error-boundary'; -import Button from './Common/Button'; +import Button from './common/Button'; function ErrorFallback({ error, resetErrorBoundary }: FallbackProps) { reportError(error); diff --git a/rsconcept/frontend/src/components/Help/ConstituentaTooltip.tsx b/rsconcept/frontend/src/components/Help/ConstituentaTooltip.tsx index f9d529ae..40cb6870 100644 --- a/rsconcept/frontend/src/components/Help/ConstituentaTooltip.tsx +++ b/rsconcept/frontend/src/components/Help/ConstituentaTooltip.tsx @@ -1,5 +1,5 @@ import { IConstituenta } from '../../models/rsform'; -import ConceptTooltip from '../Common/ConceptTooltip'; +import ConceptTooltip from '../common/ConceptTooltip'; import InfoConstituenta from './InfoConstituenta'; interface ConstituentaTooltipProps { diff --git a/rsconcept/frontend/src/components/Help/HelpAPI.tsx b/rsconcept/frontend/src/components/Help/HelpAPI.tsx index 3ba0ac84..75796c62 100644 --- a/rsconcept/frontend/src/components/Help/HelpAPI.tsx +++ b/rsconcept/frontend/src/components/Help/HelpAPI.tsx @@ -1,5 +1,5 @@ import { urls } from '../../utils/constants'; -import TextURL from '../Common/TextURL'; +import TextURL from '../common/TextURL'; function HelpAPI() { return ( diff --git a/rsconcept/frontend/src/components/Help/HelpConstituenta.tsx b/rsconcept/frontend/src/components/Help/HelpConstituenta.tsx index 8151c50d..ffcad1aa 100644 --- a/rsconcept/frontend/src/components/Help/HelpConstituenta.tsx +++ b/rsconcept/frontend/src/components/Help/HelpConstituenta.tsx @@ -1,4 +1,4 @@ -import Divider from '../Common/Divider'; +import Divider from '../common/Divider'; import InfoCstStatus from './InfoCstStatus'; function HelpConstituenta() { diff --git a/rsconcept/frontend/src/components/Help/HelpExteor.tsx b/rsconcept/frontend/src/components/Help/HelpExteor.tsx index 39fa20b6..ef444cc9 100644 --- a/rsconcept/frontend/src/components/Help/HelpExteor.tsx +++ b/rsconcept/frontend/src/components/Help/HelpExteor.tsx @@ -1,5 +1,5 @@ import { urls } from '../../utils/constants'; -import TextURL from '../Common/TextURL'; +import TextURL from '../common/TextURL'; function HelpExteor() { return ( diff --git a/rsconcept/frontend/src/components/Help/HelpMain.tsx b/rsconcept/frontend/src/components/Help/HelpMain.tsx index b39ddfab..27ba0c5f 100644 --- a/rsconcept/frontend/src/components/Help/HelpMain.tsx +++ b/rsconcept/frontend/src/components/Help/HelpMain.tsx @@ -1,5 +1,5 @@ import { urls } from '../../utils/constants'; -import TextURL from '../Common/TextURL'; +import TextURL from '../common/TextURL'; function HelpMain() { return ( diff --git a/rsconcept/frontend/src/components/Help/HelpRSFormItems.tsx b/rsconcept/frontend/src/components/Help/HelpRSFormItems.tsx index 465e7f3a..538ee4b2 100644 --- a/rsconcept/frontend/src/components/Help/HelpRSFormItems.tsx +++ b/rsconcept/frontend/src/components/Help/HelpRSFormItems.tsx @@ -1,4 +1,4 @@ -import Divider from '../Common/Divider'; +import Divider from '../common/Divider'; import InfoCstStatus from './InfoCstStatus'; function HelpRSFormItems() { diff --git a/rsconcept/frontend/src/components/Help/HelpRSLang.tsx b/rsconcept/frontend/src/components/Help/HelpRSLang.tsx index ae556f07..09c1ff7e 100644 --- a/rsconcept/frontend/src/components/Help/HelpRSLang.tsx +++ b/rsconcept/frontend/src/components/Help/HelpRSLang.tsx @@ -2,7 +2,7 @@ import { useMemo } from 'react'; import useWindowSize from '../../hooks/useWindowSize'; import { urls, youtube } from '../../utils/constants'; -import EmbedYoutube from '../Common/EmbedYoutube'; +import EmbedYoutube from '../common/EmbedYoutube'; const OPT_VIDEO_H = 1080; diff --git a/rsconcept/frontend/src/components/Help/HelpTermGraph.tsx b/rsconcept/frontend/src/components/Help/HelpTermGraph.tsx index ed3cc990..06327e28 100644 --- a/rsconcept/frontend/src/components/Help/HelpTermGraph.tsx +++ b/rsconcept/frontend/src/components/Help/HelpTermGraph.tsx @@ -1,4 +1,4 @@ -import Divider from '../Common/Divider'; +import Divider from '../common/Divider'; import InfoCstClass from './InfoCstClass'; import InfoCstStatus from './InfoCstStatus'; diff --git a/rsconcept/frontend/src/components/Navigation/UserDropdown.tsx b/rsconcept/frontend/src/components/Navigation/UserDropdown.tsx index f26946b0..a11f35d6 100644 --- a/rsconcept/frontend/src/components/Navigation/UserDropdown.tsx +++ b/rsconcept/frontend/src/components/Navigation/UserDropdown.tsx @@ -1,8 +1,8 @@ import { useAuth } from '../../context/AuthContext'; import { useConceptNavigation } from '../../context/NagivationContext'; import { useConceptTheme } from '../../context/ThemeContext'; -import Dropdown from '../Common/Dropdown'; -import DropdownButton from '../Common/DropdownButton'; +import Dropdown from '../common/Dropdown'; +import DropdownButton from '../common/DropdownButton'; interface UserDropdownProps { hideDropdown: () => void diff --git a/rsconcept/frontend/src/components/Navigation/index.tsx b/rsconcept/frontend/src/components/Navigation/index.tsx new file mode 100644 index 00000000..f110fa0f --- /dev/null +++ b/rsconcept/frontend/src/components/Navigation/index.tsx @@ -0,0 +1 @@ +export { default } from './Navigation'; \ No newline at end of file diff --git a/rsconcept/frontend/src/components/RSInput/RSInput.tsx b/rsconcept/frontend/src/components/RSInput/RSInput.tsx new file mode 100644 index 00000000..e14eef36 --- /dev/null +++ b/rsconcept/frontend/src/components/RSInput/RSInput.tsx @@ -0,0 +1,176 @@ + +import { Extension } from '@codemirror/state'; +import { tags } from '@lezer/highlight'; +import { createTheme } from '@uiw/codemirror-themes'; +import CodeMirror, { BasicSetupOptions, ReactCodeMirrorProps, ReactCodeMirrorRef } from '@uiw/react-codemirror'; +import { EditorView } from 'codemirror'; +import { RefObject, useCallback, useMemo, useRef } from 'react'; + +import { useRSForm } from '../../context/RSFormContext'; +import { useConceptTheme } from '../../context/ThemeContext'; +import { TokenID } from '../../models/rslang'; +import Label from '../common/Label'; +import { ccBracketMatching } from './bracketMatching'; +import { RSLanguage } from './rslang'; +import { getSymbolSubstitute,RSTextWrapper } from './textEditing'; +import { rsHoverTooltip } from './tooltip'; + +const editorSetup: BasicSetupOptions = { + highlightSpecialChars: false, + history: true, + drawSelection: false, + syntaxHighlighting: false, + defaultKeymap: true, + historyKeymap: true, + + lineNumbers: false, + highlightActiveLineGutter: false, + foldGutter: false, + dropCursor: true, + allowMultipleSelections: false, + indentOnInput: false, + bracketMatching: false, + closeBrackets: false, + autocompletion: false, + rectangularSelection: false, + crosshairCursor: false, + highlightActiveLine: false, + highlightSelectionMatches: false, + closeBracketsKeymap: false, + searchKeymap: false, + foldKeymap: false, + completionKeymap: false, + lintKeymap: false +}; + +interface RSInputProps +extends Pick { + label?: string + dimensions?: string + disabled?: boolean + noTooltip?: boolean + innerref?: RefObject | undefined + onChange?: (newValue: string) => void +} + +function RSInput({ + id, label, innerref, onChange, + disabled, noTooltip, + dimensions = 'w-full', + ...props +}: RSInputProps) { + const { darkMode, colors } = useConceptTheme(); + const { schema } = useRSForm(); + + const internalRef = useRef(null); + const thisRef = useMemo( + () => { + return innerref ?? internalRef; + }, [internalRef, innerref]); + + const cursor = useMemo(() => !disabled ? 'cursor-text': 'cursor-default', [disabled]); + const customTheme: Extension = useMemo( + () => createTheme({ + theme: darkMode ? 'dark' : 'light', + settings: { + fontFamily: 'inherit', + background: !disabled ? colors.bgInput : colors.bgDefault, + foreground: colors.fgDefault, + selection: colors.bgHover + }, + styles: [ + { tag: tags.name, color: colors.fgPurple, cursor: 'default' }, // GlobalID + { tag: tags.variableName, color: colors.fgGreen }, // LocalID + { tag: tags.propertyName, color: colors.fgTeal }, // Radical + { tag: tags.keyword, color: colors.fgBlue }, // keywords + { tag: tags.literal, color: colors.fgBlue }, // literals + { tag: tags.controlKeyword, fontWeight: '500'}, // R | I | D + { tag: tags.unit, fontSize: '0.75rem' }, // indicies + ] + }), [disabled, colors, darkMode]); + + const editorExtensions = useMemo( + () => [ + EditorView.lineWrapping, + RSLanguage, + ccBracketMatching(darkMode), + ... noTooltip ? [] : [rsHoverTooltip(schema?.items || [])], + ], [darkMode, schema?.items, noTooltip]); + + const handleInput = useCallback( + (event: React.KeyboardEvent) => { + if (!thisRef.current) { + return; + } + const text = new RSTextWrapper(thisRef.current as Required); + if (event.shiftKey && !event.altKey) { + if (event.key === '*') { + text.insertToken(TokenID.DECART); + event.preventDefault(); + } else if (event.code === 'KeyB') { + text.insertChar('ℬ'); + event.preventDefault(); + } else if (event.code === 'KeyZ') { + text.insertChar('Z'); + event.preventDefault(); + } else if (event.code === 'KeyR') { + text.insertChar('R'); + event.preventDefault(); + } else if (event.code === 'KeyF') { + text.insertChar('F'); + event.preventDefault(); + } else if (event.code === 'KeyP') { + text.insertChar('P'); + event.preventDefault(); + } else if (event.code === 'KeyX') { + text.insertChar('X'); + event.preventDefault(); + } else if (event.code === 'KeyS') { + text.insertChar('S'); + event.preventDefault(); + } else if (event.code === 'KeyD') { + text.insertChar('D'); + event.preventDefault(); + } else if (event.code === 'KeyC') { + text.insertChar('C'); + event.preventDefault(); + } + } else if (event.altKey) { + if (text.processAltKey(event.code, event.shiftKey)) { + event.preventDefault(); + } + } else if (!event.ctrlKey) { + const newSymbol = getSymbolSubstitute(event.code, event.shiftKey); + if (newSymbol) { + text.replaceWith(newSymbol); + event.preventDefault(); + } + } + }, [thisRef]); + + return ( +
+ {label && +
+ ); +} + +export default RSInput; diff --git a/rsconcept/frontend/src/components/RSInput/index.tsx b/rsconcept/frontend/src/components/RSInput/index.tsx index bab76389..0071f869 100644 --- a/rsconcept/frontend/src/components/RSInput/index.tsx +++ b/rsconcept/frontend/src/components/RSInput/index.tsx @@ -1,176 +1 @@ - -import { Extension } from '@codemirror/state'; -import { tags } from '@lezer/highlight'; -import { createTheme } from '@uiw/codemirror-themes'; -import CodeMirror, { BasicSetupOptions, ReactCodeMirrorProps, ReactCodeMirrorRef } from '@uiw/react-codemirror'; -import { EditorView } from 'codemirror'; -import { RefObject, useCallback, useMemo, useRef } from 'react'; - -import { useRSForm } from '../../context/RSFormContext'; -import { useConceptTheme } from '../../context/ThemeContext'; -import { TokenID } from '../../models/rslang'; -import Label from '../Common/Label'; -import { ccBracketMatching } from './bracketMatching'; -import { RSLanguage } from './rslang'; -import { getSymbolSubstitute,RSTextWrapper } from './textEditing'; -import { rsHoverTooltip } from './tooltip'; - -const editorSetup: BasicSetupOptions = { - highlightSpecialChars: false, - history: true, - drawSelection: false, - syntaxHighlighting: false, - defaultKeymap: true, - historyKeymap: true, - - lineNumbers: false, - highlightActiveLineGutter: false, - foldGutter: false, - dropCursor: true, - allowMultipleSelections: false, - indentOnInput: false, - bracketMatching: false, - closeBrackets: false, - autocompletion: false, - rectangularSelection: false, - crosshairCursor: false, - highlightActiveLine: false, - highlightSelectionMatches: false, - closeBracketsKeymap: false, - searchKeymap: false, - foldKeymap: false, - completionKeymap: false, - lintKeymap: false -}; - -interface RSInputProps -extends Pick { - label?: string - dimensions?: string - disabled?: boolean - noTooltip?: boolean - innerref?: RefObject | undefined - onChange?: (newValue: string) => void -} - -function RSInput({ - id, label, innerref, onChange, - disabled, noTooltip, - dimensions = 'w-full', - ...props -}: RSInputProps) { - const { darkMode, colors } = useConceptTheme(); - const { schema } = useRSForm(); - - const internalRef = useRef(null); - const thisRef = useMemo( - () => { - return innerref ?? internalRef; - }, [internalRef, innerref]); - - const cursor = useMemo(() => !disabled ? 'cursor-text': 'cursor-default', [disabled]); - const customTheme: Extension = useMemo( - () => createTheme({ - theme: darkMode ? 'dark' : 'light', - settings: { - fontFamily: 'inherit', - background: !disabled ? colors.bgInput : colors.bgDefault, - foreground: colors.fgDefault, - selection: colors.bgHover - }, - styles: [ - { tag: tags.name, color: colors.fgPurple, cursor: 'default' }, // GlobalID - { tag: tags.variableName, color: colors.fgGreen }, // LocalID - { tag: tags.propertyName, color: colors.fgTeal }, // Radical - { tag: tags.keyword, color: colors.fgBlue }, // keywords - { tag: tags.literal, color: colors.fgBlue }, // literals - { tag: tags.controlKeyword, fontWeight: '500'}, // R | I | D - { tag: tags.unit, fontSize: '0.75rem' }, // indicies - ] - }), [disabled, colors, darkMode]); - - const editorExtensions = useMemo( - () => [ - EditorView.lineWrapping, - RSLanguage, - ccBracketMatching(darkMode), - ... noTooltip ? [] : [rsHoverTooltip(schema?.items || [])], - ], [darkMode, schema?.items, noTooltip]); - - const handleInput = useCallback( - (event: React.KeyboardEvent) => { - if (!thisRef.current) { - return; - } - const text = new RSTextWrapper(thisRef.current as Required); - if (event.shiftKey && !event.altKey) { - if (event.key === '*') { - text.insertToken(TokenID.DECART); - event.preventDefault(); - } else if (event.code === 'KeyB') { - text.insertChar('ℬ'); - event.preventDefault(); - } else if (event.code === 'KeyZ') { - text.insertChar('Z'); - event.preventDefault(); - } else if (event.code === 'KeyR') { - text.insertChar('R'); - event.preventDefault(); - } else if (event.code === 'KeyF') { - text.insertChar('F'); - event.preventDefault(); - } else if (event.code === 'KeyP') { - text.insertChar('P'); - event.preventDefault(); - } else if (event.code === 'KeyX') { - text.insertChar('X'); - event.preventDefault(); - } else if (event.code === 'KeyS') { - text.insertChar('S'); - event.preventDefault(); - } else if (event.code === 'KeyD') { - text.insertChar('D'); - event.preventDefault(); - } else if (event.code === 'KeyC') { - text.insertChar('C'); - event.preventDefault(); - } - } else if (event.altKey) { - if (text.processAltKey(event.code, event.shiftKey)) { - event.preventDefault(); - } - } else if (!event.ctrlKey) { - const newSymbol = getSymbolSubstitute(event.code, event.shiftKey); - if (newSymbol) { - text.replaceWith(newSymbol); - event.preventDefault(); - } - } - }, [thisRef]); - - return ( -
- {label && -
- ); -} - -export default RSInput; +export { default } from './RSInput'; \ No newline at end of file diff --git a/rsconcept/frontend/src/components/RefsInput/RefsInput.tsx b/rsconcept/frontend/src/components/RefsInput/RefsInput.tsx new file mode 100644 index 00000000..779c80a0 --- /dev/null +++ b/rsconcept/frontend/src/components/RefsInput/RefsInput.tsx @@ -0,0 +1,232 @@ + +import { Extension } from '@codemirror/state'; +import { tags } from '@lezer/highlight'; +import { createTheme } from '@uiw/codemirror-themes'; +import CodeMirror, { BasicSetupOptions, ReactCodeMirrorProps, ReactCodeMirrorRef } from '@uiw/react-codemirror'; +import { EditorView } from 'codemirror'; +import { RefObject, useCallback, useMemo, useRef, useState } from 'react'; + +import { useRSForm } from '../../context/RSFormContext'; +import { useConceptTheme } from '../../context/ThemeContext'; +import DlgEditReference from '../../dialogs/DlgEditReference'; +import useResolveText from '../../hooks/useResolveText'; +import { ReferenceType } from '../../models/language'; +import { IConstituenta } from '../../models/rsform'; +import { CodeMirrorWrapper } from '../../utils/codemirror'; +import Label from '../common/Label'; +import Modal from '../common/Modal'; +import PrettyJson from '../common/PrettyJSON'; +import { NaturalLanguage, ReferenceTokens } from './parse'; +import { RefEntity } from './parse/parser.terms'; +import { refsHoverTooltip } from './tooltip'; + +const editorSetup: BasicSetupOptions = { + highlightSpecialChars: false, + history: true, + drawSelection: false, + syntaxHighlighting: false, + defaultKeymap: true, + historyKeymap: true, + + lineNumbers: false, + highlightActiveLineGutter: false, + foldGutter: false, + dropCursor: true, + allowMultipleSelections: false, + indentOnInput: false, + bracketMatching: false, + closeBrackets: false, + autocompletion: false, + rectangularSelection: false, + crosshairCursor: false, + highlightActiveLine: false, + highlightSelectionMatches: false, + closeBracketsKeymap: false, + searchKeymap: false, + foldKeymap: false, + completionKeymap: false, + lintKeymap: false +}; + +interface RefsInputInputProps +extends Pick { + label?: string + innerref?: RefObject | undefined + onChange?: (newValue: string) => void + items?: IConstituenta[] + disabled?: boolean + + initialValue?: string + value?: string + resolved?: string +} + +function RefsInput({ + id, label, innerref, disabled, items, + initialValue, value, resolved, + onFocus, onBlur, onChange, + ...props +}: RefsInputInputProps) { + const { darkMode, colors } = useConceptTheme(); + const { schema } = useRSForm(); + + const { resolveText, refsData } = useResolveText({schema: schema}); + + const [showResolve, setShowResolve] = useState(false); + const [isFocused, setIsFocused] = useState(false); + + const [showEditor, setShowEditor] = useState(false); + const [currentType, setCurrentType] = useState(ReferenceType.ENTITY); + const [refText, setRefText] = useState(''); + const [hintText, setHintText] = useState(''); + const [basePosition, setBasePosition] = useState(0); + const [mainRefs, setMainRefs] = useState([]); + + const internalRef = useRef(null); + const thisRef = useMemo( + () => { + return innerref ?? internalRef; + }, [internalRef, innerref]); + + const cursor = useMemo(() => !disabled ? 'cursor-text': 'cursor-default', [disabled]); + const customTheme: Extension = useMemo( + () => createTheme({ + theme: darkMode ? 'dark' : 'light', + settings: { + fontFamily: 'inherit', + background: !disabled ? colors.bgInput : colors.bgDefault, + foreground: colors.fgDefault, + selection: colors.bgHover + }, + styles: [ + { tag: tags.name, color: colors.fgPurple, cursor: 'default' }, // EntityReference + { tag: tags.literal, color: colors.fgTeal, cursor: 'default' }, // SyntacticReference + { tag: tags.comment, color: colors.fgRed }, // Error + ] + }), [disabled, colors, darkMode]); + + const editorExtensions = useMemo( + () => [ + EditorView.lineWrapping, + NaturalLanguage, + refsHoverTooltip(schema?.items || [], colors) + ], [schema?.items, colors]); + + function handleChange(newValue: string) { + if (onChange) onChange(newValue); + } + + function handleFocusIn(event: React.FocusEvent) { + setIsFocused(true); + if (onFocus) onFocus(event); + } + + function handleFocusOut(event: React.FocusEvent) { + setIsFocused(false); + if (onBlur) onBlur(event); + } + + const handleInput = useCallback( + (event: React.KeyboardEvent) => { + if (!thisRef.current?.view) { + event.preventDefault(); + return; + } + if (event.altKey) { + if (event.key === 'r' && value) { + event.preventDefault(); + resolveText(value, () => { + setShowResolve(true); + }); + return; + } + } + if (event.ctrlKey && event.code === 'Space') { + const wrap = new CodeMirrorWrapper(thisRef.current as Required); + wrap.fixSelection(ReferenceTokens); + const nodes = wrap.getEnvelopingNodes(ReferenceTokens); + if (nodes.length !== 1) { + setCurrentType(ReferenceType.ENTITY); + setRefText(''); + setHintText(wrap.getSelectionText()); + } else { + setCurrentType(nodes[0].type.id === RefEntity ? ReferenceType.ENTITY : ReferenceType.SYNTACTIC); + setRefText(wrap.getSelectionText()); + } + + const selection = wrap.getSelection(); + const mainNodes = wrap.getAllNodes([RefEntity]).filter(node => node.from >= selection.to || node.to <= selection.from); + setMainRefs(mainNodes.map(node => wrap.getText(node.from, node.to))); + setBasePosition(mainNodes.filter(node => node.to <= selection.from).length); + + setShowEditor(true); + } + }, [thisRef, resolveText, value]); + + const handleInputReference = useCallback( + (referenceText: string) => { + if (!thisRef.current?.view) { + return; + } + thisRef.current.view.focus(); + const wrap = new CodeMirrorWrapper(thisRef.current as Required); + wrap.replaceWith(referenceText); + }, [thisRef]); + + return ( + <> + { showEditor && + setShowEditor(false)} + items={items ?? []} + initial={{ + type: currentType, + refRaw: refText, + text: hintText, + basePosition: basePosition, + mainRefs: mainRefs + }} + onSave={handleInputReference} + /> + } + { showResolve && + setShowResolve(false)} + > +
+ +
+
} +
+ {label && +
+ ); +} + +export default RefsInput; diff --git a/rsconcept/frontend/src/components/RefsInput/index.tsx b/rsconcept/frontend/src/components/RefsInput/index.tsx index 59ad6def..92d135f7 100644 --- a/rsconcept/frontend/src/components/RefsInput/index.tsx +++ b/rsconcept/frontend/src/components/RefsInput/index.tsx @@ -1,232 +1 @@ - -import { Extension } from '@codemirror/state'; -import { tags } from '@lezer/highlight'; -import { createTheme } from '@uiw/codemirror-themes'; -import CodeMirror, { BasicSetupOptions, ReactCodeMirrorProps, ReactCodeMirrorRef } from '@uiw/react-codemirror'; -import { EditorView } from 'codemirror'; -import { RefObject, useCallback, useMemo, useRef, useState } from 'react'; - -import { useRSForm } from '../../context/RSFormContext'; -import { useConceptTheme } from '../../context/ThemeContext'; -import DlgEditReference from '../../dialogs/DlgEditReference'; -import useResolveText from '../../hooks/useResolveText'; -import { ReferenceType } from '../../models/language'; -import { IConstituenta } from '../../models/rsform'; -import { CodeMirrorWrapper } from '../../utils/codemirror'; -import Label from '../Common/Label'; -import Modal from '../Common/Modal'; -import PrettyJson from '../Common/PrettyJSON'; -import { NaturalLanguage, ReferenceTokens } from './parse'; -import { RefEntity } from './parse/parser.terms'; -import { refsHoverTooltip } from './tooltip'; - -const editorSetup: BasicSetupOptions = { - highlightSpecialChars: false, - history: true, - drawSelection: false, - syntaxHighlighting: false, - defaultKeymap: true, - historyKeymap: true, - - lineNumbers: false, - highlightActiveLineGutter: false, - foldGutter: false, - dropCursor: true, - allowMultipleSelections: false, - indentOnInput: false, - bracketMatching: false, - closeBrackets: false, - autocompletion: false, - rectangularSelection: false, - crosshairCursor: false, - highlightActiveLine: false, - highlightSelectionMatches: false, - closeBracketsKeymap: false, - searchKeymap: false, - foldKeymap: false, - completionKeymap: false, - lintKeymap: false -}; - -interface RefsInputInputProps -extends Pick { - label?: string - innerref?: RefObject | undefined - onChange?: (newValue: string) => void - items?: IConstituenta[] - disabled?: boolean - - initialValue?: string - value?: string - resolved?: string -} - -function RefsInput({ - id, label, innerref, disabled, items, - initialValue, value, resolved, - onFocus, onBlur, onChange, - ...props -}: RefsInputInputProps) { - const { darkMode, colors } = useConceptTheme(); - const { schema } = useRSForm(); - - const { resolveText, refsData } = useResolveText({schema: schema}); - - const [showResolve, setShowResolve] = useState(false); - const [isFocused, setIsFocused] = useState(false); - - const [showEditor, setShowEditor] = useState(false); - const [currentType, setCurrentType] = useState(ReferenceType.ENTITY); - const [refText, setRefText] = useState(''); - const [hintText, setHintText] = useState(''); - const [basePosition, setBasePosition] = useState(0); - const [mainRefs, setMainRefs] = useState([]); - - const internalRef = useRef(null); - const thisRef = useMemo( - () => { - return innerref ?? internalRef; - }, [internalRef, innerref]); - - const cursor = useMemo(() => !disabled ? 'cursor-text': 'cursor-default', [disabled]); - const customTheme: Extension = useMemo( - () => createTheme({ - theme: darkMode ? 'dark' : 'light', - settings: { - fontFamily: 'inherit', - background: !disabled ? colors.bgInput : colors.bgDefault, - foreground: colors.fgDefault, - selection: colors.bgHover - }, - styles: [ - { tag: tags.name, color: colors.fgPurple, cursor: 'default' }, // EntityReference - { tag: tags.literal, color: colors.fgTeal, cursor: 'default' }, // SyntacticReference - { tag: tags.comment, color: colors.fgRed }, // Error - ] - }), [disabled, colors, darkMode]); - - const editorExtensions = useMemo( - () => [ - EditorView.lineWrapping, - NaturalLanguage, - refsHoverTooltip(schema?.items || [], colors) - ], [schema?.items, colors]); - - function handleChange(newValue: string) { - if (onChange) onChange(newValue); - } - - function handleFocusIn(event: React.FocusEvent) { - setIsFocused(true); - if (onFocus) onFocus(event); - } - - function handleFocusOut(event: React.FocusEvent) { - setIsFocused(false); - if (onBlur) onBlur(event); - } - - const handleInput = useCallback( - (event: React.KeyboardEvent) => { - if (!thisRef.current?.view) { - event.preventDefault(); - return; - } - if (event.altKey) { - if (event.key === 'r' && value) { - event.preventDefault(); - resolveText(value, () => { - setShowResolve(true); - }); - return; - } - } - if (event.ctrlKey && event.code === 'Space') { - const wrap = new CodeMirrorWrapper(thisRef.current as Required); - wrap.fixSelection(ReferenceTokens); - const nodes = wrap.getEnvelopingNodes(ReferenceTokens); - if (nodes.length !== 1) { - setCurrentType(ReferenceType.ENTITY); - setRefText(''); - setHintText(wrap.getSelectionText()); - } else { - setCurrentType(nodes[0].type.id === RefEntity ? ReferenceType.ENTITY : ReferenceType.SYNTACTIC); - setRefText(wrap.getSelectionText()); - } - - const selection = wrap.getSelection(); - const mainNodes = wrap.getAllNodes([RefEntity]).filter(node => node.from >= selection.to || node.to <= selection.from); - setMainRefs(mainNodes.map(node => wrap.getText(node.from, node.to))); - setBasePosition(mainNodes.filter(node => node.to <= selection.from).length); - - setShowEditor(true); - } - }, [thisRef, resolveText, value]); - - const handleInputReference = useCallback( - (referenceText: string) => { - if (!thisRef.current?.view) { - return; - } - thisRef.current.view.focus(); - const wrap = new CodeMirrorWrapper(thisRef.current as Required); - wrap.replaceWith(referenceText); - }, [thisRef]); - - return ( - <> - { showEditor && - setShowEditor(false)} - items={items ?? []} - initial={{ - type: currentType, - refRaw: refText, - text: hintText, - basePosition: basePosition, - mainRefs: mainRefs - }} - onSave={handleInputReference} - /> - } - { showResolve && - setShowResolve(false)} - > -
- -
-
} -
- {label && -
- ); -} - -export default RefsInput; +export { default } from './RefsInput'; \ No newline at end of file diff --git a/rsconcept/frontend/src/components/RequireAuth.tsx b/rsconcept/frontend/src/components/RequireAuth.tsx index e1a5464f..94ba91c7 100644 --- a/rsconcept/frontend/src/components/RequireAuth.tsx +++ b/rsconcept/frontend/src/components/RequireAuth.tsx @@ -1,5 +1,5 @@ import { useAuth } from '../context/AuthContext'; -import TextURL from './Common/TextURL'; +import TextURL from './common/TextURL'; interface RequireAuthProps { children: React.ReactNode diff --git a/rsconcept/frontend/src/components/Shared/ConstituentaBadge.tsx b/rsconcept/frontend/src/components/Shared/ConstituentaBadge.tsx index b1890329..74edc961 100644 --- a/rsconcept/frontend/src/components/Shared/ConstituentaBadge.tsx +++ b/rsconcept/frontend/src/components/Shared/ConstituentaBadge.tsx @@ -2,7 +2,7 @@ import { IConstituenta } from '../../models/rsform'; import { isMockCst } from '../../models/rsformAPI'; import { colorfgCstStatus,IColorTheme } from '../../utils/color'; import { describeExpressionStatus } from '../../utils/labels'; -import ConceptTooltip from '../Common/ConceptTooltip'; +import ConceptTooltip from '../common/ConceptTooltip'; import ConstituentaTooltip from '../Help/ConstituentaTooltip'; interface ConstituentaBadgeProps { diff --git a/rsconcept/frontend/src/components/Shared/ConstituentaPicker.tsx b/rsconcept/frontend/src/components/Shared/ConstituentaPicker.tsx index 1a134305..80147b47 100644 --- a/rsconcept/frontend/src/components/Shared/ConstituentaPicker.tsx +++ b/rsconcept/frontend/src/components/Shared/ConstituentaPicker.tsx @@ -6,8 +6,8 @@ import { IConstituenta } from '../../models/rsform'; import { matchConstituenta } from '../../models/rsformAPI'; import { prefixes } from '../../utils/constants'; import { describeConstituenta } from '../../utils/labels'; -import ConceptSearch from '../Common/ConceptSearch'; -import DataTable, { createColumnHelper,IConditionalStyle } from '../DataTable'; +import ConceptSearch from '../common/ConceptSearch'; +import DataTable, { createColumnHelper, IConditionalStyle } from '../DataTable'; import ConstituentaBadge from './ConstituentaBadge'; interface ConstituentaPickerProps { diff --git a/rsconcept/frontend/src/dialogs/DlgCloneRSForm.tsx b/rsconcept/frontend/src/dialogs/DlgCloneRSForm.tsx index 9f40e161..64379096 100644 --- a/rsconcept/frontend/src/dialogs/DlgCloneRSForm.tsx +++ b/rsconcept/frontend/src/dialogs/DlgCloneRSForm.tsx @@ -1,10 +1,10 @@ import { useEffect, useState } from 'react'; import { toast } from 'react-toastify'; -import Checkbox from '../components/Common/Checkbox'; -import Modal, { ModalProps } from '../components/Common/Modal'; -import TextArea from '../components/Common/TextArea'; -import TextInput from '../components/Common/TextInput'; +import Checkbox from '../components/common/Checkbox'; +import Modal, { ModalProps } from '../components/common/Modal'; +import TextArea from '../components/common/TextArea'; +import TextInput from '../components/common/TextInput'; import { useLibrary } from '../context/LibraryContext'; import { useConceptNavigation } from '../context/NagivationContext'; import { useRSForm } from '../context/RSFormContext'; diff --git a/rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/ArgumentsTab.tsx b/rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/ArgumentsTab.tsx index f39ff1c1..dca99fa8 100644 --- a/rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/ArgumentsTab.tsx +++ b/rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/ArgumentsTab.tsx @@ -1,11 +1,11 @@ import { createColumnHelper } from '@tanstack/react-table'; import { Dispatch, useCallback, useEffect, useMemo, useState } from 'react'; -import MiniButton from '../../components/Common/MiniButton'; +import MiniButton from '../../components/common/MiniButton'; import DataTable, { IConditionalStyle } from '../../components/DataTable'; import { CheckIcon, CrossIcon } from '../../components/Icons'; import RSInput from '../../components/RSInput'; -import ConstituentaPicker from '../../components/Shared/ConstituentaPicker'; +import ConstituentaPicker from '../../components/shared/ConstituentaPicker'; import { useConceptTheme } from '../../context/ThemeContext'; import { IConstituenta, IRSForm } from '../../models/rsform'; import { IArgumentValue } from '../../models/rslang'; diff --git a/rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/ConstituentaTab.tsx b/rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/ConstituentaTab.tsx index c1a1ac33..532fc118 100644 --- a/rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/ConstituentaTab.tsx +++ b/rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/ConstituentaTab.tsx @@ -1,8 +1,8 @@ import { Dispatch } from 'react'; -import SelectSingle from '../../components/Common/SelectSingle'; -import TextArea from '../../components/Common/TextArea'; -import TextInput from '../../components/Common/TextInput'; +import SelectSingle from '../../components/common/SelectSingle'; +import TextArea from '../../components/common/TextArea'; +import TextInput from '../../components/common/TextInput'; import RSInput from '../../components/RSInput'; import { CstType, ICstCreateData } from '../../models/rsform'; import { labelCstType } from '../../utils/labels'; diff --git a/rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/DlgConstituentaTemplate.tsx b/rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/DlgConstituentaTemplate.tsx new file mode 100644 index 00000000..9bf016e2 --- /dev/null +++ b/rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/DlgConstituentaTemplate.tsx @@ -0,0 +1,180 @@ +import { useLayoutEffect, useState } from 'react'; +import { TabList, TabPanel, Tabs } from 'react-tabs'; + +import ConceptTab from '../../components/common/ConceptTab'; +import ConceptTooltip from '../../components/common/ConceptTooltip'; +import Modal, { ModalProps } from '../../components/common/Modal'; +import HelpRSTemplates from '../../components/Help/HelpRSTemplates'; +import { HelpIcon } from '../../components/Icons'; +import usePartialUpdate from '../../hooks/usePartialUpdate'; +import { CstType, ICstCreateData, IRSForm } from '../../models/rsform'; +import { inferTemplatedType, substituteTemplateArgs } from '../../models/rslangAPI'; +import { createAliasFor, validateCstAlias } from '../../utils/misc'; +import ArgumentsTab, { IArgumentsState } from './ArgumentsTab'; +import ConstituentaTab from './ConstituentaTab'; +import TemplateTab, { ITemplateState } from './TemplateTab'; + +interface DlgConstituentaTemplateProps +extends Pick { + schema: IRSForm + onCreate: (data: ICstCreateData) => void +} + +export enum TabID { + TEMPLATE = 0, + ARGUMENTS = 1, + CONSTITUENTA = 2 +} + +function DlgConstituentaTemplate({ hideWindow, schema, onCreate }: DlgConstituentaTemplateProps) { + const [ validated, setValidated ] = useState(false); + const [ template, updateTemplate ] = usePartialUpdate({}); + const [ substitutes, updateSubstitutes ] = usePartialUpdate({ + definition: '', + arguments: [] + }); + const [constituenta, updateConstituenta] = usePartialUpdate({ + cst_type: CstType.TERM, + insert_after: null, + alias: '', + convention: '', + definition_formal: '', + definition_raw: '', + term_raw: '', + term_forms: [] + }); + + const [ activeTab, setActiveTab ] = useState(TabID.TEMPLATE); + + const handleSubmit = () => onCreate(constituenta); + + useLayoutEffect( + () => { + updateConstituenta({ alias: createAliasFor(constituenta.cst_type, schema) }); + }, [constituenta.cst_type, updateConstituenta, schema]); + + useLayoutEffect( + () => { + setValidated(validateCstAlias(constituenta.alias, constituenta.cst_type, schema)); + }, [constituenta.alias, constituenta.cst_type, schema]); + + useLayoutEffect( + () => { + if (!template.prototype) { + updateConstituenta({ + definition_raw: '', + definition_formal: '', + term_raw: '' + }); + updateSubstitutes({ + definition: '', + arguments: [] + }); + } else { + updateConstituenta({ + cst_type: template.prototype.cst_type, + definition_raw: template.prototype.definition_raw, + definition_formal: template.prototype.definition_formal, + term_raw: template.prototype.term_raw + }); + updateSubstitutes({ + definition: template.prototype.definition_formal, + arguments: template.prototype.parse.args.map( + arg => ({ + alias: arg.alias, + typification: arg.typification, + value: '' + }) + ) + }); + } + }, [template.prototype, updateConstituenta, updateSubstitutes]); + + useLayoutEffect( + () => { + if (substitutes.arguments.length === 0 || !template.prototype) { + return; + } + const definition = substituteTemplateArgs(template.prototype.definition_formal, substitutes.arguments); + const type = inferTemplatedType(template.prototype.cst_type, substitutes.arguments); + updateConstituenta({ + cst_type: type, + definition_formal: definition, + }); + updateSubstitutes({ + definition: definition, + }); + }, [substitutes.arguments, template.prototype, updateConstituenta, updateSubstitutes]); + + return ( + +
+ +
+ + + Шаблон + + + Аргументы + + + Конституента + + + +
+ +
+ + + +
+ +
+ + + + + + + + + + + +
+
+
+
); +} + +export default DlgConstituentaTemplate; diff --git a/rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/TemplateTab.tsx b/rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/TemplateTab.tsx index 0a812741..7aa8dacf 100644 --- a/rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/TemplateTab.tsx +++ b/rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/TemplateTab.tsx @@ -1,9 +1,9 @@ import { Dispatch, useEffect, useMemo, useState } from 'react'; -import SelectSingle from '../../components/Common/SelectSingle'; -import TextArea from '../../components/Common/TextArea'; +import SelectSingle from '../../components/common/SelectSingle'; +import TextArea from '../../components/common/TextArea'; import RSInput from '../../components/RSInput'; -import ConstituentaPicker from '../../components/Shared/ConstituentaPicker'; +import ConstituentaPicker from '../../components/shared/ConstituentaPicker'; import { useLibrary } from '../../context/LibraryContext'; import { CATEGORY_CST_TYPE, IConstituenta, IRSForm } from '../../models/rsform'; import { applyFilterCategory } from '../../models/rsformAPI'; diff --git a/rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/index.tsx b/rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/index.tsx index 7fa066ed..6c906abb 100644 --- a/rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/index.tsx +++ b/rsconcept/frontend/src/dialogs/DlgConstituentaTemplate/index.tsx @@ -1,180 +1 @@ -import { useLayoutEffect, useState } from 'react'; -import { TabList, TabPanel, Tabs } from 'react-tabs'; - -import ConceptTab from '../../components/Common/ConceptTab'; -import ConceptTooltip from '../../components/Common/ConceptTooltip'; -import Modal, { ModalProps } from '../../components/Common/Modal'; -import HelpRSTemplates from '../../components/Help/HelpRSTemplates'; -import { HelpIcon } from '../../components/Icons'; -import usePartialUpdate from '../../hooks/usePartialUpdate'; -import { CstType, ICstCreateData, IRSForm } from '../../models/rsform'; -import { inferTemplatedType, substituteTemplateArgs } from '../../models/rslangAPI'; -import { createAliasFor, validateCstAlias } from '../../utils/misc'; -import ArgumentsTab, { IArgumentsState } from './ArgumentsTab'; -import ConstituentaTab from './ConstituentaTab'; -import TemplateTab, { ITemplateState } from './TemplateTab'; - -interface DlgConstituentaTemplateProps -extends Pick { - schema: IRSForm - onCreate: (data: ICstCreateData) => void -} - -export enum TabID { - TEMPLATE = 0, - ARGUMENTS = 1, - CONSTITUENTA = 2 -} - -function DlgConstituentaTemplate({ hideWindow, schema, onCreate }: DlgConstituentaTemplateProps) { - const [ validated, setValidated ] = useState(false); - const [ template, updateTemplate ] = usePartialUpdate({}); - const [ substitutes, updateSubstitutes ] = usePartialUpdate({ - definition: '', - arguments: [] - }); - const [constituenta, updateConstituenta] = usePartialUpdate({ - cst_type: CstType.TERM, - insert_after: null, - alias: '', - convention: '', - definition_formal: '', - definition_raw: '', - term_raw: '', - term_forms: [] - }); - - const [ activeTab, setActiveTab ] = useState(TabID.TEMPLATE); - - const handleSubmit = () => onCreate(constituenta); - - useLayoutEffect( - () => { - updateConstituenta({ alias: createAliasFor(constituenta.cst_type, schema) }); - }, [constituenta.cst_type, updateConstituenta, schema]); - - useLayoutEffect( - () => { - setValidated(validateCstAlias(constituenta.alias, constituenta.cst_type, schema)); - }, [constituenta.alias, constituenta.cst_type, schema]); - - useLayoutEffect( - () => { - if (!template.prototype) { - updateConstituenta({ - definition_raw: '', - definition_formal: '', - term_raw: '' - }); - updateSubstitutes({ - definition: '', - arguments: [] - }); - } else { - updateConstituenta({ - cst_type: template.prototype.cst_type, - definition_raw: template.prototype.definition_raw, - definition_formal: template.prototype.definition_formal, - term_raw: template.prototype.term_raw - }); - updateSubstitutes({ - definition: template.prototype.definition_formal, - arguments: template.prototype.parse.args.map( - arg => ({ - alias: arg.alias, - typification: arg.typification, - value: '' - }) - ) - }); - } - }, [template.prototype, updateConstituenta, updateSubstitutes]); - - useLayoutEffect( - () => { - if (substitutes.arguments.length === 0 || !template.prototype) { - return; - } - const definition = substituteTemplateArgs(template.prototype.definition_formal, substitutes.arguments); - const type = inferTemplatedType(template.prototype.cst_type, substitutes.arguments); - updateConstituenta({ - cst_type: type, - definition_formal: definition, - }); - updateSubstitutes({ - definition: definition, - }); - }, [substitutes.arguments, template.prototype, updateConstituenta, updateSubstitutes]); - - return ( - -
- -
- - - Шаблон - - - Аргументы - - - Конституента - - - -
- -
- - - -
- -
- - - - - - - - - - - -
-
-
-
); -} - -export default DlgConstituentaTemplate; +export { default } from './DlgConstituentaTemplate'; \ No newline at end of file diff --git a/rsconcept/frontend/src/dialogs/DlgCreateCst.tsx b/rsconcept/frontend/src/dialogs/DlgCreateCst.tsx index b312f458..210dee60 100644 --- a/rsconcept/frontend/src/dialogs/DlgCreateCst.tsx +++ b/rsconcept/frontend/src/dialogs/DlgCreateCst.tsx @@ -1,9 +1,9 @@ import { useEffect, useLayoutEffect, useState } from 'react'; -import Modal, { ModalProps } from '../components/Common/Modal'; -import SelectSingle from '../components/Common/SelectSingle'; -import TextArea from '../components/Common/TextArea'; -import TextInput from '../components/Common/TextInput'; +import Modal, { ModalProps } from '../components/common/Modal'; +import SelectSingle from '../components/common/SelectSingle'; +import TextArea from '../components/common/TextArea'; +import TextInput from '../components/common/TextInput'; import RSInput from '../components/RSInput'; import usePartialUpdate from '../hooks/usePartialUpdate'; import { CstType,ICstCreateData, IRSForm } from '../models/rsform'; diff --git a/rsconcept/frontend/src/dialogs/DlgDeleteCst.tsx b/rsconcept/frontend/src/dialogs/DlgDeleteCst.tsx index 6e56e380..5947db0f 100644 --- a/rsconcept/frontend/src/dialogs/DlgDeleteCst.tsx +++ b/rsconcept/frontend/src/dialogs/DlgDeleteCst.tsx @@ -1,7 +1,7 @@ import { useMemo, useState } from 'react'; -import Checkbox from '../components/Common/Checkbox'; -import Modal, { ModalProps } from '../components/Common/Modal'; +import Checkbox from '../components/common/Checkbox'; +import Modal, { ModalProps } from '../components/common/Modal'; import { useRSForm } from '../context/RSFormContext'; import { prefixes } from '../utils/constants'; import { labelConstituenta } from '../utils/labels'; diff --git a/rsconcept/frontend/src/dialogs/DlgEditReference/DlgEditReference.tsx b/rsconcept/frontend/src/dialogs/DlgEditReference/DlgEditReference.tsx new file mode 100644 index 00000000..e336ec0a --- /dev/null +++ b/rsconcept/frontend/src/dialogs/DlgEditReference/DlgEditReference.tsx @@ -0,0 +1,272 @@ +import { useCallback, useEffect, useLayoutEffect, useMemo, useState } from 'react'; + +import ConceptTooltip from '../../components/common/ConceptTooltip'; +import Label from '../../components/common/Label'; +import Modal from '../../components/common/Modal'; +import SelectMulti from '../../components/common/SelectMulti'; +import TextInput from '../../components/common/TextInput'; +import HelpTerminologyControl from '../../components/Help/HelpTerminologyControl'; +import { HelpIcon } from '../../components/Icons'; +import ConstituentaPicker from '../../components/shared/ConstituentaPicker'; +import { Grammeme, ReferenceType } from '../../models/language'; +import { getCompatibleGrams, parseEntityReference, parseGrammemes, parseSyntacticReference } from '../../models/languageAPI'; +import { CstMatchMode } from '../../models/miscelanious'; +import { IConstituenta } from '../../models/rsform'; +import { matchConstituenta } from '../../models/rsformAPI'; +import { prefixes } from '../../utils/constants'; +import { compareGrammemeOptions, IGrammemeOption, PremadeWordForms, SelectorGrammems } from '../../utils/selectors'; +import ReferenceTypeButton from './ReferenceTypeButton'; +import WordformButton from './WordformButton'; + +export interface IReferenceInputState { + type: ReferenceType + refRaw?: string + text?: string + mainRefs: string[] + basePosition: number +} + +interface DlgEditReferenceProps { + hideWindow: () => void + items: IConstituenta[] + initial: IReferenceInputState + onSave: (newRef: string) => void +} + +function DlgEditReference({ hideWindow, items, initial, onSave }: DlgEditReferenceProps) { + const [type, setType] = useState(ReferenceType.ENTITY); + + const [nominal, setNominal] = useState(''); + const [offset, setOffset] = useState(1); + + const [selectedCst, setSelectedCst] = useState(undefined); + const [alias, setAlias] = useState(''); + const [term, setTerm] = useState(''); + + const [selectedGrams, setSelectedGrams] = useState([]); + const [gramOptions, setGramOptions] = useState([]); + + const mainLink = useMemo( + () => { + const position = offset > 0 ? initial.basePosition + (offset - 1) : initial.basePosition + offset; + if (offset === 0 || position < 0 || position >= initial.mainRefs.length) { + return 'Некорректное значение смещения'; + } else { + return initial.mainRefs[position]; + } + }, [initial, offset]); + + const isValid = useMemo( + () => { + if (type === ReferenceType.ENTITY) { + return alias !== '' && selectedGrams.length > 0; + } else if (type === ReferenceType.SYNTACTIC) { + return nominal !== '' && offset !== 0; + } else { + return false; + } + }, [type, alias, selectedGrams, nominal, offset]); + + function produceReference(): string { + if (type === ReferenceType.ENTITY) { + return `@{${alias}|${selectedGrams.map(gram => gram.value).join(',')}}`; + } else if (type === ReferenceType.SYNTACTIC) { + return `@{${offset}|${nominal}}`; + } else { + return ''; + } + } + + // Initialization + useLayoutEffect( + () => { + setType(initial.type); + if (initial.refRaw) { + if (initial.type === ReferenceType.ENTITY) { + const ref = parseEntityReference(initial.refRaw); + setAlias(ref.entity); + const grams = parseGrammemes(ref.form); + setSelectedGrams(SelectorGrammems.filter(data => grams.includes(data.value))); + } else if (initial.type === ReferenceType.SYNTACTIC) { + const ref = parseSyntacticReference(initial.refRaw); + setOffset(ref.offset); + setNominal(ref.nominal); + } + } else if (initial.text) { + setNominal(initial.text ?? ''); + } + }, [initial, items]); + + // Filter grammemes when input changes + useEffect( + () => { + const compatible = getCompatibleGrams( + selectedGrams + .filter(data => Object.values(Grammeme).includes(data.value as Grammeme)) + .map(data => data.value as Grammeme) + ); + setGramOptions(SelectorGrammems.filter(({value}) => compatible.includes(value as Grammeme))); + }, [selectedGrams]); + + // Update term when alias changes + useEffect( + () => { + const cst = items.find(item => item.alias === alias) + setTerm(cst?.term_resolved ?? '') + }, [alias, term, items]); + + const handleSubmit = () => onSave(produceReference()); + + function handleSelectConstituenta(cst: IConstituenta) { + setAlias(cst.alias); + setSelectedCst(cst); + } + + const handleSelectGrams = useCallback( + (grams: Grammeme[]) => { + setSelectedGrams(SelectorGrammems.filter(({value}) => grams.includes(value as Grammeme))); + }, []); + + const FormButtons = useMemo(() => { + return ( +
+
+ {PremadeWordForms.slice(0, 6).map( + (data, index) => + selectedGrams.find(item => item.value as Grammeme === gram))} + onSelectGrams={handleSelectGrams} + /> + )} +
+ +
+ {PremadeWordForms.slice(6, 12).map( + (data, index) => + selectedGrams.find(item => item.value as Grammeme === gram))} + onSelectGrams={handleSelectGrams} + /> + )} +
+ +
); + }, [handleSelectGrams, selectedGrams]); + + return ( + +
+
+ + +
+ +
+ + + +
+ {type === ReferenceType.SYNTACTIC && +
+
+ setOffset(event.target.valueAsNumber)} + /> +
+ Основная ссылка: +
+ +
+ setNominal(event.target.value)} + /> +
} + {type === ReferenceType.ENTITY && +
+ cst.term_resolved} + matchFunc={(cst, filter) => matchConstituenta(cst, filter, CstMatchMode.TERM)} + prefilterFunc={cst => cst.term_resolved !== ''} + rows={8} + /> + +
+ setAlias(event.target.value)} + /> +
+
+ Термин: +
+ +
+
+ {FormButtons} +
+
+
} +
+
); +} + +export default DlgEditReference; diff --git a/rsconcept/frontend/src/dialogs/DlgEditReference/ReferenceTypeButton.tsx b/rsconcept/frontend/src/dialogs/DlgEditReference/ReferenceTypeButton.tsx index e85da381..3f3005e1 100644 --- a/rsconcept/frontend/src/dialogs/DlgEditReference/ReferenceTypeButton.tsx +++ b/rsconcept/frontend/src/dialogs/DlgEditReference/ReferenceTypeButton.tsx @@ -1,4 +1,4 @@ -import SwitchButton from '../../components/Common/SwitchButton'; +import SwitchButton from '../../components/common/SwitchButton'; import { ReferenceType } from '../../models/language'; import { labelReferenceType } from '../../utils/labels'; diff --git a/rsconcept/frontend/src/dialogs/DlgEditReference/index.tsx b/rsconcept/frontend/src/dialogs/DlgEditReference/index.tsx index ddf1ad97..fb07cdfa 100644 --- a/rsconcept/frontend/src/dialogs/DlgEditReference/index.tsx +++ b/rsconcept/frontend/src/dialogs/DlgEditReference/index.tsx @@ -1,272 +1 @@ -import { useCallback, useEffect, useLayoutEffect, useMemo, useState } from 'react'; - -import ConceptTooltip from '../../components/Common/ConceptTooltip'; -import Label from '../../components/Common/Label'; -import Modal from '../../components/Common/Modal'; -import SelectMulti from '../../components/Common/SelectMulti'; -import TextInput from '../../components/Common/TextInput'; -import HelpTerminologyControl from '../../components/Help/HelpTerminologyControl'; -import { HelpIcon } from '../../components/Icons'; -import ConstituentaPicker from '../../components/Shared/ConstituentaPicker'; -import { Grammeme, ReferenceType } from '../../models/language'; -import { getCompatibleGrams, parseEntityReference, parseGrammemes, parseSyntacticReference } from '../../models/languageAPI'; -import { CstMatchMode } from '../../models/miscelanious'; -import { IConstituenta } from '../../models/rsform'; -import { matchConstituenta } from '../../models/rsformAPI'; -import { prefixes } from '../../utils/constants'; -import { compareGrammemeOptions, IGrammemeOption, PremadeWordForms, SelectorGrammems } from '../../utils/selectors'; -import ReferenceTypeButton from './ReferenceTypeButton'; -import WordformButton from './WordformButton'; - -export interface IReferenceInputState { - type: ReferenceType - refRaw?: string - text?: string - mainRefs: string[] - basePosition: number -} - -interface DlgEditReferenceProps { - hideWindow: () => void - items: IConstituenta[] - initial: IReferenceInputState - onSave: (newRef: string) => void -} - -function DlgEditReference({ hideWindow, items, initial, onSave }: DlgEditReferenceProps) { - const [type, setType] = useState(ReferenceType.ENTITY); - - const [nominal, setNominal] = useState(''); - const [offset, setOffset] = useState(1); - - const [selectedCst, setSelectedCst] = useState(undefined); - const [alias, setAlias] = useState(''); - const [term, setTerm] = useState(''); - - const [selectedGrams, setSelectedGrams] = useState([]); - const [gramOptions, setGramOptions] = useState([]); - - const mainLink = useMemo( - () => { - const position = offset > 0 ? initial.basePosition + (offset - 1) : initial.basePosition + offset; - if (offset === 0 || position < 0 || position >= initial.mainRefs.length) { - return 'Некорректное значение смещения'; - } else { - return initial.mainRefs[position]; - } - }, [initial, offset]); - - const isValid = useMemo( - () => { - if (type === ReferenceType.ENTITY) { - return alias !== '' && selectedGrams.length > 0; - } else if (type === ReferenceType.SYNTACTIC) { - return nominal !== '' && offset !== 0; - } else { - return false; - } - }, [type, alias, selectedGrams, nominal, offset]); - - function produceReference(): string { - if (type === ReferenceType.ENTITY) { - return `@{${alias}|${selectedGrams.map(gram => gram.value).join(',')}}`; - } else if (type === ReferenceType.SYNTACTIC) { - return `@{${offset}|${nominal}}`; - } else { - return ''; - } - } - - // Initialization - useLayoutEffect( - () => { - setType(initial.type); - if (initial.refRaw) { - if (initial.type === ReferenceType.ENTITY) { - const ref = parseEntityReference(initial.refRaw); - setAlias(ref.entity); - const grams = parseGrammemes(ref.form); - setSelectedGrams(SelectorGrammems.filter(data => grams.includes(data.value))); - } else if (initial.type === ReferenceType.SYNTACTIC) { - const ref = parseSyntacticReference(initial.refRaw); - setOffset(ref.offset); - setNominal(ref.nominal); - } - } else if (initial.text) { - setNominal(initial.text ?? ''); - } - }, [initial, items]); - - // Filter grammemes when input changes - useEffect( - () => { - const compatible = getCompatibleGrams( - selectedGrams - .filter(data => Object.values(Grammeme).includes(data.value as Grammeme)) - .map(data => data.value as Grammeme) - ); - setGramOptions(SelectorGrammems.filter(({value}) => compatible.includes(value as Grammeme))); - }, [selectedGrams]); - - // Update term when alias changes - useEffect( - () => { - const cst = items.find(item => item.alias === alias) - setTerm(cst?.term_resolved ?? '') - }, [alias, term, items]); - - const handleSubmit = () => onSave(produceReference()); - - function handleSelectConstituenta(cst: IConstituenta) { - setAlias(cst.alias); - setSelectedCst(cst); - } - - const handleSelectGrams = useCallback( - (grams: Grammeme[]) => { - setSelectedGrams(SelectorGrammems.filter(({value}) => grams.includes(value as Grammeme))); - }, []); - - const FormButtons = useMemo(() => { - return ( -
-
- {PremadeWordForms.slice(0, 6).map( - (data, index) => - selectedGrams.find(item => item.value as Grammeme === gram))} - onSelectGrams={handleSelectGrams} - /> - )} -
- -
- {PremadeWordForms.slice(6, 12).map( - (data, index) => - selectedGrams.find(item => item.value as Grammeme === gram))} - onSelectGrams={handleSelectGrams} - /> - )} -
- -
); - }, [handleSelectGrams, selectedGrams]); - - return ( - -
-
- - -
- -
- - - -
- {type === ReferenceType.SYNTACTIC && -
-
- setOffset(event.target.valueAsNumber)} - /> -
- Основная ссылка: -
- -
- setNominal(event.target.value)} - /> -
} - {type === ReferenceType.ENTITY && -
- cst.term_resolved} - matchFunc={(cst, filter) => matchConstituenta(cst, filter, CstMatchMode.TERM)} - prefilterFunc={cst => cst.term_resolved !== ''} - rows={8} - /> - -
- setAlias(event.target.value)} - /> -
-
- Термин: -
- -
-
- {FormButtons} -
-
-
} -
-
); -} - -export default DlgEditReference; +export { default } from './DlgEditReference'; \ No newline at end of file diff --git a/rsconcept/frontend/src/dialogs/DlgEditWordForms.tsx b/rsconcept/frontend/src/dialogs/DlgEditWordForms.tsx index 4e90b1fa..7f0f8722 100644 --- a/rsconcept/frontend/src/dialogs/DlgEditWordForms.tsx +++ b/rsconcept/frontend/src/dialogs/DlgEditWordForms.tsx @@ -1,10 +1,10 @@ import { useEffect, useLayoutEffect, useMemo, useState } from 'react'; -import ConceptTooltip from '../components/Common/ConceptTooltip'; -import MiniButton from '../components/Common/MiniButton'; -import Modal from '../components/Common/Modal'; -import SelectMulti from '../components/Common/SelectMulti'; -import TextArea from '../components/Common/TextArea'; +import ConceptTooltip from '../components/common/ConceptTooltip'; +import MiniButton from '../components/common/MiniButton'; +import Modal from '../components/common/Modal'; +import SelectMulti from '../components/common/SelectMulti'; +import TextArea from '../components/common/TextArea'; import DataTable, { createColumnHelper } from '../components/DataTable'; import HelpTerminologyControl from '../components/Help/HelpTerminologyControl'; import { ArrowLeftIcon, ArrowRightIcon, CheckIcon, ChevronDoubleDownIcon, CrossIcon, HelpIcon } from '../components/Icons'; diff --git a/rsconcept/frontend/src/dialogs/DlgGraphOptions.tsx b/rsconcept/frontend/src/dialogs/DlgGraphOptions.tsx index 74b2f914..050e2cfb 100644 --- a/rsconcept/frontend/src/dialogs/DlgGraphOptions.tsx +++ b/rsconcept/frontend/src/dialogs/DlgGraphOptions.tsx @@ -1,5 +1,5 @@ -import Checkbox from '../components/Common/Checkbox'; -import Modal, { ModalProps } from '../components/Common/Modal'; +import Checkbox from '../components/common/Checkbox'; +import Modal, { ModalProps } from '../components/common/Modal'; import usePartialUpdate from '../hooks/usePartialUpdate'; import { GraphEditorParams } from '../models/miscelanious'; import { CstType } from '../models/rsform'; diff --git a/rsconcept/frontend/src/dialogs/DlgRenameCst.tsx b/rsconcept/frontend/src/dialogs/DlgRenameCst.tsx index 14a23c79..e8b7c528 100644 --- a/rsconcept/frontend/src/dialogs/DlgRenameCst.tsx +++ b/rsconcept/frontend/src/dialogs/DlgRenameCst.tsx @@ -1,8 +1,8 @@ import { useLayoutEffect, useState } from 'react'; -import Modal, { ModalProps } from '../components/Common/Modal'; -import SelectSingle from '../components/Common/SelectSingle'; -import TextInput from '../components/Common/TextInput'; +import Modal, { ModalProps } from '../components/common/Modal'; +import SelectSingle from '../components/common/SelectSingle'; +import TextInput from '../components/common/TextInput'; import { useRSForm } from '../context/RSFormContext'; import usePartialUpdate from '../hooks/usePartialUpdate'; import { CstType, ICstRenameData } from '../models/rsform'; diff --git a/rsconcept/frontend/src/dialogs/DlgShowAST.tsx b/rsconcept/frontend/src/dialogs/DlgShowAST.tsx index 56a8123b..26ba059e 100644 --- a/rsconcept/frontend/src/dialogs/DlgShowAST.tsx +++ b/rsconcept/frontend/src/dialogs/DlgShowAST.tsx @@ -1,7 +1,7 @@ import { useCallback, useMemo, useState } from 'react'; import { GraphCanvas,GraphEdge, GraphNode } from 'reagraph'; -import Modal, { ModalProps } from '../components/Common/Modal'; +import Modal, { ModalProps } from '../components/common/Modal'; import { useConceptTheme } from '../context/ThemeContext'; import { SyntaxTree } from '../models/rslang'; import { graphDarkT, graphLightT } from '../utils/color'; diff --git a/rsconcept/frontend/src/dialogs/DlgUploadRSForm.tsx b/rsconcept/frontend/src/dialogs/DlgUploadRSForm.tsx index 80f422ce..dd19f1dd 100644 --- a/rsconcept/frontend/src/dialogs/DlgUploadRSForm.tsx +++ b/rsconcept/frontend/src/dialogs/DlgUploadRSForm.tsx @@ -1,9 +1,9 @@ import { useState } from 'react'; import { toast } from 'react-toastify'; -import Checkbox from '../components/Common/Checkbox'; -import FileInput from '../components/Common/FileInput'; -import Modal from '../components/Common/Modal'; +import Checkbox from '../components/common/Checkbox'; +import FileInput from '../components/common/FileInput'; +import Modal from '../components/common/Modal'; import { useRSForm } from '../context/RSFormContext'; import { IRSFormUploadData } from '../models/rsform'; import { EXTEOR_TRS_FILE } from '../utils/constants'; diff --git a/rsconcept/frontend/src/pages/CreateRSFormPage.tsx b/rsconcept/frontend/src/pages/CreateRSFormPage.tsx index f8f9e05f..f53c1a7b 100644 --- a/rsconcept/frontend/src/pages/CreateRSFormPage.tsx +++ b/rsconcept/frontend/src/pages/CreateRSFormPage.tsx @@ -3,14 +3,14 @@ import { useLocation } from 'react-router-dom'; import { toast } from 'react-toastify'; import BackendError from '../components/BackendError'; -import Button from '../components/Common/Button'; -import Checkbox from '../components/Common/Checkbox'; -import Form from '../components/Common/Form'; -import Label from '../components/Common/Label'; -import MiniButton from '../components/Common/MiniButton'; -import SubmitButton from '../components/Common/SubmitButton'; -import TextArea from '../components/Common/TextArea'; -import TextInput from '../components/Common/TextInput'; +import Button from '../components/common/Button'; +import Checkbox from '../components/common/Checkbox'; +import Form from '../components/common/Form'; +import Label from '../components/common/Label'; +import MiniButton from '../components/common/MiniButton'; +import SubmitButton from '../components/common/SubmitButton'; +import TextArea from '../components/common/TextArea'; +import TextInput from '../components/common/TextInput'; import { DownloadIcon } from '../components/Icons'; import RequireAuth from '../components/RequireAuth'; import { useLibrary } from '../context/LibraryContext'; diff --git a/rsconcept/frontend/src/pages/LibraryPage/LibraryPage.tsx b/rsconcept/frontend/src/pages/LibraryPage/LibraryPage.tsx new file mode 100644 index 00000000..202ea8e6 --- /dev/null +++ b/rsconcept/frontend/src/pages/LibraryPage/LibraryPage.tsx @@ -0,0 +1,65 @@ +import { useCallback, useLayoutEffect, useState } from 'react'; + +import BackendError from '../../components/BackendError' +import { ConceptLoader } from '../../components/common/ConceptLoader' +import { useLibrary } from '../../context/LibraryContext'; +import { useConceptTheme } from '../../context/ThemeContext'; +import useLocalStorage from '../../hooks/useLocalStorage'; +import { ILibraryItem } from '../../models/library'; +import { ILibraryFilter, LibraryFilterStrategy } from '../../models/miscelanious'; +import SearchPanel from './SearchPanel'; +import ViewLibrary from './ViewLibrary'; + +function LibraryPage() { + const library = useLibrary(); + const { setShowScroll } = useConceptTheme(); + + const [ filter, setFilter ] = useState({}); + const [ items, setItems ] = useState([]); + + const [query, setQuery] = useState(''); + const [strategy, setStrategy] = useLocalStorage('search_strategy', LibraryFilterStrategy.MANUAL); + + useLayoutEffect( + () => { + setShowScroll(true); + return () => setShowScroll(false); + }, [setShowScroll]); + + useLayoutEffect( + () => { + setItems(library.applyFilter(filter)); + }, [library, filter, filter.query]); + + const resetQuery = useCallback( + () => { + setQuery(''); + setFilter({}); + }, []) + + return ( +
+ { library.loading && } + { library.error && } + { !library.loading && library.items && +
+ + +
+ } +
+ ); +} + +export default LibraryPage; diff --git a/rsconcept/frontend/src/pages/LibraryPage/PickerStrategy.tsx b/rsconcept/frontend/src/pages/LibraryPage/PickerStrategy.tsx index cd645267..c71fbcf5 100644 --- a/rsconcept/frontend/src/pages/LibraryPage/PickerStrategy.tsx +++ b/rsconcept/frontend/src/pages/LibraryPage/PickerStrategy.tsx @@ -1,8 +1,8 @@ import { useCallback } from 'react'; -import Dropdown from '../../components/Common/Dropdown'; -import DropdownCheckbox from '../../components/Common/DropdownCheckbox'; -import SelectorButton from '../../components/Common/SelectorButton'; +import Dropdown from '../../components/common/Dropdown'; +import DropdownCheckbox from '../../components/common/DropdownCheckbox'; +import SelectorButton from '../../components/common/SelectorButton'; import { FilterIcon } from '../../components/Icons'; import { useAuth } from '../../context/AuthContext'; import useDropdown from '../../hooks/useDropdown'; diff --git a/rsconcept/frontend/src/pages/LibraryPage/ViewLibrary.tsx b/rsconcept/frontend/src/pages/LibraryPage/ViewLibrary.tsx index 5b15e51a..dc5ae1d5 100644 --- a/rsconcept/frontend/src/pages/LibraryPage/ViewLibrary.tsx +++ b/rsconcept/frontend/src/pages/LibraryPage/ViewLibrary.tsx @@ -1,8 +1,8 @@ import { useMemo } from 'react'; import { useIntl } from 'react-intl'; -import ConceptTooltip from '../../components/Common/ConceptTooltip'; -import TextURL from '../../components/Common/TextURL'; +import ConceptTooltip from '../../components/common/ConceptTooltip'; +import TextURL from '../../components/common/TextURL'; import DataTable, { createColumnHelper } from '../../components/DataTable'; import HelpLibrary from '../../components/Help/HelpLibrary'; import { EducationIcon, GroupIcon, HelpIcon,SubscribedIcon } from '../../components/Icons'; diff --git a/rsconcept/frontend/src/pages/LibraryPage/index.tsx b/rsconcept/frontend/src/pages/LibraryPage/index.tsx index 2cd37733..16248678 100644 --- a/rsconcept/frontend/src/pages/LibraryPage/index.tsx +++ b/rsconcept/frontend/src/pages/LibraryPage/index.tsx @@ -1,65 +1 @@ -import { useCallback, useLayoutEffect, useState } from 'react'; - -import BackendError from '../../components/BackendError' -import { ConceptLoader } from '../../components/Common/ConceptLoader' -import { useLibrary } from '../../context/LibraryContext'; -import { useConceptTheme } from '../../context/ThemeContext'; -import useLocalStorage from '../../hooks/useLocalStorage'; -import { ILibraryItem } from '../../models/library'; -import { ILibraryFilter, LibraryFilterStrategy } from '../../models/miscelanious'; -import SearchPanel from './SearchPanel'; -import ViewLibrary from './ViewLibrary'; - -function LibraryPage() { - const library = useLibrary(); - const { setShowScroll } = useConceptTheme(); - - const [ filter, setFilter ] = useState({}); - const [ items, setItems ] = useState([]); - - const [query, setQuery] = useState(''); - const [strategy, setStrategy] = useLocalStorage('search_strategy', LibraryFilterStrategy.MANUAL); - - useLayoutEffect( - () => { - setShowScroll(true); - return () => setShowScroll(false); - }, [setShowScroll]); - - useLayoutEffect( - () => { - setItems(library.applyFilter(filter)); - }, [library, filter, filter.query]); - - const resetQuery = useCallback( - () => { - setQuery(''); - setFilter({}); - }, []) - - return ( -
- { library.loading && } - { library.error && } - { !library.loading && library.items && -
- - -
- } -
- ); -} - -export default LibraryPage; +export { default } from './LibraryPage'; \ No newline at end of file diff --git a/rsconcept/frontend/src/pages/LoginPage.tsx b/rsconcept/frontend/src/pages/LoginPage.tsx index 07a6dd9e..d5283af9 100644 --- a/rsconcept/frontend/src/pages/LoginPage.tsx +++ b/rsconcept/frontend/src/pages/LoginPage.tsx @@ -3,10 +3,10 @@ import { useEffect, useState } from 'react'; import { useLocation } from 'react-router-dom'; import BackendError, { ErrorInfo } from '../components/BackendError'; -import Form from '../components/Common/Form'; -import SubmitButton from '../components/Common/SubmitButton'; -import TextInput from '../components/Common/TextInput'; -import TextURL from '../components/Common/TextURL'; +import Form from '../components/common/Form'; +import SubmitButton from '../components/common/SubmitButton'; +import TextInput from '../components/common/TextInput'; +import TextURL from '../components/common/TextURL'; import { useAuth } from '../context/AuthContext'; import { useConceptNavigation } from '../context/NagivationContext'; import { useConceptTheme } from '../context/ThemeContext'; diff --git a/rsconcept/frontend/src/pages/ManualsPage/ManualsPage.tsx b/rsconcept/frontend/src/pages/ManualsPage/ManualsPage.tsx new file mode 100644 index 00000000..290ca85a --- /dev/null +++ b/rsconcept/frontend/src/pages/ManualsPage/ManualsPage.tsx @@ -0,0 +1,49 @@ +import { useCallback, useLayoutEffect, useState } from 'react'; +import { useLocation } from 'react-router-dom'; + +import { useConceptNavigation } from '../../context/NagivationContext'; +import { useConceptTheme } from '../../context/ThemeContext'; +import { HelpTopic } from '../../models/miscelanious'; +import TopicsList from './TopicsList'; +import ViewTopic from './ViewTopic'; + +function ManualsPage() { + const { navigateTo } = useConceptNavigation(); + const search = useLocation().search; + const { mainHeight } = useConceptTheme(); + const [activeTopic, setActiveTopic] = useState(HelpTopic.MAIN); + + const navigateTopic = useCallback( + (newTopic: HelpTopic) => { + navigateTo(`/manuals?topic=${newTopic}`); + }, [navigateTo]); + + + function onSelectTopic(newTopic: HelpTopic) { + navigateTopic(newTopic); + } + + useLayoutEffect(() => { + const topic = new URLSearchParams(search).get('topic') as HelpTopic; + if (!Object.values(HelpTopic).includes(topic)) { + navigateTopic(HelpTopic.MAIN); + return; + } else { + setActiveTopic(topic); + } + }, [search, setActiveTopic, navigateTopic]); + + return ( +
+ onSelectTopic(topic)} + /> + +
+ ); +} + +export default ManualsPage; diff --git a/rsconcept/frontend/src/pages/ManualsPage/index.tsx b/rsconcept/frontend/src/pages/ManualsPage/index.tsx index 290ca85a..b6edfb64 100644 --- a/rsconcept/frontend/src/pages/ManualsPage/index.tsx +++ b/rsconcept/frontend/src/pages/ManualsPage/index.tsx @@ -1,49 +1 @@ -import { useCallback, useLayoutEffect, useState } from 'react'; -import { useLocation } from 'react-router-dom'; - -import { useConceptNavigation } from '../../context/NagivationContext'; -import { useConceptTheme } from '../../context/ThemeContext'; -import { HelpTopic } from '../../models/miscelanious'; -import TopicsList from './TopicsList'; -import ViewTopic from './ViewTopic'; - -function ManualsPage() { - const { navigateTo } = useConceptNavigation(); - const search = useLocation().search; - const { mainHeight } = useConceptTheme(); - const [activeTopic, setActiveTopic] = useState(HelpTopic.MAIN); - - const navigateTopic = useCallback( - (newTopic: HelpTopic) => { - navigateTo(`/manuals?topic=${newTopic}`); - }, [navigateTo]); - - - function onSelectTopic(newTopic: HelpTopic) { - navigateTopic(newTopic); - } - - useLayoutEffect(() => { - const topic = new URLSearchParams(search).get('topic') as HelpTopic; - if (!Object.values(HelpTopic).includes(topic)) { - navigateTopic(HelpTopic.MAIN); - return; - } else { - setActiveTopic(topic); - } - }, [search, setActiveTopic, navigateTopic]); - - return ( -
- onSelectTopic(topic)} - /> - -
- ); -} - -export default ManualsPage; +export { default } from './ManualsPage'; \ No newline at end of file diff --git a/rsconcept/frontend/src/pages/NotFoundPage.tsx b/rsconcept/frontend/src/pages/NotFoundPage.tsx index f8906642..a50c5ba0 100644 --- a/rsconcept/frontend/src/pages/NotFoundPage.tsx +++ b/rsconcept/frontend/src/pages/NotFoundPage.tsx @@ -1,4 +1,4 @@ -import TextURL from '../components/Common/TextURL'; +import TextURL from '../components/common/TextURL'; export function NotFoundPage() { return ( diff --git a/rsconcept/frontend/src/pages/RSFormPage/EditorConstituenta.tsx b/rsconcept/frontend/src/pages/RSFormPage/EditorConstituenta.tsx index 962c5eae..8c297473 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/EditorConstituenta.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/EditorConstituenta.tsx @@ -1,10 +1,10 @@ import { Dispatch, SetStateAction, useLayoutEffect, useMemo, useState } from 'react'; import { toast } from 'react-toastify'; -import ConceptTooltip from '../../components/Common/ConceptTooltip'; -import MiniButton from '../../components/Common/MiniButton'; -import SubmitButton from '../../components/Common/SubmitButton'; -import TextArea from '../../components/Common/TextArea'; +import ConceptTooltip from '../../components/common/ConceptTooltip'; +import MiniButton from '../../components/common/MiniButton'; +import SubmitButton from '../../components/common/SubmitButton'; +import TextArea from '../../components/common/TextArea'; import HelpConstituenta from '../../components/Help/HelpConstituenta'; import { ArrowsRotateIcon, CloneIcon, DumpBinIcon, EditIcon, HelpIcon, SaveIcon, SmallPlusIcon } from '../../components/Icons'; import RefsInput from '../../components/RefsInput'; diff --git a/rsconcept/frontend/src/pages/RSFormPage/EditorItems.tsx b/rsconcept/frontend/src/pages/RSFormPage/EditorItems.tsx index e674d0fd..94c54b09 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/EditorItems.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/EditorItems.tsx @@ -2,7 +2,7 @@ import { useCallback, useLayoutEffect, useMemo, useState } from 'react'; import { toast } from 'react-toastify'; import DataTable, { createColumnHelper, type RowSelectionState,VisibilityState } from '../../components/DataTable'; -import ConstituentaBadge from '../../components/Shared/ConstituentaBadge'; +import ConstituentaBadge from '../../components/shared/ConstituentaBadge'; import { useRSForm } from '../../context/RSFormContext'; import { useConceptTheme } from '../../context/ThemeContext'; import useWindowSize from '../../hooks/useWindowSize'; diff --git a/rsconcept/frontend/src/pages/RSFormPage/EditorRSExpression.tsx b/rsconcept/frontend/src/pages/RSFormPage/EditorRSExpression.tsx index 2b72dc9e..9116f3ac 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/EditorRSExpression.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/EditorRSExpression.tsx @@ -2,9 +2,9 @@ import { ReactCodeMirrorRef } from '@uiw/react-codemirror'; import { useCallback, useLayoutEffect, useRef, useState } from 'react'; import { toast } from 'react-toastify'; -import Button from '../../components/Common/Button'; -import { ConceptLoader } from '../../components/Common/ConceptLoader'; -import MiniButton from '../../components/Common/MiniButton'; +import Button from '../../components/common/Button'; +import { ConceptLoader } from '../../components/common/ConceptLoader'; +import MiniButton from '../../components/common/MiniButton'; import { ASTNetworkIcon } from '../../components/Icons'; import RSInput from '../../components/RSInput'; import { RSTextWrapper } from '../../components/RSInput/textEditing'; diff --git a/rsconcept/frontend/src/pages/RSFormPage/EditorRSForm.tsx b/rsconcept/frontend/src/pages/RSFormPage/EditorRSForm.tsx index 3d490f25..2f5e9496 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/EditorRSForm.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/EditorRSForm.tsx @@ -2,13 +2,13 @@ import { Dispatch, SetStateAction, useLayoutEffect, useState } from 'react'; import { useIntl } from 'react-intl'; import { toast } from 'react-toastify'; -import Checkbox from '../../components/Common/Checkbox'; -import ConceptTooltip from '../../components/Common/ConceptTooltip'; -import Divider from '../../components/Common/Divider'; -import MiniButton from '../../components/Common/MiniButton'; -import SubmitButton from '../../components/Common/SubmitButton'; -import TextArea from '../../components/Common/TextArea'; -import TextInput from '../../components/Common/TextInput'; +import Checkbox from '../../components/common/Checkbox'; +import ConceptTooltip from '../../components/common/ConceptTooltip'; +import Divider from '../../components/common/Divider'; +import MiniButton from '../../components/common/MiniButton'; +import SubmitButton from '../../components/common/SubmitButton'; +import TextArea from '../../components/common/TextArea'; +import TextInput from '../../components/common/TextInput'; import HelpRSFormMeta from '../../components/Help/HelpRSFormMeta'; import { DownloadIcon, DumpBinIcon, HelpIcon, OwnerIcon, SaveIcon, ShareIcon } from '../../components/Icons'; import { useAuth } from '../../context/AuthContext'; diff --git a/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph.tsx b/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph.tsx index 4851527d..68ed9653 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/EditorTermGraph.tsx @@ -3,9 +3,9 @@ import { GraphCanvas, GraphCanvasRef, GraphEdge, GraphNode, LayoutTypes, Sphere, useSelection } from 'reagraph'; -import ConceptTooltip from '../../components/Common/ConceptTooltip'; -import MiniButton from '../../components/Common/MiniButton'; -import SelectSingle from '../../components/Common/SelectSingle'; +import ConceptTooltip from '../../components/common/ConceptTooltip'; +import MiniButton from '../../components/common/MiniButton'; +import SelectSingle from '../../components/common/SelectSingle'; import ConstituentaTooltip from '../../components/Help/ConstituentaTooltip'; import HelpTermGraph from '../../components/Help/HelpTermGraph'; import InfoConstituenta from '../../components/Help/InfoConstituenta'; diff --git a/rsconcept/frontend/src/pages/RSFormPage/RSFormPage.tsx b/rsconcept/frontend/src/pages/RSFormPage/RSFormPage.tsx new file mode 100644 index 00000000..ae9a5c34 --- /dev/null +++ b/rsconcept/frontend/src/pages/RSFormPage/RSFormPage.tsx @@ -0,0 +1,15 @@ +import { useParams } from 'react-router-dom'; + +import { RSFormState } from '../../context/RSFormContext'; +import RSTabs from './RSTabs'; + +function RSFormPage() { + const { id } = useParams(); + return ( + + + + ); +} + +export default RSFormPage; diff --git a/rsconcept/frontend/src/pages/RSFormPage/RSTabs.tsx b/rsconcept/frontend/src/pages/RSFormPage/RSTabs.tsx index 9664ef3d..058eb520 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/RSTabs.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/RSTabs.tsx @@ -6,9 +6,9 @@ import { TabList, TabPanel, Tabs } from 'react-tabs'; import { toast } from 'react-toastify'; import BackendError, { ErrorInfo } from '../../components/BackendError'; -import { ConceptLoader } from '../../components/Common/ConceptLoader'; -import ConceptTab from '../../components/Common/ConceptTab'; -import TextURL from '../../components/Common/TextURL'; +import { ConceptLoader } from '../../components/common/ConceptLoader'; +import ConceptTab from '../../components/common/ConceptTab'; +import TextURL from '../../components/common/TextURL'; import { useLibrary } from '../../context/LibraryContext'; import { useConceptNavigation } from '../../context/NagivationContext'; import { useRSForm } from '../../context/RSFormContext'; diff --git a/rsconcept/frontend/src/pages/RSFormPage/elements/RSFormStats.tsx b/rsconcept/frontend/src/pages/RSFormPage/elements/RSFormStats.tsx index addbc5a2..3e092ce3 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/elements/RSFormStats.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/elements/RSFormStats.tsx @@ -1,5 +1,5 @@ -import Divider from '../../../components/Common/Divider'; -import LabeledText from '../../../components/Common/LabeledText'; +import Divider from '../../../components/common/Divider'; +import LabeledText from '../../../components/common/LabeledText'; import { type IRSFormStats } from '../../../models/rsform'; interface RSFormStatsProps { diff --git a/rsconcept/frontend/src/pages/RSFormPage/elements/RSItemsMenu.tsx b/rsconcept/frontend/src/pages/RSFormPage/elements/RSItemsMenu.tsx index f5bcc22c..fb9ecc99 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/elements/RSItemsMenu.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/elements/RSItemsMenu.tsx @@ -1,9 +1,9 @@ import { useMemo } from 'react'; -import ConceptTooltip from '../../../components/Common/ConceptTooltip'; -import Dropdown from '../../../components/Common/Dropdown'; -import DropdownButton from '../../../components/Common/DropdownButton'; -import MiniButton from '../../../components/Common/MiniButton'; +import ConceptTooltip from '../../../components/common/ConceptTooltip'; +import Dropdown from '../../../components/common/Dropdown'; +import DropdownButton from '../../../components/common/DropdownButton'; +import MiniButton from '../../../components/common/MiniButton'; import HelpRSFormItems from '../../../components/Help/HelpRSFormItems'; import { ArrowDownIcon, ArrowDropdownIcon, ArrowUpIcon, CloneIcon, DiamondIcon, DumpBinIcon, HelpIcon, SmallPlusIcon,UpdateIcon } from '../../../components/Icons'; import { useRSForm } from '../../../context/RSFormContext'; diff --git a/rsconcept/frontend/src/pages/RSFormPage/elements/RSTabsMenu.tsx b/rsconcept/frontend/src/pages/RSFormPage/elements/RSTabsMenu.tsx index a3fd8988..6aace2e1 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/elements/RSTabsMenu.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/elements/RSTabsMenu.tsx @@ -1,9 +1,9 @@ import { useNavigate } from 'react-router-dom'; -import Button from '../../../components/Common/Button'; -import Dropdown from '../../../components/Common/Dropdown'; -import DropdownButton from '../../../components/Common/DropdownButton'; -import DropdownCheckbox from '../../../components/Common/DropdownCheckbox'; +import Button from '../../../components/common/Button'; +import Dropdown from '../../../components/common/Dropdown'; +import DropdownButton from '../../../components/common/DropdownButton'; +import DropdownCheckbox from '../../../components/common/DropdownCheckbox'; import { CloneIcon, DownloadIcon, DumpBinIcon, EditIcon, MenuIcon, NotSubscribedIcon, OwnerIcon, ShareIcon, SmallPlusIcon, SubscribedIcon, UploadIcon diff --git a/rsconcept/frontend/src/pages/RSFormPage/elements/ViewSideConstituents.tsx b/rsconcept/frontend/src/pages/RSFormPage/elements/ViewSideConstituents.tsx index 7565f2be..cee24fff 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/elements/ViewSideConstituents.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/elements/ViewSideConstituents.tsx @@ -1,11 +1,11 @@ import { useCallback, useLayoutEffect, useMemo, useState } from 'react'; -import Dropdown from '../../../components/Common/Dropdown'; -import DropdownButton from '../../../components/Common/DropdownButton'; -import SelectorButton from '../../../components/Common/SelectorButton'; +import Dropdown from '../../../components/common/Dropdown'; +import DropdownButton from '../../../components/common/DropdownButton'; +import SelectorButton from '../../../components/common/SelectorButton'; import DataTable, { createColumnHelper, IConditionalStyle, VisibilityState } from '../../../components/DataTable'; import { CogIcon, FilterIcon, MagnifyingGlassIcon } from '../../../components/Icons'; -import ConstituentaBadge from '../../../components/Shared/ConstituentaBadge'; +import ConstituentaBadge from '../../../components/shared/ConstituentaBadge'; import { useRSForm } from '../../../context/RSFormContext'; import { useConceptTheme } from '../../../context/ThemeContext'; import useDropdown from '../../../hooks/useDropdown'; diff --git a/rsconcept/frontend/src/pages/RSFormPage/index.tsx b/rsconcept/frontend/src/pages/RSFormPage/index.tsx index ae9a5c34..a395905e 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/index.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/index.tsx @@ -1,15 +1 @@ -import { useParams } from 'react-router-dom'; - -import { RSFormState } from '../../context/RSFormContext'; -import RSTabs from './RSTabs'; - -function RSFormPage() { - const { id } = useParams(); - return ( - - - - ); -} - -export default RSFormPage; +export { default } from './RSFormPage'; \ No newline at end of file diff --git a/rsconcept/frontend/src/pages/RegisterPage.tsx b/rsconcept/frontend/src/pages/RegisterPage.tsx index bc8a782d..b0b92b75 100644 --- a/rsconcept/frontend/src/pages/RegisterPage.tsx +++ b/rsconcept/frontend/src/pages/RegisterPage.tsx @@ -3,10 +3,10 @@ import { useLocation } from 'react-router-dom'; import { toast } from 'react-toastify'; import BackendError from '../components/BackendError'; -import Button from '../components/Common/Button'; -import Form from '../components/Common/Form'; -import SubmitButton from '../components/Common/SubmitButton'; -import TextInput from '../components/Common/TextInput'; +import Button from '../components/common/Button'; +import Form from '../components/common/Form'; +import SubmitButton from '../components/common/SubmitButton'; +import TextInput from '../components/common/TextInput'; import { useAuth } from '../context/AuthContext'; import { useConceptNavigation } from '../context/NagivationContext'; import { type IUserSignupData } from '../models/library'; diff --git a/rsconcept/frontend/src/pages/UserProfilePage/EditorPassword.tsx b/rsconcept/frontend/src/pages/UserProfilePage/EditorPassword.tsx index 9018a250..545a7c05 100644 --- a/rsconcept/frontend/src/pages/UserProfilePage/EditorPassword.tsx +++ b/rsconcept/frontend/src/pages/UserProfilePage/EditorPassword.tsx @@ -3,8 +3,8 @@ import { useEffect, useMemo, useState } from 'react'; import { toast } from 'react-toastify'; import BackendError, { ErrorInfo } from '../../components/BackendError'; -import SubmitButton from '../../components/Common/SubmitButton'; -import TextInput from '../../components/Common/TextInput'; +import SubmitButton from '../../components/common/SubmitButton'; +import TextInput from '../../components/common/TextInput'; import { useAuth } from '../../context/AuthContext'; import { useConceptNavigation } from '../../context/NagivationContext'; import { IUserUpdatePassword } from '../../models/library'; diff --git a/rsconcept/frontend/src/pages/UserProfilePage/EditorProfile.tsx b/rsconcept/frontend/src/pages/UserProfilePage/EditorProfile.tsx index 5e93062b..bdaf3996 100644 --- a/rsconcept/frontend/src/pages/UserProfilePage/EditorProfile.tsx +++ b/rsconcept/frontend/src/pages/UserProfilePage/EditorProfile.tsx @@ -1,8 +1,8 @@ import { useLayoutEffect, useState } from 'react'; import { toast } from 'react-toastify'; -import SubmitButton from '../../components/Common/SubmitButton'; -import TextInput from '../../components/Common/TextInput'; +import SubmitButton from '../../components/common/SubmitButton'; +import TextInput from '../../components/common/TextInput'; import { useUserProfile } from '../../context/UserProfileContext'; import useModificationPrompt from '../../hooks/useModificationPrompt'; import { IUserUpdateData } from '../../models/library'; diff --git a/rsconcept/frontend/src/pages/UserProfilePage/UserProfilePage.tsx b/rsconcept/frontend/src/pages/UserProfilePage/UserProfilePage.tsx new file mode 100644 index 00000000..764e7f96 --- /dev/null +++ b/rsconcept/frontend/src/pages/UserProfilePage/UserProfilePage.tsx @@ -0,0 +1,15 @@ +import RequireAuth from '../../components/RequireAuth'; +import { UserProfileState } from '../../context/UserProfileContext'; +import UserTabs from './UserTabs'; + +function UserProfilePage() { + return ( + + + + + + ); +} + +export default UserProfilePage; diff --git a/rsconcept/frontend/src/pages/UserProfilePage/UserTabs.tsx b/rsconcept/frontend/src/pages/UserProfilePage/UserTabs.tsx index dededeeb..780bb618 100644 --- a/rsconcept/frontend/src/pages/UserProfilePage/UserTabs.tsx +++ b/rsconcept/frontend/src/pages/UserProfilePage/UserTabs.tsx @@ -1,8 +1,8 @@ import { useMemo, useState } from 'react'; import BackendError from '../../components/BackendError'; -import { ConceptLoader } from '../../components/Common/ConceptLoader'; -import MiniButton from '../../components/Common/MiniButton'; +import { ConceptLoader } from '../../components/common/ConceptLoader'; +import MiniButton from '../../components/common/MiniButton'; import { NotSubscribedIcon,SubscribedIcon } from '../../components/Icons'; import { useAuth } from '../../context/AuthContext'; import { useLibrary } from '../../context/LibraryContext'; diff --git a/rsconcept/frontend/src/pages/UserProfilePage/index.tsx b/rsconcept/frontend/src/pages/UserProfilePage/index.tsx index 764e7f96..9c821034 100644 --- a/rsconcept/frontend/src/pages/UserProfilePage/index.tsx +++ b/rsconcept/frontend/src/pages/UserProfilePage/index.tsx @@ -1,15 +1 @@ -import RequireAuth from '../../components/RequireAuth'; -import { UserProfileState } from '../../context/UserProfileContext'; -import UserTabs from './UserTabs'; - -function UserProfilePage() { - return ( - - - - - - ); -} - -export default UserProfilePage; +export { default } from './UserProfilePage'; \ No newline at end of file