Skip to content

Commit 1d954b4

Browse files
UFAL/Upgrade the refbox component - the content is fetched from the BE (#930)
* Fetch the refbox content from the BE * Show an error that the refbox content wasn't properly fetched when some error * Sanitize the code from the BE. Show errors and proper messages when something has failed * Load item name in on init * Secure the refbox content using SafeHtml * Make refbox variable name consistent * Refactor fetching refbox string from the SafeHtml
1 parent 6e5473c commit 1d954b4

File tree

2 files changed

+45
-158
lines changed

2 files changed

+45
-158
lines changed

src/app/item-page/clarin-ref-citation/clarin-ref-citation.component.html

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,7 @@
1111
</div>
1212
</div>
1313
<div class="pt-2 clarin-ref-box-body d-flex justify-content-between pl-2" >
14-
<div class="clarin-ref-box-text pr-4">
15-
<span>{{citationText + ', '}}</span>
16-
<span><i>{{itemNameText + ', '}}</i></span>
17-
<span>{{repositoryNameText + ', '}}</span>
18-
<span><a [href]="identifierURI">{{prettifiedIdentifier | async}}</a></span>
14+
<div class="clarin-ref-box-text pr-4" [innerHTML]="refboxContent | async">
1915
</div>
2016
<div class="clarin-ref-box-copy-wrapper" placement="bottom" [ngbTooltip]="'Copied!'" #tooltip="ngbTooltip"
2117
(click)="copyText()">

src/app/item-page/clarin-ref-citation/clarin-ref-citation.component.ts

Lines changed: 44 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { Component, Input, OnInit, ViewChild } from '@angular/core';
22
import { Item } from '../../core/shared/item.model';
33
import { ConfigurationDataService } from '../../core/data/configuration-data.service';
4-
import { isEmpty, isNotEmpty, isNull, isUndefined } from '../../shared/empty.util';
54
import { getFirstSucceededRemoteData } from '../../core/shared/operators';
65
import { Clipboard } from '@angular/cdk/clipboard';
76
import { NgbModal, NgbTooltip, NgbTooltipConfig } from '@ng-bootstrap/ng-bootstrap';
@@ -11,16 +10,8 @@ import { RequestService } from '../../core/data/request.service';
1110
import { RemoteDataBuildService } from '../../core/cache/builders/remote-data-build.service';
1211
import { HALEndpointService } from '../../core/shared/hal-endpoint.service';
1312
import { BehaviorSubject } from 'rxjs';
14-
import {
15-
DOI_METADATA_FIELD, HANDLE_METADATA_FIELD,
16-
} from '../simple/field-components/clarin-generic-item-field/clarin-generic-item-field.component';
17-
import { ItemIdentifierService } from '../../shared/item-identifier.service';
18-
import { AUTHOR_METADATA_FIELDS } from '../../core/shared/clarin/constants';
13+
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
1914

20-
/**
21-
* If the item has more authors do not add all authors to the citation but add there a shortcut.
22-
*/
23-
export const ET_AL_TEXT = 'et al.';
2415

2516
/**
2617
* The citation part in the ref-box component.
@@ -44,38 +35,26 @@ export class ClarinRefCitationComponent implements OnInit {
4435
*/
4536
@ViewChild('tooltip', {static: false}) tooltipRef: NgbTooltip;
4637

47-
/**
48-
* The parameters retrieved from the Item metadata for creating the citation in the proper way.
49-
*/
50-
/**
51-
* Author and issued year
52-
*/
53-
citationText: string;
54-
/**
55-
* Whole Handle URI
56-
*/
57-
identifierURI: string;
5838
/**
5939
* Name of the Item
6040
*/
6141
itemNameText: string;
42+
6243
/**
63-
* The nam of the organization which provides the repository
64-
*/
65-
repositoryNameText: string;
66-
/**
67-
* BehaviorSubject to store the prettified identifier.
44+
* The content of the reference box, which will be displayed in the tooltip.
45+
* This content is fetched from the RefBox Controller.
6846
*/
69-
prettifiedIdentifier: BehaviorSubject<string> = new BehaviorSubject<string>(null);
47+
refboxContent: BehaviorSubject<SafeHtml> = new BehaviorSubject<SafeHtml>(null);
48+
7049
/**
71-
* The item has DOI or not.
50+
* The raw content of the reference box, which is fetched from the RefBox Controller.
7251
*/
73-
hasDoi = false;
52+
refboxCopyContent = '';
7453

7554
/**
76-
* The authors of the item. Fetched from the metadata.
55+
* The text to be displayed when the ref box content is empty or cannot be fetched.
7756
*/
78-
authors: string[] = [];
57+
EMPTY_CONTENT = 'Cannot fetch the ref box content';
7958

8059
constructor(private configurationService: ConfigurationDataService,
8160
private clipboard: Clipboard,
@@ -84,146 +63,59 @@ export class ClarinRefCitationComponent implements OnInit {
8463
private requestService: RequestService,
8564
protected rdbService: RemoteDataBuildService,
8665
protected halService: HALEndpointService,
87-
private itemIdentifierService: ItemIdentifierService) {
66+
private sanitizer: DomSanitizer) {
8867
// Configure the tooltip to show on click - `Copied` message
8968
config.triggers = 'click';
9069
}
9170

9271
ngOnInit(): void {
93-
this.authors = this.item.allMetadataValues(AUTHOR_METADATA_FIELDS);
94-
// First Part could be authors or publisher
95-
let firstPart = this.getAuthors();
96-
const year = this.getYear();
97-
98-
// Show publisher instead of author if author is none
99-
if (isEmpty(firstPart)) {
100-
firstPart = this.item.firstMetadataValue('dc.publisher');
101-
}
102-
103-
let citationArray = [firstPart, year];
104-
// Filter null values
105-
citationArray = citationArray.filter(textValue => {
106-
return isNotEmpty(textValue);
107-
});
108-
109-
this.hasDoi = this.hasItemDoi();
110-
this.citationText = citationArray.join(', ');
111-
this.itemNameText = this.getTitle();
112-
this.identifierURI = this.getIdentifierUri(this.whichIdentifierMetadataField());
113-
void this.itemIdentifierService.prettifyIdentifier(this.identifierURI, [this.whichIdentifierMetadataField()])
114-
.then((value: string) => {
115-
this.prettifiedIdentifier.next(value);
72+
void this.fetchRefBoxContent()
73+
.then((content) => {
74+
this.refboxCopyContent = content; // Store raw HTML
75+
this.refboxContent.next(this.sanitizer.bypassSecurityTrustHtml(content));
76+
}).catch((error) => {
77+
console.error('Failed to fetch refbox content:', error);
78+
this.refboxCopyContent = this.EMPTY_CONTENT;
79+
this.refboxContent.next(this.EMPTY_CONTENT);
11680
});
117-
void this.getRepositoryName().then(res => {
118-
this.repositoryNameText = res?.payload?.values?.[0];
119-
});
81+
this.itemNameText = this.item?.firstMetadataValue('dc.title');
12082
}
12183

12284
/**
123-
* After click on the `Copy` icon the text will be formatted and copied for the user.
85+
* Copy the text from the reference box to the clipboard.
86+
* Remove the html tags from the text and copy only the plain text.
12487
*/
12588
copyText() {
126-
const tabChar = ' ';
127-
let authorWithItemName = this.citationText + ',\n' + tabChar + this.itemNameText;
128-
this.clipboard.copy(authorWithItemName + ', ' +
129-
this.repositoryNameText + ', \n' + tabChar + this.identifierURI);
89+
let plainText = this.EMPTY_CONTENT;
90+
if (this.refboxCopyContent) {
91+
const parser = new DOMParser();
92+
const doc = parser.parseFromString(this.refboxCopyContent, 'text/html');
93+
plainText = doc.body.textContent || '';
94+
}
95+
this.clipboard.copy(plainText);
13096
setTimeout(() => {
13197
this.tooltipRef.close();
13298
}, 700);
13399
}
134100

135-
getRepositoryName(): Promise<any> {
136-
return this.configurationService.findByPropertyName('dspace.name')
137-
.pipe(getFirstSucceededRemoteData()).toPromise();
138-
}
139-
140-
/**
141-
* Get the identifier URI from the item metadata. If the item has DOI, return the DOI, otherwise return the handle.
142-
*/
143-
getIdentifierUri(identifierMetadataField) {
144-
return this.item.firstMetadataValue(identifierMetadataField);
145-
}
146-
147-
/**
148-
* Check if the item has DOI.
149-
*/
150-
hasItemDoi() {
151-
return this.item?.allMetadata(DOI_METADATA_FIELD)?.length > 0;
152-
}
153-
154-
/**
155-
* If the item has DOI, return the DOI metadata field, otherwise return the handle metadata field.
156-
*/
157-
whichIdentifierMetadataField() {
158-
return this.hasDoi ? DOI_METADATA_FIELD : HANDLE_METADATA_FIELD;
159-
}
160-
161-
getHandle() {
162-
// Separate the handle from the full URI
163-
const fullUri = this.getIdentifierUri(this.whichIdentifierMetadataField());
164-
const handleWord = 'handle/';
165-
const startHandleIndex = fullUri.indexOf('handle/') + handleWord.length;
166-
return fullUri.substr(startHandleIndex);
167-
}
168-
169101
/**
170-
* Check if the Item has any author metadata.
171-
* @param authorMetadata
102+
* Fetch the content of the reference box from the RefBox Controller.
172103
*/
173-
hasNoAuthor(authorMetadata: string[] = []) {
174-
return isEmpty(authorMetadata);
175-
}
176-
177-
getAuthors() {
178-
let authorText = '';
179-
const authorMetadata = this.authors;
180-
if (isUndefined(authorMetadata) || isNull(authorMetadata)) {
181-
return null;
182-
}
183-
184-
// If metadata value is `(:unav) Unknown author` return null
185-
if (this.hasNoAuthor(authorMetadata)) {
186-
return null;
187-
}
188-
189-
// If there is only one author
190-
if (authorMetadata.length === 1) {
191-
return authorMetadata[0];
192-
}
193-
194-
// If there are less than 5 authors
195-
if (authorMetadata.length <= 5) {
196-
let authors_list = authorMetadata.join('; ');
197-
// Replace last `;` with `and`
198-
authors_list = authors_list.replace(/;([^;]*)$/, ' and$1');
199-
return authors_list;
200-
}
201-
202-
// If there are more than 5 authors
203-
// Get only first author and add `et al.` at the end
204-
authorText = authorMetadata[0] + '; ' + ET_AL_TEXT;
205-
return authorText;
206-
}
207-
208-
getYear() {
209-
const yearMetadata = this.item.metadata['dc.date.issued'];
210-
if (isUndefined(yearMetadata) || isNull(yearMetadata)) {
211-
return null;
212-
}
213-
214-
// The issued date is in the format '2000-01-01'
215-
const issuedDateValues = yearMetadata[0]?.value?.split('-');
216-
// Extract the year and return
217-
return issuedDateValues[0];
218-
}
104+
async fetchRefBoxContent(): Promise<string> {
105+
const requestId = this.requestService.generateRequestId();
106+
const getRequest = new GetRequest(
107+
requestId,
108+
this.halService.getRootHref() + '/core/refbox?handle=' + this.item?.handle
109+
);
110+
this.requestService.send(getRequest);
219111

220-
getTitle() {
221-
const titleMetadata = this.item.metadata['dc.title'];
222-
if (isUndefined(titleMetadata) || isNull(titleMetadata)) {
223-
return null;
112+
try {
113+
const res: any = await this.rdbService.buildFromRequestUUID(requestId)
114+
.pipe(getFirstSucceededRemoteData()).toPromise();
115+
return res?.payload?.displayText || this.EMPTY_CONTENT;
116+
} catch (error) {
117+
return this.EMPTY_CONTENT;
224118
}
225-
226-
return titleMetadata[0]?.value;
227119
}
228120

229121
/**
@@ -259,8 +151,7 @@ export class ClarinRefCitationComponent implements OnInit {
259151
const requestId = this.requestService.generateRequestId();
260152
// Create the request
261153
const getRequest = new GetRequest(requestId, this.halService.getRootHref() + '/core/refbox/citations?type=' +
262-
// citationType + '&handle=' + this.getHandle(), requestOptions);
263-
citationType + '&handle=' + this.getHandle());
154+
citationType + '&handle=' + this.item?.handle);
264155

265156
// Call get request
266157
this.requestService.send(getRequest);

0 commit comments

Comments
 (0)