@abi-software/mapintegratedvuer 0.7.2-vue3.0-alpha.0 → 1.0.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/LICENSE +201 -201
- package/README.md +150 -150
- package/assets/styleguide.css +19 -19
- package/cypress.config.js +23 -23
- package/dist/index.html +17 -17
- package/dist/mapintegratedvuer.js +74289 -73840
- package/dist/mapintegratedvuer.umd.cjs +878 -515
- package/dist/style.css +1 -1
- package/package.json +134 -135
- package/public/index.html +17 -17
- package/reporter-config.json +9 -9
- package/src/App.vue +245 -245
- package/src/assets/_variables.scss +43 -43
- package/src/assets/fonts/mapicon-species.eot +0 -0
- package/src/assets/fonts/mapicon-species.ttf +0 -0
- package/src/assets/fonts/mapicon-species.woff +0 -0
- package/src/assets/header-icon.scss +67 -67
- package/src/assets/mapicon-species-style.css +41 -41
- package/src/assets/styles.scss +9 -9
- package/src/components/ContentBar.vue +376 -376
- package/src/components/ContentVuer.vue +217 -217
- package/src/components/ContextCard.vue +385 -385
- package/src/components/ContextHelp.vue +73 -73
- package/src/components/CustomSplitter.vue +151 -151
- package/src/components/DatasetHeader.vue +97 -97
- package/src/components/DialogToolbarContent.vue +464 -464
- package/src/components/EventBus.js +3 -3
- package/src/components/FlatmapContextCard.vue +134 -134
- package/src/components/MapContent.vue +328 -333
- package/src/components/ResizeSensor.vue +47 -47
- package/src/components/SearchControls.vue +115 -115
- package/src/components/SimulatedData.js +721 -721
- package/src/components/SplitDialog.vue +287 -287
- package/src/components/SplitFlow.vue +414 -414
- package/src/components/index.js +7 -7
- package/src/components/markerZoomLevelsHardCoded.js +255 -255
- package/src/components/scripts/utilities.js +173 -173
- package/src/components/viewers/Flatmap.vue +145 -145
- package/src/components/viewers/Iframe.vue +31 -31
- package/src/components/viewers/MultiFlatmap.vue +384 -384
- package/src/components/viewers/Plot.vue +23 -23
- package/src/components/viewers/Scaffold.vue +198 -198
- package/src/components/viewers/Simulation.vue +21 -21
- package/src/icons/yellowstar.js +1 -1
- package/src/main.js +31 -31
- package/src/mixins/ContentMixin.js +438 -438
- package/src/mixins/DynamicMarkerMixin.js +88 -88
- package/src/mixins/S3Bucket.vue +37 -37
- package/src/stores/entries.js +40 -40
- package/src/stores/index.js +23 -23
- package/src/stores/settings.js +144 -144
- package/src/stores/splitFlow.js +523 -523
- package/static.json +7 -7
- package/vite.config.js +70 -70
- package/vite.static-build.js +12 -12
- package/vitest.workspace.js +3 -3
- package/vuese-generator.js +65 -65
- package/assets/gazelle-icons-no-background.css +0 -32
- package/dist/matterport.pdf +0 -0
- package/dist/test.txt +0 -0
- package/public/matterport.pdf +0 -0
- package/public/test.txt +0 -0
- package/q.json +0 -690
- package/src/mixins/RetrieveContextCardMixin.js +0 -82
- package/tsconfig.json +0 -19
@@ -1,385 +1,385 @@
|
|
1
|
-
<template>
|
2
|
-
<div class="context-card-container" ref="container">
|
3
|
-
<div v-show="showContextCard">
|
4
|
-
<div v-if="showDetails && Object.keys(contextData).length !== 0" v-loading="loading" class="context-card" >
|
5
|
-
<div class="card-left">
|
6
|
-
<img :src="banner" class="context-image">
|
7
|
-
</div>
|
8
|
-
<div class="card-right scrollbar">
|
9
|
-
<div style="margin-right: 8px;">
|
10
|
-
<div class="title">{{contextData.heading}}</div>
|
11
|
-
<div v-html="parseMarkdown(contextData.description)"/>
|
12
|
-
<br/>
|
13
|
-
|
14
|
-
<!-- Show sampeles and views seperately if they do not match -->
|
15
|
-
<template v-if="!samplesUnderViews">
|
16
|
-
<div v-if="contextData.views && contextData.views.length > 0" class="subtitle">Scaffold Views</div>
|
17
|
-
<template v-for="(view, i) in contextData.views" :key="i+'_1'">
|
18
|
-
<div @click="openViewFile(view)" class="context-card-view">
|
19
|
-
<img class="view-image" :src="getFileFromPath(view.thumbnail)">
|
20
|
-
<div class="view-description">{{view.description}}</div>
|
21
|
-
</div>
|
22
|
-
<div class="padding"/>
|
23
|
-
</template>
|
24
|
-
<div style="margin-bottom: 16px;"/>
|
25
|
-
<div v-if="contextData.samples && contextData.samples.length > 0" class="subtitle">Samples on Scaffold</div>
|
26
|
-
<template v-for="(sample, i) in contextData.samples" :key="i+'_3'">
|
27
|
-
<span class="context-card-item cursor-pointer" @click="toggleSampleDetails(i)">
|
28
|
-
<div v-bind:key="i+'_6'" style="display: flex">
|
29
|
-
<div v-if="sample.color" class="color-box" :style="'background-color:'+ sample.color"></div>
|
30
|
-
<img class="key-image" v-else-if="sample.thumbnail" :src="getFileFromPath(sample.thumbnail)">
|
31
|
-
{{sample.heading}}
|
32
|
-
<i class="el-icon-warning-outline info"></i>
|
33
|
-
</div>
|
34
|
-
</span>
|
35
|
-
<div v-if="sampleDetails[i]" v-html="sample.description"/>
|
36
|
-
<a v-if="sampleDetails[i] && sample.path" :href="generateFileLink(sample)" target="_blank">View Source</a>
|
37
|
-
<div class="padding"/>
|
38
|
-
</template>
|
39
|
-
</template>
|
40
|
-
|
41
|
-
<!-- Show samples under views if the ids match -->
|
42
|
-
<template v-else>
|
43
|
-
<div v-if="contextData.views && contextData.views.length > 0" class="subtitle">Scaffold Views</div>
|
44
|
-
<template v-for="(view, i) in contextData.views" :key="i+'_1'">
|
45
|
-
<span @click="viewClicked(view, i)" class="context-card-view">
|
46
|
-
<img class="view-image" :src="getFileFromPath(view.thumbnail)"/>
|
47
|
-
<div class="view-description">{{view.description}}<i class="el-icon-warning-outline info"></i> </div>
|
48
|
-
</span>
|
49
|
-
<div v-if="sampleDetails[i]" v-html="samplesMatching(view.id).description"/>
|
50
|
-
<a v-bind:key="i+'_5'" v-if="sampleDetails[i] && samplesMatching(view.id).path" :href="generateFileLink(samplesMatching(view.id))" target="_blank">View Source</a>
|
51
|
-
<div class="padding"/>
|
52
|
-
|
53
|
-
<!-- Extra padding if sample details is open -->
|
54
|
-
<div v-if="sampleDetails[i]" class="padding"/>
|
55
|
-
</template>
|
56
|
-
</template>
|
57
|
-
</div>
|
58
|
-
</div>
|
59
|
-
</div>
|
60
|
-
</div>
|
61
|
-
</div>
|
62
|
-
</template>
|
63
|
-
|
64
|
-
|
65
|
-
<script>
|
66
|
-
/* eslint-disable no-alert, no-console */
|
67
|
-
|
68
|
-
//provide the s3Bucket related methods and data.
|
69
|
-
import S3Bucket from "../mixins/S3Bucket.vue";
|
70
|
-
|
71
|
-
import { marked } from 'marked'
|
72
|
-
import xss from 'xss'
|
73
|
-
|
74
|
-
const addFilesToPathIfMissing = function(path){
|
75
|
-
if (!path.includes('files')){
|
76
|
-
return 'files/' + path
|
77
|
-
} else {
|
78
|
-
return path
|
79
|
-
}
|
80
|
-
}
|
81
|
-
|
82
|
-
const convertBackslashToForwardSlash = function(path){
|
83
|
-
path = path.replaceAll('\\','/')
|
84
|
-
path = path.replaceAll('\\\\', '/')
|
85
|
-
return path
|
86
|
-
}
|
87
|
-
|
88
|
-
// const switchPathToDirectory = function(path){
|
89
|
-
// let newPath = path.split('/')
|
90
|
-
// newPath.pop()
|
91
|
-
// return newPath.join('/')
|
92
|
-
// }
|
93
|
-
|
94
|
-
|
95
|
-
export default {
|
96
|
-
name: "contextCard",
|
97
|
-
mixins: [S3Bucket],
|
98
|
-
props: {
|
99
|
-
/**
|
100
|
-
* Object containing information for
|
101
|
-
* the required viewing.
|
102
|
-
*/
|
103
|
-
entry: Object,
|
104
|
-
envVars: Object,
|
105
|
-
},
|
106
|
-
data: function () {
|
107
|
-
return {
|
108
|
-
contextData: {},
|
109
|
-
showDetails: true,
|
110
|
-
showContextCard: true,
|
111
|
-
sampleDetails: {},
|
112
|
-
loading: false
|
113
|
-
};
|
114
|
-
},
|
115
|
-
watch: {
|
116
|
-
'entry.contextCardUrl': {
|
117
|
-
handler(val){
|
118
|
-
if (val) {
|
119
|
-
// used for hardcoding data
|
120
|
-
if (val === true){
|
121
|
-
console.error('asked for hardcoding but none provided')
|
122
|
-
} else {
|
123
|
-
this.getContextFile(val)
|
124
|
-
this.showContextCard = true
|
125
|
-
}
|
126
|
-
} else {
|
127
|
-
this.showContextCard = false
|
128
|
-
}
|
129
|
-
},
|
130
|
-
immediate: true
|
131
|
-
},
|
132
|
-
'entry.s3uri': {
|
133
|
-
handler(val){
|
134
|
-
this.updateS3Bucket(val);
|
135
|
-
},
|
136
|
-
immediate: true
|
137
|
-
}
|
138
|
-
},
|
139
|
-
computed: {
|
140
|
-
samplesUnderViews: function(){
|
141
|
-
if (this.contextData){
|
142
|
-
if (this.contextData.samplesUnderViews){
|
143
|
-
return true
|
144
|
-
} else {
|
145
|
-
let viewId = this.contextData.views.map(v=>v.id)
|
146
|
-
let samplesView = this.contextData.samples.map(s=>s.view)
|
147
|
-
|
148
|
-
// get matching values
|
149
|
-
let matching = viewId.filter(v=>samplesView.includes(v))
|
150
|
-
|
151
|
-
// check all arrays have the same length (which means all values are in all three)
|
152
|
-
if ( viewId.length === matching.length && matching.length === samplesView.length){
|
153
|
-
return true
|
154
|
-
}
|
155
|
-
return false
|
156
|
-
}
|
157
|
-
}
|
158
|
-
else return false
|
159
|
-
},
|
160
|
-
banner: function(){
|
161
|
-
if (this.contextData.banner){
|
162
|
-
return this.getFileFromPath(this.contextData.banner)
|
163
|
-
} else if (this.contextData && this.contextData.views && this.contextData.views.length > 0) {
|
164
|
-
if(this.contextData.views[0].thumbnail){
|
165
|
-
return this.getFileFromPath(this.contextData.views[0].thumbnail)
|
166
|
-
}
|
167
|
-
}
|
168
|
-
return this.entry.banner
|
169
|
-
}
|
170
|
-
},
|
171
|
-
methods: {
|
172
|
-
samplesMatching: function(viewId){
|
173
|
-
if (this.contextData && this.contextData.samples){
|
174
|
-
return this.contextData.samples.filter(s=>s.view == viewId)[0]
|
175
|
-
}
|
176
|
-
else return []
|
177
|
-
},
|
178
|
-
viewClicked: function(view, i){
|
179
|
-
this.openViewFile(view)
|
180
|
-
this.toggleSampleDetails(i)
|
181
|
-
},
|
182
|
-
getContextFile: function (contextFileUrl) {
|
183
|
-
this.loading = true
|
184
|
-
fetch(contextFileUrl)
|
185
|
-
.then((response) =>{
|
186
|
-
if (!response.ok){
|
187
|
-
throw Error(response.statusText)
|
188
|
-
} else {
|
189
|
-
return response.json()
|
190
|
-
}
|
191
|
-
})
|
192
|
-
.then((data) => {
|
193
|
-
this.contextData = data
|
194
|
-
this.loading = false
|
195
|
-
this.addDiscoverIdsToContextData()
|
196
|
-
})
|
197
|
-
.catch((err) => {
|
198
|
-
//set defaults if we hit an error
|
199
|
-
console.error('caught error!', err)
|
200
|
-
this.discoverId = undefined
|
201
|
-
this.loading = false
|
202
|
-
});
|
203
|
-
},
|
204
|
-
removeDoubleFilesPath: function(path){
|
205
|
-
if (path) {
|
206
|
-
if (path.includes('files/')){
|
207
|
-
return path.replace('files/', '')
|
208
|
-
} else if (path.includes('files\\')) {
|
209
|
-
return path.replace('files\\', '')
|
210
|
-
} else {
|
211
|
-
return path
|
212
|
-
}
|
213
|
-
}
|
214
|
-
},
|
215
|
-
toggleSampleDetails: function(i){
|
216
|
-
if (this.sampleDetails[i] === undefined){
|
217
|
-
this.sampleDetails[i] = true;
|
218
|
-
} else {
|
219
|
-
this.sampleDetails[i] = !this.sampleDetails[i];
|
220
|
-
}
|
221
|
-
},
|
222
|
-
getFileFromPath: function(path){
|
223
|
-
// for hardcoded data
|
224
|
-
if(this.entry.contextCardUrl === true){
|
225
|
-
return path
|
226
|
-
}
|
227
|
-
path = this.removeDoubleFilesPath(path)
|
228
|
-
return `${this.envVars.API_LOCATION}s3-resource/${this.getS3Prefix()}files/${path}${this.getS3Args()}`
|
229
|
-
},
|
230
|
-
// This is used later when generateing links to the resource on sparc.science (see generateFileLink)
|
231
|
-
addDiscoverIdsToContextData(){
|
232
|
-
this.contextData.samples.forEach((sample, i)=>{
|
233
|
-
if (sample && sample.doi && sample.doi !== ""){
|
234
|
-
fetch(`${this.envVars.PENNSIEVE_API_LOCATION}/discover/datasets/doi/${this.splitDoiFromUrl(sample.doi)}`)
|
235
|
-
.then((response) => response.json())
|
236
|
-
.then((data) => {
|
237
|
-
this.contextData.samples[i].discoverId = data.id
|
238
|
-
this.contextData.samples[i].version = data.version
|
239
|
-
})
|
240
|
-
} else {
|
241
|
-
this.contextData.samples[i].discoverId = this.entry.discoverId
|
242
|
-
this.contextData.samples[i].version = this.entry.version
|
243
|
-
}
|
244
|
-
})
|
245
|
-
},
|
246
|
-
processPathForUrl(path){
|
247
|
-
path = convertBackslashToForwardSlash(path)
|
248
|
-
path = addFilesToPathIfMissing(path)
|
249
|
-
return encodeURIComponent(path)
|
250
|
-
},
|
251
|
-
splitDoiFromUrl(url){
|
252
|
-
return url.split('https://doi.org/').pop()
|
253
|
-
},
|
254
|
-
generateFileLink(sample){
|
255
|
-
const path = this.processPathForUrl(sample.path);
|
256
|
-
let link = `${this.envVars.ROOT_URL}/file/${sample.discoverId}/${sample.version}` + '?path=';
|
257
|
-
link = link + path;
|
258
|
-
return link;
|
259
|
-
},
|
260
|
-
parseMarkdown(markdown){
|
261
|
-
const returned_data = xss(marked.parse(markdown))
|
262
|
-
this.$emit('context-ready')
|
263
|
-
return returned_data
|
264
|
-
},
|
265
|
-
openViewFile: function(view){
|
266
|
-
// note that we assume that the view file is in the same directory as the scaffold (viewUrls take relative paths)
|
267
|
-
const viewUrl = this.getFileFromPath(view.path)
|
268
|
-
this.$emit("scaffold-view-clicked", viewUrl);
|
269
|
-
}
|
270
|
-
}
|
271
|
-
};
|
272
|
-
</script>
|
273
|
-
|
274
|
-
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
275
|
-
<style scoped lang="scss">
|
276
|
-
|
277
|
-
.hide{
|
278
|
-
color: #e4e7ed;
|
279
|
-
cursor: pointer;
|
280
|
-
}
|
281
|
-
|
282
|
-
.context-card-container {
|
283
|
-
width: 100%;
|
284
|
-
height: 100%;
|
285
|
-
display: flex;
|
286
|
-
justify-content: center;
|
287
|
-
align-items: center;
|
288
|
-
}
|
289
|
-
|
290
|
-
.context-card{
|
291
|
-
background-color: white;
|
292
|
-
max-height: 10 50px;
|
293
|
-
font-size: 14px;
|
294
|
-
position: relative;
|
295
|
-
display: flex;
|
296
|
-
width: 100%;
|
297
|
-
max-height: 258px;
|
298
|
-
}
|
299
|
-
|
300
|
-
.context-card-view{
|
301
|
-
cursor: pointer;
|
302
|
-
margin-bottom: 8px;
|
303
|
-
display: flex;
|
304
|
-
}
|
305
|
-
|
306
|
-
.view-image {
|
307
|
-
width: 34px;
|
308
|
-
height: 34px;
|
309
|
-
flex: 1;
|
310
|
-
}
|
311
|
-
|
312
|
-
.view-descriptions {
|
313
|
-
flex: 8;
|
314
|
-
}
|
315
|
-
|
316
|
-
.context-card :deep(.el-card__body) {
|
317
|
-
margin: 0px;
|
318
|
-
display: flex;
|
319
|
-
width: 516px;
|
320
|
-
}
|
321
|
-
|
322
|
-
.context-image{
|
323
|
-
width: 150px;
|
324
|
-
height: auto;
|
325
|
-
}
|
326
|
-
|
327
|
-
.color-box {
|
328
|
-
width: 16px;
|
329
|
-
height: 16px;
|
330
|
-
border: solid 1px $app-primary-color;
|
331
|
-
border-radius: 2px;
|
332
|
-
margin-right: 8px;
|
333
|
-
}
|
334
|
-
|
335
|
-
.card-left{
|
336
|
-
flex: 0.8
|
337
|
-
}
|
338
|
-
|
339
|
-
.card-right {
|
340
|
-
flex: 1.5;
|
341
|
-
word-break: normal !important;
|
342
|
-
overflow-y: scroll;
|
343
|
-
scrollbar-width: thin;
|
344
|
-
}
|
345
|
-
|
346
|
-
.cursor-pointer {
|
347
|
-
cursor: pointer;
|
348
|
-
}
|
349
|
-
|
350
|
-
.info{
|
351
|
-
transform: rotate(180deg);
|
352
|
-
color: $app-primary-color;
|
353
|
-
margin-left: 8px;
|
354
|
-
}
|
355
|
-
|
356
|
-
.padding {
|
357
|
-
margin-bottom: 8px;
|
358
|
-
}
|
359
|
-
|
360
|
-
.title{
|
361
|
-
font-weight: bold;
|
362
|
-
}
|
363
|
-
|
364
|
-
.subtitle{
|
365
|
-
font-weight: bold;
|
366
|
-
}
|
367
|
-
|
368
|
-
.scrollbar::-webkit-scrollbar-track {
|
369
|
-
border-radius: 10px;
|
370
|
-
background-color: #f5f5f5;
|
371
|
-
}
|
372
|
-
|
373
|
-
.scrollbar::-webkit-scrollbar {
|
374
|
-
width: 12px;
|
375
|
-
right: -12px;
|
376
|
-
background-color: #f5f5f5;
|
377
|
-
}
|
378
|
-
|
379
|
-
.scrollbar::-webkit-scrollbar-thumb {
|
380
|
-
border-radius: 4px;
|
381
|
-
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.06);
|
382
|
-
background-color: #979797;
|
383
|
-
}
|
384
|
-
|
385
|
-
</style>
|
1
|
+
<template>
|
2
|
+
<div class="context-card-container" ref="container">
|
3
|
+
<div v-show="showContextCard">
|
4
|
+
<div v-if="showDetails && Object.keys(contextData).length !== 0" v-loading="loading" class="context-card" >
|
5
|
+
<div class="card-left">
|
6
|
+
<img :src="banner" class="context-image">
|
7
|
+
</div>
|
8
|
+
<div class="card-right scrollbar">
|
9
|
+
<div style="margin-right: 8px;">
|
10
|
+
<div class="title">{{contextData.heading}}</div>
|
11
|
+
<div v-html="parseMarkdown(contextData.description)"/>
|
12
|
+
<br/>
|
13
|
+
|
14
|
+
<!-- Show sampeles and views seperately if they do not match -->
|
15
|
+
<template v-if="!samplesUnderViews">
|
16
|
+
<div v-if="contextData.views && contextData.views.length > 0" class="subtitle">Scaffold Views</div>
|
17
|
+
<template v-for="(view, i) in contextData.views" :key="i+'_1'">
|
18
|
+
<div @click="openViewFile(view)" class="context-card-view">
|
19
|
+
<img class="view-image" :src="getFileFromPath(view.thumbnail)">
|
20
|
+
<div class="view-description">{{view.description}}</div>
|
21
|
+
</div>
|
22
|
+
<div class="padding"/>
|
23
|
+
</template>
|
24
|
+
<div style="margin-bottom: 16px;"/>
|
25
|
+
<div v-if="contextData.samples && contextData.samples.length > 0" class="subtitle">Samples on Scaffold</div>
|
26
|
+
<template v-for="(sample, i) in contextData.samples" :key="i+'_3'">
|
27
|
+
<span class="context-card-item cursor-pointer" @click="toggleSampleDetails(i)">
|
28
|
+
<div v-bind:key="i+'_6'" style="display: flex">
|
29
|
+
<div v-if="sample.color" class="color-box" :style="'background-color:'+ sample.color"></div>
|
30
|
+
<img class="key-image" v-else-if="sample.thumbnail" :src="getFileFromPath(sample.thumbnail)">
|
31
|
+
{{sample.heading}}
|
32
|
+
<i class="el-icon-warning-outline info"></i>
|
33
|
+
</div>
|
34
|
+
</span>
|
35
|
+
<div v-if="sampleDetails[i]" v-html="sample.description"/>
|
36
|
+
<a v-if="sampleDetails[i] && sample.path" :href="generateFileLink(sample)" target="_blank">View Source</a>
|
37
|
+
<div class="padding"/>
|
38
|
+
</template>
|
39
|
+
</template>
|
40
|
+
|
41
|
+
<!-- Show samples under views if the ids match -->
|
42
|
+
<template v-else>
|
43
|
+
<div v-if="contextData.views && contextData.views.length > 0" class="subtitle">Scaffold Views</div>
|
44
|
+
<template v-for="(view, i) in contextData.views" :key="i+'_1'">
|
45
|
+
<span @click="viewClicked(view, i)" class="context-card-view">
|
46
|
+
<img class="view-image" :src="getFileFromPath(view.thumbnail)"/>
|
47
|
+
<div class="view-description">{{view.description}}<i class="el-icon-warning-outline info"></i> </div>
|
48
|
+
</span>
|
49
|
+
<div v-if="sampleDetails[i]" v-html="samplesMatching(view.id).description"/>
|
50
|
+
<a v-bind:key="i+'_5'" v-if="sampleDetails[i] && samplesMatching(view.id).path" :href="generateFileLink(samplesMatching(view.id))" target="_blank">View Source</a>
|
51
|
+
<div class="padding"/>
|
52
|
+
|
53
|
+
<!-- Extra padding if sample details is open -->
|
54
|
+
<div v-if="sampleDetails[i]" class="padding"/>
|
55
|
+
</template>
|
56
|
+
</template>
|
57
|
+
</div>
|
58
|
+
</div>
|
59
|
+
</div>
|
60
|
+
</div>
|
61
|
+
</div>
|
62
|
+
</template>
|
63
|
+
|
64
|
+
|
65
|
+
<script>
|
66
|
+
/* eslint-disable no-alert, no-console */
|
67
|
+
|
68
|
+
//provide the s3Bucket related methods and data.
|
69
|
+
import S3Bucket from "../mixins/S3Bucket.vue";
|
70
|
+
|
71
|
+
import { marked } from 'marked'
|
72
|
+
import xss from 'xss'
|
73
|
+
|
74
|
+
const addFilesToPathIfMissing = function(path){
|
75
|
+
if (!path.includes('files')){
|
76
|
+
return 'files/' + path
|
77
|
+
} else {
|
78
|
+
return path
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
82
|
+
const convertBackslashToForwardSlash = function(path){
|
83
|
+
path = path.replaceAll('\\','/')
|
84
|
+
path = path.replaceAll('\\\\', '/')
|
85
|
+
return path
|
86
|
+
}
|
87
|
+
|
88
|
+
// const switchPathToDirectory = function(path){
|
89
|
+
// let newPath = path.split('/')
|
90
|
+
// newPath.pop()
|
91
|
+
// return newPath.join('/')
|
92
|
+
// }
|
93
|
+
|
94
|
+
|
95
|
+
export default {
|
96
|
+
name: "contextCard",
|
97
|
+
mixins: [S3Bucket],
|
98
|
+
props: {
|
99
|
+
/**
|
100
|
+
* Object containing information for
|
101
|
+
* the required viewing.
|
102
|
+
*/
|
103
|
+
entry: Object,
|
104
|
+
envVars: Object,
|
105
|
+
},
|
106
|
+
data: function () {
|
107
|
+
return {
|
108
|
+
contextData: {},
|
109
|
+
showDetails: true,
|
110
|
+
showContextCard: true,
|
111
|
+
sampleDetails: {},
|
112
|
+
loading: false
|
113
|
+
};
|
114
|
+
},
|
115
|
+
watch: {
|
116
|
+
'entry.contextCardUrl': {
|
117
|
+
handler(val){
|
118
|
+
if (val) {
|
119
|
+
// used for hardcoding data
|
120
|
+
if (val === true){
|
121
|
+
console.error('asked for hardcoding but none provided')
|
122
|
+
} else {
|
123
|
+
this.getContextFile(val)
|
124
|
+
this.showContextCard = true
|
125
|
+
}
|
126
|
+
} else {
|
127
|
+
this.showContextCard = false
|
128
|
+
}
|
129
|
+
},
|
130
|
+
immediate: true
|
131
|
+
},
|
132
|
+
'entry.s3uri': {
|
133
|
+
handler(val){
|
134
|
+
this.updateS3Bucket(val);
|
135
|
+
},
|
136
|
+
immediate: true
|
137
|
+
}
|
138
|
+
},
|
139
|
+
computed: {
|
140
|
+
samplesUnderViews: function(){
|
141
|
+
if (this.contextData){
|
142
|
+
if (this.contextData.samplesUnderViews){
|
143
|
+
return true
|
144
|
+
} else {
|
145
|
+
let viewId = this.contextData.views.map(v=>v.id)
|
146
|
+
let samplesView = this.contextData.samples.map(s=>s.view)
|
147
|
+
|
148
|
+
// get matching values
|
149
|
+
let matching = viewId.filter(v=>samplesView.includes(v))
|
150
|
+
|
151
|
+
// check all arrays have the same length (which means all values are in all three)
|
152
|
+
if ( viewId.length === matching.length && matching.length === samplesView.length){
|
153
|
+
return true
|
154
|
+
}
|
155
|
+
return false
|
156
|
+
}
|
157
|
+
}
|
158
|
+
else return false
|
159
|
+
},
|
160
|
+
banner: function(){
|
161
|
+
if (this.contextData.banner){
|
162
|
+
return this.getFileFromPath(this.contextData.banner)
|
163
|
+
} else if (this.contextData && this.contextData.views && this.contextData.views.length > 0) {
|
164
|
+
if(this.contextData.views[0].thumbnail){
|
165
|
+
return this.getFileFromPath(this.contextData.views[0].thumbnail)
|
166
|
+
}
|
167
|
+
}
|
168
|
+
return this.entry.banner
|
169
|
+
}
|
170
|
+
},
|
171
|
+
methods: {
|
172
|
+
samplesMatching: function(viewId){
|
173
|
+
if (this.contextData && this.contextData.samples){
|
174
|
+
return this.contextData.samples.filter(s=>s.view == viewId)[0]
|
175
|
+
}
|
176
|
+
else return []
|
177
|
+
},
|
178
|
+
viewClicked: function(view, i){
|
179
|
+
this.openViewFile(view)
|
180
|
+
this.toggleSampleDetails(i)
|
181
|
+
},
|
182
|
+
getContextFile: function (contextFileUrl) {
|
183
|
+
this.loading = true
|
184
|
+
fetch(contextFileUrl)
|
185
|
+
.then((response) =>{
|
186
|
+
if (!response.ok){
|
187
|
+
throw Error(response.statusText)
|
188
|
+
} else {
|
189
|
+
return response.json()
|
190
|
+
}
|
191
|
+
})
|
192
|
+
.then((data) => {
|
193
|
+
this.contextData = data
|
194
|
+
this.loading = false
|
195
|
+
this.addDiscoverIdsToContextData()
|
196
|
+
})
|
197
|
+
.catch((err) => {
|
198
|
+
//set defaults if we hit an error
|
199
|
+
console.error('caught error!', err)
|
200
|
+
this.discoverId = undefined
|
201
|
+
this.loading = false
|
202
|
+
});
|
203
|
+
},
|
204
|
+
removeDoubleFilesPath: function(path){
|
205
|
+
if (path) {
|
206
|
+
if (path.includes('files/')){
|
207
|
+
return path.replace('files/', '')
|
208
|
+
} else if (path.includes('files\\')) {
|
209
|
+
return path.replace('files\\', '')
|
210
|
+
} else {
|
211
|
+
return path
|
212
|
+
}
|
213
|
+
}
|
214
|
+
},
|
215
|
+
toggleSampleDetails: function(i){
|
216
|
+
if (this.sampleDetails[i] === undefined){
|
217
|
+
this.sampleDetails[i] = true;
|
218
|
+
} else {
|
219
|
+
this.sampleDetails[i] = !this.sampleDetails[i];
|
220
|
+
}
|
221
|
+
},
|
222
|
+
getFileFromPath: function(path){
|
223
|
+
// for hardcoded data
|
224
|
+
if(this.entry.contextCardUrl === true){
|
225
|
+
return path
|
226
|
+
}
|
227
|
+
path = this.removeDoubleFilesPath(path)
|
228
|
+
return `${this.envVars.API_LOCATION}s3-resource/${this.getS3Prefix()}files/${path}${this.getS3Args()}`
|
229
|
+
},
|
230
|
+
// This is used later when generateing links to the resource on sparc.science (see generateFileLink)
|
231
|
+
addDiscoverIdsToContextData(){
|
232
|
+
this.contextData.samples.forEach((sample, i)=>{
|
233
|
+
if (sample && sample.doi && sample.doi !== ""){
|
234
|
+
fetch(`${this.envVars.PENNSIEVE_API_LOCATION}/discover/datasets/doi/${this.splitDoiFromUrl(sample.doi)}`)
|
235
|
+
.then((response) => response.json())
|
236
|
+
.then((data) => {
|
237
|
+
this.contextData.samples[i].discoverId = data.id
|
238
|
+
this.contextData.samples[i].version = data.version
|
239
|
+
})
|
240
|
+
} else {
|
241
|
+
this.contextData.samples[i].discoverId = this.entry.discoverId
|
242
|
+
this.contextData.samples[i].version = this.entry.version
|
243
|
+
}
|
244
|
+
})
|
245
|
+
},
|
246
|
+
processPathForUrl(path){
|
247
|
+
path = convertBackslashToForwardSlash(path)
|
248
|
+
path = addFilesToPathIfMissing(path)
|
249
|
+
return encodeURIComponent(path)
|
250
|
+
},
|
251
|
+
splitDoiFromUrl(url){
|
252
|
+
return url.split('https://doi.org/').pop()
|
253
|
+
},
|
254
|
+
generateFileLink(sample){
|
255
|
+
const path = this.processPathForUrl(sample.path);
|
256
|
+
let link = `${this.envVars.ROOT_URL}/file/${sample.discoverId}/${sample.version}` + '?path=';
|
257
|
+
link = link + path;
|
258
|
+
return link;
|
259
|
+
},
|
260
|
+
parseMarkdown(markdown){
|
261
|
+
const returned_data = xss(marked.parse(markdown))
|
262
|
+
this.$emit('context-ready')
|
263
|
+
return returned_data
|
264
|
+
},
|
265
|
+
openViewFile: function(view){
|
266
|
+
// note that we assume that the view file is in the same directory as the scaffold (viewUrls take relative paths)
|
267
|
+
const viewUrl = this.getFileFromPath(view.path)
|
268
|
+
this.$emit("scaffold-view-clicked", viewUrl);
|
269
|
+
}
|
270
|
+
}
|
271
|
+
};
|
272
|
+
</script>
|
273
|
+
|
274
|
+
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
275
|
+
<style scoped lang="scss">
|
276
|
+
|
277
|
+
.hide{
|
278
|
+
color: #e4e7ed;
|
279
|
+
cursor: pointer;
|
280
|
+
}
|
281
|
+
|
282
|
+
.context-card-container {
|
283
|
+
width: 100%;
|
284
|
+
height: 100%;
|
285
|
+
display: flex;
|
286
|
+
justify-content: center;
|
287
|
+
align-items: center;
|
288
|
+
}
|
289
|
+
|
290
|
+
.context-card{
|
291
|
+
background-color: white;
|
292
|
+
max-height: 10 50px;
|
293
|
+
font-size: 14px;
|
294
|
+
position: relative;
|
295
|
+
display: flex;
|
296
|
+
width: 100%;
|
297
|
+
max-height: 258px;
|
298
|
+
}
|
299
|
+
|
300
|
+
.context-card-view{
|
301
|
+
cursor: pointer;
|
302
|
+
margin-bottom: 8px;
|
303
|
+
display: flex;
|
304
|
+
}
|
305
|
+
|
306
|
+
.view-image {
|
307
|
+
width: 34px;
|
308
|
+
height: 34px;
|
309
|
+
flex: 1;
|
310
|
+
}
|
311
|
+
|
312
|
+
.view-descriptions {
|
313
|
+
flex: 8;
|
314
|
+
}
|
315
|
+
|
316
|
+
.context-card :deep(.el-card__body) {
|
317
|
+
margin: 0px;
|
318
|
+
display: flex;
|
319
|
+
width: 516px;
|
320
|
+
}
|
321
|
+
|
322
|
+
.context-image{
|
323
|
+
width: 150px;
|
324
|
+
height: auto;
|
325
|
+
}
|
326
|
+
|
327
|
+
.color-box {
|
328
|
+
width: 16px;
|
329
|
+
height: 16px;
|
330
|
+
border: solid 1px $app-primary-color;
|
331
|
+
border-radius: 2px;
|
332
|
+
margin-right: 8px;
|
333
|
+
}
|
334
|
+
|
335
|
+
.card-left{
|
336
|
+
flex: 0.8
|
337
|
+
}
|
338
|
+
|
339
|
+
.card-right {
|
340
|
+
flex: 1.5;
|
341
|
+
word-break: normal !important;
|
342
|
+
overflow-y: scroll;
|
343
|
+
scrollbar-width: thin;
|
344
|
+
}
|
345
|
+
|
346
|
+
.cursor-pointer {
|
347
|
+
cursor: pointer;
|
348
|
+
}
|
349
|
+
|
350
|
+
.info{
|
351
|
+
transform: rotate(180deg);
|
352
|
+
color: $app-primary-color;
|
353
|
+
margin-left: 8px;
|
354
|
+
}
|
355
|
+
|
356
|
+
.padding {
|
357
|
+
margin-bottom: 8px;
|
358
|
+
}
|
359
|
+
|
360
|
+
.title{
|
361
|
+
font-weight: bold;
|
362
|
+
}
|
363
|
+
|
364
|
+
.subtitle{
|
365
|
+
font-weight: bold;
|
366
|
+
}
|
367
|
+
|
368
|
+
.scrollbar::-webkit-scrollbar-track {
|
369
|
+
border-radius: 10px;
|
370
|
+
background-color: #f5f5f5;
|
371
|
+
}
|
372
|
+
|
373
|
+
.scrollbar::-webkit-scrollbar {
|
374
|
+
width: 12px;
|
375
|
+
right: -12px;
|
376
|
+
background-color: #f5f5f5;
|
377
|
+
}
|
378
|
+
|
379
|
+
.scrollbar::-webkit-scrollbar-thumb {
|
380
|
+
border-radius: 4px;
|
381
|
+
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.06);
|
382
|
+
background-color: #979797;
|
383
|
+
}
|
384
|
+
|
385
|
+
</style>
|