diff --git a/api-editor/gui/src/app/App.tsx b/api-editor/gui/src/app/App.tsx index abdcd0747..7e93d5a7d 100644 --- a/api-editor/gui/src/app/App.tsx +++ b/api-editor/gui/src/app/App.tsx @@ -169,7 +169,7 @@ const App: React.FC = function () { {currentUserAction.type === 'rename' && } - + {showAnnotationImportDialog && } diff --git a/api-editor/gui/src/features/packageData/packageDataSlice.ts b/api-editor/gui/src/features/packageData/packageDataSlice.ts index e7acb6f6a..ded123926 100644 --- a/api-editor/gui/src/features/packageData/packageDataSlice.ts +++ b/api-editor/gui/src/features/packageData/packageDataSlice.ts @@ -30,6 +30,12 @@ const packageDataSlice = createSlice({ state.expandedInTreeView[action.payload] = true; } }, + expandParents(state, action: PayloadAction) { + const parents = action.payload; + for (const parent of parents) { + state.expandedInTreeView[parent] = true; + } + }, setScrollOffset(state, action: PayloadAction) { state.treeViewScrollOffset = action.payload; }, @@ -42,6 +48,7 @@ const packageDataSlice = createSlice({ const { actions, reducer } = packageDataSlice; export const { toggleIsExpanded: toggleIsExpandedInTreeView, + expandParents: expandParentsInTreeView, setScrollOffset: setTreeViewScrollOffset, toggleImportDialog: togglePackageDataImportDialog, } = actions; diff --git a/api-editor/gui/src/features/packageData/selectionView/SelectionView.tsx b/api-editor/gui/src/features/packageData/selectionView/SelectionView.tsx index c61f04b7e..3b91d7f58 100644 --- a/api-editor/gui/src/features/packageData/selectionView/SelectionView.tsx +++ b/api-editor/gui/src/features/packageData/selectionView/SelectionView.tsx @@ -1,6 +1,6 @@ -import { Box } from '@chakra-ui/react'; +import { Box, Button, HStack, Spacer, VStack } from '@chakra-ui/react'; import React from 'react'; -import { useLocation } from 'react-router'; +import { useLocation, useNavigate } from 'react-router'; import PythonClass from '../model/PythonClass'; import PythonFunction from '../model/PythonFunction'; import PythonModule from '../model/PythonModule'; @@ -10,34 +10,164 @@ import ClassView from './ClassView'; import FunctionView from './FunctionView'; import ModuleView from './ModuleView'; import ParameterView from './ParameterView'; +import { expandParentsInTreeView } from '../packageDataSlice'; +import { useAppDispatch, useAppSelector } from '../../../app/hooks'; +import PythonDeclaration from '../model/PythonDeclaration'; +import AbstractPythonFilter from '../model/filters/AbstractPythonFilter'; +import { AnnotationsState, selectAnnotations } from '../../annotations/annotationSlice'; interface SelectionViewProps { pythonPackage: PythonPackage; + pythonFilter: AbstractPythonFilter; } -const SelectionView: React.FC = function ({ - pythonPackage, -}) { - const declaration = pythonPackage.getByRelativePath( - useLocation().pathname.split('/').splice(2), - ); +const SelectionView: React.FC = function ({ pythonPackage, pythonFilter }) { + const dispatch = useAppDispatch(); + const navigate = useNavigate(); + + const declaration = pythonPackage.getByRelativePath(useLocation().pathname.split('/').splice(2)); + const annotations = useAppSelector(selectAnnotations); + + if (!declaration) { + return <>; + } return ( - - {declaration instanceof PythonFunction && ( - - )} - {declaration instanceof PythonClass && ( - - )} - {declaration instanceof PythonModule && ( - - )} - {declaration instanceof PythonParameter && ( - - )} - + + + + {declaration instanceof PythonFunction && } + {declaration instanceof PythonClass && } + {declaration instanceof PythonModule && } + {declaration instanceof PythonParameter && } + + + + + + + + + + ); }; +const getNextElementPath = function ( + current: PythonDeclaration, + filter: AbstractPythonFilter, + annotations: AnnotationsState, +): string | null { + const nextElement = getNextElementInTree(current); + if (nextElement != null) { + if (filter.shouldKeepDeclaration(nextElement, annotations)) { + return nextElement.pathAsString(); + } + return getNextElementPath(nextElement, filter, annotations); + } + return null; +}; + +const getNextElementInTree = function (current: PythonDeclaration): PythonDeclaration | null { + if (current.children().length > 0) { + return current.children()[0]; + } else if (current.parent() != null) { + return getNextFromParentInTree(current); + } + return null; +}; + +const getNextFromParentInTree = function (current: PythonDeclaration): PythonDeclaration | null { + if (current instanceof PythonPackage && current.children().length > 0) { + return current.children()[0]; + } + const parent = current.parent(); + if (parent != null) { + const index = parent.children().indexOf(current); + if (parent.children().length > index + 1) { + return parent.children()[index + 1]; + } + return getNextFromParentInTree(parent); + } + return null; +}; + +const getPreviousElementPath = function ( + current: PythonDeclaration, + filter: AbstractPythonFilter, + annotations: AnnotationsState, +): string | null { + const previousElement = getPreviousElementInTree(current); + if (previousElement != null) { + if (filter.shouldKeepDeclaration(previousElement, annotations)) { + return previousElement.pathAsString(); + } + return getPreviousElementPath(previousElement, filter, annotations); + } + return null; +}; + +const getPreviousElementInTree = function (current: PythonDeclaration): PythonDeclaration | null { + const parent = current.parent(); + if (parent != null) { + const index = parent.children().indexOf(current); + if (index > 0) { + return getLastElementInTree(parent.children()[index - 1]); + } + if (parent instanceof PythonPackage) { + return getLastElementInTree(parent); + } + return parent; + } + return null; +}; + +const getLastElementInTree = function (current: PythonDeclaration): PythonDeclaration { + if (current.children().length > 0) { + return getLastElementInTree(current.children()[current.children().length - 1]); + } + return current; +}; + +const getParents = function (navStr: string, filteredPythonPackage: PythonPackage): string[] { + const parents: string[] = []; + let currentElement = filteredPythonPackage.getByRelativePathAsString(navStr); + if (currentElement != null) { + currentElement = currentElement.parent(); + while (currentElement != null) { + parents.push(currentElement.pathAsString()); + currentElement = currentElement.parent(); + } + } + return parents; +}; + export default SelectionView;