@abi-software/scaffoldvuer 1.5.1 → 1.6.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/scaffoldvuer",
3
- "version": "1.5.1",
3
+ "version": "1.6.0",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -41,7 +41,7 @@
41
41
  "*.js"
42
42
  ],
43
43
  "dependencies": {
44
- "@abi-software/map-utilities": "^1.1.2",
44
+ "@abi-software/map-utilities": "^1.2.0",
45
45
  "@abi-software/sparc-annotation": "^0.3.1",
46
46
  "@abi-software/svg-sprite": "^1.0.1",
47
47
  "@element-plus/icons-vue": "^2.3.1",
package/src/App.vue CHANGED
@@ -297,7 +297,8 @@
297
297
 
298
298
  <script>
299
299
  /* eslint-disable no-alert, no-console */
300
- import { shallowRef } from 'vue';
300
+ import { AnnotationService } from '@abi-software/sparc-annotation'
301
+ import { markRaw, shallowRef } from 'vue';
301
302
  import { ScaffoldVuer } from "./components/index.js";
302
303
  import DropZone from "./app/DropZone.vue";
303
304
  import ModelsTable from "./app/ModelsTable.vue";
@@ -356,6 +357,11 @@ export default {
356
357
  ModelsTable,
357
358
  HelpModeDialog,
358
359
  },
360
+ provide() {
361
+ return {
362
+ $annotator: this.annotator,
363
+ }
364
+ },
359
365
  data: function () {
360
366
  return {
361
367
  consoleOn: true,
@@ -406,7 +412,8 @@ export default {
406
412
  router: useRouter(),
407
413
  ElIconSetting: shallowRef(ElIconSetting),
408
414
  ElIconFolderOpened: shallowRef(ElIconFolderOpened),
409
- auto: NaN
415
+ auto: NaN,
416
+ annotator: markRaw(new AnnotationService(`https://mapcore-demo.org/devel/flatmap/v4/annotator`)),
410
417
  };
411
418
  },
412
419
  watch: {
@@ -596,7 +603,7 @@ export default {
596
603
  }
597
604
  cb(
598
605
  this.$refs.scaffold.fetchSuggestions(term).map((item) => {
599
- const value = item.terms.length > 1 ? item.terms[1] : item.terms[0];
606
+ const value = item.suggestion;
600
607
  return {
601
608
  value: value,
602
609
  label: value
@@ -14,7 +14,7 @@
14
14
  <template #default>
15
15
  <div class="tooltip-text">{{ label }}</div>
16
16
  <div class="tooltip-text" v-if="region">Region: {{ region }}</div>
17
- <CreateTooltiipContent
17
+ <CreateTooltipContent
18
18
  v-show="createData.toBeConfirmed"
19
19
  :createData="createData"
20
20
  @confirm-create="$emit('confirm-create', $event)"
@@ -66,10 +66,9 @@ import {
66
66
  import {
67
67
  Delete as ElIconDelete,
68
68
  } from '@element-plus/icons-vue'
69
- import CreateTooltiipContent from "./CreateTooltipContent.vue";
70
69
  import { mapState } from 'pinia';
71
70
  import { useMainStore } from "@/store/index";
72
- import { Tooltip } from '@abi-software/map-utilities'
71
+ import { CreateTooltipContent, Tooltip } from '@abi-software/map-utilities'
73
72
  import '@abi-software/map-utilities/dist/style.css'
74
73
 
75
74
  /**
@@ -79,7 +78,7 @@ export default {
79
78
  name: "ScaffoldTooltip",
80
79
  components: {
81
80
  Col,
82
- CreateTooltiipContent,
81
+ CreateTooltipContent,
83
82
  ElIconDelete,
84
83
  Icon,
85
84
  Popover,
@@ -165,9 +164,7 @@ export default {
165
164
  }
166
165
  },
167
166
  hideTriggered: function() {
168
- if (this.createData.toBeConfirmed) {
169
- this.$emit('cancel-create');
170
- }
167
+ this.$emit('tooltip-hide');
171
168
  },
172
169
  },
173
170
  watch: {
@@ -142,6 +142,12 @@ export default {
142
142
  isRegion: true,
143
143
  };
144
144
  this.addTreeItem(data.children, childRegionItem, region);
145
+ //Special case for helper region
146
+ if (path === "/_helper") {
147
+ this.$nextTick(() => {
148
+ this.$refs.treeControls.$refs.regionTree.setChecked(childRegionItem.id, false);
149
+ });
150
+ }
145
151
  }
146
152
  _paths.shift();
147
153
  return this.findOrCreateRegion(childRegionItem, _paths, path);
@@ -17,7 +17,8 @@
17
17
  :annotationDisplay="annotationDisplay"
18
18
  @confirm-create="confirmCreate($event)"
19
19
  @cancel-create="cancelCreate()"
20
- @confirm-delete="confirmDelete($event)"
20
+ @confirm-delete="confirmDelete()"
21
+ @tooltip-hide="onTooltipHide()"
21
22
  />
22
23
  <div
23
24
  id="organsDisplayArea"
@@ -382,7 +383,7 @@
382
383
 
383
384
  <script>
384
385
  /* eslint-disable no-alert, no-console */
385
- import { markRaw, shallowRef } from 'vue';
386
+ import { inject, markRaw, provide, shallowRef } from 'vue';
386
387
  import {
387
388
  WarningFilled as ElIconWarningFilled,
388
389
  ArrowDown as ElIconArrowDown,
@@ -454,10 +455,21 @@ export default {
454
455
  ScaffoldTreeControls
455
456
  },
456
457
  setup(props) {
457
- const annotator = markRaw(new AnnotationService(`${props.flatmapAPI}annotator`));
458
- return { annotator };
458
+ let annotator = inject('$annotator')
459
+ if (!annotator) {
460
+ annotator = markRaw(new AnnotationService(`${props.flatmapAPI}annotator`));
461
+ provide('$annotator', annotator)
462
+ }
463
+ return { annotator }
459
464
  },
460
465
  props: {
466
+ /**
467
+ * The option to show annotation information in sidebar
468
+ */
469
+ annotationSidebar: {
470
+ type: Boolean,
471
+ default: false,
472
+ },
461
473
  /**
462
474
  * URL of the zincjs metadata. This value will be ignored if a valid
463
475
  * state prop is also provided.
@@ -698,7 +710,6 @@ export default {
698
710
  return {
699
711
  flatmapAPI: this.flatmapAPI,
700
712
  scaffoldUrl: this.url,
701
- $annotator: this.annotator,
702
713
  boundingDims: this.boundingDims,
703
714
  };
704
715
  },
@@ -812,6 +823,11 @@ export default {
812
823
  centre: [0, 0, 0],
813
824
  size:[1, 1, 1],
814
825
  },
826
+ lastSelected: markRaw({
827
+ region: "",
828
+ group: "",
829
+ isSearch: false,
830
+ })
815
831
  };
816
832
  },
817
833
  watch: {
@@ -902,6 +918,24 @@ export default {
902
918
  }
903
919
  this.previousMarkerLabels = markRaw({...labels});
904
920
  },
921
+ annotationDisplay: function(value) {
922
+ if (this.annotationSidebar) {
923
+ if (value) {
924
+ const region = this.tData.region ? this.tData.region +"/" : "";
925
+ const annotationEntry = {
926
+ "featureId": region + this.tData.label,
927
+ "resourceId": this.url,
928
+ "resource": this.url,
929
+ };
930
+ this.$emit('annotation-open', {annotationEntry: annotationEntry,
931
+ commitCallback: this.commitAnnotationEvent});
932
+ } else {
933
+ if (!this.createData.toBeConfirmed || !this.createData.toBeDeleted) {
934
+ this.$emit("annotation-close");
935
+ }
936
+ }
937
+ }
938
+ }
905
939
  },
906
940
  beforeCreate: function () {
907
941
  this.$module = new OrgansViewer();
@@ -1171,13 +1205,16 @@ export default {
1171
1205
  this.$module.scene.removeTemporaryPrimitive(this._tempPoint);
1172
1206
  this._tempPoint = undefined;
1173
1207
  }
1208
+ if (this.annotationSidebar){
1209
+ this.$emit("annotation-close");
1210
+ }
1174
1211
  },
1175
1212
  /**
1176
1213
  * Internal only.
1177
1214
  * Confirm delete of user created primitive.
1178
1215
  * This is only called from callback.
1179
1216
  */
1180
- confirmDelete: function() {
1217
+ confirmDelete: function() {
1181
1218
  if (this._editingZincObject?.isEditable) {
1182
1219
  const regionPath = this._editingZincObject.region.getFullPath() + "/";
1183
1220
  const group = this._editingZincObject.groupName;
@@ -1191,6 +1228,15 @@ export default {
1191
1228
  }
1192
1229
  this.cancelCreate();
1193
1230
  },
1231
+ /**
1232
+ * Internal only.
1233
+ * This is triggered when tooltip is hidden
1234
+ */
1235
+ onTooltipHide: function() {
1236
+ if (this.createData.toBeConfirmed && !this.annotationSidebar) {
1237
+ this.cancelCreate();
1238
+ }
1239
+ },
1194
1240
  formatTooltip(val) {
1195
1241
  if (this.timeMax >= 1000) {
1196
1242
  if (val) {
@@ -1286,6 +1332,7 @@ export default {
1286
1332
  toggleDrawing: function (type, icon) {
1287
1333
  this.createData.toBeDeleted = false;
1288
1334
  if (type === 'mode') {
1335
+ this.cancelCreate()
1289
1336
  this.activeDrawMode = icon;
1290
1337
  this.createData.shape = '';
1291
1338
  this.$module.selectObjectOnPick = true;
@@ -1387,21 +1434,21 @@ export default {
1387
1434
  if (this.createData.toBeConfirmed === false) {
1388
1435
  this.createData.points.length = 0;
1389
1436
  this.createData.points.push(coords);
1437
+ this.createData.toBeConfirmed = true;
1390
1438
  this.showRegionTooltipWithAnnotations(data, true, false);
1391
1439
  this.tData.x = 50;
1392
1440
  this.tData.y = 200;
1393
1441
  this._tempPoint = this.$module.scene.addTemporaryPoints([coords], 0xffff00);
1394
- this.createData.toBeConfirmed = true;
1395
1442
  }
1396
1443
  },
1397
1444
  drawLine: function(coords, data) {
1398
1445
  if (this.createData.toBeConfirmed === false) {
1399
1446
  if (this.createData.points.length === 1) {
1400
1447
  this.createData.points.push(coords);
1448
+ this.createData.toBeConfirmed = true;
1401
1449
  this.showRegionTooltipWithAnnotations(data, true, false);
1402
1450
  this.tData.x = 50;
1403
1451
  this.tData.y = 200;
1404
- this.createData.toBeConfirmed = true;
1405
1452
  } else {
1406
1453
  this._tempPoint = this.$module.scene.addTemporaryPoints([coords], 0xffff00);
1407
1454
  this.createData.points.push(coords);
@@ -1508,7 +1555,6 @@ export default {
1508
1555
  } else {
1509
1556
  if (this.$refs.scaffoldTreeControls) {
1510
1557
  if (names.length > 0) {
1511
- //this.$refs.scaffoldTreeControls.changeActiveByNames(names, region, false);
1512
1558
  this.$refs.scaffoldTreeControls.updateActiveUI(zincObjects);
1513
1559
  this.updatePrimitiveControls(zincObjects);
1514
1560
  } else {
@@ -1516,6 +1562,17 @@ export default {
1516
1562
  this.$refs.scaffoldTreeControls.removeActive(false);
1517
1563
  }
1518
1564
  }
1565
+ //Store the following for state saving. Search will handle the case with more than 1
1566
+ //identifiers.
1567
+ if (event.identifiers.length === 1) {
1568
+ this.lastSelected.isSearch = false;
1569
+ this.lastSelected.region = event.identifiers[0].data.region;
1570
+ this.lastSelected.group = event.identifiers[0].data.group;
1571
+ } else if (event.identifiers.length === 0) {
1572
+ this.lastSelected.isSearch = false;
1573
+ this.lastSelected.region = "";
1574
+ this.lastSelected.group = "";
1575
+ }
1519
1576
  /**
1520
1577
  * Emit when an object is selected
1521
1578
  * @arg {Object} "Identifier of selected objects"
@@ -1525,10 +1582,8 @@ export default {
1525
1582
  } else if (event.eventType == 2) {
1526
1583
  if (this.selectedObjects.length === 0) {
1527
1584
  this.hideRegionTooltip();
1528
- // const offsets = this.$refs.scaffoldContainer.getBoundingClientRect();
1529
1585
  if (this.$refs.scaffoldTreeControls) {
1530
1586
  if (names.length > 0) {
1531
- //this.$refs.scaffoldTreeControls.changeHoverByNames(names, region, false);
1532
1587
  this.$refs.scaffoldTreeControls.updateHoverUI(zincObjects);
1533
1588
  } else {
1534
1589
  this.$refs.scaffoldTreeControls.removeHover(true);
@@ -1540,7 +1595,9 @@ export default {
1540
1595
  : event.identifiers[0].data.group;
1541
1596
  if (event.identifiers[0].coords) {
1542
1597
  this.tData.active = false;
1543
- this.tData.visible = true;
1598
+ if (!this.annotationSidebar) {
1599
+ this.tData.visible = true;
1600
+ }
1544
1601
  this.tData.label = id;
1545
1602
  if (event.identifiers[0].data.region) {
1546
1603
  this.tData.region = event.identifiers[0].data.region;
@@ -1881,13 +1938,30 @@ export default {
1881
1938
  if (this.$module.scene) {
1882
1939
  const result = getObjectsFromAnnotations(this.$module.scene, annotations);
1883
1940
  if (result && result.objects.length > 0) {
1884
- return this.showRegionTooltipWithObjects(
1885
- result.label,
1886
- result.objects,
1887
- result.regionPath,
1888
- resetView,
1889
- liveUpdates
1890
- );
1941
+ if (!this.annotationSidebar) {
1942
+ return this.showRegionTooltipWithObjects(
1943
+ result.label,
1944
+ result.objects,
1945
+ result.regionPath,
1946
+ resetView,
1947
+ liveUpdates
1948
+ );
1949
+ } else {
1950
+ const region = this.tData.region ? this.tData.region +"/" : "";
1951
+ const annotationEntry = {
1952
+ "featureId": region + this.tData.label,
1953
+ "resourceId": this.url,
1954
+ "resource": this.url,
1955
+ };
1956
+ this.$emit('annotation-open', {
1957
+ annotationEntry: annotationEntry,
1958
+ createData: this.createData,
1959
+ confirmCreate: this.confirmCreate,
1960
+ cancelCreate: this.cancelCreate,
1961
+ confirmDelete: this.confirmDelete,
1962
+ });
1963
+ return;
1964
+ }
1891
1965
  }
1892
1966
  }
1893
1967
  this.hideRegionTooltip();
@@ -1900,7 +1974,7 @@ export default {
1900
1974
  changeViewingMode: function (modeName) {
1901
1975
  if (this.$module) {
1902
1976
  if (modeName) {
1903
- this.viewingMode = modeName
1977
+ this.viewingMode = modeName;
1904
1978
  }
1905
1979
  if (this.viewingMode === "Annotation") {
1906
1980
  let authenticated = false;
@@ -2029,9 +2103,15 @@ export default {
2029
2103
  if (text === undefined || text === "" ||
2030
2104
  ((Array.isArray(text) && text.length === 0))
2031
2105
  ) {
2106
+ this.lastSelected.region = "";
2107
+ this.lastSelected.group = "";
2108
+ this.lastSelected.isSearch = true;
2032
2109
  this.objectSelected([], true);
2033
2110
  return false;
2034
2111
  } else {
2112
+ this.lastSelected.region = "";
2113
+ this.lastSelected.group = text;
2114
+ this.lastSelected.isSearch = true;
2035
2115
  const result = this.$_searchIndex.searchAndProcessResult(text);
2036
2116
  const zincObjects = result.zincObjects;
2037
2117
  if (zincObjects.length > 0) {
@@ -2091,26 +2171,42 @@ export default {
2091
2171
  }
2092
2172
  this.timeMax = this.$module.scene.getDuration();
2093
2173
  },
2094
- setURLFinishCallback: function (options) {
2095
- return () => {
2096
- if (options) {
2097
- if (options.viewport) {
2098
- this.$module.scene
2099
- .getZincCameraControls()
2100
- .setCurrentCameraSettings(options.viewport);
2101
- } else if (options.viewURL && options.viewURL !== "") {
2102
- const url = new URL(options.viewURL, this.url);
2103
- this.$module.scene.loadViewURL(url);
2104
- } else if (options.region && options.region !== "") {
2105
- this.viewRegion(options.region);
2106
- }
2107
- if (options.visibility) {
2108
- // Some UIs may not be ready at this time.
2109
- this.$nextTick(() => {
2110
- this.$refs.scaffoldTreeControls.setState(options.visibility);
2111
- });
2174
+ restoreSettings: function(options) {
2175
+ if (options) {
2176
+ if (options.viewport) {
2177
+ this.$module.scene
2178
+ .getZincCameraControls()
2179
+ .setCurrentCameraSettings(options.viewport);
2180
+ } else if (options.viewURL && options.viewURL !== "") {
2181
+ const url = new URL(options.viewURL, this.url);
2182
+ this.$module.scene.loadViewURL(url);
2183
+ } else if (options.region && options.region !== "") {
2184
+ this.viewRegion(options.region);
2185
+ }
2186
+ if (options.visibility) {
2187
+ // Some UIs may not be ready at this time.
2188
+ this.$nextTick(() => {
2189
+ this.$refs.scaffoldTreeControls.setState(options.visibility);
2190
+ });
2191
+ }
2192
+ if (options.background) {
2193
+ this.backgroundChangeCallback(options.background);
2194
+ }
2195
+ if (options.viewingMode) {
2196
+ this.changeViewingMode(options.viewingMode);
2197
+ }
2198
+ const search = options.search;
2199
+ if (search && search.group) {
2200
+ if (search.isSearch) {
2201
+ this.search(search.group, true);
2202
+ } else {
2203
+ this.changeActiveByName(search.group, search.region, true);
2112
2204
  }
2113
2205
  }
2206
+ }
2207
+ },
2208
+ setURLFinishCallback: function (options) {
2209
+ return () => {
2114
2210
  this.localAnnotationsList.length = 0;
2115
2211
  this.updateSettingsfromScene();
2116
2212
  this.$module.updateTime(0.01);
@@ -2132,6 +2228,7 @@ export default {
2132
2228
  const {centre, size} = this.$module.getCentreAndSize();
2133
2229
  this.boundingDims.centre = centre;
2134
2230
  this.boundingDims.size = size;
2231
+ this.$nextTick(() => this.restoreSettings(options) );
2135
2232
  this.isReady = true;
2136
2233
  };
2137
2234
  },
@@ -2147,6 +2244,8 @@ export default {
2147
2244
  url: this._currentURL,
2148
2245
  viewport: undefined,
2149
2246
  visibility: undefined,
2247
+ background: this.currentBackground,
2248
+ viewingMode: this.viewingMode,
2150
2249
  };
2151
2250
  if (this.$refs.scaffoldTreeControls)
2152
2251
  state.visibility = this.$refs.scaffoldTreeControls.getState();
@@ -2154,6 +2253,9 @@ export default {
2154
2253
  let zincCameraControls = this.$module.scene.getZincCameraControls();
2155
2254
  state.viewport = zincCameraControls.getCurrentViewport();
2156
2255
  }
2256
+ if (this.lastSelected && this.lastSelected.group) {
2257
+ state.search = {...this.lastSelected};
2258
+ }
2157
2259
  return state;
2158
2260
  },
2159
2261
  /**
@@ -2170,21 +2272,22 @@ export default {
2170
2272
  fileFormat: state.fileFormat,
2171
2273
  viewport: state.viewport,
2172
2274
  visibility: state.visibility,
2275
+ background: state.background,
2276
+ viewingMode: this.viewingMode,
2277
+ search: state.search,
2173
2278
  });
2174
2279
  } else {
2175
- if (state.viewport || state.visibility) {
2280
+ if (state.background || state.search || state.viewport || state.viewingMode || state.visibility) {
2176
2281
  if (this.isReady && this.$module.scene) {
2177
- if (state.viewport)
2178
- this.$module.scene
2179
- .getZincCameraControls()
2180
- .setCurrentCameraSettings(state.viewport);
2181
- if (state.visibility)
2182
- this.$refs.scaffoldTreeControls.setState(state.visibility);
2282
+ this.restoreSettings(state);
2183
2283
  } else {
2184
2284
  this.$module.setFinishDownloadCallback(
2185
2285
  this.setURLFinishCallback({
2286
+ background: state.background,
2287
+ viewingMode: state.viewingMode,
2186
2288
  viewport: state.viewport,
2187
2289
  visibility: state.visibility,
2290
+ search: state.search,
2188
2291
  })
2189
2292
  );
2190
2293
  }
@@ -2241,6 +2344,7 @@ export default {
2241
2344
  });
2242
2345
  }
2243
2346
  },
2347
+
2244
2348
  /**
2245
2349
  * Function used for reading in new scaffold metadata and a custom
2246
2350
  * viewport. This function will ignore the state prop and
@@ -2252,10 +2356,7 @@ export default {
2252
2356
  */
2253
2357
  setURLAndState: function (newValue, state) {
2254
2358
  if (newValue != this._currentURL) {
2255
- if (state && state.format) this.fileFormat = state.format;
2256
- let viewport = state && state.viewport ? state.viewport : undefined;
2257
- let visibility =
2258
- state && state.visibility ? state.visibility : undefined;
2359
+ if (state?.format) this.fileFormat = state.format;
2259
2360
  this._currentURL = newValue;
2260
2361
  if (this.$refs.scaffoldTreeControls) this.$refs.scaffoldTreeControls.clear();
2261
2362
  this.loading = true;
@@ -2265,10 +2366,13 @@ export default {
2265
2366
  this.hideRegionTooltip();
2266
2367
  this.$module.setFinishDownloadCallback(
2267
2368
  this.setURLFinishCallback({
2268
- viewport: viewport,
2369
+ background: state?.background,
2269
2370
  region: this.region,
2371
+ search: state?.search,
2372
+ viewingMode: state?.viewingMode,
2270
2373
  viewURL: this.viewURL,
2271
- visibility: visibility,
2374
+ viewport: state?.viewport,
2375
+ visibility: state?.visibility,
2272
2376
  })
2273
2377
  );
2274
2378
  if (this.fileFormat === "gltf") {
@@ -7,21 +7,18 @@ export {}
7
7
 
8
8
  declare module 'vue' {
9
9
  export interface GlobalComponents {
10
- CreateTooltipContent: typeof import('./components/CreateTooltipContent.vue')['default']
11
10
  ElButton: typeof import('element-plus/es')['ElButton']
12
11
  ElCol: typeof import('element-plus/es')['ElCol']
13
12
  ElCollapse: typeof import('element-plus/es')['ElCollapse']
14
13
  ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
15
14
  ElContainer: typeof import('element-plus/es')['ElContainer']
16
15
  ElFooter: typeof import('element-plus/es')['ElFooter']
17
- ElHeader: typeof import('element-plus/es')['ElHeader']
18
16
  ElIcon: typeof import('element-plus/es')['ElIcon']
19
17
  ElIconArrowLeft: typeof import('@element-plus/icons-vue')['ArrowLeft']
20
18
  ElIconArrowRight: typeof import('@element-plus/icons-vue')['ArrowRight']
21
19
  ElIconDelete: typeof import('@element-plus/icons-vue')['Delete']
22
20
  ElIconPlus: typeof import('@element-plus/icons-vue')['Plus']
23
21
  ElIconWarningFilled: typeof import('@element-plus/icons-vue')['WarningFilled']
24
- ElInput: typeof import('element-plus/es')['ElInput']
25
22
  ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
26
23
  ElMain: typeof import('element-plus/es')['ElMain']
27
24
  ElOption: typeof import('element-plus/es')['ElOption']