@abi-software/map-side-bar 2.4.2-beta.0 → 2.4.2

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.
@@ -1,497 +0,0 @@
1
- <template>
2
- <div class="image-thumbnails-container">
3
- <div class="toolbar">
4
- <div class="filters">
5
- <el-tag
6
- v-for="(species, index) in speciesFilterTags"
7
- :key="index"
8
- type="info"
9
- class="tag"
10
- :class="{ 'active-tag': species.name === activeSpecies.name }"
11
- :closable="species.name === activeSpecies.name"
12
- @close="removeSpeciesFilterTag"
13
- @click="filterBySpecies(species)"
14
- >
15
- {{ species.name }} ({{ species.count }})
16
- </el-tag>
17
- </div>
18
- <div class="view-selector">
19
- <el-select
20
- v-model="viewOption"
21
- placeholder="Select view"
22
- popper-class="view-selector-select-popper"
23
- >
24
- <el-option
25
- v-for="item in viewOptions"
26
- :key="item.value"
27
- :label="item.label"
28
- :value="item.value"
29
- />
30
- </el-select>
31
- </div>
32
- </div>
33
- <div class="gallery-container" v-if="viewOption === 'gallery'">
34
- <Gallery :items="imageItems" :imageStyle="imageStyle" />
35
- </div>
36
- <div class="dataset-card-container" v-if="viewOption === 'list'">
37
- <div class="dataset-card" v-for="imageThumbnail in imageItems">
38
- <div class="card" :key="imageThumbnail.link">
39
- <div class="card-left">
40
- <a :href="imageThumbnail.link" class="card-image card-button-link" target="_blank">
41
- <el-image :src="imageThumbnail.imgSrc" loading="lazy">
42
- <template #error>
43
- <div class="image-slot">Loading...</div>
44
- </template>
45
- </el-image>
46
- </a>
47
- </div>
48
- <div class="card-right">
49
- <div class="details">
50
- <div class="title">
51
- <strong>{{ imageThumbnail.type }}</strong>
52
- </div>
53
- </div>
54
- <div class="details">
55
- <div>
56
- {{ formattedTitle(imageThumbnail) }}
57
- </div>
58
- </div>
59
- <div class="details">
60
- <a class="button el-button el-button--large card-button-link" :href="imageThumbnail.link" target="_blank">
61
- View {{ imageThumbnail.type }}
62
- </a>
63
- </div>
64
- <!-- Copy to clipboard button container -->
65
- <div class="float-button-container">
66
- <CopyToClipboard :content="getCopyContent(imageThumbnail)" />
67
- </div>
68
- </div>
69
- </div>
70
- </div>
71
- </div>
72
- </div>
73
- </template>
74
-
75
- <script>
76
- import {
77
- ElImage,
78
- ElTag as Tag,
79
- ElOption as Option,
80
- ElSelect as Select,
81
- } from 'element-plus';
82
- import { CopyToClipboard } from '@abi-software/map-utilities';
83
- import '@abi-software/map-utilities/dist/style.css';
84
- import Gallery from "@abi-software/gallery";
85
- import "@abi-software/gallery/dist/style.css";
86
-
87
- const BASE64PREFIX = 'data:image/png;base64,';
88
- const VIEW_OPTIONS = [
89
- {
90
- value: 'list',
91
- label: 'List'
92
- },
93
- {
94
- value: 'gallery',
95
- label: 'Gallery'
96
- }
97
- ];
98
-
99
- export default {
100
- name: 'ImageThumbnails',
101
- components: {
102
- Tag,
103
- Option,
104
- Select,
105
- ElImage,
106
- Gallery,
107
- CopyToClipboard,
108
- },
109
- props: {
110
- /**
111
- * The image thumbnails data to show in sidebar.
112
- */
113
- imageThumbnails: {
114
- type: Array,
115
- default: [],
116
- },
117
- },
118
- data: function () {
119
- return {
120
- activeSpecies: { name: "" },
121
- speciesFilterTags: [],
122
- imageItems: [],
123
- showImageGallery: false,
124
- viewOption: 'list',
125
- viewOptions: VIEW_OPTIONS,
126
- };
127
- },
128
- computed: {
129
- imageStyle() {
130
- return {
131
- width: "180px",
132
- height: "135px",
133
- };
134
- },
135
- },
136
- mounted: function () {
137
- this.injectImgSrc();
138
- this.populateFilterTags();
139
- this.imageItems = this.imageThumbnails;
140
- },
141
- watch: {
142
- imageThumbnails: {
143
- handler: function (value) {
144
- if (value) {
145
- this.injectImgSrc();
146
- this.populateFilterTags();
147
- this.imageItems = this.imageThumbnails;
148
- }
149
- },
150
- deep: true,
151
- },
152
- },
153
- methods: {
154
- injectImgSrc: function() {
155
- this.imageThumbnails.forEach((imageThumbnail) => {
156
- return this.mapImage(imageThumbnail);
157
- });
158
- },
159
- formattedTitle: function(imageThumbnail) {
160
- const type = imageThumbnail.mimetype?.split('/')[1];
161
- const title = imageThumbnail.title;
162
- let formattedTitle = '';
163
- if (type !== 'jpg') {
164
- formattedTitle = title.replace('.' + type, '');
165
- }
166
- formattedTitle = formattedTitle.replaceAll('_', ' ');
167
- return formattedTitle;
168
- },
169
- datasetURL: function(id) {
170
- return `https://sparc.science/datasets/${id}?type=dataset`;
171
- },
172
- mapImage: async function (image) {
173
- const imgSrc = await this.transformedImage(image.thumbnail);
174
- if (imgSrc) {
175
- image.imgSrc = imgSrc;
176
- }
177
- },
178
- transformedImage: async function(imgUrl) {
179
- try {
180
- const response = await fetch(imgUrl);
181
- if (!response.ok) {
182
- return null;
183
- }
184
- const data = await response.text();
185
- return BASE64PREFIX + data;
186
- } catch (error) {
187
- return null;
188
- }
189
- },
190
- removeSpeciesFilterTag: function () {
191
- this.activeSpecies = { name: "" };
192
- this.imageItems = this.imageThumbnails;
193
- },
194
- filterBySpecies: function (tagInfo) {
195
- this.activeSpecies = tagInfo;
196
- let filteredImageItems = [];
197
- this.imageThumbnails.forEach((image) => {
198
- if (image.species && image.species.length) {
199
- image.species.forEach((species) => {
200
- if (species === tagInfo.name) {
201
- filteredImageItems.push(image);
202
- }
203
- });
204
- }
205
- });
206
- this.imageItems = filteredImageItems;
207
- },
208
- populateFilterTags: function () {
209
- let imageObjects = {};
210
- this.imageThumbnails.forEach((image) => {
211
- if (image.species && image.species.length) {
212
- image.species.forEach((species) => {
213
- if (!(species in imageObjects)) {
214
- imageObjects[species] = {
215
- name: species,
216
- count: 0,
217
- };
218
- }
219
- imageObjects[species].count++;
220
- });
221
- }
222
- });
223
- this.speciesFilterTags = Object.values(imageObjects);
224
- },
225
- getCopyContent: function (imageThumbnail) {
226
- const contentArray = [];
227
-
228
- // Use <div> instead of <h1>..<h6> or <p>
229
- // to avoid default formatting on font size and margin
230
-
231
- // Title
232
- if (imageThumbnail.title) {
233
- contentArray.push(`<div><strong>${this.formattedTitle(imageThumbnail)}</strong></div>`);
234
- }
235
-
236
- // Type
237
- if (imageThumbnail.type) {
238
- let imageType = `<div><strong>Type:</strong></div>`;
239
- imageType += `\n`;
240
- imageType += `${imageThumbnail.type}`;
241
- contentArray.push(`<div>${imageType}</div>`);
242
- }
243
-
244
- // Species
245
- if (imageThumbnail.species?.length) {
246
- let species = `<div><strong>Species:</strong></div>`;
247
- species += `\n`;
248
- species += imageThumbnail.species.join(', ');
249
- contentArray.push(`<div>${species}</div>`);
250
- }
251
-
252
- // Image URL
253
- if (imageThumbnail.link) {
254
- let thumbnailLink = `<div><strong>Link:</strong></div>`;
255
- thumbnailLink += `\n`;
256
- thumbnailLink += `<a href="${imageThumbnail.link}">${imageThumbnail.link}</a>`;
257
- contentArray.push(`<div>${thumbnailLink}</div>`);
258
- }
259
-
260
- // Dataset ID
261
- if (imageThumbnail.id) {
262
- let datasetIdContent = `<div><strong>Dataset ID:</strong></div>`;
263
- datasetIdContent += `\n`;
264
- datasetIdContent += `${imageThumbnail.id}`;
265
- contentArray.push(`<div>${datasetIdContent}</div>`);
266
- }
267
-
268
- // Dataset URL
269
- if (imageThumbnail.id) {
270
- const datasetURL = this.datasetURL(imageThumbnail.id);
271
- let dataLocationContent = `<div><strong>Dataset URL:</strong></div>`;
272
- dataLocationContent += `\n`;
273
- dataLocationContent += `<a href="${datasetURL}">${datasetURL}</a>`;
274
- contentArray.push(`<div>${dataLocationContent}</div>`);
275
- }
276
-
277
- // Dataset version
278
- if (imageThumbnail.version) {
279
- let versionContent = `<div><strong>Dataset version:</strong></div>`;
280
- versionContent += `\n`;
281
- versionContent += `${imageThumbnail.version}`;
282
- contentArray.push(`<div>${versionContent}</div>`);
283
- }
284
-
285
- const copyContent = contentArray.join('\n\n<br>');
286
- return copyContent;
287
- },
288
- },
289
- }
290
- </script>
291
-
292
- <style lang="scss" scoped>
293
- .image-thumbnails-container {
294
- font-size: 14px;
295
- text-align: left;
296
- line-height: 1.5em;
297
- font-family: $font-family;
298
- font-weight: 400;
299
- background-color: #f7faff;
300
- border-left: 1px solid var(--el-border-color);
301
- border-top: 1px solid var(--el-border-color);
302
- display: flex;
303
- flex-direction: column;
304
- height: calc(100% - 30px); // minus tabs height
305
- z-index: 1;
306
- }
307
-
308
- .toolbar {
309
- display: flex;
310
- flex-direction: row;
311
- align-items: center;
312
- justify-content: space-between;
313
- padding: 1rem;
314
- gap: 1rem;
315
- background-color: #f7faff;
316
- position: sticky;
317
- top: 0;
318
- z-index: 1;
319
- }
320
-
321
- .filters {
322
- display: flex;
323
- flex-direction: row;
324
- flex-wrap: wrap;
325
- gap: 5px;
326
-
327
- .tag {
328
- cursor: pointer;
329
- }
330
- }
331
-
332
- .view-selector .el-select {
333
- width: 100px;
334
- font-family: $font-family;
335
- }
336
-
337
- .gallery-container,
338
- .dataset-card-container {
339
- margin: 1rem;
340
- margin-top: 0;
341
- padding: 1rem;
342
- flex-grow: 1;
343
- overflow-y: auto;
344
- scrollbar-width: thin;
345
- box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.06);
346
- border: solid 1px #e4e7ed;
347
- background-color: #ffffff;
348
- border-radius: var(--el-border-radius-base);
349
- }
350
-
351
- .gallery-container {
352
- :deep(.gallery) {
353
- .gallery-strip {
354
- padding: 1rem 0;
355
- }
356
-
357
- > div {
358
- min-height: max-content !important;
359
- }
360
- }
361
- }
362
-
363
- .dataset-card-container {
364
- display: flex;
365
- flex-direction: column;
366
- gap: 1.5rem;
367
- }
368
-
369
- .dataset-card {
370
- position: relative;
371
-
372
- + .dataset-card {
373
- padding-top: 1.5rem;
374
- border-top: 1px solid var(--el-border-color);
375
- }
376
- }
377
-
378
- .card {
379
- position: relative;
380
- display: flex;
381
- gap: 1.5rem;
382
- }
383
-
384
- .card-left {
385
- flex: 1;
386
- }
387
-
388
- .card-right {
389
- flex: 1.3;
390
- padding-left: 6px;
391
- display: flex;
392
- flex-direction: column;
393
- gap: 1rem;
394
- }
395
-
396
- .card-image {
397
- display: block;
398
- text-decoration: none;
399
- outline: none;
400
-
401
- .el-image {
402
- display: block;
403
- width: 200px;
404
- height: 150px;
405
-
406
- :deep(img) {
407
- aspect-ratio: 4/3;
408
- object-fit: cover;
409
- }
410
- }
411
-
412
- .image-slot {
413
- display: flex;
414
- justify-content: center;
415
- align-items: center;
416
- width: 100%;
417
- height: 100%;
418
- background: var(--el-fill-color-light);
419
- color: var(--el-text-color-secondary);
420
- font-size: 14px;
421
- }
422
- }
423
-
424
- .title {
425
- font-family: $font-family;
426
- font-size: 14px;
427
- font-weight: bold;
428
- font-stretch: normal;
429
- font-style: normal;
430
- line-height: 1.5;
431
- letter-spacing: 1.05px;
432
- color: #484848;
433
- }
434
-
435
- .details {
436
- font-family: $font-family;
437
- font-size: 14px;
438
- font-weight: normal;
439
- font-stretch: normal;
440
- font-style: normal;
441
- line-height: 1.5;
442
- letter-spacing: 1.05px;
443
- color: #484848;
444
- }
445
-
446
- .active-tag {
447
- background-color: $app-primary-color;
448
- color: #fff;
449
- }
450
-
451
- .button {
452
- margin-left: 0px !important;
453
- margin-top: 0px !important;
454
- font-size: 14px !important;
455
- letter-spacing: initial;
456
- background-color: $app-primary-color;
457
- color: #fff;
458
-
459
- & + .button {
460
- margin-top: 10px !important;
461
- }
462
- &:hover {
463
- color: #fff !important;
464
- background: #ac76c5 !important;
465
- border: 1px solid #ac76c5 !important;
466
- }
467
- }
468
-
469
- .card-button-link {
470
- text-decoration: none;
471
- }
472
-
473
- .float-button-container {
474
- position: absolute;
475
- bottom: 0;
476
- right: 0;
477
- opacity: 0;
478
- visibility: hidden;
479
-
480
- .dataset-card:hover & {
481
- opacity: 1;
482
- visibility: visible;
483
- }
484
- }
485
- </style>
486
-
487
- <style lang="scss">
488
- .view-selector-select-popper {
489
- font-family: $font-family;
490
- font-size: 14px;
491
- color: #292b66;
492
-
493
- .el-select-dropdown__item.is-selected {
494
- color: $app-primary-color;
495
- }
496
- }
497
- </style>
@@ -1,41 +0,0 @@
1
- [
2
- {
3
- "thumbnail": "http://localhost:8000//thumbnail/21567",
4
- "resource": "derivative/sub-Pirt-1A/sam-7/2020-01-06_11.26.19_ AAV DRG inj.- Pirt Cre 1A_DRG T2b.jpx",
5
- "id": "353",
6
- "title": "2020-01-06_11.26.19_ AAV DRG inj.- Pirt Cre 1A_DRG T2b.jpx",
7
- "type": "Image",
8
- "link": "http://localhost:8000//thumbnail/21567",
9
- "mimetype": "image/jpx",
10
- "species": [
11
- "Mouse"
12
- ],
13
- "version": "1"
14
- },
15
- {
16
- "thumbnail": "http://localhost:8000//thumbnail/21568",
17
- "resource": "derivative/sub-Pirt-1A/sam-7/2020-01-06_11.36.02_FusionStitcher AAV DRG inj.- Pirt Cre 1A_DRG T4ab.jpx",
18
- "id": "353",
19
- "title": "2020-01-06_11.36.02_FusionStitcher AAV DRG inj.- Pirt Cre 1A_DRG T4ab.jpx",
20
- "type": "Image",
21
- "link": "http://localhost:8000//thumbnail/21568",
22
- "mimetype": "image/jpx",
23
- "species": [
24
- "Mouse"
25
- ],
26
- "version": "1"
27
- },
28
- {
29
- "thumbnail": "http://localhost:8000//thumbnail/21569",
30
- "resource": "derivative/sub-Pirt-2A/2020-01-13_11.16.35_ssxxs_Kim_FusionStitcher vagal ganglia.jpx",
31
- "id": "353",
32
- "title": "2020-01-13_11.16.35_ssxxs_Kim_FusionStitcher vagal ganglia.jpx",
33
- "type": "Image",
34
- "link": "http://localhost:8000//thumbnail/21569",
35
- "mimetype": "image/jpx",
36
- "species": [
37
- "Mouse"
38
- ],
39
- "version": "1"
40
- }
41
- ]