Allowing to define a default format string per-metric (#750)

This commit is contained in:
Maxime Beauchemin 2016-07-13 23:45:05 -04:00 committed by GitHub
parent 8312f1c2aa
commit f034f2701e
7 changed files with 63 additions and 6 deletions

View File

@ -2,6 +2,7 @@ var $ = require('jquery');
var jQuery = $;
var d3 = require('d3');
var Mustache = require('mustache');
var utils = require('./utils');
// vis sources
var sourceMap = {
@ -240,6 +241,12 @@ var px = (function () {
endpoint += "&force=" + this.force;
return endpoint;
},
d3format: function (col, number) {
// uses the utils memoized d3format function and formats based on
// column level defined preferences
var format = this.data.column_formats[col];
return utils.d3format(format, number);
},
done: function (data) {
clearInterval(timer);
token.find("img.loading").hide();

View File

@ -105,9 +105,20 @@ var fixDataTableBodyHeight = function ($tableDom, height) {
.css('max-height', height - headHeight);
};
var formatters = {};
function d3format(format, number) {
// Formats a number and memoizes formatters to be reused
format = format || '.3s';
if (!(format in formatters)) {
formatters[format] = d3.format(format);
}
return formatters[format](number);
}
module.exports = {
wrapSvgText: wrapSvgText,
showModal: showModal,
toggleCheckbox: toggleCheckbox,
fixDataTableBodyHeight: fixDataTableBodyHeight
fixDataTableBodyHeight: fixDataTableBodyHeight,
d3format: d3format
};

View File

@ -2,14 +2,13 @@ var $ = window.$ = require('jquery');
var jQuery = window.jQuery = $;
var d3 = require('d3');
var px = window.px || require('../javascripts/modules/caravel.js');
var utils = require('../javascripts/modules/utils.js');
require('./table.css');
require('datatables.net-bs');
require('../node_modules/datatables-bootstrap3-plugin/media/css/datatables-bootstrap3.css');
var utils = require('../javascripts/modules/utils');
function tableVis(slice) {
var f = d3.format('.3s');
var fC = d3.format('0,000');
var timestampFormatter;
@ -120,7 +119,7 @@ function tableVis(slice) {
})
.html(function (d) {
if (d.isMetric) {
return f(d.val);
return slice.d3format(d.col, d.val);
} else {
return d.val;
}

View File

@ -0,0 +1,24 @@
"""d3format_by_metric
Revision ID: f162a1dea4c4
Revises: 960c69cb1f5b
Create Date: 2016-07-06 22:04:28.685100
"""
# revision identifiers, used by Alembic.
revision = 'f162a1dea4c4'
down_revision = '960c69cb1f5b'
from alembic import op
import sqlalchemy as sa
def upgrade():
op.add_column('metrics', sa.Column('d3format', sa.String(length=128), nullable=True))
op.add_column('sql_metrics', sa.Column('d3format', sa.String(length=128), nullable=True))
def downgrade():
op.drop_column('sql_metrics', 'd3format')
op.drop_column('metrics', 'd3format')

View File

@ -870,6 +870,7 @@ class SqlMetric(Model, AuditMixinNullable):
expression = Column(Text)
description = Column(Text)
is_restricted = Column(Boolean, default=False, nullable=True)
d3format = Column(String(128))
@property
def sqla_col(self):
@ -1499,6 +1500,7 @@ class DruidMetric(Model, AuditMixinNullable):
json = Column(Text)
description = Column(Text)
is_restricted = Column(Boolean, default=False, nullable=True)
d3format = Column(String(128))
@property
def json_obj(self):

View File

@ -278,7 +278,7 @@ class SqlMetricInlineView(CompactCRUDMixin, CaravelModelView): # noqa
list_columns = ['metric_name', 'verbose_name', 'metric_type']
edit_columns = [
'metric_name', 'description', 'verbose_name', 'metric_type',
'expression', 'table', 'is_restricted']
'expression', 'table', 'd3format', 'is_restricted']
description_columns = {
'expression': utils.markdown(
"a valid SQL expression as supported by the underlying backend. "
@ -287,6 +287,13 @@ class SqlMetricInlineView(CompactCRUDMixin, CaravelModelView): # noqa
"to certain roles. Only roles with the permission "
"'metric access on XXX (the name of this metric)' "
"are allowed to access this metric"),
'd3format': utils.markdown(
"d3 formatting string as defined [here]"
"(https://github.com/d3/d3-format/blob/master/README.md#format). "
"For instance, this default formatting applies in the Table "
"visualization and allow for different metric to use different "
"formats", True
),
}
add_columns = edit_columns
page_size = 500
@ -313,7 +320,7 @@ class DruidMetricInlineView(CompactCRUDMixin, CaravelModelView): # noqa
list_columns = ['metric_name', 'verbose_name', 'metric_type']
edit_columns = [
'metric_name', 'description', 'verbose_name', 'metric_type', 'json',
'datasource', 'is_restricted']
'datasource', 'd3format', 'is_restricted']
add_columns = edit_columns
page_size = 500
validators_columns = {

View File

@ -310,6 +310,7 @@ class BaseViz(object):
# cache.set call can fail if the backend is down or if
# the key is too large or whatever other reasons
logging.warning("Could not cache key {}".format(cache_key))
logging.exception(e)
cache.delete(cache_key)
payload['is_cached'] = is_cached
return self.json_dumps(payload)
@ -320,6 +321,7 @@ class BaseViz(object):
@property
def data(self):
"""This is the data object serialized to the js layer"""
content = {
'csv_endpoint': self.csv_endpoint,
'form_data': self.form_data,
@ -327,6 +329,11 @@ class BaseViz(object):
'standalone_endpoint': self.standalone_endpoint,
'token': self.token,
'viz_name': self.viz_type,
'column_formats': {
m.metric_name: m.d3format
for m in self.datasource.metrics
if m.d3format
},
}
return content