@abi-software/map-side-bar 2.11.4 → 2.12.0-acupoints.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abi-software/map-side-bar",
3
- "version": "2.11.4",
3
+ "version": "2.12.0-acupoints.1",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
package/src/App.vue CHANGED
@@ -18,6 +18,7 @@
18
18
  <el-button @click="keywordSearch">keyword search</el-button>
19
19
  <el-button @click="getFacets">Get facets</el-button>
20
20
  <el-button @click="toggleCreateData">Create Data/Annotation</el-button>
21
+ <el-button @click="searchAcupoints">Search Acupoints</el-button>
21
22
  <el-button @click="openConnectivitySearch()">Connectivity Search</el-button>
22
23
  </div>
23
24
  <SideBar
@@ -26,14 +27,18 @@
26
27
  ref="sideBar"
27
28
  :visible="sideBarVisibility"
28
29
  :annotationEntry="annotationEntry"
30
+ :acupointsInfoList="acupoints"
29
31
  :createData="createData"
30
32
  :connectivityEntry="connectivityEntry"
31
33
  :connectivityKnowledge="connectivityKnowledge"
32
34
  :showVisibilityFilter="true"
35
+ :tabs="tabArray"
33
36
  @search-changed="searchChanged($event)"
34
37
  @hover-changed="hoverChanged($event)"
35
38
  @connectivity-hovered="onConnectivityHovered"
36
39
  @actionClick="action"
40
+ @acupoints-clicked="onAcupointsClicked"
41
+ @acupoints-hovered="onAcupointsHovered"
37
42
  @connectivity-collapse-change="onConnectivityCollapseChange"
38
43
  />
39
44
  </div>
@@ -42,6 +47,7 @@
42
47
  <script>
43
48
  /* eslint-disable no-alert, no-console */
44
49
  // optionally import default styles
50
+ import { acupointEntries } from './acupoints.js'
45
51
  import SideBar from './components/SideBar.vue'
46
52
  import EventBus from './components/EventBus.js'
47
53
  import exampleConnectivityInput from './exampleConnectivityInput.js'
@@ -121,6 +127,14 @@ export default {
121
127
  },
122
128
  data: function () {
123
129
  return {
130
+ acupoints: acupointEntries,
131
+ contextArray: [null, null],
132
+ tabArray: [
133
+ { title: 'Dataset Explorer', id: 1, type: 'datasetExplorer', closable: false },
134
+ { title: 'Connectivity Explorer', id: 2, type: 'connectivityExplorer', closable: false },
135
+ { title: 'Annotation', id: 3, type: 'annotation', closable: true },
136
+ {title: 'Acupoints', id: 4, type: 'acupoints' },
137
+ ],
124
138
  annotationEntry: [{
125
139
  featureId: "epicardium",
126
140
  resourceId: "https://mapcore-bucket1.s3-us-west-2.amazonaws.com/others/29_Jan_2020/heartICN_metadata.json",
@@ -156,6 +170,12 @@ export default {
156
170
  }
157
171
  },
158
172
  methods: {
173
+ onAcupointsClicked: function (data) {
174
+ console.log("acupoints-clicked", data)
175
+ },
176
+ onAcupointsHovered: function (data) {
177
+ console.log("acupoints-hovered", data)
178
+ },
159
179
  loadConnectivityKnowledge: async function () {
160
180
  const sql = `select knowledge from knowledge
161
181
  where source="${this.sckanVersion}"
@@ -232,6 +252,9 @@ export default {
232
252
  'http://purl.obolibrary.org/obo/UBERON_0001103'
233
253
  )
234
254
  },
255
+ searchAcupoints: function() {
256
+ this.$refs.sideBar.openAcupointsSearch("LU 1")
257
+ },
235
258
  singleFacets: function () {
236
259
  this.$refs.sideBar.addFilter({
237
260
  facet: 'Cardiovascular system',
@@ -406,4 +429,4 @@ body {
406
429
  align-items: center;
407
430
  gap: 0.5rem;
408
431
  }
409
- </style>
432
+ </style>./acupoints.js
@@ -0,0 +1,49 @@
1
+ export const acupointEntries = {
2
+ "LU 1": {
3
+ "Acupoint": "LU 1",
4
+ "Label": "LU 1",
5
+ "Synonym": "Test data",
6
+ "UMLS CUI": "",
7
+ "Meridian": "LTest data",
8
+ "Chinese Name": "Zhongfu",
9
+ "English Name": "Central Treasury",
10
+ "Location": " z zxczc.",
11
+ "Reference": "Test data",
12
+ "Indications": "Test data",
13
+ "Acupuncture Method": "Test data",
14
+ "Vasculature": "Test data",
15
+ "Innervation": "Test data",
16
+ "Curated": false,
17
+ },
18
+ "LU 2": {
19
+ "Acupoint": "LU 2",
20
+ "Label": "LU 2",
21
+ "Synonym": "Test data",
22
+ "UMLS CUI": "",
23
+ "Meridian": "LTest data",
24
+ "Chinese Name": "Yunmen",
25
+ "English Name": "Cloud Gate",
26
+ "Location": " z zxczc.",
27
+ "Reference": "Test data",
28
+ "Indications": "Test data",
29
+ "Acupuncture Method": "Test data",
30
+ "Vasculature": "Test data",
31
+ "Innervation": "Test data",
32
+ "Curated": true,
33
+ },
34
+ "ST 3": {
35
+ "Acupoint": "ST 3",
36
+ "Label": "ST 3",
37
+ "Synonym": "Test data",
38
+ "UMLS CUI": "",
39
+ "Meridian": "STest data",
40
+ "Chinese Name": "Cheng Qi",
41
+ "English Name": "Not Available",
42
+ "Location": " z zxcxadadadzc.",
43
+ "Reference": "Test data",
44
+ "Indications": "Test data",
45
+ "Acupuncture Method": "Test data",
46
+ "Vasculature": "Test data",
47
+ "Innervation": "Test data"
48
+ }
49
+ }
@@ -187,24 +187,47 @@ export class AlgoliaClient {
187
187
  * This is using fetch from the Algolia API
188
188
  */
189
189
  search(filter, query = '', hitsperPage = 10, page = 1) {
190
+ const terms = query.replaceAll('"', '').split(",")
191
+ let processed = "";
192
+ const optionalWords = [];
193
+ if (terms) {
194
+ if (terms.length === 1 && (!(query.includes(" ")))) {
195
+ processed = query;
196
+ } else {
197
+ terms.forEach(term => {
198
+ optionalWords.push(term.trim())
199
+ processed += `"${term.trim()}" `;
200
+ });
201
+ }
202
+ }
203
+ processed = processed.trim()
204
+
205
+ const payload = {
206
+ advancedSyntax: true,
207
+ advancedSyntaxFeatures: ['exactPhrase'],
208
+ queryType: 'prefixAll',
209
+ facets: ['*'],
210
+ hitsPerPage: hitsperPage,
211
+ page: page - 1,
212
+ filters: filter,
213
+ attributesToHighlight: [],
214
+ attributesToRetrieve: [
215
+ 'pennsieve.publishDate',
216
+ 'pennsieve.updatedAt',
217
+ 'item.curie',
218
+ 'item.name',
219
+ 'item.description',
220
+ 'objectID',
221
+ 'anatomy.organ.curie'
222
+ ],
223
+ }
224
+ if (optionalWords.length > 1) {
225
+ payload.optionalWords = optionalWords
226
+ }
227
+
190
228
  return new Promise(resolve => {
191
229
  this.index
192
- .search(query, {
193
- facets: ['*'],
194
- hitsPerPage: hitsperPage,
195
- page: page - 1,
196
- filters: filter,
197
- attributesToHighlight: [],
198
- attributesToRetrieve: [
199
- 'pennsieve.publishDate',
200
- 'pennsieve.updatedAt',
201
- 'item.curie',
202
- 'item.name',
203
- 'item.description',
204
- 'objectID',
205
- 'anatomy.organ.curie'
206
- ],
207
- })
230
+ .search(processed, payload)
208
231
  .then(response => {
209
232
  let searchData = {
210
233
  items: this._processResultsForCards(response.hits),
@@ -299,7 +322,7 @@ export class AlgoliaClient {
299
322
  const anatomyOrganSubcategoryNames = anatomyOrganSubcategoryName ? Object.keys(anatomyOrganSubcategoryName) : []
300
323
  const anatomyOrganSubsubcategoryNames = anatomyOrganSubsubcategoryName ? Object.keys(anatomyOrganSubsubcategoryName) : []
301
324
  const filteredOrganNames = []
302
-
325
+
303
326
  anatomyOrganCategoryNames.forEach((_categoryName) => {
304
327
  const categoryName = _categoryName.toLowerCase();
305
328
  anatomyOrganNames.forEach((_organName) => {
@@ -313,7 +336,7 @@ export class AlgoliaClient {
313
336
  } else {
314
337
  return anatomyOrganSubsubcategoryNames.find((name) => {
315
338
  const fullsubsubname = `${subcategoryName}.${organName}`
316
- return (fullsubsubname === name)
339
+ return (fullsubsubname === name)
317
340
  })
318
341
  }
319
342
  });
@@ -0,0 +1,90 @@
1
+
2
+ .filter-help-popover {
3
+ font-family: 'Asap', sans-serif;
4
+ background: #f3ecf6 !important;
5
+ border: 1px solid $app-primary-color !important;
6
+ border-radius: 4px !important;
7
+ color: #303133 !important;
8
+ font-size: 12px !important;
9
+ line-height: 18px !important;
10
+
11
+ > div {
12
+ word-break: break-word;
13
+ text-align: initial;
14
+ }
15
+
16
+ ul {
17
+ padding-left: 1.5rem;
18
+
19
+ > li + li {
20
+ margin-top: 0.5rem;
21
+ }
22
+ }
23
+
24
+ .el-popper__arrow::before {
25
+ background: #f3ecf6 !important;
26
+ border-color: $app-primary-color !important;
27
+ }
28
+
29
+ &[data-popper-placement^=bottom] .el-popper__arrow:before {
30
+ border-bottom-color: transparent !important;
31
+ border-right-color: transparent !important;
32
+ }
33
+
34
+ code {
35
+ font-size: 90%;
36
+ }
37
+ }
38
+
39
+ .header {
40
+ display: flex;
41
+ align-items: center;
42
+
43
+ .el-button {
44
+ font-family: inherit;
45
+
46
+ &:hover,
47
+ &:focus {
48
+ background: $app-primary-color;
49
+ box-shadow: -3px 2px 4px #00000040;
50
+ color: #ffffff;
51
+ }
52
+ }
53
+ }
54
+
55
+ .help {
56
+ width: 24px !important;
57
+ height: 24px;
58
+ transform: scale(1.1);
59
+ cursor: pointer;
60
+ color: #ffffff !important;
61
+ }
62
+
63
+ .search-input {
64
+ width: 298px !important;
65
+ height: 40px;
66
+ padding-right: 14px;
67
+ font-family: inherit;
68
+
69
+ :deep(.el-input__inner) {
70
+ font-family: inherit;
71
+ }
72
+ }
73
+
74
+ .search-input-container {
75
+ position: relative;
76
+ display: flex;
77
+ align-items: center;
78
+
79
+ .map-icon {
80
+ position: absolute;
81
+ right: 18px;
82
+ color: $app-primary-color !important;
83
+ }
84
+
85
+ &.is-focus {
86
+ .map-icon {
87
+ display: none;
88
+ }
89
+ }
90
+ }
@@ -0,0 +1,215 @@
1
+ <template>
2
+ <div class="dataset-card-container" ref="container">
3
+ <div class="dataset-card" ref="card">
4
+ <div class="seperator-path"></div>
5
+ <div class="card"
6
+ @click="cardClicked(entry)"
7
+ @mouseover="cardHovered(entry)"
8
+ @mouseleave="cardHovered(undefined)"
9
+ >
10
+ <div class="card-right">
11
+ <el-collapse class="collapse-card" v-model="expanded" @change="expandedChanged">
12
+ <el-collapse-item :title="entry.Acupoint" name="1" class="collapse-card">
13
+ <template v-for="field in displayFields" :key="field['name']">
14
+ <div class="details" >
15
+ <strong>{{ field['name'] }}: </strong>
16
+ <span
17
+ v-if="!field['isEditing']"
18
+ @click="field['isEditing'] = true"
19
+ >
20
+ {{ entry[field['name']] || 'Not Available' }}
21
+ </span>
22
+ <el-input
23
+ v-else
24
+ v-model="entry[field['name']]"
25
+ @blur="field['isEditing'] = false"
26
+ @keyup.enter="field['isEditing'] = false"
27
+ @vue:mounted="inputMounted"
28
+ type="textarea"
29
+ />
30
+ </div>
31
+ </template>
32
+ </el-collapse-item>
33
+ </el-collapse>
34
+ </div>
35
+ </div>
36
+ </div>
37
+ </div>
38
+ </template>
39
+
40
+ <script>
41
+ import EventBus from './EventBus.js'
42
+ /* eslint-disable no-alert, no-console */
43
+
44
+ export default {
45
+ data() {
46
+ return {
47
+ expanded: [],
48
+ displayFields: [
49
+ {name: "Synonym", isEditing: false},
50
+ {name: "Chinese Name", isEditing: false},
51
+ {name: "English Name", isEditing: false},
52
+ {name: "Reference", isEditing: false},
53
+ {name: "Indications", isEditing: false},
54
+ {name: "Acupuncture Method", isEditing: false},
55
+ {name: "Vasculature", isEditing: false},
56
+ {name: "Innervation", isEditing: false},
57
+ {name: "Notes", isEditing: false},
58
+ ]
59
+ }
60
+ },
61
+ name: 'AcupointsCard',
62
+ props: {
63
+ /**
64
+ * Object containing information for
65
+ * the required viewing.
66
+ */
67
+ entry: {
68
+ type: Object,
69
+ default: () => {},
70
+ },
71
+ },
72
+ methods: {
73
+ expandedChanged: function() {
74
+ if (this.expanded.length > 0) {
75
+ EventBus.emit('acupoints-clicked', this.entry);
76
+ }
77
+ },
78
+ cardClicked: function (data) {
79
+ EventBus.emit('acupoints-clicked', data);
80
+ },
81
+ cardHovered: function (data) {
82
+ EventBus.emit('acupoints-hovered', data);
83
+ },
84
+ inputMounted: function(event) {
85
+ event.el?.querySelector('textarea')?.focus();
86
+ }
87
+ }
88
+ }
89
+ </script>
90
+
91
+ <style lang="scss" scoped>
92
+
93
+ :deep(.el-collapse-item__header) {
94
+ font-weight: bold;
95
+ }
96
+
97
+ :deep(.el-collapse-item__content) {
98
+ padding-bottom: 4px;
99
+ }
100
+
101
+ :deep(.el-collapse-item__wrap) {
102
+ border: none;
103
+ }
104
+
105
+ .collapse-card {
106
+ border-top: none;
107
+ :deep(.el-collapse-item__header) {
108
+ border-bottom: none;
109
+ }
110
+ }
111
+
112
+ .dataset-card {
113
+ padding-left: 5px;
114
+ padding-right: 5px;
115
+ position: relative;
116
+ }
117
+
118
+ .title {
119
+ padding-bottom: 0.75rem;
120
+ font-family: Asap;
121
+ font-size: 14px;
122
+ font-weight: bold;
123
+ font-stretch: normal;
124
+ font-style: normal;
125
+ line-height: 1.5;
126
+ letter-spacing: 1.05px;
127
+ color: #484848;
128
+ cursor: pointer;
129
+ }
130
+ .card {
131
+ padding-top: 12px;
132
+ position: relative;
133
+ display: flex;
134
+ }
135
+
136
+ .card-left {
137
+ flex: 1;
138
+ }
139
+
140
+ .card-right {
141
+ flex: 1.3;
142
+ padding-left: 6px;
143
+ }
144
+
145
+ .button {
146
+ z-index: 10;
147
+ font-family: Asap;
148
+ font-size: 14px;
149
+ font-weight: normal;
150
+ font-stretch: normal;
151
+ font-style: normal;
152
+ line-height: normal;
153
+ letter-spacing: normal;
154
+ background-color: $app-primary-color;
155
+ border: $app-primary-color;
156
+ color: white;
157
+ cursor: pointer;
158
+ margin-top: 8px;
159
+ }
160
+
161
+ .button:hover {
162
+ background-color: $app-primary-color;
163
+ color: white;
164
+ }
165
+
166
+ .banner-img {
167
+ width: 128px;
168
+ height: 128px;
169
+ box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.25);
170
+ background-color: #ffffff;
171
+ cursor: pointer;
172
+ }
173
+ .details {
174
+ font-family: Asap;
175
+ font-size: 14px;
176
+ font-weight: normal;
177
+ font-stretch: normal;
178
+ font-style: normal;
179
+ line-height: 1.5;
180
+ letter-spacing: 1.05px;
181
+ color: #484848;
182
+ }
183
+
184
+ .badges-container {
185
+ margin-top: 0.75rem;
186
+ }
187
+
188
+ .loading-icon {
189
+ z-index: 20;
190
+ width: 40px;
191
+ height: 40px;
192
+ left: 80px;
193
+ }
194
+
195
+ .loading-icon :deep(.el-loading-mask) {
196
+ background-color: rgba(117, 190, 218, 0) !important;
197
+ }
198
+
199
+ .loading-icon :deep(.el-loading-spinner .path) {
200
+ stroke: $app-primary-color;
201
+ }
202
+
203
+ .float-button-container {
204
+ position: absolute;
205
+ bottom: 8px;
206
+ right: 16px;
207
+ opacity: 0;
208
+ visibility: hidden;
209
+
210
+ .card:hover & {
211
+ opacity: 1;
212
+ visibility: visible;
213
+ }
214
+ }
215
+ </style>