Skip to content

Commit

Permalink
work in progress -- adding shelves
Browse files Browse the repository at this point in the history
  • Loading branch information
jrdzha committed Apr 25, 2020
1 parent 4790f6b commit fa001c5
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 27 deletions.
5 changes: 2 additions & 3 deletions css/widget.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#widgetContainer{
height:312px;
height:380px;
width:100%;
display:inline-flex;
}
Expand Down Expand Up @@ -108,7 +108,6 @@ input[type=text], select {
overflow-x: hidden;
display: flex;
min-width: 30%;
height: 100%;
}

#mainVizInnerContainer{
Expand All @@ -131,7 +130,7 @@ input[type=text], select {
position: absolute;
/* bottom: 90%; */
/* left: 97%; */
top: 0px;
top: 70px;
right: 0px;
font-size: 20px;
padding: 5px;
Expand Down
4 changes: 2 additions & 2 deletions luxWidget/nbextension/static/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion luxWidget/nbextension/static/index.js.map

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions luxWidget/widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ class LuxWidget(DOMWidget):
recommendations = List([]).tag(sync=True)
data = List([]).tag(sync=True)
selectedVisLst = List([]).tag(sync=True)
def __init__(self, currentView=None, recommendations=None, spec=None, opt=None, **kwargs):
context = Dict({}).tag(sync=True)
def __init__(self, currentView=None, recommendations=None, spec=None, opt=None, context=None, **kwargs):
super().__init__(**kwargs)
self._opt_source = json.dumps(opt)
self.current_view = currentView
self.recommendations = recommendations
self.recommendations = recommendations
self.context = context
3 changes: 3 additions & 0 deletions run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
sh install.sh
cd ../lux/
jupyter notebook
14 changes: 8 additions & 6 deletions src/currentView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ class CurrentViewComponent extends Component<currentViewProps,any> {
if (!_.isEmpty(this.props.currentViewSpec)){
return (
<div id="mainVizContainer">
<h2 id="mainVizTitle">Current View</h2>
<div id="mainVizInnerContainer">
<div className="vizContainer" onClick={()=>selectedVis("main")}>
<VegaLite spec={this.props.currentViewSpec}
padding={{left: 10, top: 5, right: 5, bottom: 5}}
actions={false}/>
<div style={{ display: 'flex', flexDirection: 'column'}}>
<h2 id="mainVizTitle" style={{ position: 'relative', top: '0px', left: '0px', width: '245px', textAlign: 'center' }}>Current View</h2>
<div id="mainVizInnerContainer" style={{ position: 'relative', top: '0px', left: '0px' }}>
<div className="vizContainer" onClick={()=>selectedVis("main")}>
<VegaLite spec={this.props.currentViewSpec}
padding={{left: 10, top: 5, right: 5, bottom: 5}}
actions={false}/>
</div>
</div>
</div>
</div>
Expand Down
103 changes: 90 additions & 13 deletions src/widget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export class ExampleModel extends DOMWidgetModel {
}

export class JupyterWidgetView extends DOMWidgetView {

initialize(){
let view = this;
interface WidgetProps{
Expand All @@ -54,8 +55,10 @@ export class JupyterWidgetView extends DOMWidgetView {
activeTab:any,
showAlert:boolean,
selectedRec:object,
selectedVisLst:object[]
selectedVisLst:object[],
context:object[]
}

class ReactWidget extends React.Component<JupyterWidgetView,WidgetProps> {
constructor(props:any){
super(props);
Expand All @@ -66,7 +69,8 @@ export class JupyterWidgetView extends DOMWidgetView {
activeTab: props.activeTab,
showAlert:false,
selectedRec:{},
selectedVisLst:[]
selectedVisLst:[],
context:props.model.get("context")
}
console.log("this.state:",this.state)
// This binding is necessary to make `this` work in the callback
Expand All @@ -77,9 +81,11 @@ export class JupyterWidgetView extends DOMWidgetView {
onChange(model:any){// called when the variable is changed in the view.model
this.setState(model.changed);
}

componentDidMount(){ //triggered when component is mounted (i.e., when widget first rendered)
view.listenTo(view.model,"change",this.onChange.bind(this));
}

componentDidUpdate(){ //triggered after component is updated
console.log("componentDidUpdate:",view.model.get("selectedVisLst"));
view.model.save_changes(); // instead of touch (which leads to callback issues), we have to use save_changes
Expand All @@ -91,7 +97,8 @@ export class JupyterWidgetView extends DOMWidgetView {
this.setState({
activeTab: selectedTab
});
}
}

onListChanged(tabIdx,selectedLst) {
this.state.selectedRec[tabIdx] = selectedLst
var selectedVisLst = []
Expand All @@ -103,6 +110,7 @@ export class JupyterWidgetView extends DOMWidgetView {
selectedVisLst: selectedVisLst
});
}

exportSelection() {
console.log("export selection")
this.setState(
Expand All @@ -118,6 +126,7 @@ export class JupyterWidgetView extends DOMWidgetView {
},7000);
view.model.set('selectedVisLst',this.state.selectedVisLst);
}

render(){
console.log("this.state.activeTab:",this.state.activeTab)
const tabItems = this.state.recommendations.map((actionResult,tabIdx) =>
Expand All @@ -128,14 +137,15 @@ export class JupyterWidgetView extends DOMWidgetView {
onChange={this.onListChanged.bind(this,tabIdx)}
graphSpec={actionResult.vspec}/>
</Tab>);

let exportBtn;
if (tabItems.length>0){
exportBtn = <i id="exportBtn"
className='fa fa-upload'
title='Export selected visualization into variable'
onClick={(e) => this.exportSelection()}
/>
onClick={(e) => this.exportSelection()}/>
}

let alertBtn;
if (this.state.showAlert){
alertBtn= <Alert id="alertBox"
Expand All @@ -145,15 +155,82 @@ export class JupyterWidgetView extends DOMWidgetView {
Exported selected visualizations to Python variable `widget.selectedVisLst`
</Alert>
}
return (<div id="widgetContainer">
<CurrentViewComponent currentViewSpec={this.state.currentView}/>
<div id="tabBanner">
<Tabs activeKey={this.state.activeTab} id="tabBannerList" onSelect={this.handleSelect}>
{tabItems}
</Tabs>

let attributeShelf =
<div style={{ display: 'flex', flexDirection: 'row' }}>
<div style={{ width: '100%', border: 'solid 1px lightgray', borderRadius: '5px', marginBottom: '5px', minHeight: '30px', maxHeight: '30px', display: 'flex', flexDirection: 'row' }}>
<div style={{ width: '100px', height: '100%', borderRight: 'solid 1px lightgray', paddingLeft: '10px', paddingRight: '10px', display: 'flex', flexDirection: 'row', backgroundColor: '#f7f7f7' }}>
<i id="attributeIcon"
className='fa fa-th-list'
style={{ marginTop: 'auto', marginBottom: 'auto', marginRight: '5px', minWidth: '15px' }}/>
<p style={{ lineHeight: '28px' }}>Attribute</p>
</div>
<div style={{ height: '100%', display: 'flex' }}>

{this.state.context['attributes'].map((attribute) => {
<div style={{ marginTop: '2px', marginBottom: '2px', marginLeft: '10px', border: 'solid 1px lightgray', borderRadius: '5px', display: 'flex', flexDirection: 'row', backgroundColor: '#f7f7f7' }}>
<i id="attributeIcon"
className='fa fa-hashtag'
style={{ marginTop: 'auto', marginBottom: 'auto', marginRight: '5px', marginLeft: '5px', minWidth: '15px' }}/>
<p style={{ lineHeight: '22px' }}>{attribute}</p>
<i id="attributeIcon"
className='fa fa-times-circle'
style={{ marginTop: 'auto', marginBottom: 'auto', marginRight: '5px', marginLeft: '5px', minWidth: '15px' }}
onClick={() => {}}/>
</div>
})}

</div>
</div>
<i id="attributeIcon"
className='fa fa-bars'
style={{ marginTop: 'auto', marginBottom: 'auto', marginLeft: '10px', marginRight: '5px', minWidth: '15px' }}/>
</div>

let filterShelf =
<div style={{ display: 'flex', flexDirection: 'row' }}>
<div style={{ width: '100%', border: 'solid 1px lightgray', borderRadius: '5px', marginBottom: '5px', minHeight: '30px' }}>
<div style={{ width: '100px', height: '100%', borderRight: 'solid 1px lightgray', paddingLeft: '10px', paddingRight: '10px', display: 'flex', flexDirection: 'row', backgroundColor: '#f7f7f7' }}>
<i id="attributeIcon"
className='fa fa-filter'
style={{ marginTop: 'auto', marginBottom: 'auto', marginRight: '3px', marginLeft: '2px', minWidth: '15px' }}/>
<p style={{ lineHeight: '28px' }}>Filter</p>
</div>
<div style={{ width: '100%' }}>

{this.state.context['filters'].map((filter) => {
<div style={{ marginTop: '2px', marginBottom: '2px', marginLeft: '10px', border: 'solid 1px lightgray', borderRadius: '5px', display: 'flex', flexDirection: 'row', backgroundColor: '#f7f7f7' }}>
<i id="attributeIcon"
className='fa fa-hashtag'
style={{ marginTop: 'auto', marginBottom: 'auto', marginRight: '5px', marginLeft: '5px', minWidth: '15px' }}/>
<p style={{ lineHeight: '22px' }}>{filter}</p>
<i id="attributeIcon"
className='fa fa-times-circle'
style={{ marginTop: 'auto', marginBottom: 'auto', marginRight: '5px', marginLeft: '5px', minWidth: '15px' }}
onClick={() => {}}/>
</div>
{exportBtn}
{alertBtn}
})}

</div>
</div>
<i id="attributeIcon"
className='fa fa-database'
style={{ marginTop: 'auto', marginBottom: 'auto', marginLeft: '10px', marginRight: '5px', minWidth: '15px' }}/>
</div>

return (<div id="widgetContainer" style={{ flexDirection: 'column' }}>
{attributeShelf}
{filterShelf}
<div style={{ display: 'flex', flexDirection: 'row' }}>
<CurrentViewComponent currentViewSpec={this.state.currentView}/>
<div id="tabBanner">
<Tabs activeKey={this.state.activeTab} id="tabBannerList" onSelect={this.handleSelect}>
{tabItems}
</Tabs>
</div>
{exportBtn}
{alertBtn}
</div>
</div>);
}
}
Expand Down

0 comments on commit fa001c5

Please sign in to comment.