@abi-software/map-side-bar 2.14.6-demo.0 → 2.14.7

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.14.6-demo.0",
3
+ "version": "2.14.7",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
package/src/App.vue CHANGED
@@ -19,7 +19,6 @@
19
19
  <el-button @click="getFacets">Get facets</el-button>
20
20
  <el-button @click="toggleCreateData">Create Data/Annotation</el-button>
21
21
  <el-button @click="openConnectivitySearch()">Connectivity Search</el-button>
22
- <el-button @click="showCellCardExplorer()">Show Cell Card Explorer</el-button>
23
22
  </div>
24
23
  <SideBar
25
24
  :envVars="envVars"
@@ -31,7 +30,6 @@
31
30
  :connectivityEntry="connectivityEntry"
32
31
  :connectivityKnowledge="connectivityKnowledge"
33
32
  :showVisibilityFilter="true"
34
- :showCellCards="showCellCards"
35
33
  @search-changed="searchChanged($event)"
36
34
  @hover-changed="hoverChanged($event)"
37
35
  @connectivity-hovered="onConnectivityHovered"
@@ -47,7 +45,9 @@
47
45
  import SideBar from './components/SideBar.vue'
48
46
  import EventBus from './components/EventBus.js'
49
47
  import exampleConnectivityInput from './exampleConnectivityInput.js'
50
- import { capitalise } from './utils/common.js'
48
+
49
+
50
+ const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
51
51
 
52
52
  const flatmapQuery = (flatmapApi, sql) => {
53
53
  const data = { sql: sql };
@@ -136,7 +136,6 @@ export default {
136
136
  BL_SERVER_URL: import.meta.env.VITE_APP_BL_SERVER_URL,
137
137
  ROOT_URL: import.meta.env.VITE_APP_ROOT_URL,
138
138
  FLATMAPAPI_LOCATION: import.meta.env.VITE_FLATMAPAPI_LOCATION,
139
- CELL_CARDS_API: import.meta.env.VITE_APP_CELL_CARDS_API,
140
139
  },
141
140
  connectivityEntry: [],
142
141
  createData: {
@@ -153,7 +152,6 @@ export default {
153
152
  query: '',
154
153
  filter: [],
155
154
  target: [],
156
- showCellCards: false,
157
155
  }
158
156
  },
159
157
  methods: {
@@ -368,12 +366,7 @@ export default {
368
366
  },
369
367
  onConnectivityCollapseChange: function () {
370
368
  this.connectivityEntry = [...exampleConnectivityInput]
371
- },
372
- showCellCardExplorer: function () {
373
- this.showCellCards = true;
374
- this.$refs.sideBar.tabClicked({ id: 4, type: 'cellCardExplorer' });
375
- this.$refs.sideBar.setDrawerOpen(true);
376
- },
369
+ }
377
370
  },
378
371
  mounted: async function () {
379
372
  console.log('mounted app')
@@ -2,14 +2,10 @@
2
2
  * Common styles for connectivity explorer components
3
3
  */
4
4
 
5
- .id-tag,
6
- .icon-tag {
7
- color: #555;
8
- padding: 2px 4px;
9
- font-size: .75rem !important;
10
- }
11
-
12
5
  .id-tag {
6
+ color: #555;
13
7
  background: #e0e0e0;
8
+ padding: 2px 4px;
14
9
  border-radius: 4px;
10
+ font-size: .75rem !important;
15
11
  }
@@ -21,11 +21,6 @@
21
21
  <span class="id-tag" v-else>{{ entry[field] }}</span>
22
22
  </div>
23
23
  </template>
24
- <div v-if="uniqueSpecies.length" class="card-details">
25
- <span class="icon-tag" v-for="species in uniqueSpecies" :key="species.iconClass">
26
- <i :class="species.iconClass"></i>
27
- </span>
28
- </div>
29
24
  </div>
30
25
  </div>
31
26
  </div>
@@ -33,7 +28,6 @@
33
28
 
34
29
  <script>
35
30
  import EventBus from './EventBus';
36
- import { capitalise as capitaliseText } from '../utils/common.js';
37
31
 
38
32
  export default {
39
33
  name: "ConnectivityCard",
@@ -81,29 +75,11 @@ export default {
81
75
  }
82
76
  return false;
83
77
  },
84
- // Get unique species based on iconClass to avoid duplicates in display,
85
- // mainly used for human.
86
- uniqueSpecies: function () {
87
- if (!Array.isArray(this.entry?.species)) {
88
- return [];
89
- }
90
-
91
- const seenIconClasses = new Set();
92
- return this.entry.species.filter((species) => {
93
- if (!species?.iconClass) {
94
- return false;
95
- }
96
- if (seenIconClasses.has(species.iconClass)) {
97
- return false;
98
- }
99
- seenIconClasses.add(species.iconClass);
100
- return true;
101
- });
102
- },
103
78
  },
104
79
  methods: {
105
80
  capitalise: function (text) {
106
- return capitaliseText(text);
81
+ if (text) return text.charAt(0).toUpperCase() + text.slice(1);
82
+ return "";
107
83
  },
108
84
  cardClicked: function (data) {
109
85
  if (!this.loading) {
@@ -330,7 +330,6 @@ import {
330
330
  ExternalResourceCard,
331
331
  } from '@abi-software/map-utilities';
332
332
  import '@abi-software/map-utilities/dist/style.css';
333
- import { capitalise, formatAlertText as formatAlertTextUtil, scrollToRef } from '../utils/common.js'
334
333
 
335
334
  const titleCase = (str) => {
336
335
  return str.replace(/\w\S*/g, (t) => {
@@ -338,6 +337,11 @@ const titleCase = (str) => {
338
337
  })
339
338
  }
340
339
 
340
+ const capitalise = function (str) {
341
+ if (str) return str.charAt(0).toUpperCase() + str.slice(1)
342
+ return ''
343
+ }
344
+
341
345
  export default {
342
346
  name: 'ConnectivityInfo',
343
347
  components: {
@@ -929,10 +933,49 @@ export default {
929
933
  EventBus.emit('trackEvent', data);
930
934
  },
931
935
  showAlertMessage: function () {
932
- scrollToRef(this, 'alertElement');
936
+ // scroll to alert message
937
+ this.$nextTick(() => {
938
+ const alertElement = this.$refs.alertElement;
939
+ if (alertElement) {
940
+ alertElement.scrollIntoView({
941
+ behavior: 'smooth',
942
+ block: 'start',
943
+ inline: 'nearest',
944
+ });
945
+ }
946
+ });
933
947
  },
934
948
  formatAlertText: function (text) {
935
- return formatAlertTextUtil(text, { formatLines: true });
949
+ if (!text) return '';
950
+ const escaped = text
951
+ .replace(/&/g, '&amp;')
952
+ .replace(/</g, '&lt;')
953
+ .replace(/>/g, '&gt;');
954
+ const linkified = escaped.replace(
955
+ /(https?:\/\/[^\s"<>\[]+)/g,
956
+ (url) => {
957
+ const parts = url.match(/^(.*?)([\].,;:!?]*)$/);
958
+ const cleanUrl = parts ? parts[1] : url;
959
+ const suffix = parts ? parts[2] : '';
960
+ return `<a href="${cleanUrl}" target="_blank" rel="noopener noreferrer">${cleanUrl}</a>${suffix}`;
961
+ }
962
+ );
963
+
964
+ const normalised = linkified
965
+ .replace(/\\n/g, '\n')
966
+ .replace(/\r\n/g, '\n')
967
+ .replace(/\r/g, '\n');
968
+
969
+ return normalised
970
+ .split('\n')
971
+ .map((line) => {
972
+ const withBoldLabel = line.replace(
973
+ /^\s*([A-Za-z][^:<]{0,120}:)/,
974
+ '<strong>$1</strong>'
975
+ );
976
+ return `<div class="alert-line">${withBoldLabel}</div>`;
977
+ })
978
+ .join('\n');
936
979
  },
937
980
  },
938
981
  mounted: function () {
@@ -638,14 +638,19 @@ export default {
638
638
  },
639
639
  },
640
640
  created: function () {
641
- this.getBanner()
641
+ if (this.entry.detailsReady) {
642
+ this.getBanner()
643
+ }
642
644
  },
643
645
  watch: {
644
- // currently not using card overflow
645
- 'entry.description': function () {
646
- // watch it
647
- this.getBanner()
648
- },
646
+ 'entry.detailsReady':{
647
+ immediate: true,
648
+ handler: function (val) {
649
+ if (val === true) {
650
+ this.getBanner()
651
+ }
652
+ },
653
+ }
649
654
  },
650
655
  }
651
656
  </script>
@@ -505,7 +505,6 @@ export default {
505
505
  additionalLinks: element.additionalLinks,
506
506
  detailsReady: true,
507
507
  })
508
- this.results[i] = this.results[i]
509
508
  })
510
509
  },
511
510
  createfilterParams: function (params) {
@@ -157,7 +157,10 @@ import '@abi-software/svg-sprite/dist/style.css'
157
157
  import { AlgoliaClient } from '../algolia/algolia.js'
158
158
  import { facetPropPathMapping } from '../algolia/utils.js'
159
159
  import EventBus from './EventBus.js'
160
- import { capitalise } from '../utils/common.js'
160
+
161
+ const capitalise = function (txt) {
162
+ return txt.charAt(0).toUpperCase() + txt.slice(1)
163
+ }
161
164
 
162
165
  const convertReadableLabel = function (original) {
163
166
  const name = original.toLowerCase()
@@ -285,22 +288,18 @@ export default {
285
288
  return value;
286
289
  },
287
290
  createChildrenCascaderValue: function(children, facet, facets) {
288
- const parentKey = facet.key;
289
-
290
291
  if (children?.length) {
291
292
  for (let i = 0; i < children.length; i++) {
292
293
  const facetItem = children[i];
293
294
  //copy the facets into
294
295
  if (children[i].facetPropPath !== 'supportingAwards.consortium.name') {
295
- // `sourceNomenclatureLabel` is from cell card explorer filters
296
- if (parentKey === 'sourceNomenclatureLabel') {
297
- children[i].label = facetItem.label;
298
- } else {
299
- children[i].label = convertReadableLabel(facetItem.label);
300
- }
296
+ children[i].label = convertReadableLabel(
297
+ facetItem.label
298
+ )
301
299
  }
302
- if (facetItem.key && parentKey.includes('flatmap.connectivity.source.')) {
300
+ if (facetItem.key && facet.key.includes('flatmap.connectivity.source.')) {
303
301
  const childKey = facetItem.key;
302
+ const parentKey = facet.key;
304
303
  const key = childKey.replace(`${parentKey}.`, '');
305
304
  children[i].value = this.createCascaderItemValue([facet.label, key]);
306
305
  } else {
@@ -147,10 +147,23 @@ import {
147
147
  } from 'element-plus'
148
148
 
149
149
  import EventBus from './EventBus.js'
150
- import { generateUUID } from '../utils/common.js';
151
150
 
152
151
  const MAX_SEARCH_HISTORY = 12;
153
152
 
153
+ function generateUUID() {
154
+ const arr = new Uint8Array(16);
155
+ window.crypto.getRandomValues(arr);
156
+
157
+ arr[6] = (arr[6] & 0x0f) | 0x40;
158
+ arr[8] = (arr[8] & 0x3f) | 0x80;
159
+
160
+ const hex = Array.from(arr)
161
+ .map(byte => byte.toString(16).padStart(2, '0'))
162
+ .join('');
163
+
164
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
165
+ }
166
+
154
167
  export default {
155
168
  name: 'SearchHistory',
156
169
  components: {
@@ -65,19 +65,6 @@
65
65
  @connectivity-item-close="onConnectivityItemClose"
66
66
  />
67
67
  </template>
68
- <template v-else-if="tab.type === 'cellCardExplorer' && showCellCards">
69
- <CellCardExplorer
70
- :ref="'cellCardExplorerTab_' + tab.id"
71
- class="sidebar-content-container"
72
- v-show="tab.id === activeTabId"
73
- :envVars="envVars"
74
- :activeSpecies="activeSpeciesForEntries"
75
- @dataset-search="openDatasetSearchFromCellCard($event)"
76
- @connectivity-search="openConnectivitySearch($event.facets, $event.query)"
77
- @soma-location-hovered="showSomaLocation"
78
- @soma-locations-ready="onSomaLocationsReady"
79
- />
80
- </template>
81
68
  <template v-else>
82
69
  <DatasetExplorer
83
70
  class="sidebar-content-container"
@@ -108,7 +95,6 @@ import EventBus from './EventBus.js'
108
95
  import Tabs from './Tabs.vue'
109
96
  import AnnotationTool from './AnnotationTool.vue'
110
97
  import ConnectivityExplorer from './ConnectivityExplorer.vue'
111
- import CellCardExplorer from './CellCardExplorer.vue'
112
98
  import { removeShowAllFacets } from '../algolia/utils.js'
113
99
 
114
100
  /**
@@ -124,7 +110,6 @@ export default {
124
110
  Icon,
125
111
  AnnotationTool,
126
112
  ConnectivityExplorer,
127
- CellCardExplorer,
128
113
  },
129
114
  name: 'SideBar',
130
115
  props: {
@@ -134,7 +119,6 @@ export default {
134
119
  { title: 'Dataset Explorer', id: 1, type: 'datasetExplorer', closable: false },
135
120
  { title: 'Connectivity Explorer', id: 2, type: 'connectivityExplorer', closable: false },
136
121
  { title: 'Annotation', id: 3, type: 'annotation', closable: true },
137
- { title: 'Cell Card Explorer', id: 4, type: 'cellCardExplorer', closable: false },
138
122
  ],
139
123
  },
140
124
  /**
@@ -200,10 +184,6 @@ export default {
200
184
  type: Boolean,
201
185
  default: false,
202
186
  },
203
- showCellCards: {
204
- type: Boolean,
205
- default: false,
206
- },
207
187
  },
208
188
  data: function () {
209
189
  return {
@@ -212,7 +192,6 @@ export default {
212
192
  activeTabId: 1,
213
193
  activeAnnotationData: { tabType: "annotation" },
214
194
  activeConnectivityData: { tabType: "connectivity" },
215
- activeSpeciesForEntries: [],
216
195
  state: {
217
196
  dataset: {
218
197
  search: '',
@@ -256,16 +235,6 @@ export default {
256
235
  this.activeAnnotationData = data;
257
236
  }
258
237
  },
259
- /**
260
- * This event is emitted when the mouse hover on or off a soma location in cell card explorer.
261
- * @param name Soma location
262
- */
263
- showSomaLocation: function (name) {
264
- this.$emit('soma-location-hovered', name);
265
- },
266
- onSomaLocationsReady: function (somaLocations) {
267
- this.$emit('soma-locations-ready', somaLocations);
268
- },
269
238
  /**
270
239
  * This event is emitted when the show connectivity button is clicked.
271
240
  * @arg featureIds
@@ -330,42 +299,6 @@ export default {
330
299
  datasetExplorerTabRef.openSearch(facets, query);
331
300
  })
332
301
  },
333
- openCellCardExplorerSearch: function (filters, query) {
334
- this.drawerOpen = true
335
- // Because refs are in v-for, nextTick is needed here
336
- this.$nextTick(() => {
337
- const cellCardExplorerTabRef = this.getTabRef(undefined, 'cellCardExplorer', true);
338
- if (cellCardExplorerTabRef && typeof cellCardExplorerTabRef.openSearch === 'function') {
339
- cellCardExplorerTabRef.openSearch(filters, query);
340
- }
341
- })
342
- },
343
- openDatasetSearchFromCellCard: function (payload) {
344
- if (!payload || typeof payload !== 'object') {
345
- this.openSearch([], payload);
346
- return;
347
- }
348
-
349
- const facets = [];
350
- if (payload.species) {
351
- facets.push({
352
- facet: payload.species,
353
- term: 'Species',
354
- facetPropPath: 'organisms.primary.species.name',
355
- });
356
- }
357
-
358
- if (payload.location) {
359
- facets.push({
360
- facet: payload.location,
361
- term: 'Anatomical structure',
362
- facetPropPath: 'anatomy.organ.category.name',
363
- AND: true,
364
- });
365
- }
366
-
367
- this.openSearch(facets, '');
368
- },
369
302
  /**
370
303
  * Get the ref id of the tab by id and type.
371
304
  */
@@ -568,17 +501,7 @@ export default {
568
501
  ...data,
569
502
  };
570
503
  this.$emit('trackEvent', taggingData);
571
- },
572
- /**
573
- * @public
574
- * Update the active species to use in filters.
575
- * Used by SplitFlow component.
576
- * @param activeSpecies
577
- */
578
- updateActiveSpeciesForEntries: function (activeSpecies) {
579
- const speciesEntries = Array.isArray(activeSpecies) ? activeSpecies : [activeSpecies];
580
- this.activeSpeciesForEntries = [...new Set(speciesEntries.filter(Boolean))];
581
- },
504
+ }
582
505
  },
583
506
  computed: {
584
507
  // This should respect the information provided by the property
@@ -590,10 +513,6 @@ export default {
590
513
  tab.type === "annotation" &&
591
514
  this.annotationEntry &&
592
515
  this.annotationEntry.length > 0
593
- ) ||
594
- (
595
- tab.type === "cellCardExplorer" &&
596
- this.showCellCards
597
516
  )
598
517
  );
599
518
  },
@@ -4,7 +4,7 @@
4
4
  class="tab"
5
5
  v-for="tab in tabs"
6
6
  :key="tab.id"
7
- :class="{ 'active-tab': tab.id == activeId, 'closable-tab': tab.closable }"
7
+ :class="{ 'active-tab': tab.id == activeId }"
8
8
  @click="tabClicked(tab)"
9
9
  >
10
10
  <span class="tab-title">{{ tab.title }} </span>
@@ -103,23 +103,14 @@ export default {
103
103
  .tab-title {
104
104
  text-align: center;
105
105
  font-size: 14px;
106
- padding: 0 0.75rem;
107
-
108
- .closable-tab & {
109
- padding-right: 0.25rem;
110
- }
106
+ padding: 0 1rem;
111
107
  }
112
108
 
113
109
  .tab-close-icon {
114
- width: 18px !important;
115
- height: 18px !important;
116
- font-size: 18px !important;
117
- margin-right: 4px !important;
110
+ width: 20px !important;
111
+ height: 20px !important;
112
+ font-size: 20px !important;
113
+ padding-right: 4px !important;
118
114
  color: $app-primary-color !important;
119
- border-radius: 2px;
120
-
121
- &:hover {
122
- background-color: rgba($app-primary-color, 0.15) !important;
123
- }
124
115
  }
125
116
  </style>
@@ -9,8 +9,6 @@ declare module 'vue' {
9
9
  export interface GlobalComponents {
10
10
  AnnotationTool: typeof import('./components/AnnotationTool.vue')['default']
11
11
  BadgesGroup: typeof import('./components/BadgesGroup.vue')['default']
12
- CellCard: typeof import('./components/CellCard.vue')['default']
13
- CellCardExplorer: typeof import('./components/CellCardExplorer.vue')['default']
14
12
  ConnectivityCard: typeof import('./components/ConnectivityCard.vue')['default']
15
13
  ConnectivityExplorer: typeof import('./components/ConnectivityExplorer.vue')['default']
16
14
  ConnectivityInfo: typeof import('./components/ConnectivityInfo.vue')['default']
@@ -45,7 +43,6 @@ declare module 'vue' {
45
43
  ElRow: typeof import('element-plus/es')['ElRow']
46
44
  ElSelect: typeof import('element-plus/es')['ElSelect']
47
45
  ElTag: typeof import('element-plus/es')['ElTag']
48
- IconOpenExternal: typeof import('./components/icons/IconOpenExternal.vue')['default']
49
46
  ImageGallery: typeof import('./components/ImageGallery.vue')['default']
50
47
  SearchFilters: typeof import('./components/SearchFilters.vue')['default']
51
48
  SearchHistory: typeof import('./components/SearchHistory.vue')['default']