Skip to content

Commit

Permalink
Dashboards
Browse files Browse the repository at this point in the history
  • Loading branch information
mistercrunch committed Sep 14, 2015
1 parent 3635191 commit a5b8964
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 52 deletions.
2 changes: 0 additions & 2 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
* DRUID: Allow for post aggregations (ratios!)
* compare time ranges
* csv export out of table view
* Save / bookmark / url shortener
* SQL: Find a way to manage granularity
* Create ~/.panoramix/ to host DB and config, generate default config there
* Add a per-datasource permission

65 changes: 63 additions & 2 deletions panoramix/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
Column, Integer, String, ForeignKey, Text, Boolean, DateTime)
from panoramix.utils import JSONEncodedDict
from sqlalchemy import Table as sqlaTable
from sqlalchemy import create_engine, MetaData, desc, select, and_
from sqlalchemy import create_engine, MetaData, desc, select, and_, Table
from sqlalchemy.orm import relationship
from sqlalchemy.sql import table, literal_column, text

Expand All @@ -33,12 +33,23 @@ class Slice(Model, AuditMixin):
__tablename__ = 'slices'
id = Column(Integer, primary_key=True)
slice_name = Column(String(250))
datasource_id = Column(Integer)
datasource_id = Column(Integer, ForeignKey('datasources.id'))
table_id = Column(Integer, ForeignKey('tables.id'))
datasource_type = Column(String(200))
datasource_name = Column(String(2000))
viz_type = Column(String(250))
params = Column(Text)

table = relationship('Table', backref='slices')
druid_datasource = relationship('Datasource', backref='slices')

def __repr__(self):
return self.slice_name

@property
def datasource(self):
return self.table or self.druid_datasource

@property
def slice_link(self):
d = json.loads(self.params)
Expand All @@ -48,6 +59,53 @@ def slice_link(self):
"{self.datasource_id}/?{kwargs}").format(**locals())
return '<a href="{url}">{self.slice_name}</a>'.format(**locals())

@property
def js_files(self):
from panoramix.viz import viz_types
return viz_types[self.viz_type].js_files

@property
def css_files(self):
from panoramix.viz import viz_types
return viz_types[self.viz_type].css_files


dashboard_slices = Table('dashboard_slices', Model.metadata,
Column('id', Integer, primary_key=True),
Column('dashboard_id', Integer, ForeignKey('dashboards.id')),
Column('slice_id', Integer, ForeignKey('slices.id')),
)


class Dashboard(Model, AuditMixin):
"""A dash to slash"""
__tablename__ = 'dashboards'
id = Column(Integer, primary_key=True)
dashboard_title = Column(String(500))
slices = relationship(
'Slice', secondary=dashboard_slices, backref='dashboards')

def __repr__(self):
return self.dashboard_title

def dashboard_link(self):
url = "/panoramix/dashboard/{}/".format(self.id)
return '<a href="{url}">{self.dashboard_title}</a>'.format(**locals())

@property
def js_files(self):
l = []
for o in self.slices:
l += o.js_files
return list(set(l))

@property
def css_files(self):
l = []
for o in self.slices:
l += o.css_files
return list(set(l))


class Queryable(object):
@property
Expand Down Expand Up @@ -99,6 +157,9 @@ class Table(Model, Queryable, AuditMixin):

baselink = "tableview"

def __repr__(self):
return self.table_name

@property
def name(self):
return self.table_name
Expand Down
47 changes: 26 additions & 21 deletions panoramix/templates/panoramix/dashboard.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{% extends "panoramix/base.html" %}

{% block head_css %}
{{super()}}
{{ super() }}
<link rel="stylesheet" href="{{ url_for('static', filename="jquery.gridster.min.css") }}">
<style>
.gridster li {
Expand All @@ -10,36 +10,40 @@
background: #EEEEEE;
overflow: auto;
box-shadow: 2px 2px 2px #AAA;
border-radius: 5px;
}
img.loading {
width: 20px;
margin: 5px;
}
.title {
text-align: center;
}
.slice_title {
text-align: center;
}
div.gridster {
visibility: hidden
}
</style>
{% endblock %}

{% block content_fluid %}
<div class="title"><h2>{{ dashboard.dashboard_title }}</h2></div>
<div class="gridster content_fluid">
<ul>
<li id="loadme3" data-row="1" data-col="1" data-sizex="1" data-sizey="1">
</li>
<li data-row="2" data-col="1" data-sizex="1" data-sizey="1"></li>
<li data-row="3" data-col="1" data-sizex="1" data-sizey="1"></li>

<li data-row="1" data-col="2" data-sizex="2" data-sizey="1"></li>
<li id="loadme1" data-row="2" data-col="2" data-sizex="2" data-sizey="2"></li>

<li data-row="1" data-col="4" data-sizex="1" data-sizey="1"></li>
<li data-row="2" data-col="4" data-sizex="2" data-sizey="1"></li>
<li data-row="3" data-col="4" data-sizex="1" data-sizey="1"></li>

<li data-row="1" data-col="5" data-sizex="1" data-sizey="1"></li>
<li data-row="3" data-col="5" data-sizex="1" data-sizey="1"></li>

<li data-row="1" data-col="6" data-sizex="1" data-sizey="1"></li>
<li data-row="2" data-col="6" data-sizex="1" data-sizey="2"></li>
<li id="loadme2" data-row="4" data-col="1" data-sizex="2" data-sizey="2">
{% for slice in dashboard.slices %}
<li
id="slice_{{ slice.id }}"
data-row="1"
data-col="{{ loop.index }}"
data-sizex="2"
data-sizey="2">
<div class="slice_title">
<h5>{{ slice.slice_name }}</h5>
</div>
</li>
{% endfor %}
</ul>
</div>
{% endblock %}
Expand All @@ -48,15 +52,16 @@
{{ super() }}
<script src="{{ url_for("static", filename="jquery.gridster.with-extras.min.js") }}"></script>
<script>
$(".gridster li").html('<img src="/static/loading.gif" class="loading">');
//$(".gridster li").html('<img src="/static/loading.gif" class="loading">');
$(".gridster ul").gridster({
widget_margins: [5, 5],
widget_base_dimensions: [200, 200],
widget_base_dimensions: [150, 150],
resize: {enabled: true}
});
$("#loadme1").load("/panoramix/table/2/?flt_col_0=gender&datasource_id=2&flt_op_0=in&viz_type=table&row_limit=50&since=50%20years%20ago&until=now&metrics=total&granularity=all&datasource_name=baby_names&slice_name=Top%2050%20table&where=&groupby=name&flt_eq_0=&datasource_type=table&standalone=true");
//$("#loadme2").load("/panoramix/table/2/?flt_col_0=gender&datasource_id=2&flt_op_0=in&viz_type=pie&since=50%20years%20ago&until=now&metrics=total&limit=10&granularity=one%20day&datasource_name=baby_names&slice_name=Pie&where=&groupby=name&flt_eq_0=&datasource_type=table&standalone=true");
//$("loadme3").html('<iframe src="http://localhost:8088/panoramix/table/2/?flt_col_0=gender&datasource_id=2&flt_op_0=in&viz_type=pie&since=50%20years%20ago&until=now&metrics=total&limit=10&granularity=one%20day&datasource_name=baby_names&slice_name=Pie&where=&groupby=name&flt_eq_0=&datasource_type=table&standalone=true"></iframe>');
$("div.gridster").css('visibility', 'visible');
</script>

{% endblock %}
Expand Down
15 changes: 15 additions & 0 deletions panoramix/templates/panoramix/viz.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,18 @@
{% else %}
{% extends 'panoramix/datasource.html' %}
{% endif %}

{% block head %}
{{super()}}
{% for css in viz.css_files %}
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename=css) }}">
{% endfor %}
{% endblock %}


{% block tail %}
{{super()}}
{% for js in viz.js_files %}
<script src="{{ url_for('static', filename=js) }}"></script>
{% endfor %}
{% endblock %}
6 changes: 0 additions & 6 deletions panoramix/templates/panoramix/viz_highcharts.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,6 @@

{% block tail %}
{{ super() }}
{% if viz.stockchart %}
<script src="{{ url_for("static", filename="highstock.js") }}"></script>
{% else %}
<script src="{{ url_for("static", filename="highcharts.js") }}"></script>
{% endif %}
<script src="{{ url_for("static", filename="highcharts-more.js") }}"></script>
<script>
$( document ).ready(function() {
Highcharts.setOptions({
Expand Down
26 changes: 9 additions & 17 deletions panoramix/templates/panoramix/viz_table.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
{% extends "panoramix/viz.html" %}

{% block head_css %}
{{super()}}
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='dataTables.bootstrap.css') }}">
{% endblock %}

{% block viz %}
{{ super() }}
{% if not error_msg %}
Expand Down Expand Up @@ -36,18 +31,15 @@
{% endblock %}

{% block tail %}
{{ super() }}
<script src="{{ url_for('static', filename='jquery.dataTables.min.js') }}"></script>
<script src="{{ url_for('static', filename='dataTables.bootstrap.js') }}"></script>

<script>
//$('table').css('background-color', 'white');
$(document).ready(function() {
var table = $('table').DataTable({
paging: false,
{{ super() }}
<script>
//$('table').css('background-color', 'white');
$(document).ready(function() {
var table = $('table').DataTable({
paging: false,
});
table.column('-1').order( 'desc' ).draw();
});
table.column('-1').order( 'desc' ).draw();
});
</script>
</script>
{% endblock %}

31 changes: 27 additions & 4 deletions panoramix/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class ClusterModelView(ModelView, DeleteMixin):

class SliceModelView(ModelView, DeleteMixin):
datamodel = SQLAInterface(models.Slice)
list_columns = ['slice_link', 'viz_type', 'created_by']
list_columns = ['slice_link', 'viz_type', 'datasource', 'created_by']

appbuilder.add_view(
SliceModelView,
Expand All @@ -116,6 +116,21 @@ class SliceModelView(ModelView, DeleteMixin):
category_icon='',)


class DashboardModelView(ModelView, DeleteMixin):
datamodel = SQLAInterface(models.Dashboard)
list_columns = ['dashboard_link', 'created_by']
edit_columns = ['dashboard_title', 'slices',]
add_columns = edit_columns


appbuilder.add_view(
DashboardModelView,
"Dashboards",
icon="fa-dashboard",
category="",
category_icon='',)


class DatabaseView(ModelView, DeleteMixin):
datamodel = SQLAInterface(models.Database)
list_columns = ['database_name']
Expand Down Expand Up @@ -258,9 +273,17 @@ def save(self):
return "super!"

@has_access
@expose("/dashboard/")
def dashboard(self):
return self.render_template("panoramix/dashboard.html")
@expose("/dashboard/<id_>/")
def dashboard(self, id_):
session = db.session()
dashboard = (
session
.query(models.Dashboard)
.filter(models.Dashboard.id == id_)
.first()
)
return self.render_template(
"panoramix/dashboard.html", dashboard=dashboard)

@has_access
@expose("/refresh_datasources/")
Expand Down
7 changes: 7 additions & 0 deletions panoramix/viz.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class BaseViz(object):
form_fields = [
'viz_type', 'metrics', 'groupby', 'granularity',
('since', 'until')]
js_files = []
css_files = []

def __init__(self, datasource, form_data, view):
self.datasource = datasource
Expand Down Expand Up @@ -137,6 +139,8 @@ class TableViz(BaseViz):
verbose_name = "Table View"
template = 'panoramix/viz_table.html'
form_fields = BaseViz.form_fields + ['row_limit']
css_files = ['dataTables.bootstrap.css']
js_files = ['jquery.dataTables.min.js', 'dataTables.bootstrap.js']

def query_obj(self):
d = super(TableViz, self).query_obj()
Expand Down Expand Up @@ -165,6 +169,7 @@ class HighchartsViz(BaseViz):
stacked = False
chart_type = 'not_stock'
compare = False
js_files = ['highcharts.js']


class BubbleViz(HighchartsViz):
Expand All @@ -174,6 +179,7 @@ class BubbleViz(HighchartsViz):
form_fields = [
'viz_type', 'since', 'until',
'series', 'entity', 'x', 'y', 'size', 'limit']
js_files = ['highcharts.js', 'highcharts-more.js']

def query_obj(self):
d = super(BubbleViz, self).query_obj()
Expand Down Expand Up @@ -212,6 +218,7 @@ class TimeSeriesViz(HighchartsViz):
chart_type = "spline"
stockchart = True
sort_legend_y = True
js_files = ['highstock.js', 'highcharts-more.js']
form_fields = [
'viz_type',
'granularity', ('since', 'until'),
Expand Down

0 comments on commit a5b8964

Please sign in to comment.