@abi-software/mapintegratedvuer 1.1.0-beta.1 → 1.1.0-beta.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.
- package/package.json +3 -3
- package/src/components/ContentBar.vue +10 -15
- package/src/components/MapContent.vue +17 -2
- package/src/components/SplitFlow.vue +147 -2
- package/src/components/scripts/utilities.js +26 -2
- package/src/components/viewers/Flatmap.vue +31 -1
- package/src/components/viewers/MultiFlatmap.vue +61 -2
- package/src/mixins/ContentMixin.js +14 -0
- package/src/mixins/DynamicMarkerMixin.js +11 -1
- package/src/mixins/RetrieveContextCardMixin.js +83 -0
- package/src/services/tagging.js +28 -0
- package/src/stores/settings.js +4 -0
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@abi-software/mapintegratedvuer",
|
3
|
-
"version": "1.1.0-beta.
|
3
|
+
"version": "1.1.0-beta.2",
|
4
4
|
"license": "Apache-2.0",
|
5
5
|
"scripts": {
|
6
6
|
"serve": "vite --host --force",
|
@@ -49,9 +49,9 @@
|
|
49
49
|
],
|
50
50
|
"dependencies": {
|
51
51
|
"@abi-software/flatmapvuer": "^1.1.0-beta.2",
|
52
|
-
"@abi-software/map-side-bar": "2.0
|
52
|
+
"@abi-software/map-side-bar": "^2.2.0",
|
53
53
|
"@abi-software/plotvuer": "1.0.0",
|
54
|
-
"@abi-software/scaffoldvuer": "^1.1.0-beta.
|
54
|
+
"@abi-software/scaffoldvuer": "^1.1.0-beta.1",
|
55
55
|
"@abi-software/simulationvuer": "1.0.0",
|
56
56
|
"@abi-software/svg-sprite": "1.0.0",
|
57
57
|
"@element-plus/icons-vue": "^2.3.1",
|
@@ -22,15 +22,6 @@
|
|
22
22
|
</div>
|
23
23
|
</div>
|
24
24
|
<el-row class="icon-group">
|
25
|
-
<div v-show="contextCardEntry && contextCardVisible" class="hide" @click="contextCardVisible = false">
|
26
|
-
Hide information
|
27
|
-
<el-icon><el-icon-arrow-up /></el-icon>
|
28
|
-
</div>
|
29
|
-
<div v-show="contextCardEntry && !contextCardVisible" class="hide" @click="contextCardVisible = true">
|
30
|
-
Show information
|
31
|
-
<el-icon><el-icon-arrow-down /></el-icon>
|
32
|
-
</div>
|
33
|
-
|
34
25
|
<el-popover
|
35
26
|
placement="bottom"
|
36
27
|
:teleported="false"
|
@@ -58,12 +49,16 @@
|
|
58
49
|
/>
|
59
50
|
</template>
|
60
51
|
<template #reference>
|
61
|
-
<
|
62
|
-
class="
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
52
|
+
<div v-show="contextCardEntry">
|
53
|
+
<div v-show="contextCardVisible" class="hide" @click="contextCardVisible = false">
|
54
|
+
Hide information
|
55
|
+
<el-icon><el-icon-arrow-up /></el-icon>
|
56
|
+
</div>
|
57
|
+
<div v-show="!contextCardVisible" class="hide" @click="contextCardVisible = true">
|
58
|
+
Show information
|
59
|
+
<el-icon><el-icon-arrow-down /></el-icon>
|
60
|
+
</div>
|
61
|
+
</div>
|
67
62
|
</template>
|
68
63
|
</el-popover>
|
69
64
|
<el-popover class="tooltip" content="Close and remove" placement="bottom-end" :show-after="helpDelay"
|
@@ -19,6 +19,7 @@
|
|
19
19
|
|
20
20
|
<script>
|
21
21
|
/* eslint-disable no-alert, no-console */
|
22
|
+
import Tagging from '../services/tagging.js';
|
22
23
|
import SplitFlow from './SplitFlow.vue';
|
23
24
|
import EventBus from './EventBus';
|
24
25
|
import { mapStores } from 'pinia';
|
@@ -26,6 +27,7 @@ import { useSettingsStore } from '../stores/settings';
|
|
26
27
|
import { findSpeciesKey } from './scripts/utilities.js';
|
27
28
|
import { MapSvgSpriteColor} from '@abi-software/svg-sprite';
|
28
29
|
import { initialState } from "./scripts/utilities.js";
|
30
|
+
import RetrieveContextCardMixin from "../mixins/RetrieveContextCardMixin.js"
|
29
31
|
import {
|
30
32
|
ElLoading as Loading
|
31
33
|
} from "element-plus";
|
@@ -40,6 +42,7 @@ export default {
|
|
40
42
|
Loading,
|
41
43
|
SplitFlow,
|
42
44
|
},
|
45
|
+
mixins: [RetrieveContextCardMixin],
|
43
46
|
props: {
|
44
47
|
/**
|
45
48
|
* A link (URL) to share.
|
@@ -158,7 +161,7 @@ export default {
|
|
158
161
|
* instead change the current entry by setting the state.
|
159
162
|
* @arg state
|
160
163
|
*/
|
161
|
-
setCurrentEntry: function(state) {
|
164
|
+
setCurrentEntry: async function(state) {
|
162
165
|
if (state && state.type) {
|
163
166
|
if (state.type === "Scaffold" && state.url) {
|
164
167
|
//State for scaffold containing the following items:
|
@@ -167,7 +170,7 @@ export default {
|
|
167
170
|
// resource - the url to metadata
|
168
171
|
// state - state to restore (viewport)
|
169
172
|
// viewUrl - relative path of the view file to metadata
|
170
|
-
|
173
|
+
let newView = {
|
171
174
|
type: state.type,
|
172
175
|
label: state.label,
|
173
176
|
region: state.region,
|
@@ -175,6 +178,9 @@ export default {
|
|
175
178
|
state: state.state,
|
176
179
|
viewUrl: state.viewUrl
|
177
180
|
};
|
181
|
+
// Add content from scicrunch for the context card
|
182
|
+
const contextCardInfo = await this.retrieveContextCardFromUrl(state.url);
|
183
|
+
newView = {...newView, ...contextCardInfo};
|
178
184
|
this.$refs.flow.createNewEntry(newView);
|
179
185
|
} else if (state.type === "MultiFlatmap") {
|
180
186
|
//State for scaffold containing the following items:
|
@@ -246,6 +252,15 @@ export default {
|
|
246
252
|
* This event emit when the component is mounted.
|
247
253
|
*/
|
248
254
|
this.$emit("isReady");
|
255
|
+
|
256
|
+
// GA Tagging
|
257
|
+
// Page view tracking for maps' buttons click on portal
|
258
|
+
// category: AC | FC | WholeBody
|
259
|
+
Tagging.sendEvent({
|
260
|
+
'event': 'interaction_event',
|
261
|
+
'event_name': 'portal_maps_page_view',
|
262
|
+
'category': this.startingMap
|
263
|
+
});
|
249
264
|
},
|
250
265
|
},
|
251
266
|
computed: {
|
@@ -28,7 +28,9 @@
|
|
28
28
|
@actionClick="actionClick"
|
29
29
|
@tabClicked="tabClicked"
|
30
30
|
@search-changed="searchChanged($event)"
|
31
|
+
@hover-changed="hoverChanged($event)"
|
31
32
|
@contextUpdate="contextUpdate($event)"
|
33
|
+
@datalink-clicked="datalinkClicked($event)"
|
32
34
|
/>
|
33
35
|
<SplitDialog
|
34
36
|
:entries="entries"
|
@@ -42,12 +44,18 @@
|
|
42
44
|
|
43
45
|
<script>
|
44
46
|
/* eslint-disable no-alert, no-console */
|
47
|
+
import Tagging from '../services/tagging.js';
|
45
48
|
import DialogToolbarContent from "./DialogToolbarContent.vue";
|
46
49
|
import EventBus from "./EventBus";
|
47
50
|
import SplitDialog from "./SplitDialog.vue";
|
48
51
|
// import contextCards from './context-cards'
|
49
52
|
import { SideBar } from "@abi-software/map-side-bar";
|
50
|
-
import {
|
53
|
+
import {
|
54
|
+
capitalise,
|
55
|
+
getNewMapEntry,
|
56
|
+
initialDefaultState,
|
57
|
+
intersectArrays,
|
58
|
+
} from "./scripts/utilities.js";
|
51
59
|
import { mapStores } from 'pinia';
|
52
60
|
import { useEntriesStore } from '../stores/entries';
|
53
61
|
import { useSettingsStore } from '../stores/settings';
|
@@ -85,6 +93,9 @@ export default {
|
|
85
93
|
startUp: true,
|
86
94
|
search: '',
|
87
95
|
activeDockedId : 1,
|
96
|
+
filterTriggered: false,
|
97
|
+
availableFacets: [],
|
98
|
+
hoveredMarkerDelay: undefined,
|
88
99
|
}
|
89
100
|
},
|
90
101
|
watch: {
|
@@ -109,12 +120,34 @@ export default {
|
|
109
120
|
this.openSearch([action.filter], action.label);
|
110
121
|
} else {
|
111
122
|
this.openSearch([], action.term);
|
123
|
+
// GA Tagging
|
124
|
+
// Event tracking for map action search/filter data
|
125
|
+
const eventName = action.featuredDataset
|
126
|
+
? 'portal_maps_featured_dataset_search'
|
127
|
+
: 'portal_maps_action_search';
|
128
|
+
Tagging.sendEvent({
|
129
|
+
'event': 'interaction_event',
|
130
|
+
'event_name': eventName,
|
131
|
+
'category': action.term || 'filter',
|
132
|
+
'location': 'map_location_pin'
|
133
|
+
});
|
134
|
+
this.filterTriggered = true;
|
112
135
|
}
|
113
136
|
} else if (action.type == "URL") {
|
114
137
|
window.open(action.resource, "_blank");
|
115
138
|
} else if (action.type == "Facet") {
|
116
139
|
if (this.$refs.sideBar) {
|
117
140
|
this.$refs.sideBar.addFilter(action);
|
141
|
+
const { facet } = action;
|
142
|
+
// GA Tagging
|
143
|
+
// Event tracking for map action search/filter data
|
144
|
+
Tagging.sendEvent({
|
145
|
+
'event': 'interaction_event',
|
146
|
+
'event_name': 'portal_maps_action_filter',
|
147
|
+
'category': facet || 'filter',
|
148
|
+
'location': 'map_location_pin'
|
149
|
+
});
|
150
|
+
this.filterTriggered = true;
|
118
151
|
}
|
119
152
|
} else if (action.type == "Facets") {
|
120
153
|
const facets = [];
|
@@ -140,12 +173,51 @@ export default {
|
|
140
173
|
);
|
141
174
|
if (this.$refs.sideBar) {
|
142
175
|
this.$refs.sideBar.openSearch(facets, "");
|
176
|
+
|
177
|
+
const filterValuesArray = intersectArrays(this.availableFacets, action.labels);
|
178
|
+
const filterValues = filterValuesArray.join(', ');
|
179
|
+
// GA Tagging
|
180
|
+
// Event tracking for map action search/filter data
|
181
|
+
Tagging.sendEvent({
|
182
|
+
'event': 'interaction_event',
|
183
|
+
'event_name': 'portal_maps_action_filter',
|
184
|
+
'category': filterValues || 'filter',
|
185
|
+
'location': 'map_popup_button'
|
186
|
+
});
|
143
187
|
}
|
144
188
|
} else {
|
189
|
+
this.trackGalleryClick(action);
|
145
190
|
this.createNewEntry(action);
|
146
191
|
}
|
147
192
|
}
|
148
193
|
},
|
194
|
+
trackGalleryClick: function (action) {
|
195
|
+
const categoryValues = [];
|
196
|
+
const { label, type, datasetId, discoverId, resource } = action;
|
197
|
+
let filePath = '';
|
198
|
+
let id = datasetId ? datasetId : discoverId;
|
199
|
+
if (label) categoryValues.push(label);
|
200
|
+
if (type) categoryValues.push(type);
|
201
|
+
if (datasetId) categoryValues.push('(' + id + ')');
|
202
|
+
if (resource) {
|
203
|
+
if (type === "Plot") {
|
204
|
+
filePath = resource.dataSource.url;
|
205
|
+
} else {
|
206
|
+
filePath = typeof resource === 'string' ? resource : resource.share_link;
|
207
|
+
}
|
208
|
+
}
|
209
|
+
|
210
|
+
// GA Tagging
|
211
|
+
// Event tracking for map sidebar gallery click
|
212
|
+
Tagging.sendEvent({
|
213
|
+
'event': 'interaction_event',
|
214
|
+
'event_name': 'portal_maps_gallery_click',
|
215
|
+
'category': categoryValues.join(' '),
|
216
|
+
'location': 'map_sidebar_gallery',
|
217
|
+
'dataset_id': id ? id + '' : '', // change to string format
|
218
|
+
'file_path': filePath,
|
219
|
+
});
|
220
|
+
},
|
149
221
|
onDisplaySearch: function (payload) {
|
150
222
|
let searchFound = false;
|
151
223
|
//Search all active viewers when global callback is on
|
@@ -159,6 +231,15 @@ export default {
|
|
159
231
|
});
|
160
232
|
}
|
161
233
|
this.$refs.dialogToolbar.setFailedSearch(searchFound ? undefined : payload.term);
|
234
|
+
|
235
|
+
// GA Tagging
|
236
|
+
// Event tracking for map on display search
|
237
|
+
Tagging.sendEvent({
|
238
|
+
'event': 'interaction_event',
|
239
|
+
'event_name': 'portal_maps_display_search',
|
240
|
+
'category': payload.term,
|
241
|
+
'location': 'map_toolbar'
|
242
|
+
});
|
162
243
|
},
|
163
244
|
fetchSuggestions: function(payload) {
|
164
245
|
const suggestions = [];
|
@@ -174,17 +255,61 @@ export default {
|
|
174
255
|
}
|
175
256
|
payload.data.cb(suggestions);
|
176
257
|
},
|
258
|
+
hoverChanged: function (data) {
|
259
|
+
const hoverEntries = data && data.anatomy ? data.anatomy : []
|
260
|
+
this.settingsStore.updateHoveredMarkers(hoverEntries);
|
261
|
+
if (!hoverEntries.length) {
|
262
|
+
this.hoveredMarkerDelay = setTimeout(() => {
|
263
|
+
EventBus.emit("markerUpdate");
|
264
|
+
}, 3000)
|
265
|
+
} else {
|
266
|
+
clearTimeout(this.hoveredMarkerDelay)
|
267
|
+
EventBus.emit("markerUpdate");
|
268
|
+
}
|
269
|
+
},
|
177
270
|
searchChanged: function (data) {
|
178
271
|
if (data && data.type == "query-update") {
|
179
272
|
this.search = data.value;
|
273
|
+
if (this.search && !this.filterTriggered) {
|
274
|
+
// GA Tagging
|
275
|
+
// Event tracking for map action search/filter data
|
276
|
+
Tagging.sendEvent({
|
277
|
+
'event': 'interaction_event',
|
278
|
+
'event_name': 'portal_maps_action_search',
|
279
|
+
'category': this.search,
|
280
|
+
'location': 'map_sidebar_search'
|
281
|
+
});
|
282
|
+
}
|
283
|
+
this.filterTriggered = false; // reset for next action
|
180
284
|
}
|
181
285
|
if (data && data.type == "filter-update") {
|
182
286
|
this.settingsStore.updateFacets(data.value);
|
287
|
+
|
288
|
+
// Remove filter event from maps' popup
|
289
|
+
if (!this.filterTriggered) {
|
290
|
+
const { value } = data;
|
291
|
+
const filterValuesArray = value.filter((val) =>
|
292
|
+
val.facet && val.facet.toLowerCase() !== 'show all'
|
293
|
+
).map((val) => val.facet);
|
294
|
+
const filterValues = filterValuesArray.join(', ');
|
295
|
+
|
296
|
+
// GA Tagging
|
297
|
+
// Event tracking for map action search/filter data
|
298
|
+
Tagging.sendEvent({
|
299
|
+
'event': 'interaction_event',
|
300
|
+
'event_name': 'portal_maps_action_filter',
|
301
|
+
'category': filterValues || 'filter',
|
302
|
+
'location': 'map_sidebar_filter'
|
303
|
+
});
|
304
|
+
}
|
305
|
+
this.filterTriggered = false; // reset for next action
|
183
306
|
}
|
184
307
|
if (data && data.type == "available-facets") {
|
185
308
|
this.settingsStore.updateFacetLabels(data.value.labels);
|
186
309
|
this.settingsStore.updateMarkers(data.value.uberons);
|
187
310
|
EventBus.emit("markerUpdate");
|
311
|
+
|
312
|
+
this.availableFacets = data.value.labels
|
188
313
|
}
|
189
314
|
},
|
190
315
|
getNewEntryId: function() {
|
@@ -323,7 +448,27 @@ export default {
|
|
323
448
|
},
|
324
449
|
contextUpdate: function (payload) {
|
325
450
|
EventBus.emit("contextUpdate", payload);
|
326
|
-
}
|
451
|
+
},
|
452
|
+
datalinkClicked: function (payload) {
|
453
|
+
// payload is dataset URL
|
454
|
+
const datasetURL = payload || '';
|
455
|
+
const substringA = 'datasets/';
|
456
|
+
const substringB = '?type=dataset';
|
457
|
+
const datasetId = datasetURL.substring(
|
458
|
+
datasetURL.indexOf(substringA) + substringA.length,
|
459
|
+
datasetURL.indexOf(substringB)
|
460
|
+
);
|
461
|
+
|
462
|
+
// GA Tagging
|
463
|
+
// Event tracking for map sidebar gallery dataset click
|
464
|
+
Tagging.sendEvent({
|
465
|
+
'event': 'interaction_event',
|
466
|
+
'event_name': 'portal_maps_gallery_click',
|
467
|
+
'category': datasetURL,
|
468
|
+
'location': 'map_sidebar_gallery',
|
469
|
+
'dataset_id': datasetId || ''
|
470
|
+
});
|
471
|
+
},
|
327
472
|
},
|
328
473
|
created: function () {
|
329
474
|
this._facets = [];
|
@@ -162,12 +162,36 @@ const getBodyScaffoldInfo = async (sparcApi, species) => {
|
|
162
162
|
return {url, datasetInfo};
|
163
163
|
}
|
164
164
|
|
165
|
-
|
165
|
+
// Array intersection
|
166
|
+
const intersectArrays = (arr1, arr2) => {
|
167
|
+
return arr1.filter((x) => arr2.includes(x));
|
168
|
+
};
|
169
|
+
|
170
|
+
// Not using URLSearchParams to avoid encoding spaces
|
171
|
+
const transformObjToString = (obj) => {
|
172
|
+
return Object.keys(obj)
|
173
|
+
.map((key) => `${key}=${obj[key]}`)
|
174
|
+
.join('&');
|
175
|
+
};
|
176
|
+
|
177
|
+
const transformStringToObj = (str) => {
|
178
|
+
const params = new URLSearchParams(str);
|
179
|
+
const obj = {};
|
180
|
+
for (const [key, value] of params) {
|
181
|
+
obj[key] = value;
|
182
|
+
}
|
183
|
+
return obj;
|
184
|
+
};
|
185
|
+
|
186
|
+
export {
|
166
187
|
availableSpecies,
|
167
188
|
capitalise,
|
168
189
|
findSpeciesKey,
|
169
190
|
initialState,
|
170
191
|
initialDefaultState,
|
171
192
|
getBodyScaffoldInfo,
|
172
|
-
getNewMapEntry
|
193
|
+
getNewMapEntry,
|
194
|
+
intersectArrays,
|
195
|
+
transformObjToString,
|
196
|
+
transformStringToObj,
|
173
197
|
}
|
@@ -17,6 +17,7 @@
|
|
17
17
|
:flatmapAPI="flatmapAPI"
|
18
18
|
:sparcAPI="apiLocation"
|
19
19
|
@open-map="openMap"
|
20
|
+
@pathway-selection-changed="onPathwaySelectionChanged"
|
20
21
|
/>
|
21
22
|
</template>
|
22
23
|
|
@@ -26,6 +27,7 @@ import { FlatmapVuer } from "@abi-software/flatmapvuer";
|
|
26
27
|
import EventBus from "../EventBus";
|
27
28
|
import ContentMixin from "../../mixins/ContentMixin";
|
28
29
|
import DynamicMarkerMixin from "../../mixins/DynamicMarkerMixin";
|
30
|
+
import { transformObjToString } from '../scripts/utilities';
|
29
31
|
import "@abi-software/flatmapvuer/dist/style.css";
|
30
32
|
|
31
33
|
export default {
|
@@ -49,7 +51,24 @@ export default {
|
|
49
51
|
},
|
50
52
|
flatmaprResourceSelected: function (type, resource) {
|
51
53
|
this.resourceSelected(
|
52
|
-
type, resource, (this.$refs.
|
54
|
+
type, resource, (this.$refs.map.viewingMode === "Exploration"));
|
55
|
+
if (resource.eventType === 'click' && resource.feature.type === 'feature') {
|
56
|
+
const eventData = {
|
57
|
+
label: resource.label || '',
|
58
|
+
id: resource.feature.id || '',
|
59
|
+
featureId: resource.feature.featureId || '',
|
60
|
+
taxonomy: resource.taxonomy || '',
|
61
|
+
resources: resource.resource.join(', ')
|
62
|
+
};
|
63
|
+
const paramString = transformObjToString(eventData);
|
64
|
+
// `transformStringToObj` function can be used to change it back to object
|
65
|
+
Tagging.sendEvent({
|
66
|
+
'event': 'interaction_event',
|
67
|
+
'event_name': 'portal_maps_connectivity',
|
68
|
+
'category': paramString,
|
69
|
+
"location": type + ' ' + this.$refs.map.viewingMode
|
70
|
+
});
|
71
|
+
}
|
53
72
|
},
|
54
73
|
flatmapReadyCall: function (flatmap) {
|
55
74
|
let provClone = {id: this.entry.id, prov: this.getFlatmapImp().provenance}; //create clone of provenance and add id
|
@@ -60,6 +79,17 @@ export default {
|
|
60
79
|
this.flatmapReadyForMarkerUpdates(flatmap);
|
61
80
|
}
|
62
81
|
},
|
82
|
+
onPathwaySelectionChanged: function (data) {
|
83
|
+
const { label, property, checked, selectionsTitle } = data;
|
84
|
+
// GA Tagging
|
85
|
+
// Event tracking for maps' pathway selection change
|
86
|
+
Tagging.sendEvent({
|
87
|
+
'event': 'interaction_event',
|
88
|
+
'event_name': 'portal_maps_pathway_change',
|
89
|
+
'category': label + ' [' + property + '] ' + checked,
|
90
|
+
'location': selectionsTitle
|
91
|
+
});
|
92
|
+
},
|
63
93
|
highlightFeatures: function(info) {
|
64
94
|
let name = info.name;
|
65
95
|
const flatmap = this.$refs.flatmap.mapImp;
|
@@ -17,16 +17,22 @@
|
|
17
17
|
:sparcAPI="apiLocation"
|
18
18
|
@pan-zoom-callback="flatmapPanZoomCallback"
|
19
19
|
@open-map="openMap"
|
20
|
+
@pathway-selection-changed="onPathwaySelectionChanged"
|
21
|
+
@open-pubmed-url="onOpenPubmedUrl"
|
20
22
|
/>
|
21
23
|
</template>
|
22
24
|
|
23
25
|
<script>
|
24
26
|
/* eslint-disable no-alert, no-console */
|
25
|
-
import
|
27
|
+
import Tagging from '../../services/tagging.js';
|
26
28
|
import { MultiFlatmapVuer } from "@abi-software/flatmapvuer";
|
27
29
|
import ContentMixin from "../../mixins/ContentMixin";
|
28
30
|
import EventBus from "../EventBus";
|
29
|
-
import {
|
31
|
+
import {
|
32
|
+
availableSpecies,
|
33
|
+
getBodyScaffoldInfo,
|
34
|
+
transformObjToString
|
35
|
+
} from "../scripts/utilities";
|
30
36
|
import DyncamicMarkerMixin from "../../mixins/DynamicMarkerMixin";
|
31
37
|
|
32
38
|
import "@abi-software/flatmapvuer/dist/style.css";
|
@@ -159,6 +165,45 @@ export default {
|
|
159
165
|
flatmaprResourceSelected: function (type, resource) {
|
160
166
|
const map = this.$refs.multiflatmap.getCurrentFlatmap();
|
161
167
|
this.resourceSelected(type, resource, (map.viewingMode === "Exploration"));
|
168
|
+
|
169
|
+
if (resource.eventType === 'click' && resource.feature.type === 'feature') {
|
170
|
+
const eventData = {
|
171
|
+
label: resource.label || '',
|
172
|
+
id: resource.feature.id || '',
|
173
|
+
featureId: resource.feature.featureId || '',
|
174
|
+
taxonomy: resource.taxonomy || '',
|
175
|
+
resources: resource.resource.join(', ')
|
176
|
+
};
|
177
|
+
const paramString = transformObjToString(eventData);
|
178
|
+
// `transformStringToObj` function can be used to change it back to object
|
179
|
+
Tagging.sendEvent({
|
180
|
+
'event': 'interaction_event',
|
181
|
+
'event_name': 'portal_maps_connectivity',
|
182
|
+
'category': paramString,
|
183
|
+
"location": type + ' ' + map.viewingMode
|
184
|
+
});
|
185
|
+
}
|
186
|
+
},
|
187
|
+
onPathwaySelectionChanged: function (data) {
|
188
|
+
const { label, property, checked, selectionsTitle } = data;
|
189
|
+
// GA Tagging
|
190
|
+
// Event tracking for maps' pathway selection change
|
191
|
+
Tagging.sendEvent({
|
192
|
+
'event': 'interaction_event',
|
193
|
+
'event_name': 'portal_maps_pathway_change',
|
194
|
+
'category': label + ' [' + property + '] ' + checked,
|
195
|
+
'location': selectionsTitle
|
196
|
+
});
|
197
|
+
},
|
198
|
+
onOpenPubmedUrl: function (url) {
|
199
|
+
// GA Tagging
|
200
|
+
// Event tracking for open pubmed url from popup
|
201
|
+
Tagging.sendEvent({
|
202
|
+
'event': 'interaction_event',
|
203
|
+
'event_name': 'portal_maps_pubmed_url',
|
204
|
+
'file_path': url,
|
205
|
+
'location': 'map_popup_button',
|
206
|
+
});
|
162
207
|
},
|
163
208
|
/**
|
164
209
|
* Handle sync pan zoom event
|
@@ -243,6 +288,14 @@ export default {
|
|
243
288
|
await this.toggleSyncMode();
|
244
289
|
}
|
245
290
|
this.updateProvCard();
|
291
|
+
|
292
|
+
// GA Tagging
|
293
|
+
// Event tracking for maps' species change
|
294
|
+
Tagging.sendEvent({
|
295
|
+
'event': 'interaction_event',
|
296
|
+
'event_name': 'portal_maps_species_change',
|
297
|
+
'category': this.activeSpecies
|
298
|
+
});
|
246
299
|
},
|
247
300
|
multiFlatmapReady: function (flatmap) {
|
248
301
|
if (flatmap) {
|
@@ -368,6 +421,12 @@ export default {
|
|
368
421
|
cursor: pointer !important;
|
369
422
|
z-index: 2;
|
370
423
|
}
|
424
|
+
&.hovered {
|
425
|
+
div {
|
426
|
+
scale: 2;
|
427
|
+
transform: translate(0px, -5px);
|
428
|
+
}
|
429
|
+
}
|
371
430
|
&.highlight-marker {
|
372
431
|
visibility: visible !important;
|
373
432
|
cursor: pointer !important;
|
@@ -9,6 +9,7 @@ import markerZoomLevels from "../components/markerZoomLevelsHardCoded.js";
|
|
9
9
|
import { mapStores } from 'pinia';
|
10
10
|
import { useSettingsStore } from '../stores/settings';
|
11
11
|
import { useSplitFlowStore } from '../stores/splitFlow';
|
12
|
+
import Tagging from '../services/tagging.js';
|
12
13
|
|
13
14
|
function capitalise(text) {
|
14
15
|
return text[0].toUpperCase() + text.substring(1)
|
@@ -52,10 +53,22 @@ export default {
|
|
52
53
|
openMap: function (type) {
|
53
54
|
if (type === "SYNC") {
|
54
55
|
this.toggleSyncMode();
|
56
|
+
this.trackOpenMap('toggle_map_sync_mode');
|
55
57
|
} else {
|
56
58
|
EventBus.emit("OpenNewMap", type);
|
59
|
+
this.trackOpenMap(`open_new_${type}_map`);
|
57
60
|
}
|
58
61
|
},
|
62
|
+
trackOpenMap: function (category) {
|
63
|
+
// GA Tagging
|
64
|
+
// Open map tracking
|
65
|
+
Tagging.sendEvent({
|
66
|
+
'event': 'interaction_event',
|
67
|
+
'event_name': 'portal_maps_open_map',
|
68
|
+
'category': category,
|
69
|
+
'location': 'open_new_map'
|
70
|
+
});
|
71
|
+
},
|
59
72
|
updateWithViewUrl: function() {
|
60
73
|
return;
|
61
74
|
},
|
@@ -113,6 +126,7 @@ export default {
|
|
113
126
|
term: this.settingsStore.featuredMarkerDoi(
|
114
127
|
resource.feature.id
|
115
128
|
),
|
129
|
+
featuredDataset: true,
|
116
130
|
};
|
117
131
|
} else if (hardcodedAnnotation.filter(h => h.keyword).length > 0) {
|
118
132
|
// if it matches our stored keywords, it is a keyword search
|
@@ -42,9 +42,19 @@ export default {
|
|
42
42
|
|
43
43
|
if (flatmapImp) {
|
44
44
|
let markers = this.settingsStore.markers;
|
45
|
+
let hoveredMarkers = this.settingsStore.hoveredMarkers
|
45
46
|
markers = removeDuplicates(markers);
|
47
|
+
hoveredMarkers = removeDuplicates(hoveredMarkers);
|
46
48
|
flatmapImp.clearMarkers();
|
47
|
-
markers.forEach(id =>
|
49
|
+
markers.forEach(id => {
|
50
|
+
let markerClass = "standard-marker"
|
51
|
+
let markerCluster = true
|
52
|
+
if (hoveredMarkers.includes(id)) {
|
53
|
+
markerClass += " hovered" // Space-separated CSS class names
|
54
|
+
markerCluster = false // Disable cluster when related dataset is hovered
|
55
|
+
}
|
56
|
+
flatmapImp.addMarker(id, { className: markerClass, cluster: markerCluster })
|
57
|
+
})
|
48
58
|
if (this.entry.type === "MultiFlatmap") {
|
49
59
|
this.restoreFeaturedMarkers(flatmapImp);
|
50
60
|
}
|
@@ -0,0 +1,83 @@
|
|
1
|
+
|
2
|
+
/* eslint-disable no-alert, no-console */
|
3
|
+
export default {
|
4
|
+
// Note that the setting store is included in MapContent.vue
|
5
|
+
methods: {
|
6
|
+
retrieveContextCardFromUrl: async function (url) {
|
7
|
+
// split the url to get the datasetId
|
8
|
+
const [datasetId, basePath, scaffoldPath, s3uri] = this.splitInfoFromUrl(url);
|
9
|
+
|
10
|
+
// get the context file from scicrunch
|
11
|
+
const sciResults = await this.getContextFileFromScicrunch(datasetId, scaffoldPath);
|
12
|
+
if (!sciResults.success){
|
13
|
+
return {} // return empty object if no context file is found (the empty object will be added to the entry)
|
14
|
+
}
|
15
|
+
|
16
|
+
// return the context file
|
17
|
+
const fullPath = basePath + sciResults.contextFile + s3uri;
|
18
|
+
return {
|
19
|
+
s3uri: sciResults.s3uri,
|
20
|
+
contextCardUrl: fullPath,
|
21
|
+
}
|
22
|
+
},
|
23
|
+
splitInfoFromUrl: function (url) {
|
24
|
+
// example url: "https://mapcore-demo.org/current/sparc-api-v2/s3-resource/221/3/files/derivative/Scaffolds/mouse_colon_metadata.json",
|
25
|
+
// find the part after 's3-resource'
|
26
|
+
let s3path = url.split('s3-resource')[1];
|
27
|
+
let basePath = url.split('files/')[0] + 'files/' // This gives us the base path for our relative path we will get from scicrunch
|
28
|
+
let scaffoldPath = url.split('files/')[1].split('?')[0] // This gives us the relative path to the file we want to get from scicrunch
|
29
|
+
let s3uri = '?' + url.split('?')[1] // This gives us the uri needed to get the file from s3
|
30
|
+
|
31
|
+
// split the url by '/'
|
32
|
+
const parts = s3path.split('/');
|
33
|
+
// remove the first part
|
34
|
+
parts.shift();
|
35
|
+
// return the datasetId which is the first part
|
36
|
+
const datasetId = parts[0];
|
37
|
+
|
38
|
+
return [datasetId, basePath, scaffoldPath, s3uri];
|
39
|
+
},
|
40
|
+
getContextFileFromScicrunch: async function (datasetId, scaffoldPath) {
|
41
|
+
// get the context file from scicrunch
|
42
|
+
let results = await fetch(`${this.settingsStore.sparcApi}/dataset_info/using_multiple_discoverIds/?discoverIds=${datasetId}`)
|
43
|
+
.then(response => response.json())
|
44
|
+
.then(data => {
|
45
|
+
// get the context info from the response
|
46
|
+
if (data.numberOfHits === 1) { // check if there is only one hit (We don't want to use the data if there are multiple hits)
|
47
|
+
const contextFile = data.results[0]['abi-contextual-information']
|
48
|
+
|
49
|
+
// check if there is only one context file and if so return it
|
50
|
+
if ( contextFile && contextFile.length === 1) {
|
51
|
+
return {
|
52
|
+
success: true,
|
53
|
+
contextFile: contextFile[0],
|
54
|
+
s3uri: data.results[0]['s3uri']
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
// If there are multiple context files, find the one that matches the scaffold path
|
59
|
+
else if (contextFile && contextFile.length > 1) {
|
60
|
+
let search = this.findContextInforForFilePath(data.results[0]['abi-context-file'], scaffoldPath);
|
61
|
+
if (search) {
|
62
|
+
return {
|
63
|
+
success: true,
|
64
|
+
contextFile: search,
|
65
|
+
s3uri: data.results[0]['s3uri']
|
66
|
+
}
|
67
|
+
}
|
68
|
+
}
|
69
|
+
}
|
70
|
+
return {success: false};
|
71
|
+
}).catch(error => {
|
72
|
+
console.error('Error:', error);
|
73
|
+
return {success: false};
|
74
|
+
});
|
75
|
+
return results;
|
76
|
+
},
|
77
|
+
findContextInforForFilePath: function (dataciteInfo, filePath) {
|
78
|
+
// find the context file that matches the scaffold path
|
79
|
+
let result = dataciteInfo.find((info) => info.datacite.isDerivedFrom.path.includes(filePath))
|
80
|
+
return result?.dataset?.path
|
81
|
+
}
|
82
|
+
}
|
83
|
+
}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
export default {
|
2
|
+
sendEvent: function(data) {
|
3
|
+
const taggingData = {
|
4
|
+
event: data.event || '',
|
5
|
+
event_name: data.event_name || '',
|
6
|
+
files: data.files || '',
|
7
|
+
file_name: data.file_name || '',
|
8
|
+
file_path: data.file_path || '',
|
9
|
+
file_type: data.file_type || '',
|
10
|
+
category: data.category || '',
|
11
|
+
dataset_id: data.dataset_id || '',
|
12
|
+
version_id: data.version_id || '',
|
13
|
+
doi: data.doi || '',
|
14
|
+
citation_type: data.citation_type || '',
|
15
|
+
location: data.location || ''
|
16
|
+
};
|
17
|
+
|
18
|
+
// set debugging mode
|
19
|
+
if (localStorage.getItem('debugTagging') === 'yes') {
|
20
|
+
console.table(taggingData);
|
21
|
+
}
|
22
|
+
|
23
|
+
// push to dataLayer for GTM
|
24
|
+
if (typeof dataLayer !== 'undefined') {
|
25
|
+
dataLayer.push(taggingData);
|
26
|
+
}
|
27
|
+
}
|
28
|
+
}
|
package/src/stores/settings.js
CHANGED
@@ -17,6 +17,7 @@ export const useSettingsStore = defineStore('settings', {
|
|
17
17
|
facets: { species: [], gender: [], organ: [] },
|
18
18
|
facetLabels: [],
|
19
19
|
markers: [],
|
20
|
+
hoveredMarkers: [],
|
20
21
|
featuredMarkers: [],
|
21
22
|
featuredMarkerIdentifiers: [],
|
22
23
|
featuredMarkerDois: [],
|
@@ -67,6 +68,9 @@ export const useSettingsStore = defineStore('settings', {
|
|
67
68
|
updateMarkers(markers) {
|
68
69
|
this.markers = markers;
|
69
70
|
},
|
71
|
+
updateHoveredMarkers(markers) {
|
72
|
+
this.hoveredMarkers = markers;
|
73
|
+
},
|
70
74
|
updateFeatured(datasetIdentifiers) {
|
71
75
|
this.featuredMarkerIdentifiers = new Array(datasetIdentifiers.length);
|
72
76
|
this.featuredMarkers = new Array(datasetIdentifiers.length);
|