Skip to content

Commit

Permalink
WID-100: add functionality to display the description of the componen…
Browse files Browse the repository at this point in the history
…t arguments
  • Loading branch information
rarescodemart committed Dec 5, 2022
1 parent 2daab9e commit a42d19d
Show file tree
Hide file tree
Showing 11 changed files with 195 additions and 19 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,7 @@ labextension/
mlruns/

# Pytorch dataset default dir
data
data

# pycharm files
/.idea/
8 changes: 6 additions & 2 deletions src/components/CustomNodeModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,13 @@ export class CustomNodeModel extends DefaultNodeModel {
this.extras=event.data.extras;
}

addOutPortEnhance(label: string, name: string, after: boolean = true, id?: string): CustomPortModel {
addOutPortEnhance(label: string, name: string, after: boolean = true, id?: string, description: string = ""): CustomPortModel {

//check if portID is passed, if not SR will generate a new port ID
const p = (id) ? new CustomPortModel({in: false, name: name, label: label, id:id}) :
new CustomPortModel({in: false, name: name, label: label});

p.description = description;

if (!after) {
this.portsOut.splice(0, 0, p);
Expand All @@ -54,12 +56,14 @@ export class CustomNodeModel extends DefaultNodeModel {
return this.addPort(p);
}

addInPortEnhance(label: string, name: string, after: boolean = true, id?: string): CustomPortModel {
addInPortEnhance(label: string, name: string, after: boolean = true, id?: string, description: string = ""): CustomPortModel {

//check if portID is passed, if not SR will generate a new port ID
const p = (id) ? new CustomPortModel({in: true, name: name, label: label, id:id}) :
new CustomPortModel({in: true, name: name, label: label});

p.description = description;

if (!after) {
this.portsOut.splice(0, 0, p);
}
Expand Down
47 changes: 42 additions & 5 deletions src/components/CustomNodeWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,7 @@ export interface DefaultNodeProps {
*/
export class CustomNodeWidget extends React.Component<DefaultNodeProps> {

generatePort = (port) => {
return <CustomPortLabel engine={this.props.engine} port={port} key={port.getID()} node={this.props.node} />;
};

element:Object;
state = {

Expand All @@ -127,7 +125,46 @@ export class CustomNodeWidget extends React.Component<DefaultNodeProps> {
original: 'https://picsum.photos/id/1019/1000/600/',
thumbnail: 'https://picsum.photos/id/1019/250/150/'
},
]
],
showParamDescriptionList: new Array(this.props.node.getInPorts().length + this.props.node.getOutPorts().length).fill(false)
};

/**
* creates a particular function for each component so that it can set only it's state
* @param id
*/
setShowParamDescription = (id : number) => {
const _setShowParamDescription = (newShowDescription : boolean) => {
this.setState({
showParamDescriptionList: this.state.showParamDescriptionList.map((value, index) => (
id === index ? newShowDescription : false
)
)
})
}
return _setShowParamDescription;
}

generatePort = (port, index) => {
const argumentDescriptions = this.props.node['extras']['argumentDescriptions'];

const description = argumentDescriptions && (port.getOptions().label in argumentDescriptions) ? argumentDescriptions[port.getOptions().label] : "";

const isOutPort = port.getOptions().name.includes('parameter-out');

index = isOutPort ? index + this.props.node.getInPorts().length: index;

return (
<CustomPortLabel
engine={this.props.engine}
port={port}
key={port.getID()}
node={this.props.node}
showDescription={this.state.showParamDescriptionList[index]}
setShowDescription={this.setShowParamDescription(index)}
description={description}
/>
);
};

showTooltip() {
Expand Down Expand Up @@ -295,7 +332,7 @@ export class CustomNodeWidget extends React.Component<DefaultNodeProps> {
/>
</label>
</S.Title>
<S.Ports>
<S.Ports>{/*aici se pun intrarile*/}
<S.PortsContainer>{_.map(this.props.node.getInPorts(), this.generatePort)}</S.PortsContainer>
<S.PortsContainer>{_.map(this.props.node.getOutPorts(), this.generatePort)}</S.PortsContainer>
</S.Ports>
Expand Down
14 changes: 13 additions & 1 deletion src/components/port/CustomPortLabel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@ import * as React from 'react';
import { DiagramEngine, PortWidget } from '@projectstorm/react-diagrams-core';
import { DefaultNodeModel, DefaultPortModel } from "@projectstorm/react-diagrams";
import styled from '@emotion/styled';
import WithToggle from "./WithToggle";


export interface CustomPortLabelProps {
port: DefaultPortModel;
engine: DiagramEngine;
node: DefaultNodeModel;
showDescription: boolean;
setShowDescription: any;
description : string;
}

namespace S {
Expand Down Expand Up @@ -122,7 +127,14 @@ export class CustomPortLabel extends React.Component<CustomPortLabelProps> {

const label = (
<S.Label>
{this.props.port.getOptions().label}
<WithToggle
renderToggleBeforeChildren={!this.props.port.getOptions().in}
showDescription={this.props.showDescription}
setShowDescription={this.props.setShowDescription}
description={this.props.description}
>
{this.props.port.getOptions().label}
</WithToggle>
</S.Label>);

return (
Expand Down
11 changes: 11 additions & 0 deletions src/components/port/CustomPortModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@ import {PortModel} from "@projectstorm/react-diagrams-core";
*/
export class CustomPortModel extends DefaultPortModel {

private _description : string;

get description(): string {
return this._description;
}

set description(value: string) {
this._description = value;
}



canLinkToPort(port: PortModel): boolean {
if (port instanceof DefaultPortModel) {
Expand Down
52 changes: 52 additions & 0 deletions src/components/port/WithToggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import * as React from "react";
import Toggle from 'react-toggle'
import {useRef} from "react";
import {WithToggleProps} from "./types";
import ToolTip from 'react-portal-tooltip';


export default function WithToggle(props: WithToggleProps){
const ref = useRef(null);

return (
<div ref ={ref} className="alignToggle">
{props.renderToggleBeforeChildren ?
<>
{
props.description &&
<Toggle
className='description'
name='Description'
checked={props.showDescription}
onChange={() => props.setShowDescription(!props.showDescription)}
/>
}
<span>
{props.children}
</span>
</>
:
<>
<span>
{props.children}
</span>
{
props.description &&
<Toggle
className='description'
name='Description'
checked={props.showDescription}
onChange={() => props.setShowDescription(!props.showDescription)}
/>
}
</>
}

{props.showDescription &&
<ToolTip active={props.showDescription} position="left" arrow="center" parent={ref.current}>
<div>{props.description}</div>
</ToolTip>
}
</div>
)
}
13 changes: 13 additions & 0 deletions src/components/port/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import {ReactElement} from "react";

export type WithToggleProps = {
renderToggleBeforeChildren : boolean;
children: ReactElement[] | ReactElement | string;
showDescription: boolean;
setShowDescription: any;
description: string;
}

export type WithToggleState = {
showDescription : boolean
}
20 changes: 13 additions & 7 deletions src/tray_library/AdvanceComponentLib.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ export function AdvancedComponentLibrary(props: AdvancedComponentLibraryProps) {
extras: {
"type": nodeData.type,
"path": nodeData.file_path,
"description": nodeData.docstring,
"description": nodeData["json_description"]["description"] || nodeData.docstring,
"argumentDescriptions" : nodeData["json_description"]["arguments"],
"lineNo": nodeData.lineno
}
});
Expand All @@ -44,19 +45,24 @@ export function AdvancedComponentLibrary(props: AdvancedComponentLibraryProps) {
"str": "string"
}

nodeData["variables"].forEach(variable => {
let name = variable["name"];
let type = type_name_remappings[variable["type"]] || variable["type"];
const argumentDescriptions = nodeData["json_description"]["arguments"];


nodeData["variables"].forEach((variable, _) => {
const name = variable["name"];
const type = type_name_remappings[variable["type"]] || variable["type"];

const description = argumentDescriptions ? argumentDescriptions[name] || "" : "";

switch (variable["kind"]) {
case "InCompArg":
node.addInPortEnhance(`★${name}`, `parameter-${type}-${name}`);
node.addInPortEnhance(`★${name}`, `parameter-${type}-${name}`, true, null, description);
break;
case "InArg":
node.addInPortEnhance(name, `parameter-${type}-${name}`);
node.addInPortEnhance(name, `parameter-${type}-${name}`, true, null, description);
break;
case "OutArg":
node.addOutPortEnhance(name, `parameter-out-${type}-${name}`);
node.addOutPortEnhance(name, `parameter-out-${type}-${name}`, true, null, description);
break;
default:
console.warn("Unknown variable kind for variable", variable)
Expand Down
13 changes: 13 additions & 0 deletions style/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,17 @@ input[type=number]::-webkit-inner-spin-button {
/* Fix arrow position of HTMLSelect tag on run dialog */
.jp-Dialog-content .f1ozlkqi {
position: relative;
}

.alignToggle {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
}

.alignToggle span, div {
display: inline-block;
padding: 0;
margin: 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"description" : "keras_transfer_learning description",
"arguments" : {
"base_model_name" : "base_model_name description",
"include_top" : "include_top description",
"weights" : "weights description",
"input_shape" : "input_shape description",
"freeze_all" : "freeze_all description",
"fine_tune_from" : "fine_tune_from description",
"classes" : "classes description",
"binary" : "binary description",
"classifier_activation" : "classifier_activation description",
"kwargs" : "kwargs description",
"model" : "model description"
}
}
15 changes: 12 additions & 3 deletions xircuits/handlers/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ def get(self):
"error_msg" : error_msg}

self.finish(json.dumps(data))

def get_component_directories(self):
paths = list(DEFAULT_COMPONENTS_PATHS)
paths.append(get_config().get("DEV", "BASE_PATH"))
Expand All @@ -151,7 +151,7 @@ def get_component_directories(self):
def extract_components(self, file_path, base_dir, python_path):
with open(file_path) as f:
lines = f.readlines()

parse_tree = ast.parse(file_path.read_text(), file_path)
# Look for top level class definitions that are decorated with "@xai_component"
is_xai_component = lambda node: isinstance(node, ast.ClassDef) and \
Expand All @@ -175,7 +175,7 @@ def extract_component(self, node: ast.ClassDef, file_path, file_lines, python_pa
is_arg = lambda n: isinstance(n, ast.AnnAssign) and \
isinstance(n.annotation, ast.Subscript) and \
n.annotation.value.id in ('InArg', 'InCompArg', 'OutArg')

python_version = platform.python_version_tuple()
if int(python_version[1]) == 8:
variables = [
Expand Down Expand Up @@ -205,6 +205,14 @@ def extract_component(self, node: ast.ClassDef, file_path, file_lines, python_pa
}
]


description = {}
path = os.path.join("xai_components", os.path.dirname(file_path), "description", str(node.name).lower() + ".json")
if os.path.isfile(path):
with open(path) as file:
description = json.load(file)


output = {
"class": name,
"package_name": ("xai_components." if python_path is None else "") + file_path.as_posix().replace("/", ".")[:-3],
Expand All @@ -216,6 +224,7 @@ def extract_component(self, node: ast.ClassDef, file_path, file_lines, python_pa
"category": category,
"type": "debug",
"variables": variables,
"json_description": description,
"docstring": docstring,
"lineno" : lineno
}
Expand Down

0 comments on commit a42d19d

Please sign in to comment.