@geode/opengeodeweb-front 10.33.4-rc.2 → 10.34.0-rc.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.
@@ -0,0 +1,24 @@
1
+ .v-card-title.text-caption {
2
+ font-size: 0.75rem !important;
3
+ line-height: 1.25rem !important;
4
+ }
5
+
6
+ .v-card-title.text-subtitle-2 {
7
+ font-size: 0.875rem !important;
8
+ line-height: 1.375rem !important;
9
+ }
10
+
11
+ .v-card-title.text-subtitle-1 {
12
+ font-size: 1rem !important;
13
+ line-height: 1.5rem !important;
14
+ }
15
+
16
+ .v-card-title.text-body-2 {
17
+ font-size: 0.875rem !important;
18
+ line-height: 1.25rem !important;
19
+ }
20
+
21
+ .v-card-title.text-body-1 {
22
+ font-size: 1rem !important;
23
+ line-height: 1.5rem !important;
24
+ }
@@ -39,7 +39,7 @@ const {
39
39
  selectedDatasetIds,
40
40
  allItems,
41
41
  hybridViewerStore,
42
- debouncedApply: () => debouncedApply(),
42
+ debouncedApply: (...args) => debouncedApply?.(...args),
43
43
  });
44
44
 
45
45
  async function applyClippingPlanes() {
@@ -90,33 +90,33 @@ const modelVisibility = computed({
90
90
  },
91
91
  });
92
92
 
93
- const modelComponentsActiveColoring = computed({
94
- get: () => dataStyleStore.getModelActiveColoring(modelId.value),
95
- set: async (coloringType) => {
93
+ const modelComponentsColor = computed({
94
+ get: () => dataStyleStore.getModelColor(modelId.value),
95
+ set: async (color) => {
96
96
  await dataStyleStore.mutateStyle(modelId.value, {
97
- coloring: { active: coloringType },
97
+ coloring: { constant: color },
98
98
  });
99
99
  await dataStyleStore.setModelComponentsColor(
100
100
  modelId.value,
101
101
  selection.value,
102
- dataStyleStore.getModelColor(modelId.value),
103
- coloringType,
102
+ color,
103
+ dataStyleStore.getModelActiveColoring(modelId.value),
104
104
  );
105
105
  hybridViewerStore.remoteRender();
106
106
  },
107
107
  });
108
108
 
109
- const modelComponentsColor = computed({
110
- get: () => dataStyleStore.getModelColor(modelId.value),
111
- set: async (color) => {
109
+ const modelComponentsActiveColoring = computed({
110
+ get: () => dataStyleStore.getModelActiveColoring(modelId.value),
111
+ set: async (coloringType) => {
112
112
  await dataStyleStore.mutateStyle(modelId.value, {
113
- coloring: { constant: color },
113
+ coloring: { active: coloringType },
114
114
  });
115
115
  await dataStyleStore.setModelComponentsColor(
116
116
  modelId.value,
117
117
  selection.value,
118
- color,
119
- dataStyleStore.getModelActiveColoring(modelId.value),
118
+ dataStyleStore.getModelColor(modelId.value),
119
+ coloringType,
120
120
  );
121
121
  hybridViewerStore.remoteRender();
122
122
  },
@@ -54,8 +54,8 @@ const { virtualScrollRef, stickyHeader, handleScroll, scrollToIndex, getScrollIn
54
54
  actualItemProps,
55
55
  );
56
56
 
57
- const lastActiveIndex = ref(-1);
58
57
  const focusedIndex = ref(-1);
58
+ const lastActiveIndex = ref(-1);
59
59
 
60
60
  function handleItemClick(item, index, event) {
61
61
  if (index !== undefined) {
@@ -110,6 +110,8 @@ const { handleKeyDown } = useTreeKeyboardNav(
110
110
  scrollToIndex,
111
111
  toggleOpen,
112
112
  handleItemClick,
113
+ getScrollInfo,
114
+ focusedIndex,
113
115
  );
114
116
  </script>
115
117
 
@@ -177,5 +177,7 @@ watch(
177
177
  background-color: rgba(255, 255, 255, 0.05);
178
178
  border-bottom: 1px solid rgba(0, 0, 0, 0.05);
179
179
  flex-shrink: 0;
180
+ font-size: 0.875rem !important;
181
+ line-height: 1.25rem !important;
180
182
  }
181
183
  </style>
@@ -210,11 +210,10 @@ function useClippingPlanesWidget({
210
210
  maxDistance = localRenderWindow.getRenderer().getActiveCamera().getDistance();
211
211
  }
212
212
  }
213
+
213
214
  function initLocalWidget(container) {
214
215
  cleanupLocalWidget();
215
- container.addEventListener("wheel", (event) => event.stopPropagation(), {
216
- passive: true,
217
- });
216
+ container.addEventListener("wheel", (event) => event.stopPropagation(), { passive: true });
218
217
  localRenderWindow = vtkGenericRenderWindow({
219
218
  background: [0, 0, 0, 0],
220
219
  listenWindowResize: false,
@@ -223,16 +222,13 @@ function useClippingPlanesWidget({
223
222
  const camera = localRenderWindow.getRenderer().getActiveCamera();
224
223
  camera.onModified(() => limitCameraZoomOut(camera));
225
224
  const canvas = localRenderWindow.getApiSpecificRenderWindow().getCanvas();
226
- Object.assign(canvas.style, {
227
- width: "100%",
228
- height: "100%",
229
- background: "transparent",
230
- });
225
+ Object.assign(canvas.style, { width: "100%", height: "100%", background: "transparent" });
231
226
  localRenderWindow.resize();
232
227
  widgetManager = vtkWidgetManager();
233
228
  widgetManager.setRenderer(localRenderWindow.getRenderer());
234
229
  updateWidgetPlacement();
235
230
  }
231
+
236
232
  function isFromWidget() {
237
233
  return fromWidget;
238
234
  }
@@ -23,8 +23,9 @@ export function useTreeKeyboardNav(
23
23
  toggleOpen,
24
24
  handleItemClick,
25
25
  getScrollInfo,
26
+ externalFocusedIndex,
26
27
  ) {
27
- const focusedIndex = ref(-1);
28
+ const focusedIndex = externalFocusedIndex || ref(-1);
28
29
 
29
30
  function findParentIndex(item, currentIndex) {
30
31
  for (let index = currentIndex - 1; index >= 0; index -= 1) {
@@ -196,13 +196,16 @@ export const useDataStore = defineStore("data", () => {
196
196
  await model_components_db.where("id").equals(modelId).delete();
197
197
  await database.model_components_relation.where("id").equals(modelId).delete();
198
198
  }
199
+
199
200
  async function deleteItem(id) {
200
201
  await data_db.delete(id);
201
202
  await deleteModelComponents(id);
202
203
  }
204
+
203
205
  async function updateItem(id, changes) {
204
206
  await data_db.update(id, changes);
205
207
  }
208
+
206
209
  async function getAllModelComponentsViewerIds(modelId) {
207
210
  const components = await model_components_db.where("id").equals(modelId).toArray();
208
211
  return components.map((component) => Math.trunc(Number(component.viewer_id)));
@@ -224,11 +227,13 @@ export const useDataStore = defineStore("data", () => {
224
227
  modelComponentsRelations,
225
228
  };
226
229
  }
230
+
227
231
  async function clear() {
228
232
  await data_db.clear();
229
233
  await model_components_db.clear();
230
234
  await model_components_relation_db.clear();
231
235
  }
236
+
232
237
  async function importStores(snapshot) {
233
238
  await clear();
234
239
  await model_components_db.bulkPut(snapshot.modelComponents);
@@ -13,6 +13,7 @@ async function uploadExtension(file) {
13
13
  const appStore = useAppStore();
14
14
  await appStore.upload(file);
15
15
  }
16
+
16
17
  function runExtensions() {
17
18
  const appStore = useAppStore();
18
19
  const { projectFolderPath } = appStore;
@@ -29,6 +30,22 @@ function runExtensions() {
29
30
  params,
30
31
  });
31
32
  }
33
+
34
+ function downloadExtension({ url, extensionFileName }) {
35
+ const appStore = useAppStore();
36
+ const { PROJECT: projectName } = useRuntimeConfig().public;
37
+ const schema = opengeodeweb_front_schemas.api.microservice.extensions.download;
38
+ const params = {
39
+ projectName,
40
+ url,
41
+ extensionFileName,
42
+ };
43
+ return appStore.request({
44
+ schema,
45
+ params,
46
+ });
47
+ }
48
+
32
49
  async function registerRunningExtensions() {
33
50
  const appStore = useAppStore();
34
51
  const infraStore = useInfraStore();
@@ -55,28 +72,17 @@ async function registerRunningExtensions() {
55
72
  }),
56
73
  );
57
74
  }
75
+
58
76
  async function importExtensionFile(file) {
59
77
  await uploadExtension(file);
60
78
  return registerRunningExtensions();
61
79
  }
62
- function downloadExtension({ url, extensionFileName }) {
63
- const appStore = useAppStore();
64
- const { PROJECT: projectName } = useRuntimeConfig().public;
65
- const schema = opengeodeweb_front_schemas.api.microservice.extensions.download;
66
- const params = {
67
- projectName,
68
- url,
69
- extensionFileName,
70
- };
71
- return appStore.request({
72
- schema,
73
- params,
74
- });
75
- }
80
+
76
81
  async function importExtensionURL(url) {
77
82
  await downloadExtension(url);
78
83
  return registerRunningExtensions();
79
84
  }
85
+
80
86
  async function unloadExtension(extensionId) {
81
87
  const appStore = useAppStore();
82
88
  console.log("[ExtensionManager] Unloading extension:", extensionId);
@@ -101,6 +107,7 @@ async function unloadExtension(extensionId) {
101
107
  console.log("[ExtensionManager] Extension unloaded:", extensionId);
102
108
  return true;
103
109
  }
110
+
104
111
  function killExtension(extensionId) {
105
112
  const appStore = useAppStore();
106
113
  const { projectFolderPath } = appStore;
@@ -69,12 +69,14 @@ async function importFile(filename, geode_object_type) {
69
69
  });
70
70
  return importItem(response);
71
71
  }
72
+
72
73
  async function importWorkflow(files) {
73
74
  const chunk_size = 5;
74
75
  const chunks = [];
75
76
  for (let i = 0; i < files.length; i += chunk_size) {
76
77
  chunks.push(files.slice(i, i + chunk_size));
77
78
  }
79
+
78
80
  const results = [];
79
81
  async function processChunk(chunkIndex) {
80
82
  if (chunkIndex >= chunks.length) {
@@ -92,10 +94,9 @@ async function importWorkflow(files) {
92
94
  hybridViewerStore.remoteRender();
93
95
  return results;
94
96
  }
97
+
95
98
  async function importWorkflowFromSnapshot(items) {
96
- console.log("[importWorkflowFromSnapshot] start", {
97
- count: items?.length,
98
- });
99
+ console.log("[importWorkflowFromSnapshot] start", { count: items?.length });
99
100
  const hybridViewerStore = useHybridViewerStore();
100
101
  const chunk_size = 5;
101
102
  const chunks = [];
@@ -58,6 +58,7 @@ class Database extends BaseDatabase {
58
58
  }
59
59
  }
60
60
  }
61
+
61
62
  // oxlint-disable-next-line no-top-level-await
62
63
  await Dexie.delete("Database");
63
64
  databaseContainer.instance = new Database();
@@ -99,9 +99,10 @@ function applyCameraOptions(camera, options) {
99
99
  });
100
100
  }
101
101
  }
102
+
102
103
  function performSetCamera(targetCameraOptions) {
103
104
  const hybridViewerStore = useHybridViewerStore();
104
- const { genericRenderWindow, syncRemoteCamera } = hybridViewerStore;
105
+ const { genericRenderWindow } = hybridViewerStore;
105
106
  const { is_moving } = storeToRefs(hybridViewerStore);
106
107
  const imageStyle = getImageStyle();
107
108
  const renderer = genericRenderWindow.value.getRenderer();
@@ -128,7 +129,7 @@ function performSetCamera(targetCameraOptions) {
128
129
  const renderWindow = genericRenderWindow.value.getRenderWindow();
129
130
  renderWindow.render();
130
131
  is_moving.value = false;
131
- syncRemoteCamera();
132
+ performSyncRemoteCamera();
132
133
  },
133
134
  });
134
135
  }
@@ -162,7 +163,7 @@ async function performFocusCameraOnObject(id, block_ids = []) {
162
163
  }
163
164
  function performCameraOrientation(orientation) {
164
165
  const hybridViewerStore = useHybridViewerStore();
165
- const { genericRenderWindow, syncRemoteCamera } = hybridViewerStore;
166
+ const { genericRenderWindow } = hybridViewerStore;
166
167
  const { is_moving } = storeToRefs(hybridViewerStore);
167
168
  const imageStyle = getImageStyle();
168
169
  const config = ORIENTATIONS[orientation.toLowerCase()];
@@ -196,7 +197,7 @@ function performCameraOrientation(orientation) {
196
197
  },
197
198
  onEnd: () => {
198
199
  is_moving.value = false;
199
- syncRemoteCamera();
200
+ performSyncRemoteCamera();
200
201
  },
201
202
  });
202
203
  }
@@ -14,6 +14,7 @@ function createClearHoverData(hoverTimeoutRef, hoverData, currentHoverId) {
14
14
  currentHoverId.value = undefined;
15
15
  };
16
16
  }
17
+
17
18
  function performHoverHighlight(event, onResponse) {
18
19
  const hybridViewerStore = useHybridViewerStore();
19
20
  const { genericRenderWindow, hybridDb } = hybridViewerStore;
@@ -127,6 +128,7 @@ function performClearHoverHighlight() {
127
128
  params,
128
129
  });
129
130
  }
131
+
130
132
  function useHybridViewerHighlight() {
131
133
  const is_hover_highlight = ref(false);
132
134
  const hover_highlight_field_type = ref("CELL");
@@ -143,10 +145,12 @@ function useHybridViewerHighlight() {
143
145
  currentHoverId,
144
146
  clearHoverData,
145
147
  });
148
+
146
149
  function clearHoverHighlight() {
147
150
  clearHoverData();
148
151
  performClearHoverHighlight();
149
152
  }
153
+
150
154
  return {
151
155
  is_hover_highlight,
152
156
  hover_highlight_field_type,
@@ -156,6 +160,7 @@ function useHybridViewerHighlight() {
156
160
  hoverHighlight,
157
161
  };
158
162
  }
163
+
159
164
  export {
160
165
  createClearHoverData,
161
166
  createHoverHighlight,
@@ -26,6 +26,7 @@ async function performResize(width, height) {
26
26
  renderWindow.render();
27
27
  await remoteRender();
28
28
  }
29
+
29
30
  function performClickPicking(event, containerElement) {
30
31
  const { genericRenderWindow, syncRemoteCamera } = useHybridViewerStore();
31
32
  const viewerStore = useViewerStore();
@@ -55,6 +56,7 @@ function performClickPicking(event, containerElement) {
55
56
  },
56
57
  );
57
58
  }
59
+
58
60
  function performSetContainer(container) {
59
61
  if (!container || !container.value) {
60
62
  return;
package/nuxt.config.js CHANGED
@@ -17,7 +17,11 @@ export default defineNuxtConfig({
17
17
  },
18
18
  },
19
19
 
20
- modules: [["@pinia/nuxt", { autoImports: ["defineStore", "storeToRefs"] }], "@vueuse/nuxt"],
20
+ modules: [
21
+ "vuetify-nuxt-module",
22
+ ["@pinia/nuxt", { autoImports: ["defineStore", "storeToRefs"] }],
23
+ "@vueuse/nuxt",
24
+ ],
21
25
  imports: {
22
26
  scan: false,
23
27
  },
@@ -33,7 +37,7 @@ export default defineNuxtConfig({
33
37
  },
34
38
 
35
39
  // ** Global CSS
36
- css: ["vuetify/lib/styles/main.sass"],
40
+ css: ["vuetify/lib/styles/main.sass", path.resolve(__dirname, "app/assets/css/main.css")],
37
41
 
38
42
  // ** Build configuration
39
43
  build: {
@@ -43,6 +47,10 @@ export default defineNuxtConfig({
43
47
  vuetify: {
44
48
  moduleOptions: {
45
49
  prefixComposables: true,
50
+ enableRules: false,
51
+ rulesConfiguration: {
52
+ fromLabs: false,
53
+ },
46
54
  },
47
55
  vuetifyOptions: {
48
56
  defaults: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geode/opengeodeweb-front",
3
- "version": "10.33.4-rc.2",
3
+ "version": "10.34.0-rc.1",
4
4
  "description": "OpenSource Vue/Nuxt/Pinia/Vuetify framework for web applications",
5
5
  "homepage": "https://github.com/Geode-solutions/OpenGeodeWeb-Front",
6
6
  "bugs": {
@@ -69,8 +69,8 @@
69
69
  "semver": "7.7.1",
70
70
  "tar": "7.5.22",
71
71
  "uuid": "11.1.0",
72
- "vuetify": "3.12.5",
73
- "vuetify-nuxt-module": "0.18.7",
72
+ "vuetify": "4.2.0",
73
+ "vuetify-nuxt-module": "1.0.0-rc.5",
74
74
  "ws": "8.21.2",
75
75
  "wslink": "1.12.4"
76
76
  },
@@ -39,10 +39,12 @@ function addExtensionToConf(projectName, { extensionId, extensionPath }) {
39
39
  const projectConfig = projectConf(projectName);
40
40
  projectConfig.set(`extensions.${extensionId}.path`, extensionPath);
41
41
  }
42
+
42
43
  function extensionPathFromConf(projectName, extensionId) {
43
44
  const projectConfig = projectConf(projectName);
44
45
  return projectConfig.get(`extensions.${extensionId}.path`);
45
46
  }
47
+
46
48
  async function removeExtensionFromConf(projectName, extensionId) {
47
49
  const projectConfig = projectConf(projectName);
48
50
  const extensionArchivePath = extensionPathFromConf(projectName, extensionId);
@@ -55,6 +57,7 @@ async function removeExtensionFromConf(projectName, extensionId) {
55
57
  projectConfig.delete(`extensions.${extensionId}`);
56
58
  console.log(`${extensionId} was deleted from ${projectName} config`);
57
59
  }
60
+
58
61
  async function registerExtensionFile(projectName, file) {
59
62
  const StreamZipAsync = StreamZip.async;
60
63
  const zip = new StreamZipAsync({
@@ -134,6 +134,7 @@ async function killMicroservices(microservices) {
134
134
  function microservicesMetadatasPath(projectFolderPath) {
135
135
  return path.join(projectFolderPath, "microservices.json");
136
136
  }
137
+
137
138
  function projectMicroservices(projectFolderPath) {
138
139
  console.log("projectMicroservices", {
139
140
  projectFolderPath,
@@ -160,6 +161,7 @@ async function cleanupBackend(projectFolderPath) {
160
161
  function getMicroserviceByName(microservices, name) {
161
162
  return microservices.find((microservice) => microservice.name === name);
162
163
  }
164
+
163
165
  export {
164
166
  cleanupBackend,
165
167
  deleteFolderRecursive,
@@ -49,6 +49,7 @@ async function runScript(
49
49
  function isPortInUseError(errorMessage) {
50
50
  return /EADDRINUSE|address already in use|port already in use/iu.test(errorMessage);
51
51
  }
52
+
52
53
  function backArgs(args, port) {
53
54
  const { projectFolderPath } = args;
54
55
  if (!projectFolderPath) {
@@ -72,6 +73,7 @@ function backArgs(args, port) {
72
73
  }
73
74
  return executableArgs;
74
75
  }
76
+
75
77
  async function runBack(execName, execPath, args = {}, attempts = 0) {
76
78
  let port = undefined;
77
79
  try {
@@ -92,6 +94,7 @@ async function runBack(execName, execPath, args = {}, attempts = 0) {
92
94
  }
93
95
  }
94
96
  }
97
+
95
98
  async function runViewer(execName, execPath, args = {}, attempts = 0) {
96
99
  const { projectFolderPath } = args;
97
100
  if (!projectFolderPath) {
@@ -123,6 +126,7 @@ async function runViewer(execName, execPath, args = {}, attempts = 0) {
123
126
  }
124
127
  }
125
128
  }
129
+
126
130
  async function runExtension(extensionId, execName, execPath, args = {}, attempts = 0) {
127
131
  let port = undefined;
128
132
  try {
@@ -11,6 +11,13 @@ import { v4 as uuidv4 } from "uuid";
11
11
  import { appMode } from "@geode/opengeodeweb-front/shared/app_mode.js";
12
12
  import { commandExistsSync } from "./scripts.js";
13
13
 
14
+ function executableName(execName) {
15
+ if (process.platform === "win32") {
16
+ return `${execName}.exe`;
17
+ }
18
+ return execName;
19
+ }
20
+
14
21
  function findExecutableInDir(baseDir, execName, osExecutableName) {
15
22
  const oneFilePath = path.join(baseDir, osExecutableName);
16
23
  if (fs.existsSync(oneFilePath) && fs.statSync(oneFilePath).isFile()) {
@@ -27,12 +34,7 @@ function findExecutableInDir(baseDir, execName, osExecutableName) {
27
34
  );
28
35
  return undefined;
29
36
  }
30
- function executableName(execName) {
31
- if (process.platform === "win32") {
32
- return `${execName}.exe`;
33
- }
34
- return execName;
35
- }
37
+
36
38
  function executablePath(execPath, execName) {
37
39
  const osExecutableName = executableName(execName);
38
40
  const resourcesPath = process.env.RESOURCES_PATH;
@@ -62,6 +64,7 @@ function executablePath(execPath, execName) {
62
64
 
63
65
  throw new Error(`Executable not found: ${osExecutableName}`);
64
66
  }
67
+
65
68
  function createPath(dirPath) {
66
69
  if (!fs.existsSync(dirPath)) {
67
70
  fs.mkdirSync(dirPath, {
@@ -31,12 +31,21 @@ describe("step", () => {
31
31
  ],
32
32
  { geode_object_type },
33
33
  );
34
- const wrapper = mount(Step, {
35
- global: {
36
- plugins: [vuetify],
34
+ const wrapper = mount(
35
+ {
36
+ components: { Step },
37
+ template:
38
+ '<v-stepper-vertical><Step :stepIndex="0" :stepperTree="stepperTree" /></v-stepper-vertical>',
39
+ setup() {
40
+ return { stepperTree: stepper_tree };
41
+ },
42
+ },
43
+ {
44
+ global: {
45
+ plugins: [vuetify],
46
+ },
37
47
  },
38
- props: { stepIndex: 0, stepperTree: stepper_tree },
39
- });
48
+ );
40
49
  expect(wrapper.exists()).toBe(true);
41
50
  });
42
51
  });