diff --git a/superset/assets/javascripts/explore/components/ControlPanelsContainer.jsx b/superset/assets/javascripts/explore/components/ControlPanelsContainer.jsx index dfa958c5088c..198529ab0925 100644 --- a/superset/assets/javascripts/explore/components/ControlPanelsContainer.jsx +++ b/superset/assets/javascripts/explore/components/ControlPanelsContainer.jsx @@ -65,10 +65,11 @@ class ControlPanelsContainer extends React.Component { } {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 ( 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(); } diff --git a/superset/connectors/sqla/models.py b/superset/connectors/sqla/models.py index 03c8c54a6c92..245da8a45e9d 100644 --- a/superset/connectors/sqla/models.py +++ b/superset/connectors/sqla/models.py @@ -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 @@ -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: @@ -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) @@ -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( diff --git a/superset/viz.py b/superset/viz.py index 7a2b22ac7f2e..9e11a6e9eedb 100644 --- a/superset/viz.py +++ b/superset/viz.py @@ -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