Skip to content

Commit a56e444

Browse files
Andrea Barbassoatarix83
authored andcommitted
Merged in DSC-1652 (pull request DSpace#1584)
[DSC-1652] add warning and error messages to loader component Approved-by: Giuseppe Digilio
2 parents 361f6ef + 0e51214 commit a56e444

11 files changed

Lines changed: 143 additions & 33 deletions
Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,28 @@
1-
<div *ngIf="!spinner">
2-
<label *ngIf="showMessage && message">{{ message }}</label>
3-
<div class="loader">
4-
<span class="l-1"></span>
5-
<span class="l-2"></span>
6-
<span class="l-3"></span>
7-
<span class="l-4"></span>
8-
<span class="l-5"></span>
9-
<span class="l-6"></span>
10-
<span class="l-7"></span>
11-
<span class="l-8"></span>
12-
<span class="l-9"></span>
13-
<span class="l-10"></span>
14-
</div>
15-
</div>
16-
<div *ngIf='spinner' class="spinner spinner-border" role="status">
17-
<span class="sr-only">{{ message }}</span>
1+
<div [ngSwitch]="messageToShow">
2+
<ng-container *ngSwitchCase="MessageType.LOADING">
3+
<label *ngIf="message">{{ message }}</label>
4+
</ng-container>
5+
<ng-container *ngSwitchCase="MessageType.WARNING">
6+
<label *ngIf="warningMessage">{{ warningMessage }}</label>
7+
</ng-container>
8+
<ng-container *ngSwitchCase="MessageType.ERROR">
9+
<ds-alert *ngIf="errorMessage" [type]="AlertTypeEnum.Error" [content]="errorMessage"></ds-alert>
10+
</ng-container>
11+
<ng-container *ngIf="!spinner && messageToShow !== MessageType.ERROR">
12+
<div class="loader">
13+
<span class="l-1"></span>
14+
<span class="l-2"></span>
15+
<span class="l-3"></span>
16+
<span class="l-4"></span>
17+
<span class="l-5"></span>
18+
<span class="l-6"></span>
19+
<span class="l-7"></span>
20+
<span class="l-8"></span>
21+
<span class="l-9"></span>
22+
<span class="l-10"></span>
23+
</div>
24+
</ng-container>
25+
<ng-container *ngIf="spinner && messageToShow !== MessageType.ERROR" class="spinner spinner-border" role="status">
26+
<span class="sr-only">{{ message }}</span>
27+
</ng-container>
1828
</div>

src/app/shared/loading/loading.component.spec.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@ describe('LoadingComponent (inline template)', () => {
3535

3636
comp = fixture.componentInstance; // LoadingComponent test instance
3737
comp.message = 'test message';
38+
comp.warningMessage = 'test warning message';
39+
comp.errorMessage = 'test error message';
40+
3841
fixture.detectChanges();
39-
// query for the message <label> by CSS element selector
40-
de = fixture.debugElement.query(By.css('label'));
41-
el = de.nativeElement;
4242
});
4343

4444
it('should create', () => {
@@ -47,13 +47,32 @@ describe('LoadingComponent (inline template)', () => {
4747

4848
it('should display default message', () => {
4949
fixture.detectChanges();
50+
de = fixture.debugElement.query(By.css('label'));
51+
el = de.nativeElement;
5052
expect(el.textContent).toContain(comp.message);
5153
});
5254

5355
it('should display input message', () => {
5456
comp.message = 'Test Message';
5557
fixture.detectChanges();
58+
de = fixture.debugElement.query(By.css('label'));
59+
el = de.nativeElement;
5660
expect(el.textContent).toContain('Test Message');
5761
});
5862

63+
it('should display warning message when MessageType WARNING is set as messageToShow', () => {
64+
comp.messageToShow = comp.MessageType.WARNING;
65+
fixture.detectChanges();
66+
de = fixture.debugElement.query(By.css('label'));
67+
el = de.nativeElement;
68+
expect(el.textContent).toContain(comp.warningMessage);
69+
});
70+
71+
it('should display ds-alert when MessageType ERROR is set as messageToShow', () => {
72+
comp.messageToShow = comp.MessageType.ERROR;
73+
fixture.detectChanges();
74+
de = fixture.debugElement.query(By.css('ds-alert'));
75+
expect(de).toBeTruthy();
76+
});
77+
5978
});
Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
1-
import { Component, Input, OnDestroy, OnInit } from '@angular/core';
1+
import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';
22

33
import { TranslateService } from '@ngx-translate/core';
44

5-
import { Subscription } from 'rxjs';
65
import { hasValue } from '../empty.util';
6+
import { environment } from '../../../environments/environment';
7+
import { AlertType } from '../alert/alert-type';
8+
9+
enum MessageType {
10+
LOADING = 'loading',
11+
WARNING = 'warning',
12+
ERROR = 'error'
13+
}
714

815
@Component({
916
selector: 'ds-loading',
@@ -15,29 +22,57 @@ export class LoadingComponent implements OnDestroy, OnInit {
1522
@Input() message: string;
1623
@Input() showMessage = true;
1724

25+
@Input() showFallbackMessages = environment.loader.showFallbackMessagesByDefault;
26+
@Input() warningMessage: string;
27+
@Input() warningMessageDelay = environment.loader.warningMessageDelay;
28+
@Input() errorMessage: string;
29+
@Input() errorMessageDelay = environment.loader.errorMessageDelay;
30+
1831
/**
1932
* Show a more compact spinner animation instead of the default one
2033
*/
2134
@Input() spinner = false;
2235

23-
private subscription: Subscription;
36+
readonly MessageType = MessageType;
37+
messageToShow: MessageType = this.showMessage ? MessageType.LOADING : undefined;
38+
39+
warningTimeout: any;
40+
errorTimeout: any;
2441

25-
constructor(private translate: TranslateService) {
42+
readonly AlertTypeEnum = AlertType;
43+
44+
constructor(private translate: TranslateService, private changeDetectorRef: ChangeDetectorRef) {
2645

2746
}
2847

2948
ngOnInit() {
30-
if (this.message === undefined) {
31-
this.subscription = this.translate.get('loading.default').subscribe((message: string) => {
32-
this.message = message;
33-
});
49+
if (this.showMessage) {
50+
this.message = this.message || this.translate.instant('loading.default');
51+
}
52+
if (this.showFallbackMessages) {
53+
this.warningMessage = this.warningMessage || this.translate.instant('loading.warning');
54+
this.errorMessage = this.errorMessage || this.translate.instant('loading.error');
55+
if (this.warningMessageDelay > 0) {
56+
this.warningTimeout = setTimeout(() => {
57+
this.messageToShow = MessageType.WARNING;
58+
this.changeDetectorRef.detectChanges();
59+
}, this.warningMessageDelay);
60+
}
61+
if (this.errorMessageDelay > 0) {
62+
this.errorTimeout = setTimeout(() => {
63+
this.messageToShow = MessageType.ERROR;
64+
this.changeDetectorRef.detectChanges();
65+
}, this.errorMessageDelay);
66+
}
3467
}
3568
}
3669

3770
ngOnDestroy() {
38-
if (hasValue(this.subscription)) {
39-
this.subscription.unsubscribe();
71+
if (hasValue(this.warningTimeout)) {
72+
clearTimeout(this.warningTimeout);
73+
}
74+
if (hasValue(this.errorTimeout)) {
75+
clearTimeout(this.errorTimeout);
4076
}
4177
}
42-
4378
}

src/app/shared/loading/themed-loading.component.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,22 @@ export class ThemedLoadingComponent extends ThemedComponent<LoadingComponent> {
1616
@Input() message: string;
1717
@Input() showMessage: boolean;
1818
@Input() spinner: boolean;
19+
@Input() showFallbackMessages: boolean;
20+
@Input() warningMessage: string;
21+
@Input() warningMessageDelay: number;
22+
@Input() errorMessage: string;
23+
@Input() errorMessageDelay: number;
1924

20-
protected inAndOutputNames: (keyof LoadingComponent & keyof this)[] = ['message', 'showMessage', 'spinner'];
25+
protected inAndOutputNames: (keyof LoadingComponent & keyof this)[] = [
26+
'message',
27+
'showMessage',
28+
'spinner',
29+
'showFallbackMessages',
30+
'warningMessage',
31+
'warningMessageDelay',
32+
'errorMessage',
33+
'errorMessageDelay'
34+
];
2135

2236
constructor(
2337
protected resolver: ComponentFactoryResolver,

src/app/shared/search/search-results/search-results.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ <h2 *ngIf="!disableHeader">{{ (configuration ? configuration + '.search.results.
2222
(selectObject)="selectObject.emit($event)">
2323
</ds-viewable-collection>
2424
</div>
25-
<ds-themed-loading *ngIf="isLoading()" message="{{'loading.search-results' | translate}}"></ds-themed-loading>
25+
<ds-themed-loading *ngIf="isLoading()" message="{{'loading.search-results' | translate}}" [showFallbackMessages]="true"></ds-themed-loading>
2626
<ds-error *ngIf="showError()"
2727
message="{{errorMessageLabel() | translate}}"></ds-error>
2828
<div *ngIf="searchResults?.payload?.page.length == 0 || searchResults?.statusCode == 400">

src/assets/i18n/en.json5

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3677,6 +3677,10 @@
36773677

36783678
"loading.default": "Loading...",
36793679

3680+
"loading.warning": "This is taking longer than expected. Please be patient.",
3681+
3682+
"loading.error": "An error occurred while loading the page. Please refresh the page and try again.",
3683+
36803684
"loading.item": "Loading item...",
36813685

36823686
"loading.items": "Loading items...",

src/assets/i18n/it.json5

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5372,6 +5372,12 @@
53725372
// "loading.default": "Loading...",
53735373
"loading.default": "Caricamento...",
53745374

5375+
// "loading.warning": "This is taking longer than expected. Please be patient.",
5376+
"loading.warning": "Il caricamento sta richiedendo più tempo del previsto. Si prega di attendere.",
5377+
5378+
// "loading.error": "An error occurred while loading the page. Please refresh the page and try again.",
5379+
"loading.error": "Si è verificato un errore durante il caricamento della pagina. Si prega di aggiornare la pagina e riprovare.",
5380+
53755381
// "loading.item": "Loading item...",
53765382
"loading.item": "Caricamento articolo...",
53775383

src/config/app-config.interface.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import { AdvancedAttachmentRenderingConfig } from './advanced-attachment-renderi
3232
import { AttachmentRenderingConfig } from './attachment-rendering.config';
3333
import { SearchResultConfig } from './search-result-config.interface';
3434
import { MiradorConfig } from './mirador-config.interfaces';
35+
import { LoaderConfig } from './loader-config.interfaces';
3536

3637
interface AppConfig extends Config {
3738
ui: UIServerConfig;
@@ -70,6 +71,7 @@ interface AppConfig extends Config {
7071
advancedAttachmentRendering: AdvancedAttachmentRenderingConfig;
7172
searchResult: SearchResultConfig;
7273
mirador: MiradorConfig;
74+
loader: LoaderConfig;
7375
}
7476

7577
/**

src/config/default-app-config.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import {
3535
import { AttachmentRenderingConfig } from './attachment-rendering.config';
3636
import { SearchResultConfig } from './search-result-config.interface';
3737
import { MiradorConfig } from './mirador-config.interfaces';
38+
import { LoaderConfig } from './loader-config.interfaces';
3839

3940
export class DefaultAppConfig implements AppConfig {
4041
production = false;
@@ -760,4 +761,10 @@ export class DefaultAppConfig implements AppConfig {
760761
mirador: MiradorConfig = {
761762
enableDownloadPlugin: true,
762763
};
764+
765+
loader: LoaderConfig = {
766+
showFallbackMessagesByDefault: false,
767+
warningMessageDelay: 5000, // 5 seconds
768+
errorMessageDelay: 15000, // 15 seconds
769+
};
763770
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { Config } from './config.interface';
2+
3+
export interface LoaderConfig extends Config {
4+
showFallbackMessagesByDefault: boolean;
5+
warningMessageDelay: number;
6+
errorMessageDelay: number;
7+
}

0 commit comments

Comments
 (0)