Skip to content

Commit 05f9052

Browse files
Romuald Caplierjahow
Romuald Caplier
authored andcommitted
[BP] refactor(datahub): added an error message when record has no link.
backported from geonetwork/geonetwork-ui#874
1 parent 0892e6d commit 05f9052

20 files changed

+177
-67
lines changed

apps/datahub/src/app/record/record-metadata/record-metadata.component.html

+10-5
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,12 @@
130130
></datahub-record-apis>
131131
</div>
132132
</div>
133-
133+
<ng-container *ngIf="displayDatasetHasNoLinkBlock$ | async">
134+
<gn-ui-error
135+
data-test="dataset-has-no-link-block"
136+
[type]="errorTypes.DATASET_HAS_NO_LINK"
137+
></gn-ui-error>
138+
</ng-container>
134139
<div id="related-records" *ngIf="displayRelated$ | async">
135140
<div>
136141
<div class="h-48 overflow-visible">
@@ -150,14 +155,14 @@
150155
class="mt-12 p-4 max-w-[600px] m-auto text-[13px]"
151156
*ngIf="facade.error$ | async as error"
152157
>
153-
<gn-ui-search-results-error
158+
<gn-ui-error
154159
*ngIf="error.notFound"
155160
[type]="errorTypes.RECORD_NOT_FOUND"
156161
[recordId]="(facade.metadata$ | async).uniqueIdentifier"
157-
></gn-ui-search-results-error>
158-
<gn-ui-search-results-error
162+
></gn-ui-error>
163+
<gn-ui-error
159164
*ngIf="error.otherError"
160165
[type]="errorTypes.RECEIVED_ERROR"
161166
[error]="error.otherError"
162-
></gn-ui-search-results-error>
167+
></gn-ui-error>
163168
</div>

apps/datahub/src/app/record/record-metadata/record-metadata.component.spec.ts

+25-14
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,7 @@ import { By } from '@angular/platform-browser'
1010
import { SourcesService } from '@geonetwork-ui/feature/catalog'
1111
import { MapManagerService } from '@geonetwork-ui/feature/map'
1212
import { SearchService } from '@geonetwork-ui/feature/search'
13-
import {
14-
ErrorType,
15-
SearchResultsErrorComponent,
16-
} from '@geonetwork-ui/ui/elements'
13+
import { ErrorComponent, ErrorType } from '@geonetwork-ui/ui/elements'
1714
import { TranslateModule } from '@ngx-translate/core'
1815
import { BehaviorSubject, of } from 'rxjs'
1916
import { RecordMetadataComponent } from './record-metadata.component'
@@ -168,7 +165,7 @@ describe('RecordMetadataComponent', () => {
168165
MockDataOtherlinksComponent,
169166
MockDataApisComponent,
170167
MockRelatedComponent,
171-
SearchResultsErrorComponent,
168+
ErrorComponent,
172169
MockMetadataInfoComponent,
173170
MockMetadataContactComponent,
174171
MockRecordApiFormComponent,
@@ -598,9 +595,9 @@ describe('RecordMetadataComponent', () => {
598595
describe('error handling', () => {
599596
describe('normal', () => {
600597
it('does not show errors', () => {
601-
const result = fixture.debugElement.query(
602-
By.directive(SearchResultsErrorComponent)
603-
)
598+
facade.otherLinks$.next([''])
599+
fixture.detectChanges()
600+
const result = fixture.debugElement.query(By.directive(ErrorComponent))
604601
expect(result).toBeFalsy()
605602
})
606603
})
@@ -610,9 +607,7 @@ describe('RecordMetadataComponent', () => {
610607
fixture.detectChanges()
611608
})
612609
it('shows error', () => {
613-
const result = fixture.debugElement.query(
614-
By.directive(SearchResultsErrorComponent)
615-
)
610+
const result = fixture.debugElement.query(By.directive(ErrorComponent))
616611

617612
expect(result).toBeTruthy()
618613
expect(result.componentInstance.type).toBe(ErrorType.RECORD_NOT_FOUND)
@@ -628,14 +623,30 @@ describe('RecordMetadataComponent', () => {
628623
fixture.detectChanges()
629624
})
630625
it('shows error', () => {
631-
const result = fixture.debugElement.query(
632-
By.directive(SearchResultsErrorComponent)
633-
)
626+
const result = fixture.debugElement.query(By.directive(ErrorComponent))
634627

635628
expect(result).toBeTruthy()
636629
expect(result.componentInstance.type).toBe(ErrorType.RECEIVED_ERROR)
637630
expect(result.componentInstance.error).toBe('This is an Error!')
638631
})
639632
})
633+
634+
describe('When there are no link (download, api or other links)', () => {
635+
beforeEach(() => {
636+
facade.apiLinks$.next([])
637+
facade.downloadLinks$.next([])
638+
facade.otherLinks$.next([])
639+
fixture.detectChanges()
640+
})
641+
it('shows the no link error block', () => {
642+
const result = fixture.debugElement.query(
643+
By.css('[data-test="dataset-has-no-link-block"]')
644+
)
645+
expect(result).toBeTruthy()
646+
expect(result.componentInstance.type).toBe(
647+
ErrorType.DATASET_HAS_NO_LINK
648+
)
649+
})
650+
})
640651
})
641652
})

apps/datahub/src/app/record/record-metadata/record-metadata.component.ts

+11
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,17 @@ export class RecordMetadataComponent {
4949
map((records) => records?.length > 0)
5050
)
5151

52+
displayDatasetHasNoLinkBlock$ = combineLatest([
53+
this.displayDownload$,
54+
this.displayApi$,
55+
this.displayOtherLinks,
56+
]).pipe(
57+
map(
58+
([displayDownload, displayApi, displayOtherLinks]) =>
59+
!displayDownload && !displayApi && !displayOtherLinks
60+
)
61+
)
62+
5263
sourceLabel$ = this.facade.metadata$.pipe(
5364
map((record) => record?.extras?.catalogUuid as string),
5465
filter((uuid) => !!uuid),

libs/feature/search/src/lib/results-list/results-list.container.component.html

+4-4
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,16 @@
4242
</div>
4343

4444
<div class="p-4 max-w-[600px] m-auto text-[13px]">
45-
<gn-ui-search-results-error
45+
<gn-ui-error
4646
*ngIf="(errorCode$ | async) === 0"
4747
[type]="errorTypes.COULD_NOT_REACH_API"
4848
>
49-
</gn-ui-search-results-error>
50-
<gn-ui-search-results-error
49+
</gn-ui-error>
50+
<gn-ui-error
5151
*ngIf="(error$ | async) !== null && (errorCode$ | async) !== 0"
5252
[type]="errorTypes.RECEIVED_ERROR"
5353
[error]="errorMessage$ | async"
54-
></gn-ui-search-results-error>
54+
></gn-ui-error>
5555
</div>
5656

5757
<ng-template #favoriteToggle let-record>

libs/ui/elements/src/index.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ export * from './lib/metadata-info/metadata-info.component'
33
export * from './lib/metadata-contact/metadata-contact.component'
44
export * from './lib/metadata-quality/metadata-quality.component'
55
export * from './lib/metadata-quality-item/metadata-quality-item.component'
6-
export * from './lib/search-results-error/search-results-error.component'
76
export * from './lib/thumbnail/thumbnail.component'
87
export * from './lib/content-ghost/content-ghost.component'
98
export * from './lib/pagination-buttons/pagination-buttons.component'
@@ -15,7 +14,7 @@ export * from './lib/downloads-list/downloads-list.component'
1514
export * from './lib/link-card/link-card.component'
1615
export * from './lib/pagination/pagination.component'
1716
export * from './lib/related-record-card/related-record-card.component'
18-
export * from './lib/search-results-error/search-results-error.component'
17+
export * from './lib/error/error.component'
1918
export * from './lib/user-preview/user-preview.component'
2019
export * from './lib/max-lines/max-lines.component'
2120
export * from './lib/record-api-form/record-api-form.component'

libs/ui/elements/src/lib/search-results-error/search-results-error.component.html libs/ui/elements/src/lib/error/error.component.html

+18-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
<div
22
class="p-[1.7em] bg-red-50 text-red-800 text-[1.5em] text-center rounded-lg"
33
>
4-
<div *ngIf="type === types.COULD_NOT_REACH_API">
4+
<div
5+
*ngIf="type === types.COULD_NOT_REACH_API"
6+
data-test="could-not-reach-api-error"
7+
>
58
<div class="relative opacity-40">
69
<mat-icon class="material-symbols-outlined face">face</mat-icon>
710
<mat-icon class="material-symbols-outlined question-mark1"
@@ -13,14 +16,26 @@
1316
</div>
1417
<div translate>search.error.couldNotReachApi</div>
1518
</div>
16-
<div *ngIf="type === types.RECEIVED_ERROR">
19+
<div
20+
*ngIf="type === types.DATASET_HAS_NO_LINK"
21+
data-test="dataset-has-no-link-error"
22+
>
23+
<div class="relative opacity-40">
24+
<mat-icon class="material-symbols-outlined face">computer</mat-icon>
25+
</div>
26+
<div translate>search.error.recordHasnolink</div>
27+
</div>
28+
<div *ngIf="type === types.RECEIVED_ERROR" data-test="received-error-error">
1729
<div class="relative opacity-40">
1830
<mat-icon class="material-symbols-outlined face">mood_bad</mat-icon>
1931
</div>
2032
<div translate>search.error.receivedError</div>
2133
<div *ngIf="error">{{ error }}</div>
2234
</div>
23-
<div *ngIf="type === types.RECORD_NOT_FOUND">
35+
<div
36+
*ngIf="type === types.RECORD_NOT_FOUND"
37+
data-test="record-not-found-error"
38+
>
2439
<div class="relative opacity-40">
2540
<mat-icon class="material-symbols-outlined computer">computer</mat-icon>
2641
<mat-icon class="material-symbols-outlined computer-question-mark"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import { ComponentFixture, TestBed } from '@angular/core/testing'
2+
3+
import { ErrorComponent, ErrorType } from './error.component'
4+
import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'
5+
import { By } from '@angular/platform-browser'
6+
7+
describe('ErrorComponent', () => {
8+
let component: ErrorComponent
9+
let fixture: ComponentFixture<ErrorComponent>
10+
let compiled: DebugElement
11+
12+
beforeEach(async () => {
13+
await TestBed.configureTestingModule({
14+
declarations: [ErrorComponent],
15+
schemas: [NO_ERRORS_SCHEMA],
16+
}).compileComponents()
17+
})
18+
19+
beforeEach(() => {
20+
fixture = TestBed.createComponent(ErrorComponent)
21+
component = fixture.componentInstance
22+
compiled = fixture.debugElement
23+
})
24+
25+
it('should create', () => {
26+
expect(component).toBeTruthy()
27+
})
28+
29+
describe('ErrorType', () => {
30+
describe('ErrorType.COULD_NOT_REACH_API', () => {
31+
beforeEach(() => {
32+
component.type = ErrorType.COULD_NOT_REACH_API
33+
fixture.detectChanges()
34+
})
35+
36+
it('COULD_NOT_REACH_API block is displayed.', () => {
37+
const errorBlock = compiled.query(
38+
By.css('[data-test="could-not-reach-api-error"]')
39+
)
40+
expect(errorBlock).toBeTruthy()
41+
})
42+
})
43+
44+
describe('ErrorType.RECEIVED_ERROR', () => {
45+
beforeEach(() => {
46+
component.type = ErrorType.RECEIVED_ERROR
47+
fixture.detectChanges()
48+
})
49+
50+
it('RECEIVED_ERROR block is displayed.', () => {
51+
const errorBlock = compiled.query(
52+
By.css('[data-test="received-error-error"]')
53+
)
54+
expect(errorBlock).toBeTruthy()
55+
})
56+
})
57+
58+
describe('ErrorType.RECORD_NOT_FOUND', () => {
59+
beforeEach(() => {
60+
component.type = ErrorType.RECORD_NOT_FOUND
61+
fixture.detectChanges()
62+
})
63+
64+
it('RECORD_NOT_FOUND block is displayed.', () => {
65+
const errorBlock = compiled.query(
66+
By.css('[data-test="record-not-found-error"]')
67+
)
68+
expect(errorBlock).toBeTruthy()
69+
})
70+
})
71+
72+
describe('ErrorType.NO_LINK', () => {
73+
beforeEach(() => {
74+
component.type = ErrorType.DATASET_HAS_NO_LINK
75+
fixture.detectChanges()
76+
})
77+
78+
it('NO_LINK block is displayed.', () => {
79+
const errorBlock = compiled.query(
80+
By.css('[data-test="dataset-has-no-link-error"]')
81+
)
82+
expect(errorBlock).toBeTruthy()
83+
})
84+
})
85+
})
86+
})

libs/ui/elements/src/lib/search-results-error/search-results-error.component.stories.ts libs/ui/elements/src/lib/error/error.component.stories.ts

+6-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
import {
2-
ErrorType,
3-
SearchResultsErrorComponent,
4-
} from './search-results-error.component'
1+
import { ErrorComponent, ErrorType } from './error.component'
52
import {
63
applicationConfig,
74
componentWrapperDecorator,
@@ -19,8 +16,8 @@ import { importProvidersFrom } from '@angular/core'
1916
import { MatIcon } from '@angular/material/icon'
2017

2118
export default {
22-
title: 'Elements/SearchResultsErrorComponent',
23-
component: SearchResultsErrorComponent,
19+
title: 'Elements/ErrorComponent',
20+
component: ErrorComponent,
2421
decorators: [
2522
moduleMetadata({
2623
declarations: [MatIcon],
@@ -36,9 +33,9 @@ export default {
3633
(story) => `<div style="max-width: 800px">${story}</div>`
3734
),
3835
],
39-
} as Meta<SearchResultsErrorComponent>
36+
} as Meta<ErrorComponent>
4037

41-
export const Primary: StoryObj<SearchResultsErrorComponent> = {
38+
export const Primary: StoryObj<ErrorComponent> = {
4239
args: {
4340
type: ErrorType.RECEIVED_ERROR,
4441
error: 'something wrong happened',
@@ -51,6 +48,7 @@ export const Primary: StoryObj<SearchResultsErrorComponent> = {
5148
ErrorType.RECEIVED_ERROR,
5249
ErrorType.COULD_NOT_REACH_API,
5350
ErrorType.RECORD_NOT_FOUND,
51+
ErrorType.DATASET_HAS_NO_LINK,
5452
],
5553
},
5654
},

libs/ui/elements/src/lib/search-results-error/search-results-error.component.ts libs/ui/elements/src/lib/error/error.component.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@ export enum ErrorType {
44
COULD_NOT_REACH_API,
55
RECEIVED_ERROR,
66
RECORD_NOT_FOUND,
7+
DATASET_HAS_NO_LINK,
78
}
89

910
@Component({
10-
selector: 'gn-ui-search-results-error',
11-
templateUrl: './search-results-error.component.html',
12-
styleUrls: ['./search-results-error.component.css'],
11+
selector: 'gn-ui-error',
12+
templateUrl: './error.component.html',
13+
styleUrls: ['./error.component.css'],
1314
changeDetection: ChangeDetectionStrategy.OnPush,
1415
})
15-
export class SearchResultsErrorComponent {
16+
export class ErrorComponent {
1617
@Input() type!: ErrorType
1718
@Input() error?: string
1819
@Input() recordId?: string

libs/ui/elements/src/lib/search-results-error/search-results-error.component.spec.ts

-24
This file was deleted.

0 commit comments

Comments
 (0)