@abi-software/map-side-bar 2.14.8-demo.7 → 2.15.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.14.8-demo.7",
3
+ "version": "2.15.0",
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')
@@ -28,7 +28,6 @@
28
28
 
29
29
  <script>
30
30
  import EventBus from './EventBus';
31
- import { capitalise as capitaliseText } from '../utils/common.js';
32
31
 
33
32
  export default {
34
33
  name: "ConnectivityCard",
@@ -79,7 +78,8 @@ export default {
79
78
  },
80
79
  methods: {
81
80
  capitalise: function (text) {
82
- return capitaliseText(text);
81
+ if (text) return text.charAt(0).toUpperCase() + text.slice(1);
82
+ return "";
83
83
  },
84
84
  cardClicked: function (data) {
85
85
  if (!this.loading) {
@@ -420,7 +420,7 @@ export default {
420
420
  this.openSearch([], '');
421
421
  this.$emit('search-changed', {
422
422
  value: [],
423
- tabType: 'connectivity',
423
+ tabType: 'dataset',
424
424
  type: 'reset-update',
425
425
  })
426
426
 
@@ -468,7 +468,7 @@ export default {
468
468
  if (notFoundItems.length) {
469
469
  this.$emit('search-changed', {
470
470
  value: notFoundItems,
471
- tabType: 'connectivity',
471
+ tabType: 'dataset',
472
472
  type: 'reset-update',
473
473
  })
474
474
  }
@@ -355,7 +355,6 @@ import {
355
355
  ExternalResourceCard,
356
356
  } from '@abi-software/map-utilities';
357
357
  import '@abi-software/map-utilities/dist/style.css';
358
- import { capitalise, formatAlertText as formatAlertTextUtil, scrollToRef } from '../utils/common.js'
359
358
 
360
359
  const titleCase = (str) => {
361
360
  return str.replace(/\w\S*/g, (t) => {
@@ -363,6 +362,11 @@ const titleCase = (str) => {
363
362
  })
364
363
  }
365
364
 
365
+ const capitalise = function (str) {
366
+ if (str) return str.charAt(0).toUpperCase() + str.slice(1)
367
+ return ''
368
+ }
369
+
366
370
  export default {
367
371
  name: 'ConnectivityInfo',
368
372
  components: {
@@ -1153,10 +1157,49 @@ export default {
1153
1157
  EventBus.emit('trackEvent', data);
1154
1158
  },
1155
1159
  showAlertMessage: function () {
1156
- scrollToRef(this, 'alertElement');
1160
+ // scroll to alert message
1161
+ this.$nextTick(() => {
1162
+ const alertElement = this.$refs.alertElement;
1163
+ if (alertElement) {
1164
+ alertElement.scrollIntoView({
1165
+ behavior: 'smooth',
1166
+ block: 'start',
1167
+ inline: 'nearest',
1168
+ });
1169
+ }
1170
+ });
1157
1171
  },
1158
1172
  formatAlertText: function (text) {
1159
- return formatAlertTextUtil(text, { formatLines: true });
1173
+ if (!text) return '';
1174
+ const escaped = text
1175
+ .replace(/&/g, '&amp;')
1176
+ .replace(/</g, '&lt;')
1177
+ .replace(/>/g, '&gt;');
1178
+ const linkified = escaped.replace(
1179
+ /(https?:\/\/[^\s"<>\[]+)/g,
1180
+ (url) => {
1181
+ const parts = url.match(/^(.*?)([\].,;:!?]*)$/);
1182
+ const cleanUrl = parts ? parts[1] : url;
1183
+ const suffix = parts ? parts[2] : '';
1184
+ return `<a href="${cleanUrl}" target="_blank" rel="noopener noreferrer">${cleanUrl}</a>${suffix}`;
1185
+ }
1186
+ );
1187
+
1188
+ const normalised = linkified
1189
+ .replace(/\\n/g, '\n')
1190
+ .replace(/\r\n/g, '\n')
1191
+ .replace(/\r/g, '\n');
1192
+
1193
+ return normalised
1194
+ .split('\n')
1195
+ .map((line) => {
1196
+ const withBoldLabel = line.replace(
1197
+ /^\s*([A-Za-z][^:<]{0,120}:)/,
1198
+ '<strong>$1</strong>'
1199
+ );
1200
+ return `<div class="alert-line">${withBoldLabel}</div>`;
1201
+ })
1202
+ .join('\n');
1160
1203
  },
1161
1204
  },
1162
1205
  mounted: function () {
@@ -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: {
@@ -334,8 +347,7 @@ export default {
334
347
  getParentComponentName: function () {
335
348
  const isConnectivity = this.localStorageKey?.indexOf('connectivity') !== -1;
336
349
  const isDataset = this.localStorageKey?.indexOf('dataset') !== -1;
337
- const isCellCard = this.localStorageKey?.indexOf('cell-card') !== -1;
338
- const location = isConnectivity ? 'connectivity' : isDataset ? 'dataset' : isCellCard ? 'cell_card' : '';
350
+ const location = isConnectivity ? 'connectivity' : isDataset ? 'dataset' : '';
339
351
  return location;
340
352
  },
341
353
  search: function (item) {
@@ -65,20 +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
- @search-changed="searchChanged(tab.id, $event)"
76
- @dataset-search="openDatasetSearchFromCellCard($event)"
77
- @connectivity-search="openConnectivitySearch($event.facets, $event.query)"
78
- @soma-location-hovered="showSomaLocation"
79
- @soma-locations-ready="onSomaLocationsReady"
80
- />
81
- </template>
82
68
  <template v-else>
83
69
  <DatasetExplorer
84
70
  class="sidebar-content-container"
@@ -109,7 +95,6 @@ import EventBus from './EventBus.js'
109
95
  import Tabs from './Tabs.vue'
110
96
  import AnnotationTool from './AnnotationTool.vue'
111
97
  import ConnectivityExplorer from './ConnectivityExplorer.vue'
112
- import CellCardExplorer from './CellCardExplorer.vue'
113
98
  import { removeShowAllFacets } from '../algolia/utils.js'
114
99
 
115
100
  /**
@@ -125,7 +110,6 @@ export default {
125
110
  Icon,
126
111
  AnnotationTool,
127
112
  ConnectivityExplorer,
128
- CellCardExplorer,
129
113
  },
130
114
  name: 'SideBar',
131
115
  props: {
@@ -135,7 +119,6 @@ export default {
135
119
  { title: 'Dataset Explorer', id: 1, type: 'datasetExplorer', closable: false },
136
120
  { title: 'Connectivity Explorer', id: 2, type: 'connectivityExplorer', closable: false },
137
121
  { title: 'Annotation', id: 3, type: 'annotation', closable: true },
138
- { title: 'Cell Card Explorer', id: 4, type: 'cellCardExplorer', closable: false },
139
122
  ],
140
123
  },
141
124
  /**
@@ -201,10 +184,6 @@ export default {
201
184
  type: Boolean,
202
185
  default: false,
203
186
  },
204
- showCellCards: {
205
- type: Boolean,
206
- default: false,
207
- },
208
187
  },
209
188
  data: function () {
210
189
  return {
@@ -213,17 +192,12 @@ export default {
213
192
  activeTabId: 1,
214
193
  activeAnnotationData: { tabType: "annotation" },
215
194
  activeConnectivityData: { tabType: "connectivity" },
216
- activeSpeciesForEntries: [],
217
195
  state: {
218
196
  dataset: {
219
197
  search: '',
220
198
  filters: [],
221
199
  },
222
- connectivity: {
223
- search: '',
224
- filters: [],
225
- },
226
- cellCards: {
200
+ connectivity: {
227
201
  search: '',
228
202
  filters: [],
229
203
  },
@@ -261,16 +235,6 @@ export default {
261
235
  this.activeAnnotationData = data;
262
236
  }
263
237
  },
264
- /**
265
- * This event is emitted when the mouse hover on or off a soma location in cell card explorer.
266
- * @param name Soma location
267
- */
268
- showSomaLocation: function (name) {
269
- this.$emit('soma-location-hovered', name);
270
- },
271
- onSomaLocationsReady: function (somaLocations) {
272
- this.$emit('soma-locations-ready', somaLocations);
273
- },
274
238
  /**
275
239
  * This event is emitted when the show connectivity button is clicked.
276
240
  * @arg featureIds
@@ -335,42 +299,6 @@ export default {
335
299
  datasetExplorerTabRef.openSearch(facets, query);
336
300
  })
337
301
  },
338
- openCellCardExplorerSearch: function (filters, query) {
339
- this.drawerOpen = true
340
- // Because refs are in v-for, nextTick is needed here
341
- this.$nextTick(() => {
342
- const cellCardExplorerTabRef = this.getTabRef(undefined, 'cellCardExplorer', true);
343
- if (cellCardExplorerTabRef && typeof cellCardExplorerTabRef.openSearch === 'function') {
344
- cellCardExplorerTabRef.openSearch(filters, query);
345
- }
346
- })
347
- },
348
- openDatasetSearchFromCellCard: function (payload) {
349
- if (!payload || typeof payload !== 'object') {
350
- this.openSearch([], payload);
351
- return;
352
- }
353
-
354
- const facets = [];
355
- if (payload.species) {
356
- facets.push({
357
- facet: payload.species,
358
- term: 'Species',
359
- facetPropPath: 'organisms.primary.species.name',
360
- });
361
- }
362
-
363
- if (payload.location) {
364
- facets.push({
365
- facet: payload.location,
366
- term: 'Anatomical structure',
367
- facetPropPath: 'anatomy.organ.category.name',
368
- AND: true,
369
- });
370
- }
371
-
372
- this.openSearch(facets, '');
373
- },
374
302
  /**
375
303
  * Get the ref id of the tab by id and type.
376
304
  */
@@ -509,13 +437,6 @@ export default {
509
437
  this.state.connectivity.filters = connectivityExplorerTabRef.getFilters();
510
438
  }
511
439
 
512
- // Update cell card explorer state if available
513
- const cellCardExplorerTabRef = this.getTabRef(undefined, 'cellCardExplorer');
514
- if (cellCardExplorerTabRef) {
515
- this.state.cellCards.search = cellCardExplorerTabRef.getSearch();
516
- this.state.cellCards.filters = cellCardExplorerTabRef.getFilters();
517
- }
518
-
519
440
  // Update connectivity entries if available
520
441
  if (this.connectivityEntry && this.connectivityEntry.length > 0) {
521
442
  this.state.connectivityEntries = this.connectivityEntry.map((entry) => entry.id);
@@ -545,15 +466,11 @@ export default {
545
466
  setState: function (state) {
546
467
  // if state is not provided or formatted incorrectly, do nothing
547
468
  if (!state || !state.dataset || !state.connectivity) return;
548
- // Create a deep copy while preserving the original state structure for future extensibility
549
- const newState = JSON.parse(JSON.stringify(state));
550
- this.state = { ...this.state, ...newState };
551
- const datasetFilters = this.state.dataset.filters;
552
- const connectivityFilters = this.state.connectivity.filters;
553
- const datasetSearch = this.state.dataset.search;
554
- const connectivitySearch = this.state.connectivity.search;
555
- const cellCardFilters = this.state.cellCards.filters || [];
556
- const cellCardSearch = this.state.cellCards.search || '';
469
+ this.state = JSON.parse(JSON.stringify(state)); // deep copy to avoid reference issues
470
+ const datasetFilters = state.dataset.filters;
471
+ const connectivityFilters = state.connectivity.filters;
472
+ const datasetSearch = state.dataset.search;
473
+ const connectivitySearch = state.connectivity.search;
557
474
 
558
475
  if (datasetFilters.length || datasetSearch) {
559
476
  this.openSearch(datasetFilters, datasetSearch);
@@ -563,10 +480,6 @@ export default {
563
480
  this.openConnectivitySearch(connectivityFilters, connectivitySearch);
564
481
  }
565
482
 
566
- if (cellCardFilters.length || cellCardSearch) {
567
- this.openCellCardExplorerSearch(cellCardFilters, cellCardSearch);
568
- }
569
-
570
483
  if (state.activeTabId) {
571
484
  this.$nextTick(() => {
572
485
  const hasTab = this.tabEntries.find((t) => t.id === state.activeTabId);
@@ -588,17 +501,7 @@ export default {
588
501
  ...data,
589
502
  };
590
503
  this.$emit('trackEvent', taggingData);
591
- },
592
- /**
593
- * @public
594
- * Update the active species to use in filters.
595
- * Used by SplitFlow component.
596
- * @param activeSpecies
597
- */
598
- updateActiveSpeciesForEntries: function (activeSpecies) {
599
- const speciesEntries = Array.isArray(activeSpecies) ? activeSpecies : [activeSpecies];
600
- this.activeSpeciesForEntries = [...new Set(speciesEntries.filter(Boolean))];
601
- },
504
+ }
602
505
  },
603
506
  computed: {
604
507
  // This should respect the information provided by the property
@@ -610,10 +513,6 @@ export default {
610
513
  tab.type === "annotation" &&
611
514
  this.annotationEntry &&
612
515
  this.annotationEntry.length > 0
613
- ) ||
614
- (
615
- tab.type === "cellCardExplorer" &&
616
- this.showCellCards
617
516
  )
618
517
  );
619
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']
@@ -46,7 +44,6 @@ declare module 'vue' {
46
44
  ElRow: typeof import('element-plus/es')['ElRow']
47
45
  ElSelect: typeof import('element-plus/es')['ElSelect']
48
46
  ElTag: typeof import('element-plus/es')['ElTag']
49
- IconOpenExternal: typeof import('./components/icons/IconOpenExternal.vue')['default']
50
47
  ImageGallery: typeof import('./components/ImageGallery.vue')['default']
51
48
  SearchFilters: typeof import('./components/SearchFilters.vue')['default']
52
49
  SearchHistory: typeof import('./components/SearchHistory.vue')['default']