Skip to content
This repository has been archived by the owner on Nov 29, 2023. It is now read-only.

Parameter view und breadcrump mit auswahl in tree view synchronisieren #66

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 9 additions & 16 deletions client/src/Components/App/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,21 @@ import React, {useState} from 'react';
import './App.css';
import ParameterView from "../ParameterView/ParameterView";
import TreeView from "../TreeView/TreeView";
import PythonFunction from "../../model/PythonFunction";
import PythonParameter from "../../model/PythonParameter";
import PythonDeclaration from "../../model/PythonDeclaration";
import {parsePythonPackageJson, PythonPackageJson} from "../../model/PythonPackageBuilder";
import packageJson from "../../data/sklearn.json";

function App(): JSX.Element {
export default function App(): JSX.Element {

const [parameters, setParameters] = useState<PythonParameter[]>([]);
const [selection, setSelection] = useState<string[]>([]);
const [selectedFunction, setSelectedFunction] = useState<Nullable<PythonFunction>>(null);
const pythonPackage = parsePythonPackageJson(packageJson as PythonPackageJson);
const [selection, setSelection] = useState<PythonDeclaration>(pythonPackage);

return (
<div className="App">
<TreeView setParameters={setParameters}
<TreeView pythonPackage={pythonPackage}
selection={selection}
setSelection={setSelection}
setSelectedFunction={setSelectedFunction}
/>
<ParameterView inputParameters={parameters}
selection={selection}
selectedFunction={selectedFunction}
/>
setSelection={setSelection}/>
<ParameterView selection={selection}/>
</div>
);
}

export default App;
41 changes: 17 additions & 24 deletions client/src/Components/ParameterView/ParameterView.tsx
Original file line number Diff line number Diff line change
@@ -1,50 +1,43 @@
import ParameterNode from "./ParameterNode";
import React from "react";
import PythonParameter from "../../model/PythonParameter";
import PythonFunction from "../../model/PythonFunction";
import DocumentationText from "./DocumentationText";
import {Breadcrumb} from "react-bootstrap";
import PythonDeclaration from "../../model/PythonDeclaration";

type ParameterViewProps = {
inputParameters: PythonParameter[],
selection: string[],
selectedFunction: Nullable<PythonFunction>
selection: PythonDeclaration
};

export default function ParameterView({inputParameters, selection, selectedFunction}: ParameterViewProps): JSX.Element {

const hasInputParameters = inputParameters.length > 0;
export default function ParameterView({selection}: ParameterViewProps): JSX.Element {

return (
<div className="parameter-view">
<div className="parameter-view-path">
<Breadcrumb>
{(!selection || selection.length === 0) && (
{(!selection || selection.path().length === 0) && (
<Breadcrumb.Item active>Nothing selected.</Breadcrumb.Item>
)}
{selection.map((name, index) => (
{selection.path().map((name, index) => (
<Breadcrumb.Item active key={index}>{name}</Breadcrumb.Item>
))}
</Breadcrumb>
</div>
{selectedFunction !== null &&

{selection instanceof PythonFunction &&
<>
<h1>{selectedFunction.name}</h1>
<DocumentationText inputText={selectedFunction.description}/>
<h1>{selection.name}</h1>
<DocumentationText inputText={selection.description}/>
<h2 className={"parameter-title"}>Parameters</h2>
{
selection.parameters ?
selection.parameters.map(function (parameters) {
return (<ParameterNode key={parameters.name} inputParameter={parameters}/>);
}) :
<span>There are no Parameters.</span>
}
</>
}

<h2 className={"parameter-title"}>Parameters</h2>
{
inputParameters?.map(function (parameters) {
return (<ParameterNode key={parameters.name} inputParameter={parameters}/>);
})
}
{
!hasInputParameters &&
<span>There are no Parameters.</span>
}

</div>
);
}
45 changes: 16 additions & 29 deletions client/src/Components/Tree/ClassNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,68 +3,55 @@ import PythonClass from "../../model/PythonClass";
import classNames from "classnames";
import FunctionNode from "./FunctionNode";
import {isEmptyList} from "../../util/listOperations";
import PythonFunction from "../../model/PythonFunction";
import PythonParameter from "../../model/PythonParameter";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {faChalkboard} from "@fortawesome/free-solid-svg-icons";
import VisibilityIndicator from "../Util/VisibilityIndicator";
import PythonDeclaration from "../../model/PythonDeclaration";

type ClassNodeProps = {
parentPath: string[],
pythonClass: PythonClass,
selection: string[],
setSelection: (newValue: string[]) => void,
selection: PythonDeclaration,
setSelection: Setter<PythonDeclaration>,
moduleName: string,
setParameters: Setter<PythonParameter[]>,
setSelectedFunction: Setter<Nullable<PythonFunction>>
}
};

export default function ClassNode({
parentPath,
pythonClass,
selection,
setSelection,
setParameters,
setSelectedFunction
}: ClassNodeProps): JSX.Element {
export default function ClassNode({pythonClass,
selection,
setSelection}: ClassNodeProps): JSX.Element {

const [childVisible, setChildVisibility] = useState(false);
const hasMethods = !isEmptyList(pythonClass.methods);
const path = parentPath.concat(pythonClass.name);
const cssClasses = classNames(
"tree-view-row", {
"text-muted": !hasMethods,
"cursor-na": !hasMethods,
"pl-3-5rem": !hasMethods,
"pl-3rem": hasMethods,
"selected": (selection.join() === path.join()) && hasMethods,
"selected": (selection.path().join() === pythonClass.path().join()) && hasMethods
}
);

const handleClick = function () {
setSelection(pythonClass);
setChildVisibility(!childVisible);
};

return (
<div className="class-node">
<div className={cssClasses}
onClick={() => {
setSelection(path);
setChildVisibility(!childVisible);
setSelectedFunction(null);
}}>
onClick={handleClick}>
<VisibilityIndicator hasChildren={hasMethods} childrenVisible={childVisible}/>
<FontAwesomeIcon icon={faChalkboard}/>
{" "}
<span> {pythonClass.name} </span>
</div>
{hasMethods && childVisible && <div>
{pythonClass.methods.map(method => (
<FunctionNode parentPath={path}
key={method.name}
<FunctionNode key={method.name}
pythonFunction={method}
selection={selection}
setSelection={setSelection}
isMethod={true}
setParameters={setParameters}
setSelectedFunction={setSelectedFunction}
/>
isMethod={true}/>
))}
</div>}
</div>
Expand Down
41 changes: 15 additions & 26 deletions client/src/Components/Tree/FunctionNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,40 @@ import React from "react";
import PythonFunction from "../../model/PythonFunction";
import classNames from "classnames";
import {isEmptyList} from "../../util/listOperations";
import PythonParameter from "../../model/PythonParameter";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {faCogs} from "@fortawesome/free-solid-svg-icons";
import PythonDeclaration from "../../model/PythonDeclaration";

type FunctionNodeProps = {
pythonFunction: PythonFunction,
selection: string[],
setSelection: (newValue: string[]) => void,
setParameters: Setter<PythonParameter[]>,
isMethod?: boolean,

/** A parent of a Python class can be a class or a Python module. */
parentPath: string[],
setSelectedFunction: Setter<Nullable<PythonFunction>>
selection: PythonDeclaration,
setSelection: Setter<PythonDeclaration>,
isMethod?: boolean
}

export default function FunctionNode({
pythonFunction,
selection,
setSelection,
setParameters,
parentPath,
isMethod = false,
setSelectedFunction
}: FunctionNodeProps): JSX.Element {
export default function FunctionNode({pythonFunction,
selection,
setSelection,
isMethod = false}: FunctionNodeProps): JSX.Element {

const path = parentPath.concat(pythonFunction.name);
const hasParameters = !isEmptyList(pythonFunction.parameters);
const cssClasses = classNames(
"tree-view-row", {
"text-muted": !hasParameters,
"pl-3-5rem": !isMethod,
"pl-5rem": isMethod,
"selected": (selection.join() === path.join()) && hasParameters
"selected": (selection.path().join() === pythonFunction.path().join()) && hasParameters
}
);

const handleClick = function() {
setSelection(pythonFunction);
};

return (
<div className="function-node">
<div className={cssClasses}
onClick={() => {
setSelection(path);
setParameters(pythonFunction.parameters);
setSelectedFunction(pythonFunction);
}}>
onClick={handleClick}>
<FontAwesomeIcon icon={faCogs}/>
{" "}
<span>
Expand Down
54 changes: 17 additions & 37 deletions client/src/Components/Tree/ModuleNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,21 @@ import FunctionNode from "./FunctionNode";
import {isEmptyList} from "../../util/listOperations";
import classNames from "classnames";
import PythonModule from "../../model/PythonModule";
import PythonFunction from "../../model/PythonFunction";
import PythonParameter from "../../model/PythonParameter";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {faArchive} from "@fortawesome/free-solid-svg-icons";
import VisibilityIndicator from "../Util/VisibilityIndicator";
import PythonDeclaration from "../../model/PythonDeclaration";

type ModuleNodeProps = {
parentPath: string[],
pythonModule: PythonModule,
selection: string[],
setSelection: Setter<string[]>,
setParameters: Setter<PythonParameter[]>,
setSelectedFunction: Setter<Nullable<PythonFunction>>
}

export default function ModuleNode({
parentPath,
pythonModule,
selection,
setSelection,
setParameters,
setSelectedFunction
}: ModuleNodeProps): JSX.Element {
selection: PythonDeclaration,
setSelection: Setter<PythonDeclaration>
};

/** This is the Name of this module without its packages name prefixed. */
export default function ModuleNode({pythonModule,
selection,
setSelection}: ModuleNodeProps): JSX.Element {

const [, ...moduleName] = pythonModule.name.split(".");

const path = parentPath.concat(moduleName);
const [childVisible, setChildVisibility] = useState(false);
const hasClasses = !isEmptyList(pythonModule.classes);
const hasFunctions = !isEmptyList(pythonModule.functions);
Expand All @@ -44,17 +30,19 @@ export default function ModuleNode({
"cursor-na": !hasChildren,
"pl-2rem": !hasChildren,
"pl-1-5rem": hasChildren,
"selected": (selection.join() === path.join()) && hasChildren,
"selected": (selection.path().join() === pythonModule.path().join()) && hasChildren
}
);

const handleClick = function() {
setSelection(pythonModule);
setChildVisibility(!childVisible);
};

return (
<div className="module-node">
<div className={cssClasses}
onClick={() => {
setSelection(path);
setChildVisibility(!childVisible);
}}>
onClick={handleClick}>
<VisibilityIndicator hasChildren={hasClasses || hasFunctions} childrenVisible={childVisible}/>
<FontAwesomeIcon icon={faArchive} />
{" "}
Expand All @@ -66,26 +54,18 @@ export default function ModuleNode({
{hasClasses && childVisible && <div>
{pythonModule.classes.map(moduleClass => (
<ClassNode key={moduleClass.name}
parentPath={path}
pythonClass={moduleClass}
selection={selection}
setSelection={setSelection}
moduleName={pythonModule.name}
setParameters={setParameters}
setSelectedFunction={setSelectedFunction}
/>
moduleName={pythonModule.name}/>
))}
</div>}
{hasFunctions && childVisible && <div>
{pythonModule.functions.map(moduleFunction => (
<FunctionNode parentPath={path}
key={moduleFunction.name}
<FunctionNode key={moduleFunction.name}
pythonFunction={moduleFunction}
selection={selection}
setSelection={setSelection}
setParameters={setParameters}
setSelectedFunction={setSelectedFunction}
/>
setSelection={setSelection}/>
))}
</div>}
</div>
Expand Down
Loading