mirror of https://github.com/apache/superset.git
An airpal like interface
This commit is contained in:
parent
354ef9b4bb
commit
e8ae49d181
4
TODO.md
4
TODO.md
|
@ -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
|
||||
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
|
||||
* **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...
|
||||
* **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
|
||||
* **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.
|
||||
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.
|
||||
|
|
|
@ -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 %}
|
|
@ -552,6 +552,38 @@ class Panoramix(BaseView):
|
|||
templates=templates,
|
||||
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
|
||||
@expose("/refresh_datasources/")
|
||||
def refresh_datasources(self):
|
||||
|
|
Loading…
Reference in New Issue