@abi-software/map-utilities 1.2.2-beta.2 → 1.2.2-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/map-utilities.js +7080 -6824
- package/dist/map-utilities.umd.cjs +54 -54
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/components/ConnectivityGraph/graph.js +1 -1
- package/src/components/Tooltip/ExternalResourceCard.vue +539 -61
- package/src/components/Tooltip/ProvenancePopup.vue +1 -1
- package/src/components/index.js +2 -0
- package/src/components/utilities.js +41 -0
package/package.json
CHANGED
|
@@ -1,27 +1,67 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="resource-container">
|
|
3
|
-
<
|
|
4
|
-
<div class="
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
3
|
+
<div class="attribute-title-container">
|
|
4
|
+
<div class="attribute-title">References</div>
|
|
5
|
+
</div>
|
|
6
|
+
<div class="citation-tabs">
|
|
7
|
+
<el-button
|
|
8
|
+
link
|
|
9
|
+
v-for="citationOption of citationOptions"
|
|
10
|
+
:key="citationOption.value"
|
|
11
|
+
:type="citationType === citationOption.value ? 'primary' : ''"
|
|
12
|
+
@click="onCitationFormatChange(citationOption.value)"
|
|
13
|
+
>
|
|
14
|
+
{{ citationOption.label }}
|
|
15
|
+
</el-button>
|
|
16
|
+
</div>
|
|
17
|
+
<ul class="citation-list">
|
|
18
|
+
<li
|
|
19
|
+
v-for="reference of references"
|
|
20
|
+
:key="reference.id"
|
|
21
|
+
:class="{'loading': reference.citation && reference.citation[citationType] === ''}"
|
|
22
|
+
>
|
|
23
|
+
<template v-if="reference.citation && reference.citation[citationType]">
|
|
24
|
+
<span v-html="reference.citation[citationType]"></span>
|
|
25
|
+
<CopyToClipboard :content="reference.citation[citationType]" />
|
|
26
|
+
</template>
|
|
27
|
+
</li>
|
|
28
|
+
|
|
29
|
+
<li v-for="reference of openLibReferences">
|
|
30
|
+
<div v-html="formatCopyReference(reference)"></div>
|
|
31
|
+
<CopyToClipboard :content="formatCopyReference(reference)" />
|
|
32
|
+
</li>
|
|
33
|
+
|
|
34
|
+
<li v-for="reference of isbnDBReferences">
|
|
35
|
+
<a :href="reference.url">{{ reference.url }}</a>
|
|
36
|
+
<CopyToClipboard :content="reference.url" />
|
|
37
|
+
</li>
|
|
38
|
+
</ul>
|
|
16
39
|
</div>
|
|
17
40
|
</template>
|
|
18
41
|
|
|
19
42
|
<script>
|
|
20
|
-
|
|
21
|
-
import { shallowRef } from "vue";
|
|
22
|
-
import { Notebook as ElIconNotebook } from "@element-plus/icons-vue";
|
|
43
|
+
import CopyToClipboard from '../CopyToClipboard/CopyToClipboard.vue';
|
|
23
44
|
|
|
24
|
-
|
|
45
|
+
const CROSSCITE_API_HOST = 'https://citation.crosscite.org';
|
|
46
|
+
const CITATION_OPTIONS = [
|
|
47
|
+
{
|
|
48
|
+
label: 'APA',
|
|
49
|
+
value: 'apa',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
label: 'Chicago',
|
|
53
|
+
value: 'chicago-note-bibliography',
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
label: 'IEEE',
|
|
57
|
+
value: 'ieee',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
label: 'Bibtex',
|
|
61
|
+
value: 'bibtex',
|
|
62
|
+
},
|
|
63
|
+
];
|
|
64
|
+
const CITATION_DEFAULT = 'apa';
|
|
25
65
|
|
|
26
66
|
export default {
|
|
27
67
|
name: "ExternalResourceCard",
|
|
@@ -33,26 +73,422 @@ export default {
|
|
|
33
73
|
},
|
|
34
74
|
data: function () {
|
|
35
75
|
return {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
76
|
+
references: [],
|
|
77
|
+
pubMedReferences: [],
|
|
78
|
+
openLibReferences: [],
|
|
79
|
+
isbnDBReferences: [],
|
|
80
|
+
citationOptions: CITATION_OPTIONS,
|
|
81
|
+
citationType: CITATION_DEFAULT,
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
watch: {
|
|
85
|
+
resources: function (_resources) {
|
|
86
|
+
this.formatReferences([..._resources]);
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
mounted: function () {
|
|
90
|
+
this.formatReferences([...this.resources]);
|
|
91
|
+
this.getCitationText(CITATION_DEFAULT);
|
|
40
92
|
},
|
|
41
93
|
methods: {
|
|
42
|
-
|
|
43
|
-
|
|
94
|
+
formatReferences: function (references) {
|
|
95
|
+
const nonPubMedReferences = this.extractNonPubMedReferences(references);
|
|
96
|
+
const pubMedReferences = references.filter((reference) => !nonPubMedReferences.includes(reference));
|
|
97
|
+
|
|
98
|
+
this.pubMedReferences = pubMedReferences.map((reference) =>
|
|
99
|
+
(typeof reference === 'object') ?
|
|
100
|
+
this.extractPublicationIdFromURLString(reference[0]) :
|
|
101
|
+
this.extractPublicationIdFromURLString(reference)
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
this.formatNonPubMedReferences(nonPubMedReferences).then((responses) => {
|
|
105
|
+
this.openLibReferences = responses.filter((response) => response.type === 'openlib');
|
|
106
|
+
this.isbnDBReferences = responses.filter((response) => response.type === 'isbndb');
|
|
107
|
+
|
|
108
|
+
this.formatOpenLibReferences();
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
this.references = [
|
|
112
|
+
...this.pubMedReferences,
|
|
113
|
+
];
|
|
114
|
+
},
|
|
115
|
+
extractNonPubMedReferences: function (references) {
|
|
116
|
+
const extractedReferences = [];
|
|
117
|
+
const pubmedDomains = this.getPubMedDomains();
|
|
118
|
+
|
|
119
|
+
references.forEach((reference) => {
|
|
120
|
+
let count = 0;
|
|
121
|
+
pubmedDomains.forEach((name) => {
|
|
122
|
+
if (reference.includes(name)) {
|
|
123
|
+
count++;
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
if (!count) {
|
|
127
|
+
extractedReferences.push(reference);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
return extractedReferences;
|
|
132
|
+
},
|
|
133
|
+
formatNonPubMedReferences: async function (references) {
|
|
134
|
+
const transformedReferences = [];
|
|
135
|
+
const filteredReferences = references.filter((referenceURL) => referenceURL.indexOf('isbn') !== -1);
|
|
136
|
+
const isbnIDs = filteredReferences.map((url) => {
|
|
137
|
+
const isbnId = url.split('/').pop();
|
|
138
|
+
return 'ISBN:' + isbnId;
|
|
139
|
+
});
|
|
140
|
+
const isbnIDsKey = isbnIDs.join(',');
|
|
141
|
+
const failedIDs = isbnIDs.slice();
|
|
142
|
+
|
|
143
|
+
const openlibAPI = `https://openlibrary.org/api/books?bibkeys=${isbnIDsKey}&format=json`;
|
|
144
|
+
const response = await fetch(openlibAPI);
|
|
145
|
+
const data = await response.json();
|
|
146
|
+
|
|
147
|
+
for (const key in data) {
|
|
148
|
+
const successKeyIndex = failedIDs.indexOf(key);
|
|
149
|
+
failedIDs.splice(successKeyIndex, 1);
|
|
150
|
+
|
|
151
|
+
const url = data[key].info_url;
|
|
152
|
+
const urlSegments = url.split('/');
|
|
153
|
+
const endpointIndex = urlSegments.indexOf('books');
|
|
154
|
+
const bookId = urlSegments[endpointIndex + 1];
|
|
155
|
+
|
|
156
|
+
transformedReferences.push({
|
|
157
|
+
id: key.split(':')[1], // Key => "ISBN:1234"
|
|
158
|
+
type: 'openlib',
|
|
159
|
+
url: url,
|
|
160
|
+
bookId: bookId,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
failedIDs.forEach((failedID) => {
|
|
165
|
+
const id = failedID.split(':')[1];
|
|
166
|
+
// Data does not exist in OpenLibrary
|
|
167
|
+
// Provide ISBNDB link for reference
|
|
168
|
+
const url = `https://isbndb.com/book/${id}`;
|
|
169
|
+
transformedReferences.push({
|
|
170
|
+
id: id,
|
|
171
|
+
url: url,
|
|
172
|
+
type: 'isbndb'
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
return transformedReferences;
|
|
177
|
+
},
|
|
178
|
+
getURLsForPubMed: function (data) {
|
|
179
|
+
return new Promise((resolve) => {
|
|
180
|
+
const ids = data.map((id) =>
|
|
181
|
+
(typeof id === 'object') ?
|
|
182
|
+
this.extractPublicationIdFromURLString(id[0]) :
|
|
183
|
+
this.extractPublicationIdFromURLString(id)
|
|
184
|
+
)
|
|
185
|
+
this.convertPublicationIds(ids).then((pmids) => {
|
|
186
|
+
if (pmids.length > 0) {
|
|
187
|
+
const transformedIDs = [];
|
|
188
|
+
pmids.forEach(pmid => {
|
|
189
|
+
transformedIDs.push({
|
|
190
|
+
id: pmid,
|
|
191
|
+
link: this.pubmedSearchUrl(pmid),
|
|
192
|
+
})
|
|
193
|
+
})
|
|
194
|
+
resolve(transformedIDs)
|
|
195
|
+
} else {
|
|
196
|
+
resolve([])
|
|
197
|
+
}
|
|
198
|
+
})
|
|
199
|
+
})
|
|
200
|
+
},
|
|
201
|
+
extractPublicationIdFromURLString: function (urlStr) {
|
|
202
|
+
if (!urlStr) return
|
|
203
|
+
|
|
204
|
+
const str = decodeURIComponent(urlStr)
|
|
205
|
+
|
|
206
|
+
let term = {id: '', type: '', citation: {}}
|
|
207
|
+
|
|
208
|
+
const names = this.getPubMedDomains()
|
|
209
|
+
|
|
210
|
+
names.forEach((name) => {
|
|
211
|
+
const lastIndex = str.lastIndexOf(name)
|
|
212
|
+
if (lastIndex !== -1) {
|
|
213
|
+
term.id = str.slice(lastIndex + name.length)
|
|
214
|
+
if (name === 'doi.org/') {
|
|
215
|
+
term.type = "doi"
|
|
216
|
+
} else if (name === 'pmc/articles/') {
|
|
217
|
+
term.type = "pmc"
|
|
218
|
+
} else {
|
|
219
|
+
term.type = "pmid"
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
//Backward compatability with doi: and PMID:
|
|
225
|
+
if (term.id === '') {
|
|
226
|
+
if (urlStr.includes("doi:")) {
|
|
227
|
+
term.id = this.stripPMIDPrefix(urlStr)
|
|
228
|
+
term.type = "doi"
|
|
229
|
+
} else if (urlStr.includes("PMID:")) {
|
|
230
|
+
term.id = this.stripPMIDPrefix(urlStr)
|
|
231
|
+
term.type = "pmid"
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (term.id.endsWith('/')) {
|
|
236
|
+
term.id = term.id.slice(0, -1)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return term
|
|
240
|
+
},
|
|
241
|
+
getPubMedDomains: function () {
|
|
242
|
+
const names = [
|
|
243
|
+
'doi.org/',
|
|
244
|
+
'nih.gov/pubmed/',
|
|
245
|
+
'pmc/articles/',
|
|
246
|
+
'pubmed.ncbi.nlm.nih.gov/',
|
|
247
|
+
]
|
|
248
|
+
|
|
249
|
+
return names;
|
|
250
|
+
},
|
|
251
|
+
convertPublicationIds: function (ids) {
|
|
252
|
+
return new Promise((resolve) => {
|
|
253
|
+
const pmids = []
|
|
254
|
+
const toBeConverted = []
|
|
255
|
+
ids.forEach((id) => {
|
|
256
|
+
if (id.type === "pmid") {
|
|
257
|
+
pmids.push(id.id)
|
|
258
|
+
} else if (id.type === "doi" || id.type === "pmc") {
|
|
259
|
+
toBeConverted.push(id.id)
|
|
260
|
+
}
|
|
261
|
+
})
|
|
262
|
+
this.getPMID(toBeConverted).then((idList) => {
|
|
263
|
+
pmids.push(...idList)
|
|
264
|
+
resolve(pmids)
|
|
265
|
+
})
|
|
266
|
+
.catch(() => {
|
|
267
|
+
resolve(pmids)
|
|
268
|
+
})
|
|
269
|
+
})
|
|
270
|
+
},
|
|
271
|
+
pubmedSearchUrl: function (ids) {
|
|
272
|
+
let url = 'https://pubmed.ncbi.nlm.nih.gov/?'
|
|
273
|
+
let params = new URLSearchParams()
|
|
274
|
+
params.append('term', ids)
|
|
275
|
+
return url + params.toString()
|
|
276
|
+
},
|
|
277
|
+
stripPMIDPrefix: function (pubmedId) {
|
|
278
|
+
return pubmedId.split(':')[1]
|
|
279
|
+
},
|
|
280
|
+
getPMID: function(idsList) {
|
|
281
|
+
return new Promise((resolve) => {
|
|
282
|
+
if (idsList.length > 0) {
|
|
283
|
+
//Muliple term search does not work well,
|
|
284
|
+
//DOIs term get splitted unexpectedly
|
|
285
|
+
//
|
|
286
|
+
const promises = []
|
|
287
|
+
const results = []
|
|
288
|
+
let wrapped = ''
|
|
289
|
+
idsList.forEach((id, i) => {
|
|
290
|
+
wrapped += i > 0 ? 'OR"' + id + '"' : '"' + id + '"'
|
|
291
|
+
})
|
|
292
|
+
|
|
293
|
+
const params = new URLSearchParams({
|
|
294
|
+
db: 'pubmed',
|
|
295
|
+
term: wrapped,
|
|
296
|
+
format: 'json'
|
|
297
|
+
})
|
|
298
|
+
const promise = fetch(`https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?${params}`, {
|
|
299
|
+
method: 'GET',
|
|
300
|
+
})
|
|
301
|
+
.then((response) => response.json())
|
|
302
|
+
.then((data) => {
|
|
303
|
+
const newIds = data.esearchresult ? data.esearchresult.idlist : []
|
|
304
|
+
results.push(...newIds)
|
|
305
|
+
})
|
|
306
|
+
promises.push(promise)
|
|
307
|
+
|
|
308
|
+
Promise.all(promises).then(() => {
|
|
309
|
+
resolve(results)
|
|
310
|
+
}).catch(() => {
|
|
311
|
+
resolve(results)
|
|
312
|
+
})
|
|
313
|
+
} else {
|
|
314
|
+
resolve([])
|
|
315
|
+
}
|
|
316
|
+
})
|
|
317
|
+
},
|
|
318
|
+
onCitationFormatChange: function(citationType) {
|
|
319
|
+
this.citationType = citationType;
|
|
320
|
+
this.getCitationText(citationType);
|
|
321
|
+
},
|
|
322
|
+
getCitationText: function(citationType) {
|
|
323
|
+
this.references.forEach((reference) => {
|
|
324
|
+
const { id, type, doi } = reference;
|
|
325
|
+
|
|
326
|
+
if (
|
|
327
|
+
!(reference.citation && reference.citation[citationType])
|
|
328
|
+
&& id
|
|
329
|
+
) {
|
|
330
|
+
reference.citation[citationType] = ''; // loading
|
|
331
|
+
|
|
332
|
+
if (type === 'doi' || doi) {
|
|
333
|
+
const doiID = type === 'doi' ? id : doi;
|
|
334
|
+
|
|
335
|
+
this.getCitationTextByDOI(doiID)
|
|
336
|
+
.then((text) => {
|
|
337
|
+
reference.citation[citationType] = this.replaceLinkInText(text);
|
|
338
|
+
});
|
|
339
|
+
} else if (type === 'pmid') {
|
|
340
|
+
this.getDOIFromPubMedID(id)
|
|
341
|
+
.then((data) => {
|
|
342
|
+
if (data?.result) {
|
|
343
|
+
const resultObj = data.result[id];
|
|
344
|
+
const articleIDs = resultObj?.articleids || [];
|
|
345
|
+
const doiObj = articleIDs.find((item) => item.idtype === 'doi');
|
|
346
|
+
const doiID = doiObj?.value;
|
|
347
|
+
reference['doi'] = doiID;
|
|
348
|
+
|
|
349
|
+
this.getCitationTextByDOI(doiID)
|
|
350
|
+
.then((text) => {
|
|
351
|
+
reference.citation[citationType] = this.replaceLinkInText(text);
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
},
|
|
359
|
+
replaceLinkInText: function (text) {
|
|
360
|
+
const protocol = 'https://';
|
|
361
|
+
let linkBody = text.split(protocol)[1];
|
|
362
|
+
|
|
363
|
+
if (linkBody) {
|
|
364
|
+
linkBody = linkBody.split(' ')[0];
|
|
365
|
+
linkBody = linkBody.trim();
|
|
366
|
+
|
|
367
|
+
if (linkBody.endsWith('.')) {
|
|
368
|
+
linkBody = linkBody.substring(0, linkBody.length - 1);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
const fullLink = protocol + linkBody;
|
|
372
|
+
const htmlLink = `<a href="${fullLink}" target="_blank">${fullLink}</a>`;
|
|
373
|
+
|
|
374
|
+
return text.replace(fullLink, htmlLink);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
return text;
|
|
378
|
+
},
|
|
379
|
+
getCitationTextByDOI: async function (id) {
|
|
380
|
+
const citationAPI = `${CROSSCITE_API_HOST}/format?doi=${id}&style=${this.citationType}&lang=en-US`;
|
|
381
|
+
try {
|
|
382
|
+
const response = await fetch(citationAPI);
|
|
383
|
+
if (!response.ok) {
|
|
384
|
+
throw new Error(`Response status: ${response.status}`);
|
|
385
|
+
}
|
|
386
|
+
const data = await response.text();
|
|
387
|
+
return data;
|
|
388
|
+
} catch (error) {
|
|
389
|
+
console.error(`Fetch citation text error: ${error}`);
|
|
390
|
+
}
|
|
44
391
|
},
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
392
|
+
getDOIFromPubMedID: async function (pubmedId) {
|
|
393
|
+
const summaryAPI = `https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=pubmed&id=${pubmedId}&format=json`;
|
|
394
|
+
try {
|
|
395
|
+
const response = await fetch(summaryAPI);
|
|
396
|
+
if (!response.ok) {
|
|
397
|
+
throw new Error(`Response status: ${response.status}`);
|
|
398
|
+
}
|
|
399
|
+
const data = await response.json();
|
|
400
|
+
return data;
|
|
401
|
+
} catch (error) {
|
|
402
|
+
console.error(`Fetch article summary error: ${error}`);
|
|
403
|
+
}
|
|
404
|
+
},
|
|
405
|
+
formatOpenLibReferences: function () {
|
|
406
|
+
this.openLibReferences.forEach((reference) => {
|
|
407
|
+
const { bookId } = reference;
|
|
408
|
+
this.getBookData(bookId)
|
|
409
|
+
.then((data) => {
|
|
410
|
+
const { title, authors, publish_date } = data;
|
|
411
|
+
if (title) {
|
|
412
|
+
reference['title'] = title;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
if (publish_date) {
|
|
416
|
+
reference['date'] = publish_date;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
if (authors) {
|
|
420
|
+
reference['authors'] = [];
|
|
421
|
+
|
|
422
|
+
authors.forEach((author) => {
|
|
423
|
+
this.getBookAuthor(author.key)
|
|
424
|
+
.then((data) => {
|
|
425
|
+
const { name } = data;
|
|
426
|
+
if (name) {
|
|
427
|
+
reference['authors'].push(name);
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
});
|
|
433
|
+
});
|
|
434
|
+
},
|
|
435
|
+
getBookData: async function (bookId) {
|
|
436
|
+
const apiURL = `https://openlibrary.org/books/${bookId}.json`;
|
|
437
|
+
try {
|
|
438
|
+
const response = await fetch(apiURL);
|
|
439
|
+
if (!response.ok) {
|
|
440
|
+
throw new Error(`Response status: ${response.status}`);
|
|
441
|
+
}
|
|
442
|
+
const data = await response.json();
|
|
443
|
+
return data;
|
|
444
|
+
} catch (error) {
|
|
445
|
+
console.error(`Fetch book data error: ${error}`);
|
|
446
|
+
}
|
|
447
|
+
},
|
|
448
|
+
getBookAuthor: async function (key) {
|
|
449
|
+
const apiURL = `https://openlibrary.org${key}.json`;
|
|
450
|
+
try {
|
|
451
|
+
const response = await fetch(apiURL);
|
|
452
|
+
if (!response.ok) {
|
|
453
|
+
throw new Error(`Response status: ${response.status}`);
|
|
454
|
+
}
|
|
455
|
+
const data = await response.json();
|
|
456
|
+
return data;
|
|
457
|
+
} catch (error) {
|
|
458
|
+
console.error(`Fetch book author error: ${error}`);
|
|
459
|
+
}
|
|
460
|
+
},
|
|
461
|
+
formatCopyReference: function (reference) {
|
|
462
|
+
const copyContents = [];
|
|
463
|
+
const { title, date, authors, url } = reference;
|
|
464
|
+
|
|
465
|
+
if (title) {
|
|
466
|
+
copyContents.push(title);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
if (date) {
|
|
470
|
+
copyContents.push(`(${date})`);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
if (authors) {
|
|
474
|
+
copyContents.push(`- ${authors.join(', ')}`);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
copyContents.push(`<div><a href="${url}" target="_blank">${url}</a></div>`);
|
|
478
|
+
|
|
479
|
+
return copyContents.join(' ');
|
|
48
480
|
},
|
|
49
481
|
},
|
|
50
|
-
}
|
|
482
|
+
}
|
|
51
483
|
</script>
|
|
52
484
|
|
|
53
485
|
<style lang="scss" scoped>
|
|
54
486
|
.resource-container {
|
|
55
|
-
margin-top:
|
|
487
|
+
margin-top: 1em;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
.attribute-title-container {
|
|
491
|
+
margin-bottom: 0.5rem;
|
|
56
492
|
}
|
|
57
493
|
|
|
58
494
|
.attribute-title {
|
|
@@ -62,47 +498,89 @@ export default {
|
|
|
62
498
|
text-transform: uppercase;
|
|
63
499
|
}
|
|
64
500
|
|
|
65
|
-
.
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
501
|
+
.citation-list {
|
|
502
|
+
margin: 0;
|
|
503
|
+
margin-top: 0.5rem;
|
|
504
|
+
padding: 0;
|
|
505
|
+
list-style: none;
|
|
506
|
+
line-height: 1.3;
|
|
507
|
+
|
|
508
|
+
li {
|
|
509
|
+
margin: 0;
|
|
510
|
+
padding: 0.5rem 1.5rem 0.5rem 0.75rem;
|
|
511
|
+
border-radius: var(--el-border-radius-base);
|
|
512
|
+
background-color: var(--el-bg-color-page);
|
|
513
|
+
position: relative;
|
|
514
|
+
|
|
515
|
+
:deep(a) {
|
|
516
|
+
word-wrap: break-word;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
+ li {
|
|
520
|
+
margin-top: 0.5rem;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
&.loading {
|
|
524
|
+
padding: 1rem;
|
|
69
525
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
526
|
+
&::before {
|
|
527
|
+
content: "";
|
|
528
|
+
display: block;
|
|
529
|
+
width: 100%;
|
|
530
|
+
height: 100%;
|
|
531
|
+
position: absolute;
|
|
532
|
+
top: 0;
|
|
533
|
+
left: 0;
|
|
534
|
+
animation-duration: 3s;
|
|
535
|
+
animation-fill-mode: forwards;
|
|
536
|
+
animation-iteration-count: infinite;
|
|
537
|
+
animation-name: loadingAnimation;
|
|
538
|
+
animation-timing-function: linear;
|
|
539
|
+
background: linear-gradient(to right,
|
|
540
|
+
var(--el-bg-color-page) 5%,
|
|
541
|
+
var(--el-color-info-light-8) 15%,
|
|
542
|
+
var(--el-bg-color-page) 30%
|
|
543
|
+
);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
:deep(.copy-clipboard-button) {
|
|
548
|
+
position: absolute;
|
|
549
|
+
bottom: 0.25rem;
|
|
550
|
+
right: 0.25rem;
|
|
551
|
+
opacity: 0;
|
|
552
|
+
visibility: hidden;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
&:hover {
|
|
556
|
+
:deep(.copy-clipboard-button) {
|
|
557
|
+
opacity: 1;
|
|
558
|
+
visibility: visible;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
77
561
|
}
|
|
78
562
|
}
|
|
79
563
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
564
|
+
.citation-tabs {
|
|
565
|
+
.el-button {
|
|
566
|
+
&:hover,
|
|
567
|
+
&:focus,
|
|
568
|
+
&:active {
|
|
569
|
+
color: $app-primary-color;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
83
572
|
|
|
84
|
-
.
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
/* font-weight: bold; */
|
|
88
|
-
text-transform: uppercase;
|
|
573
|
+
.el-button + .el-button {
|
|
574
|
+
margin-left: 0.25rem;
|
|
575
|
+
}
|
|
89
576
|
}
|
|
90
577
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
font-size: 14px !important;
|
|
95
|
-
background-color: $app-primary-color;
|
|
96
|
-
color: #fff;
|
|
97
|
-
&:hover {
|
|
98
|
-
color: #fff !important;
|
|
99
|
-
background: #ac76c5 !important;
|
|
100
|
-
border: 1px solid #ac76c5 !important;
|
|
578
|
+
@keyframes loadingAnimation {
|
|
579
|
+
0% {
|
|
580
|
+
background-position: -30vw 0;
|
|
101
581
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
background-color: $app-primary-color;
|
|
105
|
-
color: #fff;
|
|
582
|
+
100% {
|
|
583
|
+
background-position: 70vw 0;
|
|
106
584
|
}
|
|
107
585
|
}
|
|
108
586
|
</style>
|
|
@@ -164,7 +164,7 @@
|
|
|
164
164
|
Search for data on components
|
|
165
165
|
</el-button>
|
|
166
166
|
|
|
167
|
-
<external-resource-card :resources="resources"></external-resource-card>
|
|
167
|
+
<external-resource-card :resources="resources" v-if="resources.length"></external-resource-card>
|
|
168
168
|
</div>
|
|
169
169
|
</transition>
|
|
170
170
|
</div>
|
package/src/components/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import DrawToolbar from "./DrawToolbar/DrawToolbar.vue";
|
|
|
6
6
|
import HelpModeDialog from "./HelpModeDialog/HelpModeDialog.vue";
|
|
7
7
|
import Tooltip from "./Tooltip/Tooltip.vue";
|
|
8
8
|
import TreeControls from "./TreeControls/TreeControls.vue";
|
|
9
|
+
import ExternalResourceCard from "./Tooltip/ExternalResourceCard.vue";
|
|
9
10
|
|
|
10
11
|
export {
|
|
11
12
|
AnnotationPopup,
|
|
@@ -16,4 +17,5 @@ export {
|
|
|
16
17
|
HelpModeDialog,
|
|
17
18
|
Tooltip,
|
|
18
19
|
TreeControls,
|
|
20
|
+
ExternalResourceCard,
|
|
19
21
|
};
|