mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
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:
parent
43ceb6e0e1
commit
d1d3da7741
12 changed files with 284 additions and 48 deletions
|
@ -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>
|
||||
|
|
|
@ -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, () => {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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}`;
|
||||
};
|
||||
|
|
1
src/ui/public/pager/index.js
Normal file
1
src/ui/public/pager/index.js
Normal file
|
@ -0,0 +1 @@
|
|||
import './pager_service.factory';
|
12
src/ui/public/pager/pager_service.factory.js
Normal file
12
src/ui/public/pager/pager_service.factory.js
Normal 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);
|
||||
}
|
||||
};
|
||||
});
|
58
src/ui/public/pager/pager_service.js
Normal file
58
src/ui/public/pager/pager_service.js
Normal 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;
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -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();
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
|
@ -0,0 +1,3 @@
|
|||
<div class="kuiToolBarText">
|
||||
{{ toolBarPagerText.startItem | number }}–{{ toolBarPagerText.endItem | number }} of {{ toolBarPagerText.totalItems | number }}
|
||||
</div>
|
|
@ -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 {
|
||||
}
|
||||
};
|
||||
});
|
2
src/ui/public/pager_control/index.js
Normal file
2
src/ui/public/pager_control/index.js
Normal 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';
|
Loading…
Add table
Add a link
Reference in a new issue