Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change: paginate queries page & add explicit urls. #1306

Merged
merged 1 commit into from
Oct 5, 2016
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
12 changes: 12 additions & 0 deletions migrations/0026_add_queries_org_index.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from redash.models import db
from playhouse.migrate import PostgresqlMigrator, migrate

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

with db.database.transaction():
migrate(
migrator.add_index('queries', ('org_id',)),
)

db.close_db(None)
10 changes: 10 additions & 0 deletions rd_ui/app/scripts/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,16 @@ angular.module('redash', [
}]
}
});
$routeProvider.when('/queries/my', {
templateUrl: '/views/queries.html',
controller: 'QueriesCtrl',
reloadOnSearch: false
});
$routeProvider.when('/queries/drafts', {
templateUrl: '/views/queries.html',
controller: 'QueriesCtrl',
reloadOnSearch: false
});
$routeProvider.when('/queries/search', {
templateUrl: '/views/queries_search_results.html',
controller: 'QuerySearchCtrl',
Expand Down
123 changes: 49 additions & 74 deletions rd_ui/app/scripts/controllers/controllers.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,91 +63,66 @@
};

var QueriesCtrl = function ($scope, $http, $location, $filter, Query) {
$scope.$parent.pageTitle = "All Queries";
$scope.gridConfig = {
isPaginationEnabled: true,
itemsByPage: 50,
maxSize: 8,
isGlobalSearchActivated: true};
var loader;

$scope.allQueries = [];
$scope.queries = [];
$scope.page = parseInt($location.search().page || 1);
$scope.total = undefined;
$scope.pageSize = 25;

function loadQueries(resource, defaultOptions) {
return function(options) {
options = _.extend({}, defaultOptions, options);
resource(options, function (queries) {
$scope.totalQueriesCount = queries.count;
$scope.queries = _.map(queries.results, function (query) {
query.created_at = moment(query.created_at);
query.retrieved_at = moment(query.retrieved_at);
return query;
});
});
}
}

var filterQueries = function () {
$scope.queries = _.filter($scope.allQueries, function (query) {
if (!$scope.selectedTab) {
return false;
}

if ($scope.selectedTab.key == 'my') {
return query.user.id == currentUser.id && query.name != 'New Query';
} else if ($scope.selectedTab.key == 'drafts') {
return query.user.id == currentUser.id && query.name == 'New Query';
}

return query.name != 'New Query';
});
switch($location.path()) {
case '/queries':
$scope.$parent.pageTitle = "Queries";
// page title
loader = loadQueries(Query.query);
break;
case '/queries/drafts':
$scope.$parent.pageTitle = "Drafts";
loader = loadQueries(Query.myQueries, {drafts: true});
break;
case '/queries/my':
$scope.$parent.pageTitle = "My Queries";
loader = loadQueries(Query.myQueries);
break;
}

Query.query(function (queries) {
$scope.allQueries = _.map(queries, function (query) {
query.created_at = moment(query.created_at);
query.retrieved_at = moment(query.retrieved_at);
return query;
});
var loadAllQueries = loadQueries(Query.query);
var loadMyQueries = loadQueries(Query.myQueries);

filterQueries();
});
function load() {
var options = {page: $scope.page, page_size: $scope.pageSize};
loader(options);
}

$scope.gridColumns = [
{
"label": "Name",
"map": "name",
"cellTemplateUrl": "/views/queries_query_name_cell.html"
},
{
'label': 'Created By',
'map': 'user.name'
},
{
'label': 'Created At',
'map': 'created_at',
'formatFunction': dateFormatter
},
{
'label': 'Runtime',
'map': 'runtime',
'formatFunction': function (value) {
return $filter('durationHumanize')(value);
}
},
{
'label': 'Last Executed At',
'map': 'retrieved_at',
'formatFunction': dateFormatter
},
{
'label': 'Update Schedule',
'map': 'schedule',
'formatFunction': function (value) {
return $filter('scheduleHumanize')(value);
}
}
]
$scope.selectPage = function(page) {
$location.search('page', page);
$scope.page = page;
load();
}

$scope.tabs = [
{"name": "My Queries", "key": "my"},
{"key": "all", "name": "All Queries"},
{"key": "drafts", "name": "Drafts"}
{"name": "My Queries", "path": "queries/my", loader: loadMyQueries},
{"path": "queries", "name": "All Queries", isActive: function(path) {
return path === '/queries';
}, "loader": loadAllQueries},
{"path": "queries/drafts", "name": "Drafts", loader: loadMyQueries},
];

$scope.$watch('selectedTab', function (tab) {
if (tab) {
$scope.$parent.pageTitle = tab.name;
}

filterQueries();
});
load();
}

var MainCtrl = function ($scope, $location, Dashboard) {
Expand Down
122 changes: 111 additions & 11 deletions rd_ui/app/scripts/directives/directives.js
Original file line number Diff line number Diff line change
Expand Up @@ -483,21 +483,121 @@
restrict: 'E',
transclude: true,
templateUrl: '/views/directives/settings_screen.html',
link: function(scope, elem, attrs) {
scope.usersPage = _.string.startsWith($location.path(), '/users');
scope.groupsPage = _.string.startsWith($location.path(), '/groups');
scope.dsPage = _.string.startsWith($location.path(), '/data_sources');
scope.destinationsPage = _.string.startsWith($location.path(), '/destinations');
scope.snippetsPage = _.string.startsWith($location.path(), '/query_snippets');

scope.showGroupsLink = currentUser.hasPermission('list_users');
scope.showUsersLink = currentUser.hasPermission('list_users');
scope.showDsLink = currentUser.hasPermission('admin');
scope.showDestinationsLink = currentUser.hasPermission('admin');
controller: ['$scope', function(scope) {
scope.tabs = [];

if (currentUser.hasPermission('admin')) {
scope.tabs.push({name: 'Data Sources', path: 'data_sources'});
}

if (currentUser.hasPermission('list_users')) {
scope.tabs.push({name: 'Users', path: 'users'});
scope.tabs.push({name: 'Groups', path: 'groups'});
}

if (currentUser.hasPermission('admin')) {
scope.tabs.push({name: 'Alert Destinations', path: 'destinations'});
}

scope.tabs.push({name: "Query Snippets", path: "query_snippets"});
}]
}
}]);

directives.directive('tabNav', ['$location', function($location) {
return {
restrict: 'E',
transclude: true,
scope: {
tabs: '='
},
template: '<ul class="tab-nav bg-white">' +
'<li ng-repeat="tab in tabs" ng-class="{\'active\': tab.active }"><a ng-href="{{tab.path}}">{{tab.name}}</a></li>' +
'</ul>',
link: function($scope) {
_.each($scope.tabs, function(tab) {
if (tab.isActive) {
tab.active = tab.isActive($location.path());
} else {
tab.active = _.string.startsWith($location.path(), "/" + tab.path);
}
});
}
}
}]);

directives.directive('queriesList', [function () {
return {
restrict: 'E',
replace: true,
scope: {
queries: '=',
total: '=',
selectPage: '=',
page: '=',
pageSize: '='
},
templateUrl: '/views/directives/queries_list.html',
link: function ($scope) {
function hasNext() {
return !($scope.page * $scope.pageSize >= $scope.total);
}

function hasPrevious() {
return $scope.page !== 1;
}

function updatePages() {
if ($scope.total === undefined) {
return;
}

var maxSize = 5;
var pageCount = Math.ceil($scope.total/$scope.pageSize);
var pages = [];

function makePage(title, page, disabled) {
return {title: title, page: page, active: page == $scope.page, disabled: disabled};
}

// Default page limits
var startPage = 1, endPage = pageCount;

// recompute if maxSize
if (maxSize && maxSize < pageCount) {
startPage = Math.max($scope.page - Math.floor(maxSize / 2), 1);
endPage = startPage + maxSize - 1;

// Adjust if limit is exceeded
if (endPage > pageCount) {
endPage = pageCount;
startPage = endPage - maxSize + 1;
}
}

// Add page number links
for (var number = startPage; number <= endPage; number++) {
var page = makePage(number, number, false);
pages.push(page);
}

// Add previous & next links
var previousPage = makePage('<', $scope.page - 1, !hasPrevious());
pages.unshift(previousPage);

var nextPage = makePage('>', $scope.page + 1, !hasNext());
pages.push(nextPage);

$scope.pages = pages;
}

$scope.$watch('total', updatePages);
$scope.$watch('page', updatePages);
}
}
}]);


directives.directive('parameters', ['$location', '$modal', function($location, $modal) {
return {
restrict: 'E',
Expand Down
3 changes: 3 additions & 0 deletions rd_ui/app/scripts/filters.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ angular.module('redash.filters', []).

.filter('dateTime', function() {
return function(value) {
if (!value) {
return '-';
}
return moment(value).format(clientConfig.dateTimeFormat);
}
})
Expand Down
10 changes: 9 additions & 1 deletion rd_ui/app/scripts/services/resources.js
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,14 @@
method: 'get',
isArray: true,
url: "api/queries/recent"
},
query: {
isArray: false
},
myQueries: {
method: 'get',
isArray: false,
url: "api/queries/my"
}
});

Expand Down Expand Up @@ -769,7 +777,7 @@
"tabTrigger": this.trigger
};
}

return resource;
};

Expand Down
30 changes: 30 additions & 0 deletions rd_ui/app/views/directives/queries_list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<div class="bg-white">
<table class="table table-condensed table-hover">
<thead>
<tr>
<th>Name</th>
<th>Created By</th>
<th>Created At</th>
<th>Runtime</th>
<th>Last Executed At</th>
<th>Update Schedule</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="query in queries">
<td><a href="queries/{{query.id}}">{{query.name}}</a></td>
<td>{{query.user.name}}</td>
<td>{{query.created_at | dateTime}}</td>
<td>{{query.runtime | durationHumanize}}</td>
<td>{{query.retrieved_at | dateTime}}</td>
<td>{{query.schedule | scheduleHumanize}}</td>
</tr>
</tbody>
</table>

<div class="text-center">
<ul class="pagination">
<li ng-repeat="p in pages" ng-class="{active: p.active, disabled: p.disabled}"><a ng-click="selectPage(p.page)">{{p.title}}</a></li>
</ul>
</div>
</div>
8 changes: 1 addition & 7 deletions rd_ui/app/views/directives/settings_screen.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,7 @@

<div class="container">
<div class="container bg-white p-5">
<ul class="tab-nav">
<li ng-class="{'active': dsPage }" ng-if="showDsLink"><a href="data_sources">Data Sources</a></li>
<li ng-class="{'active': usersPage }" ng-if="showUsersLink"><a href="users">Users</a></li>
<li ng-class="{'active': groupsPage }" ng-if="showGroupsLink"><a href="groups">Groups</a></li>
<li ng-class="{'active': destinationsPage }" ng-if="showDestinationsLink"><a href="destinations">Alert Destinations</a></li>
<li ng-class="{'active': snippetsPage }"><a href="query_snippets">Query Snippets</a></li>
</ul>
<tab-nav tabs="tabs"></tab-nav>

<div ng-transclude>

Expand Down
6 changes: 2 additions & 4 deletions rd_ui/app/views/queries.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
<div class="container">
<page-header title="Queries"></page-header>

<rd-tabs tabs-collection='tabs' selected-tab='selectedTab'></rd-tabs>
<smart-table rows="queries" columns="gridColumns"
config="gridConfig"
class="table table-condensed table-hover"></smart-table>
<tab-nav tabs="tabs"></tab-nav>
<queries-list queries="queries" total="totalQueriesCount" page="page" select-page="selectPage" page-size="pageSize"></queries-list>
</div>
Loading