Skip to content

Commit 1792515

Browse files
alisaismailatiFrancescoMolinaro
authored andcommitted
Merged in task/dspace-cris-2023_02_x/DSC-1708 (pull request DSpace#1736)
Task/dspace cris 2023 02 x/DSC-1708 Approved-by: Francesco Molinaro
2 parents 9754c00 + a880668 commit 1792515

23 files changed

Lines changed: 753 additions & 53 deletions
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<div class="thumbnail" [class.limit-width]="limitWidth" *ngVar="(isLoading$ | async) as isLoading">
2+
<div *ngIf="isLoading" class="thumbnail-content outer">
3+
<div class="inner">
4+
<div class="centered">
5+
<ds-themed-loading [spinner]="true"></ds-themed-loading>
6+
</div>
7+
</div>
8+
</div>
9+
<ng-container *ngVar="(src$ | async) as src">
10+
<!-- don't use *ngIf="!isLoading" so the thumbnail can load in while the animation is playing -->
11+
<img *ngIf="src !== null" class="thumbnail-content img-fluid" [ngClass]="{'d-none': isLoading}"
12+
[src]="src | dsSafeUrl" [alt]="alt | translate" (error)="errorHandler()" (load)="successHandler()">
13+
<div *ngIf="src === null && !isLoading" class="thumbnail-content outer" #thumbnailBox>
14+
<img [src]="fallbackImage" [alt]="placeholder | translate">
15+
</div>
16+
</ng-container>
17+
</div>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
:host{
2+
img {
3+
height: 80px;
4+
width: 80px;
5+
border: 1px solid #ccc;
6+
border-radius: 50%;
7+
object-fit: cover;
8+
}
9+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/* tslint:disable:no-unused-variable */
2+
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
3+
4+
import { MetadataLinkViewAvatarPopoverComponent } from './metadata-link-view-avatar-popover.component';
5+
import { of as observableOf } from 'rxjs';
6+
import { AuthService } from '../../../core/auth/auth.service';
7+
import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service';
8+
import { FileService } from '../../../core/shared/file.service';
9+
10+
describe('MetadataLinkViewAvatarPopoverComponent', () => {
11+
let component: MetadataLinkViewAvatarPopoverComponent;
12+
let fixture: ComponentFixture<MetadataLinkViewAvatarPopoverComponent>;
13+
let authService;
14+
let authorizationService;
15+
let fileService;
16+
17+
beforeEach(async(() => {
18+
authService = jasmine.createSpyObj('AuthService', {
19+
isAuthenticated: observableOf(true),
20+
});
21+
authorizationService = jasmine.createSpyObj('AuthorizationService', {
22+
isAuthorized: observableOf(true),
23+
});
24+
fileService = jasmine.createSpyObj('FileService', {
25+
retrieveFileDownloadLink: null
26+
});
27+
TestBed.configureTestingModule({
28+
declarations: [ MetadataLinkViewAvatarPopoverComponent ],
29+
providers: [
30+
{ provide: AuthService, useValue: authService },
31+
{ provide: AuthorizationDataService, useValue: authorizationService },
32+
{ provide: FileService, useValue: fileService }
33+
]
34+
})
35+
.compileComponents();
36+
}));
37+
38+
beforeEach(() => {
39+
fixture = TestBed.createComponent(MetadataLinkViewAvatarPopoverComponent);
40+
component = fixture.componentInstance;
41+
fixture.detectChanges();
42+
});
43+
44+
it('should create', () => {
45+
expect(component).toBeTruthy();
46+
});
47+
});
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Component } from '@angular/core';
2+
import { ThumbnailComponent } from 'src/app/thumbnail/thumbnail.component';
3+
4+
@Component({
5+
selector: 'ds-metadata-link-view-avatar-popover',
6+
templateUrl: './metadata-link-view-avatar-popover.component.html',
7+
styleUrls: ['./metadata-link-view-avatar-popover.component.scss']
8+
})
9+
export class MetadataLinkViewAvatarPopoverComponent extends ThumbnailComponent {
10+
11+
/**
12+
* The fallback image to use when the thumbnail is not available
13+
*/
14+
fallbackImage = 'assets/images/person-placeholder.svg';
15+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<span class="d-flex align-items-center txt-value">
2+
<a *ngIf="(orcidUrl$ | async); else noOrcidUrl" href="{{(orcidUrl$ | async)}}/{{metadataValue}}" target="_blank">
3+
{{ metadataValue }}
4+
</a>
5+
6+
<ng-template #noOrcidUrl>{{ metadataValue }}</ng-template>
7+
8+
<img *ngIf="hasOrcidBadge()"
9+
placement="top"
10+
ngbTooltip="{{ 'orcid.badge.tooltip' | translate }}"
11+
class="orcid-icon"
12+
alt="orcid-logo"
13+
src="assets/images/orcid.logo.icon.svg"/>
14+
15+
</span>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.orcid-icon {
2+
height: 1.2rem;
3+
padding-left: 0.3rem;
4+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { ConfigurationDataService } from './../../../core/data/configuration-data.service';
2+
import { Item } from 'src/app/core/shared/item.model';
3+
import { TranslateLoaderMock } from './../../testing/translate-loader.mock';
4+
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
5+
import { ComponentFixture, TestBed } from '@angular/core/testing';
6+
7+
import { MetadataLinkViewOrcidComponent } from './metadata-link-view-orcid.component';
8+
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
9+
import { MetadataValue } from 'src/app/core/shared/metadata.models';
10+
import { createSuccessfulRemoteDataObject$ } from '../../remote-data.utils';
11+
12+
describe('MetadataLinkViewOrcidComponent', () => {
13+
let component: MetadataLinkViewOrcidComponent;
14+
let fixture: ComponentFixture<MetadataLinkViewOrcidComponent>;
15+
16+
const configurationDataService = jasmine.createSpyObj('configurationDataService', {
17+
findByPropertyName: createSuccessfulRemoteDataObject$({ values: ['https://sandbox.orcid.org'] })
18+
});
19+
20+
21+
const metadataValue = Object.assign(new MetadataValue(), {
22+
'value': '0000-0001-8918-3592',
23+
'language': 'en_US',
24+
'authority': null,
25+
'confidence': -1,
26+
'place': 0
27+
});
28+
29+
const testItem = Object.assign(new Item(),
30+
{
31+
type: 'item',
32+
metadata: {
33+
'person.identifier.orcid': [metadataValue],
34+
'dspace.orcid.authenticated': [
35+
{
36+
language: null,
37+
value: 'authenticated'
38+
}
39+
]
40+
},
41+
uuid: 'test-item-uuid',
42+
}
43+
);
44+
45+
beforeEach(async () => {
46+
await TestBed.configureTestingModule({
47+
declarations: [ MetadataLinkViewOrcidComponent ],
48+
imports: [TranslateModule.forRoot({
49+
loader: {
50+
provide: TranslateLoader,
51+
useClass: TranslateLoaderMock
52+
}
53+
}), BrowserAnimationsModule],
54+
providers: [
55+
{ provide: ConfigurationDataService, useValue: configurationDataService}
56+
],
57+
})
58+
.compileComponents();
59+
60+
fixture = TestBed.createComponent(MetadataLinkViewOrcidComponent);
61+
component = fixture.componentInstance;
62+
component.itemValue = testItem;
63+
fixture.detectChanges();
64+
});
65+
66+
it('should create', () => {
67+
expect(component).toBeTruthy();
68+
});
69+
});
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { ConfigurationProperty } from './../../../core/shared/configuration-property.model';
2+
import { getFirstSucceededRemoteDataPayload } from './../../../core/shared/operators';
3+
import { ConfigurationDataService } from './../../../core/data/configuration-data.service';
4+
import { Component, Input, OnInit } from '@angular/core';
5+
import { Item } from '../../../core/shared/item.model';
6+
import { Observable, map } from 'rxjs';
7+
8+
@Component({
9+
selector: 'ds-metadata-link-view-orcid',
10+
templateUrl: './metadata-link-view-orcid.component.html',
11+
styleUrls: ['./metadata-link-view-orcid.component.scss'],
12+
})
13+
export class MetadataLinkViewOrcidComponent implements OnInit {
14+
/**
15+
* Item value to display the metadata for
16+
*/
17+
@Input() itemValue: Item;
18+
19+
metadataValue: string;
20+
21+
orcidUrl$: Observable<string>;
22+
23+
constructor(protected configurationService: ConfigurationDataService) {}
24+
25+
ngOnInit(): void {
26+
this.orcidUrl$ = this.configurationService
27+
.findByPropertyName('orcid.domain-url')
28+
.pipe(
29+
getFirstSucceededRemoteDataPayload(),
30+
map((property: ConfigurationProperty) =>
31+
property?.values?.length > 0 ? property.values[0] : null
32+
)
33+
);
34+
this.metadataValue = this.itemValue.firstMetadataValue(
35+
'person.identifier.orcid'
36+
);
37+
}
38+
39+
public hasOrcid(): boolean {
40+
return this.itemValue.hasMetadata('person.identifier.orcid');
41+
}
42+
43+
public hasOrcidBadge(): boolean {
44+
return this.itemValue.hasMetadata('dspace.orcid.authenticated');
45+
}
46+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<div class="view-container">
2+
3+
<div class="d-flex flex-row align-items-center gap-4 mb-2">
4+
<ds-metadata-link-view-avatar-popover
5+
*ngIf="item.thumbnail | async"
6+
[thumbnail]="item.thumbnail | async"
7+
></ds-metadata-link-view-avatar-popover>
8+
<span class="font-weight-bold h4"> {{item.firstMetadataValue('dc.title')}} </span>
9+
</div>
10+
11+
<ng-container *ngFor="let metadata of entityMetdataFields">
12+
<div class="row" *ngIf="item.hasMetadata(metadata)">
13+
<div class="col-4">
14+
<span class="font-weight-bold">{{ "metadata-link-view.popover.label." + (isOtherEntityType ? "other" : item.entityType) + "." + metadata | translate }}</span>
15+
</div>
16+
<div class="col-8">
17+
<span class="ellipsis-y-3" *ngIf="longTextMetadataList.includes(metadata)">
18+
{{ item.firstMetadataValue(metadata) }}
19+
</span>
20+
<a [href]="item.firstMetadataValue(metadata)" target="_blank" *ngIf="isLink(item.firstMetadataValue(metadata)) && !getSourceSubTypeIdentifier(metadata)">
21+
{{ item.firstMetadataValue(metadata) }}
22+
</a>
23+
24+
<div *ngIf="getSourceSubTypeIdentifier(metadata)" class="d-flex align-items-center">
25+
<ng-container *ngVar="item.firstMetadataValue(metadata) as rorValue">
26+
<a *ngIf="isLink(rorValue)" [href]="item.firstMetadataValue(metadata)" target="_blank" >
27+
{{ item.firstMetadataValue(metadata) }}
28+
</a>
29+
<a *ngIf="!isLink(rorValue)" [href]="getSourceSubTypeIdentifier(metadata)?.link + '/' + item.firstMetadataValue(metadata)" target="_blank" >
30+
{{ item.firstMetadataValue(metadata) }}
31+
</a>
32+
</ng-container>
33+
<img
34+
placement="top"
35+
[ngbTooltip]="getSourceSubTypeIdentifier(metadata)?.link"
36+
class="source-icon"
37+
alt="source-logo"
38+
[src]="getSourceSubTypeIdentifier(metadata)?.icon"
39+
data-test="sourceIcon"
40+
/>
41+
</div>
42+
43+
<div class="d-flex" *ngIf="!isLink(item.firstMetadataValue(metadata)) && !longTextMetadataList.includes(metadata)">
44+
<ds-metadata-link-view-orcid [itemValue]="item" *ngIf="metadata === 'person.identifier.orcid'; else textType"></ds-metadata-link-view-orcid>
45+
<ng-template #textType>
46+
<span>{{ item.firstMetadataValue(metadata) }}</span>
47+
</ng-template>
48+
</div>
49+
</div>
50+
</div>
51+
</ng-container>
52+
53+
<div class="d-flex">
54+
<a
55+
class="font-weight-bold"
56+
[routerLink]="[getItemPageRoute()]"
57+
data-test="more-info-link"
58+
>
59+
{{ "metadata-link-view.popover.label.more-info" | translate }}
60+
</a>
61+
</div>
62+
</div>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.source-icon {
2+
height: var(--ds-identifier-sybetype-icon-height);
3+
min-height: 16px;
4+
width: auto;
5+
padding-left: 0.3rem;
6+
}

0 commit comments

Comments
 (0)