@abi-software/scaffoldvuer 1.8.0 → 1.8.1-beta.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.8.0",
3
+ "version": "1.8.1-beta.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.4.0",
44
+ "@abi-software/map-utilities": "^1.4.1-beta.0",
45
45
  "@abi-software/sparc-annotation": "^0.3.2",
46
46
  "@abi-software/svg-sprite": "^1.0.1",
47
47
  "@element-plus/icons-vue": "^2.3.1",
package/src/App.vue CHANGED
@@ -27,7 +27,6 @@
27
27
  :view-u-r-l="viewURL"
28
28
  :format="format"
29
29
  :marker-labels="markerLabels"
30
- :enableLocalAnnotations="false"
31
30
  @open-map="openMap"
32
31
  @on-error="onError"
33
32
  @on-ready="onReady"
@@ -140,7 +139,7 @@
140
139
 
141
140
  <el-row :gutter="20" justify="center" align="middle">
142
141
  <el-col :span="auto">
143
- <el-button size="small" @click="exportLocalAnnotations()">
142
+ <el-button size="small" @click="exportOfflineAnnotations()">
144
143
  Export Annotations
145
144
  </el-button>
146
145
  </el-col>
@@ -151,7 +150,7 @@
151
150
  id="annotations-upload"
152
151
  type="file"
153
152
  accept="application/json"
154
- @change="importLocalAnnotations"
153
+ @change="importOfflineAnnotations"
155
154
  />
156
155
  </el-button>
157
156
  </el-col>
@@ -491,16 +490,16 @@ export default {
491
490
  hrefElement.remove();
492
491
  });
493
492
  },
494
- exportLocalAnnotations: function() {
495
- const annotations = this.$refs.scaffold.getLocalAnnotations();
493
+ exportOfflineAnnotations: function() {
494
+ const annotations = this.$refs.scaffold.getOfflineAnnotations();
496
495
  const filename = 'scaffoldAnnotations' + JSON.stringify(new Date()) + '.json';
497
496
  writeTextFile(filename, annotations);
498
497
  },
499
498
  onReaderLoad: function(event) {
500
499
  const annotationsList = JSON.parse(event.target.result);
501
- this.$refs.scaffold.importLocalAnnotations(annotationsList);
500
+ this.$refs.scaffold.importOfflineAnnotations(annotationsList);
502
501
  },
503
- importLocalAnnotations: function() {
502
+ importOfflineAnnotations: function() {
504
503
  const selectedFile = document.getElementById("annotations-upload").files[0];
505
504
  const reader = new FileReader();
506
505
  reader.onload = this.onReaderLoad;
@@ -155,6 +155,17 @@ export default {
155
155
  return data;
156
156
  }
157
157
  },
158
+ removeRegion: function (label) {
159
+ if (this.treeData[0].children) {
160
+ for (let i = 0; i < this.treeData[0].children.length; i++) {
161
+ if (this.treeData[0].children[i].label === label) {
162
+ this.treeData[0].children.splice(i, 1);
163
+ this.nodeNumbers--;
164
+ return;
165
+ }
166
+ }
167
+ }
168
+ },
158
169
  /**
159
170
  * This is called when a new zinc object is read into the scene.
160
171
  */
@@ -29,7 +29,7 @@
29
29
  />
30
30
  <div v-show="displayUI && !isTransitioning">
31
31
  <DrawToolbar
32
- v-if="viewingMode === 'Annotation' && (userInformation || enableLocalAnnotations)"
32
+ v-if="viewingMode === 'Annotation' && (authorisedUser || offlineAnnotate)"
33
33
  :toolbarOptions="toolbarOptions"
34
34
  :activeDrawTool="activeDrawTool"
35
35
  :activeDrawMode="activeDrawMode"
@@ -310,6 +310,9 @@
310
310
  <el-row class="viewing-mode-description">
311
311
  {{ modeDescription }}
312
312
  </el-row>
313
+ <el-row v-if="viewingMode === 'Annotation' && offlineAnnotate" class="viewing-mode-description">
314
+ (Offline annotate)
315
+ </el-row>
313
316
  </el-row>
314
317
  <el-row class="backgroundSpacer"></el-row>
315
318
  <el-row class="backgroundText"> Change background </el-row>
@@ -698,13 +701,6 @@ export default {
698
701
  type: String,
699
702
  default: "https://mapcore-demo.org/current/flatmap/v3/"
700
703
  },
701
- /**
702
- * Enable local annotations
703
- */
704
- enableLocalAnnotations: {
705
- type: Boolean,
706
- default: false
707
- },
708
704
  },
709
705
  provide() {
710
706
  return {
@@ -809,16 +805,18 @@ export default {
809
805
  },
810
806
  openMapRef: undefined,
811
807
  backgroundIconRef: undefined,
812
- userInformation: undefined,
808
+ offlineAnnotate: false,
809
+ offlineAnnotation: markRaw([]),
810
+ authorisedUser: undefined,
813
811
  toolbarOptions: [
814
812
  "Delete",
815
813
  "Edit",
816
814
  "Point",
817
815
  "LineString",
818
816
  ],
817
+ existDrawnFeatures: markRaw([]), // Store all exist drawn features
819
818
  activeDrawTool: undefined,
820
819
  activeDrawMode: undefined,
821
- localAnnotationsList: markRaw([]),
822
820
  boundingDims: {
823
821
  centre: [0, 0, 0],
824
822
  size:[1, 1, 1],
@@ -963,7 +961,7 @@ export default {
963
961
  modeDescription: function () {
964
962
  let description = this.viewingModes[this.viewingMode];
965
963
  if (this.viewingMode === 'Annotation') {
966
- if (this.userInformation) {
964
+ if (this.authorisedUser) {
967
965
  return description[1]
968
966
  }
969
967
  return description[0]
@@ -1005,12 +1003,12 @@ export default {
1005
1003
  * Remove an entry matching region and group from
1006
1004
  * local annotation list.
1007
1005
  */
1008
- removeFromLocalAnnotationList: function(regionPath, groupName) {
1009
- for (let i = 0; i < this.localAnnotationsList.length; i++) {
1010
- const annotation = this.localAnnotationsList[i];
1006
+ removeFromOfflineAnnotation: function(regionPath, groupName) {
1007
+ for (let i = 0; i < this.offlineAnnotation.length; i++) {
1008
+ const annotation = this.offlineAnnotation[i];
1011
1009
  if (annotation.region === regionPath &&
1012
1010
  annotation.group === groupName) {
1013
- this.localAnnotationsList.splice(i, 1);
1011
+ this.offlineAnnotation.splice(i, 1);
1014
1012
  return;
1015
1013
  }
1016
1014
  }
@@ -1028,7 +1026,9 @@ export default {
1028
1026
  //Remove relevant objects from the rest of the app.
1029
1027
  if (objects.length === 0) {
1030
1028
  this.$_searchIndex.removeZincObject(zincObject, zincObject.uuid);
1031
- this.removeFromLocalAnnotationList(regionPath, groupName);
1029
+ if (this.offlineAnnotate) {
1030
+ this.removeFromOfflineAnnotation(regionPath, groupName);
1031
+ }
1032
1032
  }
1033
1033
  }
1034
1034
  },
@@ -1109,16 +1109,20 @@ export default {
1109
1109
  addAndEditAnnotations: function (region, group, zincObject, comment) {
1110
1110
  const annotation = addUserAnnotationWithFeature(this.annotator, this.userToken, zincObject,
1111
1111
  region, group, this.url, comment);
1112
- if (this.enableLocalAnnotations) {
1112
+ this.existDrawnFeatures = markRaw(this.existDrawnFeatures.filter(feature => feature.id !== annotation.item.id));
1113
+ this.existDrawnFeatures.push(annotation.feature);
1114
+ if (this.offlineAnnotate) {
1113
1115
  annotation.group = group;
1114
1116
  let regionPath = region;
1115
1117
  if (regionPath.slice(-1) === "/") {
1116
1118
  regionPath = regionPath.slice(0, -1);
1117
1119
  }
1118
1120
  annotation.region = regionPath;
1121
+ this.offlineAnnotation = JSON.parse(sessionStorage.getItem('offline-annotation')) || [];
1119
1122
  //Remove previous entry if there is matching region and group
1120
- this.removeFromLocalAnnotationList(regionPath, group);
1121
- this.localAnnotationsList.push(annotation);
1123
+ this.removeFromOfflineAnnotation(regionPath, group);
1124
+ this.offlineAnnotation.push(annotation);
1125
+ sessionStorage.setItem('offline-annotation', JSON.stringify(this.offlineAnnotation));
1122
1126
  }
1123
1127
  this.$emit('userPrimitivesUpdated', {region, group, zincObject});
1124
1128
  },
@@ -1206,16 +1210,19 @@ export default {
1206
1210
  * Confirm delete of user created primitive.
1207
1211
  * This is only called from callback.
1208
1212
  */
1209
- confirmDelete: function() {
1213
+ confirmDelete: function () {
1210
1214
  if (this._editingZincObject?.isEditable) {
1211
1215
  const regionPath = this._editingZincObject.region.getFullPath() + "/";
1212
1216
  const group = this._editingZincObject.groupName;
1213
1217
  const annotation = addUserAnnotationWithFeature(this.annotator, this.userToken,
1214
1218
  this._editingZincObject, regionPath, group, this.url, "Deleted");
1215
1219
  if (annotation) {
1216
- const childRegion = this.$module.scene.getRootRegion().
1217
- findChildFromPath(regionPath);
1220
+ this.existDrawnFeatures = markRaw(this.existDrawnFeatures.filter(feature => feature.id !== annotation.item.id));
1221
+ const childRegion = this.$module.scene.getRootRegion().findChildFromPath(regionPath);
1218
1222
  childRegion.removeZincObject(this._editingZincObject);
1223
+ if (this.offlineAnnotate) {
1224
+ sessionStorage.setItem('offline-annotation', JSON.stringify(this.offlineAnnotation));
1225
+ }
1219
1226
  }
1220
1227
  }
1221
1228
  this.cancelCreate();
@@ -1329,7 +1336,6 @@ export default {
1329
1336
  this.createData.shape = '';
1330
1337
  this.$module.selectObjectOnPick = true;
1331
1338
  } else if (type === 'tool') {
1332
- if (this.annotationDisplay) return;
1333
1339
  this.activeDrawTool = icon;
1334
1340
  this.createData.shape = this.activeDrawTool ? this.activeDrawTool : '';
1335
1341
  this.$module.selectObjectOnPick = false;
@@ -1475,7 +1481,7 @@ export default {
1475
1481
  }
1476
1482
  },
1477
1483
  activateAnnotationMode: function(names, event) {
1478
- if (this.userInformation || this.enableLocalAnnotations) {
1484
+ if (this.authorisedUser || this.offlineAnnotate) {
1479
1485
  this.createData.toBeDeleted = false;
1480
1486
  if ((this.createData.shape !== "") || (this.createData.editingIndex > -1)) {
1481
1487
  // Create new shape bsaed on current settings
@@ -1964,6 +1970,41 @@ export default {
1964
1970
  this.hideRegionTooltip();
1965
1971
  return false;
1966
1972
  },
1973
+ clearAnnotationFeature: function () {
1974
+ const annotations = this.getOfflineAnnotations();
1975
+ const featureGroups = this.existDrawnFeatures.map(feature => decodeURIComponent(feature.id).split("/").pop());
1976
+ featureGroups.forEach((name) => {
1977
+ const zincObject = this.$module.scene.findObjectsWithGroupName(name, false);
1978
+ if (zincObject && zincObject.length) {
1979
+ const regionPath = zincObject[0].region.getFullPath() + "/";
1980
+ const childRegion = this.$module.scene.getRootRegion().findChildFromPath(regionPath);
1981
+ childRegion.removeZincObject(zincObject[0]);
1982
+ }
1983
+ })
1984
+ this.$refs.scaffoldTreeControls.removeRegion('__annotation');
1985
+ // Offline annotations are removed when switch viewing mode
1986
+ // Restore data in case need to save settings, doesn't affect anything
1987
+ this.offlineAnnotation = annotations;
1988
+ },
1989
+ addAnnotationFeature: async function () {
1990
+ let drawnFeatures;
1991
+ if (this.offlineAnnotate) {
1992
+ this.offlineAnnotation = JSON.parse(sessionStorage.getItem('offline-annotation')) || [];
1993
+ drawnFeatures = this.offlineAnnotation.filter((offline) => offline.resource === this.url).map(offline => offline.feature);
1994
+ } else {
1995
+ drawnFeatures = [];
1996
+ const drawn = await getDrawnAnnotations(this.annotator, this.userToken, this.url);
1997
+ if (drawn && drawn.features) {
1998
+ drawnFeatures = [...drawn.features];
1999
+ }
2000
+ const drawnEncode = await getDrawnAnnotations(this.annotator, this.userToken, encodeURIComponent(this.url));
2001
+ if (drawnEncode && drawnEncode.features) {
2002
+ drawnFeatures = [...drawnFeatures, ...drawnEncode.features];
2003
+ }
2004
+ }
2005
+ this.existDrawnFeatures = markRaw(drawnFeatures);
2006
+ annotationFeaturesToPrimitives(this.$module.scene, drawnFeatures);
2007
+ },
1967
2008
  /**
1968
2009
  * Callback on viewing mode change
1969
2010
  * Optional, can be used to update the view mode.
@@ -1973,35 +2014,26 @@ export default {
1973
2014
  if (modeName) {
1974
2015
  this.viewingMode = modeName;
1975
2016
  }
2017
+ this.clearAnnotationFeature();
1976
2018
  if (this.viewingMode === "Annotation") {
1977
- let authenticated = false;
1978
- if (this.userInformation) {
1979
- authenticated = true;
1980
- }
1981
- this.userInformation = undefined;
2019
+ this.loading = true;
1982
2020
  this.annotator.authenticate(this.userToken).then((userData) => {
1983
2021
  if (userData.name && userData.email && userData.canUpdate) {
1984
- this.userInformation = userData;
1985
- //Only draw annotations stored in the server on initial authentication
1986
- if (!authenticated) {
1987
- getDrawnAnnotations(this.annotator, this.userToken, this.url).then((payload) => {
1988
- if (payload && payload.features) {
1989
- annotationFeaturesToPrimitives(this.$module.scene, payload.features);
1990
- }
1991
- });
1992
- //Support previously supported encoded resource
1993
- getDrawnAnnotations(this.annotator, this.userToken, encodeURIComponent(this.url)).then((payload) => {
1994
- if (payload && payload.features) {
1995
- annotationFeaturesToPrimitives(this.$module.scene, payload.features);
1996
- }
1997
- });
1998
- }
2022
+ this.authorisedUser = userData;
2023
+ this.offlineAnnotate = false;
2024
+ } else {
2025
+ this.authorisedUser = undefined;
2026
+ this.offlineAnnotate = true;
1999
2027
  }
2028
+ this.addAnnotationFeature();
2029
+ this.loading = false;
2000
2030
  });
2001
- } else if (this.viewingMode === "Exploration") {
2002
- this.activeDrawTool = undefined;
2003
- this.activeDrawMode = undefined;
2004
- this.createData.shape = "";
2031
+ } else {
2032
+ if (this.viewingMode === "Exploration") {
2033
+ this.activeDrawTool = undefined;
2034
+ this.activeDrawMode = undefined;
2035
+ this.createData.shape = "";
2036
+ }
2005
2037
  }
2006
2038
  if ((this.viewingMode === "Exploration") ||
2007
2039
  (this.viewingMode === "Annotation") &&
@@ -2189,6 +2221,11 @@ export default {
2189
2221
  if (options.background) {
2190
2222
  this.backgroundChangeCallback(options.background);
2191
2223
  }
2224
+ if (options.offlineAnnotation) {
2225
+ if (options.offlineAnnotation.expiry > new Date().getTime()) {
2226
+ sessionStorage.setItem('offline-annotation', options.offlineAnnotation.value);
2227
+ }
2228
+ }
2192
2229
  if (options.viewingMode) {
2193
2230
  this.changeViewingMode(options.viewingMode);
2194
2231
  }
@@ -2209,7 +2246,7 @@ export default {
2209
2246
  },
2210
2247
  setURLFinishCallback: function (options) {
2211
2248
  return () => {
2212
- this.localAnnotationsList.length = 0;
2249
+ this.offlineAnnotation.length = 0;
2213
2250
  this.updateSettingsfromScene();
2214
2251
  this.$module.updateTime(0.01);
2215
2252
  this.$module.updateTime(0);
@@ -2258,6 +2295,16 @@ export default {
2258
2295
  if (this.lastSelected && this.lastSelected.group) {
2259
2296
  state.search = {...this.lastSelected};
2260
2297
  }
2298
+ if (this.offlineAnnotate) {
2299
+ if (!sessionStorage.getItem('offline-annotation-expiry')) {
2300
+ const expiry = new Date().getTime() + 24 * 60 * 60 * 1000;
2301
+ sessionStorage.setItem('offline-annotation-expiry', expiry);
2302
+ }
2303
+ state.offlineAnnotation = {
2304
+ expiry: sessionStorage.getItem('offline-annotation-expiry'),
2305
+ value: sessionStorage.getItem('offline-annotation'),
2306
+ };
2307
+ }
2261
2308
  return state;
2262
2309
  },
2263
2310
  /**
@@ -2277,6 +2324,7 @@ export default {
2277
2324
  background: state.background,
2278
2325
  viewingMode: this.viewingMode,
2279
2326
  search: state.search,
2327
+ offlineAnnotation: state.offlineAnnotation,
2280
2328
  });
2281
2329
  } else {
2282
2330
  if (state.background || state.search || state.viewport || state.viewingMode || state.visibility) {
@@ -2290,6 +2338,7 @@ export default {
2290
2338
  viewport: state.viewport,
2291
2339
  visibility: state.visibility,
2292
2340
  search: state.search,
2341
+ offlineAnnotation: state.offlineAnnotation,
2293
2342
  })
2294
2343
  );
2295
2344
  }
@@ -2309,23 +2358,23 @@ export default {
2309
2358
  /**
2310
2359
  * Return a copy of the local annotations list.
2311
2360
  * This list is used for storing user created annotation
2312
- * when enableLocalAnnotations is set to true.
2361
+ * when offlineAnnotate is set to true.
2313
2362
  *
2314
2363
  * @public
2315
2364
  */
2316
- getLocalAnnotations: function () {
2317
- return [...this.localAnnotationsList];
2365
+ getOfflineAnnotations: function () {
2366
+ return [...this.offlineAnnotation];
2318
2367
  },
2319
2368
  /**
2320
2369
  * Import local annotations. The annotations will only
2321
- * be imported when enableLocalAnnotations is set to
2370
+ * be imported when offlineAnnotate is set to
2322
2371
  * true;
2323
2372
  *
2324
2373
  * @public
2325
2374
  * @arg {Array} `annotationsList`
2326
2375
  */
2327
- importLocalAnnotations: function (annotationsList) {
2328
- if (this.enableLocalAnnotations) {
2376
+ importOfflineAnnotations: function (annotationsList) {
2377
+ if (this.offlineAnnotate) {
2329
2378
  //Make sure the annotations are encoded correctly
2330
2379
  annotationsList.forEach(annotation => {
2331
2380
  const group = annotation.group;
@@ -2342,8 +2391,9 @@ export default {
2342
2391
  annotationFeaturesToPrimitives(this.$module.scene, featuresList);
2343
2392
  //Make a local non-reactive copy.
2344
2393
  annotationsList.forEach((annotation) => {
2345
- this.localAnnotationsList.push({...annotation});
2394
+ this.offlineAnnotation.push({...annotation});
2346
2395
  });
2396
+ sessionStorage.setItem('offline-annotation', JSON.stringify(this.offlineAnnotation));
2347
2397
  }
2348
2398
  },
2349
2399
 
@@ -2378,6 +2428,7 @@ export default {
2378
2428
  viewURL: this.viewURL,
2379
2429
  viewport: state?.viewport,
2380
2430
  visibility: state?.visibility,
2431
+ offlineAnnotation: state?.offlineAnnotation,
2381
2432
  })
2382
2433
  );
2383
2434
  if (this.fileFormat === "gltf") {
@@ -1,36 +0,0 @@
1
- import { defineConfig } from 'vite'
2
- import rootConfig from './vite.config.js'
3
- import { nodePolyfills } from 'vite-plugin-node-polyfills'
4
- import vue from '@vitejs/plugin-vue'
5
-
6
- // defineWorkspace provides a nice type hinting DX
7
- export default defineConfig((configEnv) => {
8
- const config = rootConfig(configEnv);
9
- config.css.extract = false
10
- config.plugins.push(
11
- nodePolyfills({
12
- // To add only specific polyfills, add them here. If no option is passed, adds all polyfills
13
- include: ['path']
14
- })
15
- );
16
- // config.plugins.push(
17
- // cssInjectedByJsPlugin()
18
- // );
19
- config.plugins[0] = vue({
20
- template: {
21
- compilerOptions: {
22
- isCustomElement: (tag) => tag.includes('scaffoldvuer-wc')
23
- }
24
- }
25
- }),
26
- config.build = {
27
- lib: {
28
- entry: './src/ScaffoldVuer-wc.js',
29
- name: 'scaffoldvuer-wc',
30
- // the proper extensions will be added
31
- fileName: 'scaffoldvuer-wc'
32
- },
33
- }
34
-
35
- return config;
36
- })