@abi-software/map-side-bar 2.14.2-demo.0 → 2.14.2-demo.1
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-side-bar.js +9866 -9788
- package/dist/map-side-bar.umd.cjs +66 -63
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/components/BadgesGroup.vue +23 -15
- package/src/components/ConnectivityInfo.vue +1 -0
- package/src/components/DatasetCard.vue +332 -7
- package/src/components/ImageGallery.vue +14 -359
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div v-if="categories['All'].size > 1" class="container" ref="container">
|
|
3
|
-
<div>View data types:</div>
|
|
3
|
+
<div v-if="displayText">View data types:</div>
|
|
4
4
|
<template v-for="(item, key) in categories">
|
|
5
5
|
<el-button
|
|
6
6
|
v-if="item.size > 0"
|
|
@@ -32,7 +32,15 @@ export default {
|
|
|
32
32
|
return []
|
|
33
33
|
},
|
|
34
34
|
},
|
|
35
|
-
|
|
35
|
+
displayDataset: {
|
|
36
|
+
type: Boolean,
|
|
37
|
+
default: true,
|
|
38
|
+
},
|
|
39
|
+
displayText: {
|
|
40
|
+
type: Boolean,
|
|
41
|
+
default: true,
|
|
42
|
+
},
|
|
43
|
+
items: {
|
|
36
44
|
type: Object,
|
|
37
45
|
default: () => {
|
|
38
46
|
return {}
|
|
@@ -47,33 +55,33 @@ export default {
|
|
|
47
55
|
}
|
|
48
56
|
},
|
|
49
57
|
methods: {
|
|
50
|
-
addToCategories: function (
|
|
58
|
+
addToCategories: function (name) {
|
|
59
|
+
const array = this.items[name]
|
|
51
60
|
if (array && array.length > 0) {
|
|
52
61
|
this.categories[name] = { size: array.length }
|
|
53
62
|
this.categories['All'].size += array.length
|
|
54
63
|
}
|
|
55
64
|
},
|
|
56
|
-
addSimulationsToCategories: function (array) {
|
|
57
|
-
if (array && array.length > 0) {
|
|
58
|
-
const size = array.length
|
|
59
|
-
this.categories['Simulations'] = { size }
|
|
60
|
-
this.categories['All'].size += size
|
|
61
|
-
}
|
|
62
|
-
},
|
|
63
65
|
categoryClicked: function (name) {
|
|
64
66
|
this.active = name
|
|
65
67
|
this.$emit('categoryChanged', name)
|
|
66
68
|
},
|
|
67
69
|
},
|
|
68
70
|
watch: {
|
|
69
|
-
|
|
71
|
+
items: {
|
|
70
72
|
deep: true,
|
|
71
73
|
immediate: true,
|
|
72
74
|
handler: function () {
|
|
73
|
-
this.
|
|
74
|
-
this.
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
this.categories = {}
|
|
76
|
+
this.active = "All"
|
|
77
|
+
if (this.displayDataset) {
|
|
78
|
+
this.categories.All = { size: 1 }
|
|
79
|
+
this.categories.Dataset = { size: 1 }
|
|
80
|
+
} else {
|
|
81
|
+
this.categories.All = { size: 0 }
|
|
82
|
+
}
|
|
83
|
+
let keys = ['Flatmaps', 'Plots', 'Scaffolds', 'Simulations']
|
|
84
|
+
keys.forEach(key => this.addToCategories(key))
|
|
77
85
|
/** disable the following
|
|
78
86
|
this.addToCategories(this.entry.images, 'Images');
|
|
79
87
|
this.addToCategories(this.entry.videos, 'Videos');
|
|
@@ -6,12 +6,7 @@
|
|
|
6
6
|
<span class="card-left">
|
|
7
7
|
<ImageGallery
|
|
8
8
|
v-if="!loading && discoverId"
|
|
9
|
-
:
|
|
10
|
-
:datasetVersion="version"
|
|
11
|
-
:entry="entry"
|
|
12
|
-
:envVars="envVars"
|
|
13
|
-
:label="label"
|
|
14
|
-
:datasetThumbnail="thumbnail"
|
|
9
|
+
:items="items"
|
|
15
10
|
:category="currentCategory"
|
|
16
11
|
@card-clicked="galleryClicked"
|
|
17
12
|
@datalink-clicked="galleryDatalinkClicked"
|
|
@@ -40,7 +35,7 @@
|
|
|
40
35
|
</div>
|
|
41
36
|
<div class="badges-container">
|
|
42
37
|
<BadgesGroup
|
|
43
|
-
:
|
|
38
|
+
:items="items"
|
|
44
39
|
@categoryChanged="categoryChanged"
|
|
45
40
|
/>
|
|
46
41
|
</div>
|
|
@@ -56,6 +51,15 @@
|
|
|
56
51
|
</template>
|
|
57
52
|
|
|
58
53
|
<script>
|
|
54
|
+
/* eslint-disable no-alert, no-console */
|
|
55
|
+
const baseName = (str) => {
|
|
56
|
+
return str.split('\\').pop().split('/').pop()
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const capitalise = function (string) {
|
|
60
|
+
return string.replace(/\b\w/g, (v) => v.toUpperCase())
|
|
61
|
+
}
|
|
62
|
+
|
|
59
63
|
/* eslint-disable no-alert, no-console */
|
|
60
64
|
import { View as ElIconView } from '@element-plus/icons-vue'
|
|
61
65
|
import BadgesGroup from './BadgesGroup.vue'
|
|
@@ -68,7 +72,9 @@ import speciesMap from './species-map.js'
|
|
|
68
72
|
import ImageGallery from './ImageGallery.vue'
|
|
69
73
|
import MissingImage from '@/../assets/missing-image.svg'
|
|
70
74
|
import { CopyToClipboard } from '@abi-software/map-utilities';
|
|
75
|
+
import S3Bucket from '../mixins/S3Bucket.vue';
|
|
71
76
|
import '@abi-software/map-utilities/dist/style.css';
|
|
77
|
+
import GalleryHelper from '@abi-software/gallery/src/mixins/GalleryHelpers.js'
|
|
72
78
|
|
|
73
79
|
export default {
|
|
74
80
|
data() {
|
|
@@ -84,6 +90,7 @@ export default {
|
|
|
84
90
|
Icon,
|
|
85
91
|
CopyToClipboard,
|
|
86
92
|
},
|
|
93
|
+
mixins: [GalleryHelper, S3Bucket],
|
|
87
94
|
props: {
|
|
88
95
|
/**
|
|
89
96
|
* Object containing information for
|
|
@@ -103,6 +110,15 @@ export default {
|
|
|
103
110
|
thumbnail: MissingImage,
|
|
104
111
|
dataLocation: this.entry.doi,
|
|
105
112
|
discoverId: undefined,
|
|
113
|
+
items: {
|
|
114
|
+
Dataset: [],
|
|
115
|
+
Flatmaps:[],
|
|
116
|
+
Images: [],
|
|
117
|
+
Scaffolds: [],
|
|
118
|
+
Simulations: [],
|
|
119
|
+
Videos: [],
|
|
120
|
+
Plots: [],
|
|
121
|
+
},
|
|
106
122
|
loading: true,
|
|
107
123
|
version: 1,
|
|
108
124
|
lastDoi: undefined,
|
|
@@ -170,12 +186,318 @@ export default {
|
|
|
170
186
|
categoryChanged: function (name) {
|
|
171
187
|
this.currentCategory = name
|
|
172
188
|
},
|
|
189
|
+
createSciCurnchItems: function () {
|
|
190
|
+
if (this.entry.detailsReady) {
|
|
191
|
+
this.updateS3Bucket(this.entry.s3uri)
|
|
192
|
+
this.createDatasetItem()
|
|
193
|
+
this.createFlatmapItems()
|
|
194
|
+
this.createScaffoldItems()
|
|
195
|
+
this.createSimulationItems()
|
|
196
|
+
this.createPlotItems()
|
|
197
|
+
}
|
|
198
|
+
/* Disable these two
|
|
199
|
+
this.createImageItems();
|
|
200
|
+
this.createVideoItems();
|
|
201
|
+
*/
|
|
202
|
+
},
|
|
203
|
+
createDatasetItem: function () {
|
|
204
|
+
const link = `${this.envVars.ROOT_URL}/datasets/${this.discoverId}?type=dataset`
|
|
205
|
+
if (this.thumbnail) {
|
|
206
|
+
this.items['Dataset'].push({
|
|
207
|
+
id: -1,
|
|
208
|
+
//Work around gallery requires a truthy string
|
|
209
|
+
title: ' ',
|
|
210
|
+
type: `Dataset ${this.discoverId}`,
|
|
211
|
+
thumbnail: this.thumbnail,
|
|
212
|
+
link,
|
|
213
|
+
hideType: true,
|
|
214
|
+
hideTitle: true,
|
|
215
|
+
})
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
createFlatmapItems: function () {
|
|
219
|
+
if (this.entry.flatmaps) {
|
|
220
|
+
this.entry.flatmaps.forEach((flatmap) => {
|
|
221
|
+
if (flatmap.associated_flatmap?.identifier) {
|
|
222
|
+
const filePath = flatmap.dataset.path
|
|
223
|
+
const id = flatmap.identifier
|
|
224
|
+
const thumbnail = this.getThumbnailForPlot(
|
|
225
|
+
flatmap,
|
|
226
|
+
this.entry.thumbnails
|
|
227
|
+
)
|
|
228
|
+
let thumbnailURL = undefined
|
|
229
|
+
let mimetype = ''
|
|
230
|
+
if (thumbnail) {
|
|
231
|
+
thumbnailURL = this.getImageURL(this.envVars.API_LOCATION, {
|
|
232
|
+
id,
|
|
233
|
+
prefix: this.getS3Prefix(),
|
|
234
|
+
file_path: thumbnail.dataset.path,
|
|
235
|
+
s3Bucket: this.s3Bucket,
|
|
236
|
+
})
|
|
237
|
+
mimetype = thumbnail.mimetype.name
|
|
238
|
+
}
|
|
239
|
+
let action = {
|
|
240
|
+
label: baseName(filePath),
|
|
241
|
+
resource: flatmap.associated_flatmap.identifier,
|
|
242
|
+
title: 'View Flatmap',
|
|
243
|
+
type: 'Flatmap',
|
|
244
|
+
discoverId: this.discoverId,
|
|
245
|
+
version: this.version,
|
|
246
|
+
}
|
|
247
|
+
this.items['Flatmaps'].push({
|
|
248
|
+
id,
|
|
249
|
+
title: baseName(filePath),
|
|
250
|
+
type: 'Flatmap',
|
|
251
|
+
thumbnail: thumbnailURL,
|
|
252
|
+
userData: action,
|
|
253
|
+
hideType: true,
|
|
254
|
+
mimetype,
|
|
255
|
+
})
|
|
256
|
+
}
|
|
257
|
+
})
|
|
258
|
+
}
|
|
259
|
+
},
|
|
260
|
+
createImageItems: function () {
|
|
261
|
+
if (this.entry.images) {
|
|
262
|
+
this.entry.images.forEach((image) => {
|
|
263
|
+
const filePath = image.dataset.path
|
|
264
|
+
const id = image.identifier
|
|
265
|
+
const linkUrl = `${this.envVars.ROOT_URL}/datasets/imageviewer?dataset_id=${this.discoverId}&dataset_version=${this.version}&file_path=${filePath}&mimetype=${image.mimetype.name}`
|
|
266
|
+
this.items['Images'].push({
|
|
267
|
+
id,
|
|
268
|
+
title: baseName(filePath),
|
|
269
|
+
type: 'Image',
|
|
270
|
+
link: linkUrl,
|
|
271
|
+
hideType: true,
|
|
272
|
+
})
|
|
273
|
+
})
|
|
274
|
+
}
|
|
275
|
+
},
|
|
276
|
+
createPlotItems: function () {
|
|
277
|
+
if (this.entry.plots) {
|
|
278
|
+
this.entry.plots.forEach((plot) => {
|
|
279
|
+
const filePath = plot.dataset.path
|
|
280
|
+
const id = plot.identifier
|
|
281
|
+
const thumbnail = this.getThumbnailForPlot(
|
|
282
|
+
plot,
|
|
283
|
+
this.entry.thumbnails
|
|
284
|
+
)
|
|
285
|
+
let thumbnailURL = undefined
|
|
286
|
+
let mimetype = ''
|
|
287
|
+
if (thumbnail) {
|
|
288
|
+
|
|
289
|
+
thumbnailURL = this.getImageURL(this.envVars.API_LOCATION, {
|
|
290
|
+
id,
|
|
291
|
+
prefix: this.getS3Prefix(),
|
|
292
|
+
file_path: thumbnail.dataset.path,
|
|
293
|
+
s3Bucket: this.s3Bucket,
|
|
294
|
+
})
|
|
295
|
+
mimetype = thumbnail.mimetype.name
|
|
296
|
+
}
|
|
297
|
+
const plotAnnotation = plot.datacite;
|
|
298
|
+
const filePathPrefix = `${this.envVars.API_LOCATION}/s3-resource/${this.getS3Prefix()}files/`;
|
|
299
|
+
const sourceUrl = filePathPrefix + plot.dataset.path + this.getS3Args();
|
|
300
|
+
|
|
301
|
+
//plotAnnotation.supplemental_json_metadata.description can be undefined or
|
|
302
|
+
//contain an empty string causing an error with JSON.parse
|
|
303
|
+
let metadata = {}
|
|
304
|
+
try {
|
|
305
|
+
metadata = JSON.parse(
|
|
306
|
+
plotAnnotation.supplemental_json_metadata.description
|
|
307
|
+
)
|
|
308
|
+
} catch (error) {
|
|
309
|
+
console.warn(error)
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
let supplementalData = []
|
|
313
|
+
if (plotAnnotation.isDescribedBy) {
|
|
314
|
+
supplementalData.push({
|
|
315
|
+
url: filePathPrefix + plotAnnotation.isDescribedBy.path,
|
|
316
|
+
})
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const resource = {
|
|
320
|
+
dataSource: { url: sourceUrl },
|
|
321
|
+
metadata,
|
|
322
|
+
supplementalData,
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
let action = {
|
|
326
|
+
label: baseName(filePath),
|
|
327
|
+
resource: resource,
|
|
328
|
+
s3uri: this.entry.s3uri,
|
|
329
|
+
title: 'View plot',
|
|
330
|
+
type: 'Plot',
|
|
331
|
+
discoverId: this.discoverId,
|
|
332
|
+
version: this.version,
|
|
333
|
+
}
|
|
334
|
+
this.items['Plots'].push({
|
|
335
|
+
id,
|
|
336
|
+
title: baseName(filePath),
|
|
337
|
+
type: 'Plot',
|
|
338
|
+
thumbnail: thumbnailURL,
|
|
339
|
+
userData: action,
|
|
340
|
+
hideType: true,
|
|
341
|
+
mimetype,
|
|
342
|
+
})
|
|
343
|
+
})
|
|
344
|
+
}
|
|
345
|
+
},
|
|
346
|
+
createScaffoldItems: function () {
|
|
347
|
+
if (this.entry.scaffolds) {
|
|
348
|
+
let index = 0
|
|
349
|
+
this.entry.scaffolds.forEach((scaffold, i) => {
|
|
350
|
+
const filePath = scaffold.dataset.path
|
|
351
|
+
const id = scaffold.identifier
|
|
352
|
+
const thumbnail = this.getThumbnailForScaffold(
|
|
353
|
+
scaffold,
|
|
354
|
+
this.entry.scaffoldViews,
|
|
355
|
+
this.entry.thumbnails,
|
|
356
|
+
index
|
|
357
|
+
)
|
|
358
|
+
let mimetype = ''
|
|
359
|
+
let thumbnailURL = undefined
|
|
360
|
+
if (thumbnail) {
|
|
361
|
+
thumbnailURL = this.getImageURL(this.envVars.API_LOCATION, {
|
|
362
|
+
id,
|
|
363
|
+
prefix: this.getS3Prefix(),
|
|
364
|
+
file_path: thumbnail.dataset.path,
|
|
365
|
+
s3Bucket: this.s3Bucket,
|
|
366
|
+
})
|
|
367
|
+
mimetype = thumbnail.mimetype.name
|
|
368
|
+
}
|
|
369
|
+
let action = {
|
|
370
|
+
label: baseName(filePath),
|
|
371
|
+
resource: `${this.envVars.API_LOCATION}s3-resource/${this.getS3Prefix()}files/${filePath}${this.getS3Args()}`,
|
|
372
|
+
title: "View 3D scaffold",
|
|
373
|
+
type: "Scaffold",
|
|
374
|
+
discoverId: this.discoverId,
|
|
375
|
+
apiLocation: this.envVars.API_LOCATION,
|
|
376
|
+
version: this.version,
|
|
377
|
+
banner: this.thumbnail,
|
|
378
|
+
s3uri: this.entry.s3uri,
|
|
379
|
+
contextCardUrl: this.getContextCardUrl(i),
|
|
380
|
+
}
|
|
381
|
+
this.items['Scaffolds'].push({
|
|
382
|
+
id,
|
|
383
|
+
title: baseName(filePath),
|
|
384
|
+
type: 'Scaffold',
|
|
385
|
+
thumbnail: thumbnailURL,
|
|
386
|
+
userData: action,
|
|
387
|
+
hideType: true,
|
|
388
|
+
mimetype,
|
|
389
|
+
})
|
|
390
|
+
})
|
|
391
|
+
}
|
|
392
|
+
},
|
|
393
|
+
createSimulationItems: function () {
|
|
394
|
+
if (this.entry.simulation) {
|
|
395
|
+
this.entry.simulation.forEach((simulation) => {
|
|
396
|
+
if (simulation.additional_mimetype.name === "application/x.vnd.abi.simulation+json") {
|
|
397
|
+
let action = {
|
|
398
|
+
label: undefined,
|
|
399
|
+
apiLocation: this.envVars.API_LOCATION,
|
|
400
|
+
s3uri: this.entry.s3uri,
|
|
401
|
+
version: this.version,
|
|
402
|
+
title: 'View simulation',
|
|
403
|
+
type: 'Simulation',
|
|
404
|
+
name: this.entry.name,
|
|
405
|
+
description: this.entry.description,
|
|
406
|
+
discoverId: this.discoverId,
|
|
407
|
+
dataset: `${this.envVars.ROOT_URL}/datasets/${this.discoverId}?type=dataset`,
|
|
408
|
+
}
|
|
409
|
+
this.items['Simulations'].push({
|
|
410
|
+
id: 'simulation',
|
|
411
|
+
title: ' ',
|
|
412
|
+
type: 'Simulation',
|
|
413
|
+
hideType: true,
|
|
414
|
+
hideTitle: true,
|
|
415
|
+
userData: action,
|
|
416
|
+
})
|
|
417
|
+
} else {
|
|
418
|
+
const filePath = simulation.dataset.path
|
|
419
|
+
const id = simulation.identifier
|
|
420
|
+
//Despite of the name, this method can be used to retreive
|
|
421
|
+
//the thumbnail information for any none scaffold type thumbnail
|
|
422
|
+
const thumbnail = this.getThumbnailForPlot(
|
|
423
|
+
simulation,
|
|
424
|
+
this.entry.thumbnails
|
|
425
|
+
)
|
|
426
|
+
let thumbnailURL = undefined
|
|
427
|
+
let mimetype = ''
|
|
428
|
+
if (thumbnail) {
|
|
429
|
+
thumbnailURL = this.getImageURL(this.envVars.API_LOCATION, {
|
|
430
|
+
id,
|
|
431
|
+
prefix: this.getS3Prefix(),
|
|
432
|
+
file_path: thumbnail.dataset.path,
|
|
433
|
+
s3Bucket: this.s3Bucket,
|
|
434
|
+
})
|
|
435
|
+
mimetype = thumbnail.mimetype.name
|
|
436
|
+
}
|
|
437
|
+
const resource = `${this.envVars.API_LOCATION}s3-resource/${this.getS3Prefix()}files/${filePath}${this.getS3Args()}`
|
|
438
|
+
let action = {
|
|
439
|
+
label: baseName(filePath),
|
|
440
|
+
resource: resource,
|
|
441
|
+
s3uri: this.entry.s3uri,
|
|
442
|
+
title: 'View simulation',
|
|
443
|
+
type: 'Simulation',
|
|
444
|
+
discoverId: this.discoverId,
|
|
445
|
+
version: this.version,
|
|
446
|
+
}
|
|
447
|
+
this.items['Simulations'].push({
|
|
448
|
+
id,
|
|
449
|
+
title: baseName(filePath),
|
|
450
|
+
type: 'Simulation',
|
|
451
|
+
thumbnail: thumbnailURL,
|
|
452
|
+
userData: action,
|
|
453
|
+
hideType: true,
|
|
454
|
+
mimetype,
|
|
455
|
+
})
|
|
456
|
+
}
|
|
457
|
+
})
|
|
458
|
+
}
|
|
459
|
+
},
|
|
460
|
+
createVideoItems: function () {
|
|
461
|
+
if (this.entry.videos) {
|
|
462
|
+
this.entry.videos.forEach((video) => {
|
|
463
|
+
const filePath = this.getS3FilePath(
|
|
464
|
+
this.discoverId,
|
|
465
|
+
this.version,
|
|
466
|
+
video.dataset.path
|
|
467
|
+
)
|
|
468
|
+
const linkUrl = `${this.envVars.ROOT_URL}/datasets/videoviewer?dataset_version=${this.version}&dataset_id=${this.discoverId}&file_path=${filePath}&mimetype=${video.mimetype.name}`
|
|
469
|
+
this.items['Videos'].push({
|
|
470
|
+
title: video.name,
|
|
471
|
+
type: 'Video',
|
|
472
|
+
thumbnail: this.defaultVideoImg,
|
|
473
|
+
hideType: true,
|
|
474
|
+
link: linkUrl,
|
|
475
|
+
})
|
|
476
|
+
})
|
|
477
|
+
}
|
|
478
|
+
},
|
|
173
479
|
galleryClicked: function (payload) {
|
|
174
480
|
this.propogateCardAction(payload)
|
|
175
481
|
},
|
|
176
482
|
galleryDatalinkClicked: function (payload) {
|
|
177
483
|
EventBus.emit('datalink-clicked', payload); // Pass to mapintegratedvuer
|
|
178
484
|
},
|
|
485
|
+
getContextCardUrl: function(scaffoldIndex){
|
|
486
|
+
if(!this.entry.contextualInformation || this.entry.contextualInformation.length == 0){
|
|
487
|
+
return undefined
|
|
488
|
+
} else {
|
|
489
|
+
// The line below checks if there is a context file for each scaffold. If there is not, we use the first context card for each scaffold.
|
|
490
|
+
let contextIndex = this.entry['abi-contextual-information'].length == this.entry.scaffolds.length ? scaffoldIndex : 0
|
|
491
|
+
return `${this.envVars.API_LOCATION}s3-resource/${this.getS3Prefix()}files/${this.entry.contextualInformation[contextIndex]}${this.getS3Args()}`
|
|
492
|
+
}
|
|
493
|
+
},
|
|
494
|
+
getImageURL: function(apiEndpoint, info) {
|
|
495
|
+
let url = `${apiEndpoint}/s3-resource/${info.prefix}files/${info.file_path}?encodeBase64=true`
|
|
496
|
+
if (info.s3Bucket) {
|
|
497
|
+
url = url + `&s3BucketName=${info.s3Bucket}`
|
|
498
|
+
}
|
|
499
|
+
return url
|
|
500
|
+
},
|
|
179
501
|
openDataset: function () {
|
|
180
502
|
window.open(this.dataLocation, '_blank')
|
|
181
503
|
},
|
|
@@ -242,6 +564,9 @@ export default {
|
|
|
242
564
|
this.discoverId = Number(this.entry.datasetId)
|
|
243
565
|
this.loading = false
|
|
244
566
|
})
|
|
567
|
+
.finally(() => {
|
|
568
|
+
this.createSciCurnchItems()
|
|
569
|
+
})
|
|
245
570
|
}
|
|
246
571
|
},
|
|
247
572
|
lastName: function (fullName) {
|