mirror of
https://github.com/valitydev/redash.git
synced 2024-11-07 09:28:51 +00:00
This applies to the queries, dashboard and users views.
This commit is contained in:
parent
5b2ec81e65
commit
af3a1e00c6
@ -17,14 +17,12 @@ export default class ListCtrl {
|
||||
if (this.pageOrderReverse) {
|
||||
this.pageOrder = this.pageOrder.substr(1);
|
||||
}
|
||||
|
||||
this.defaultOptions = {};
|
||||
|
||||
// use $parent because we're using a component as route target instead of controller;
|
||||
// $parent refers to scope created for the page by router
|
||||
this.resource = $scope.$parent.$resolve.resource;
|
||||
this.currentPage = $scope.$parent.$resolve.currentPage;
|
||||
|
||||
this.currentUser = currentUser;
|
||||
|
||||
this.showEmptyState = false;
|
||||
@ -38,20 +36,12 @@ export default class ListCtrl {
|
||||
|
||||
this.isInSearchMode = () => this.searchTerm !== undefined && this.searchTerm !== null && this.searchTerm.length > 0;
|
||||
|
||||
const fetcher = (requestedPage, itemsPerPage, orderByField, orderByReverse) => {
|
||||
const fetcher = (requestedPage, itemsPerPage, orderByField, orderByReverse, paginator, requested = false) => {
|
||||
$location.search('page', requestedPage);
|
||||
$location.search('page_size', itemsPerPage);
|
||||
|
||||
if (orderByReverse && !orderByField.startsWith(this.orderSeparator)) {
|
||||
orderByField = this.orderSeparator + orderByField;
|
||||
}
|
||||
if (orderByField) {
|
||||
$location.search('order', orderByField);
|
||||
} else {
|
||||
$location.search('order', undefined);
|
||||
}
|
||||
|
||||
const request = this.getRequest(requestedPage, itemsPerPage, orderByField);
|
||||
const order = this.getOrder(orderByField, orderByReverse, requested, paginator);
|
||||
$location.search('order', order);
|
||||
const request = this.getRequest(requestedPage, itemsPerPage, order);
|
||||
|
||||
if (this.searchTerm === '') {
|
||||
this.searchTerm = null;
|
||||
@ -80,8 +70,12 @@ export default class ListCtrl {
|
||||
};
|
||||
|
||||
this.update = () => {
|
||||
// `queriesFetcher` will be called by paginator
|
||||
this.paginator.setPage(this.page, this.pageSize);
|
||||
this.paginator.setPage(
|
||||
this.page,
|
||||
this.pageSize,
|
||||
this.pageOrder,
|
||||
this.pageOrderReverse,
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@ -89,6 +83,27 @@ export default class ListCtrl {
|
||||
this.loaded = true;
|
||||
}
|
||||
|
||||
getOrder(orderByField, orderByReverse, requested, paginator) {
|
||||
// in search mode ignore the ordering and use the ranking order
|
||||
// provided by the server-side FTS backend instead, unless it was
|
||||
// requested by the user by actively ordering in search mode
|
||||
if (this.isInSearchMode() && !requested) {
|
||||
orderByField = undefined;
|
||||
} else {
|
||||
this.pageOrder = orderByField;
|
||||
this.pageOrderReverse = orderByReverse;
|
||||
}
|
||||
// pass the current ordering state to the paginator
|
||||
// so the sort icons work correctly
|
||||
paginator.orderByField = orderByField;
|
||||
paginator.orderByReverse = orderByReverse;
|
||||
// combine the ordering field and direction in one query parameter
|
||||
if (orderByField && orderByReverse && !orderByField.startsWith(this.orderSeparator)) {
|
||||
orderByField = this.orderSeparator + orderByField;
|
||||
}
|
||||
return orderByField;
|
||||
}
|
||||
|
||||
getRequest(requestedPage, itemsPerPage, orderByField) {
|
||||
const request = Object.assign({}, this.defaultOptions, {
|
||||
page: requestedPage,
|
||||
|
@ -10,11 +10,17 @@ export default class LivePaginator {
|
||||
this.fetchPage(page);
|
||||
}
|
||||
|
||||
fetchPage(page) {
|
||||
this.rowsFetcher(page, this.itemsPerPage, this.orderByField, this.orderByReverse);
|
||||
fetchPage(page, requested = false) {
|
||||
this.rowsFetcher(page, this.itemsPerPage, this.orderByField, this.orderByReverse, this, requested);
|
||||
}
|
||||
|
||||
setPage(page, pageSize) {
|
||||
setPage(page, pageSize, pageOrder, pageOrderReverse) {
|
||||
if (pageOrder) {
|
||||
this.orderByField = pageOrder;
|
||||
}
|
||||
if (pageOrderReverse) {
|
||||
this.orderByReverse = pageOrderReverse;
|
||||
}
|
||||
if (pageSize) {
|
||||
this.itemsPerPage = pageSize;
|
||||
}
|
||||
@ -44,7 +50,7 @@ export default class LivePaginator {
|
||||
}
|
||||
|
||||
if (this.orderByField) {
|
||||
this.fetchPage(this.page);
|
||||
this.fetchPage(this.page, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -130,20 +130,26 @@ def filter_by_tags(result_set, column):
|
||||
if request.args.getlist('tags'):
|
||||
tags = request.args.getlist('tags')
|
||||
result_set = result_set.filter(cast(column, postgresql.ARRAY(db.Text)).contains(tags))
|
||||
|
||||
return result_set
|
||||
|
||||
|
||||
def order_results(results, default_order, orders_whitelist):
|
||||
def order_results(results, default_order, allowed_orders, fallback=True):
|
||||
"""
|
||||
Orders the given results with the sort order as requested in the
|
||||
"order" request query parameter or the given default order.
|
||||
"""
|
||||
# See if a particular order has been requested
|
||||
order = request.args.get('order', '').strip() or default_order
|
||||
requested_order = request.args.get('order', '').strip()
|
||||
|
||||
# and if not (and no fallback is wanted) return results as is
|
||||
if not requested_order and not fallback:
|
||||
return results
|
||||
|
||||
# and if it matches a long-form for related fields, falling
|
||||
# back to the default order
|
||||
selected_order = orders_whitelist.get(order, default_order)
|
||||
selected_order = allowed_orders.get(requested_order, None)
|
||||
if selected_order is None and fallback:
|
||||
selected_order = default_order
|
||||
# The query may already have an ORDER BY statement attached
|
||||
# so we clear it here and apply the selected order
|
||||
return sort_query(results.order_by(None), selected_order)
|
||||
|
@ -1,5 +1,5 @@
|
||||
from flask import request, url_for
|
||||
from funcy import project, rpartial
|
||||
from funcy import project, partial
|
||||
|
||||
from flask_restful import abort
|
||||
from redash import models, serializers
|
||||
@ -21,7 +21,11 @@ order_map = {
|
||||
'-created_at': '-created_at',
|
||||
}
|
||||
|
||||
order_results = rpartial(_order_results, '-created_at', order_map)
|
||||
order_results = partial(
|
||||
_order_results,
|
||||
default_order='-created_at',
|
||||
allowed_orders=order_map,
|
||||
)
|
||||
|
||||
|
||||
class DashboardListResource(BaseResource):
|
||||
@ -56,8 +60,10 @@ class DashboardListResource(BaseResource):
|
||||
|
||||
results = filter_by_tags(results, models.Dashboard.tags)
|
||||
|
||||
# order results according to passed order parameter
|
||||
ordered_results = order_results(results)
|
||||
# order results according to passed order parameter,
|
||||
# special-casing search queries where the database
|
||||
# provides an order by search rank
|
||||
ordered_results = order_results(results, fallback=bool(search_term))
|
||||
|
||||
page = request.args.get('page', 1, type=int)
|
||||
page_size = request.args.get('page_size', 25, type=int)
|
||||
|
@ -20,8 +20,10 @@ class QueryFavoriteListResource(BaseResource):
|
||||
|
||||
favorites = filter_by_tags(favorites, models.Query.tags)
|
||||
|
||||
# order results according to passed order parameter
|
||||
ordered_favorites = order_results(favorites)
|
||||
# order results according to passed order parameter,
|
||||
# special-casing search queries where the database
|
||||
# provides an order by search rank
|
||||
ordered_favorites = order_results(favorites, fallback=bool(search_term))
|
||||
|
||||
page = request.args.get('page', 1, type=int)
|
||||
page_size = request.args.get('page_size', 25, type=int)
|
||||
|
@ -3,7 +3,7 @@ from flask import jsonify, request, url_for
|
||||
from flask_login import login_required
|
||||
from flask_restful import abort
|
||||
from sqlalchemy.orm.exc import StaleDataError
|
||||
from funcy import rpartial
|
||||
from funcy import partial
|
||||
|
||||
from redash import models
|
||||
from redash.authentication.org_resolving import current_org
|
||||
@ -34,7 +34,11 @@ order_map = {
|
||||
'-created_by': '-users-name',
|
||||
}
|
||||
|
||||
order_results = rpartial(_order_results, '-created_at', order_map)
|
||||
order_results = partial(
|
||||
_order_results,
|
||||
default_order='-created_at',
|
||||
allowed_orders=order_map,
|
||||
)
|
||||
|
||||
|
||||
@routes.route(org_scoped_rule('/api/queries/format'), methods=['POST'])
|
||||
@ -188,8 +192,10 @@ class QueryListResource(BaseResource):
|
||||
|
||||
results = filter_by_tags(results, models.Query.tags)
|
||||
|
||||
# order results according to passed order parameter
|
||||
ordered_results = order_results(results)
|
||||
# order results according to passed order parameter,
|
||||
# special-casing search queries where the database
|
||||
# provides an order by search rank
|
||||
ordered_results = order_results(results, fallback=bool(search_term))
|
||||
|
||||
page = request.args.get('page', 1, type=int)
|
||||
page_size = request.args.get('page_size', 25, type=int)
|
||||
@ -239,8 +245,10 @@ class MyQueriesResource(BaseResource):
|
||||
|
||||
results = filter_by_tags(results, models.Query.tags)
|
||||
|
||||
# order results according to passed order parameter
|
||||
ordered_results = order_results(results)
|
||||
# order results according to passed order parameter,
|
||||
# special-casing search queries where the database
|
||||
# provides an order by search rank
|
||||
ordered_results = order_results(results, fallback=bool(search_term))
|
||||
|
||||
page = request.args.get('page', 1, type=int)
|
||||
page_size = request.args.get('page_size', 25, type=int)
|
||||
|
@ -5,7 +5,7 @@ from flask_login import current_user
|
||||
from funcy import project
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
from disposable_email_domains import blacklist
|
||||
from funcy import rpartial
|
||||
from funcy import partial
|
||||
|
||||
from redash import models
|
||||
from redash.permissions import require_permission, require_admin_or_owner, is_admin_or_owner, \
|
||||
@ -25,7 +25,11 @@ order_map = {
|
||||
'-groups': '-group_ids',
|
||||
}
|
||||
|
||||
order_results = rpartial(_order_results, '-created_at', order_map)
|
||||
order_results = partial(
|
||||
_order_results,
|
||||
default_order='-created_at',
|
||||
allowed_orders=order_map,
|
||||
)
|
||||
|
||||
|
||||
def invite_user(org, inviter, user):
|
||||
@ -75,9 +79,12 @@ class UserListResource(BaseResource):
|
||||
'object_type': 'user',
|
||||
})
|
||||
|
||||
users = order_results(users)
|
||||
# order results according to passed order parameter,
|
||||
# special-casing search queries where the database
|
||||
# provides an order by search rank
|
||||
ordered_users = order_results(users, fallback=bool(search_term))
|
||||
|
||||
return paginate(users, page, page_size, serialize_user)
|
||||
return paginate(ordered_users, page, page_size, serialize_user)
|
||||
|
||||
@require_admin
|
||||
def post(self):
|
||||
|
Loading…
Reference in New Issue
Block a user