@abi-software/map-side-bar 2.19.0 → 2.20.0-acuppoints.0

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.
@@ -0,0 +1,620 @@
1
+ <template>
2
+ <div v-if="entry" class="main">
3
+ <div class="header">
4
+ <el-row>
5
+ <el-input
6
+ class="search-input"
7
+ placeholder="Search"
8
+ v-model="searchInput"
9
+ @keyup="search(searchInput)"
10
+ clearable
11
+ @clear="clearSearchClicked"
12
+ ></el-input>
13
+ <el-button
14
+ v-show="false"
15
+ type="primary"
16
+ class="button"
17
+ @click="search(searchInput)"
18
+ size="large"
19
+ >
20
+ Search
21
+ </el-button>
22
+ </el-row>
23
+ </div>
24
+ <SearchFilters
25
+ v-if="filterEntry.options"
26
+ class="filters"
27
+ ref="filtersRef"
28
+ :entry="filterEntry"
29
+ @filterResults="filterUpdate"
30
+ @numberPerPage="numberPerPageUpdate"
31
+ @cascaderReady="cascaderReady"
32
+ ></SearchFilters>
33
+ <div class="content scrollbar" ref="content">
34
+ <div v-if="paginatedResults.length > 0" v-for="result in paginatedResults" :key="result.Acupoint" class="step-item">
35
+ <AcupointsCard
36
+ class="dataset-card"
37
+ :entry="result"
38
+ @mouseenter="hoverChanged(result)"
39
+ @mouseleave="hoverChanged(undefined)"
40
+ />
41
+ </div>
42
+ <div v-else class="error-feedback">
43
+ No results found - Please change your search / filter criteria.
44
+ </div>
45
+ <el-pagination
46
+ class="pagination"
47
+ v-model:current-page="page"
48
+ hide-on-single-page
49
+ large
50
+ layout="prev, pager, next"
51
+ :page-size="numberPerPage"
52
+ :total="numberOfHits"
53
+ @current-change="pageChange"
54
+ ></el-pagination>
55
+ </div>
56
+ </div>
57
+ </template>
58
+
59
+ <script>
60
+ /* eslint-disable no-alert, no-console */
61
+ import { markRaw } from 'vue';
62
+ import {
63
+ ElButton as Button,
64
+ ElCard as Card,
65
+ ElCol as Col,
66
+ ElRadioButton as RadioButton,
67
+ ElRadioGroup as RadioGroup,
68
+ ElDrawer as Drawer,
69
+ ElIcon as Icon,
70
+ ElInput as Input,
71
+ ElPagination as Pagination,
72
+ ElRow as Row,
73
+ } from 'element-plus'
74
+ import AcupointsCard from './AcupointsCard.vue'
75
+ import SearchFilters from "./SearchFilters.vue"
76
+
77
+ export default {
78
+ components: {
79
+ AcupointsCard,
80
+ Button,
81
+ Card,
82
+ Col,
83
+ RadioButton,
84
+ RadioGroup,
85
+ SearchFilters,
86
+ Drawer,
87
+ Icon,
88
+ Input,
89
+ Pagination,
90
+ Row
91
+ },
92
+ name: 'AcupointsInfoSearch',
93
+ props: {
94
+ entry: {
95
+ type: Object,
96
+ default: () => {},
97
+ },
98
+ },
99
+ created: function() {
100
+ if (this.entry) {
101
+ let entries = Object.values(this.entry)
102
+ const meridians = []
103
+ let others = false
104
+ entries.forEach((acupoint) => {
105
+ let meridian = acupoint.Meridian
106
+ if (!meridian) {
107
+ others = true
108
+ } else if (!(meridians.includes(meridian))) {
109
+ meridians.push(meridian)
110
+ }
111
+ });
112
+ meridians.sort();
113
+ if (others) {
114
+ meridians.push("Others")
115
+ }
116
+ if (meridians.length > 1) {
117
+ const filterOption = {
118
+ "key": "acupoints.meridian",
119
+ "label": "Meridian",
120
+ "children": [
121
+ ],
122
+ }
123
+ meridians.forEach(meridian => {
124
+ const entry = {
125
+ "key": `acupoints.meridian.${meridian}`,
126
+ "label": meridian,
127
+ "value": meridian,
128
+ }
129
+ filterOption.children.push(entry)
130
+ })
131
+ this.filterOptions.unshift(filterOption)
132
+ this.filters.unshift({
133
+ "facetPropPath": "acupoints.meridian",
134
+ "facet": "Show all",
135
+ "term": "Meridian"
136
+ })
137
+ }
138
+ }
139
+ },
140
+ computed: {
141
+ // This computed property populates filter data's entry object with $data from this sidebar
142
+ filterEntry: function () {
143
+ return {
144
+ numberOfHits: this.numberOfHits,
145
+ filterFacets: this.filters,
146
+ options: this.filterOptions,
147
+ showFilters: true,
148
+ };
149
+ },
150
+ },
151
+ data: function () {
152
+ return {
153
+ filters: [
154
+ {
155
+ "facetPropPath": "acupoints.WHO",
156
+ "facet": "Show all",
157
+ "term": "WHO",
158
+ },
159
+ {
160
+ "facetPropPath": "acupoints.visualized",
161
+ "facet": "Show all",
162
+ "term": "Visualized"
163
+ },
164
+ {
165
+ "facetPropPath": "acupoints.onMRI",
166
+ "facet": "Show all",
167
+ "term": "onMRI"
168
+ },
169
+ {
170
+ "facetPropPath": "acupoints.userDefined",
171
+ "facet": "Show all",
172
+ "term": "User defined"
173
+ }
174
+ ],
175
+ filterOptions: [
176
+ {
177
+ "key": "acupoints.visualized",
178
+ "label": "Visualized",
179
+ "children": [
180
+ {
181
+ "key": "acupoints.visualized.yes",
182
+ "label": "Visualized",
183
+ "value": "Visualized>Yes"
184
+ },
185
+ {
186
+ "key": "acupoints.visualized.no",
187
+ "label": "Non visualized",
188
+ "value": "Visualized>No"
189
+ },
190
+ ],
191
+ },
192
+ {
193
+ "key": "acupoints.onMRI",
194
+ "label": "Markers",
195
+ "children": [
196
+ {
197
+ "key": "acupoints.onMRI.yes",
198
+ "label": "Marked",
199
+ "value": "onMRI>Yes"
200
+ },
201
+ {
202
+ "key": "acupoints.onMRI.no",
203
+ "label": "Unmarked",
204
+ "value": "onMRI>No"
205
+ },
206
+ ],
207
+ },
208
+ {
209
+ "key": "acupoints.WHO",
210
+ "label": "WHO",
211
+ "children": [
212
+ {
213
+ "key": "acupoints.WHO.yes",
214
+ "label": "WHO",
215
+ "value": "WHO>Yes"
216
+ },
217
+ {
218
+ "key": "acupoints.WHO.no",
219
+ "label": "Non WHO",
220
+ "value": "WHO>No"
221
+ },
222
+ ],
223
+ },
224
+ {
225
+ "key": "acupoints.userDefined",
226
+ "label": "User Defined",
227
+ "children": [
228
+ {
229
+ "key": "acupoints.userDefined.yes",
230
+ "label": "User data",
231
+ "value": "userDefined>Yes"
232
+ },
233
+ {
234
+ "key": "acupoints.userDefined.no",
235
+ "label": "Official data",
236
+ "value": "userDefined>No"
237
+ },
238
+ ],
239
+ },
240
+ ],
241
+ currentFilters: markRaw({
242
+ curated: "Both",
243
+ mri: "Both",
244
+ who: "Both",
245
+ userDefined: "Both",
246
+ meridian: {
247
+ showAll: true,
248
+ list: []
249
+ },
250
+ }),
251
+ results: [],
252
+ paginatedResults: [],
253
+ searchInput: "",
254
+ lastSearch: "",
255
+ numberOfHits: 0,
256
+ numberPerPage: 10,
257
+ page: 1,
258
+ }
259
+ },
260
+ watch: {
261
+ entry: {
262
+ handler: function () {
263
+ this.filterUpdate(this.filters)
264
+ },
265
+ immediate: true,
266
+ deep: true,
267
+ },
268
+ },
269
+ methods: {
270
+ cascaderReady: function () {
271
+ this.cascaderIsReady = true;
272
+ this.search(this.searchInput);
273
+ },
274
+ filterUpdate: function (filters) {
275
+ this.filters = [...filters]
276
+ this.currentFilters['meridian']['list'] = []
277
+ this.filters.forEach((filter) => {
278
+ if (filter.facetPropPath === "acupoints.visualized") {
279
+ if (filter.facet === "Visualized") {
280
+ this.currentFilters['curated'] = 'Curated'
281
+ } else if (filter.facet === 'Non visualized') {
282
+ this.currentFilters['curated'] = 'Uncurated'
283
+ } else {
284
+ this.currentFilters['curated'] = 'Both'
285
+ }
286
+ }
287
+ if (filter.facetPropPath === "acupoints.onMRI") {
288
+ if (filter.facet === "Marked") {
289
+ this.currentFilters['mri'] = 'On'
290
+ } else if (filter.facet === 'Unmarked') {
291
+ this.currentFilters['mri'] = 'Off'
292
+ } else {
293
+ this.currentFilters['mri'] = 'Both'
294
+ }
295
+ }
296
+ if (filter.facetPropPath === "acupoints.WHO") {
297
+ if (filter.facet === "WHO") {
298
+ this.currentFilters['who'] = 'Yes'
299
+ } else if (filter.facet === 'Non who') {
300
+ this.currentFilters['who'] = 'No'
301
+ } else {
302
+ this.currentFilters['who'] = 'Both'
303
+ }
304
+ }
305
+ if (filter.facetPropPath === "acupoints.userDefined") {
306
+ if (filter.facet === "User data") {
307
+ this.currentFilters['userDefined'] = 'Yes'
308
+ } else if (filter.facet === 'Official data') {
309
+ this.currentFilters['userDefined'] = 'No'
310
+ } else {
311
+ this.currentFilters['userDefined'] = 'Both'
312
+ }
313
+ }
314
+ if (filter.facetPropPath === "acupoints.meridian") {
315
+ if (filter.facet === "Show all") {
316
+ this.currentFilters['meridian']['showAll'] = true
317
+ } else {
318
+ this.currentFilters['meridian']['showAll'] = false
319
+ this.currentFilters['meridian']['list'].push(filter.facet.toLowerCase())
320
+ }
321
+ }
322
+ });
323
+
324
+ this.search( this.searchInput)
325
+ },
326
+ numberPerPageUpdate: function (val) {
327
+ this.numberPerPage = val;
328
+ this.pageChange(1);
329
+ },
330
+ hoverChanged: function (data) {
331
+ this.$emit('hover-changed', data)
332
+ },
333
+ resetSearch: function () {
334
+ this.numberOfHits = 0
335
+ this.search(this.searchInput)
336
+ },
337
+ clearSearchClicked: function () {
338
+ this.searchInput = '';
339
+ this.search("");
340
+ },
341
+ getFilteredList: function() {
342
+ let filteredList = Object.values(this.entry)
343
+ if (this.currentFilters['curated'] !== "Both") {
344
+ const curated = this.currentFilters['curated'] === "Curated" ? true : false
345
+ filteredList = filteredList.filter(
346
+ item => (item.Curated ? true : false) === curated)
347
+ }
348
+ if (this.currentFilters['mri'] !== "Both") {
349
+ const mri = this.currentFilters['mri'] === "On" ? true : false
350
+ filteredList = filteredList.filter(item => (item.onMRI ? true : false) === mri)
351
+ }
352
+ if (this.currentFilters['who'] !== "Both") {
353
+ const who = this.currentFilters['who'] === "Yes" ? true : false
354
+ filteredList = filteredList.filter(
355
+ item => (item["Meridian Point"] ? true : false) === who)
356
+ }
357
+ if (this.currentFilters['userDefined'] !== "Both") {
358
+ const user = this.currentFilters['userDefined'] === "Yes" ? true : false
359
+ filteredList = filteredList.filter(
360
+ item => (item["userDefined"] ? true : false) === user)
361
+ }
362
+ if (!this.currentFilters['meridian']['showAll']) {
363
+ filteredList = filteredList.filter((item) => {
364
+ let meridian = "others"
365
+ if (item.Meridian) {
366
+ meridian = item.Meridian.toLowerCase()
367
+ }
368
+ return this.currentFilters['meridian']['list'].includes(meridian)
369
+ })
370
+ }
371
+ return filteredList;
372
+ },
373
+ search: function(input) {
374
+ this.results = []
375
+ let filteredList = this.getFilteredList()
376
+ if (input === "") {
377
+ this.results = filteredList
378
+ } else {
379
+ const lowerCase = input.toLowerCase()
380
+ for (const value of filteredList) {
381
+ const searchFields = [
382
+ value["Acupoint"],
383
+ value["Synonym"],
384
+ value["Chinese Name"],
385
+ value["English Name"],
386
+ value["Reference"],
387
+ value["Indications"],
388
+ value["Acupuncture Method"],
389
+ value["Vasculature"],
390
+ value["Innervation"],
391
+ value["Note"],
392
+ ];
393
+ const allstrings = searchFields.join();
394
+ const myJSON = allstrings.toLowerCase();
395
+ if (myJSON.includes(lowerCase)) {
396
+ this.results.push(value)
397
+ }
398
+ }
399
+ }
400
+ this.results.sort((a, b) => {
401
+ if (a["Meridian Point"] == b["Meridian Point"]) {
402
+ return a['Acupoint'].localeCompare(b['Acupoint'], undefined, { numeric: true })
403
+ } else if (a["Meridian Point"]) {
404
+ return -1
405
+ } else {
406
+ return 1
407
+ }
408
+ })
409
+
410
+ const start = this.numberPerPage * (this.page - 1)
411
+ this.paginatedResults = this.results.slice(start, start + this.numberPerPage)
412
+ this.numberOfHits = this.results.length
413
+ this.searchInput = input
414
+ this.lastSearch = input
415
+ this.$emit("acupoints-result", {
416
+ list: this.results
417
+ });
418
+ },
419
+ openSearch: function (filters, searchTerm = '') {
420
+ this.searchInput = searchTerm
421
+ this.filterUpdate(filters)
422
+ this.$refs.filtersRef.setCascader(this.filters)
423
+ },
424
+ numberPerPageUpdate: function (val) {
425
+ this.numberPerPage = val
426
+ this.pageChange(1)
427
+ },
428
+ pageChange: function (page) {
429
+ this.page = page
430
+ this.search( this.searchInput)
431
+ },
432
+ scrollToTop: function () {
433
+ if (this.$refs.content) {
434
+ this.$refs.content.scroll({ top: 0, behavior: 'smooth' })
435
+ }
436
+ },
437
+ resetPageNavigation: function () {
438
+ this.page = 1
439
+ },
440
+ },
441
+ }
442
+ </script>
443
+
444
+ <style lang="scss" scoped>
445
+
446
+ .acuRadioGroup {
447
+ padding-top: 8px;
448
+ }
449
+
450
+ .dataset-card {
451
+ position: relative;
452
+
453
+ &::before {
454
+ content: "";
455
+ display: block;
456
+ width: calc(100% - 15px);
457
+ height: 100%;
458
+ position: absolute;
459
+ top: 7px;
460
+ left: 7px;
461
+ border-style: solid;
462
+ border-radius: 5px;
463
+ border-color: transparent;
464
+ }
465
+
466
+ &:hover {
467
+ &::before {
468
+ border-color: var(--el-color-primary);
469
+ }
470
+ }
471
+ }
472
+
473
+ .main {
474
+ font-size: 14px;
475
+ text-align: left;
476
+ line-height: 1.5em;
477
+ font-family: Asap, sans-serif, Helvetica;
478
+ font-weight: 400;
479
+ /* outline: thin red solid; */
480
+ overflow-y: auto;
481
+ scrollbar-width: thin;
482
+ min-width: 16rem;
483
+ background-color: #f7faff;
484
+ height: 100%;
485
+ border-left: 1px solid var(--el-border-color);
486
+ border-top: 1px solid var(--el-border-color);
487
+ display: flex;
488
+ flex-direction: column;
489
+ gap: 1rem;
490
+ padding: 1rem;
491
+ }
492
+
493
+ .step-item {
494
+ font-size: 14px;
495
+ margin-bottom: 8px;
496
+ text-align: left;
497
+ }
498
+
499
+ .search-input {
500
+ width: 298px !important;
501
+ height: 40px;
502
+ padding-right: 14px;
503
+
504
+ :deep(.el-input__inner) {
505
+ font-family: inherit;
506
+ }
507
+ }
508
+
509
+ .header {
510
+ .el-button {
511
+ font-family: inherit;
512
+
513
+ &:hover,
514
+ &:focus {
515
+ background: $app-primary-color;
516
+ box-shadow: -3px 2px 4px #00000040;
517
+ color: #fff;
518
+ }
519
+ }
520
+ }
521
+
522
+ .pagination {
523
+ padding-bottom: 16px;
524
+ background-color: white;
525
+ padding-left: 95px;
526
+ font-weight: bold;
527
+ }
528
+
529
+ .pagination :deep(button) {
530
+ background-color: white !important;
531
+ }
532
+ .pagination :deep(li) {
533
+ background-color: white !important;
534
+ }
535
+ .pagination :deep(li.is-active) {
536
+ color: $app-primary-color;
537
+ }
538
+
539
+ .error-feedback {
540
+ font-family: Asap;
541
+ font-size: 14px;
542
+ font-style: italic;
543
+ padding-top: 15px;
544
+ }
545
+
546
+ .content-card :deep(.el-card__header) {
547
+ background-color: #292b66;
548
+ padding: 1rem;
549
+ }
550
+
551
+ .content-card :deep(.el-card__body) {
552
+ background-color: #f7faff;
553
+ overflow-y: hidden;
554
+ padding: 1rem;
555
+ }
556
+
557
+ .content {
558
+ // width: 515px;
559
+ flex: 1 1 auto;
560
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.06);
561
+ border: solid 1px #e4e7ed;
562
+ background-color: #ffffff;
563
+ overflow-y: scroll;
564
+ scrollbar-width: thin;
565
+ border-radius: var(--el-border-radius-base);
566
+ }
567
+
568
+ .content :deep(.el-loading-spinner .path) {
569
+ stroke: $app-primary-color;
570
+ }
571
+
572
+ .content :deep(.step-item:first-child .seperator-path) {
573
+ display: none;
574
+ }
575
+
576
+ .content :deep(.step-item:not(:first-child) .seperator-path) {
577
+ width: 455px;
578
+ height: 0px;
579
+ border: solid 1px #e4e7ed;
580
+ background-color: #e4e7ed;
581
+ }
582
+
583
+ .filter-text {
584
+ top:4px;
585
+ position:relative;
586
+ }
587
+
588
+ .scrollbar::-webkit-scrollbar-track {
589
+ border-radius: 10px;
590
+ background-color: #f5f5f5;
591
+ }
592
+
593
+ .scrollbar::-webkit-scrollbar {
594
+ width: 12px;
595
+ right: -12px;
596
+ background-color: #f5f5f5;
597
+ }
598
+
599
+ .scrollbar::-webkit-scrollbar-thumb {
600
+ border-radius: 4px;
601
+ box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.06);
602
+ background-color: #979797;
603
+ }
604
+
605
+ :deep(.el-input__suffix) {
606
+ padding-right: 0px;
607
+ }
608
+
609
+ :deep(.my-drawer) {
610
+ background: rgba(0, 0, 0, 0);
611
+ box-shadow: none;
612
+ }
613
+
614
+ .error-feedback {
615
+ font-family: Asap;
616
+ font-size: 14px;
617
+ font-style: italic;
618
+ padding-top: 15px;
619
+ }
620
+ </style>
@@ -935,6 +935,9 @@ export default {
935
935
  return null;
936
936
  }
937
937
 
938
+ //A scicrunch entry typically looks like https://scicrunch.org/resolver/RRID:XXXXXX
939
+ //but due to CORS issue, we need to replace it with sparc-api interface,
940
+ //Replacing the domain while leaving the subpath the same.
938
941
  const APIURL = isScicrunchURL
939
942
  ? url.replace(scicrunchBase, `${apiLocationBase}scicrunch`)
940
943
  : url.replace(orcidBase, orcidAPIBase);
@@ -92,6 +92,7 @@
92
92
  </el-cascader>
93
93
  <div v-if="showFiltersText" class="filter-default-value">Filters</div>
94
94
  <el-popover
95
+ v-if="entry.helper"
95
96
  title="How do filters work?"
96
97
  width="250"
97
98
  trigger="hover"
@@ -340,7 +341,7 @@ export default {
340
341
  });
341
342
 
342
343
  // trigger reactivity only once
343
- Object.assign(this.options, processedOptions);
344
+ Object.assign(this.options, processedOptions)
344
345
  },
345
346
  populateCascader: function () {
346
347
  if (this.entry.options) {
@@ -520,7 +521,14 @@ export default {
520
521
  });
521
522
  return count;
522
523
  }
523
- return facet.children.length;
524
+ const found = facet.children.find((item) => {
525
+ return item.label === "Show all"
526
+ })
527
+ if (found) {
528
+ return facet.children.length - 1
529
+ }
530
+
531
+ return facet.children.length
524
532
  },
525
533
  /**
526
534
  * When check/uncheck all child items, automatically check "Show all"