diff --git a/rsconcept/frontend/src/components/select/PickInlineSubstitutions.tsx b/rsconcept/frontend/src/components/select/PickInlineSubstitutions.tsx new file mode 100644 index 00000000..fcf9c5dc --- /dev/null +++ b/rsconcept/frontend/src/components/select/PickInlineSubstitutions.tsx @@ -0,0 +1,273 @@ +'use client'; + +import { useCallback, useMemo, useState } from 'react'; + +import BadgeConstituenta from '@/components/info/BadgeConstituenta'; +import SelectConstituenta from '@/components/select/SelectConstituenta'; +import DataTable, { createColumnHelper } from '@/components/ui/DataTable'; +import Label from '@/components/ui/Label'; +import MiniButton from '@/components/ui/MiniButton'; +import { useConceptOptions } from '@/context/ConceptOptionsContext'; +import { IBinarySubstitution, IConstituenta, IRSForm } from '@/models/rsform'; +import { describeConstituenta } from '@/utils/labels'; + +import { + IconKeepAliasOff, + IconKeepAliasOn, + IconKeepTermOff, + IconKeepTermOn, + IconPageFirst, + IconPageLast, + IconPageLeft, + IconPageRight, + IconRemove, + IconReplace +} from '../Icons'; +import NoData from '../ui/NoData'; + +interface PickInlineSubstitutionsProps { + prefixID: string; + rows?: number; + + schema1?: IRSForm; + schema2?: IRSForm; + filter1?: (cst: IConstituenta) => boolean; + filter2?: (cst: IConstituenta) => boolean; + + items: IBinarySubstitution[]; + setItems: React.Dispatch>; +} + +function SubstitutionIcon({ item }: { item: IBinarySubstitution }) { + if (item.deleteRight) { + if (item.takeLeftTerm) { + return ; + } else { + return ; + } + } else { + if (item.takeLeftTerm) { + return ; + } else { + return ; + } + } +} + +const columnHelper = createColumnHelper(); + +function PickInlineSubstitutions({ + items, + schema1, + schema2, + filter1, + filter2, + rows, + setItems, + prefixID +}: PickInlineSubstitutionsProps) { + const { colors } = useConceptOptions(); + + const [leftCst, setLeftCst] = useState(undefined); + const [rightCst, setRightCst] = useState(undefined); + const [deleteRight, setDeleteRight] = useState(true); + const [takeLeftTerm, setTakeLeftTerm] = useState(true); + + const toggleDelete = () => setDeleteRight(prev => !prev); + const toggleTerm = () => setTakeLeftTerm(prev => !prev); + + function addSubstitution() { + if (!leftCst || !rightCst) { + return; + } + const newSubstitution: IBinarySubstitution = { + leftCst: leftCst, + rightCst: rightCst, + deleteRight: deleteRight, + takeLeftTerm: takeLeftTerm + }; + setItems([ + newSubstitution, + ...items.filter( + item => + (!item.deleteRight && item.leftCst.id !== leftCst.id) || + (item.deleteRight && item.rightCst.id !== rightCst.id) + ) + ]); + } + + const handleDeleteRow = useCallback( + (row: number) => { + setItems(prev => { + const newItems: IBinarySubstitution[] = []; + prev.forEach((item, index) => { + if (index !== row) { + newItems.push(item); + } + }); + return newItems; + }); + }, + [setItems] + ); + + const columns = useMemo( + () => [ + columnHelper.accessor(item => describeConstituenta(item.leftCst), { + id: 'left_text', + header: 'Описание', + size: 1000, + cell: props =>
{props.getValue()}
+ }), + columnHelper.accessor(item => item.leftCst.alias, { + id: 'left_alias', + header: () => Имя, + size: 65, + cell: props => ( + + ) + }), + columnHelper.display({ + id: 'status', + header: '', + size: 40, + cell: props => + }), + columnHelper.accessor(item => item.rightCst.alias, { + id: 'right_alias', + header: () => Имя, + size: 65, + cell: props => ( + + ) + }), + columnHelper.accessor(item => describeConstituenta(item.rightCst), { + id: 'right_text', + header: 'Описание', + minSize: 1000, + cell: props =>
{props.getValue()}
+ }), + columnHelper.display({ + id: 'actions', + cell: props => ( + } + onClick={() => handleDeleteRow(props.row.index)} + /> + ) + }) + ], + [handleDeleteRow, colors, prefixID] + ); + + return ( +
+
+
+
+
+ !filter1 || filter1(cst))} + value={leftCst} + onSelectValue={setLeftCst} + /> +
+ + } + disabled={!leftCst || !rightCst || leftCst === rightCst} + onClick={addSubstitution} + /> + +
+
+
+ !filter2 || filter2(cst))} + value={rightCst} + onSelectValue={setRightCst} + /> +
+
+ + +

Список пуст

+

Добавьте отождествление

+ + } + /> +
+ ); +} + +export default PickInlineSubstitutions; diff --git a/rsconcept/frontend/src/components/select/PickSubstitutions.tsx b/rsconcept/frontend/src/components/select/PickSubstitutions.tsx index 88e6eadc..d8303aad 100644 --- a/rsconcept/frontend/src/components/select/PickSubstitutions.tsx +++ b/rsconcept/frontend/src/components/select/PickSubstitutions.tsx @@ -5,74 +5,100 @@ import { useCallback, useMemo, useState } from 'react'; import BadgeConstituenta from '@/components/info/BadgeConstituenta'; import SelectConstituenta from '@/components/select/SelectConstituenta'; import DataTable, { createColumnHelper } from '@/components/ui/DataTable'; -import Label from '@/components/ui/Label'; import MiniButton from '@/components/ui/MiniButton'; import { useConceptOptions } from '@/context/ConceptOptionsContext'; -import { IConstituenta, IRSForm, ISingleSubstitution } from '@/models/rsform'; -import { describeConstituenta } from '@/utils/labels'; +import { LibraryItemID } from '@/models/library'; +import { ICstSubstitute, IMultiSubstitution, IOperation } from '@/models/oss'; +import { ConstituentaID, IConstituenta, IRSForm } from '@/models/rsform'; import { IconKeepAliasOff, IconKeepAliasOn, IconKeepTermOff, IconKeepTermOn, - IconPageFirst, IconPageLast, - IconPageLeft, IconPageRight, IconRemove, IconReplace } from '../Icons'; import NoData from '../ui/NoData'; +import SelectOperation from './SelectOperation'; + +function SubstitutionIcon({ item, className }: { item: IMultiSubstitution; className?: string }) { + if (!item.transfer_term) { + return ; + } else { + return ; + } +} interface PickSubstitutionsProps { prefixID: string; rows?: number; - schema1?: IRSForm; - schema2?: IRSForm; - filter1?: (cst: IConstituenta) => boolean; - filter2?: (cst: IConstituenta) => boolean; - - items: ISingleSubstitution[]; - setItems: React.Dispatch>; + operations: IOperation[]; + getSchema: (id: LibraryItemID) => IRSForm | undefined; + getConstituenta: (id: ConstituentaID) => IConstituenta | undefined; + getSchemaByCst: (id: ConstituentaID) => IRSForm | undefined; + substitutions: ICstSubstitute[]; + setSubstitutions: React.Dispatch>; } -function SubstitutionIcon({ item }: { item: ISingleSubstitution }) { - if (item.deleteRight) { - if (item.takeLeftTerm) { - return ; - } else { - return ; - } - } else { - if (item.takeLeftTerm) { - return ; - } else { - return ; - } - } -} - -const columnHelper = createColumnHelper(); +const columnHelper = createColumnHelper(); function PickSubstitutions({ - items, - schema1, - schema2, - filter1, - filter2, + prefixID, rows, - setItems, - prefixID + operations, + getSchema, + getConstituenta, + getSchemaByCst, + substitutions, + setSubstitutions }: PickSubstitutionsProps) { const { colors } = useConceptOptions(); + const [leftArgument, setLeftArgument] = useState(undefined); + const [rightArgument, setRightArgument] = useState(undefined); + const leftSchema = useMemo( + () => (leftArgument?.result ? getSchema(leftArgument.result) : undefined), + [leftArgument, getSchema] + ); + + const rightSchema = useMemo( + () => (rightArgument?.result ? getSchema(rightArgument.result) : undefined), + [rightArgument, getSchema] + ); const [leftCst, setLeftCst] = useState(undefined); const [rightCst, setRightCst] = useState(undefined); + const [deleteRight, setDeleteRight] = useState(true); const [takeLeftTerm, setTakeLeftTerm] = useState(true); + const operationByConstituenta = useCallback( + (cst: ConstituentaID): IOperation | undefined => { + const schema = getSchemaByCst(cst); + if (!schema) { + return undefined; + } + const cstOperations = operations.filter(item => item.result === schema.id); + return cstOperations.length === 1 ? cstOperations[0] : undefined; + }, + [getSchemaByCst, operations] + ); + + const substitutionData: IMultiSubstitution[] = useMemo( + () => + substitutions.map(item => ({ + original_operation: operationByConstituenta(item.original), + original: getConstituenta(item.original), + substitution: getConstituenta(item.substitution), + substitution_operation: operationByConstituenta(item.substitution), + transfer_term: item.transfer_term + })), + [getConstituenta, operationByConstituenta, substitutions] + ); + const toggleDelete = () => setDeleteRight(prev => !prev); const toggleTerm = () => setTakeLeftTerm(prev => !prev); @@ -80,26 +106,20 @@ function PickSubstitutions({ if (!leftCst || !rightCst) { return; } - const newSubstitution: ISingleSubstitution = { - leftCst: leftCst, - rightCst: rightCst, - deleteRight: deleteRight, - takeLeftTerm: takeLeftTerm + const newSubstitution: ICstSubstitute = { + original: deleteRight ? rightCst.id : leftCst.id, + substitution: deleteRight ? leftCst.id : rightCst.id, + transfer_term: deleteRight != takeLeftTerm }; - setItems([ - newSubstitution, - ...items.filter( - item => - (!item.deleteRight && item.leftCst.id !== leftCst.id) || - (item.deleteRight && item.rightCst.id !== rightCst.id) - ) - ]); + setSubstitutions(prev => [...prev, newSubstitution]); + setLeftCst(undefined); + setRightCst(undefined); } const handleDeleteRow = useCallback( (row: number) => { - setItems(prev => { - const newItems: ISingleSubstitution[] = []; + setSubstitutions(prev => { + const newItems: ICstSubstitute[] = []; prev.forEach((item, index) => { if (index !== row) { newItems.push(item); @@ -108,24 +128,27 @@ function PickSubstitutions({ return newItems; }); }, - [setItems] + [setSubstitutions] ); const columns = useMemo( () => [ - columnHelper.accessor(item => describeConstituenta(item.leftCst), { - id: 'left_text', - header: 'Описание', - size: 1000, - cell: props =>
{props.getValue()}
+ columnHelper.accessor(item => item.substitution_operation?.alias ?? 'N/A', { + id: 'left_schema', + header: 'Операция', + size: 100, + cell: props =>
{props.getValue()}
}), - columnHelper.accessor(item => item.leftCst.alias, { + columnHelper.accessor(item => item.substitution?.alias ?? 'N/A', { id: 'left_alias', header: () => Имя, size: 65, - cell: props => ( - - ) + cell: props => + props.row.original.substitution ? ( + + ) : ( + 'N/A' + ) }), columnHelper.display({ id: 'status', @@ -133,29 +156,34 @@ function PickSubstitutions({ size: 40, cell: props => }), - columnHelper.accessor(item => item.rightCst.alias, { + columnHelper.accessor(item => item.original?.alias ?? 'N/A', { id: 'right_alias', header: () => Имя, size: 65, - cell: props => ( - - ) + cell: props => + props.row.original.original ? ( + + ) : ( + 'N/A' + ) }), - columnHelper.accessor(item => describeConstituenta(item.rightCst), { - id: 'right_text', - header: 'Описание', - minSize: 1000, - cell: props =>
{props.getValue()}
+ columnHelper.accessor(item => item.original_operation?.alias ?? 'N/A', { + id: 'right_schema', + header: 'Операция', + size: 100, + cell: props =>
{props.getValue()}
}), columnHelper.display({ id: 'actions', cell: props => ( - } - onClick={() => handleDeleteRow(props.row.index)} - /> +
+ } + onClick={() => handleDeleteRow(props.row.index)} + /> +
) }) ], @@ -165,41 +193,47 @@ function PickSubstitutions({ return (
-
-
-