Merge pull request #29 from mistercrunch/markup_widgets

Adding support for markup (html/markdown) widgets
This commit is contained in:
Maxime Beauchemin 2015-09-22 22:58:57 -07:00
commit 11c291b9a1
7 changed files with 76 additions and 13 deletions

View File

@ -1,10 +1,12 @@
# TODO
* Add a per-datasource permission
* in/notin filters autocomplete
* DRUID: Allow for post aggregations (ratios!)
* compare time ranges
* csv export out of table view
* SQL: Find a way to manage granularity
* Create ~/.panoramix/ to host DB and config, generate default config there
* Add a per-datasource permission
* Reintroduce query and stopwatch
* Sort tooltip
* Add a "Test Connection" button in Add Connection menu

View File

@ -107,7 +107,7 @@ def load_examples():
def get_slice_json(
slice_name, filter_value, viz_type="table", group_by=None,
granularity="all", filter_operator='in',
row_limit=config.ROW_LIMIT, flt_col_1="gender"):
row_limit=config.ROW_LIMIT, flt_col_1="gender", code=""):
group_by = group_by if group_by is not None else ["name"]
default_json = {
"compare_lag": "10",
@ -130,7 +130,9 @@ def load_examples():
"slice_name": slice_name,
"until": "now",
"viz_type": viz_type,
"where": ""
"where": "",
"code": code,
"markup_type": "markdown",
}
return json.dumps(default_json, indent=4, sort_keys=True)
Slice = models.Slice
@ -210,6 +212,24 @@ def load_examples():
session.add(slc)
slices.append(slc)
slice_name = "Title"
slc = session.query(Slice).filter_by(slice_name=slice_name).first()
code = """
### Birth Names Dashboard
The source dataset came from [here](https://github.com/hadley/babynames)
![img](http://monblog.system-linux.net/image/tux/baby-tux_overlord59-tux.png)
"""
if not slc:
slc = Slice(
slice_name=slice_name,
viz_type='markup',
datasource_type='table',
table=tbl,
params=get_slice_json(
slice_name, "", "markup", ['name'], code=code))
session.add(slc)
slices.append(slc)
print("Creating a dashboard")
Dash = models.Dashboard
@ -222,44 +242,51 @@ def load_examples():
{
"size_y": 5,
"size_x": 2,
"col": 5,
"col": 10,
"slice_id": "1",
"row": 1
},
{
"size_y": 5,
"size_x": 2,
"col": 7,
"col": 8,
"slice_id": "2",
"row": 1
},
{
"size_y": 2,
"size_x": 2,
"col": 1,
"col": 6,
"slice_id": "3",
"row": 1
},
{
"size_y": 2,
"size_x": 2,
"col": 3,
"col": 4,
"slice_id": "4",
"row": 1
},
{
"size_y": 3,
"size_x": 4,
"col": 1,
"col": 4,
"slice_id": "5",
"row": 3
},
{
"size_y": 6,
"size_x": 8,
"size_x": 11,
"col": 1,
"slice_id": "6",
"row": 6
},
{
"size_y": 5,
"size_x": 3,
"col": 1,
"slice_id": "9",
"row": 1
}
]
"""

View File

@ -1,4 +1,5 @@
from wtforms import Field, Form, SelectMultipleField, SelectField, TextField
from wtforms import (
Field, Form, SelectMultipleField, SelectField, TextField, TextAreaField)
from copy import copy
@ -84,6 +85,12 @@ def form_factory(viz):
description="Based on granularity, number of time periods to compare against"),
'compare_suffix': TextField('Comparison suffix',
description="Suffix to apply after the percentage display"),
'markup_type': SelectField(
"Markup Type",
choices=[(s, s) for s in ['markdown', 'html']],
default="markdown",
description="Pick your favorite markup language"),
'code': TextAreaField("Code", description="Put your code here"),
}
field_css_classes = {k: ['form-control'] for k in px_form_fields.keys()}
select2 = [

View File

@ -0,0 +1,9 @@
{% macro viz_html(viz) %}
<div style="padding: 10px;">{{ viz.rendered()|safe }}</div>
{% endmacro %}
{% macro viz_js(viz) %}
{% endmacro %}
{% macro viz_css(viz) %}
{% endmacro %}

View File

@ -10,7 +10,7 @@ from pydruid.client import doublesum
from wtforms.validators import ValidationError
from flask.ext.appbuilder.actions import action
from panoramix import appbuilder, db, models, viz, utils, app
from panoramix import appbuilder, db, models, viz, utils, app, config
def validate_json(form, field):
@ -291,6 +291,8 @@ class Panoramix(BaseView):
try:
resp = self.render_template("panoramix/viz.html", viz=obj)
except Exception as e:
if config.DEBUG:
raise(e)
return Response(
str(e),
status=500,

View File

@ -4,6 +4,7 @@ import json
import uuid
from flask import flash
from markdown import markdown
from werkzeug.datastructures import MultiDict
from werkzeug.urls import Href
import numpy as np
@ -21,7 +22,6 @@ CHART_ARGS = {
class BaseViz(object):
verbose_name = "Base Viz"
template = None
hidden_fields = []
form_fields = [
'viz_type', 'metrics', 'groupby', 'granularity',
('since', 'until')]
@ -161,6 +161,20 @@ class TableViz(BaseViz):
return df
class MarkupViz(BaseViz):
verbose_name = "Markup Widget"
template = 'panoramix/viz_markup.html'
form_fields = ['viz_type', 'markup_type', 'code']
def rendered(self):
markup_type = self.form_data.get("markup_type")
code = self.form_data.get("code", '')
if markup_type == "markdown":
return markdown(code)
elif markup_type == "html":
return code
class HighchartsViz(BaseViz):
verbose_name = "Base Highcharts Viz"
template = 'panoramix/viz_highcharts.html'
@ -174,7 +188,6 @@ class HighchartsViz(BaseViz):
class BubbleViz(HighchartsViz):
verbose_name = "Bubble Chart"
chart_type = 'bubble'
hidden_fields = ['granularity', 'metrics', 'groupby']
form_fields = [
'viz_type', 'since', 'until',
'series', 'entity', 'x', 'y', 'size', 'limit']
@ -376,4 +389,6 @@ viz_types = OrderedDict([
['dist_bar', DistributionBarViz],
['pie', DistributionPieViz],
['bubble', BubbleViz],
['markup', MarkupViz],
['word_cloud', WordCloudViz],
])

View File

@ -2,6 +2,7 @@ flask
flask-migrate
flask-appbuilder
gunicorn
markdown
mysql-python
pandas
parsedatetime