From 062f64e828a902d65b51323f1870d699b9547f53 Mon Sep 17 00:00:00 2001 From: AdrySky Date: Fri, 15 Apr 2022 11:57:24 +0800 Subject: [PATCH 01/11] Add docstring data to node --- src/tray_library/AdvanceComponentLib.tsx | 5 +++-- src/tray_library/Sidebar.tsx | 6 ++++-- xircuits/handlers/components.py | 5 ++++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/tray_library/AdvanceComponentLib.tsx b/src/tray_library/AdvanceComponentLib.tsx index 38a9d582..f9b3937d 100644 --- a/src/tray_library/AdvanceComponentLib.tsx +++ b/src/tray_library/AdvanceComponentLib.tsx @@ -30,7 +30,8 @@ export function AdvancedComponentLibrary(props: AdvancedComponentLibraryProps) { color: nodeData.color, extras: { "type": nodeData.type, - "path": nodeData.file_path + "path": nodeData.file_path, + "description": nodeData.docstring } }); node.addInPortEnhance('▶', 'in-0'); @@ -42,7 +43,7 @@ export function AdvancedComponentLibrary(props: AdvancedComponentLibraryProps) { "str": "string" } - props.model["variables"].forEach(variable => { + nodeData["variables"].forEach(variable => { let name = variable["name"]; let type = type_name_remappings[variable["type"]] || variable["type"]; diff --git a/src/tray_library/Sidebar.tsx b/src/tray_library/Sidebar.tsx index 5e1b7f34..c335960f 100644 --- a/src/tray_library/Sidebar.tsx +++ b/src/tray_library/Sidebar.tsx @@ -220,7 +220,8 @@ export default function Sidebar(props: SidebarProps) { type: componentVal.type, name: componentVal.task, color: componentVal.color, - path: componentVal.file_path + path: componentVal.file_path, + docstring: componentVal.docstring }} name={componentVal.task} color={componentVal.color} @@ -251,7 +252,8 @@ export default function Sidebar(props: SidebarProps) { type: val.type, name: val.task, color: val.color, - path: val.file_path + path: val.file_path, + docstring: val.docstring }} name={val.task} color={val.color} diff --git a/xircuits/handlers/components.py b/xircuits/handlers/components.py index d3b9327b..e5de7f5a 100644 --- a/xircuits/handlers/components.py +++ b/xircuits/handlers/components.py @@ -157,6 +157,8 @@ def extract_component(self, node: ast.ClassDef, file_path, python_path): for v in node.body if is_arg(v) ] + docstring = ast.get_docstring(node) + output = { "class": name, "package_name": ("xai_components." if python_path is None else "") + file_path.as_posix().replace("/", ".")[:-3], @@ -167,7 +169,8 @@ def extract_component(self, node: ast.ClassDef, file_path, python_path): "header": GROUP_ADVANCED, "category": category, "type": "debug", - "variables": variables + "variables": variables, + "docstring": docstring } output.update(keywords) From 87043c3779b097798265b4f5df0da0a38d12ad83 Mon Sep 17 00:00:00 2001 From: AdrySky Date: Fri, 15 Apr 2022 12:00:02 +0800 Subject: [PATCH 02/11] Add tooltip to display component's docstring --- src/components/CustomNodeWidget.tsx | 46 +++++++++++++++++++++++++++++ style/ComponentInfo.css | 14 +++++++++ style/icons/3-vertical-dot.svg | 8 +++++ style/index.css | 3 +- style/index.js | 3 +- style/toggle.css | 8 +++++ 6 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 style/ComponentInfo.css create mode 100644 style/icons/3-vertical-dot.svg diff --git a/src/components/CustomNodeWidget.tsx b/src/components/CustomNodeWidget.tsx index 1f6bf832..4d998534 100644 --- a/src/components/CustomNodeWidget.tsx +++ b/src/components/CustomNodeWidget.tsx @@ -53,6 +53,14 @@ var S; font-size: 12px; border: solid 2px ${(p) => p.selected ? 'rgb(0,192,255)':'black'}; padding: 5px; + `; + + S.DescriptionName = styled.div<{ color:string }>` + color: ${(p) => p.color ?? 'rgb(0, 0, 0)'}; + text-align: justify; + font-family: 'Roboto', sans-serif; + font-weight: 700; + font-size: 13px; `; S.Ports = styled.div` @@ -100,6 +108,7 @@ export class CustomNodeWidget extends React.Component { isTooltipActive: false, nodeDeletable: false, commentInput: this.props.node['extras']['commentInput'], + showDescription: false, imageGalleryItems:[ { @@ -188,6 +197,31 @@ export class CustomNodeWidget extends React.Component { this.handleOnChangeCanvas(); } + tooltipStyle = { + style: { + background: 'rgb(255,255,255)', + maxWidth: 450, + maxHeight: 250, + borderRadius: 10, + border: '2px solid rgba(0, 253, 232,.5)', + padding: '20px 20px 0px 20px', + overflow: 'auto', + boxShadow: '5px 5px 3px rgba(0,0,0,.5)' + }, + arrowStyle: { + visibility:'hidden' + } + } + /** + * Show/Hide Component's Description Tooltip + */ + handleDescription() { + const noDescription = No description provided; + const nodeDescription = this.props.node['extras']['description']; + this.props.node.getOptions().extras["descrpt"] = nodeDescription ?? noDescription; + this.setState({showDescription:!this.state.showDescription}); + } + render() { if(this.props.node.getOptions().extras["tip"]!=undefined&&this.props.node.getOptions().extras["tip"]!=""){ @@ -286,11 +320,17 @@ export class CustomNodeWidget extends React.Component { else if(this.props.node.getOptions()["name"] !== 'Start' && this.props.node.getOptions()["name"] !== 'Finish'){ return ( { this.element = element }} borderColor={this.props.node.getOptions().extras["borderColor"]} data-default-node-name={this.props.node.getOptions().name} selected={this.props.node.isSelected()} background={this.props.node.getOptions().color} onDoubleClick={this.handleEditLiteral.bind(this)}> + + {this.props.node.getOptions()["name"]} +

Description:

+
{this.props.node.getOptions().extras["descrpt"]}
+
{this.props.node.getOptions().name} diff --git a/style/ComponentInfo.css b/style/ComponentInfo.css new file mode 100644 index 00000000..5453be29 --- /dev/null +++ b/style/ComponentInfo.css @@ -0,0 +1,14 @@ +.description-text{ + text-align: justify; + font-family: sans-serif; + font-weight: 400; + font-size: 11px; + white-space:pre-wrap; +} + +.description-title{ + text-align: justify; + font-family: 'Roboto', sans-serif; + font-weight: 700; + font-size: 13px; +} \ No newline at end of file diff --git a/style/icons/3-vertical-dot.svg b/style/icons/3-vertical-dot.svg new file mode 100644 index 00000000..49411ed7 --- /dev/null +++ b/style/icons/3-vertical-dot.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/style/index.css b/style/index.css index f5f12d1a..347f7c47 100644 --- a/style/index.css +++ b/style/index.css @@ -3,4 +3,5 @@ @import url('Sidebar.css'); @import url('ComponentsPanel.css'); @import url('NodeActionPanel.css'); -@import url('Comment.css'); \ No newline at end of file +@import url('Comment.css'); +@import url('ComponentInfo.css'); diff --git a/style/index.js b/style/index.js index 94250c56..7675a73d 100644 --- a/style/index.js +++ b/style/index.js @@ -3,4 +3,5 @@ import './toggle.css'; import './Sidebar.css'; import './ComponentsPanel.css'; import './NodeActionPanel.css'; -import './Comment.css'; \ No newline at end of file +import './Comment.css'; +import './ComponentInfo.css'; diff --git a/style/toggle.css b/style/toggle.css index d73efcc1..b6bff1c1 100644 --- a/style/toggle.css +++ b/style/toggle.css @@ -147,4 +147,12 @@ background-color: #128D15; .lock.react-toggle--checked .react-toggle-track { background: url(../style/icons/lock-nodes.svg) no-repeat; +} + +.description.react-toggle .react-toggle-track { + background: url(../style/icons/3-vertical-dot.svg) no-repeat; +} + +.description.react-toggle--checked .react-toggle-track { + background: url(../style/icons/3-vertical-dot.svg) #FAFAFA no-repeat; } \ No newline at end of file From 5fafd97e94753142422a6f4b8ff6517156afd921 Mon Sep 17 00:00:00 2001 From: AdrySky Date: Thu, 21 Apr 2022 11:44:32 +0800 Subject: [PATCH 03/11] Use react-tooltip for node description tooltip --- package.json | 3 +- src/components/CustomNodeWidget.tsx | 43 ++++++++++++++++++++++------- style/ComponentInfo.css | 21 ++++++++++++-- 3 files changed, 54 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 1637f895..37400e16 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,8 @@ "react-sanity-pagination": "^2.0.2", "react-switch": "^6.0.0", "react-textarea-autosize": "^8.3.3", - "react-toggle": "^4.1.2" + "react-toggle": "^4.1.2", + "react-tooltip": "^4.2.21" }, "devDependencies": { "@babel/core": "^7.12.10", diff --git a/src/components/CustomNodeWidget.tsx b/src/components/CustomNodeWidget.tsx index 4d998534..95fbe9b5 100644 --- a/src/components/CustomNodeWidget.tsx +++ b/src/components/CustomNodeWidget.tsx @@ -17,6 +17,7 @@ import { Dialog } from '@jupyterlab/apputils'; import { formDialogWidget } from '../dialog/formDialogwidget'; import { showFormDialog } from '../dialog/FormDialog'; import { CommentDialog } from '../dialog/CommentDialog'; +import ReactTooltip from 'react-tooltip'; var S; (function (S) { @@ -212,29 +213,30 @@ export class CustomNodeWidget extends React.Component { visibility:'hidden' } } + /** * Show/Hide Component's Description Tooltip */ - handleDescription() { - const noDescription = No description provided; - const nodeDescription = this.props.node['extras']['description']; - this.props.node.getOptions().extras["descrpt"] = nodeDescription ?? noDescription; - this.setState({showDescription:!this.state.showDescription}); + async handleDescription() { + await this.setState({ showDescription: !this.state.showDescription }); + ReactTooltip.show(this.element as Element) } render() { - - if(this.props.node.getOptions().extras["tip"]!=undefined&&this.props.node.getOptions().extras["tip"]!=""){ + if (this.props.node.getOptions()["name"] !== 'Start' && this.props.node.getOptions()["name"] !== 'Finish') { return ( + <> { this.element = element }} + ref={(element) => this.element = element} + // Data for description's tooltip + data-tip data-for={this.props.node.getOptions().id} borderColor={this.props.node.getOptions().extras["borderColor"]} data-default-node-name={this.props.node.getOptions().name} selected={this.props.node.isSelected()} - background={this.props.node.getOptions().color}> - + background={this.props.node.getOptions().color} + onDoubleClick={this.handleEditLiteral.bind(this)}>

{this.props.node.getOptions().extras["tip"]}

@@ -245,6 +247,12 @@ export class CustomNodeWidget extends React.Component { checked={this.props.node.isLocked()} onChange={this.handleDeletableNode.bind(this, 'nodeDeletable')} /> + @@ -252,6 +260,21 @@ export class CustomNodeWidget extends React.Component { {_.map(this.props.node.getOutPorts(), this.generatePort)}
+ {this.state.showDescription && { this.setState({ showDescription: true }) }} + afterHide={() => { this.setState({ showDescription: false }) }} + delayHide={60000} + getContent={() => +
+ {this.props.node.getOptions()["name"]} +

Description:

+
{this.props.node['extras']['description'] ?? No description provided}
+
+ } + />} + ); } else if(this.props.node.getOptions().extras["imageGalleryItems"] != undefined){ diff --git a/style/ComponentInfo.css b/style/ComponentInfo.css index 5453be29..5297bb2f 100644 --- a/style/ComponentInfo.css +++ b/style/ComponentInfo.css @@ -1,9 +1,25 @@ +.description-tooltip{ + background-color: rgb(255, 255, 255) !important; + box-shadow: 5px 5px 3px rgba(0,0,0,.5) !important; + border: 2px solid rgba(0, 253, 232, .5) !important; + border-radius: 10 !important; + opacity: 0.99 !important; +} + +.description-container{ + max-width: 450px; + max-height: 250px; + overflow: auto; +} + .description-text{ text-align: justify; font-family: sans-serif; - font-weight: 400; + font-weight: 500; font-size: 11px; - white-space:pre-wrap; + white-space: pre-wrap; + cursor: default; + color: rgb(0, 0, 0); } .description-title{ @@ -11,4 +27,5 @@ font-family: 'Roboto', sans-serif; font-weight: 700; font-size: 13px; + color: rgb(0, 0, 0); } \ No newline at end of file From 97d9c1edf7fcbd5ad22676a0b3c48a0fb5d8792a Mon Sep 17 00:00:00 2001 From: AdrySky Date: Thu, 21 Apr 2022 11:45:34 +0800 Subject: [PATCH 04/11] Update style for error tooltip --- src/components/CustomNodeWidget.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/components/CustomNodeWidget.tsx b/src/components/CustomNodeWidget.tsx index 95fbe9b5..21a8c6b6 100644 --- a/src/components/CustomNodeWidget.tsx +++ b/src/components/CustomNodeWidget.tsx @@ -198,19 +198,16 @@ export class CustomNodeWidget extends React.Component { this.handleOnChangeCanvas(); } - tooltipStyle = { + errorTooltipStyle = { style: { background: 'rgb(255,255,255)', - maxWidth: 450, - maxHeight: 250, borderRadius: 10, - border: '2px solid rgba(0, 253, 232,.5)', - padding: '20px 20px 0px 20px', - overflow: 'auto', - boxShadow: '5px 5px 3px rgba(0,0,0,.5)' + border: '2px solid rgba(255, 0, 0, .9)', + boxShadow: '5px 5px 3px rgba(0,0,0,.5)', }, arrowStyle: { - visibility:'hidden' + color: 'rgba(255, 0, 0, .9)', + borderColor: false } } @@ -237,8 +234,11 @@ export class CustomNodeWidget extends React.Component { selected={this.props.node.isSelected()} background={this.props.node.getOptions().color} onDoubleClick={this.handleEditLiteral.bind(this)}> + {(this.props.node.getOptions().extras["tip"] != undefined && this.props.node.getOptions().extras["tip"] != "") ? +

{this.props.node.getOptions().extras["tip"]}

+ : null} {this.props.node.getOptions().name} + + + {_.map(this.props.node.getInPorts(), this.generatePort)} + {_.map(this.props.node.getOutPorts(), this.generatePort)} + +
{this.state.showDescription && { ); } - else if(this.props.node.getOptions()["name"] !== 'Start' && this.props.node.getOptions()["name"] !== 'Finish'){ - return ( - { this.element = element }} - borderColor={this.props.node.getOptions().extras["borderColor"]} - data-default-node-name={this.props.node.getOptions().name} - selected={this.props.node.isSelected()} - background={this.props.node.getOptions().color} - onDoubleClick={this.handleEditLiteral.bind(this)}> - - {this.props.node.getOptions()["name"]} -

Description:

-
{this.props.node.getOptions().extras["descrpt"]}
-
- - {this.props.node.getOptions().name} - - - - {_.map(this.props.node.getInPorts(), this.generatePort)} - {_.map(this.props.node.getOutPorts(), this.generatePort)} - -
- ); - } return ( Date: Tue, 26 Apr 2022 09:41:39 +0800 Subject: [PATCH 06/11] Override position of tooltip --- src/components/CustomNodeWidget.tsx | 47 +++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/src/components/CustomNodeWidget.tsx b/src/components/CustomNodeWidget.tsx index d9051d1d..6b04bfac 100644 --- a/src/components/CustomNodeWidget.tsx +++ b/src/components/CustomNodeWidget.tsx @@ -226,9 +226,8 @@ export class CustomNodeWidget extends React.Component { this.element = element} - // Data for description's tooltip - data-tip data-for={this.props.node.getOptions().id} + ref={(element) => { this.element = element }} + data-tip data-for={this.props.node.getOptions().id} // Data for tooltip borderColor={this.props.node.getOptions().extras["borderColor"]} data-default-node-name={this.props.node.getOptions().name} selected={this.props.node.isSelected()} @@ -260,19 +259,55 @@ export class CustomNodeWidget extends React.Component { {_.map(this.props.node.getOutPorts(), this.generatePort)} + {/** Description Tooltip */} {this.state.showDescription && { this.setState({ showDescription: true }) }} afterHide={() => { this.setState({ showDescription: false }) }} delayHide={60000} + delayUpdate={5000} getContent={() => -
+
{this.props.node.getOptions()["name"]}

Description:

-
{this.props.node['extras']['description'] ?? No description provided}
+
+
{this.props.node['extras']['description'] ?? No description provided}
+
} + overridePosition={( + { left, top }, + currentEvent, currentTarget, node, refNode) => { + const currentNode = this.props.node; + const nodeDimension = { x: currentNode.width, y: currentNode.height }; + const nodePosition = { x: currentNode.getX(), y: currentNode.getY() }; + let newPositionX = nodePosition.x; + let newPositionY = nodePosition.y; + + if (refNode == 'top') { + newPositionX = newPositionX - 200 + (nodeDimension.x / 2); + newPositionY = newPositionY - 220; + } + else if (refNode == 'bottom') { + newPositionX = newPositionX - 200 + (nodeDimension.x / 2); + newPositionY = newPositionY + 85 + nodeDimension.y; } + else if (refNode == 'right') { + newPositionX = newPositionX + 40 + nodeDimension.x; + newPositionY = newPositionY - 30; + } + else if (refNode == 'left') { + newPositionX = newPositionX - 450; + newPositionY = newPositionY - 30; + } + const tooltipPosition = this.props.engine.getRelativePoint(newPositionX, newPositionY); + + left = tooltipPosition.x; + top = tooltipPosition.y; + return { top, left } + }} />} ); From 46938b751df37a39b563859beef963bdddbe2908 Mon Sep 17 00:00:00 2001 From: AdrySky Date: Tue, 26 Apr 2022 09:45:20 +0800 Subject: [PATCH 07/11] Add close button --- src/components/CustomNodeWidget.tsx | 8 ++++++++ style/ComponentInfo.css | 17 +++++++++++++++++ style/base.css | 19 ------------------- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/components/CustomNodeWidget.tsx b/src/components/CustomNodeWidget.tsx index 6b04bfac..21281e90 100644 --- a/src/components/CustomNodeWidget.tsx +++ b/src/components/CustomNodeWidget.tsx @@ -271,6 +271,14 @@ export class CustomNodeWidget extends React.Component { delayUpdate={5000} getContent={() =>
+ {this.props.node.getOptions()["name"]}

Description:

diff --git a/style/ComponentInfo.css b/style/ComponentInfo.css index 5297bb2f..7cec8da2 100644 --- a/style/ComponentInfo.css +++ b/style/ComponentInfo.css @@ -28,4 +28,21 @@ font-weight: 700; font-size: 13px; color: rgb(0, 0, 0); +/* Close button*/ +.close { + background-color: transparent; + position: absolute; + top: 4px; + right: 17px; + font-size: 20px; + border-radius: 50%; + border: none; +} +.close:hover, +.close:focus { + color: rgb(255, 255, 255); + background-color: #616161; + text-decoration: none; + cursor: pointer; + outline: none; } \ No newline at end of file diff --git a/style/base.css b/style/base.css index 1eef6dc8..ef6be07e 100644 --- a/style/base.css +++ b/style/base.css @@ -35,23 +35,4 @@ .jp-debugger-toolbar-panel { flex: 0 0 auto; -} - -/* Close button for image viewer*/ -.close { - color: #fff; - background-color: #999; - position: absolute; - top: -22px; - right: -17px; - font-size: 20px; - border-radius: 50%; - border: 2px solid #333; -} -.close:hover, -.close:focus { - color: #000; - text-decoration: none; - cursor: pointer; - outline: none; } \ No newline at end of file From b058f88204e6f0862059e9abf940066db3b5eeb8 Mon Sep 17 00:00:00 2001 From: AdrySky Date: Tue, 26 Apr 2022 09:46:14 +0800 Subject: [PATCH 08/11] Fixed dimension tooltip --- style/ComponentInfo.css | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/style/ComponentInfo.css b/style/ComponentInfo.css index 7cec8da2..bad5a67f 100644 --- a/style/ComponentInfo.css +++ b/style/ComponentInfo.css @@ -7,18 +7,18 @@ } .description-container{ - max-width: 450px; - max-height: 250px; + width: 450px; + height: 250px; overflow: auto; + position: relative; } .description-text{ text-align: justify; font-family: sans-serif; font-weight: 500; - font-size: 11px; + font-size: 12px; white-space: pre-wrap; - cursor: default; color: rgb(0, 0, 0); } @@ -28,6 +28,8 @@ font-weight: 700; font-size: 13px; color: rgb(0, 0, 0); + padding-bottom: 5px; +} /* Close button*/ .close { background-color: transparent; From 6bb271492d2286964e0143165e49382051b3056a Mon Sep 17 00:00:00 2001 From: AdrySky Date: Tue, 26 Apr 2022 09:47:02 +0800 Subject: [PATCH 09/11] Change error tooltip into using ReactTooltip --- src/components/CustomNodeWidget.tsx | 68 ++++++++++++++++++++--------- style/ComponentInfo.css | 20 +++++++++ 2 files changed, 68 insertions(+), 20 deletions(-) diff --git a/src/components/CustomNodeWidget.tsx b/src/components/CustomNodeWidget.tsx index 21281e90..53c6e795 100644 --- a/src/components/CustomNodeWidget.tsx +++ b/src/components/CustomNodeWidget.tsx @@ -198,19 +198,6 @@ export class CustomNodeWidget extends React.Component { this.handleOnChangeCanvas(); } - errorTooltipStyle = { - style: { - background: 'rgb(255,255,255)', - borderRadius: 10, - border: '2px solid rgba(255, 0, 0, .9)', - boxShadow: '5px 5px 3px rgba(0,0,0,.5)', - }, - arrowStyle: { - color: 'rgba(255, 0, 0, .9)', - borderColor: false - } - } - /** * Show/Hide Component's Description Tooltip */ @@ -218,6 +205,12 @@ export class CustomNodeWidget extends React.Component { await this.setState({ showDescription: !this.state.showDescription }); ReactTooltip.show(this.element as Element) } + + // Hide Error Tooltip + hideErrorTooltip(){ + delete this.props.node.getOptions().extras["tip"]; + this.props.node.getOptions().extras["borderColor"]="rgb(0,192,255)"; + } render() { if (this.props.node.getOptions()["name"] !== 'Start' && this.props.node.getOptions()["name"] !== 'Finish') { @@ -233,11 +226,6 @@ export class CustomNodeWidget extends React.Component { selected={this.props.node.isSelected()} background={this.props.node.getOptions().color} onDoubleClick={this.handleEditLiteral.bind(this)}> - {(this.props.node.getOptions().extras["tip"] != undefined && this.props.node.getOptions().extras["tip"] != "") ? - -

{this.props.node.getOptions().extras["tip"]}

-
- : null} {this.props.node.getOptions().name}
} overridePosition={( { left, top }, @@ -301,7 +289,7 @@ export class CustomNodeWidget extends React.Component { else if (refNode == 'bottom') { newPositionX = newPositionX - 200 + (nodeDimension.x / 2); newPositionY = newPositionY + 85 + nodeDimension.y; - } + } else if (refNode == 'right') { newPositionX = newPositionX + 40 + nodeDimension.x; newPositionY = newPositionY - 30; @@ -317,6 +305,46 @@ export class CustomNodeWidget extends React.Component { return { top, left } }} />} + {/** Error Tooltip */} + {(this.props.node.getOptions().extras["tip"] != undefined && this.props.node.getOptions().extras["tip"] != "") ? + +
+

{this.props.node.getOptions().extras["tip"]}

+ +
+ } + overridePosition={({ left, top }) => { + const currentNode = this.props.node; + const nodeDimension = { x: currentNode.width, y: currentNode.height }; + const nodePosition = { x: currentNode.getX(), y: currentNode.getY() }; + let newPositionX = nodePosition.x; + let newPositionY = nodePosition.y; + newPositionX = newPositionX - 110 + (nodeDimension.x / 2); + newPositionY = newPositionY + 90 + nodeDimension.y; + + const tooltipPosition = this.props.engine.getRelativePoint(newPositionX, newPositionY); + + left = tooltipPosition.x; + top = tooltipPosition.y; + return { top, left } + }} + /> + : null} ); } diff --git a/style/ComponentInfo.css b/style/ComponentInfo.css index bad5a67f..24197d71 100644 --- a/style/ComponentInfo.css +++ b/style/ComponentInfo.css @@ -30,6 +30,26 @@ color: rgb(0, 0, 0); padding-bottom: 5px; } + +.error-tooltip{ + background: rgb(255, 255, 255) !important; + border-radius: 10px !important; + border: 2px solid rgba(255, 0, 0, .9) !important; + box-shadow: 5px 5px 3px rgba(0,0,0,.5) !important; +} + +.error-text{ + color: rgb(0, 0, 0); + width: 250px; + text-align: center; + padding-right: 10px; + cursor: default; +} + +.error-container .close{ + right: 5px; +} + /* Close button*/ .close { background-color: transparent; From 95753f9a03bcafd990f714e5170ffbd537c2606e Mon Sep 17 00:00:00 2001 From: AdrySky Date: Thu, 28 Apr 2022 14:16:23 +0800 Subject: [PATCH 10/11] Add offset of left sidebar width --- src/components/CustomNodeFactory.tsx | 8 +++++--- src/components/CustomNodeWidget.tsx | 22 +++++++++++++++------- src/components/XircuitsApp.ts | 6 +++--- src/xircuitWidget.tsx | 2 +- 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/components/CustomNodeFactory.tsx b/src/components/CustomNodeFactory.tsx index d5db01ec..8ca2c1f3 100644 --- a/src/components/CustomNodeFactory.tsx +++ b/src/components/CustomNodeFactory.tsx @@ -4,13 +4,15 @@ import { CustomNodeModel } from './CustomNodeModel'; import {AbstractReactFactory, GenerateModelEvent, GenerateWidgetEvent} from '@projectstorm/react-canvas-core'; import { DiagramEngine } from '@projectstorm/react-diagrams-core'; import {CustomNodeWidget} from "./CustomNodeWidget"; -import { JupyterFrontEnd } from '@jupyterlab/application'; +import { ILabShell, JupyterFrontEnd } from '@jupyterlab/application'; export class CustomNodeFactory extends AbstractReactFactory { app : JupyterFrontEnd - constructor(app) { + shell : ILabShell + constructor(app, shell) { super('custom-node'); this.app = app; + this.shell = shell; } generateModel(initialConfig: GenerateModelEvent) { @@ -18,6 +20,6 @@ export class CustomNodeFactory extends AbstractReactFactory): JSX.Element { - return ; + return ; } } diff --git a/src/components/CustomNodeWidget.tsx b/src/components/CustomNodeWidget.tsx index 53c6e795..e42f2bc1 100644 --- a/src/components/CustomNodeWidget.tsx +++ b/src/components/CustomNodeWidget.tsx @@ -9,7 +9,7 @@ import ToolTip from 'react-portal-tooltip'; import { Pagination } from "krc-pagination"; import 'krc-pagination/styles.css'; import Toggle from 'react-toggle' -import { JupyterFrontEnd } from '@jupyterlab/application'; +import { ILabShell, JupyterFrontEnd } from '@jupyterlab/application'; import { commandIDs } from './xircuitBodyWidget'; import { CustomPortLabel } from './port/CustomPortLabel'; import TextareaAutosize from 'react-textarea-autosize'; @@ -92,6 +92,7 @@ export interface DefaultNodeProps { node: DefaultNodeModel; engine: DiagramEngine; app: JupyterFrontEnd; + shell : ILabShell; } /** @@ -281,22 +282,29 @@ export class CustomNodeWidget extends React.Component { const nodePosition = { x: currentNode.getX(), y: currentNode.getY() }; let newPositionX = nodePosition.x; let newPositionY = nodePosition.y; + let offset = 0; + + if (!this.props.shell.leftCollapsed) { + // Some weird offset happened when left sidebar opened, need to add this + let leftSidebar = document.getElementById('jp-left-stack'); + offset = leftSidebar.clientWidth + 2; + } if (refNode == 'top') { - newPositionX = newPositionX - 200 + (nodeDimension.x / 2); + newPositionX = newPositionX - 208 + offset + (nodeDimension.x / 2); newPositionY = newPositionY - 220; } else if (refNode == 'bottom') { - newPositionX = newPositionX - 200 + (nodeDimension.x / 2); + newPositionX = newPositionX - 208 + offset + (nodeDimension.x / 2); newPositionY = newPositionY + 85 + nodeDimension.y; } else if (refNode == 'right') { - newPositionX = newPositionX + 40 + nodeDimension.x; - newPositionY = newPositionY - 30; + newPositionX = newPositionX + 40 + offset + nodeDimension.x; + newPositionY = newPositionY - 66 + (nodeDimension.y / 2); } else if (refNode == 'left') { - newPositionX = newPositionX - 450; - newPositionY = newPositionY - 30; + newPositionX = newPositionX - 450 + offset; + newPositionY = newPositionY - 66 + (nodeDimension.y / 2); } const tooltipPosition = this.props.engine.getRelativePoint(newPositionX, newPositionY); diff --git a/src/components/XircuitsApp.ts b/src/components/XircuitsApp.ts index 8977fc74..f13f2f2c 100644 --- a/src/components/XircuitsApp.ts +++ b/src/components/XircuitsApp.ts @@ -3,7 +3,7 @@ import { CustomNodeFactory } from "./CustomNodeFactory"; import { CustomNodeModel } from './CustomNodeModel'; import { ZoomCanvasAction } from '@projectstorm/react-canvas-core'; import { CustomActionEvent } from '../commands/CustomActionEvent'; -import { JupyterFrontEnd } from '@jupyterlab/application'; +import { ILabShell, JupyterFrontEnd } from '@jupyterlab/application'; import { CustomDiagramState } from './state/CustomDiagramState' import { CustomLinkModel, TriangleLinkModel } from './link/CustomLinkModel'; import { CustomLinkFactory, TriangleLinkFactory } from './link/CustomLinkFactory'; @@ -14,11 +14,11 @@ export class XircuitsApplication { protected diagramEngine: SRD.DiagramEngine; - constructor(app: JupyterFrontEnd) { + constructor(app: JupyterFrontEnd, shell: ILabShell) { this.diagramEngine = SRD.default({ registerDefaultZoomCanvasAction: false, registerDefaultDeleteItemsAction: false }); this.activeModel = new SRD.DiagramModel(); - this.diagramEngine.getNodeFactories().registerFactory(new CustomNodeFactory(app)); + this.diagramEngine.getNodeFactories().registerFactory(new CustomNodeFactory(app, shell)); this.diagramEngine.getLinkFactories().registerFactory(new CustomLinkFactory()); this.diagramEngine.getLinkFactories().registerFactory(new TriangleLinkFactory()); this.diagramEngine.getActionEventBus().registerAction(new ZoomCanvasAction({ inverseZoom: true })) diff --git a/src/xircuitWidget.tsx b/src/xircuitWidget.tsx index edee4dfa..e7a16e43 100644 --- a/src/xircuitWidget.tsx +++ b/src/xircuitWidget.tsx @@ -62,7 +62,7 @@ export class XPipePanel extends ReactWidget { this.stepOutDebugSignal = options.stepOutDebugSignal; this.evaluateDebugSignal = options.evaluateDebugSignal; this.debugModeSignal = options.debugModeSignal; - this.xircuitsApp = new XircuitsApplication(this.app); + this.xircuitsApp = new XircuitsApplication(this.app, this.shell); } handleEvent(event: Event): void { From 5894a7bf1466299738db229a06bee337912aa336 Mon Sep 17 00:00:00 2001 From: AdrySky Date: Thu, 28 Apr 2022 14:25:26 +0800 Subject: [PATCH 11/11] Add offset for error tooltip --- src/components/CustomNodeWidget.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/components/CustomNodeWidget.tsx b/src/components/CustomNodeWidget.tsx index e42f2bc1..5fc7b967 100644 --- a/src/components/CustomNodeWidget.tsx +++ b/src/components/CustomNodeWidget.tsx @@ -342,7 +342,15 @@ export class CustomNodeWidget extends React.Component { const nodePosition = { x: currentNode.getX(), y: currentNode.getY() }; let newPositionX = nodePosition.x; let newPositionY = nodePosition.y; - newPositionX = newPositionX - 110 + (nodeDimension.x / 2); + let offset = 0; + + if (!this.props.shell.leftCollapsed) { + // Some weird offset happened when left sidebar opened, need to add this + let leftSidebar = document.getElementById('jp-left-stack'); + offset = leftSidebar.clientWidth + 2; + } + + newPositionX = newPositionX - 110 + offset + (nodeDimension.x / 2); newPositionY = newPositionY + 90 + nodeDimension.y; const tooltipPosition = this.props.engine.getRelativePoint(newPositionX, newPositionY);