From: nsedrickm Date: Wed, 3 Aug 2022 11:14:27 +0000 (+0100) Subject: mgr/dashboard: Improve level A accessibility for pagination component X-Git-Tag: v18.0.0~163^2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=363352163dd13c2ebe2a03865eda6cf5319d2536;p=ceph-ci.git mgr/dashboard: Improve level A accessibility for pagination component Add custom pagination component based on patternfly design Fixes: https://tracker.ceph.com/issues/55876 Signed-off-by: nsedrickm --- diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.spec.ts index ecf0bedf961..c8cddfdc8a9 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.spec.ts @@ -77,7 +77,7 @@ describe('RgwDaemonListComponent', () => { expect(listDaemonsSpy).toHaveBeenCalledTimes(1); expect(component.daemons).toEqual([daemon]); expect(fixture.debugElement.query(By.css('cd-table')).nativeElement.textContent).toContain( - 'total 1' + 'total of 1' ); fixture.destroy(); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/crud-table/crud-table.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/crud-table/crud-table.component.spec.ts index df10e2a97e4..f641cbba4c1 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/crud-table/crud-table.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/crud-table/crud-table.component.spec.ts @@ -12,6 +12,7 @@ import { ComponentsModule } from '~/app/shared/components/components.module'; import { PipesModule } from '~/app/shared/pipes/pipes.module'; import { configureTestBed } from '~/testing/unit-test-helper'; import { TableKeyValueComponent } from '../table-key-value/table-key-value.component'; +import { TablePaginationComponent } from '../table-pagination/table-pagination.component'; import { TableComponent } from '../table/table.component'; import { CRUDTableComponent } from './crud-table.component'; @@ -20,7 +21,12 @@ describe('CRUDTableComponent', () => { let fixture: ComponentFixture; configureTestBed({ - declarations: [CRUDTableComponent, TableComponent, TableKeyValueComponent], + declarations: [ + CRUDTableComponent, + TableComponent, + TableKeyValueComponent, + TablePaginationComponent + ], imports: [ NgxDatatableModule, FormsModule, diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/datatable.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/datatable.module.ts index 5cd33633200..9edd6624fed 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/datatable.module.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/datatable.module.ts @@ -12,6 +12,7 @@ import { PipesModule } from '../pipes/pipes.module'; import { CRUDTableComponent } from './crud-table/crud-table.component'; import { TableActionsComponent } from './table-actions/table-actions.component'; import { TableKeyValueComponent } from './table-key-value/table-key-value.component'; +import { TablePaginationComponent } from './table-pagination/table-pagination.component'; import { TableComponent } from './table/table.component'; @NgModule({ @@ -26,13 +27,20 @@ import { TableComponent } from './table/table.component'; ComponentsModule, RouterModule ], - declarations: [TableComponent, TableKeyValueComponent, TableActionsComponent, CRUDTableComponent], + declarations: [ + TableComponent, + TableKeyValueComponent, + TableActionsComponent, + CRUDTableComponent, + TablePaginationComponent + ], exports: [ TableComponent, NgxDatatableModule, TableKeyValueComponent, TableActionsComponent, - CRUDTableComponent + CRUDTableComponent, + TablePaginationComponent ] }) export class DataTableModule {} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.spec.ts index 150d4424105..af493513eec 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.spec.ts @@ -12,6 +12,7 @@ import { CdTableColumn } from '~/app/shared/models/cd-table-column'; import { CdDatePipe } from '~/app/shared/pipes/cd-date.pipe'; import { PipesModule } from '~/app/shared/pipes/pipes.module'; import { configureTestBed } from '~/testing/unit-test-helper'; +import { TablePaginationComponent } from '../table-pagination/table-pagination.component'; import { TableComponent } from '../table/table.component'; import { TableKeyValueComponent } from './table-key-value.component'; @@ -20,7 +21,7 @@ describe('TableKeyValueComponent', () => { let fixture: ComponentFixture; configureTestBed({ - declarations: [TableComponent, TableKeyValueComponent], + declarations: [TableComponent, TableKeyValueComponent, TablePaginationComponent], imports: [ FormsModule, NgxDatatableModule, diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-pagination/table-pagination.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-pagination/table-pagination.component.html new file mode 100644 index 00000000000..7582c76a504 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-pagination/table-pagination.component.html @@ -0,0 +1,58 @@ + diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-pagination/table-pagination.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-pagination/table-pagination.component.scss new file mode 100644 index 00000000000..4455ded18d0 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-pagination/table-pagination.component.scss @@ -0,0 +1,21 @@ +@use './src/styles/vendor/variables' as vv; + +.pagination { + align-items: center; + display: flex; +} + +.pagination__btn { + background: none; + border: 0; + + &:disabled { + color: vv.$gray-500; + } +} + +.pagination__page_input { + border: 1px solid vv.$gray-500; + border-radius: 0.25rem; + padding-left: 0.25rem; +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-pagination/table-pagination.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-pagination/table-pagination.component.spec.ts new file mode 100644 index 00000000000..b220b59e633 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-pagination/table-pagination.component.spec.ts @@ -0,0 +1,54 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TablePaginationComponent } from './table-pagination.component'; + +describe('TablePaginationComponent', () => { + let component: TablePaginationComponent; + let fixture: ComponentFixture; + let element: HTMLElement; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [TablePaginationComponent] + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TablePaginationComponent); + component = fixture.componentInstance; + element = fixture.debugElement.nativeElement; + component.page = 1; + component.size = 10; + component.count = 100; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should contain valid inputs', () => { + expect(component.page).toEqual(1); + expect(component.size).toEqual(10); + expect(component.count).toEqual(100); + }); + + it('should change page', () => { + const input = element.querySelector('input'); + input.value = '5'; + input.dispatchEvent(new Event('input')); + expect(component.page).toEqual(5); + }); + + it('should disable prev button', () => { + const prev: HTMLButtonElement = element.querySelector('.pagination__btn_prev'); + expect(prev.disabled).toBeTruthy(); + }); + + it('should disable next button', () => { + const next: HTMLButtonElement = element.querySelector('.pagination__btn_next'); + component.size = 100; + fixture.detectChanges(); + expect(next.disabled).toBeTruthy(); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-pagination/table-pagination.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-pagination/table-pagination.component.ts new file mode 100644 index 00000000000..5080f05c4d1 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-pagination/table-pagination.component.ts @@ -0,0 +1,110 @@ +import { Component, EventEmitter, Input, Output } from '@angular/core'; + +@Component({ + selector: 'cd-table-pagination', + templateUrl: './table-pagination.component.html', + styleUrls: ['./table-pagination.component.scss'] +}) +export class TablePaginationComponent { + private _size = 0; + private _count = 0; + private _page = 1; + pages: any; + + @Input() + set size(value: number) { + this._size = value; + this.pages = this.calcPages(); + } + + get size(): number { + return this._size; + } + + @Input() + set page(value: number) { + this._page = value; + } + + get page(): number { + return this._page; + } + + @Input() + set count(value: number) { + this._count = value; + } + + get count(): number { + return this._count; + } + + get totalPages(): number { + const count = this.size < 1 ? 1 : Math.ceil(this._count / this._size); + return Math.max(count || 0, 1); + } + + @Output() pageChange: EventEmitter = new EventEmitter(); + + canPrevious(): boolean { + return this._page > 1; + } + + canNext(): boolean { + return this._page < this.totalPages; + } + + prevPage(): void { + this.selectPage(this._page - 1); + } + + nextPage(): void { + this.selectPage(this._page + 1); + } + + selectPage(page: number): void { + if (page > 0 && page <= this.totalPages && page !== this.page) { + this._page = page; + this.pageChange.emit({ + page + }); + } else if (page > 0 && page >= this.totalPages) { + this._page = this.totalPages; + this.pageChange.emit({ + page: this.totalPages + }); + } + } + + calcPages(page?: number): any[] { + const pages = []; + let startPage = 1; + let endPage = this.totalPages; + const maxSize = 5; + const isMaxSized = maxSize < this.totalPages; + + page = page || this.page; + + if (isMaxSized) { + startPage = page - Math.floor(maxSize / 2); + endPage = page + Math.floor(maxSize / 2); + + if (startPage < 1) { + startPage = 1; + endPage = Math.min(startPage + maxSize - 1, this.totalPages); + } else if (endPage > this.totalPages) { + startPage = Math.max(this.totalPages - maxSize + 1, 1); + endPage = this.totalPages; + } + } + + for (let num = startPage; num <= endPage; num++) { + pages.push({ + number: num, + text: (num) + }); + } + + return pages; + } +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.html index d7dd7e5c703..b92fb655d55 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.html @@ -221,16 +221,11 @@ {{ rowCount }} total - - + diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.spec.ts index f0f649780af..f8178be26d8 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.spec.ts @@ -16,6 +16,7 @@ import { CdTableFetchDataContext } from '~/app/shared/models/cd-table-fetch-data import { CdTableSelection } from '~/app/shared/models/cd-table-selection'; import { PipesModule } from '~/app/shared/pipes/pipes.module'; import { configureTestBed } from '~/testing/unit-test-helper'; +import { TablePaginationComponent } from '../table-pagination/table-pagination.component'; import { TableComponent } from './table.component'; describe('TableComponent', () => { @@ -39,7 +40,7 @@ describe('TableComponent', () => { }; configureTestBed({ - declarations: [TableComponent], + declarations: [TableComponent, TablePaginationComponent], imports: [ BrowserAnimationsModule, NgxDatatableModule,