diff --git a/superset/assets/javascripts/dashboard/Dashboard.jsx b/superset/assets/javascripts/dashboard/Dashboard.jsx
index dc02a7ef14f44..e8509a5f06320 100644
--- a/superset/assets/javascripts/dashboard/Dashboard.jsx
+++ b/superset/assets/javascripts/dashboard/Dashboard.jsx
@@ -14,8 +14,8 @@ import Header from './components/Header';
require('bootstrap');
require('../../stylesheets/dashboard.css');
-export function getInitialState(dashboardData, context) {
- const dashboard = Object.assign({ context }, utils.controllerInterface, dashboardData);
+export function getInitialState(boostrapData) {
+ const dashboard = Object.assign({}, utils.controllerInterface, boostrapData.dashboard_data);
dashboard.firstLoad = true;
dashboard.posDict = {};
@@ -24,12 +24,8 @@ export function getInitialState(dashboardData, context) {
dashboard.posDict[position.slice_id] = position;
});
}
- dashboard.curUserId = dashboard.context.user_id;
dashboard.refreshTimer = null;
-
- const state = {
- dashboard,
- };
+ const state = Object.assign({}, boostrapData, { dashboard });
return state;
}
@@ -98,19 +94,19 @@ function initDashboardView(dashboard) {
$('[data-toggle="tooltip"]').tooltip({ container: 'body' });
}
-export function dashboardContainer(dashboard) {
+export function dashboardContainer(dashboard, datasources) {
return Object.assign({}, dashboard, {
type: 'dashboard',
filters: {},
init() {
this.sliceObjects = [];
- dashboard.slices.forEach((data) => {
+ dashboard.slices.forEach(data => {
if (data.error) {
- const html = '
' + data.error + '
';
- $('#slice_' + data.slice_id).find('.token').html(html);
+ const html = `${data.error}
`;
+ $(`#slice_${data.slice_id}`).find('.token').html(html);
} else {
- const slice = px.Slice(data, this);
- $('#slice_' + data.slice_id).find('a.refresh').click(() => {
+ const slice = px.Slice(data, datasources[data.form_data.datasource], this);
+ $(`#slice_${data.slice_id}`).find('a.refresh').click(() => {
slice.render(true);
});
this.sliceObjects.push(slice);
@@ -337,11 +333,10 @@ export function dashboardContainer(dashboard) {
$(document).ready(() => {
// Getting bootstrapped data from the DOM
utils.initJQueryAjaxCSRF();
- const dashboardData = $('.dashboard').data('dashboard');
- const contextData = $('.dashboard').data('context');
+ const dashboardData = $('.dashboard').data('bootstrap');
- const state = getInitialState(dashboardData, contextData);
- const dashboard = dashboardContainer(state.dashboard);
+ const state = getInitialState(dashboardData);
+ const dashboard = dashboardContainer(state.dashboard, state.datasources);
initDashboardView(dashboard);
dashboard.init();
});
diff --git a/superset/assets/javascripts/dashboard/components/Controls.jsx b/superset/assets/javascripts/dashboard/components/Controls.jsx
index cb78d862bcd8a..463a75ffb3251 100644
--- a/superset/assets/javascripts/dashboard/components/Controls.jsx
+++ b/superset/assets/javascripts/dashboard/components/Controls.jsx
@@ -43,7 +43,7 @@ class Controls extends React.PureComponent {
}
render() {
const dashboard = this.props.dashboard;
- const canSave = dashboard.context.dash_save_perm;
+ const canSave = dashboard.dash_save_perm;
const emailBody = `Checkout this dashboard: ${window.location.href}`;
const emailLink = 'mailto:?Subject=Superset%20Dashboard%20'
+ `${dashboard.dashboard_title}&Body=${emailBody}`;
diff --git a/superset/assets/javascripts/dashboard/components/Header.jsx b/superset/assets/javascripts/dashboard/components/Header.jsx
index 58230b95cdebf..3e8e407f86a95 100644
--- a/superset/assets/javascripts/dashboard/components/Header.jsx
+++ b/superset/assets/javascripts/dashboard/components/Header.jsx
@@ -25,7 +25,7 @@ class Header extends React.PureComponent {
- {!this.props.dashboard.context.standalone_mode &&
+ {!this.props.dashboard.standalone_mode &&
}
diff --git a/superset/assets/javascripts/modules/superset.js b/superset/assets/javascripts/modules/superset.js
index 6076875dec23a..d95d159acbf6a 100644
--- a/superset/assets/javascripts/modules/superset.js
+++ b/superset/assets/javascripts/modules/superset.js
@@ -55,7 +55,7 @@ const px = function () {
})
.tooltip();
}
- const Slice = function (data, controller) {
+ const Slice = function (data, datasource, controller) {
let timer;
const token = $('#token_' + data.slice_id);
const containerId = 'con_' + data.slice_id;
@@ -74,6 +74,7 @@ const px = function () {
formData,
container,
containerId,
+ datasource,
selector,
getWidgetHeader() {
return this.container.parents('div.widget').find('.chart-header');
@@ -105,11 +106,11 @@ const px = function () {
d3format(col, number) {
// uses the utils memoized d3format function and formats based on
// column level defined preferences
- if (data.column_formats) {
- const format = data.column_formats[col];
- return utils.d3format(format, number);
+ let format = '.3s';
+ if (this.datasource.column_formats[col]) {
+ format = this.datasource.column_formats[col];
}
- return utils.d3format('.3s', number);
+ return utils.d3format(format, number);
},
/* eslint no-shadow: 0 */
always(data) {
diff --git a/superset/connectors/base.py b/superset/connectors/base.py
index c96f2bbb9969b..02016a09319f8 100644
--- a/superset/connectors/base.py
+++ b/superset/connectors/base.py
@@ -44,6 +44,11 @@ class BaseDatasource(AuditMixinNullable, ImportMixin):
# placeholder for a relationship to a derivative of BaseMetric
metrics = []
+ @property
+ def uid(self):
+ """Unique id across datasource types"""
+ return "{self.id}__{self.type}".format(**locals())
+
@property
def column_names(self):
return sorted([c.column_name for c in self.columns])
diff --git a/superset/models/core.py b/superset/models/core.py
index 79b2e63b8b32b..0cbcd15c4b413 100644
--- a/superset/models/core.py
+++ b/superset/models/core.py
@@ -336,11 +336,11 @@ def dashboard_link(self):
'{title}'.format(**locals()))
@property
- def json_data(self):
+ def data(self):
positions = self.position_json
if positions:
positions = json.loads(positions)
- d = {
+ return {
'id': self.id,
'metadata': self.params_dict,
'css': self.css,
@@ -349,7 +349,6 @@ def json_data(self):
'slices': [slc.data for slc in self.slices],
'position_json': positions,
}
- return json.dumps(d)
@property
def params(self):
diff --git a/superset/templates/superset/dashboard.html b/superset/templates/superset/dashboard.html
index f899d6fa0a24b..8fe4a6ed5bfc1 100644
--- a/superset/templates/superset/dashboard.html
+++ b/superset/templates/superset/dashboard.html
@@ -6,13 +6,12 @@
{% include "superset/partials/_script_tag.html" %}
{% endwith %}
{% endblock %}
-{% block title %}[dashboard] {{ dashboard.dashboard_title }}{% endblock %}
+{% block title %}[dashboard] {{ dashboard_title }}{% endblock %}
{% block body %}
{% include 'superset/flash_wrapper.html' %}
diff --git a/superset/views/core.py b/superset/views/core.py
index 1d4e4f88a0e5d..1c0b7bb688aba 100755
--- a/superset/views/core.py
+++ b/superset/views/core.py
@@ -1257,7 +1257,7 @@ def copy_dash(self, dashboard_id):
self._set_dash_metadata(dash, data)
session.add(dash)
session.commit()
- dash_json = dash.json_data
+ dash_json = json.dumps(dash.data)
session.close()
return json_success(dash_json)
@@ -1628,29 +1628,36 @@ def dashboard(self, dashboard_id):
"danger")
return redirect(
'superset/request_access/?'
- 'dashboard_id={dash.id}&'
- ''.format(**locals()))
+ 'dashboard_id={dash.id}&'.format(**locals()))
# Hack to log the dashboard_id properly, even when getting a slug
@log_this
def dashboard(**kwargs): # noqa
pass
dashboard(dashboard_id=dash.id)
+
dash_edit_perm = check_ownership(dash, raise_if_false=False)
dash_save_perm = \
dash_edit_perm and self.can_access('can_save_dash', 'Superset')
- standalone = request.args.get("standalone") == "true"
- context = dict(
- user_id=g.user.get_id(),
- dash_save_perm=dash_save_perm,
- dash_edit_perm=dash_edit_perm,
- standalone_mode=standalone,
- )
+
+ dashboard_data = dash.data
+ dashboard_data.update({
+ 'standalone_mode': request.args.get("standalone") == "true",
+ })
+
+ bootstrap_data = {
+ 'user_id': g.user.get_id(),
+ 'dash_save_perm': dash_save_perm,
+ 'dash_edit_perm': dash_edit_perm,
+ 'dash_edit_perm': check_ownership(dash, raise_if_false=False),
+ 'dashboard_data': dash.data,
+ 'datasources': {ds.uid: ds.data for ds in datasources},
+ }
+
return self.render_template(
"superset/dashboard.html",
- dashboard=dash,
- context=json.dumps(context),
- standalone_mode=standalone,
+ dashboard_title=dash.dashboard_title,
+ bootstrap_data=json.dumps(bootstrap_data),
)
@has_access
diff --git a/tests/core_tests.py b/tests/core_tests.py
index d18f2d93900c5..f9e6c8a964c4d 100644
--- a/tests/core_tests.py
+++ b/tests/core_tests.py
@@ -396,7 +396,7 @@ def test_copy_dash(self, username='admin'):
self.client.post(url, data=dict(data=json.dumps(data)))
dash = db.session.query(models.Dashboard).filter_by(
id=dash_id).first()
- orig_json_data = json.loads(dash.json_data)
+ orig_json_data = dash.data
# Verify that copy matches original
url = '/superset/copy_dash/{}/'.format(dash_id)