Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,11 @@ class ControlPanelsContainer extends React.Component {
</Alert>
}
{this.sectionsToRender().map((section) => {
const hasErrors = section.controlSetRows.some(rows => rows.some((s) => {
const errors = ctrls[s].validationErrors;
return errors && (errors.length > 0);
}));
const hasErrors = section.controlSetRows.some(rows => rows.some(s => (
ctrls[s] &&
ctrls[s].validationErrors &&
(ctrls[s].validationErrors.length > 0)
)));
return (
<ControlPanelSection
key={section.label}
Expand Down
7 changes: 7 additions & 0 deletions superset/assets/javascripts/explore/stores/controls.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,13 @@ export const controls = {
}),
},

order_desc: {
type: 'CheckboxControl',
label: 'Sort Descending',
default: true,
description: 'Whether to sort descending or ascending',
},

rolling_type: {
type: 'SelectControl',
label: 'Rolling',
Expand Down
4 changes: 3 additions & 1 deletion superset/assets/javascripts/explore/stores/visTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export const sections = {
['metrics'],
['groupby'],
['limit', 'timeseries_limit_metric'],
['order_desc', null],
],
},
{
Expand Down Expand Up @@ -324,7 +325,8 @@ export const visTypes = {
description: 'Use this section if you want a query that aggregates',
controlSetRows: [
['groupby', 'metrics'],
['include_time'],
['include_time', null],
['timeseries_limit_metric', 'order_desc'],
],
},
{
Expand Down
18 changes: 15 additions & 3 deletions superset/assets/visualizations/table.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,22 @@ function tableVis(slice, payload) {
fixDataTableBodyHeight(
container.find('.dataTables_wrapper'), height);
// Sorting table by main column
if (metrics.length > 0) {
const mainMetric = metrics[0];
datatable.column(data.columns.indexOf(mainMetric)).order('desc').draw();
let sortBy;
if (fd.timeseries_limit_metric) {
// Sort by as specified
sortBy = fd.timeseries_limit_metric;
} else if (metrics.length > 0) {
// If not specified, use the first metric from the list
sortBy = metrics[0];
}
if (sortBy) {
datatable.column(data.columns.indexOf(sortBy)).order(fd.order_desc ? 'desc' : 'asc');
}
if (fd.timeseries_limit_metric && metrics.indexOf(fd.timeseries_limit_metric) < 0) {
// Hiding the sortBy column if not in the metrics list
datatable.column(data.columns.indexOf(sortBy)).visible(false);
}
datatable.draw();
container.parents('.widget').find('.tooltip').remove();
}

Expand Down
33 changes: 19 additions & 14 deletions superset/connectors/sqla/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,8 @@ def get_sqla_query( # sqla
template_processor = self.get_template_processor(**template_kwargs)
db_engine_spec = self.database.db_engine_spec

orderby = orderby or []

# For backward compatibility
if granularity not in self.dttm_cols:
granularity = self.main_dttm_col
Expand All @@ -392,15 +394,12 @@ def get_sqla_query( # sqla
raise Exception(_(
"Datetime column not provided as part table configuration "
"and is required by this type of chart"))
if not groupby and not metrics and not columns:
raise Exception(_("Empty query?"))
for m in metrics:
if m not in metrics_dict:
raise Exception(_("Metric '{}' is not valid".format(m)))
metrics_exprs = [metrics_dict.get(m).sqla_col for m in metrics]
timeseries_limit_metric = metrics_dict.get(timeseries_limit_metric)
timeseries_limit_metric_expr = None
if timeseries_limit_metric:
timeseries_limit_metric_expr = \
timeseries_limit_metric.sqla_col
if metrics_exprs:
main_metric_expr = metrics_exprs[0]
else:
Expand Down Expand Up @@ -512,13 +511,16 @@ def get_sqla_query( # sqla
else:
qry = qry.where(and_(*where_clause_and))
qry = qry.having(and_(*having_clause_and))
if groupby:
direction = desc if order_desc else asc
qry = qry.order_by(direction(main_metric_expr))
elif orderby:
for col, ascending in orderby:
direction = asc if ascending else desc
qry = qry.order_by(direction(col))

if not orderby and not columns:
orderby = [(main_metric_expr, not order_desc)]

for col, ascending in orderby:
direction = asc if ascending else desc
print('-='*20)
print([col, ascending])
print('-='*20)
qry = qry.order_by(direction(col))

if row_limit:
qry = qry.limit(row_limit)
Expand All @@ -538,12 +540,15 @@ def get_sqla_query( # sqla
)
subq = subq.where(and_(*(where_clause_and + [inner_time_filter])))
subq = subq.group_by(*inner_groupby_exprs)

ob = inner_main_metric_expr
if timeseries_limit_metric_expr is not None:
ob = timeseries_limit_metric_expr
if timeseries_limit_metric:
timeseries_limit_metric = metrics_dict.get(timeseries_limit_metric)
ob = timeseries_limit_metric.sqla_col
direction = desc if order_desc else asc
subq = subq.order_by(direction(ob))
subq = subq.limit(timeseries_limit)

on_clause = []
for i, gb in enumerate(groupby):
on_clause.append(
Expand Down
5 changes: 5 additions & 0 deletions superset/viz.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,11 +351,16 @@ def query_obj(self):
"Choose either fields to [Group By] and [Metrics] or "
"[Columns], not both"))

sort_by = fd.get('timeseries_limit_metric')
if fd.get('all_columns'):
d['columns'] = fd.get('all_columns')
d['groupby'] = []
order_by_cols = fd.get('order_by_cols') or []
d['orderby'] = [json.loads(t) for t in order_by_cols]
elif sort_by:
if sort_by not in d['metrics']:
d['metrics'] += [sort_by]
d['orderby'] = [(sort_by, not fd.get("order_desc", True))]

d['is_timeseries'] = self.should_be_timeseries()
return d
Expand Down