From ca2ba3c5c7adb4805e589e4eacb44e3fa83ce57a Mon Sep 17 00:00:00 2001 From: Cristi Socea Date: Tue, 8 Aug 2017 18:37:47 +0300 Subject: [PATCH] [ADF-994] Integrate SFS enhancements for Pagination component (#2119) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add pagination module with pagination component * Update the old pagination to have the old selector * Add licence headers to ts files * Update pagination files * Rename properties for consistency reasons and remove redundant event emitters * Add PaginationQueryParams interface to reference the query params used for paginated requests * Add documentation of pagination (work in progress) * Add i18n translations to pagination component * Rename some variables used in pagination template * Update pagination component to be backwards compatible * Update pagination component specs * Update pagination’s documentation * Remove the old pagination code * Add old alfresco-pagination tag selector * Update document list component to include the new pagination * Add adf-pagination in search component * Update link to pagination component from main readme file * Update search component specs * Add a default pagination object in case it’s not provided * Assign pagination to default one to default the missing properties (if any) * Remove unused variables * Add fail hints from expectancies of pagination tests * Add default onInit and remove the old defaults --- ng2-components/README.md | 2 +- .../docs/pagination/basic.png | Bin 0 -> 20119 bytes ng2-components/ng2-alfresco-core/index.ts | 3 + .../pagination-query-params.interface.ts | 31 ++ .../pagination/pagination.component.html | 64 ++++ .../pagination/pagination.component.scss | 37 +++ .../pagination/pagination.component.spec.ts | 276 ++++++++++++++++++ .../pagination/pagination.component.ts | 206 +++++++++++++ .../src/components/pagination/pagination.md | 37 +++ .../pagination/pagination.module.ts | 39 +++ .../ng2-alfresco-core/src/i18n/en.json | 9 +- .../ng2-alfresco-datatable/index.ts | 5 +- .../pagination/pagination.component.css | 63 ---- .../pagination/pagination.component.html | 27 -- .../pagination/pagination.component.spec.ts | 108 ------- .../pagination/pagination.component.ts | 104 ------- .../src/models/pagination.data.ts | 57 ---- .../components/document-list.component.html | 26 +- .../src/components/search.component.html | 1 + .../src/components/search.component.spec.ts | 18 ++ 20 files changed, 738 insertions(+), 375 deletions(-) create mode 100644 ng2-components/ng2-alfresco-core/docs/pagination/basic.png create mode 100644 ng2-components/ng2-alfresco-core/src/components/pagination/pagination-query-params.interface.ts create mode 100644 ng2-components/ng2-alfresco-core/src/components/pagination/pagination.component.html create mode 100644 ng2-components/ng2-alfresco-core/src/components/pagination/pagination.component.scss create mode 100644 ng2-components/ng2-alfresco-core/src/components/pagination/pagination.component.spec.ts create mode 100644 ng2-components/ng2-alfresco-core/src/components/pagination/pagination.component.ts create mode 100644 ng2-components/ng2-alfresco-core/src/components/pagination/pagination.md create mode 100644 ng2-components/ng2-alfresco-core/src/components/pagination/pagination.module.ts delete mode 100644 ng2-components/ng2-alfresco-datatable/src/components/pagination/pagination.component.css delete mode 100644 ng2-components/ng2-alfresco-datatable/src/components/pagination/pagination.component.html delete mode 100644 ng2-components/ng2-alfresco-datatable/src/components/pagination/pagination.component.spec.ts delete mode 100644 ng2-components/ng2-alfresco-datatable/src/components/pagination/pagination.component.ts delete mode 100644 ng2-components/ng2-alfresco-datatable/src/models/pagination.data.ts diff --git a/ng2-components/README.md b/ng2-components/README.md index 8dd0b1a5eb..9799c8130b 100644 --- a/ng2-components/README.md +++ b/ng2-components/README.md @@ -62,7 +62,7 @@ - [adf-dropdown-breadcrumb](ng2-alfresco-documentlist/README.md) - [adf-breadcrumb](ng2-alfresco-documentlist/README.md) - [adf-document-list](ng2-alfresco-documentlist/README.md) -- [adf-pagination](ng2-alfresco-datatable/README.md) +- [adf-pagination](ng2-alfresco-core/src/components/pagination/pagination.md) - [adf-empty-list](ng2-alfresco-datatable/README.md) - [adf-datatable](ng2-alfresco-datatable/README.md) - [adf-datatable-cell](ng2-alfresco-datatable/README.md) diff --git a/ng2-components/ng2-alfresco-core/docs/pagination/basic.png b/ng2-components/ng2-alfresco-core/docs/pagination/basic.png new file mode 100644 index 0000000000000000000000000000000000000000..9ceb4da7abf4f8d1e590fa47adafebfb043c4c3d GIT binary patch literal 20119 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 Fng9emT>=0A literal 0 HcmV?d00001 diff --git a/ng2-components/ng2-alfresco-core/index.ts b/ng2-components/ng2-alfresco-core/index.ts index 36ce9acf97..82b045a76a 100644 --- a/ng2-components/ng2-alfresco-core/index.ts +++ b/ng2-components/ng2-alfresco-core/index.ts @@ -24,6 +24,7 @@ import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { CollapsableModule } from './src/components/collapsable/collapsable.module'; import { ContextMenuModule } from './src/components/context-menu/context-menu.module'; +import { PaginationModule } from './src/components/pagination/pagination.module'; import { ToolbarModule } from './src/components/toolbar/toolbar.module'; import { CardViewModule } from './src/components/view/card-view.module'; import { MaterialModule } from './src/material.module'; @@ -209,6 +210,7 @@ export function createTranslateLoader(http: Http, logService: LogService) { }), MaterialModule, AppConfigModule, + PaginationModule, ToolbarModule, ContextMenuModule, CardViewModule, @@ -236,6 +238,7 @@ export function createTranslateLoader(http: Http, logService: LogService) { ContextMenuModule, CardViewModule, CollapsableModule, + PaginationModule, ToolbarModule, ...obsoleteMdlDirectives(), UploadDirective, diff --git a/ng2-components/ng2-alfresco-core/src/components/pagination/pagination-query-params.interface.ts b/ng2-components/ng2-alfresco-core/src/components/pagination/pagination-query-params.interface.ts new file mode 100644 index 0000000000..bc763d21ec --- /dev/null +++ b/ng2-components/ng2-alfresco-core/src/components/pagination/pagination-query-params.interface.ts @@ -0,0 +1,31 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * PaginationQueryParams object is used to emit events regarding pagination having two + * properties from the Pagination interface found in AlfrescoJS API + * + * The two properties are "skipCount" and "maxItems" that are sent as query parameters + * to server to paginate results + * + * @TODO Contribute this to AlfrescoJS API + */ + +export interface PaginationQueryParams { + skipCount: number; + maxItems: number; +}; diff --git a/ng2-components/ng2-alfresco-core/src/components/pagination/pagination.component.html b/ng2-components/ng2-alfresco-core/src/components/pagination/pagination.component.html new file mode 100644 index 0000000000..86aa826a70 --- /dev/null +++ b/ng2-components/ng2-alfresco-core/src/components/pagination/pagination.component.html @@ -0,0 +1,64 @@ +
+ + {{ + 'CORE.PAGINATION.ITEMS_RANGE' | translate: { + range: range.join('-'), + total: pagination.totalItems + } + }} + +
+ +
+ {{ 'CORE.PAGINATION.ITEMS_PER_PAGE' | translate }} + {{ pagination.maxItems }} + + + + + +
+ +
+ {{ 'CORE.PAGINATION.CURRENT_PAGE' | translate }} {{ current }} + + + + + {{ 'CORE.PAGINATION.TOTAL_PAGES' | translate: { total: pages.length } }} + + + + + +
+ +
+ + + +
diff --git a/ng2-components/ng2-alfresco-core/src/components/pagination/pagination.component.scss b/ng2-components/ng2-alfresco-core/src/components/pagination/pagination.component.scss new file mode 100644 index 0000000000..6982250540 --- /dev/null +++ b/ng2-components/ng2-alfresco-core/src/components/pagination/pagination.component.scss @@ -0,0 +1,37 @@ +@import 'theming'; + +$adf-pagination--height: 48px; +$adf-pagination--icon-button-size: 32px; + +.adf-pagination { + display: flex; + border-top: 1px solid $alfresco-divider-color; + height: $adf-pagination--height; + line-height: $adf-pagination--height; + + &__block { + display: flex; + align-items: center; + padding: 0 12px; + border-right: 1px solid $alfresco-divider-color; + + &:first-child { + flex: 1 1 auto; + } + + &:last-child { + border-right-width: 0; + } + + span { + color: $alfresco-secondary-text-color; + margin: 0 5px; + } + } + + button[md-icon-button] { + width: $adf-pagination--icon-button-size; + height: $adf-pagination--icon-button-size; + line-height: $adf-pagination--icon-button-size; + } +} \ No newline at end of file diff --git a/ng2-components/ng2-alfresco-core/src/components/pagination/pagination.component.spec.ts b/ng2-components/ng2-alfresco-core/src/components/pagination/pagination.component.spec.ts new file mode 100644 index 0000000000..13772f3173 --- /dev/null +++ b/ng2-components/ng2-alfresco-core/src/components/pagination/pagination.component.spec.ts @@ -0,0 +1,276 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { async, TestBed } from '@angular/core/testing'; +import { MaterialModule } from '@angular/material'; + +import { CoreModule } from 'ng2-alfresco-core'; + +import { PaginationComponent } from './pagination.component'; + +declare let jasmine: any; + +class FakePaginationInput { + count: string = 'Not applicable / not used'; + hasMoreItems: string = 'Not applicable / not used'; + totalItems: number = null; + skipCount: number = null; + maxItems: number = 25; + + constructor(pagesCount, currentPage, lastPageItems) { + this.totalItems = ((pagesCount - 1) * this.maxItems) + lastPageItems; + this.skipCount = (currentPage - 1) * this.maxItems; + } +} + +class TestConfig { + testBed: any = null; + + constructor() { + this.testBed = TestBed.configureTestingModule({ + imports: [ + CoreModule.forRoot(), + MaterialModule + ], + schemas: [ NO_ERRORS_SCHEMA ] + }); + } +} + +describe('PaginationComponent', () => { + beforeEach(() => { + jasmine.Ajax.install(); + }); + + afterEach(() => { + jasmine.Ajax.uninstall(); + }); + + beforeEach(async(() => { + const test = new TestConfig(); + + test.testBed + .compileComponents() + .then(() => { + const fixture = test.testBed.createComponent(PaginationComponent); + const component: PaginationComponent = fixture.componentInstance; + + ( component).ngAfterViewInit = jasmine + .createSpy('ngAfterViewInit').and + .callThrough(); + + spyOn(component.onChangePageNumber, 'emit'); + spyOn(component.onChangePageSize, 'emit'); + spyOn(component.onNextPage, 'emit'); + spyOn(component.onPrevPage, 'emit'); + + this.fixture = fixture; + this.component = component; + + fixture.detectChanges(); + }); + })); + + describe('Single page', () => { + beforeEach(() => { + this.component.pagination = new FakePaginationInput(1, 1, 10); + }); + + it('has a single page', () => { + expect(this.component.pages.length).toBe(1); + }); + + it('has current page 1', () => { + expect(this.component.current).toBe(1); + }); + + it('is first and last page', () => { + expect(this.component.isFirstPage).toBe(true); + expect(this.component.isLastPage).toBe(true); + }); + + it('has range', () => { + expect(this.component.range).toEqual([ 1, 10 ]); + }); + }); + + describe('Single full page', () => { + beforeEach(() => { + this.component.pagination = new FakePaginationInput(1, 1, 25); + }); + + it('has a single page', () => { + expect(this.component.pages.length).toBe(1); + }); + + it('has range', () => { + expect(this.component.range).toEqual([ 1, 25 ]); + }); + }); + + describe('Middle page', () => { + + // This test describes 6 pages being on the third page + // and last page has 5 items + + beforeEach(() => { + this.component.pagination = new FakePaginationInput(6, 3, 5); + }); + + it('has more pages', () => { + expect(this.component.pages.length).toBe(6); + }); + + it('has the last page', () => { + expect(this.component.lastPage).toBe(6); + }); + + it('is on the 3rd page', () => { + expect(this.component.current).toBe(3); + }); + + it('has previous and next page', () => { + expect(this.component.previous).toBe(2); + expect(this.component.next).toBe(4); + }); + + it('is not first, nor last', () => { + expect(this.component.isFirstPage).toBe(false); + expect(this.component.isLastPage).toBe(false); + }); + + it('has range', () => { + expect(this.component.range).toEqual([ 51, 75 ]); + }); + + it('goes next', () => { + const { component } = this; + + component.goNext(); + + const { emit: { calls } } = component.onNextPage; + const { skipCount } = calls.mostRecent().args[0]; + + expect(skipCount).toBe(75); + }); + + it('goes previous', () => { + const { component } = this; + + component.goPrevious(); + + const { emit: { calls } } = component.onPrevPage; + const { skipCount } = calls.mostRecent().args[0]; + + expect(skipCount).toBe(25); + }); + + it('changes page size', () => { + const { component } = this; + component.changePageSize(50); + + const { emit: { calls } } = component.onChangePageSize; + const { maxItems } = calls.mostRecent().args[0]; + + expect(maxItems).toBe(50); + }); + + it('changes page number', () => { + const { component } = this; + + component.changePageNumber(5); + + const { emit: { calls } } = component.onChangePageNumber; + const { skipCount } = calls.mostRecent().args[0]; + + expect(skipCount).toBe(100); + }); + }); + + describe('First page', () => { + + // This test describes 10 pages being on the first page + + beforeEach(() => { + this.component.pagination = new FakePaginationInput(10, 1, 5); + }); + + it('is on the first page', () => { + expect(this.component.current).toBe(1); + expect(this.component.isFirstPage).toBe(true); + }); + + it('has the same, previous page', () => { + expect(this.component.previous).toBe(1); + }); + + it('has next page', () => { + expect(this.component.next).toBe(2); + }); + + it('has range', () => { + expect(this.component.range).toEqual([ 1, 25 ]); + }); + }); + + describe('Last page', () => { + + // This test describes 10 pages being on the last page + + beforeEach(() => { + this.component.pagination = new FakePaginationInput(10, 10, 5); + }); + + it('is on the last page', () => { + expect(this.component.current).toBe(10); + expect(this.component.isLastPage).toBe(true); + }); + + it('has the same, next page', () => { + expect(this.component.next).toBe(10); + }); + + it('has previous page', () => { + expect(this.component.previous).toBe(9); + }); + + it('has range', () => { + expect(this.component.range).toEqual([ 226, 230 ]); + }); + }); + + describe('Without pagination input', () => { + it('has defaults', () => { + const { + current, lastPage, isFirstPage, isLastPage, + next, previous, range, pages + } = this.component; + + expect(lastPage).toBe(1, 'lastPage'); + expect(previous).toBe(1, 'previous'); + expect(current).toBe(1, 'current'); + expect(next).toBe(1, 'next'); + + expect(isFirstPage).toBe(true, 'isFirstPage'); + expect(isLastPage).toBe(true, 'isLastPage'); + + expect(range).toEqual([ 0, 0 ], 'range'); + expect(pages).toEqual([ 1 ], 'pages'); + }); + }); +}); diff --git a/ng2-components/ng2-alfresco-core/src/components/pagination/pagination.component.ts b/ng2-components/ng2-alfresco-core/src/components/pagination/pagination.component.ts new file mode 100644 index 0000000000..c5e2eee8ab --- /dev/null +++ b/ng2-components/ng2-alfresco-core/src/components/pagination/pagination.component.ts @@ -0,0 +1,206 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + ChangeDetectionStrategy, + Component, + EventEmitter, + Input, + OnInit, + Output, + ViewEncapsulation +} from '@angular/core'; + +import { Pagination } from 'alfresco-js-api'; +import { PaginationQueryParams } from './pagination-query-params.interface'; + +@Component({ + selector: 'adf-pagination, alfresco-pagination', + host: { 'class': 'adf-pagination' }, + templateUrl: './pagination.component.html', + styleUrls: [ './pagination.component.scss' ], + changeDetection: ChangeDetectionStrategy.OnPush, + encapsulation: ViewEncapsulation.None +}) +export class PaginationComponent implements OnInit { + + static DEFAULT_PAGE_SIZE: number = 25; + + static ACTIONS = { + NEXT_PAGE: 'NEXT_PAGE', + PREV_PAGE: 'PREV_PAGE', + CHANGE_PAGE_SIZE: 'CHANGE_PAGE_SIZE', + CHANGE_PAGE_NUMBER: 'CHANGE_PAGE_NUMBER' + }; + + @Input() + supportedPageSizes: number[] = [ 25, 50, 100 ]; + + /** @deprecated */ + /** "pagination" object already has "maxItems" */ + @Input() + maxItems: number = PaginationComponent.DEFAULT_PAGE_SIZE; + + @Input() + pagination: Pagination; + + @Output('change') + onChange: EventEmitter = new EventEmitter(); + + @Output('changePageNumber') + onChangePageNumber: EventEmitter = new EventEmitter(); + + @Output('changePageSize') + onChangePageSize: EventEmitter = new EventEmitter(); + + @Output('nextPage') + onNextPage: EventEmitter = new EventEmitter(); + + @Output('prevPage') + onPrevPage: EventEmitter = new EventEmitter(); + + ngOnInit() { + this.pagination = { + skipCount: 0, + maxItems: PaginationComponent.DEFAULT_PAGE_SIZE, + totalItems: 0 + }; + } + + get lastPage(): number { + const { maxItems, totalItems } = this.pagination; + + return (totalItems && maxItems) + ? Math.ceil(totalItems / maxItems) + : 1; + } + + get current(): number { + const { maxItems, skipCount } = this.pagination; + + return (skipCount && maxItems) + ? Math.floor(skipCount / maxItems) + 1 + : 1; + } + + get isLastPage(): boolean { + const { current, lastPage } = this; + return current === lastPage; + } + + get isFirstPage(): boolean { + return this.current === 1; + } + + get next(): number { + const { isLastPage, current } = this; + return isLastPage ? current : current + 1; + } + + get previous(): number { + const { isFirstPage, current } = this; + return isFirstPage ? 1 : current - 1; + } + + get range(): number[] { + const { skipCount, maxItems, totalItems } = this.pagination; + const { isLastPage } = this; + + const start = totalItems ? skipCount + 1 : 0; + const end = isLastPage ? totalItems : skipCount + maxItems; + + return [ start, end ]; + } + + get pages(): number[] { + return Array(this.lastPage) + .fill('n') + .map((item, index) => (index + 1)); + } + + goNext() { + const { next, pagination: { maxItems } } = this; + + this.handlePaginationEvent(PaginationComponent.ACTIONS.NEXT_PAGE, { + skipCount: (next - 1) * maxItems, + maxItems + }); + } + + goPrevious() { + const { previous, pagination: { maxItems } } = this; + + this.handlePaginationEvent(PaginationComponent.ACTIONS.PREV_PAGE, { + skipCount: (previous - 1) * maxItems, + maxItems + }); + } + + changePageNumber(pageNumber: number) { + const { pagination: { maxItems } } = this; + + this.handlePaginationEvent(PaginationComponent.ACTIONS.CHANGE_PAGE_NUMBER, { + skipCount: (pageNumber - 1) * maxItems, + maxItems + }); + } + + changePageSize(maxItems: number) { + this.handlePaginationEvent(PaginationComponent.ACTIONS.CHANGE_PAGE_SIZE, { + skipCount: 0, + maxItems + }); + } + + handlePaginationEvent(action: string, params: PaginationQueryParams) { + const { + NEXT_PAGE, + PREV_PAGE, + CHANGE_PAGE_NUMBER, + CHANGE_PAGE_SIZE + } = PaginationComponent.ACTIONS; + + const { + onChange, + onChangePageNumber, + onChangePageSize, + onNextPage, + onPrevPage, + pagination + } = this; + + const data = Object.assign({}, pagination, params); + + if (action === NEXT_PAGE) { + onNextPage.emit(data); + } + + if (action === PREV_PAGE) { + onPrevPage.emit(data); + } + + if (action === CHANGE_PAGE_NUMBER) { + onChangePageNumber.emit(data); + } + + if (action === CHANGE_PAGE_SIZE) { + onChangePageSize.emit(data); + } + + onChange.emit(params); + } +} diff --git a/ng2-components/ng2-alfresco-core/src/components/pagination/pagination.md b/ng2-components/ng2-alfresco-core/src/components/pagination/pagination.md new file mode 100644 index 0000000000..39a64cc603 --- /dev/null +++ b/ng2-components/ng2-alfresco-core/src/components/pagination/pagination.md @@ -0,0 +1,37 @@ +# Pagination Component + +## Basic example + +```html + + +``` + +Depending on the pagination data, you should see result similar to the following one: + +![](../../../docs/pagination/basic.png) + +## Properties + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| pagination | Pagination | | Pagination object | +| supportedPageSizes | Array<number> | [ 25, 50, 100 ] | An array of page sizes | +| change | EventEmitter<PaginationQueryParams> | | Triggered for any action in pagination | +| nextPage | EventEmitter<Pagination> | | Triggered on next page action | +| prevPage | EventEmitter<Pagination> | | Triggered on previous page action | +| changePageSize | EventEmitter<Pagination> | | Triggered on page size change action | +| changePageNumber | EventEmitter<Pagination> | | Triggered on page change action | + +Each event helps to detect the certain action that user have made using the component. + +For `change` event, a [PaginationQueryParams](https://github.com/Alfresco/alfresco-ng2-components/tree/master/ng2-components/ng2-alfresco-core/src/components/pagination/pagination-query-params.ts) (including the query params supported by the REST API, `skipCount` and `maxItems`) is returned. + +For all other events, other than `change`, a new [Pagination object](https://github.com/Alfresco/alfresco-js-api/blob/master/src/alfresco-core-rest-api/docs/Pagination.md) is returned as in the folowing example, with updated properties to be used to query further. diff --git a/ng2-components/ng2-alfresco-core/src/components/pagination/pagination.module.ts b/ng2-components/ng2-alfresco-core/src/components/pagination/pagination.module.ts new file mode 100644 index 0000000000..7e4c7b11e6 --- /dev/null +++ b/ng2-components/ng2-alfresco-core/src/components/pagination/pagination.module.ts @@ -0,0 +1,39 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { MaterialModule } from '@angular/material'; + +import { TranslateModule } from '@ngx-translate/core'; + +import { PaginationComponent } from './pagination.component'; + +@NgModule({ + imports: [ + CommonModule, + TranslateModule, + MaterialModule + ], + declarations: [ + PaginationComponent + ], + exports: [ + PaginationComponent + ] +}) +export class PaginationModule {} diff --git a/ng2-components/ng2-alfresco-core/src/i18n/en.json b/ng2-components/ng2-alfresco-core/src/i18n/en.json index 0db3279e44..2c8da2442e 100644 --- a/ng2-components/ng2-alfresco-core/src/i18n/en.json +++ b/ng2-components/ng2-alfresco-core/src/i18n/en.json @@ -1,3 +1,10 @@ { - + "CORE": { + "PAGINATION": { + "ITEMS_RANGE": "Showing {{ range }} of {{ total }}", + "ITEMS_PER_PAGE": "Items per page", + "CURRENT_PAGE": "Page", + "TOTAL_PAGES": "of {{ total }}" + } + } } diff --git a/ng2-components/ng2-alfresco-datatable/index.ts b/ng2-components/ng2-alfresco-datatable/index.ts index e612b72ab6..43842fe5a4 100644 --- a/ng2-components/ng2-alfresco-datatable/index.ts +++ b/ng2-components/ng2-alfresco-datatable/index.ts @@ -24,14 +24,12 @@ export * from './src/data/index'; export { DataTableCellComponent } from './src/components/datatable/datatable-cell.component'; export { DataTableComponent } from './src/components/datatable/datatable.component'; export { EmptyListComponent } from './src/components/datatable/empty-list.component'; -export { PaginationComponent } from './src/components/pagination/pagination.component'; export { DataCellEvent, DataCellEventModel } from './src/components/datatable/data-cell.event'; export { DataRowActionEvent, DataRowActionModel } from './src/components/datatable/data-row-action.event'; import { DataTableCellComponent } from './src/components/datatable/datatable-cell.component'; import { DataTableComponent } from './src/components/datatable/datatable.component'; import { EmptyListComponent } from './src/components/datatable/empty-list.component'; -import { PaginationComponent } from './src/components/pagination/pagination.component'; import { LoadingContentTemplateDirective } from './src/directives/loading-template.directive'; import { NoContentTemplateDirective } from './src/directives/no-content-template.directive'; @@ -41,8 +39,7 @@ export function directives() { EmptyListComponent, DataTableCellComponent, NoContentTemplateDirective, - LoadingContentTemplateDirective, - PaginationComponent + LoadingContentTemplateDirective ]; } diff --git a/ng2-components/ng2-alfresco-datatable/src/components/pagination/pagination.component.css b/ng2-components/ng2-alfresco-datatable/src/components/pagination/pagination.component.css deleted file mode 100644 index faed4d0dbf..0000000000 --- a/ng2-components/ng2-alfresco-datatable/src/components/pagination/pagination.component.css +++ /dev/null @@ -1,63 +0,0 @@ -.mdl-paging { - color: rgba(0, 0, 0, 0.54); - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - -webkit-align-items: center; - -ms-flex-align: center; - align-items: center; - height: 56px; - -webkit-flex-flow: row wrap; - -ms-flex-flow: row wrap; - flex-flow: row wrap; -} - -.mdl-paging > * { - -webkit-flex: none; - -ms-flex: none; - flex: none; -} - -.mdl-list + .mdl-paging { - margin: 0; -} - -.mdl-paging__per-page { - position: relative; -} - -.mdl-paging__per-page-label { - margin-right: 40px; -} - -.mdl-paging__per-page-value { - right: 36px; - top: 6px; -} - -.mdl-paging__per-page + .mdl-paging__count { - margin-left: 24px; -} - -.mdl-paging .mdl-menu { - min-width: 64px; -} - -.mdl-paging__prev:last-child { - margin-right: 44px; -} - -.mdl-paging__count + .mdl-paging__prev { - margin-left: 24px; -} - -.mdl-paging__prev + .mdl-paging__next { - margin-left: 12px; -} - -.mdl-paging__count + .mdl-paging__next { - margin-left: 68px; -} diff --git a/ng2-components/ng2-alfresco-datatable/src/components/pagination/pagination.component.html b/ng2-components/ng2-alfresco-datatable/src/components/pagination/pagination.component.html deleted file mode 100644 index 3fe519bcd6..0000000000 --- a/ng2-components/ng2-alfresco-datatable/src/components/pagination/pagination.component.html +++ /dev/null @@ -1,27 +0,0 @@ -
- - Rows per page: - {{pagination.maxItems}} - - -
- {{size}} -
-
- -
- {{summary}} - - -
diff --git a/ng2-components/ng2-alfresco-datatable/src/components/pagination/pagination.component.spec.ts b/ng2-components/ng2-alfresco-datatable/src/components/pagination/pagination.component.spec.ts deleted file mode 100644 index 1d5856cee5..0000000000 --- a/ng2-components/ng2-alfresco-datatable/src/components/pagination/pagination.component.spec.ts +++ /dev/null @@ -1,108 +0,0 @@ -/*! - * @license - * Copyright 2016 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Injector, SimpleChange } from '@angular/core'; -import { getTestBed, TestBed } from '@angular/core/testing'; -import { PaginationData } from '../../models/pagination.data'; -import { PaginationComponent } from '../pagination/pagination.component'; - -describe('PaginationComponent', () => { - let injector: Injector; - let paginationComponent: PaginationComponent; - - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ - PaginationComponent - ] - }); - injector = getTestBed(); - paginationComponent = injector.get(PaginationComponent); - paginationComponent.pagination = new PaginationData(0, 0, 0, 20, true); - }); - - it('should create Pagination object on init if no object pagination is passed', () => { - paginationComponent.pagination = null; - paginationComponent.ngOnInit(); - expect(paginationComponent.pagination).not.toBe(null); - }); - - it('is defined', () => { - expect(paginationComponent).toBeDefined(); - }); - - it('page size', () => { - expect(paginationComponent.pagination.maxItems).toBe(20); - }); - - it('set page size', () => { - paginationComponent.pagination.maxItems = 100; - expect(paginationComponent.pagination.maxItems).toBe(100); - }); - - it('prevPageAvail dafault false', () => { - expect(paginationComponent.prevPageAvail()).toBe(false); - }); - - it('nextPageAvail default true', () => { - expect(paginationComponent.nextPageAvail()).toBe(true); - }); - - it('showNextPage', () => { - expect(paginationComponent.pagination.skipCount).toBe(0); - paginationComponent.showNextPage(); - expect(paginationComponent.pagination.skipCount).toBe(20); - }); - - it('showPrevPage', () => { - paginationComponent.pagination.skipCount = 100; - paginationComponent.showPrevPage(); - expect(paginationComponent.pagination.skipCount).toBe(80); - }); - - it('should update the summary on nextpage click', () => { - spyOn(paginationComponent, 'updateSummary'); - - paginationComponent.showNextPage(); - - expect(paginationComponent.updateSummary).toHaveBeenCalled(); - }); - - it('should update the summary on prevpage click', () => { - spyOn(paginationComponent, 'updateSummary'); - - paginationComponent.showPrevPage(); - - expect(paginationComponent.updateSummary).toHaveBeenCalled(); - }); - - it('should update the summary on chage page size click', () => { - spyOn(paginationComponent, 'updateSummary'); - - paginationComponent.setPageSize(100); - - expect(paginationComponent.updateSummary).toHaveBeenCalled(); - }); - - it('should update the summary on input pagination parameter change', () => { - spyOn(paginationComponent, 'updateSummary'); - - paginationComponent.ngOnChanges({pagination: new SimpleChange(null, new PaginationData(0, 0, 0, 20, true), true)}); - - expect(paginationComponent.updateSummary).toHaveBeenCalled(); - }); -}); diff --git a/ng2-components/ng2-alfresco-datatable/src/components/pagination/pagination.component.ts b/ng2-components/ng2-alfresco-datatable/src/components/pagination/pagination.component.ts deleted file mode 100644 index c21cf021ff..0000000000 --- a/ng2-components/ng2-alfresco-datatable/src/components/pagination/pagination.component.ts +++ /dev/null @@ -1,104 +0,0 @@ -/*! - * @license - * Copyright 2016 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core'; -import { Pagination } from 'alfresco-js-api'; -import { PaginationData } from '../../models/pagination.data'; - -@Component({ - selector: 'adf-pagination, alfresco-pagination', - templateUrl: './pagination.component.html', - styleUrls: ['./pagination.component.css'] -}) -export class PaginationComponent implements OnInit, OnChanges { - - static DEFAULT_PAGE_SIZE: number = 20; - - summary: string = ''; - - @Input() - supportedPageSizes: number[] = [5, 10, 20, 50, 100]; - - @Input() - maxItems: number = PaginationComponent.DEFAULT_PAGE_SIZE; - - @Input() - pagination: Pagination; - - @Output() - changePageSize: EventEmitter = new EventEmitter(); - - @Output() - nextPage: EventEmitter = new EventEmitter(); - - @Output() - prevPage: EventEmitter = new EventEmitter(); - - constructor() { - } - - ngOnInit() { - if (!this.pagination) { - this.pagination = new PaginationData(0, 0, 0, this.maxItems, true); - } - } - - ngOnChanges(changes: SimpleChanges) { - if (changes['pagination']) { - if (changes['pagination'].currentValue) { - this.pagination = changes['pagination'].currentValue; - this.updateSummary(); - } - } - } - - setPageSize(value: number) { - this.pagination.maxItems = value; - this.updateSummary(); - this.changePageSize.emit(this.pagination); - } - - nextPageAvail(): boolean { - return this.pagination.hasMoreItems; - } - - prevPageAvail(): boolean { - return this.pagination.skipCount > 0; - } - - showNextPage() { - this.pagination.skipCount += this.pagination.maxItems; - this.updateSummary(); - this.nextPage.emit(this.pagination); - } - - showPrevPage() { - this.pagination.skipCount -= this.pagination.maxItems; - this.updateSummary(); - this.prevPage.emit(this.pagination); - } - - updateSummary() { - let from = this.pagination.skipCount; - if (from === 0) { - from = 1; - } - let to = this.pagination.skipCount + this.pagination.count; - let of = this.pagination.totalItems; - this.summary = `${from}-${to} of ${of}`; - } -} diff --git a/ng2-components/ng2-alfresco-datatable/src/models/pagination.data.ts b/ng2-components/ng2-alfresco-datatable/src/models/pagination.data.ts deleted file mode 100644 index 94fbe0d19e..0000000000 --- a/ng2-components/ng2-alfresco-datatable/src/models/pagination.data.ts +++ /dev/null @@ -1,57 +0,0 @@ -/*! - * @license - * Copyright 2016 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Pagination } from 'alfresco-js-api'; - -export class PaginationData implements Pagination { - - /** - * The number of objects in the collection. - */ - count: number; - - /** - * A boolean value which is true if there are more entities in the collection beyond those in this response. - * A true value means a request with a larger value for the skipCount or the maxItems parameter will return more entities. - */ - hasMoreItems: boolean; - - /** - * An integer describing the total number of entities in the collection. - * The API might not be able to determine this value, in which case this property will not be present. - */ - totalItems: number; - - /** - * An integer describing how many entities exist in the collection before those included in this list. - */ - skipCount: number; - - /** - * The value of the maxItems parameter used to generate this list, - * or if there was no maxItems parameter the default value is 100. - */ - maxItems: number; - - constructor(count: number, totalItems: number, skipCount: number, maxItems: number, hasMoreItems: boolean) { - this.count = count; - this.hasMoreItems = hasMoreItems; - this.totalItems = totalItems; - this.skipCount = skipCount; - this.maxItems = maxItems; - } -} diff --git a/ng2-components/ng2-alfresco-documentlist/src/components/document-list.component.html b/ng2-components/ng2-alfresco-documentlist/src/components/document-list.component.html index 4c4b76b02d..43235a77c2 100644 --- a/ng2-components/ng2-alfresco-documentlist/src/components/document-list.component.html +++ b/ng2-components/ng2-alfresco-documentlist/src/components/document-list.component.html @@ -5,6 +5,7 @@ (error)="onActionMenuError($event)" (permissionErrorEvent)="onPermissionError($event)"> + +
@@ -33,24 +35,28 @@
+
- +
- + + diff --git a/ng2-components/ng2-alfresco-search/src/components/search.component.html b/ng2-components/ng2-alfresco-search/src/components/search.component.html index 4882f862b6..da814fe06f 100644 --- a/ng2-components/ng2-alfresco-search/src/components/search.component.html +++ b/ng2-components/ng2-alfresco-search/src/components/search.component.html @@ -68,6 +68,7 @@ + { let result = { list: { + pagination: { + hasMoreItems: false, + maxItems: 25, + skipCount: 0, + totalItems: 1 + }, entries: [ { entry: { @@ -55,6 +61,12 @@ describe('SearchComponent', () => { let folderResult = { list: { + pagination: { + hasMoreItems: false, + maxItems: 25, + skipCount: 0, + totalItems: 1 + }, entries: [ { entry: { @@ -76,6 +88,12 @@ describe('SearchComponent', () => { let noResult = { list: { + pagination: { + hasMoreItems: false, + maxItems: 25, + skipCount: 0, + totalItems: 0 + }, entries: [] } };