@abi-software/flatmapvuer 1.1.4 → 1.2.0-beta.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.
Files changed (43) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +120 -120
  3. package/cypress.config.js +23 -23
  4. package/dist/flatmapvuer.js +44509 -43153
  5. package/dist/flatmapvuer.umd.cjs +171 -171
  6. package/dist/index.html +17 -17
  7. package/dist/style.css +1 -1
  8. package/package.json +96 -95
  9. package/public/index.html +17 -17
  10. package/reporter-config.json +9 -9
  11. package/src/App.vue +378 -379
  12. package/src/assets/_variables.scss +43 -43
  13. package/src/assets/styles.scss +5 -5
  14. package/src/components/EventBus.js +3 -3
  15. package/src/components/FlatmapVuer.vue +3616 -3461
  16. package/src/components/MultiFlatmapVuer.vue +830 -814
  17. package/src/components/SelectionsGroup.vue +363 -363
  18. package/src/components/index.js +6 -8
  19. package/src/components/legends/DynamicLegends.vue +106 -106
  20. package/src/components/legends/SvgLegends.vue +112 -112
  21. package/src/components.d.ts +0 -18
  22. package/src/icons/flatmap-marker.js +9 -9
  23. package/src/icons/fonts/mapicon-species.svg +14 -14
  24. package/src/icons/fonts/mapicon-species.ttf +0 -0
  25. package/src/icons/fonts/mapicon-species.woff +0 -0
  26. package/src/icons/mapicon-species-style.css +42 -42
  27. package/src/icons/yellowstar.js +5 -5
  28. package/src/legends/legend.svg +25 -25
  29. package/src/main.js +19 -19
  30. package/src/services/flatmapQueries.js +475 -475
  31. package/src/store/flatmap.js +22 -0
  32. package/src/store/index.js +23 -23
  33. package/vite.config.js +74 -73
  34. package/vite.static-build.js +12 -12
  35. package/vuese-generator.js +64 -64
  36. package/src/components/AnnotationTool.vue +0 -501
  37. package/src/components/ConnectionDialog.vue +0 -134
  38. package/src/components/DrawTool.vue +0 -502
  39. package/src/components/ExternalResourceCard.vue +0 -109
  40. package/src/components/HelpModeDialog.vue +0 -360
  41. package/src/components/ProvenancePopup.vue +0 -530
  42. package/src/components/Tooltip.vue +0 -50
  43. package/src/components/TreeControls.vue +0 -236
@@ -1,501 +0,0 @@
1
- <template>
2
- <el-main class="main">
3
- <div class="block">
4
- <el-row class="info-field">
5
- <div class="title">Feature Annotations</div>
6
- </el-row>
7
- <template v-if="annotationEntry">
8
- <el-row
9
- v-for="(key, label) in displayPair"
10
- v-show="annotationEntry[key]"
11
- class="dialog-text"
12
- :key="key"
13
- >
14
- <strong>{{ label }}: </strong>&nbsp;{{ annotationEntry[key] }}
15
- </el-row>
16
- <template v-if="prevSubs.length > 0">
17
- <div
18
- v-show="showSubmissions"
19
- class="hide"
20
- @click="showSubmissions = false"
21
- >
22
- Hide previous submissions
23
- <el-icon><el-icon-arrow-up /></el-icon>
24
- </div>
25
- <div
26
- v-show="!showSubmissions"
27
- class="hide"
28
- @click="showSubmissions = true"
29
- >
30
- Show previous {{ prevSubs.length }} submission(s)
31
- <el-icon><el-icon-arrow-down /></el-icon>
32
- </div>
33
- <template v-if="showSubmissions">
34
- <el-row class="dialog-spacer"></el-row>
35
- <el-row class="dialog-text">
36
- <strong class="sub-title">Previous submissions:</strong>
37
- </el-row>
38
- <div class="entry" v-for="(sub, index) in prevSubs" :key="index">
39
- <el-row class="dialog-text">
40
- <strong>{{ formatTime(sub.created) }}</strong>
41
- {{ sub.creator.name }}
42
- </el-row>
43
- <el-row class="dialog-text">
44
- <strong>Evidence: </strong>
45
- <el-row
46
- v-for="evidence in sub.body.evidence"
47
- :key="evidence"
48
- class="dialog-text"
49
- >
50
- <a :href="evidence" target="_blank"> {{ evidence }}</a>
51
- </el-row>
52
- </el-row>
53
- <el-row class="dialog-text">
54
- <strong>Comment: </strong> {{ sub.body.comment }}
55
- </el-row>
56
- </div>
57
- </template>
58
- </template>
59
- <template v-if="authenticated">
60
- <template v-if="isEditable">
61
- <el-row class="dialog-spacer"></el-row>
62
- <el-row v-if="!editing">
63
- <el-icon class="standard-icon">
64
- <el-icon-edit @click="editing = true" />
65
- </el-icon>
66
- <el-icon
67
- class="standard-icon"
68
- v-if="isDeleted"
69
- >
70
- <el-icon-delete @click="submit"/>
71
- </el-icon>
72
- <el-icon
73
- class="standard-icon"
74
- v-else-if="isPositionUpdated"
75
- >
76
- <el-icon-finished @click="submit" />
77
- </el-icon>
78
- </el-row>
79
- <template v-else>
80
- <el-row class="dialog-text">
81
- <strong class="sub-title">Suggest changes:</strong>
82
- </el-row>
83
- <template v-if="!isDeleted">
84
- <el-row class="dialog-text">
85
- <strong>Evidence:</strong>
86
- </el-row>
87
- <el-row v-for="(value, index) in evidence" :key="value">
88
- <el-col :span="20">
89
- {{ evidence[index] }}
90
- </el-col>
91
- <el-col :span="4">
92
- <el-icon class="standard-icon">
93
- <el-icon-close @click="removeEvidence(index)" />
94
- </el-icon>
95
- </el-col>
96
- </el-row>
97
- <el-row>
98
- <el-input
99
- size="small"
100
- placeholder="Enter"
101
- v-model="newEvidence"
102
- @change="evidenceEntered($event)"
103
- >
104
- <template #prepend>
105
- <el-select
106
- :teleported="false"
107
- v-model="evidencePrefix"
108
- placeholder="Select"
109
- class="select-box"
110
- popper-class="flatmap_dropdown"
111
- >
112
- <el-option
113
- v-for="item in evidencePrefixes"
114
- :key="item"
115
- :label="item"
116
- :value="item"
117
- >
118
- <el-row>
119
- <el-col :span="12">{{ item }}</el-col>
120
- </el-row>
121
- </el-option>
122
- </el-select>
123
- </template>
124
- </el-input>
125
- </el-row>
126
- </template>
127
- <el-row>
128
- <strong>Comment:</strong>
129
- </el-row>
130
- <el-row class="dialog-text">
131
- <el-input
132
- type="textarea"
133
- :autosize="{ minRows: 2, maxRows: 4 }"
134
- placeholder="Enter"
135
- v-model="comment"
136
- />
137
- </el-row>
138
- <el-row class="dialog-text">
139
- <el-button class="button" type="primary" plain @click="submit">
140
- Submit
141
- </el-button>
142
- </el-row>
143
- </template>
144
- <el-row class="dialog-text" v-if="errorMessage">
145
- <strong class="sub-title"> {{ errorMessage }} </strong>
146
- </el-row>
147
- </template>
148
- </template>
149
- </template>
150
- </div>
151
- </el-main>
152
- </template>
153
-
154
- <script>
155
- import {
156
- ArrowUp as ElIconArrowUp,
157
- ArrowDown as ElIconArrowDown,
158
- Edit as ElIconEdit,
159
- Close as ElIconClose,
160
- Delete as ElIconDelete,
161
- Finished as ElIconFinished,
162
- } from '@element-plus/icons-vue'
163
- /* eslint-disable no-alert, no-console */
164
- import {
165
- ElButton as Button,
166
- ElCol as Col,
167
- ElInput as Input,
168
- ElMain as Main,
169
- ElRow as Row,
170
- ElSelect as Select,
171
- } from 'element-plus'
172
-
173
- export default {
174
- name: 'AnnotationTool',
175
- components: {
176
- Button,
177
- Col,
178
- Input,
179
- Main,
180
- Row,
181
- Select,
182
- ElIconArrowUp,
183
- ElIconArrowDown,
184
- ElIconEdit,
185
- ElIconClose,
186
- },
187
- props: {
188
- annotationEntry: {
189
- type: Object,
190
- },
191
- },
192
- inject: ['flatmapAPI', '$annotator', 'userApiKey'],
193
- data: function () {
194
- return {
195
- displayPair: {
196
- 'Feature ID': 'featureId',
197
- Tooltip: 'label',
198
- Models: 'models',
199
- Name: 'name',
200
- Resource: 'resourceId',
201
- },
202
- editing: false,
203
- evidencePrefixes: ['DOI:', 'PMID:'],
204
- evidencePrefix: 'DOI:',
205
- evidence: [],
206
- authenticated: false,
207
- newEvidence: '',
208
- comment: '',
209
- prevSubs: [],
210
- showSubmissions: true,
211
- errorMessage: '',
212
- creator: undefined
213
- }
214
- },
215
- computed: {
216
- isEditable: function () {
217
- return (
218
- this.annotationEntry['resourceId'] &&
219
- this.annotationEntry['featureId']
220
- )
221
- },
222
- isPositionUpdated: function () {
223
- return (
224
- this.annotationEntry['resourceId'] &&
225
- this.annotationEntry['type'] === 'updated' &&
226
- this.annotationEntry['positionUpdated']
227
- )
228
- },
229
- isDeleted: function () {
230
- return (
231
- this.annotationEntry['resourceId'] &&
232
- this.annotationEntry['type'] === 'deleted'
233
- )
234
- }
235
- },
236
- methods: {
237
- evidenceEntered: function (value) {
238
- if (value) {
239
- this.evidence.push(this.evidencePrefix + value)
240
- this.newEvidence = ''
241
- }
242
- },
243
- formatTime: function (dateString) {
244
- const options = {
245
- year: 'numeric',
246
- month: 'long',
247
- day: 'numeric',
248
- hour: 'numeric',
249
- minute: 'numeric',
250
- second: 'numeric',
251
- }
252
- return new Date(dateString).toLocaleDateString(undefined, options)
253
- },
254
- updatePrevSubmissions: function () {
255
- if (this.$annotator && this.authenticated) {
256
- if (
257
- this.annotationEntry['resourceId'] &&
258
- this.annotationEntry['featureId']
259
- ) {
260
- this.$annotator
261
- .itemAnnotations(
262
- this.userApiKey,
263
- this.annotationEntry['resourceId'],
264
- this.annotationEntry['featureId']
265
- )
266
- .then((value) => {
267
- this.prevSubs = value
268
- })
269
- .catch((reason) => {
270
- console.log(reason) // Error!
271
- })
272
- }
273
- }
274
- },
275
- submit: function () {
276
- // User can either update/delete annotation directly
277
- // or provide extra comments for update/delete action
278
- if (
279
- this.annotationEntry['type'] === 'updated' &&
280
- this.annotationEntry['positionUpdated']
281
- ) {
282
- this.comment = this.comment ?
283
- `Position Updated: ${this.comment}` :
284
- 'Position Updated'
285
- } else if (this.annotationEntry['type'] === 'deleted') {
286
- this.comment = this.comment ?
287
- `Feature Deleted: ${this.comment}` :
288
- 'Feature Deleted'
289
- }
290
-
291
- if (this.evidence.length > 0 || this.comment) {
292
- if (
293
- this.annotationEntry['resourceId'] &&
294
- this.annotationEntry['featureId']
295
- ) {
296
- const evidenceURLs = []
297
- this.evidence.forEach((evidence) => {
298
- if (evidence.includes('DOI:')) {
299
- const link = evidence.replace('DOI:', 'https://doi.org/')
300
- evidenceURLs.push(new URL(link))
301
- } else if (evidence.includes('PMID:')) {
302
- const link = evidence.replace(
303
- 'PMID:',
304
- 'https://pubmed.ncbi.nlm.nih.gov/'
305
- )
306
- evidenceURLs.push(new URL(link))
307
- }
308
- })
309
- const userAnnotation = {
310
- resource: this.annotationEntry['resourceId'],
311
- item: Object.assign({id: this.annotationEntry['featureId']},
312
- Object.fromEntries(
313
- Object.entries(this.annotationEntry)
314
- .filter(([key]) => ['label', 'models'].includes(key)))),
315
- body: {
316
- evidence: evidenceURLs,
317
- comment: this.comment,
318
- },
319
- feature: this.annotationEntry['feature']
320
- }
321
- Object.assign(userAnnotation.body, this.annotationEntry['body'])
322
- if (this.annotationEntry['type'] === 'deleted') {
323
- userAnnotation.feature = undefined
324
- }
325
- if (this.creator) userAnnotation.creator = this.creator
326
- this.$annotator
327
- .addAnnotation(this.userApiKey, userAnnotation)
328
- .then(() => {
329
- this.$emit('annotation', userAnnotation)
330
- this.errorMessage = ''
331
- this.resetSubmission()
332
- this.updatePrevSubmissions()
333
- })
334
- .catch(() => {
335
- this.errorMessage =
336
- 'There is a problem with the submission, please try again later'
337
- })
338
- }
339
- }
340
- },
341
- removeEvidence: function (index) {
342
- this.evidence.splice(index, 1)
343
- },
344
- resetSubmission: function () {
345
- this.editing = false
346
- this.evidence = []
347
- this.newFeature = ''
348
- this.comment = ''
349
- },
350
- },
351
- watch: {
352
- annotationEntry: {
353
- handler: function (newVal, oldVal) {
354
- if (newVal !== oldVal) {
355
- this.resetSubmission()
356
- this.updatePrevSubmissions()
357
- }
358
- },
359
- immediate: false,
360
- deep: false,
361
- },
362
- },
363
- mounted: function () {
364
- this.$annotator.authenticate(this.userApiKey).then((userData) => {
365
- if (userData.name && userData.email) {
366
- this.creator = userData
367
- if (!userData.orcid) this.creator.orcid = '0000-0000-0000-0000'
368
- this.authenticated = true
369
- this.updatePrevSubmissions()
370
- } else {
371
- this.errorMessage = ''
372
- }
373
- })
374
- },
375
- }
376
- </script>
377
-
378
- <style lang="scss" scoped>
379
-
380
- .info-field {
381
- display: flex;
382
- }
383
-
384
- .block {
385
- margin-bottom: 0.5em;
386
-
387
- .main > &:first-of-type {
388
- margin-right: 0.5em;
389
- }
390
- }
391
-
392
- .button {
393
- padding-top: 5px;
394
- padding-bottom: 5px;
395
- }
396
-
397
- .standard-icon {
398
- color: $app-primary-color;
399
- &:hover {
400
- cursor: pointer;
401
- }
402
- }
403
-
404
- .dialog-text {
405
- color: rgb(48, 49, 51);
406
- font-size: 14px;
407
- font-weight: normal;
408
- line-height: 20px;
409
- }
410
-
411
- .main {
412
- font-size: 14px;
413
- text-align: left;
414
- line-height: 1.5em;
415
- font-family: Asap, sans-serif, Helvetica;
416
- font-weight: 400;
417
- /* outline: thin red solid; */
418
- padding: 1em !important;
419
- overflow-x: hidden;
420
- overflow-y: auto;
421
- min-width: 300px; // .maplibregl-popup max-width
422
- max-height: 400px;
423
- scrollbar-width: thin;
424
-
425
- &::-webkit-scrollbar {
426
- width: 4px;
427
- }
428
-
429
- &::-webkit-scrollbar-thumb {
430
- border-radius: 10px;
431
- box-shadow: inset 0 0 6px #c0c4cc;
432
- }
433
- }
434
-
435
- .title {
436
- font-size: 18px;
437
- font-weight: 500;
438
- font-weight: bold;
439
- padding-bottom: 8px;
440
- color: rgb(131, 0, 191);
441
- }
442
-
443
- .sub-title {
444
- font-size: 16px;
445
- }
446
-
447
- .dialog-spacer {
448
- border-bottom: 1px solid #e4e7ed;
449
- margin-bottom: 10px;
450
- }
451
-
452
- .submit {
453
- color: $app-primary-color;
454
- &:hover {
455
- cursor: pointer;
456
- }
457
- }
458
-
459
- .entry ~ .entry {
460
- border-top: 1px solid #e4e7ed;
461
- margin-top: 10px;
462
- }
463
-
464
- .hide {
465
- color: $app-primary-color;
466
- cursor: pointer;
467
- margin-right: 6px;
468
- margin-top: 3px;
469
- }
470
-
471
- :deep(.el-input__inner),
472
- :deep(.el-textarea__inner) {
473
- font-family: Asap, sans-serif;
474
- }
475
-
476
- .select-box {
477
- width: 80px;
478
- background-color: var(--white);
479
- font-weight: 500;
480
- color: rgb(48, 49, 51);
481
- :deep(.el-input__inner) {
482
- height: 30px;
483
- color: rgb(48, 49, 51);
484
- }
485
- :deep(.el-input__icon) {
486
- line-height: 30px;
487
- }
488
- }
489
-
490
- :deep(.flatmap_dropdown) {
491
- min-width: 80px !important;
492
- .el-select-dropdown__item {
493
- white-space: nowrap;
494
- text-align: left;
495
- &.selected {
496
- color: $app-primary-color;
497
- font-weight: normal;
498
- }
499
- }
500
- }
501
- </style>
@@ -1,134 +0,0 @@
1
- <template>
2
- <div class="dialog-container">
3
- <el-row>
4
- <el-col>
5
- <span class="dialog-title">Visualise connection</span>
6
- <el-row v-if="inDrawing">
7
- <span class="dialog-subtitle">Finalise drawing</span>
8
- <el-button-group>
9
- <el-button
10
- type="primary"
11
- plain
12
- @click="$emit('confirmDrawn', true)"
13
- >
14
- Confirm
15
- </el-button>
16
- <el-button type="primary" plain @click="$emit('cancelDrawn', true)">
17
- Cancel
18
- </el-button>
19
- </el-button-group>
20
- </el-row>
21
- <el-row v-else>
22
- <el-button
23
- type="primary"
24
- plain
25
- @click="$emit('dialogDisplay', false)"
26
- >
27
- Close
28
- </el-button>
29
- </el-row>
30
- </el-col>
31
- </el-row>
32
- <el-row v-if="hasConnection">
33
- <el-col>
34
- <b><span>Related Features</span></b>
35
- <el-row v-for="(value, key) in connectionEntry" :key="key">
36
- <el-card :shadow="shadowDisplay(key)" @click="handleTooltip(key)">
37
- <span>{{ capitalise(value.label) }}</span>
38
- </el-card>
39
- </el-row>
40
- </el-col>
41
- </el-row>
42
- </div>
43
- </template>
44
-
45
- <script>
46
- /* eslint-disable no-alert, no-console */
47
- import {
48
- ElRow as Row,
49
- ElCol as Col,
50
- ElCard as Card,
51
- ElButton as Button,
52
- ElButtonGroup as ButtonGroup,
53
- } from "element-plus";
54
-
55
- export default {
56
- name: "ConnectionDialog",
57
- components: {
58
- Row,
59
- Col,
60
- ButtonGroup,
61
- Button,
62
- Card,
63
- },
64
- props: {
65
- connectionEntry: {
66
- type: Object,
67
- },
68
- inDrawing: {
69
- type: Boolean,
70
- default: false,
71
- },
72
- hasConnection: {
73
- type: Boolean,
74
- default: false,
75
- },
76
- },
77
- data: function () {
78
- return {
79
- tooltipId: undefined,
80
- };
81
- },
82
- methods: {
83
- shadowDisplay: function (value) {
84
- return this.tooltipId === value ? "always" : "hover";
85
- },
86
- capitalise: function (label) {
87
- return label[0].toUpperCase() + label.slice(1);
88
- },
89
- handleTooltip: function (value) {
90
- this.tooltipId = this.tooltipId === value ? undefined : value;
91
- this.$emit("featureTooltip", this.tooltipId);
92
- },
93
- },
94
- };
95
- </script>
96
-
97
- <style lang="scss" scoped>
98
- .dialog-container {
99
- width: 200px;
100
- height: fit-content;
101
- text-align: justify;
102
- border-radius: 4px;
103
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
104
- pointer-events: auto;
105
- background: #fff;
106
- border: 1px solid $app-primary-color;
107
- display: flex;
108
- flex-direction: column;
109
- padding: 0.8em;
110
- }
111
-
112
- .dialog-title {
113
- font-size: 18px;
114
- font-weight: bold;
115
- color: rgb(131, 0, 191);
116
- }
117
-
118
- .dialog-subtitle {
119
- margin-top: 5px;
120
- font-size: 15px;
121
- color: rgb(131, 0, 191);
122
- }
123
-
124
- .el-button {
125
- margin: 5px 0px;
126
- }
127
-
128
- :deep(.el-card) {
129
- width: 100%;
130
- --el-card-padding: 8px;
131
- border: 0;
132
- cursor: pointer;
133
- }
134
- </style>