An airpal like interface

This commit is contained in:
Maxime Beauchemin 2016-01-29 10:29:23 -08:00
parent 354ef9b4bb
commit e8ae49d181
3 changed files with 139 additions and 2 deletions

View File

@ -11,11 +11,11 @@ List of TODO items for Panoramix
the same way that you can groupby for series, you could chart by. The form fieldset would be common and use the same way that you can groupby for series, you could chart by. The form fieldset would be common and use
a single field to "grid by", a limit number of chart as an N * N grid size. a single field to "grid by", a limit number of chart as an N * N grid size.
* **Free form SQL editor:** Having an Airpal-like easy SQL editor * **Free form SQL editor:** Having an Airpal-like easy SQL editor
* **Advanced dashboard configuration:** define which slices are immune to which filters, how often widgets should refresh, * **Advanced dashboard configuration:** define which slices are immune to which filters, how often widgets should refresh,
maybe this should start as a json blob... maybe this should start as a json blob...
* **Getting proper JS testing:** unit tests on the Python side are pretty solid, but now we need a test * **Getting proper JS testing:** unit tests on the Python side are pretty solid, but now we need a test
suite for the JS part of the site, testing all the ajax-type calls suite for the JS part of the site, testing all the ajax-type calls
* **Annotations layers:** allow for people to maintain data annotations, * **Annotations layers:** allow for people to maintain data annotations,
attached to a layer and time range. These layers can be added on top of some visualizations as annotations. attached to a layer and time range. These layers can be added on top of some visualizations as annotations.
An example of a layer might be "holidays" or "site outages", ... An example of a layer might be "holidays" or "site outages", ...
* **Worth doing? User defined groups:** People could define mappings in the UI of say "Countries I follow" and apply it to different datasets. For now, this is done by writing CASE-WHEN-type expression which is probably good enough. * **Worth doing? User defined groups:** People could define mappings in the UI of say "Countries I follow" and apply it to different datasets. For now, this is done by writing CASE-WHEN-type expression which is probably good enough.

View File

@ -0,0 +1,105 @@
{% extends "panoramix/base.html" %}
{% block head_css %}
{{super()}}
<link rel="stylesheet" type="text/css" href="/static/lib/dataTables/jquery.dataTables.min.css" />
<link rel="stylesheet" type="text/css" href="/static/lib/dataTables/dataTables.bootstrap.css" />
<style type="text/css">
.topsql {
height: 250px;
}
.bordered {
padding: 5px 10px;
border: 1px solid grey;
border-radius: 5px;
background-color: #EEE;
}
.metadata {
overflow: auto;
width: 300px;
height: 100px;
}
.fillup {
width: 100%;
height: 100%;
}
.fillheight {
height: 100%;
}
#interactive {
padding-top: 10px;
}
#results {
overflow: auto;
font-size: 12px;
}
#results table tbody tr td{
padding: 2px 4px;
}
</style>
{% endblock %}
{% block content %}
<h2>db: [{{ db }}]</h2>
<div class="topsql row">
<div class="col-xs-7 fillheight">
<textarea id="sql" class="fillup">SELECT * FROM information_schema.tables;
</textarea>
</div>
<div class="col-xs-5 fillheight">
<div class="metadata fillup bordered">
Tables
</div>
</div>
</div>
<div id="interactive">
<input type="hidden" id="database_id" value="{{ database_id }}">
<button class="btn btn-primary" id="run">Run!</button>
<button class="btn btn-default" id="view">Create View</button>
</div>
<div id="results_section">
<hr/>
<img id="loading" width="25" style="display: none;" src="/static/img/loading.gif">
</div>
<div>
<div id="results" class="bordered"></div>
</div>
{% endblock %}
{% block tail_js %}
{{ super() }}
<script src="/static/lib/bootstrap-toggle.min.js"></script>
<script src="/static/lib/dataTables/jquery.dataTables.min.js"></script>
<script src="/static/lib/dataTables/dataTables.bootstrap.js"></script>
<script>
$(document).ready(function() {
$("#run").click(function() {
$('#results').hide(0);
$('#loading').show(0);
$.ajax({
type: "POST",
url: '/panoramix/runsql/',
data: {
'data': JSON.stringify({
'database_id': $('#database_id').val(),
'sql': $('#sql').val(),
})},
success: function(data) {
$('#loading').hide(0);
$('#results').show(0);
$('#results').html(data);
var datatable = $('table').DataTable({
paging: false,
searching: true,
});
},
error: function() {
$('#loading').hide(0);
},
});
});
});
</script>
{% endblock %}

View File

@ -552,6 +552,38 @@ class Panoramix(BaseView):
templates=templates, templates=templates,
pos_dict=pos_dict) pos_dict=pos_dict)
@has_access
@expose("/sql/<database_id>/")
@utils.log_this
def sql(self, database_id):
mydb = db.session.query(models.Database).filter_by(id=database_id).first()
return self.render_template(
"panoramix/sql.html",
database_id=database_id,
db=mydb)
@has_access
@expose("/runsql/", methods=['POST', 'GET'])
@utils.log_this
def runsql(self):
session = db.session()
data = json.loads(request.form.get('data'))
sql = data.get('sql')
database_id = data.get('database_id')
mydb = session.query(models.Database).filter_by(id=database_id).first()
content = ""
if mydb:
print("SUPER!")
from pandas import read_sql_query
eng = mydb.get_sqla_engine()
df = read_sql_query(sql=sql, con=eng)
content = df.to_html(
classes="dataframe table table-striped table-bordered table-condensed")
else:
print("ELSE")
session.commit()
return content
@has_access @has_access
@expose("/refresh_datasources/") @expose("/refresh_datasources/")
def refresh_datasources(self): def refresh_datasources(self):