Skip to content

Commit

Permalink
Feature: UI for query parameters
Browse files Browse the repository at this point in the history
This pull request implements UI for parameters and also allows to set the default value and type of a parameter.
(Closes #583)

Other changes in this pull request:

- Loading/error state for dashboard widgets.
- Refresh button on dashboard widgets (Closes #810).
- Maintain sync between query/dashboard URL and current parameters, and preserve them when navigating.
- Removed Pivot Table tab.
  • Loading branch information
arikfr committed Jun 14, 2016
1 parent 790128c commit c2e3637
Show file tree
Hide file tree
Showing 16 changed files with 313 additions and 123 deletions.
10 changes: 10 additions & 0 deletions migrations/0024_add_options_to_query.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from redash.models import db, Query
from playhouse.migrate import PostgresqlMigrator, migrate

if __name__ == '__main__':
migrator = PostgresqlMigrator(db.database)

with db.database.transaction():
migrate(
migrator.add_column('queries', 'options', Query.options),
)
12 changes: 9 additions & 3 deletions rd_ui/app/scripts/controllers/dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -211,14 +211,20 @@

Events.record(currentUser, "view", "widget", $scope.widget.id);

$scope.reload = function(force) {
var maxAge = $location.search()['maxAge'];
if (force) {
maxAge = 0;
}
$scope.queryResult = $scope.query.getQueryResult(maxAge);
};

if ($scope.widget.visualization) {
Events.record(currentUser, "view", "query", $scope.widget.visualization.query.id);
Events.record(currentUser, "view", "visualization", $scope.widget.visualization.id);

$scope.query = $scope.widget.getQuery();
var parameters = Query.collectParamsFromQueryString($location, $scope.query);
var maxAge = $location.search()['maxAge'];
$scope.queryResult = $scope.query.getQueryResult(maxAge, parameters);
$scope.reload(false);

$scope.type = 'visualization';
} else if ($scope.widget.restricted) {
Expand Down
12 changes: 5 additions & 7 deletions rd_ui/app/scripts/controllers/query_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
var DEFAULT_TAB = 'table';

var getQueryResult = function(maxAge) {
// Collect params, and getQueryResult with params; getQueryResult merges it into the query
var parameters = Query.collectParamsFromQueryString($location, $scope.query);
if (maxAge === undefined) {
maxAge = $location.search()['maxAge'];
}
Expand All @@ -16,7 +14,7 @@
}

$scope.showLog = false;
$scope.queryResult = $scope.query.getQueryResult(maxAge, parameters);
$scope.queryResult = $scope.query.getQueryResult(maxAge);
};

var getDataSourceId = function() {
Expand Down Expand Up @@ -127,17 +125,17 @@
if (data) {
data.id = $scope.query.id;
} else {
data = _.clone($scope.query);
data = _.pick($scope.query, ["schedule", "query", "id", "description", "name", "data_source_id", "options"]);
if ($scope.query.isNew()) {
data['latest_query_data_id'] = $scope.query.latest_query_data_id;
}
}

options = _.extend({}, {
successMessage: 'Query saved',
errorMessage: 'Query could not be saved'
}, options);

delete data.latest_query_data;
delete data.queryResult;

return Query.save(data, function() {
growl.addSuccessMessage(options.successMessage);
}, function(httpResponse) {
Expand Down
42 changes: 40 additions & 2 deletions rd_ui/app/scripts/directives/directives.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,14 @@
restrict: 'E',
scope: {
'tabId': '@',
'name': '@'
'name': '@',
'basePath': '=?'
},
transclude: true,
template: '<li class="rd-tab" ng-class="{active: tabId==selectedTab}"><a href="{{basePath}}#{{tabId}}">{{name}}<span ng-transclude></span></a></li>',
replace: true,
link: function (scope) {
scope.basePath = $location.path().substring(1);
scope.basePath = scope.basePath || $location.path().substring(1);
scope.$watch(function () {
return scope.$parent.selectedTab
}, function (tab) {
Expand Down Expand Up @@ -496,4 +497,41 @@
}
}]);

directives.directive('parameters', ['$location', '$modal', function($location, $modal) {
return {
restrict: 'E',
transclude: true,
scope: {
'parameters': '=',
'syncValues': '=?',
'editable': '=?'
},
templateUrl: '/views/directives/parameters.html',
link: function(scope, elem, attrs) {
// is this the correct location for this logic?
if (scope.syncValues !== false) {
scope.$watch('parameters', function() {
_.each(scope.parameters, function(param) {
if (param.value !== null || param.value !== '') {
$location.search('p_' + param.name, param.value);
}
})
}, true);
}

scope.showParameterSettings = function(param) {
$modal.open({
templateUrl: '/views/dialogs/parameter_settings.html',
controller: ['$scope', '$modalInstance', function($scope, $modalInstance) {
$scope.close = function() {
$modalInstance.close();
};
$scope.parameter = param;
}]
})
}
}
}
}]);

})();
16 changes: 8 additions & 8 deletions rd_ui/app/scripts/directives/query_directives.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,29 @@
},
template: '<a ng-href="{{link}}" class="query-link">{{query.name}}</a>',
link: function(scope, element) {
scope.link = 'queries/' + scope.query.id;
var hash = null;
if (scope.visualization) {
if (scope.visualization.type === 'TABLE') {
// link to hard-coded table tab instead of the (hidden) visualization tab
scope.link += '#table';
hash = 'table';
} else {
scope.link += '#' + scope.visualization.id;
hash = scope.visualization.id;
}
}
// element.find('a').attr('href', link);
scope.link = scope.query.getUrl(false, hash);
}
}
}

function querySourceLink() {
function querySourceLink($location) {
return {
restrict: 'E',
template: '<span ng-show="query.id && canViewSource">\
<a ng-show="!sourceMode"\
ng-href="queries/{{query.id}}/source#{{selectedTab}}" class="btn btn-default">Show Source\
ng-href="{{query.getUrl(true, selectedTab)}}" class="btn btn-default">Show Source\
</a>\
<a ng-show="sourceMode"\
ng-href="queries/{{query.id}}#{{selectedTab}}" class="btn btn-default">Hide Source\
ng-href="{{query.getUrl(false, selectedTab)}}" class="btn btn-default">Hide Source\
</a>\
</span>'
}
Expand Down Expand Up @@ -285,7 +285,7 @@

angular.module('redash.directives')
.directive('queryLink', queryLink)
.directive('querySourceLink', querySourceLink)
.directive('querySourceLink', ['$location', querySourceLink])
.directive('queryResultLink', queryResultLink)
.directive('queryEditor', queryEditor)
.directive('queryRefreshSelect', queryRefreshSelect)
Expand Down
6 changes: 6 additions & 0 deletions rd_ui/app/scripts/filters.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,10 @@ angular.module('redash.filters', []).
filtered.push(items[i])
return filtered;
};
})

.filter('notEmpty', function() {
return function(collection) {
return !_.isEmpty(collection);
}
});
Loading

0 comments on commit c2e3637

Please sign in to comment.