Skip to content

Commit

Permalink
Carapal react mockup
Browse files Browse the repository at this point in the history
This is really just a mock up written in React to try different
components. It could become scaffolding to build a prototype, or not.
  • Loading branch information
mistercrunch committed May 25, 2016
1 parent eb3bfb5 commit dc0c143
Show file tree
Hide file tree
Showing 7 changed files with 240 additions and 2 deletions.
160 changes: 160 additions & 0 deletions caravel/assets/javascripts/carapal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import React from 'react';
import { render } from 'react-dom';

import { Button, ButtonGroup } from 'react-bootstrap';
import { Table } from 'reactable';

import brace from 'brace';
import AceEditor from 'react-ace';
import 'brace/mode/sql';
import 'brace/theme/chrome';


var ReactGridLayout = require('react-grid-layout');

require('../stylesheets/carapal.css')

const GridItem = React.createClass({
getDefaultProps: function() {
return {
nopadding: false
};
},
render: function () {
return (
<div className="panel panel-default">
<div className="panel-heading">{this.props.header}</div>
<div className={"panel-body " + (this.props.nopadding ? 'nopadding': '')}>
{this.props.children}
</div>
</div>
)
}
});

const SqlEditor = React.createClass({
render: function () {
return (
<GridItem
nopadding={true}
header={
<div>Query
<span className="pull-right">
<Button bsSize="small">Run</Button>
</span>
</div>
}>
<div className="sqleditor">
<AceEditor
mode="sql"
name={this.props.name}
theme="chrome"
minLines={10}
maxLines={50}
editorProps={{$blockScrolling: true}}
value="SELECT * FROM users"
/>
</div>
</GridItem>
)
}
});

const ResultSet = React.createClass({
render: function () {
return (
<GridItem
header={(
<div>
Result Set
<span className="pull-right">
<ButtonGroup>
<Button bsSize="small">.csv</Button>
<Button bsSize="small">.json</Button>
</ButtonGroup>
</span>
</div>
)}
nopadding={true}>
<Table
className="table table-condensed table-striped table-bordered small"
sortable={true}
data={[
{'State': 'New York', 'Description': 'this is some text', 'Tag': 'new'},
{'State': 'New Mexico', 'Description': 'lorem ipsum', 'Tag': 'old'},
{'State': 'Colorado',
'Description': 'new description that shouldn\'t match filter',
'Tag': 'old'},
{'State': 'Alaska', 'Description': 'bacon', 'Tag': 'renewed'},
{'State': 'New York', 'Description': 'this is some text', 'Tag': 'new'},
{'State': 'New Mexico', 'Description': 'lorem ipsum', 'Tag': 'old'},
{'State': 'Colorado',
'Description': 'new description that shouldn\'t match filter',
'Tag': 'old'},
{'State': 'Alaska', 'Description': 'bacon', 'Tag': 'renewed'},
{'State': 'New York', 'Description': 'this is some text', 'Tag': 'new'},
{'State': 'New Mexico', 'Description': 'lorem ipsum', 'Tag': 'old'},
{'State': 'Colorado',
'Description': 'new description that shouldn\'t match filter',
'Tag': 'old'},
{'State': 'Alaska', 'Description': 'bacon', 'Tag': 'renewed'},
]}/>
</GridItem>
)
}
});


const Workspace = React.createClass({
render: function () {
return (
<GridItem header="Workspace Browser">
<strong>
Tables <Button bsSize="small"><a className="fa fa-plus"></a></Button>
</strong>
<ul>
<li><a href="#">fct_bookings</a></li>
<li><a href="#">dim_users</a></li>
<li><a href="#">dim_markets</a></li>
</ul>
<strong>
Queries <Button bsSize="small"><a className="fa fa-plus"></a></Button>
</strong>
<ul>
<li><a href="#">bookings by market</a></li>
<li><a href="#">bookings time series</a></li>
<li><a href="#">hour hot spots</a></li>
</ul>
</GridItem>
)
}
});

const App = React.createClass({
render: function () {
return (
<ReactGridLayout
className="layout"
cols={12} rowHeight={30}
width={window.innerWidth}>
<div key="qry1" _grid={{x: 3, y: 0, w: 5, h: 5}}>
<SqlEditor name="qry1"/>
</div>
<div key="qry2" _grid={{x: 8, y: 0, w: 4, h: 5}}>
<SqlEditor name="qry2"/>
</div>
<div key="results" _grid={{x: 3, y: 6, w: 9, h: 10}}>
<ResultSet/>
</div>
<div key="workspace" _grid={{x: 0, y: 0, w: 3, h: 15, maxW:4, minW: 4}}>
<Workspace/>
</div>
</ReactGridLayout>
)
}
});

render(
<App/>,
document.getElementById('app')
);
6 changes: 5 additions & 1 deletion caravel/assets/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
},
"homepage": "https://github.com/airbnb/caravel#readme",
"dependencies": {
"babel-loader": "^6.2.1",
"babel-loader": "^6.2.4",
"babel-plugin-transform-runtime": "^6.9.0",
"babel-polyfill": "^6.3.14",
"babel-preset-es2015": "^6.3.13",
"babel-preset-react": "^6.3.13",
Expand Down Expand Up @@ -63,8 +64,11 @@
"mustache": "^2.2.1",
"nvd3": "1.8.2",
"react": "^0.14.7",
"react-ace": "^3.4.1",
"react-bootstrap": "^0.28.3",
"react-dom": "^0.14.7",
"react-grid-layout": "^0.12.4",
"reactable": "^0.13.2",
"select2": "3.5",
"select2-bootstrap-css": "^1.4.6",
"style-loader": "^0.13.0",
Expand Down
58 changes: 58 additions & 0 deletions caravel/assets/stylesheets/carapal.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@

.nopadding {
padding: 0px;
}
.panel {
height: 100%;
width: 100%;
overflow: auto;
}
.panel-body {
}

.react-grid-layout {
position: relative;
transition: height 200ms ease;
}
.react-grid-item {
transition: all 200ms ease;
transition-property: left, top;
}
.react-grid-item.cssTransforms {
transition-property: transform;
}
.react-grid-item.resizing {
z-index: 1;
}

.react-grid-item.react-draggable-dragging {
transition: none;
z-index: 3;
}

.react-grid-item.react-grid-placeholder {
background: red;
opacity: 0.2;
transition-duration: 100ms;
z-index: 2;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
}

.react-grid-item > .react-resizable-handle {
position: absolute;
width: 20px;
height: 20px;
bottom: 0;
right: 0;
background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pg08IS0tIEdlbmVyYXRvcjogQWRvYmUgRmlyZXdvcmtzIENTNiwgRXhwb3J0IFNWRyBFeHRlbnNpb24gYnkgQWFyb24gQmVhbGwgKGh0dHA6Ly9maXJld29ya3MuYWJlYWxsLmNvbSkgLiBWZXJzaW9uOiAwLjYuMSAgLS0+DTwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DTxzdmcgaWQ9IlVudGl0bGVkLVBhZ2UlMjAxIiB2aWV3Qm94PSIwIDAgNiA2IiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjojZmZmZmZmMDAiIHZlcnNpb249IjEuMSINCXhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbDpzcGFjZT0icHJlc2VydmUiDQl4PSIwcHgiIHk9IjBweCIgd2lkdGg9IjZweCIgaGVpZ2h0PSI2cHgiDT4NCTxnIG9wYWNpdHk9IjAuMzAyIj4NCQk8cGF0aCBkPSJNIDYgNiBMIDAgNiBMIDAgNC4yIEwgNCA0LjIgTCA0LjIgNC4yIEwgNC4yIDAgTCA2IDAgTCA2IDYgTCA2IDYgWiIgZmlsbD0iIzAwMDAwMCIvPg0JPC9nPg08L3N2Zz4=');
background-position: bottom right;
padding: 0 3px 3px 0;
background-repeat: no-repeat;
background-origin: content-box;
box-sizing: border-box;
cursor: se-resize;
}
5 changes: 5 additions & 0 deletions caravel/assets/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ var config = {
explore: APP_DIR + '/javascripts/explore.js',
welcome: APP_DIR + '/javascripts/welcome.js',
sql: APP_DIR + '/javascripts/sql.js',
carapal: APP_DIR + '/javascripts/carapal.jsx',
standalone: APP_DIR + '/javascripts/standalone.js'
},
output: {
Expand All @@ -22,6 +23,10 @@ var config = {
test: /\.jsx?/,
include: APP_DIR,
exclude: APP_DIR + '/node_modules',
query: {
presets: ['es2015'],
},
//plugins: ['transform-runtime'],
loader: 'babel'
},
/* for require('*.css') */
Expand Down
6 changes: 6 additions & 0 deletions caravel/templates/caravel/carapal.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{% extends "caravel/basic.html" %}

{% block tail_js %}
{{ super() }}
<script src="/static/assets/javascripts/dist/carapal.entry.js"></script>
{% endblock %}
5 changes: 5 additions & 0 deletions caravel/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1039,6 +1039,11 @@ def welcome(self):
"""Personalized welcome page"""
return self.render_template('caravel/welcome.html', utils=utils)

@has_access
@expose("/carapal")
def carapal(self):
"""SQL Editor"""
return self.render_template('caravel/carapal.html')

appbuilder.add_view_no_menu(Caravel)

Expand Down
2 changes: 1 addition & 1 deletion tests/core_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ def test_public_user_dashboard_access(self):
# Confirm that public doesn't have access to other datasets.
resp = self.client.get('/slicemodelview/list/')
data = resp.data.decode('utf-8')
assert '<a href="/tablemodelview/edit/2">wb_health_population</a>' not in data
assert 'wb_health_population</a>' not in data

resp = self.client.get('/dashboardmodelview/list/')
data = resp.data.decode('utf-8')
Expand Down

0 comments on commit dc0c143

Please sign in to comment.