Skip to content

Commit e6c07da

Browse files
author
FrancescoMauto
committed
[DSC-2901] edit: updated orcid rendering component with badge
1 parent 223dce3 commit e6c07da

3 files changed

Lines changed: 115 additions & 167 deletions

File tree

src/app/cris-layout/cris-layout-matrix/cris-layout-box-container/boxes/metadata/rendering-types/orcid/orcid.component.html

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,11 @@
1010
}
1111

1212

13-
@if (hasOrcidBadge()) {
14-
<img
15-
placement="top"
16-
ngbTooltip="{{ 'orcid.badge.tooltip' | translate }}"
17-
class="orcid-icon"
18-
alt="orcid-logo"
19-
src="assets/images/orcid.logo.icon.svg"/>
20-
}
13+
<ds-orcid-badge-and-tooltip
14+
class="ms-1"
15+
[orcid]="metadataValue"
16+
[authenticatedTimestamp]="orcidAuthenticatedTimestamp">
17+
</ds-orcid-badge-and-tooltip>
2118

2219
</span>
2320
</div>
Lines changed: 101 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -1,117 +1,3 @@
1-
/*
2-
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
3-
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
4-
import { By } from '@angular/platform-browser';
5-
6-
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
7-
8-
import { OrcidComponent } from './orcid.component';
9-
import { Item } from '../../../../../../../core/shared/item.model';
10-
import { TranslateLoaderMock } from '../../../../../../../shared/mocks/translate-loader.mock';
11-
import { DsDatePipe } from '../../../../../../pipes/ds-date.pipe';
12-
import { ConfigurationDataService } from '../../../../../../../core/data/configuration-data.service';
13-
import { createSuccessfulRemoteDataObject$ } from '../../../../../../../shared/remote-data.utils';
14-
import { MetadataBoxConfiguration } from '../../../../../../../core/layout/models/box.model';
15-
16-
export const testItem: Item = Object.assign(new Item(), {
17-
id: '0ec7ff22-f211-40ab-a69e-c819b0b1f357',
18-
uuid: '0ec7ff22-f211-40ab-a69e-c819b0b1f357',
19-
type: 'item',
20-
metadata: {
21-
'person.identifier.orcid': [
22-
{
23-
language: 'en_US',
24-
value: '0000-0001-8918-3592'
25-
}
26-
],
27-
'dspace.orcid.authenticated': [
28-
{
29-
language: null,
30-
value: 'authenticated'
31-
}
32-
]
33-
}
34-
});
35-
36-
export const medataComponent: MetadataBoxConfiguration = {
37-
id: 'testTagBox',
38-
type: 'boxmetadataconfiguration',
39-
rows: [{
40-
style: 'row-style',
41-
cells: [{
42-
style: 'cell-style',
43-
fields: [
44-
{
45-
metadata: 'person.identifier.orcid',
46-
label: 'ORCID',
47-
rendering: 'orcid',
48-
fieldType: 'metadata',
49-
labelAsHeading: true,
50-
valuesInline: true
51-
}
52-
]
53-
}]
54-
}]
55-
};
56-
57-
describe('OrcidComponent', () => {
58-
let component: OrcidComponent;
59-
let fixture: ComponentFixture<OrcidComponent>;
60-
let configurationDataService;
61-
62-
beforeEach(fakeAsync(() => {
63-
64-
configurationDataService = jasmine.createSpyObj('configurationDataService', {
65-
findByPropertyName: createSuccessfulRemoteDataObject$({ values: ['https://sandbox.orcid.org'] })
66-
});
67-
68-
TestBed.configureTestingModule({
69-
imports: [TranslateModule.forRoot({
70-
loader: {
71-
provide: TranslateLoader,
72-
useClass: TranslateLoaderMock
73-
}
74-
}), BrowserAnimationsModule],
75-
declarations: [ OrcidComponent, DsDatePipe ],
76-
providers: [ { provide: ConfigurationDataService, useValue: configurationDataService}]
77-
})
78-
.compileComponents();
79-
}));
80-
81-
beforeEach(() => {
82-
fixture = TestBed.createComponent(OrcidComponent);
83-
component = fixture.componentInstance;
84-
component.item = testItem;
85-
component.field = medataComponent.rows[0].fields[0];
86-
component.ngOnInit();
87-
fixture.detectChanges();
88-
});
89-
90-
it('check metadata rendering', fakeAsync(() => {
91-
tick();
92-
fixture.detectChanges();
93-
fixture.whenStable().then(() => {
94-
const spanValueFound = fixture.debugElement.queryAll(By.css('span.txt-value'));
95-
expect(spanValueFound.length).toBe(1);
96-
expect(spanValueFound[0].nativeElement.textContent).toContain('0000-0001-8918-3592');
97-
98-
const orcidLinkFound = fixture.debugElement.queryAll(By.css('a'));
99-
expect(orcidLinkFound.length).toBe(1);
100-
expect(orcidLinkFound[0].nativeElement.href).toBe('https://sandbox.orcid.org/0000-0001-8918-3592');
101-
102-
const orcidIconFound = fixture.debugElement.queryAll(By.css('.orcid-icon'));
103-
expect(orcidIconFound.length).toBe(1);
104-
expect(orcidIconFound[0].nativeElement.src).toContain('assets/images/orcid.logo.icon.svg');
105-
106-
const spanLabelFound = fixture.debugElement.query(By.css('div.' + medataComponent.rows[0].fields[0].style));
107-
const label: HTMLElement = spanLabelFound.nativeElement;
108-
expect(label.textContent).toContain(medataComponent.rows[0].fields[0].label);
109-
});
110-
111-
}));
112-
});
113-
*/
114-
1151
import {
1162
ComponentFixture,
1173
fakeAsync,
@@ -131,6 +17,7 @@ import { LayoutField } from '../../../../../../../core/layout/models/box.model';
13117
import { Item } from '../../../../../../../core/shared/item.model';
13218
import { MetadataValue } from '../../../../../../../core/shared/metadata.models';
13319
import { TranslateLoaderMock } from '../../../../../../../shared/mocks/translate-loader.mock';
20+
import { OrcidBadgeAndTooltipComponent } from '../../../../../../../shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component';
13421
import { createSuccessfulRemoteDataObject$ } from '../../../../../../../shared/remote-data.utils';
13522
import { DsDatePipe } from '../../../../../../pipes/ds-date.pipe';
13623
import { FieldRenderingType } from '../field-rendering-type';
@@ -152,21 +39,13 @@ describe('OrcidComponent', () => {
15239
'place': 0,
15340
});
15441

155-
const testItem = Object.assign(new Item(),
156-
{
157-
type: 'item',
158-
metadata: {
159-
'person.identifier.orcid': [metadataValue],
160-
'dspace.orcid.authenticated': [
161-
{
162-
language: null,
163-
value: 'authenticated',
164-
},
165-
],
166-
},
167-
uuid: 'test-item-uuid',
168-
},
169-
);
42+
const authenticatedTimestamp = Object.assign(new MetadataValue(), {
43+
'value': '2026-01-26T15:20:27.524758999',
44+
'language': null,
45+
'authority': null,
46+
'confidence': -1,
47+
'place': 0,
48+
});
17049

17150
const mockField: LayoutField = {
17251
'metadata': 'person.identifier.orcid',
@@ -180,7 +59,27 @@ describe('OrcidComponent', () => {
18059
'valuesInline': true,
18160
};
18261

183-
beforeEach(waitForAsync(() => {
62+
/**
63+
* Build a Person item optionally containing the `dspace.orcid.authenticated` metadata.
64+
*/
65+
function buildItem(authenticated: boolean): Item {
66+
const metadata: { [key: string]: MetadataValue[] } = {
67+
'person.identifier.orcid': [metadataValue],
68+
};
69+
if (authenticated) {
70+
metadata['dspace.orcid.authenticated'] = [authenticatedTimestamp];
71+
}
72+
return Object.assign(new Item(), {
73+
type: 'item',
74+
metadata,
75+
uuid: 'test-item-uuid',
76+
});
77+
}
78+
79+
/**
80+
* Configure the TestBed and create the component with the given item.
81+
*/
82+
function setup(item: Item): void {
18483
TestBed.configureTestingModule({
18584
imports: [TranslateModule.forRoot({
18685
loader: {
@@ -190,49 +89,94 @@ describe('OrcidComponent', () => {
19089
}), BrowserAnimationsModule, OrcidComponent, DsDatePipe],
19190
providers: [
19291
{ provide: 'fieldProvider', useValue: mockField },
193-
{ provide: 'itemProvider', useValue: testItem },
92+
{ provide: 'itemProvider', useValue: item },
19493
{ provide: 'metadataValueProvider', useValue: metadataValue },
19594
{ provide: 'renderingSubTypeProvider', useValue: '' },
19695
{ provide: 'tabNameProvider', useValue: '' },
19796
{ provide: ConfigurationDataService, useValue: configurationDataService },
19897
],
199-
})
200-
.compileComponents();
201-
}));
98+
}).compileComponents();
20299

203-
beforeEach(() => {
204100
fixture = TestBed.createComponent(OrcidComponent);
205101
component = fixture.componentInstance;
206102
fixture.detectChanges();
207-
});
103+
}
208104

209-
it('should create', () => {
210-
expect(component).toBeTruthy();
211-
});
105+
describe('when the ORCID is authenticated', () => {
106+
beforeEach(waitForAsync(() => {
107+
setup(buildItem(true));
108+
}));
212109

213-
it('check metadata rendering', fakeAsync(() => {
214-
tick();
215-
fixture.detectChanges();
216-
fixture.whenStable().then(() => {
217-
const spanValueFound = fixture.debugElement.queryAll(By.css('span.txt-value'));
110+
it('should create', () => {
111+
expect(component).toBeTruthy();
112+
});
113+
114+
it('check metadata rendering', fakeAsync(() => {
115+
tick();
116+
fixture.detectChanges();
117+
fixture.whenStable().then(() => {
118+
const spanValueFound = fixture.debugElement.queryAll(By.css('span.txt-value'));
119+
expect(spanValueFound.length).toBe(1);
120+
expect(spanValueFound[0].nativeElement.textContent).toContain('0000-0001-8918-3592');
121+
122+
const orcidLinkFound = fixture.debugElement.queryAll(By.css('a'));
123+
expect(orcidLinkFound.length).toBe(1);
124+
expect(orcidLinkFound[0].nativeElement.href).toBe('https://sandbox.orcid.org/0000-0001-8918-3592');
125+
126+
const orcidIconFound = fixture.debugElement.queryAll(By.css('.orcid-icon'));
127+
expect(orcidIconFound.length).toBe(1);
128+
expect(orcidIconFound[0].nativeElement.src).toContain('assets/images/orcid.logo.icon.svg');
129+
});
130+
}));
131+
132+
it('check value style', (done) => {
133+
const spanValueFound = fixture.debugElement.queryAll(By.css('.test-style-value'));
218134
expect(spanValueFound.length).toBe(1);
219-
expect(spanValueFound[0].nativeElement.textContent).toContain('0000-0001-8918-3592');
135+
done();
136+
});
137+
138+
it('should render the ds-orcid-badge-and-tooltip component with the correct inputs', () => {
139+
const badge = fixture.debugElement.query(By.directive(OrcidBadgeAndTooltipComponent));
140+
expect(badge).toBeTruthy();
141+
const badgeInstance = badge.componentInstance as OrcidBadgeAndTooltipComponent;
142+
expect(badgeInstance.orcid).toBe(metadataValue);
143+
expect(badgeInstance.authenticatedTimestamp).toBe(authenticatedTimestamp);
144+
});
145+
146+
it('should expose the authenticated timestamp through orcidAuthenticatedTimestamp', () => {
147+
expect(component.orcidAuthenticatedTimestamp).toBe(authenticatedTimestamp);
148+
expect(component.hasOrcidBadge()).toBeTrue();
149+
});
220150

221-
const orcidLinkFound = fixture.debugElement.queryAll(By.css('a'));
222-
expect(orcidLinkFound.length).toBe(1);
223-
expect(orcidLinkFound[0].nativeElement.href).toBe('https://sandbox.orcid.org/0000-0001-8918-3592');
151+
it('should render the badge icon in full color (not greyed out)', () => {
152+
const orcidIcon = fixture.debugElement.query(By.css('.orcid-icon'));
153+
expect(orcidIcon).toBeTruthy();
154+
expect(orcidIcon.nativeElement.classList).not.toContain('not-authenticated');
155+
});
156+
});
224157

225-
const orcidIconFound = fixture.debugElement.queryAll(By.css('.orcid-icon'));
226-
expect(orcidIconFound.length).toBe(1);
227-
expect(orcidIconFound[0].nativeElement.src).toContain('assets/images/orcid.logo.icon.svg');
158+
describe('when the ORCID is not authenticated', () => {
159+
beforeEach(waitForAsync(() => {
160+
setup(buildItem(false));
161+
}));
162+
163+
it('should still render the badge, without an authenticated timestamp', () => {
164+
const badge = fixture.debugElement.query(By.directive(OrcidBadgeAndTooltipComponent));
165+
expect(badge).toBeTruthy();
166+
const badgeInstance = badge.componentInstance as OrcidBadgeAndTooltipComponent;
167+
expect(badgeInstance.orcid).toBe(metadataValue);
168+
expect(badgeInstance.authenticatedTimestamp).toBeUndefined();
228169
});
229170

230-
}));
171+
it('should not expose an authenticated timestamp', () => {
172+
expect(component.orcidAuthenticatedTimestamp).toBeUndefined();
173+
expect(component.hasOrcidBadge()).toBeFalse();
174+
});
231175

232-
it('check value style', (done) => {
233-
const spanValueFound = fixture.debugElement.queryAll(By.css('.test-style-value'));
234-
expect(spanValueFound.length).toBe(1);
235-
done();
176+
it('should render the badge icon greyed out (not-authenticated) but still visible', () => {
177+
const orcidIcon = fixture.debugElement.query(By.css('.orcid-icon'));
178+
expect(orcidIcon).toBeTruthy();
179+
expect(orcidIcon.nativeElement.classList).toContain('not-authenticated');
180+
});
236181
});
237182
});
238-

src/app/cris-layout/cris-layout-matrix/cris-layout-box-container/boxes/metadata/rendering-types/orcid/orcid.component.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import {
44
Inject,
55
OnInit,
66
} from '@angular/core';
7-
import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap';
87
import {
98
TranslateModule,
109
TranslateService,
@@ -18,6 +17,7 @@ import { ConfigurationProperty } from '../../../../../../../core/shared/configur
1817
import { Item } from '../../../../../../../core/shared/item.model';
1918
import { MetadataValue } from '../../../../../../../core/shared/metadata.models';
2019
import { getFirstSucceededRemoteDataPayload } from '../../../../../../../core/shared/operators';
20+
import { OrcidBadgeAndTooltipComponent } from '../../../../../../../shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component';
2121
import { RenderingTypeValueModelComponent } from '../rendering-type-value.model';
2222

2323
/**
@@ -30,7 +30,7 @@ import { RenderingTypeValueModelComponent } from '../rendering-type-value.model'
3030
styleUrls: ['./orcid.component.scss'],
3131
imports: [
3232
AsyncPipe,
33-
NgbTooltipModule,
33+
OrcidBadgeAndTooltipComponent,
3434
TranslateModule,
3535
],
3636
})
@@ -65,4 +65,11 @@ export class OrcidComponent extends RenderingTypeValueModelComponent implements
6565
return this.item.hasMetadata('dspace.orcid.authenticated');
6666
}
6767

68+
/**
69+
* The metadata value holding the timestamp of when the ORCID was authenticated, if any.
70+
*/
71+
public get orcidAuthenticatedTimestamp(): MetadataValue {
72+
return this.item.firstMetadata('dspace.orcid.authenticated');
73+
}
74+
6875
}

0 commit comments

Comments
 (0)