Add pager_controls directive and pager service. Add pagination to Dashboard and Visualize landing pages. Change Dashboard listing to use hrefs for each dashboard.

This commit is contained in:
CJ Cenizal 2017-02-03 16:37:28 -08:00
parent 43ceb6e0e1
commit d1d3da7741
12 changed files with 284 additions and 48 deletions

View file

@ -31,10 +31,6 @@
</div>
</div>
<div class="kuiToolBarSection">
<!-- We need an empty section for the buttons to be positioned consistently. -->
</div>
<div class="kuiToolBarSection">
<!-- Bulk delete button -->
<button
@ -59,6 +55,21 @@
<span aria-hidden="true" class="kuiButton__icon kuiIcon fa-plus"></span>
</a>
</div>
<div class="kuiToolBarSection">
<!-- Pagination -->
<tool-bar-pager-text
start-item="listingController.pager.startItem"
end-item="listingController.pager.endItem"
total-items="listingController.pager.totalItems"
></tool-bar-pager-text>
<tool-bar-pager-buttons
has-previous-page="listingController.pager.hasPreviousPage"
has-next-page="listingController.pager.hasNextPage"
on-page-next="listingController.onPageNext"
on-page-previous="listingController.onPagePrevious"
></tool-bar-pager-buttons>
</div>
</div>
<!-- NoResults -->
@ -118,7 +129,7 @@
<tbody>
<tr
ng-repeat="item in listingController.items track by item.id"
ng-repeat="item in listingController.pageOfItems track by item.id"
class="kuiTableRow"
>
<td class="kuiTableRowCell kuiTableRowCell--checkBox">
@ -132,7 +143,7 @@
<td class="kuiTableRowCell">
<div class="kuiTableRowCell__liner">
<a class="kuiLink" ng-click="listingController.open(item)">
<a class="kuiLink" ng-href="{{ listingController.getUrlForItem(item) }}">
{{ item.title }}
</a>
</div>
@ -149,8 +160,20 @@
{{ listingController.getSelectedItemsCount() }} selected
</div>
</div>
<div class="kuiToolBarFooterSection">
<!-- We need an empty section for the buttons to be positioned consistently. -->
<div class="kuiToolBarSection">
<!-- Pagination -->
<tool-bar-pager-text
start-item="listingController.pager.startItem"
end-item="listingController.pager.endItem"
total-items="listingController.pager.totalItems"
></tool-bar-pager-text>
<tool-bar-pager-buttons
has-previous-page="listingController.pager.hasPreviousPage"
has-next-page="listingController.pager.hasNextPage"
on-page-next="listingController.onPageNext"
on-page-previous="listingController.onPagePrevious"
></tool-bar-pager-buttons>
</div>
</div>
</div>

View file

@ -1,17 +1,22 @@
import SavedObjectRegistryProvider from 'ui/saved_objects/saved_object_registry';
import 'ui/pager_control';
import 'ui/pager';
import { DashboardConstants } from '../dashboard_constants';
import _ from 'lodash';
export function DashboardListingController(
$filter,
$scope,
confirmModal,
kbnUrl,
Notifier,
pagerService,
Private,
timefilter,
confirmModal
timefilter
) {
timefilter.enabled = false;
const limitTo = $filter('limitTo');
// TODO: Extract this into an external service.
const services = Private(SavedObjectRegistryProvider).byLoaderPropertiesName;
const dashboardService = services.dashboards;
@ -19,17 +24,38 @@ export function DashboardListingController(
let selectedItems = [];
/**
* Sorts hits either ascending or descending
* @param {Array} hits Array of saved finder object hits
* @return {Array} Array sorted either ascending or descending
*/
const sortItems = () => {
this.items =
this.isAscending
? _.sortBy(this.items, 'title')
: _.sortBy(this.items, 'title').reverse();
};
const calculateItemsOnPage = () => {
sortItems();
this.pager.setTotalItems(this.items.length);
this.pageOfItems = limitTo(this.items, this.pager.pageSize, this.pager.startIndex);
};
const fetchObjects = () => {
dashboardService.find(this.filter)
.then(result => {
this.items = result.hits;
this.sortItems();
calculateItemsOnPage();
});
};
this.items = [];
this.pageOfItems = [];
this.filter = '';
this.pager = pagerService.create(this.items.length, 20, 1);
/**
* Boolean that keeps track of whether hits are sorted ascending (true)
* or descending (false) by title
@ -37,21 +63,9 @@ export function DashboardListingController(
*/
this.isAscending = true;
/**
* Sorts hits either ascending or descending
* @param {Array} hits Array of saved finder object hits
* @return {Array} Array sorted either ascending or descending
*/
this.sortItems = function sortItems() {
this.items =
this.isAscending
? _.sortBy(this.items, 'title')
: _.sortBy(this.items, 'title').reverse();
};
this.toggleSort = function toggleSort() {
this.isAscending = !this.isAscending;
this.sortItems();
calculateItemsOnPage();
};
this.toggleAll = function toggleAll() {
@ -102,8 +116,18 @@ export function DashboardListingController(
});
};
this.open = function open(item) {
kbnUrl.change(item.url.substr(1));
this.onPageNext = () => {
this.pager.nextPage();
calculateItemsOnPage();
};
this.onPagePrevious = () => {
this.pager.previousPage();
calculateItemsOnPage();
};
this.getUrlForItem = function getUrlForItem(item) {
return `#/dashboard/${item.id}`;
};
$scope.$watch(() => this.filter, () => {

View file

@ -30,10 +30,6 @@
</div>
</div>
<div class="kuiToolBarSection">
<!-- We need an empty section for the buttons to be positioned consistently. -->
</div>
<div class="kuiToolBarSection">
<!-- Bulk delete button -->
<button
@ -57,6 +53,21 @@
<span aria-hidden="true" class="kuiButton__icon kuiIcon fa-plus"></span>
</a>
</div>
<div class="kuiToolBarSection">
<!-- Pagination -->
<tool-bar-pager-text
start-item="listingController.pager.startItem"
end-item="listingController.pager.endItem"
total-items="listingController.pager.totalItems"
></tool-bar-pager-text>
<tool-bar-pager-buttons
has-previous-page="listingController.pager.hasPreviousPage"
has-next-page="listingController.pager.hasNextPage"
on-page-next="listingController.onPageNext"
on-page-previous="listingController.onPagePrevious"
></tool-bar-pager-buttons>
</div>
</div>
<!-- NoResults -->
@ -101,7 +112,7 @@
<tbody>
<tr
ng-repeat="item in listingController.items track by item.id"
ng-repeat="item in listingController.pageOfItems track by item.id"
class="kuiTableRow"
>
<td class="kuiTableRowCell kuiTableRowCell--checkBox">
@ -141,8 +152,20 @@
{{ listingController.getSelectedItemsCount() }} selected
</div>
</div>
<div class="kuiToolBarFooterSection">
<!-- We need an empty section for the buttons to be positioned consistently. -->
<!-- Pagination -->
<tool-bar-pager-text
start-item="listingController.pager.startItem"
end-item="listingController.pager.endItem"
total-items="listingController.pager.totalItems"
></tool-bar-pager-text>
<tool-bar-pager-buttons
has-previous-page="listingController.pager.hasPreviousPage"
has-next-page="listingController.pager.hasNextPage"
on-page-next="listingController.onPageNext"
on-page-previous="listingController.onPagePrevious"
></tool-bar-pager-buttons>
</div>
</div>
</div>

View file

@ -1,16 +1,21 @@
import SavedObjectRegistryProvider from 'ui/saved_objects/saved_object_registry';
import 'ui/pager_control';
import 'ui/pager';
import _ from 'lodash';
export function VisualizeListingController(
$filter,
$scope,
confirmModal,
kbnUrl,
Notifier,
pagerService,
Private,
timefilter
) {
timefilter.enabled = false;
const limitTo = $filter('limitTo');
// TODO: Extract this into an external service.
const services = Private(SavedObjectRegistryProvider).byLoaderPropertiesName;
const visualizationService = services.visualizations;
@ -18,17 +23,40 @@ export function VisualizeListingController(
let selectedItems = [];
/**
* Sorts hits either ascending or descending
* @param {Array} hits Array of saved finder object hits
* @return {Array} Array sorted either ascending or descending
*/
const sortItems = () => {
const sortProperty = this.getSortProperty();
this.items =
sortProperty.isAscending
? _.sortBy(this.items, sortProperty.getValue)
: _.sortBy(this.items, sortProperty.getValue).reverse();
};
const calculateItemsOnPage = () => {
sortItems();
this.pager.setTotalItems(this.items.length);
this.pageOfItems = limitTo(this.items, this.pager.pageSize, this.pager.startIndex);
};
const fetchObjects = () => {
visualizationService.find(this.filter)
.then(result => {
this.items = result.hits;
this.sortItems();
calculateItemsOnPage();
});
};
this.items = [];
this.pageOfItems = [];
this.filter = '';
this.pager = pagerService.create(this.items.length, 20, 1);
/**
* Remember sort direction per property.
*/
@ -57,20 +85,6 @@ export function VisualizeListingController(
return sortProperty.isAscending;
};
/**
* Sorts hits either ascending or descending
* @param {Array} hits Array of saved finder object hits
* @return {Array} Array sorted either ascending or descending
*/
this.sortItems = function sortItems() {
const sortProperty = this.getSortProperty();
this.items =
sortProperty.isAscending
? _.sortBy(this.items, sortProperty.getValue)
: _.sortBy(this.items, sortProperty.getValue).reverse();
};
this.sortOn = function sortOn(propertyName) {
const sortProperty = this.getSortProperty();
@ -81,7 +95,7 @@ export function VisualizeListingController(
this.getSortPropertyByName(propertyName).isSelected = true;
}
this.sortItems();
calculateItemsOnPage();
};
this.toggleAll = function toggleAll() {
@ -133,6 +147,16 @@ export function VisualizeListingController(
});
};
this.onPageNext = () => {
this.pager.nextPage();
calculateItemsOnPage();
};
this.onPagePrevious = () => {
this.pager.previousPage();
calculateItemsOnPage();
};
this.getUrlForItem = function getUrlForItem(item) {
return `#/visualize/edit/${item.id}`;
};

View file

@ -0,0 +1 @@
import './pager_service.factory';

View file

@ -0,0 +1,12 @@
import uiModules from 'ui/modules';
import { PagerService } from './pager_service';
const app = uiModules.get('kibana');
app.factory('pagerService', () => {
return {
create(...args) {
return new PagerService(...args);
}
};
});

View file

@ -0,0 +1,58 @@
function clamp(val, min, max) {
return Math.min(Math.max(min, val), max);
}
export class PagerService {
constructor(totalItems, pageSize, startingPage) {
this.currentPage = startingPage;
this.totalItems = totalItems;
this.pageSize = pageSize;
this.startIndex = 0;
this.updateMeta();
}
get pageCount() {
return Math.ceil(this.totalItems / this.pageSize);
}
get hasNextPage() {
return this.currentPage < this.totalPages;
}
get hasPreviousPage() {
return this.currentPage > 1;
}
nextPage() {
this.currentPage += 1;
this.updateMeta();
}
previousPage() {
this.currentPage -= 1;
this.updateMeta();
}
setTotalItems(count) {
this.totalItems = count;
this.updateMeta();
}
setPageSize(count) {
this.pageSize = count;
this.updateMeta();
}
updateMeta() {
this.totalPages = Math.ceil(this.totalItems / this.pageSize);
this.currentPage = clamp(this.currentPage, 1, this.totalPages);
this.startItem = ((this.currentPage - 1) * this.pageSize) + 1;
this.startItem = clamp(this.startItem, 0, this.totalItems);
this.endItem = (this.startItem - 1) + this.pageSize;
this.endItem = clamp(this.endItem, 0, this.totalItems);
this.startIndex = this.startItem - 1;
}
}

View file

@ -0,0 +1,16 @@
<div class="kuiButtonGroup">
<button
class="kuiButton kuiButton--basic kuiButton--icon"
ng-click="toolBarPagerButtons.previousPage()"
ng-disabled="!toolBarPagerButtons.hasPreviousPage"
>
<span class="kuiButton__icon kuiIcon fa-chevron-left"></span>
</button>
<button
class="kuiButton kuiButton--basic kuiButton--icon"
ng-click="toolBarPagerButtons.nextPage()"
ng-disabled="!toolBarPagerButtons.hasNextPage"
>
<span class="kuiButton__icon kuiIcon fa-chevron-right"></span>
</button>
</div>

View file

@ -0,0 +1,29 @@
import uiModules from 'ui/modules';
import template from './tool_bar_pager_buttons.html';
const app = uiModules.get('kibana');
app.directive('toolBarPagerButtons', function () {
return {
restrict: 'E',
replace: true,
template: template,
scope: {
hasNextPage: '=',
hasPreviousPage: '=',
onPageNext: '=',
onPagePrevious: '=',
},
controllerAs: 'toolBarPagerButtons',
bindToController: true,
controller: class ToolBarPagerButtonsController {
nextPage = () => {
this.onPageNext();
};
previousPage = () => {
this.onPagePrevious();
};
}
};
});

View file

@ -0,0 +1,3 @@
<div class="kuiToolBarText">
{{ toolBarPagerText.startItem | number }}&ndash;{{ toolBarPagerText.endItem | number }} of {{ toolBarPagerText.totalItems | number }}
</div>

View file

@ -0,0 +1,21 @@
import uiModules from 'ui/modules';
import template from './tool_bar_pager_text.html';
const app = uiModules.get('kibana');
app.directive('toolBarPagerText', function () {
return {
restrict: 'E',
replace: true,
template: template,
scope: {
startItem: '=',
endItem: '=',
totalItems: '=',
},
controllerAs: 'toolBarPagerText',
bindToController: true,
controller: class ToolBarPagerTextController {
}
};
});

View file

@ -0,0 +1,2 @@
import './components/tool_bar_pager_text/tool_bar_pager_text';
import './components/tool_bar_pager_buttons/tool_bar_pager_buttons';