From 721e0e57a1334ca2596a78f667cbf3189240e1f6 Mon Sep 17 00:00:00 2001 From: Olivia Guyot Date: Fri, 8 Sep 2023 11:05:29 +0200 Subject: [PATCH] feat(editor): rework sorting of records table --- .../app/records/records-list.component.html | 2 + .../src/app/records/records-list.component.ts | 5 + .../record-table/record-table.component.html | 95 +++++++++++++++---- .../record-table.component.spec.ts | 38 ++++++++ .../record-table/record-table.component.ts | 41 +++++++- libs/ui/search/src/lib/ui-search.module.ts | 2 + 6 files changed, 159 insertions(+), 24 deletions(-) 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 71204476fc..01198dccb5 100644 --- a/apps/metadata-editor/src/app/records/records-list.component.html +++ b/apps/metadata-editor/src/app/records/records-list.component.html @@ -10,6 +10,8 @@

{{ title }}

[records]="results" [totalHits]="searchFacade.resultsHits$ | async" (recordSelect)="editRecord($event)" + (sortByChange)="setSortBy($event)" + [sortBy]="searchFacade.sortBy$ | async" >
-
+ }" + > results.records.hits.displayedOn
-
+ +
-
- record.metadata.title - +
+ + record.metadata.title + + + expand_more + + expand_less +
record.metadata.formats
-
- record.metadata.author - +
+ + record.metadata.author + + expand_more + + expand_less +
-
- record.metadata.completion - +
+ + record.metadata.completion + + expand_more + + expand_less +
-
- record.metadata.createdOn +
+ + record.metadata.createdOn + + expand_more + + expand_less +
-
+
{{ record.title }}
{{ getStatus(record.extras?.isPublishedToAll) - }} + }}
person @@ -53,4 +106,4 @@
-
\ No newline at end of file +
diff --git a/libs/ui/search/src/lib/record-table/record-table.component.spec.ts b/libs/ui/search/src/lib/record-table/record-table.component.spec.ts index f1db185839..ddc11d1ae6 100644 --- a/libs/ui/search/src/lib/record-table/record-table.component.spec.ts +++ b/libs/ui/search/src/lib/record-table/record-table.component.spec.ts @@ -1,6 +1,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing' import { RecordTableComponent } from './record-table.component' +import { SortByField } from '@geonetwork-ui/common/domain/search' describe('RecordTableComponent', () => { let component: RecordTableComponent @@ -19,4 +20,41 @@ describe('RecordTableComponent', () => { it('should create', () => { expect(component).toBeTruthy() }) + + describe('sorting', () => { + describe('#setSortBy', () => { + let newSortBy: SortByField + beforeEach(() => { + newSortBy = null + component.sortByChange.subscribe((v) => (newSortBy = v)) + }) + it('initially sorts by ascending order', () => { + component.setSortBy('title') + expect(newSortBy).toEqual(['asc', 'title']) + }) + it('changes the order if already sorted', () => { + component.sortBy = ['asc', 'title'] + component.setSortBy('title') + expect(newSortBy).toEqual(['desc', 'title']) + }) + }) + describe('#isSortedBy', () => { + it('returns false if not sorted by this column', () => { + component.sortBy = ['desc', 'owner'] + expect(component.isSortedBy('title', 'desc')).toBe(false) + }) + it('returns true if the current sortBy is for this column', () => { + component.sortBy = ['desc', 'title'] + expect(component.isSortedBy('title', 'desc')).toBe(true) + }) + it('returns true if the current sortBy is for this column (multiple sorts)', () => { + component.sortBy = [ + ['asc', 'score'], + ['desc', 'title'], + ] + expect(component.isSortedBy('title', 'desc')).toBe(true) + expect(component.isSortedBy('title', 'asc')).toBe(false) + }) + }) + }) }) diff --git a/libs/ui/search/src/lib/record-table/record-table.component.ts b/libs/ui/search/src/lib/record-table/record-table.component.ts index 9a9a2a24ed..bf8bccc045 100644 --- a/libs/ui/search/src/lib/record-table/record-table.component.ts +++ b/libs/ui/search/src/lib/record-table/record-table.component.ts @@ -1,6 +1,6 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core' -import { DATASET_RECORDS } from '@geonetwork-ui/common/fixtures' import { CatalogRecord } from '@geonetwork-ui/common/domain/record' +import { SortByField } from '@geonetwork-ui/common/domain/search' @Component({ selector: 'gn-ui-record-table', @@ -8,10 +8,11 @@ import { CatalogRecord } from '@geonetwork-ui/common/domain/record' styleUrls: ['./record-table.component.css'], }) export class RecordTableComponent { - @Input() records: CatalogRecord[] = DATASET_RECORDS + @Input() records: CatalogRecord[] = [] @Input() totalHits?: number + @Input() sortBy?: SortByField @Output() recordSelect = new EventEmitter() - activeSortElement: string | null = null + @Output() sortByChange = new EventEmitter() dateToString(date: Date): string { return date?.toLocaleDateString(undefined, { @@ -33,4 +34,38 @@ export class RecordTableComponent { } return undefined } + + // single sort: ['asc', 'owner'] + // multiple sort: [['asc', 'owner'], ['desc', title]] + private getOrderForColumn(col: string): 'asc' | 'desc' | null { + if (!this.sortBy) { + return null + } + let order: 'asc' | 'desc' | null = null + const sortedArray = Array.isArray(this.sortBy[0]) + ? this.sortBy + : [this.sortBy] + sortedArray.forEach((sortedCol) => { + if (sortedCol[1] === col) { + order = sortedCol[0] + } + }) + return order + } + + setSortBy(col: string): void { + const sortOrder = this.getOrderForColumn(col) + let newOrder + if (sortOrder) { + newOrder = sortOrder === 'asc' ? 'desc' : 'asc' + } else { + newOrder = 'asc' + } + this.sortByChange.emit([newOrder, col]) + } + + isSortedBy(col: string, order: 'asc' | 'desc'): boolean { + const sortOrder = this.getOrderForColumn(col) + return sortOrder === order + } } diff --git a/libs/ui/search/src/lib/ui-search.module.ts b/libs/ui/search/src/lib/ui-search.module.ts index 39bff79431..4f0fecd261 100644 --- a/libs/ui/search/src/lib/ui-search.module.ts +++ b/libs/ui/search/src/lib/ui-search.module.ts @@ -26,6 +26,7 @@ import { UiElementsModule } from '@geonetwork-ui/ui/elements' import { RecordPreviewFeedComponent } from './record-preview-feed/record-preview-feed.component' import { RecordTableComponent } from './record-table/record-table.component' import { CommonModule } from '@angular/common' +import { UiInputsModule } from '@geonetwork-ui/ui/inputs' @NgModule({ declarations: [ @@ -52,6 +53,7 @@ import { CommonModule } from '@angular/common' TagInputModule, UtilSharedModule, UiWidgetsModule, + UiInputsModule, UiElementsModule, MatIconModule, RouterLink,