diff --git a/apps/datahub/src/app/organization/organization-details/organization-details.component.ts b/apps/datahub/src/app/organization/organization-details/organization-details.component.ts
index a089aca95..c4877241b 100644
--- a/apps/datahub/src/app/organization/organization-details/organization-details.component.ts
+++ b/apps/datahub/src/app/organization/organization-details/organization-details.component.ts
@@ -11,21 +11,16 @@ import {
CatalogRecord,
Organization,
} from '@geonetwork-ui/common/domain/model/record'
-import {
- ButtonComponent,
- PreviousNextButtonsComponent,
-} from '@geonetwork-ui/ui/inputs'
import { TranslateModule } from '@ngx-translate/core'
import {
BlockListComponent,
- CarouselComponent,
MaxLinesComponent,
+ PreviousNextButtonsComponent,
} from '@geonetwork-ui/ui/layout'
import { LetDirective } from '@ngrx/component'
import {
ErrorComponent,
ErrorType,
- LinkCardComponent,
RelatedRecordCardComponent,
UiElementsModule,
} from '@geonetwork-ui/ui/elements'
@@ -57,12 +52,8 @@ import { startWith } from 'rxjs/operators'
standalone: true,
imports: [
CommonModule,
- ButtonComponent,
TranslateModule,
- CarouselComponent,
- BlockListComponent,
LetDirective,
- LinkCardComponent,
PreviousNextButtonsComponent,
UiElementsModule,
UiSearchModule,
diff --git a/apps/datahub/src/app/record/record-apis/record-apis.component.html b/apps/datahub/src/app/record/record-apis/record-apis.component.html
index dd22ded98..3ad41c9fb 100644
--- a/apps/datahub/src/app/record/record-apis/record-apis.component.html
+++ b/apps/datahub/src/app/record/record-apis/record-apis.component.html
@@ -6,13 +6,15 @@
record.metadata.api
1"
+ [listComponent]="carousel"
>
-
+
1
- }
-
updateView() {
this.changeDetector.detectChanges()
}
- get isFirstStep() {
- return this.carousel?.isFirstStep
- }
-
- get isLastStep() {
- return this.carousel?.isLastStep
- }
-
openRecordApiForm(link: DatasetServiceDistribution) {
this.selectedApiLink = link
this.setStyle(link)
@@ -88,12 +78,4 @@ export class RecordApisComponent implements OnInit {
this.maxHeight = link === undefined ? '0px' : '500px'
this.opacity = link === undefined ? 0 : 1
}
-
- changeStepOrPage(direction: string) {
- if (direction === 'next') {
- this.carousel?.slideToNext()
- } else {
- this.carousel?.slideToPrevious()
- }
- }
}
diff --git a/apps/datahub/src/app/record/record-otherlinks/record-otherlinks.component.html b/apps/datahub/src/app/record/record-otherlinks/record-otherlinks.component.html
index b97bc8a20..8d7acc549 100644
--- a/apps/datahub/src/app/record/record-otherlinks/record-otherlinks.component.html
+++ b/apps/datahub/src/app/record/record-otherlinks/record-otherlinks.component.html
@@ -6,10 +6,8 @@
record.metadata.links
1"
+ [listComponent]="paginableElement"
>
diff --git a/apps/datahub/src/app/record/record-otherlinks/record-otherlinks.component.ts b/apps/datahub/src/app/record/record-otherlinks/record-otherlinks.component.ts
index cef2c555c..799d6dea6 100644
--- a/apps/datahub/src/app/record/record-otherlinks/record-otherlinks.component.ts
+++ b/apps/datahub/src/app/record/record-otherlinks/record-otherlinks.component.ts
@@ -6,8 +6,12 @@ import {
ViewChild,
} from '@angular/core'
import { MdViewFacade } from '@geonetwork-ui/feature/record'
-import { BlockListComponent, CarouselComponent } from '@geonetwork-ui/ui/layout'
-import { PreviousNextButtonsComponent } from '@geonetwork-ui/ui/inputs'
+import {
+ BlockListComponent,
+ CarouselComponent,
+ Paginable,
+ PreviousNextButtonsComponent,
+} from '@geonetwork-ui/ui/layout'
import { CommonModule } from '@angular/common'
import { LinkCardComponent } from '@geonetwork-ui/ui/elements'
import { LetDirective } from '@ngrx/component'
@@ -34,34 +38,15 @@ export class RecordOtherlinksComponent implements AfterViewInit {
@ViewChild(CarouselComponent) carousel: CarouselComponent
@ViewChild(BlockListComponent) list: BlockListComponent
+ get paginableElement(): Paginable {
+ return this.carousel || this.list
+ }
constructor(
public facade: MdViewFacade,
private changeDetector: ChangeDetectorRef
) {}
- get isFirstStepOrPage() {
- return this.carousel?.isFirstStep ?? this.list?.isFirstPage ?? true
- }
-
- get isLastStepOrPage() {
- return this.carousel?.isLastStep ?? this.list?.isLastPage ?? false
- }
-
- get hasPagination() {
- return (this.carousel?.stepsCount || this.list?.pagesCount) > 1
- }
-
- changeStepOrPage(direction: string) {
- if (direction === 'next') {
- this.list?.nextPage()
- this.carousel?.slideToNext()
- } else {
- this.carousel?.slideToPrevious()
- this.list?.previousPage()
- }
- }
-
updateView() {
this.changeDetector.detectChanges()
}
diff --git a/apps/metadata-editor/src/app/records/records-list.component.html b/apps/metadata-editor/src/app/records/records-list.component.html
index 215e2e950..b5be0a567 100644
--- a/apps/metadata-editor/src/app/records/records-list.component.html
+++ b/apps/metadata-editor/src/app/records/records-list.component.html
@@ -7,10 +7,6 @@
>
-
+
diff --git a/apps/metadata-editor/src/app/records/records-list.component.spec.ts b/apps/metadata-editor/src/app/records/records-list.component.spec.ts
index 2a277e859..06835d444 100644
--- a/apps/metadata-editor/src/app/records/records-list.component.spec.ts
+++ b/apps/metadata-editor/src/app/records/records-list.component.spec.ts
@@ -10,7 +10,7 @@ import { Router } from '@angular/router'
import { BehaviorSubject } from 'rxjs'
import { datasetRecordsFixture } from '@geonetwork-ui/common/fixtures'
import { MockBuilder } from 'ng-mocks'
-import { PaginationButtonsComponent } from '@geonetwork-ui/ui/elements'
+import { PaginationButtonsComponent } from '@geonetwork-ui/ui/layout'
const results = [{ md: true }]
const currentPage = 5
diff --git a/apps/metadata-editor/src/app/records/records-list.component.ts b/apps/metadata-editor/src/app/records/records-list.component.ts
index 8f53f6d99..8659cc2ac 100644
--- a/apps/metadata-editor/src/app/records/records-list.component.ts
+++ b/apps/metadata-editor/src/app/records/records-list.component.ts
@@ -8,12 +8,10 @@ import {
SearchService,
} from '@geonetwork-ui/feature/search'
import { UiSearchModule } from '@geonetwork-ui/ui/search'
-import {
- PaginationButtonsComponent,
- UiElementsModule,
-} from '@geonetwork-ui/ui/elements'
+import { UiElementsModule } from '@geonetwork-ui/ui/elements'
import { TranslateModule } from '@ngx-translate/core'
import { UiInputsModule } from '@geonetwork-ui/ui/inputs'
+import { Paginable, PaginationButtonsComponent } from '@geonetwork-ui/ui/layout'
export const allSearchFields = [
'uuid',
@@ -41,7 +39,7 @@ export const allSearchFields = [
PaginationButtonsComponent,
],
})
-export class RecordsListComponent implements OnInit {
+export class RecordsListComponent implements OnInit, Paginable {
constructor(
private router: Router,
public searchFacade: SearchFacade,
@@ -51,10 +49,13 @@ export class RecordsListComponent implements OnInit {
ngOnInit(): void {
this.searchFacade.setConfigRequestFields(allSearchFields)
this.searchFacade.setPageSize(15)
- }
- paginate(page: number) {
- this.searchService.setPage(page)
+ this.searchFacade.currentPage$.subscribe((page) => {
+ this.currentPage_ = page
+ })
+ this.searchFacade.totalPages$.subscribe((total) => {
+ this.totalPages_ = total
+ })
}
editRecord(record: CatalogRecord) {
@@ -64,4 +65,31 @@ export class RecordsListComponent implements OnInit {
duplicateRecord(record: CatalogRecord) {
this.router.navigate(['/duplicate', record.uniqueIdentifier])
}
+
+ // these are 0 based
+ totalPages_: number
+ currentPage_: number
+
+ // Paginable API
+ get isFirstPage() {
+ return this.currentPage_ === 0
+ }
+ get isLastPage() {
+ return this.currentPage_ === this.totalPages_ - 1
+ }
+ get pagesCount() {
+ return this.totalPages_
+ }
+ get currentPage() {
+ return this.currentPage_ + 1 // this is 1-based for the Paginable API
+ }
+ goToPage(page: number) {
+ this.searchService.setPage(page - 1)
+ }
+ goToNextPage() {
+ this.searchService.setPage(this.currentPage_ + 1)
+ }
+ goToPrevPage() {
+ this.searchService.setPage(this.currentPage_ - 1)
+ }
}
diff --git a/libs/feature/catalog/src/lib/organisations/organisations.component.html b/libs/feature/catalog/src/lib/organisations/organisations.component.html
index 3d253d16f..0e6e6c1c2 100644
--- a/libs/feature/catalog/src/lib/organisations/organisations.component.html
+++ b/libs/feature/catalog/src/lib/organisations/organisations.component.html
@@ -26,9 +26,5 @@
-
+
diff --git a/libs/feature/catalog/src/lib/organisations/organisations.component.ts b/libs/feature/catalog/src/lib/organisations/organisations.component.ts
index 565a631c6..474b34ec5 100644
--- a/libs/feature/catalog/src/lib/organisations/organisations.component.ts
+++ b/libs/feature/catalog/src/lib/organisations/organisations.component.ts
@@ -14,16 +14,14 @@ import { OrganizationsServiceInterface } from '@geonetwork-ui/common/domain/orga
import { SortByField } from '@geonetwork-ui/common/domain/model/search'
import { createFuzzyFilter } from '@geonetwork-ui/util/shared'
import { ORGANIZATION_PAGE_URL_TOKEN } from '../organization-url.token'
-import {
- ContentGhostComponent,
- PaginationComponent,
-} from '@geonetwork-ui/ui/elements'
+import { ContentGhostComponent } from '@geonetwork-ui/ui/elements'
import { CommonModule } from '@angular/common'
import {
OrganisationPreviewComponent,
OrganisationsFilterComponent,
OrganisationsResultComponent,
} from '@geonetwork-ui/ui/catalog'
+import { Paginable, PaginationComponent } from '@geonetwork-ui/ui/layout'
@Component({
selector: 'gn-ui-organisations',
@@ -40,7 +38,7 @@ import {
PaginationComponent,
],
})
-export class OrganisationsComponent {
+export class OrganisationsComponent implements Paginable {
@Input() itemsOnPage = 12
@Output() orgSelect = new EventEmitter()
@@ -89,10 +87,6 @@ export class OrganisationsComponent {
)
)
- protected setCurrentPage(page: number): void {
- this.currentPage$.next(page)
- }
-
protected setFilterBy(value: string): void {
this.currentPage$.next(1)
this.filterBy$.next(value)
@@ -140,4 +134,27 @@ export class OrganisationsComponent {
if (!this.urlTemplate) return null
return this.urlTemplate.replace('${name}', organisation.name)
}
+
+ // Paginable API
+ get isFirstPage() {
+ return this.currentPage === 1
+ }
+ get isLastPage() {
+ return this.currentPage === this.totalPages
+ }
+ get pagesCount() {
+ return this.totalPages
+ }
+ get currentPage() {
+ return this.currentPage$.value
+ }
+ goToPage(index: number) {
+ this.currentPage$.next(index)
+ }
+ goToNextPage() {
+ this.goToPage(this.currentPage - 1)
+ }
+ goToPrevPage() {
+ this.goToPage(this.currentPage + 1)
+ }
}
diff --git a/libs/ui/layout/src/lib/block-list/block-list.component.html b/libs/ui/layout/src/lib/block-list/block-list.component.html
index 17e706ddd..8dc5b8a66 100644
--- a/libs/ui/layout/src/lib/block-list/block-list.component.html
+++ b/libs/ui/layout/src/lib/block-list/block-list.component.html
@@ -14,7 +14,7 @@
diff --git a/libs/ui/layout/src/lib/block-list/block-list.component.spec.ts b/libs/ui/layout/src/lib/block-list/block-list.component.spec.ts
index 2b28278dd..39b4a4b45 100644
--- a/libs/ui/layout/src/lib/block-list/block-list.component.spec.ts
+++ b/libs/ui/layout/src/lib/block-list/block-list.component.spec.ts
@@ -103,7 +103,7 @@ describe('BlockListComponent', () => {
beforeEach(() => {
component.pageSize = 2
component.goToPage(2)
- component.previousPage()
+ component.goToPrevPage()
})
it('changes to previous page', () => {
expect(component['currentPage']).toEqual(1)
@@ -114,7 +114,7 @@ describe('BlockListComponent', () => {
beforeEach(() => {
component.pageSize = 2
component.goToPage(1)
- component.nextPage()
+ component.goToNextPage()
})
it('changes to next page', () => {
expect(component['currentPage']).toEqual(2)
diff --git a/libs/ui/layout/src/lib/block-list/block-list.component.stories.ts b/libs/ui/layout/src/lib/block-list/block-list.component.stories.ts
index 31f06fdd7..7e921a611 100644
--- a/libs/ui/layout/src/lib/block-list/block-list.component.stories.ts
+++ b/libs/ui/layout/src/lib/block-list/block-list.component.stories.ts
@@ -1,6 +1,6 @@
import type { Meta, StoryObj } from '@storybook/angular'
-import { BlockListComponent } from './block-list.component'
import { componentWrapperDecorator } from '@storybook/angular'
+import { BlockListComponent } from './block-list.component'
const meta: Meta = {
component: BlockListComponent,
diff --git a/libs/ui/layout/src/lib/block-list/block-list.component.ts b/libs/ui/layout/src/lib/block-list/block-list.component.ts
index 5a0937c76..405f3460c 100644
--- a/libs/ui/layout/src/lib/block-list/block-list.component.ts
+++ b/libs/ui/layout/src/lib/block-list/block-list.component.ts
@@ -10,6 +10,7 @@ import {
ViewChild,
} from '@angular/core'
import { CommonModule } from '@angular/common'
+import { Paginable } from '../paginable.interface'
@Component({
selector: 'gn-ui-block-list',
@@ -19,7 +20,7 @@ import { CommonModule } from '@angular/common'
standalone: true,
imports: [CommonModule],
})
-export class BlockListComponent implements AfterViewInit {
+export class BlockListComponent implements AfterViewInit, Paginable {
@Input() pageSize = 5
@Input() containerClass = ''
@Input() paginationContainerClass = 'w-full bottom-0 top-auto'
@@ -30,20 +31,23 @@ export class BlockListComponent implements AfterViewInit {
protected minHeight = 0
- protected currentPage = 0
+ protected currentPage_ = 0
protected get pages() {
return new Array(this.pagesCount).fill(0).map((_, i) => i)
}
get isFirstPage() {
- return this.currentPage === 0
+ return this.currentPage_ === 0
}
get isLastPage() {
- return this.currentPage === this.pagesCount - 1
+ return this.currentPage_ === this.pagesCount - 1
}
get pagesCount() {
return this.blocks ? Math.ceil(this.blocks.length / this.pageSize) : 1
}
+ get currentPage() {
+ return this.currentPage_ + 1 // this is 1-based
+ }
constructor(private changeDetector: ChangeDetectorRef) {}
@@ -59,25 +63,29 @@ export class BlockListComponent implements AfterViewInit {
protected refreshBlocksVisibility = () => {
this.blocks.forEach((block, index) => {
block.nativeElement.style.display =
- index >= this.currentPage * this.pageSize &&
- index < (this.currentPage + 1) * this.pageSize
+ index >= this.currentPage_ * this.pageSize &&
+ index < (this.currentPage_ + 1) * this.pageSize
? null
: 'none'
})
}
- public goToPage(index: number) {
- this.currentPage = Math.max(Math.min(index, this.pagesCount - 1), 0)
+ // pageIndex is 1-based
+ public goToPage(pageIndex: number) {
+ this.currentPage_ = Math.max(
+ Math.min(pageIndex - 1, this.pagesCount - 1),
+ 0
+ )
this.changeDetector.detectChanges()
this.refreshBlocksVisibility()
}
- public previousPage() {
+ public goToPrevPage() {
if (this.isFirstPage) return
this.goToPage(this.currentPage - 1)
}
- public nextPage() {
+ public goToNextPage() {
if (this.isLastPage) return
this.goToPage(this.currentPage + 1)
}
diff --git a/libs/ui/layout/src/lib/carousel/carousel.component.spec.ts b/libs/ui/layout/src/lib/carousel/carousel.component.spec.ts
index 7301cb0d1..c6b7fc1f1 100644
--- a/libs/ui/layout/src/lib/carousel/carousel.component.spec.ts
+++ b/libs/ui/layout/src/lib/carousel/carousel.component.spec.ts
@@ -73,7 +73,7 @@ describe('CarouselComponent', () => {
})
describe('click on step', () => {
beforeEach(() => {
- component.scrollToStep(2)
+ component.goToPage(2)
})
it('calls #scrollTo', () => {
expect(component.emblaApi.scrollTo).toHaveBeenCalledWith(2)
@@ -88,30 +88,30 @@ describe('CarouselComponent', () => {
it('emits the current step index', () => {
const spy = jest.fn()
component.currentStepChange.subscribe(spy)
- component.scrollToStep(2)
+ component.goToPage(2)
expect(spy).toHaveBeenCalledWith(2)
expect(spy).toHaveBeenCalledTimes(1)
})
})
- describe('isFirstStep', () => {
+ describe('isFirstPage', () => {
it('returns true if the current step is the first one', () => {
- expect(component.isFirstStep).toBe(true)
+ expect(component.isFirstPage).toBe(true)
})
it('returns false if the current step is not the first one', () => {
- component.scrollToStep(2)
- expect(component.isFirstStep).toBe(false)
+ component.goToPage(2)
+ expect(component.isFirstPage).toBe(false)
})
})
- describe('isLastStep', () => {
+ describe('isLastPage', () => {
it('returns true if the current step is the last one', () => {
- component.scrollToStep(3)
- expect(component.isLastStep).toBe(true)
+ component.goToPage(3)
+ expect(component.isLastPage).toBe(true)
})
it('returns false if the current step is not the last one', () => {
- component.scrollToStep(1)
- expect(component.isLastStep).toBe(false)
+ component.goToPage(1)
+ expect(component.isLastPage).toBe(false)
})
})
})
diff --git a/libs/ui/layout/src/lib/carousel/carousel.component.ts b/libs/ui/layout/src/lib/carousel/carousel.component.ts
index abb751af2..9894ee58a 100644
--- a/libs/ui/layout/src/lib/carousel/carousel.component.ts
+++ b/libs/ui/layout/src/lib/carousel/carousel.component.ts
@@ -11,6 +11,7 @@ import {
} from '@angular/core'
import EmblaCarousel, { EmblaCarouselType } from 'embla-carousel'
import { CommonModule } from '@angular/common'
+import { Paginable } from '../paginable.interface'
@Component({
selector: 'gn-ui-carousel',
@@ -20,7 +21,7 @@ import { CommonModule } from '@angular/common'
standalone: true,
imports: [CommonModule],
})
-export class CarouselComponent implements AfterViewInit {
+export class CarouselComponent implements AfterViewInit, Paginable {
@ViewChild('carouselOverflowContainer') carouselOverflowContainer: ElementRef
@Input() containerClass = ''
@@ -38,15 +39,30 @@ export class CarouselComponent implements AfterViewInit {
this.changeDetector.detectChanges()
}
- get isFirstStep() {
+ // Paginable API
+ get isFirstPage() {
return this.currentStep === 0
}
- get isLastStep() {
+ get isLastPage() {
return this.currentStep === this.steps.length - 1
}
- get stepsCount() {
+ get currentPage() {
+ return this.currentStep + 1 // this is 1-based
+ }
+ get pagesCount() {
return this.steps.length
}
+ public goToPage(stepIndex: number) {
+ this.emblaApi.scrollTo(stepIndex - 1) // this is 0-based
+ }
+ public goToPrevPage() {
+ if (this.isFirstPage) return
+ this.emblaApi.scrollPrev()
+ }
+ public goToNextPage() {
+ if (this.isLastPage) return
+ this.emblaApi.scrollNext()
+ }
constructor(private changeDetector: ChangeDetectorRef) {}
@@ -63,18 +79,4 @@ export class CarouselComponent implements AfterViewInit {
.on('reInit', this.refreshSteps)
.on('select', this.refreshSteps)
}
-
- public scrollToStep(stepIndex: number) {
- this.emblaApi.scrollTo(stepIndex)
- }
-
- public slideToPrevious() {
- if (this.isFirstStep) return
- this.emblaApi.scrollPrev()
- }
-
- public slideToNext() {
- if (this.isLastStep) return
- this.emblaApi.scrollNext()
- }
}