[WIP] CORD-686 Added pagination to table
Change-Id: I26c57cdf9759363e2bce2fd5333f45d63694278b
diff --git a/src/app/core/index.ts b/src/app/core/index.ts
index a31aa96..318ffeb 100644
--- a/src/app/core/index.ts
+++ b/src/app/core/index.ts
@@ -21,6 +21,8 @@
import {XosComponentInjector} from './services/helpers/component-injector.helpers';
import {XosKeyboardShortcut} from './services/keyboard-shortcut';
import {xosKeyBindingPanel} from './key-binding/key-binding-panel';
+import {xosPagination} from './pagination/pagination';
+import {PaginationFilter} from './pagination/pagination.filter';
export const xosCore = 'xosCore';
@@ -45,10 +47,12 @@
.component('xosFooter', xosFooter)
.component('xosNav', xosNav)
.component('xosLogin', xosLogin)
+ .component('xosPagination', xosPagination)
.component('xosTable', xosTable)
.component('xosForm', xosForm)
.component('xosField', xosField)
.component('xosAlert', xosAlert)
.component('xosValidation', xosValidation)
.component('xosSidePanel', xosSidePanel)
- .component('xosKeyBindingPanel', xosKeyBindingPanel);
+ .component('xosKeyBindingPanel', xosKeyBindingPanel)
+ .filter('pagination', PaginationFilter);
diff --git a/src/app/core/pagination/pagination.filter.ts b/src/app/core/pagination/pagination.filter.ts
new file mode 100644
index 0000000..2a561c9
--- /dev/null
+++ b/src/app/core/pagination/pagination.filter.ts
@@ -0,0 +1,9 @@
+export function PaginationFilter() {
+ return function(input: any[], start: string) {
+ if (!input || !angular.isArray(input)) {
+ return input;
+ }
+ let position: number = parseInt(start, 10);
+ return input.slice(position);
+ };
+}
diff --git a/src/app/core/pagination/pagination.html b/src/app/core/pagination/pagination.html
new file mode 100644
index 0000000..3bcdb51
--- /dev/null
+++ b/src/app/core/pagination/pagination.html
@@ -0,0 +1,21 @@
+<div class="row" ng-if="vm.pageList.length > 1">
+ <div class="col-xs-12 text-center">
+ <ul class="pagination">
+ <li ng-click="vm.goToPage(vm.currentPage - 1)"
+ ng-class="{disabled: vm.currentPage == 0}">
+ <a href="" aria-label="Previous">
+ <span aria-hidden="true">«</span>
+ </a>
+ </li>
+ <li ng-repeat="i in vm.pageList" ng-class="{active: i === vm.currentPage}">
+ <a href="" ng-click="vm.goToPage(i)">{{i + 1}}</a>
+ </li>
+ <li ng-click="vm.goToPage(vm.currentPage + 1)"
+ ng-class="{disabled: vm.currentPage == vm.pages - 1}">
+ <a href="" aria-label="Next">
+ <span aria-hidden="true">»</span>
+ </a>
+ </li>
+ </ul>
+ </div>
+</div>
diff --git a/src/app/core/pagination/pagination.ts b/src/app/core/pagination/pagination.ts
new file mode 100644
index 0000000..997123c
--- /dev/null
+++ b/src/app/core/pagination/pagination.ts
@@ -0,0 +1,54 @@
+class XosPaginationCtrl {
+ $inject = ['$onInit', '$scope'];
+
+ public pageSize: number;
+ public totalElements: number;
+ public change: any; // fn
+ public currentPage: number;
+ public pages: number;
+ public pageList: number[];
+
+ constructor (
+ private $scope: ng.IScope
+ ) {
+ }
+
+ $onInit() {
+ this.currentPage = 0;
+
+ // watch for data changes
+ this.$scope.$watch(() => this.totalElements, () => {
+ if (this.totalElements) {
+ this.pages = Math.ceil(this.totalElements / this.pageSize);
+ this.pageList = this.createPages(this.pages);
+ }
+ });
+ }
+
+ public goToPage = (n) => {
+ if (n < 0 || n === this.pages) {
+ return;
+ }
+ this.currentPage = n;
+ this.change(n);
+ };
+
+ private createPages = (pages) => {
+ let arr = [];
+ for (let i = 0; i < pages; i++) {
+ arr.push(i);
+ }
+ return arr;
+ };
+}
+
+export const xosPagination: angular.IComponentOptions = {
+ template: require('./pagination.html'),
+ controllerAs: 'vm',
+ controller: XosPaginationCtrl,
+ bindings: {
+ pageSize: '=',
+ totalElements: '=',
+ change: '='
+ }
+};
diff --git a/src/app/core/services/helpers/config.helpers.ts b/src/app/core/services/helpers/config.helpers.ts
index b8ff208..28a16a3 100644
--- a/src/app/core/services/helpers/config.helpers.ts
+++ b/src/app/core/services/helpers/config.helpers.ts
@@ -33,7 +33,7 @@
stateWithParamsForJs(name: string, model: any): any;
}
-export class ConfigHelpers {
+export class ConfigHelpers implements IXosConfigHelpersService {
static $inject = ['$state', 'toastr', 'AuthService', 'ModelStore'];
excluded_fields = [
@@ -96,6 +96,9 @@
columns: this.modelFieldsToColumnsCfg(model.fields, model.name),
filter: 'fulltext',
order: {field: 'id', reverse: false},
+ pagination: {
+ pageSize: 10
+ },
actions: [
{
label: 'delete',
@@ -135,24 +138,23 @@
if (f.name === 'id' || f.name === 'name') {
col.link = item => this.stateWithParams(modelName, item);
- // NOTE can we find a better method to generalize the route?
- // col.link = item => `#/core${baseUrl.replace(':id?', item.id)}`;
}
// if the field identify a relation, create a link
if (f.relation && f.relation.type === 'many_to_one') {
- // TODO read the related model name and replace the value, use the xosTable format method?
col.type = 'custom';
col.formatter = item => {
this.populateRelated(item, item[f.name], f);
return item[f.name];
};
col.link = item => this.stateWithParams(f.relation.model, item);
- // col.link = item => `#${this.urlFromCoreModel(f.relation.model)}/${item[f.name]}`;
}
if (f.name === 'backend_status') {
col.type = 'icon';
+ col.hover = (item) => {
+ return item[f.name];
+ };
col.formatter = (item) => {
if (item.backend_status.indexOf('1') > -1) {
return 'check';
diff --git a/src/app/core/table/table.html b/src/app/core/table/table.html
index 788e84c..d7df1db 100644
--- a/src/app/core/table/table.html
+++ b/src/app/core/table/table.html
@@ -48,7 +48,7 @@
</tr>
</tbody>
<tbody>
- <tr ng-repeat="item in vm.data | filter:vm.query | orderBy:vm.orderBy:vm.reverse track by $index">
+ <tr ng-repeat="item in vm.data | filter:vm.query | orderBy:vm.orderBy:vm.reverse | pagination:vm.currentPage * vm.config.pagination.pageSize | limitTo: (vm.config.pagination.pageSize || vm.data.length) track by $index">
<td ng-repeat="col in vm.columns" xos-link-wrapper>
<span ng-if="!col.type || col.type === 'text'">{{item[col.prop]}}</span>
<span ng-if="col.type === 'boolean'">
@@ -77,7 +77,12 @@
<span ng-if="col.type === 'icon'">
<i class="fa fa-{{col.formatter(item)}}">
</i>
- </span>
+ </span>
+ <div class="xos-table-hover" ng-if="col.hover">
+ <div class="alert alert-info">
+ {{col.hover(item)}}
+ </div>
+ </div>
</td>
<td ng-if="vm.config.actions">
<a href=""
@@ -92,6 +97,12 @@
</tr>
</tbody>
</table>
+ <xos-pagination
+ ng-if="vm.config.pagination"
+ page-size="vm.config.pagination.pageSize"
+ total-elements="vm.data.length"
+ change="vm.goToPage">
+ </xos-pagination>
</div>
<!--</div>-->
<!--<div ng-show="(vm.data.length == 0 || !vm.data) && vm.loader == false">-->
diff --git a/src/app/core/table/table.scss b/src/app/core/table/table.scss
index a2af05e..9922026 100644
--- a/src/app/core/table/table.scss
+++ b/src/app/core/table/table.scss
@@ -1,3 +1,6 @@
+@import './../../style/vars.scss';
+@import '../../../../node_modules/bootstrap-sass/assets/stylesheets/bootstrap/variables';
+
xos-table {
.row + .table-responsive {
margin-top: 10px;
@@ -5,40 +8,29 @@
}
table {
- border-collapse: collapse !important;
- background: darken(grey, 20);
- border: 1px solid darken(grey, 35);
+ border: 1px solid $background-dark-color;
td, th {
+ position: relative;
}
- > tbody > tr > th,
- > tfoot > tr > th,
- > thead > tr > td,
- > tbody > tr > td,
- > tfoot > tr > td {
- padding: 8px;
- line-height: 1.42857143;
- vertical-align: top;
- border-top: 1px solid #ddd;
+
+ .xos-table-hover {
+ position: absolute;
+ top: -$padding-large-vertical;
+ left: $padding-large-horizontal;
+ opacity: 0;
+ transition: all .5s;
+ z-index: -1;
+ width: 250px;
+
+ &:hover {
+ cursor: pointer;
+ }
}
- > thead > tr > th {
- vertical-align: bottom;
- border-bottom: 2px solid #ddd;
- text-align: left;
- padding: 8px;
+
+ td:hover .xos-table-hover {
+ opacity: 1;
+ z-index: 2;
}
- > caption + thead > tr:first-child > th,
- > colgroup + thead > tr:first-child > th,
- > thead:first-child > tr:first-child > th,
- > caption + thead > tr:first-child > td,
- > colgroup + thead > tr:first-child > td,
- > thead:first-child > tr:first-child > td {
- border-top: 0;
- }
- > tbody + tbody {
- border-top: 2px solid #ddd;
- }
- .table .table {
- background-color: #fff;
- }
+
}
\ No newline at end of file
diff --git a/src/app/core/table/table.ts b/src/app/core/table/table.ts
index 1ed258d..2c0b272 100644
--- a/src/app/core/table/table.ts
+++ b/src/app/core/table/table.ts
@@ -19,6 +19,7 @@
type?: string; // understand why enum does not work
formatter?(item: any): string;
link?(item: any): string;
+ hover?(item: any): string;
}
interface IXosTableCgfOrder {
@@ -28,6 +29,9 @@
export interface IXosTableCfg {
columns: any[];
+ pagination?: {
+ pageSize: number;
+ };
order?: IXosTableCgfOrder;
filter?: string;
actions?: any[]; // TODO create interface
@@ -41,6 +45,7 @@
public reverse: boolean;
public classes: string;
private config: IXosTableCfg;
+ private currentPage: number;
$onInit() {
@@ -94,9 +99,28 @@
});
}
+ // if an hover property is passed,
+ // it should be a function
+ let hoverColumns = _.filter(this.config.columns, col => angular.isDefined(col.hover));
+ if (angular.isArray(hoverColumns) && hoverColumns.length > 0) {
+ _.forEach(hoverColumns, (col) => {
+ if (!angular.isFunction(col.hover)) {
+ throw new Error('[xosTable] The hover property should be a function.');
+ }
+ });
+ }
+
+ if (this.config.pagination) {
+ this.currentPage = 0;
+ }
+
this.columns = this.config.columns;
}
+
+ public goToPage = (n) => {
+ this.currentPage = n;
+ };
}
export const xosTable: angular.IComponentOptions = {