@abi-software/scaffoldvuer 1.8.0 → 1.8.1-beta.1

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.1",
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.3-beta.3",
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 || offlineAnnotationEnabled)"
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' && offlineAnnotationEnabled" 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
+ offlineAnnotationEnabled: false,
809
+ offlineAnnotations: 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.offlineAnnotations.length; i++) {
1008
+ const annotation = this.offlineAnnotations[i];
1011
1009
  if (annotation.region === regionPath &&
1012
1010
  annotation.group === groupName) {
1013
- this.localAnnotationsList.splice(i, 1);
1011
+ this.offlineAnnotations.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.offlineAnnotationEnabled) {
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.offlineAnnotationEnabled) {
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.offlineAnnotations = 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.offlineAnnotations.push(annotation);
1125
+ sessionStorage.setItem('offline-annotation', JSON.stringify(this.offlineAnnotations));
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.offlineAnnotationEnabled) {
1224
+ sessionStorage.setItem('offline-annotation', JSON.stringify(this.offlineAnnotations));
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.offlineAnnotationEnabled) {
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.offlineAnnotations = annotations;
1988
+ },
1989
+ addAnnotationFeature: async function () {
1990
+ let drawnFeatures;
1991
+ if (this.offlineAnnotationEnabled) {
1992
+ this.offlineAnnotations = JSON.parse(sessionStorage.getItem('offline-annotation')) || [];
1993
+ drawnFeatures = this.offlineAnnotations.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.offlineAnnotationEnabled = false;
2024
+ } else {
2025
+ this.authorisedUser = undefined;
2026
+ this.offlineAnnotationEnabled = 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,9 @@ export default {
2189
2221
  if (options.background) {
2190
2222
  this.backgroundChangeCallback(options.background);
2191
2223
  }
2224
+ if (options.offlineAnnotations) {
2225
+ sessionStorage.setItem('offline-annotation', options.offlineAnnotations);
2226
+ }
2192
2227
  if (options.viewingMode) {
2193
2228
  this.changeViewingMode(options.viewingMode);
2194
2229
  }
@@ -2209,7 +2244,7 @@ export default {
2209
2244
  },
2210
2245
  setURLFinishCallback: function (options) {
2211
2246
  return () => {
2212
- this.localAnnotationsList.length = 0;
2247
+ this.offlineAnnotations.length = 0;
2213
2248
  this.updateSettingsfromScene();
2214
2249
  this.$module.updateTime(0.01);
2215
2250
  this.$module.updateTime(0);
@@ -2258,6 +2293,9 @@ export default {
2258
2293
  if (this.lastSelected && this.lastSelected.group) {
2259
2294
  state.search = {...this.lastSelected};
2260
2295
  }
2296
+ if (this.offlineAnnotationEnabled) {
2297
+ state.offlineAnnotations = sessionStorage.getItem('offline-annotation');
2298
+ }
2261
2299
  return state;
2262
2300
  },
2263
2301
  /**
@@ -2277,6 +2315,7 @@ export default {
2277
2315
  background: state.background,
2278
2316
  viewingMode: this.viewingMode,
2279
2317
  search: state.search,
2318
+ offlineAnnotations: state.offlineAnnotations,
2280
2319
  });
2281
2320
  } else {
2282
2321
  if (state.background || state.search || state.viewport || state.viewingMode || state.visibility) {
@@ -2290,6 +2329,7 @@ export default {
2290
2329
  viewport: state.viewport,
2291
2330
  visibility: state.visibility,
2292
2331
  search: state.search,
2332
+ offlineAnnotations: state.offlineAnnotations,
2293
2333
  })
2294
2334
  );
2295
2335
  }
@@ -2309,23 +2349,23 @@ export default {
2309
2349
  /**
2310
2350
  * Return a copy of the local annotations list.
2311
2351
  * This list is used for storing user created annotation
2312
- * when enableLocalAnnotations is set to true.
2352
+ * when offlineAnnotationEnabled is set to true.
2313
2353
  *
2314
2354
  * @public
2315
2355
  */
2316
- getLocalAnnotations: function () {
2317
- return [...this.localAnnotationsList];
2356
+ getOfflineAnnotations: function () {
2357
+ return [...this.offlineAnnotations];
2318
2358
  },
2319
2359
  /**
2320
2360
  * Import local annotations. The annotations will only
2321
- * be imported when enableLocalAnnotations is set to
2361
+ * be imported when offlineAnnotationEnabled is set to
2322
2362
  * true;
2323
2363
  *
2324
2364
  * @public
2325
2365
  * @arg {Array} `annotationsList`
2326
2366
  */
2327
- importLocalAnnotations: function (annotationsList) {
2328
- if (this.enableLocalAnnotations) {
2367
+ importOfflineAnnotations: function (annotationsList) {
2368
+ if (this.offlineAnnotationEnabled) {
2329
2369
  //Make sure the annotations are encoded correctly
2330
2370
  annotationsList.forEach(annotation => {
2331
2371
  const group = annotation.group;
@@ -2342,8 +2382,9 @@ export default {
2342
2382
  annotationFeaturesToPrimitives(this.$module.scene, featuresList);
2343
2383
  //Make a local non-reactive copy.
2344
2384
  annotationsList.forEach((annotation) => {
2345
- this.localAnnotationsList.push({...annotation});
2385
+ this.offlineAnnotations.push({...annotation});
2346
2386
  });
2387
+ sessionStorage.setItem('offline-annotation', JSON.stringify(this.offlineAnnotations));
2347
2388
  }
2348
2389
  },
2349
2390
 
@@ -2378,6 +2419,7 @@ export default {
2378
2419
  viewURL: this.viewURL,
2379
2420
  viewport: state?.viewport,
2380
2421
  visibility: state?.visibility,
2422
+ offlineAnnotations: state?.offlineAnnotations,
2381
2423
  })
2382
2424
  );
2383
2425
  if (this.fileFormat === "gltf") {
@@ -7,6 +7,7 @@ export {}
7
7
 
8
8
  declare module 'vue' {
9
9
  export interface GlobalComponents {
10
+ ElAutocomplete: typeof import('element-plus/es')['ElAutocomplete']
10
11
  ElButton: typeof import('element-plus/es')['ElButton']
11
12
  ElCol: typeof import('element-plus/es')['ElCol']
12
13
  ElCollapse: typeof import('element-plus/es')['ElCollapse']
@@ -19,6 +20,7 @@ declare module 'vue' {
19
20
  ElIconDelete: typeof import('@element-plus/icons-vue')['Delete']
20
21
  ElIconPlus: typeof import('@element-plus/icons-vue')['Plus']
21
22
  ElIconWarningFilled: typeof import('@element-plus/icons-vue')['WarningFilled']
23
+ ElInput: typeof import('element-plus/es')['ElInput']
22
24
  ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
23
25
  ElMain: typeof import('element-plus/es')['ElMain']
24
26
  ElOption: typeof import('element-plus/es')['ElOption']
@@ -26,6 +28,9 @@ declare module 'vue' {
26
28
  ElRow: typeof import('element-plus/es')['ElRow']
27
29
  ElSelect: typeof import('element-plus/es')['ElSelect']
28
30
  ElSlider: typeof import('element-plus/es')['ElSlider']
31
+ ElSwitch: typeof import('element-plus/es')['ElSwitch']
32
+ ElTable: typeof import('element-plus/es')['ElTable']
33
+ ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
29
34
  ElTabPane: typeof import('element-plus/es')['ElTabPane']
30
35
  ElTabs: typeof import('element-plus/es')['ElTabs']
31
36
  LinesControls: typeof import('./components/LinesControls.vue')['default']
@@ -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
- })