From 08d042c58f1a9336670fe421906ea760549a5c7a Mon Sep 17 00:00:00 2001 From: Maxime Lamer Date: Tue, 27 Aug 2024 13:50:26 -0400 Subject: [PATCH 1/8] feat(paginator): add paginator component --- packages/sdg/src/lib/paginator/index.ts | 1 + .../lib/paginator/paginator.component.html | 54 +++++++ .../lib/paginator/paginator.component.scss | 47 ++++++ .../lib/paginator/paginator.component.spec.ts | 26 +++ .../src/lib/paginator/paginator.component.ts | 148 ++++++++++++++++++ packages/sdg/src/public-api.ts | 1 + .../paginator/paginator.component.html | 49 ++++++ .../paginator/paginator.component.scss | 3 + .../paginator/paginator.component.spec.ts | 22 +++ .../paginator/paginator.component.ts | 56 +++++++ .../components/showcases/showcases.routes.ts | 8 + 11 files changed, 415 insertions(+) create mode 100644 packages/sdg/src/lib/paginator/index.ts create mode 100644 packages/sdg/src/lib/paginator/paginator.component.html create mode 100644 packages/sdg/src/lib/paginator/paginator.component.scss create mode 100644 packages/sdg/src/lib/paginator/paginator.component.spec.ts create mode 100644 packages/sdg/src/lib/paginator/paginator.component.ts create mode 100644 projects/demo/src/app/pages/components/showcases/paginator/paginator.component.html create mode 100644 projects/demo/src/app/pages/components/showcases/paginator/paginator.component.scss create mode 100644 projects/demo/src/app/pages/components/showcases/paginator/paginator.component.spec.ts create mode 100644 projects/demo/src/app/pages/components/showcases/paginator/paginator.component.ts diff --git a/packages/sdg/src/lib/paginator/index.ts b/packages/sdg/src/lib/paginator/index.ts new file mode 100644 index 0000000..1c2ed0e --- /dev/null +++ b/packages/sdg/src/lib/paginator/index.ts @@ -0,0 +1 @@ +export * from './paginator.component'; diff --git a/packages/sdg/src/lib/paginator/paginator.component.html b/packages/sdg/src/lib/paginator/paginator.component.html new file mode 100644 index 0000000..3ce94eb --- /dev/null +++ b/packages/sdg/src/lib/paginator/paginator.component.html @@ -0,0 +1,54 @@ +
+ @if (currentPage !== 1) { + + } + @for (firstPage of firstPages; track firstPage) { +

+ {{ firstPage }} +

+ } + @if ((!middlePages.length && lastPages.length === 1) || middlePages.length) { +

...

+ } + @for (middlePage of middlePages; track middlePage) { +

+ {{ middlePage }} +

+ } + @if ((!middlePages.length && firstPages.length === 1) || middlePages.length) { +

...

+ } + @for (lastPage of lastPages; track lastPage) { +

+ {{ lastPage }} +

+ } + @for (page of pages; track page) { +

+ {{ page }} +

+ } + @if (currentPage !== nbOfPages) { + + } +
diff --git a/packages/sdg/src/lib/paginator/paginator.component.scss b/packages/sdg/src/lib/paginator/paginator.component.scss new file mode 100644 index 0000000..3861721 --- /dev/null +++ b/packages/sdg/src/lib/paginator/paginator.component.scss @@ -0,0 +1,47 @@ +@use '../core/theme/colors'; + +.container { + display: flex; + align-items: center; + justify-content: center; +} + +.page { + color: colors.$blue-piv; + margin: 0; + line-height: 40px; + cursor: pointer; + min-width: 40px; + height: 40px; + text-align: center; + + &:hover { + background-color: colors.$grey-pale; + } + + &:focus { + outline: 2px solid colors.$blue-light; + } + + &:active { + background-color: colors.$blue-pale; + } + + &.active { + color: colors.$blue-dark; + font-weight: bold; + } +} + +.ellipsis { + color: colors.$blue-dark; + margin: 0; + line-height: 40px; + min-width: 40px; + height: 40px; + text-align: center; +} + +.chevron { + font-variation-settings: 'wght' 400; +} diff --git a/packages/sdg/src/lib/paginator/paginator.component.spec.ts b/packages/sdg/src/lib/paginator/paginator.component.spec.ts new file mode 100644 index 0000000..c919de0 --- /dev/null +++ b/packages/sdg/src/lib/paginator/paginator.component.spec.ts @@ -0,0 +1,26 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TEST_CONFIG } from '../../test-config'; +import { PaginatorComponent } from './paginator.component'; + +describe('PaginatorComponent', () => { + let component: PaginatorComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [PaginatorComponent], + providers: [...TEST_CONFIG.providers!] + }).compileComponents(); + + fixture = TestBed.createComponent(PaginatorComponent); + component = fixture.componentInstance; + fixture.componentRef.setInput('nbOfElementsInList', 15); + fixture.componentRef.setInput('nbOfElementsPerPage', 10); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/packages/sdg/src/lib/paginator/paginator.component.ts b/packages/sdg/src/lib/paginator/paginator.component.ts new file mode 100644 index 0000000..8731504 --- /dev/null +++ b/packages/sdg/src/lib/paginator/paginator.component.ts @@ -0,0 +1,148 @@ +import { NgFor, NgIf, NgStyle } from '@angular/common'; +import { + ChangeDetectionStrategy, + Component, + OnChanges, + OnInit, + SimpleChanges, + input, + output +} from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { MatIconModule } from '@angular/material/icon'; + +import { IgoLanguageModule } from '@igo2/core/language'; + +@Component({ + selector: 'sdg-paginator', + standalone: true, + imports: [ + NgIf, + NgFor, + NgStyle, + IgoLanguageModule, + MatButtonModule, + MatIconModule + ], + changeDetection: ChangeDetectionStrategy.OnPush, + templateUrl: './paginator.component.html', + styleUrls: ['./paginator.component.scss'] +}) +export class PaginatorComponent implements OnInit, OnChanges { + constructor() {} + + nbOfElementsInList = input.required(); + nbOfElementsPerPage = input.required(); + middlePagesMaxRange = input(1); + initialPage = input(1); + isHandset = input(); + + pageChange = output(); + + currentPage: number = 0; + nbOfPages: number = 0; + + firstPages: number[] = []; + middlePages: number[] = []; + lastPages: number[] = []; + pages: number[] = []; + + ngOnInit() { + this.currentPage = this.initialPage(); + + this.getNbOfPages(); + } + + ngOnChanges(changes: SimpleChanges) { + if ( + !changes.nbOfElementsPerPage.isFirstChange() && + changes.nbOfElementsPerPage + ) { + this.currentPage = 1; + this.pageChange.emit(this.currentPage); + + this.getNbOfPages(); + } + } + + private getNbOfPages() { + this.nbOfPages = Math.ceil( + this.nbOfElementsInList() / this.nbOfElementsPerPage() + ); + + this.getPages(); + } + + private createPagesArray(start: number, finish: number) { + return Array.from({ length: finish - start + 1 }, (_, a) => a + start); + } + + private getPages() { + this.firstPages = []; + this.middlePages = []; + this.lastPages = []; + this.pages = []; + + if (this.nbOfPages > 6) { + this.firstPages = this.getFirstPages(); + this.middlePages = this.getMiddlePages(); + this.lastPages = this.getLastPages(); + } else { + this.pages = Array.from({ length: this.nbOfPages }, (v, k) => k + 1); + } + } + + private getFirstPages() { + if (this.currentPage <= 3) { + return this.createPagesArray(1, 3); + } else { + return this.createPagesArray(1, 1); + } + } + + private getMiddlePages() { + if (this.currentPage >= 4 && this.currentPage <= this.nbOfPages - 3) { + return this.createPagesArray( + !this.isHandset() && this.currentPage - this.middlePagesMaxRange() > 2 + ? this.currentPage - this.middlePagesMaxRange() + : this.currentPage - 1, + !this.isHandset() && + this.currentPage + this.middlePagesMaxRange() < this.nbOfPages - 1 + ? this.currentPage + this.middlePagesMaxRange() + : this.currentPage + 1 + ); + } else { + return []; + } + } + + private getLastPages() { + if (this.currentPage >= this.nbOfPages - 2) { + return this.createPagesArray(this.nbOfPages - 2, this.nbOfPages); + } else { + return this.createPagesArray(this.nbOfPages, this.nbOfPages); + } + } + + goToPreviousPage() { + if (this.currentPage !== 1) { + this.currentPage -= 1; + this.getPages(); + this.pageChange.emit(this.currentPage); + } + } + + goToPage(page: number) { + this.currentPage = page; + this.getPages(); + this.pageChange.emit(this.currentPage); + } + + goToNextPage() { + if (this.currentPage !== this.nbOfPages) { + this.currentPage += 1; + this.getPages(); + this.pageChange.emit(this.currentPage); + } + } +} diff --git a/packages/sdg/src/public-api.ts b/packages/sdg/src/public-api.ts index aae5872..c21d879 100644 --- a/packages/sdg/src/public-api.ts +++ b/packages/sdg/src/public-api.ts @@ -9,3 +9,4 @@ export * from './lib/screen'; export * from './lib/alert'; export * from './lib/notice'; export * from './lib/tile'; +export * from './lib/paginator'; diff --git a/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.html b/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.html new file mode 100644 index 0000000..c8d8fc1 --- /dev/null +++ b/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.html @@ -0,0 +1,49 @@ +

+ La pagination est utilisée pour diviser le contenu ou les données en + plusieurs pages. Elle permet à l'utilisateur de naviguer vers la page + suivante ou précédente, ou de choisir une page environnante à la page en + cours. Pour plus d'information, voir la + + + du Système de design gouvernemental. +

+ + + + Nombre d'éléments par page + + @for ( + nbOfElementsOption of nbOfElementsOptions; + track nbOfElementsOption + ) { + + {{ nbOfElementsOption }} + } + + + +
+ @for (element of shownList; track element) { +

{{ element }} 

+ } +
+ + +
diff --git a/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.scss b/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.scss new file mode 100644 index 0000000..10bd4b4 --- /dev/null +++ b/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.scss @@ -0,0 +1,3 @@ +.list { + display: flex; +} diff --git a/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.spec.ts b/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.spec.ts new file mode 100644 index 0000000..3d69476 --- /dev/null +++ b/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PaginatorDemoComponent } from './paginator.component'; + +describe('PaginatorDemoComponent', () => { + let component: PaginatorDemoComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [PaginatorDemoComponent] + }).compileComponents(); + + fixture = TestBed.createComponent(PaginatorDemoComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.ts b/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.ts new file mode 100644 index 0000000..5af825c --- /dev/null +++ b/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.ts @@ -0,0 +1,56 @@ +import { Component, OnInit, Signal } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatSelectModule } from '@angular/material/select'; + +import { PaginatorComponent } from '@igo2/sdg'; + +import { AppService } from '../../../../app.service'; +import { ExampleViewerComponent } from '../../../../components/example-viewer/example-viewer.component'; +import { ExternalLinkComponent } from '../../../../components/external-link/external-link.component'; + +@Component({ + selector: 'app-paginator', + standalone: true, + imports: [ + ExampleViewerComponent, + ExternalLinkComponent, + PaginatorComponent, + MatFormFieldModule, + MatSelectModule, + FormsModule + ], + templateUrl: './paginator.component.html', + styleUrl: './paginator.component.scss' +}) +export class PaginatorDemoComponent implements OnInit { + constructor(private appService: AppService) {} + + initialPage: number = 3; + + nbOfElementsOptions: number[] = [2, 3, 5, 10, 15]; + selectedNbOfElements: number = 2; + + list = Array.from({ length: 35 }, (_, a) => a); + + shownList: number[] = []; + + get isHandset(): Signal { + return this.appService.isHandset; + } + + ngOnInit() { + this.setShownList(this.initialPage); + } + + private setShownList(page: number) { + this.shownList = this.list.slice( + this.selectedNbOfElements * (page - 1), + page * this.selectedNbOfElements + ); + } + + onPageChange(newPage: number) { + this.setShownList(newPage); + } +} diff --git a/projects/demo/src/app/pages/components/showcases/showcases.routes.ts b/projects/demo/src/app/pages/components/showcases/showcases.routes.ts index 45b0c6c..2993b78 100644 --- a/projects/demo/src/app/pages/components/showcases/showcases.routes.ts +++ b/projects/demo/src/app/pages/components/showcases/showcases.routes.ts @@ -28,6 +28,14 @@ export const routes: INavigationRoutes = [ (m) => m.BreadcrumbComponent ) }, + { + path: 'pagination', + title: 'Pagination', + loadComponent: () => + import('./paginator/paginator.component').then( + (m) => m.PaginatorDemoComponent + ) + }, { path: 'tuile', title: 'Tuile', From 638fb3a6ffb66576ab01bdda3c32c4356a802cdb Mon Sep 17 00:00:00 2001 From: Maxime Lamer Date: Fri, 30 Aug 2024 15:12:59 -0400 Subject: [PATCH 2/8] refactor(paginator): switched to indexes, scroll to header --- packages/sdg/src/_index.scss | 1 + .../src/lib/paginator/_paginator-theme.scss | 23 ++++ .../lib/paginator/paginator.component.html | 46 +++---- .../src/lib/paginator/paginator.component.ts | 113 ++++++++++-------- .../paginator/paginator.component.html | 21 ++-- .../paginator/paginator.component.scss | 1 + .../paginator/paginator.component.spec.ts | 5 +- .../paginator/paginator.component.ts | 18 +-- projects/demo/src/test-config.ts | 3 +- 9 files changed, 135 insertions(+), 96 deletions(-) create mode 100644 packages/sdg/src/lib/paginator/_paginator-theme.scss diff --git a/packages/sdg/src/_index.scss b/packages/sdg/src/_index.scss index 7348514..c3bb141 100644 --- a/packages/sdg/src/_index.scss +++ b/packages/sdg/src/_index.scss @@ -2,3 +2,4 @@ @forward './lib/breadcrumb/breadcrumb-theme' as breadcrumb-*; @forward './lib/navigation/navigation-theme' as navigation-*; +@forward './lib/paginator/paginator-theme' as paginator-*; diff --git a/packages/sdg/src/lib/paginator/_paginator-theme.scss b/packages/sdg/src/lib/paginator/_paginator-theme.scss new file mode 100644 index 0000000..a247f95 --- /dev/null +++ b/packages/sdg/src/lib/paginator/_paginator-theme.scss @@ -0,0 +1,23 @@ +@use 'sass:map'; +@use '@angular/material' as mat; + +@mixin theme($theme) { + @include color($theme); + @include density($theme); +} + +@mixin color($theme) { +} + +@mixin density($theme) { + $theme: map.merge( + $theme, + ( + density: -1 + ) + ); + + sdg-paginator { + @include mat.icon-button-density($theme); + } +} diff --git a/packages/sdg/src/lib/paginator/paginator.component.html b/packages/sdg/src/lib/paginator/paginator.component.html index 3ce94eb..c945cdb 100644 --- a/packages/sdg/src/lib/paginator/paginator.component.html +++ b/packages/sdg/src/lib/paginator/paginator.component.html @@ -1,52 +1,58 @@
- @if (currentPage !== 1) { + @if (currentPageIndex !== 0) { } - @for (firstPage of firstPages; track firstPage) { + @for (firstPageIndex of firstPagesIndexes; track firstPageIndex) {

- {{ firstPage }} + {{ firstPageIndex + 1 }}

} - @if ((!middlePages.length && lastPages.length === 1) || middlePages.length) { + @if ( + (!middlePagesIndexes.length && lastPagesIndexes.length === 1) || + middlePagesIndexes.length + ) {

...

} - @for (middlePage of middlePages; track middlePage) { + @for (middlePageIndex of middlePagesIndexes; track middlePageIndex) {

- {{ middlePage }} + {{ middlePageIndex + 1 }}

} - @if ((!middlePages.length && firstPages.length === 1) || middlePages.length) { + @if ( + (!middlePagesIndexes.length && firstPagesIndexes.length === 1) || + middlePagesIndexes.length + ) {

...

} - @for (lastPage of lastPages; track lastPage) { + @for (lastPageIndex of lastPagesIndexes; track lastPageIndex) {

- {{ lastPage }} + {{ lastPageIndex + 1 }}

} - @for (page of pages; track page) { + @for (pageIndex of pagesIndexes; track pageIndex) {

- {{ page }} + {{ pageIndex + 1 }}

} - @if (currentPage !== nbOfPages) { + @if (currentPageIndex !== nbOfPages - 1) { diff --git a/packages/sdg/src/lib/paginator/paginator.component.ts b/packages/sdg/src/lib/paginator/paginator.component.ts index 8731504..d995a87 100644 --- a/packages/sdg/src/lib/paginator/paginator.component.ts +++ b/packages/sdg/src/lib/paginator/paginator.component.ts @@ -1,7 +1,8 @@ -import { NgFor, NgIf, NgStyle } from '@angular/common'; +import { DOCUMENT, NgFor, NgIf, NgStyle } from '@angular/common'; import { ChangeDetectionStrategy, Component, + Inject, OnChanges, OnInit, SimpleChanges, @@ -29,87 +30,95 @@ import { IgoLanguageModule } from '@igo2/core/language'; styleUrls: ['./paginator.component.scss'] }) export class PaginatorComponent implements OnInit, OnChanges { - constructor() {} + constructor(@Inject(DOCUMENT) private document: Document) {} - nbOfElementsInList = input.required(); - nbOfElementsPerPage = input.required(); + listLength = input.required(); + pageSize = input.required(); middlePagesMaxRange = input(1); - initialPage = input(1); + initialPageIndex = input(0); isHandset = input(); pageChange = output(); - currentPage: number = 0; + currentPageIndex: number = 0; nbOfPages: number = 0; - firstPages: number[] = []; - middlePages: number[] = []; - lastPages: number[] = []; - pages: number[] = []; + firstPagesIndexes: number[] = []; + middlePagesIndexes: number[] = []; + lastPagesIndexes: number[] = []; + pagesIndexes: number[] = []; ngOnInit() { - this.currentPage = this.initialPage(); + this.currentPageIndex = this.initialPageIndex(); this.getNbOfPages(); } ngOnChanges(changes: SimpleChanges) { - if ( - !changes.nbOfElementsPerPage.isFirstChange() && - changes.nbOfElementsPerPage - ) { - this.currentPage = 1; - this.pageChange.emit(this.currentPage); + if (!changes.pageSize.isFirstChange() && changes.pageSize) { + this.currentPageIndex = 0; + this.pageChange.emit(this.currentPageIndex); this.getNbOfPages(); } } private getNbOfPages() { - this.nbOfPages = Math.ceil( - this.nbOfElementsInList() / this.nbOfElementsPerPage() - ); + this.nbOfPages = Math.ceil(this.listLength() / this.pageSize()); this.getPages(); } - private createPagesArray(start: number, finish: number) { - return Array.from({ length: finish - start + 1 }, (_, a) => a + start); + private createPagesArray(startIndex: number, finishIndex: number) { + return Array.from( + { length: finishIndex - startIndex + 1 }, + (_, a) => a + startIndex + ); } private getPages() { - this.firstPages = []; - this.middlePages = []; - this.lastPages = []; - this.pages = []; + this.firstPagesIndexes = []; + this.middlePagesIndexes = []; + this.lastPagesIndexes = []; + this.pagesIndexes = []; if (this.nbOfPages > 6) { - this.firstPages = this.getFirstPages(); - this.middlePages = this.getMiddlePages(); - this.lastPages = this.getLastPages(); + this.firstPagesIndexes = this.getFirstPages(); + this.middlePagesIndexes = this.getMiddlePages(); + this.lastPagesIndexes = this.getLastPages(); } else { - this.pages = Array.from({ length: this.nbOfPages }, (v, k) => k + 1); + this.pagesIndexes = Array.from({ length: this.nbOfPages }, (v, k) => k); } + + this.document + .getElementsByTagName('sdg-header') + .item(0) + ?.scrollIntoView(true); } private getFirstPages() { - if (this.currentPage <= 3) { - return this.createPagesArray(1, 3); + if (this.currentPageIndex <= 2) { + return this.createPagesArray(0, 2); } else { - return this.createPagesArray(1, 1); + return this.createPagesArray(0, 0); } } private getMiddlePages() { - if (this.currentPage >= 4 && this.currentPage <= this.nbOfPages - 3) { + if ( + this.currentPageIndex >= 3 && + this.currentPageIndex <= this.nbOfPages - 4 + ) { return this.createPagesArray( - !this.isHandset() && this.currentPage - this.middlePagesMaxRange() > 2 - ? this.currentPage - this.middlePagesMaxRange() - : this.currentPage - 1, !this.isHandset() && - this.currentPage + this.middlePagesMaxRange() < this.nbOfPages - 1 - ? this.currentPage + this.middlePagesMaxRange() - : this.currentPage + 1 + this.currentPageIndex - this.middlePagesMaxRange() > 1 + ? this.currentPageIndex - this.middlePagesMaxRange() + : this.currentPageIndex - 1, + !this.isHandset() && + this.currentPageIndex + this.middlePagesMaxRange() < + this.nbOfPages - 2 + ? this.currentPageIndex + this.middlePagesMaxRange() + : this.currentPageIndex + 1 ); } else { return []; @@ -117,32 +126,32 @@ export class PaginatorComponent implements OnInit, OnChanges { } private getLastPages() { - if (this.currentPage >= this.nbOfPages - 2) { - return this.createPagesArray(this.nbOfPages - 2, this.nbOfPages); + if (this.currentPageIndex >= this.nbOfPages - 3) { + return this.createPagesArray(this.nbOfPages - 3, this.nbOfPages - 1); } else { - return this.createPagesArray(this.nbOfPages, this.nbOfPages); + return this.createPagesArray(this.nbOfPages - 1, this.nbOfPages - 1); } } goToPreviousPage() { - if (this.currentPage !== 1) { - this.currentPage -= 1; + if (this.currentPageIndex !== 0) { + this.currentPageIndex -= 1; this.getPages(); - this.pageChange.emit(this.currentPage); + this.pageChange.emit(this.currentPageIndex); } } - goToPage(page: number) { - this.currentPage = page; + goToPage(pageIndex: number) { + this.currentPageIndex = pageIndex; this.getPages(); - this.pageChange.emit(this.currentPage); + this.pageChange.emit(this.currentPageIndex); } goToNextPage() { - if (this.currentPage !== this.nbOfPages) { - this.currentPage += 1; + if (this.currentPageIndex !== this.nbOfPages - 1) { + this.currentPageIndex += 1; this.getPages(); - this.pageChange.emit(this.currentPage); + this.pageChange.emit(this.currentPageIndex); } } } diff --git a/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.html b/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.html index c8d8fc1..5389690 100644 --- a/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.html +++ b/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.html @@ -19,30 +19,25 @@ codeFolder="paginator" > - Nombre d'éléments par page - - @for ( - nbOfElementsOption of nbOfElementsOptions; - track nbOfElementsOption - ) { - - {{ nbOfElementsOption }} + Nombre d'éléments par page + + @for (pageSize of pageSizes; track pageSize) { + {{ pageSize }} }
@for (element of shownList; track element) { -

{{ element }} 

+

{{ element }}

}
diff --git a/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.scss b/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.scss index 10bd4b4..4aee717 100644 --- a/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.scss +++ b/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.scss @@ -1,3 +1,4 @@ .list { display: flex; + flex-flow: column; } diff --git a/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.spec.ts b/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.spec.ts index 3d69476..0700cbb 100644 --- a/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.spec.ts +++ b/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.spec.ts @@ -1,5 +1,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { TEST_CONFIG } from 'projects/demo/src/test-config'; + import { PaginatorDemoComponent } from './paginator.component'; describe('PaginatorDemoComponent', () => { @@ -8,7 +10,8 @@ describe('PaginatorDemoComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [PaginatorDemoComponent] + imports: [PaginatorDemoComponent], + providers: [...TEST_CONFIG.providers!] }).compileComponents(); fixture = TestBed.createComponent(PaginatorDemoComponent); diff --git a/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.ts b/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.ts index 5af825c..2569ce7 100644 --- a/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.ts +++ b/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.ts @@ -26,10 +26,10 @@ import { ExternalLinkComponent } from '../../../../components/external-link/exte export class PaginatorDemoComponent implements OnInit { constructor(private appService: AppService) {} - initialPage: number = 3; + initialPageIndex: number = 2; - nbOfElementsOptions: number[] = [2, 3, 5, 10, 15]; - selectedNbOfElements: number = 2; + pageSizes: number[] = [2, 3, 5, 10, 15]; + selectedPageSize: number = 2; list = Array.from({ length: 35 }, (_, a) => a); @@ -40,17 +40,17 @@ export class PaginatorDemoComponent implements OnInit { } ngOnInit() { - this.setShownList(this.initialPage); + this.setShownList(this.initialPageIndex); } - private setShownList(page: number) { + private setShownList(pageIndex: number) { this.shownList = this.list.slice( - this.selectedNbOfElements * (page - 1), - page * this.selectedNbOfElements + this.selectedPageSize * pageIndex, + this.selectedPageSize * (pageIndex + 1) ); } - onPageChange(newPage: number) { - this.setShownList(newPage); + onPageChange(newPageIndex: number) { + this.setShownList(newPageIndex); } } diff --git a/projects/demo/src/test-config.ts b/projects/demo/src/test-config.ts index ec7486d..b3f33c8 100644 --- a/projects/demo/src/test-config.ts +++ b/projects/demo/src/test-config.ts @@ -1,8 +1,9 @@ import { TestModuleMetadata } from '@angular/core/testing'; +import { provideAnimations } from '@angular/platform-browser/animations'; import { provideRouter } from '@angular/router'; import { provideMockTranslation } from '@igo2/core/language'; export const TEST_CONFIG: TestModuleMetadata = { - providers: [provideRouter([]), provideMockTranslation()] + providers: [provideRouter([]), provideMockTranslation(), provideAnimations()] }; From 6e357c53ab426db64212a242a8af9f51d6e79b26 Mon Sep 17 00:00:00 2001 From: Maxime Lamer Date: Fri, 30 Aug 2024 15:17:14 -0400 Subject: [PATCH 3/8] fix(paginator): test input fix --- packages/sdg/src/lib/paginator/paginator.component.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/sdg/src/lib/paginator/paginator.component.spec.ts b/packages/sdg/src/lib/paginator/paginator.component.spec.ts index c919de0..ace7052 100644 --- a/packages/sdg/src/lib/paginator/paginator.component.spec.ts +++ b/packages/sdg/src/lib/paginator/paginator.component.spec.ts @@ -15,8 +15,8 @@ describe('PaginatorComponent', () => { fixture = TestBed.createComponent(PaginatorComponent); component = fixture.componentInstance; - fixture.componentRef.setInput('nbOfElementsInList', 15); - fixture.componentRef.setInput('nbOfElementsPerPage', 10); + fixture.componentRef.setInput('listLength', 15); + fixture.componentRef.setInput('pageSize', 10); fixture.detectChanges(); }); From 60a4daabac3bdf0a4fdcc589de263de9d38a4408 Mon Sep 17 00:00:00 2001 From: Maxime Lamer Date: Tue, 3 Sep 2024 11:07:18 -0400 Subject: [PATCH 4/8] fix(paginator): button density --- packages/sdg/src/lib/core/theme/_all-theme.scss | 4 ++++ packages/sdg/src/lib/paginator/_paginator-theme.scss | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/sdg/src/lib/core/theme/_all-theme.scss b/packages/sdg/src/lib/core/theme/_all-theme.scss index 52e834c..c1af358 100644 --- a/packages/sdg/src/lib/core/theme/_all-theme.scss +++ b/packages/sdg/src/lib/core/theme/_all-theme.scss @@ -1,10 +1,12 @@ @use '../style/overrides'; @use '../../breadcrumb/breadcrumb-theme' as breadcrumb; @use '../../navigation/navigation-theme' as navigation; +@use '../../paginator/paginator-theme' as paginator; @mixin all-component-themes($theme) { @include breadcrumb.theme($theme); @include navigation.theme($theme); + @include paginator.theme($theme); @include overrides.override-igo2-lib-themes($theme); @include overrides.override-material-themes($theme); } @@ -12,6 +14,7 @@ @mixin all-component-colors($theme) { @include breadcrumb.color($theme); @include navigation.color($theme); + @include paginator.color($theme); @include overrides.override-igo2-lib-colors($theme); @include overrides.override-material-colors($theme); } @@ -19,6 +22,7 @@ @mixin all-component-densities($theme) { @include breadcrumb.density($theme); @include navigation.density($theme); + @include paginator.density($theme); @include overrides.override-igo2-lib-densities($theme); @include overrides.override-material-densities($theme); } diff --git a/packages/sdg/src/lib/paginator/_paginator-theme.scss b/packages/sdg/src/lib/paginator/_paginator-theme.scss index a247f95..a9b04d7 100644 --- a/packages/sdg/src/lib/paginator/_paginator-theme.scss +++ b/packages/sdg/src/lib/paginator/_paginator-theme.scss @@ -13,7 +13,7 @@ $theme: map.merge( $theme, ( - density: -1 + density: -2 ) ); From 0b3a9662dc33eaa0b7cf8916de90647f561fe6f7 Mon Sep 17 00:00:00 2001 From: Maxime Lamer Date: Tue, 3 Sep 2024 11:41:07 -0400 Subject: [PATCH 5/8] refactor(paginator): ngOnChanges to effect() --- .../src/lib/paginator/paginator.component.ts | 40 ++++++++++++------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/packages/sdg/src/lib/paginator/paginator.component.ts b/packages/sdg/src/lib/paginator/paginator.component.ts index d995a87..c574852 100644 --- a/packages/sdg/src/lib/paginator/paginator.component.ts +++ b/packages/sdg/src/lib/paginator/paginator.component.ts @@ -3,9 +3,10 @@ import { ChangeDetectionStrategy, Component, Inject, - OnChanges, + Injector, OnInit, - SimpleChanges, + effect, + inject, input, output } from '@angular/core'; @@ -29,8 +30,9 @@ import { IgoLanguageModule } from '@igo2/core/language'; templateUrl: './paginator.component.html', styleUrls: ['./paginator.component.scss'] }) -export class PaginatorComponent implements OnInit, OnChanges { +export class PaginatorComponent implements OnInit { constructor(@Inject(DOCUMENT) private document: Document) {} + injector = inject(Injector); listLength = input.required(); pageSize = input.required(); @@ -40,6 +42,8 @@ export class PaginatorComponent implements OnInit, OnChanges { pageChange = output(); + initialPageIndexFirstChange = true; + currentPageIndex: number = 0; nbOfPages: number = 0; @@ -51,20 +55,26 @@ export class PaginatorComponent implements OnInit, OnChanges { ngOnInit() { this.currentPageIndex = this.initialPageIndex(); - this.getNbOfPages(); - } - - ngOnChanges(changes: SimpleChanges) { - if (!changes.pageSize.isFirstChange() && changes.pageSize) { - this.currentPageIndex = 0; - this.pageChange.emit(this.currentPageIndex); - - this.getNbOfPages(); - } + this.getNbOfPages(this.pageSize()); + + effect( + () => { + const pageSize = this.pageSize(); + if (!this.initialPageIndexFirstChange) { + this.currentPageIndex = 0; + this.pageChange.emit(this.currentPageIndex); + + this.getNbOfPages(pageSize); + } else { + this.initialPageIndexFirstChange = false; + } + }, + { injector: this.injector } + ); } - private getNbOfPages() { - this.nbOfPages = Math.ceil(this.listLength() / this.pageSize()); + private getNbOfPages(pageSize: number) { + this.nbOfPages = Math.ceil(this.listLength() / pageSize); this.getPages(); } From 5ca503a693257ecb5b8380bd000e85744075bbde Mon Sep 17 00:00:00 2001 From: Maxime Lamer Date: Fri, 6 Sep 2024 13:58:33 -0400 Subject: [PATCH 6/8] refactor(paginator): focus skip active, effect in constructor --- .../lib/paginator/paginator.component.html | 8 +++++ .../lib/paginator/paginator.component.scss | 23 ++++++++----- .../src/lib/paginator/paginator.component.ts | 33 +++++++++---------- 3 files changed, 38 insertions(+), 26 deletions(-) diff --git a/packages/sdg/src/lib/paginator/paginator.component.html b/packages/sdg/src/lib/paginator/paginator.component.html index c945cdb..7593d7b 100644 --- a/packages/sdg/src/lib/paginator/paginator.component.html +++ b/packages/sdg/src/lib/paginator/paginator.component.html @@ -9,6 +9,8 @@ class="page" [class.active]="firstPageIndex === currentPageIndex" (click)="goToPage(firstPageIndex)" + (keyup.enter)="goToPage(firstPageIndex)" + [tabindex]="firstPageIndex !== currentPageIndex ? '0' : '-1'" > {{ firstPageIndex + 1 }}

@@ -24,6 +26,8 @@ class="page" [class.active]="middlePageIndex === currentPageIndex" (click)="goToPage(middlePageIndex)" + (keyup.enter)="goToPage(middlePageIndex)" + [tabindex]="middlePageIndex !== currentPageIndex ? '0' : '-1'" > {{ middlePageIndex + 1 }}

@@ -39,6 +43,8 @@ class="page" [class.active]="lastPageIndex === currentPageIndex" (click)="goToPage(lastPageIndex)" + (keyup.enter)="goToPage(lastPageIndex)" + [tabindex]="lastPageIndex !== currentPageIndex ? '0' : '-1'" > {{ lastPageIndex + 1 }}

@@ -48,6 +54,8 @@ class="page" [class.active]="pageIndex === currentPageIndex" (click)="goToPage(pageIndex)" + (keyup.enter)="goToPage(pageIndex)" + [tabindex]="pageIndex !== currentPageIndex ? '0' : '-1'" > {{ pageIndex + 1 }}

diff --git a/packages/sdg/src/lib/paginator/paginator.component.scss b/packages/sdg/src/lib/paginator/paginator.component.scss index 3861721..1976341 100644 --- a/packages/sdg/src/lib/paginator/paginator.component.scss +++ b/packages/sdg/src/lib/paginator/paginator.component.scss @@ -15,21 +15,28 @@ height: 40px; text-align: center; - &:hover { - background-color: colors.$grey-pale; - } - &:focus { outline: 2px solid colors.$blue-light; } - &:active { - background-color: colors.$blue-pale; - } - &.active { color: colors.$blue-dark; font-weight: bold; + outline: none; + cursor: default; + + &:hover { + background-color: transparent; + } + } + + &:hover { + background-color: colors.$grey-pale; + } + + &:active { + outline: none; + background-color: colors.$blue-pale; } } diff --git a/packages/sdg/src/lib/paginator/paginator.component.ts b/packages/sdg/src/lib/paginator/paginator.component.ts index c574852..b064d97 100644 --- a/packages/sdg/src/lib/paginator/paginator.component.ts +++ b/packages/sdg/src/lib/paginator/paginator.component.ts @@ -31,7 +31,19 @@ import { IgoLanguageModule } from '@igo2/core/language'; styleUrls: ['./paginator.component.scss'] }) export class PaginatorComponent implements OnInit { - constructor(@Inject(DOCUMENT) private document: Document) {} + constructor(@Inject(DOCUMENT) private document: Document) { + effect(() => { + const pageSize = this.pageSize(); + if (!this.initialPageIndexFirstChange) { + this.currentPageIndex = 0; + this.pageChange.emit(this.currentPageIndex); + + this.getNbOfPages(pageSize); + } else { + this.initialPageIndexFirstChange = false; + } + }); + } injector = inject(Injector); listLength = input.required(); @@ -44,8 +56,8 @@ export class PaginatorComponent implements OnInit { initialPageIndexFirstChange = true; - currentPageIndex: number = 0; - nbOfPages: number = 0; + currentPageIndex = 0; + nbOfPages = 0; firstPagesIndexes: number[] = []; middlePagesIndexes: number[] = []; @@ -56,21 +68,6 @@ export class PaginatorComponent implements OnInit { this.currentPageIndex = this.initialPageIndex(); this.getNbOfPages(this.pageSize()); - - effect( - () => { - const pageSize = this.pageSize(); - if (!this.initialPageIndexFirstChange) { - this.currentPageIndex = 0; - this.pageChange.emit(this.currentPageIndex); - - this.getNbOfPages(pageSize); - } else { - this.initialPageIndexFirstChange = false; - } - }, - { injector: this.injector } - ); } private getNbOfPages(pageSize: number) { From c2aa501d454a135c3cb9ec3e6e255ed44a2ae861 Mon Sep 17 00:00:00 2001 From: Maxime Lamer Date: Fri, 6 Sep 2024 14:03:05 -0400 Subject: [PATCH 7/8] refactor(paginator): typing --- .../components/showcases/paginator/paginator.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.ts b/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.ts index 2569ce7..574ca0a 100644 --- a/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.ts +++ b/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.ts @@ -26,10 +26,10 @@ import { ExternalLinkComponent } from '../../../../components/external-link/exte export class PaginatorDemoComponent implements OnInit { constructor(private appService: AppService) {} - initialPageIndex: number = 2; + initialPageIndex = 2; pageSizes: number[] = [2, 3, 5, 10, 15]; - selectedPageSize: number = 2; + selectedPageSize = 2; list = Array.from({ length: 35 }, (_, a) => a); From 9f6ee0e333d498a4638967acb20c152a1002640f Mon Sep 17 00:00:00 2001 From: Maxime Lamer Date: Wed, 18 Sep 2024 13:16:39 -0400 Subject: [PATCH 8/8] refactor(paginator): p to button --- .../lib/paginator/paginator.component.html | 130 +++++++++--------- .../lib/paginator/paginator.component.scss | 55 ++++---- .../paginator/paginator.component.scss | 6 + 3 files changed, 98 insertions(+), 93 deletions(-) diff --git a/packages/sdg/src/lib/paginator/paginator.component.html b/packages/sdg/src/lib/paginator/paginator.component.html index 7593d7b..0368c3f 100644 --- a/packages/sdg/src/lib/paginator/paginator.component.html +++ b/packages/sdg/src/lib/paginator/paginator.component.html @@ -1,68 +1,62 @@ -
- @if (currentPageIndex !== 0) { - - } - @for (firstPageIndex of firstPagesIndexes; track firstPageIndex) { -

- {{ firstPageIndex + 1 }} -

- } - @if ( - (!middlePagesIndexes.length && lastPagesIndexes.length === 1) || - middlePagesIndexes.length - ) { -

...

- } - @for (middlePageIndex of middlePagesIndexes; track middlePageIndex) { -

- {{ middlePageIndex + 1 }} -

- } - @if ( - (!middlePagesIndexes.length && firstPagesIndexes.length === 1) || - middlePagesIndexes.length - ) { -

...

- } - @for (lastPageIndex of lastPagesIndexes; track lastPageIndex) { -

- {{ lastPageIndex + 1 }} -

- } - @for (pageIndex of pagesIndexes; track pageIndex) { -

- {{ pageIndex + 1 }} -

- } - @if (currentPageIndex !== nbOfPages - 1) { - - } -
+@if (currentPageIndex !== 0) { + +} +@for (firstPageIndex of firstPagesIndexes; track firstPageIndex) { + +} +@if ( + (!middlePagesIndexes.length && lastPagesIndexes.length === 1) || + middlePagesIndexes.length +) { +

...

+} +@for (middlePageIndex of middlePagesIndexes; track middlePageIndex) { + +} +@if ( + (!middlePagesIndexes.length && firstPagesIndexes.length === 1) || + middlePagesIndexes.length +) { +

...

+} +@for (lastPageIndex of lastPagesIndexes; track lastPageIndex) { + +} +@for (pageIndex of pagesIndexes; track pageIndex) { + +} +@if (currentPageIndex !== nbOfPages - 1) { + +} diff --git a/packages/sdg/src/lib/paginator/paginator.component.scss b/packages/sdg/src/lib/paginator/paginator.component.scss index 1976341..558726a 100644 --- a/packages/sdg/src/lib/paginator/paginator.component.scss +++ b/packages/sdg/src/lib/paginator/paginator.component.scss @@ -1,54 +1,59 @@ @use '../core/theme/colors'; -.container { - display: flex; - align-items: center; - justify-content: center; -} - -.page { - color: colors.$blue-piv; +.button, +.page, +.ellipsis { margin: 0; line-height: 40px; - cursor: pointer; min-width: 40px; height: 40px; text-align: center; + background-color: transparent; + border: none; + cursor: pointer; &:focus { outline: 2px solid colors.$blue-light; } + &:hover { + outline: none; + background-color: colors.$grey-pale; + } + + &:active { + outline: none; + background-color: colors.$blue-pale; + } + &.active { + outline: none; color: colors.$blue-dark; font-weight: bold; - outline: none; cursor: default; &:hover { background-color: transparent; } } +} - &:hover { - background-color: colors.$grey-pale; - } +.chevron { + vertical-align: middle; + font-variation-settings: 'wght' 400; +} - &:active { - outline: none; - background-color: colors.$blue-pale; - } +.page { + font-size: 16px; + font-family: 'Open Sans', sans-serif; + color: colors.$blue-piv; } .ellipsis { color: colors.$blue-dark; - margin: 0; - line-height: 40px; - min-width: 40px; - height: 40px; - text-align: center; -} + cursor: default; -.chevron { - font-variation-settings: 'wght' 400; + &:hover { + background-color: transparent; + } } diff --git a/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.scss b/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.scss index 4aee717..f3128b6 100644 --- a/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.scss +++ b/projects/demo/src/app/pages/components/showcases/paginator/paginator.component.scss @@ -2,3 +2,9 @@ display: flex; flex-flow: column; } + +sdg-paginator { + display: flex; + align-items: center; + justify-content: center; +}