@abi-software/map-side-bar 2.19.1-demo.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abi-software/map-side-bar",
3
- "version": "2.19.1-demo.0",
3
+ "version": "2.20.0-acuppoints.0",
4
4
  "license": "Apache-2.0",
5
5
  "engines": {
6
6
  "node": "^24.20.0"
@@ -49,8 +49,8 @@
49
49
  "./src/*": "./src/*"
50
50
  },
51
51
  "dependencies": {
52
- "@abi-software/gallery": "1.6.0",
53
- "@abi-software/map-utilities": "1.12.0",
52
+ "@abi-software/gallery": "1.7.0",
53
+ "@abi-software/map-utilities": "1.13.0",
54
54
  "@abi-software/svg-sprite": "1.4.0",
55
55
  "@element-plus/icons-vue": "^2.3.2",
56
56
  "algoliasearch": "^4.27.0",
package/src/App.vue CHANGED
@@ -14,8 +14,8 @@
14
14
  <el-button @click="keywordSearch">keyword search</el-button>
15
15
  <el-button @click="getFacets">Get facets</el-button>
16
16
  <el-button @click="toggleCreateData">Create Data/Annotation</el-button>
17
+ <el-button @click="searchAcupoints">Search Acupoints</el-button>
17
18
  <el-button @click="openConnectivitySearch()">Connectivity Search</el-button>
18
- <el-button @click="showCellCardExplorer()">Show Cell Card Explorer</el-button>
19
19
  </div>
20
20
  <SideBar
21
21
  :envVars="envVars"
@@ -23,15 +23,19 @@
23
23
  ref="sideBar"
24
24
  :visible="sideBarVisibility"
25
25
  :annotationEntry="annotationEntry"
26
+ :acupointsInfoList="acupoints"
26
27
  :createData="createData"
27
28
  :connectivityEntry="connectivityEntry"
28
29
  :connectivityKnowledge="connectivityKnowledge"
29
30
  :showVisibilityFilter="true"
30
- :showCellCards="showCellCards"
31
+ :tabs="tabArray"
31
32
  @search-changed="searchChanged($event)"
32
33
  @hover-changed="hoverChanged($event)"
33
34
  @connectivity-hovered="onConnectivityHovered"
34
35
  @actionClick="action"
36
+ @acupoints-clicked="onAcupointsClicked"
37
+ @acupoints-hovered="onAcupointsHovered"
38
+ @acupoints-result="onAcupointsResult"
35
39
  @connectivity-collapse-change="onConnectivityCollapseChange"
36
40
  />
37
41
  </div>
@@ -39,10 +43,13 @@
39
43
 
40
44
  <script>
41
45
  // optionally import default styles
42
- import SideBar from './components/SideBar.vue';
43
- import EventBus from './components/EventBus.js';
44
- import exampleConnectivityInput from './exampleConnectivityInput.js';
45
- import { capitalise } from './utils/common.js';
46
+ import { acupointEntries } from './acupoints.js'
47
+ import SideBar from './components/SideBar.vue'
48
+ import EventBus from './components/EventBus.js'
49
+ import exampleConnectivityInput from './exampleConnectivityInput.js'
50
+
51
+
52
+ const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
46
53
 
47
54
  const flatmapQuery = (flatmapApi, sql) => {
48
55
  const data = { sql: sql };
@@ -116,6 +123,13 @@ export default {
116
123
  },
117
124
  data: function () {
118
125
  return {
126
+ acupoints: acupointEntries,
127
+ tabArray: [
128
+ { title: 'Dataset Explorer', id: 1, type: 'datasetExplorer', closable: false },
129
+ { title: 'Connectivity Explorer', id: 2, type: 'connectivityExplorer', closable: false },
130
+ { title: 'Annotation', id: 3, type: 'annotation', closable: true },
131
+ {title: 'Acupoints', id: 4, type: 'acupoints' },
132
+ ],
119
133
  annotationEntry: [
120
134
  {
121
135
  featureId: 'epicardium',
@@ -135,7 +149,6 @@ export default {
135
149
  BL_SERVER_URL: import.meta.env.VITE_BL_SERVER_URL,
136
150
  ROOT_URL: import.meta.env.VITE_ROOT_URL,
137
151
  FLATMAPAPI_LOCATION: import.meta.env.VITE_FLATMAPAPI_LOCATION,
138
- CELL_CARDS_API: import.meta.env.VITE_APP_CELL_CARDS_API,
139
152
  },
140
153
  connectivityEntry: [],
141
154
  createData: {
@@ -152,10 +165,18 @@ export default {
152
165
  query: '',
153
166
  filter: [],
154
167
  target: [],
155
- showCellCards: false,
156
168
  };
157
169
  },
158
170
  methods: {
171
+ onAcupointsClicked: function (data) {
172
+ console.log("acupoints-clicked", data)
173
+ },
174
+ onAcupointsHovered: function (data) {
175
+ console.log("acupoints-hovered", data)
176
+ },
177
+ onAcupointsResult: function (data) {
178
+ console.log("acupoints-result", data)
179
+ },
159
180
  loadConnectivityKnowledge: async function () {
160
181
  const sql = `select knowledge from knowledge
161
182
  where source="${this.sckanVersion}"
@@ -231,6 +252,9 @@ export default {
231
252
  openSearch: function () {
232
253
  this.$refs.sideBar.openSearch([], 'http://purl.obolibrary.org/obo/UBERON_0001103');
233
254
  },
255
+ searchAcupoints: function() {
256
+ this.$refs.sideBar.openAcupointsSearch("LU 1")
257
+ },
234
258
  singleFacets: function () {
235
259
  this.$refs.sideBar.addFilter({
236
260
  facet: 'Cardiovascular system',
@@ -367,11 +391,6 @@ export default {
367
391
  onConnectivityCollapseChange: function () {
368
392
  this.connectivityEntry = [...exampleConnectivityInput];
369
393
  },
370
- showCellCardExplorer: function () {
371
- this.showCellCards = true;
372
- this.$refs.sideBar.tabClicked({ id: 4, type: 'cellCardExplorer' });
373
- this.$refs.sideBar.setDrawerOpen(true);
374
- },
375
394
  },
376
395
  mounted: async function () {
377
396
  console.log('mounted app');
@@ -0,0 +1,78 @@
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
+ "onMRI": true,
18
+ "Meridian Point": true,
19
+ "Link": "https://tara-repository.mgb.org/term_resolution/tara.html"
20
+ },
21
+ "LU 2": {
22
+ "Acupoint": "LU 2",
23
+ "Label": "LU 2",
24
+ "Synonym": "Test data",
25
+ "UMLS CUI": "",
26
+ "Meridian": "LTest data",
27
+ "Chinese Name": "Yunmen",
28
+ "English Name": "Cloud Gate",
29
+ "Location": " z zxczc.",
30
+ "Reference": "Test data",
31
+ "Indications": "Test data",
32
+ "Acupuncture Method": "Test data",
33
+ "Vasculature": "Test data",
34
+ "Innervation": "Test data",
35
+ "Curated": true,
36
+ "onMRI": true,
37
+ "Meridian Point": false,
38
+ "Link": "https://tara-repository.mgb.org/term_resolution/tara.html"
39
+ },
40
+ "ST 3": {
41
+ "Acupoint": "ST 3",
42
+ "Label": "ST 3",
43
+ "Synonym": "Test data",
44
+ "UMLS CUI": "",
45
+ "Meridian": "STest data",
46
+ "Chinese Name": "Cheng Qi",
47
+ "English Name": "Not Available",
48
+ "Location": " z zxcxadadadzc.",
49
+ "Reference": "Test data",
50
+ "Indications": "Test data",
51
+ "Acupuncture Method": "Test data",
52
+ "Vasculature": "Test data",
53
+ "Innervation": "Test data",
54
+ "Curated": true,
55
+ "onMRI": false,
56
+ "Meridian Point": false,
57
+ "Link": "https://tara-repository.mgb.org/term_resolution/tara.html"
58
+ },
59
+ "LR 4": {
60
+ "Acupoint": "LR 4",
61
+ "Label": "LR 4",
62
+ "Synonym": "Test data",
63
+ "UMLS CUI": "",
64
+ "Meridian": "STest data",
65
+ "Chinese Name": "Zhongfeng",
66
+ "English Name": "Not Available",
67
+ "Location": " z zxcxadadadzc.",
68
+ "Reference": "Test data",
69
+ "Indications": "Test data",
70
+ "Acupuncture Method": "Test data",
71
+ "Vasculature": "Test data",
72
+ "Innervation": "Test data",
73
+ "Curated": false,
74
+ "onMRI": false,
75
+ "Meridian Point": true,
76
+ "Link": "https://tara-repository.mgb.org/term_resolution/tara.html"
77
+ }
78
+ }
@@ -0,0 +1,316 @@
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 #title>
14
+ <div>
15
+ <span class="title">{{ entry.Acupoint }}</span>
16
+ <el-tag
17
+ v-for="tag in tags"
18
+ :key="tag.name"
19
+ :type="tag.type"
20
+ effect="plain"
21
+ class="acupointTags"
22
+ size="small"
23
+ >
24
+ {{ tag.name }}
25
+ </el-tag>
26
+ </div>
27
+ </template>
28
+ <template v-for="field in displayFields" :key="field['name']">
29
+ <div class="details">
30
+ <strong>{{ field['name'] }}: </strong>
31
+ <template v-if="field['name'] === 'Acupoint Curie'">
32
+ <a :href="entry['Acupoint IRI']" target="_blank">
33
+ <span>
34
+ {{ entry['Acupoint Curie'] }}
35
+ </span>
36
+ </a>
37
+ </template>
38
+ <template v-else-if="field['name'] === 'Reference'">
39
+ <div v-html="formatReference(entry[field['name']])"></div>
40
+ </template>
41
+ <template v-else>
42
+ <span
43
+ v-if="!field['isEditing']"
44
+ @click="setFieldToEditing(field)"
45
+ >
46
+ {{ entry[field['name']] || 'Not Available' }}
47
+ </span>
48
+ <el-input
49
+ v-else
50
+ v-model="entry[field['name']]"
51
+ @blur="field['isEditing'] = false"
52
+ @keyup.enter="field['isEditing'] = false"
53
+ @vue:mounted="inputMounted"
54
+ type="textarea"
55
+ />
56
+ </template>
57
+ </div>
58
+ </template>
59
+ </el-collapse-item>
60
+ </el-collapse>
61
+ </div>
62
+ </div>
63
+ </div>
64
+ </div>
65
+ </template>
66
+
67
+ <script>
68
+ import EventBus from './EventBus.js'
69
+ import {
70
+ ElCollapse as Collapse,
71
+ ElCollapseItem as CollapseItem,
72
+ ElTag as Tag
73
+ } from 'element-plus'
74
+ /* eslint-disable no-alert, no-console */
75
+
76
+ export default {
77
+ components: {
78
+ Collapse,
79
+ CollapseItem,
80
+ Tag
81
+ },
82
+ data() {
83
+ return {
84
+ expanded: [],
85
+ tags: [],
86
+ displayFields: [
87
+ {name: "Acupoint Curie", isEditing: false},
88
+ {name: "Acupoint", isEditing: false},
89
+ {name: "Acupoint Category", isEditing: false},
90
+ {name: "Synonym", isEditing: false},
91
+ {name: "Pinyin Name", isEditing: false},
92
+ {name: "Chinese Name", isEditing: false},
93
+ {name: "Meridian", isEditing: false},
94
+ {name: "Special Point Role", isEditing: false},
95
+ {name: "Location", isEditing: false},
96
+ {name: "Location Anatomy", isEditing: false},
97
+ {name: "Acupuncture Method", isEditing: false},
98
+ {name: "Indications", isEditing: false},
99
+ {name: "Innervation", isEditing: false},
100
+ {name: "Nearby Nerve", isEditing: false},
101
+ {name: "Vasculature", isEditing: false},
102
+ {name: "Nearby Artery", isEditing: false},
103
+ {name: "Nearby Vein", isEditing: false},
104
+ {name: "Reference", isEditing: false},
105
+ //{name: "Notes", isEditing: false},
106
+ ]
107
+ }
108
+ },
109
+ name: 'AcupointsCard',
110
+ props: {
111
+ /**
112
+ * Object containing information for
113
+ * the required viewing.
114
+ */
115
+ entry: {
116
+ type: Object,
117
+ default: () => {},
118
+ },
119
+ allowEditing: {
120
+ type: Boolean,
121
+ default: false,
122
+ },
123
+ },
124
+ created: function () {
125
+ if (this.entry["Meridian Point"]) {
126
+ this.tags.push({ name: 'WHO', type: 'info' })
127
+ }
128
+ if (this.entry.Meridian) {
129
+ this.tags.push({ name: this.entry.Meridian, type: 'info' })
130
+ }
131
+ if (this.entry.onMRI) {
132
+ this.tags.push({ name: 'Spotted', type: 'success' })
133
+ }
134
+ if (this.entry.userDefined) {
135
+ this.tags.push({ name: 'User Defined', type: 'warning' })
136
+ }
137
+ },
138
+ methods: {
139
+ expandedChanged: function() {
140
+ if (this.expanded.length > 0) {
141
+ EventBus.emit('acupoints-clicked', this.entry);
142
+ }
143
+ },
144
+ cardClicked: function (data) {
145
+ EventBus.emit('acupoints-clicked', data);
146
+ },
147
+ cardHovered: function (data) {
148
+ EventBus.emit('acupoints-hovered', data);
149
+ },
150
+ inputMounted: function(event) {
151
+ event.el?.querySelector('textarea')?.focus();
152
+ },
153
+ formatReference: function(text) {
154
+ if (!text) {
155
+ return 'Not Available';
156
+ }
157
+ // Escape HTML first so only the markup added below is rendered
158
+ const escaped = String(text)
159
+ .replace(/&/g, '&amp;')
160
+ .replace(/</g, '&lt;')
161
+ .replace(/>/g, '&gt;')
162
+ .replace(/"/g, '&quot;')
163
+ .replace(/'/g, '&#39;');
164
+ return escaped
165
+ // Bold and italicise square-bracketed labels, e.g. [Acupoint Location, Pinyin Label]
166
+ .replace(/\[([^\]\n]+)\]/g, '<strong><em>[$1]</em></strong>')
167
+ // Turn http(s) URLs into links, leaving trailing punctuation outside
168
+ .replace(/https?:\/\/[^\s<]+?(?=[.,;:!?)]*(?:\s|<|$))/g,
169
+ (url) => `<a href="${url}" target="_blank" rel="noopener noreferrer">${url}</a>`)
170
+ .replace(/\n/g, '<br>');
171
+ },
172
+ setFieldToEditing: function(field) {
173
+ if (this.allowEditing) {
174
+ field['isEditing'] = true;
175
+ }
176
+ }
177
+ },
178
+ }
179
+ </script>
180
+
181
+ <style lang="scss" scoped>
182
+
183
+ :deep(.el-collapse-item__header) {
184
+ font-weight: bold;
185
+ }
186
+
187
+ :deep(.el-collapse-item__content) {
188
+ padding-bottom: 4px;
189
+ }
190
+
191
+ :deep(.el-collapse-item__wrap) {
192
+ border: none;
193
+ }
194
+
195
+ .collapse-card {
196
+ border-top: none;
197
+ :deep(.el-collapse-item__header) {
198
+ border-bottom: none;
199
+ }
200
+ }
201
+
202
+ .dataset-card {
203
+ padding-left: 5px;
204
+ padding-right: 5px;
205
+ position: relative;
206
+ }
207
+
208
+ .title {
209
+ padding-bottom: 0.75rem;
210
+ font-family: Asap;
211
+ font-size: 14px;
212
+ font-weight: bold;
213
+ font-stretch: normal;
214
+ font-style: normal;
215
+ line-height: 1.5;
216
+ letter-spacing: 1.05px;
217
+ color: #484848;
218
+ cursor: pointer;
219
+ }
220
+ .card {
221
+ padding-top: 12px;
222
+ position: relative;
223
+ display: flex;
224
+ }
225
+
226
+ .card-left {
227
+ flex: 1;
228
+ }
229
+
230
+ .card-right {
231
+ flex: 1.3;
232
+ padding-left: 6px;
233
+ }
234
+
235
+ .button {
236
+ z-index: 10;
237
+ font-family: Asap;
238
+ font-size: 14px;
239
+ font-weight: normal;
240
+ font-stretch: normal;
241
+ font-style: normal;
242
+ line-height: normal;
243
+ letter-spacing: normal;
244
+ background-color: $app-primary-color;
245
+ border: $app-primary-color;
246
+ color: white;
247
+ cursor: pointer;
248
+ margin-top: 8px;
249
+ }
250
+
251
+ .button:hover {
252
+ background-color: $app-primary-color;
253
+ color: white;
254
+ }
255
+
256
+ .banner-img {
257
+ width: 128px;
258
+ height: 128px;
259
+ box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.25);
260
+ background-color: #ffffff;
261
+ cursor: pointer;
262
+ }
263
+ .details {
264
+ font-family: Asap;
265
+ font-size: 14px;
266
+ font-weight: normal;
267
+ font-stretch: normal;
268
+ font-style: normal;
269
+ line-height: 1.5;
270
+ letter-spacing: 1.05px;
271
+ color: #484848;
272
+ }
273
+
274
+ .badges-container {
275
+ margin-top: 0.75rem;
276
+ }
277
+
278
+ .loading-icon {
279
+ z-index: 20;
280
+ width: 40px;
281
+ height: 40px;
282
+ left: 80px;
283
+ }
284
+
285
+ .loading-icon :deep(.el-loading-mask) {
286
+ background-color: rgba(117, 190, 218, 0) !important;
287
+ }
288
+
289
+ .loading-icon :deep(.el-loading-spinner .path) {
290
+ stroke: $app-primary-color;
291
+ }
292
+
293
+ .title {
294
+ font: inherit;
295
+ margin-top:4px;
296
+ padding-right:30px;
297
+ vertical-align:middle;
298
+ }
299
+
300
+ .acupointTags {
301
+ margin-right:4px;
302
+ }
303
+
304
+ .float-button-container {
305
+ position: absolute;
306
+ bottom: 8px;
307
+ right: 16px;
308
+ opacity: 0;
309
+ visibility: hidden;
310
+
311
+ .card:hover & {
312
+ opacity: 1;
313
+ visibility: visible;
314
+ }
315
+ }
316
+ </style>