@geode/opengeodeweb-front 10.29.0-rc.1 → 10.29.0-rc.10

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.
Files changed (28) hide show
  1. package/app/components/Viewer/ContextMenu/InfoCard.vue +56 -21
  2. package/app/components/Viewer/Generic/Model/BlocksOptions.vue +3 -3
  3. package/app/components/Viewer/Generic/Model/CornersOptions.vue +3 -4
  4. package/app/components/Viewer/Generic/Model/LinesOptions.vue +3 -3
  5. package/app/components/Viewer/Generic/Model/ModelStyleCard.vue +5 -1
  6. package/app/components/Viewer/Generic/Model/SurfacesOptions.vue +3 -3
  7. package/app/components/Viewer/ObjectTree/Views/ModelComponents.vue +6 -2
  8. package/app/components/Viewer/Options/ColorMapList.vue +3 -2
  9. package/app/stores/app.js +2 -2
  10. package/app/stores/back.js +1 -1
  11. package/app/stores/cloud.js +1 -1
  12. package/app/stores/menu.js +1 -1
  13. package/app/stores/viewer.js +1 -1
  14. package/app/utils/extension.js +2 -2
  15. package/app/utils/local/microservices.js +61 -32
  16. package/nuxt.config.js +2 -0
  17. package/package.json +1 -1
  18. package/server/api/{app → serverless}/run_cloud.js +3 -3
  19. package/server/utils/cloud.js +22 -52
  20. package/tests/unit/stores/cloud.nuxt.test.js +2 -2
  21. package/tests/unit/stores/infra.nuxt.test.js +1 -1
  22. /package/server/api/{app → local}/kill.post.js +0 -0
  23. /package/server/api/{app → local}/project_folder_path.post.js +0 -0
  24. /package/server/api/{app → local}/run_back.post.js +0 -0
  25. /package/server/api/{app → local}/run_viewer.post.js +0 -0
  26. /package/server/api/{extensions → microservice/extensions}/kill.post.js +0 -0
  27. /package/server/api/{extensions → microservice/extensions}/run.post.js +0 -0
  28. /package/server/api/{extensions → microservice/extensions}/upload.put.js +0 -0
@@ -23,28 +23,24 @@ const menuStore = useMenuStore();
23
23
  const dataStore = useDataStore();
24
24
 
25
25
  const componentName = ref("");
26
+ const componentItem = ref(undefined);
26
27
 
27
28
  watch(
28
29
  () => menuStore.current_meta_data,
29
30
  async (newMeta) => {
30
31
  componentName.value = "";
32
+ componentItem.value = undefined;
31
33
  if (!newMeta) {
32
34
  return;
33
35
  }
34
36
 
35
- if (newMeta.viewer_type === "model_component" && newMeta.modelId && newMeta.pickedComponentId) {
36
- try {
37
- const comp = await dataStore.getComponentByViewerId(
38
- newMeta.modelId,
39
- newMeta.pickedComponentId,
40
- );
41
- if (comp && comp.name) {
42
- componentName.value = comp.name;
43
- } else {
44
- componentName.value = newMeta.pickedComponentId;
45
- }
46
- } catch {
47
- componentName.value = newMeta.pickedComponentId;
37
+ const modelId = newMeta.modelId || newMeta.id;
38
+ if (newMeta.pickedComponentId && modelId) {
39
+ const components = await dataStore.getAllMeshComponents(modelId);
40
+ const comp = components.find((component) => component.id === newMeta.pickedComponentId);
41
+ if (comp) {
42
+ componentName.value = comp.title;
43
+ componentItem.value = comp;
48
44
  }
49
45
  }
50
46
  },
@@ -56,7 +52,7 @@ const cleanName = computed(() => {
56
52
  if (!meta) {
57
53
  return "Unnamed Object";
58
54
  }
59
- if (componentName.value) {
55
+ if (componentName.value && meta.viewer_type === "model_component") {
60
56
  return componentName.value;
61
57
  }
62
58
  return meta.name || "Unnamed Object";
@@ -70,6 +66,18 @@ const displayTitle = computed(() => {
70
66
  return middleTruncate(name, TRUNCATE_MAX_LENGTH, TRUNCATE_START_CHARS, TRUNCATE_END_CHARS);
71
67
  });
72
68
 
69
+ const displayComponentTitle = computed(() => {
70
+ if (!componentItem.value) {
71
+ return "";
72
+ }
73
+ return middleTruncate(
74
+ componentItem.value.title,
75
+ TRUNCATE_MAX_LENGTH,
76
+ TRUNCATE_START_CHARS,
77
+ TRUNCATE_END_CHARS,
78
+ );
79
+ });
80
+
73
81
  const copied = ref(false);
74
82
  async function copyId(targetId) {
75
83
  if (!targetId) {
@@ -86,16 +94,17 @@ async function copyId(targetId) {
86
94
  }
87
95
  }
88
96
 
89
- const formattedId = computed(() => {
90
- const metaId = metaData?.id;
91
- if (!metaId) {
97
+ function formatId(id) {
98
+ if (!id) {
92
99
  return "";
93
100
  }
94
- if (metaId.length <= MAX_SHORT_ID_LENGTH) {
95
- return metaId;
101
+ if (id.length <= MAX_SHORT_ID_LENGTH) {
102
+ return id;
96
103
  }
97
- return `${metaId.slice(0, ID_SLICE_START)}...${metaId.slice(metaId.length - ID_SLICE_END_OFFSET)}`;
98
- });
104
+ return `${id.slice(0, ID_SLICE_START)}...${id.slice(id.length - ID_SLICE_END_OFFSET)}`;
105
+ }
106
+
107
+ const formattedId = computed(() => formatId(metaData?.id));
99
108
  </script>
100
109
 
101
110
  <template>
@@ -138,6 +147,32 @@ const formattedId = computed(() => {
138
147
  class="ml-1"
139
148
  />
140
149
  </v-col>
150
+
151
+ <template v-if="componentItem">
152
+ <v-divider class="w-100 my-2" opacity="0.2" />
153
+ <v-col
154
+ class="text-subtitle-2 font-weight-bold text-truncate text-white w-100 pa-0"
155
+ cols="auto"
156
+ style="line-height: 1.3"
157
+ >
158
+ {{ displayComponentTitle }}
159
+ </v-col>
160
+ <v-col
161
+ class="text-caption font-weight-black text-uppercase text-secondary pa-0"
162
+ style="font-size: 0.68rem; line-height: 1.2"
163
+ >
164
+ {{ componentItem.category }}
165
+ </v-col>
166
+ <v-col
167
+ class="id-badge-container mt-1 d-inline-flex align-center px-2 py-0.5"
168
+ @click.stop="copyId(componentItem.id)"
169
+ >
170
+ <span class="id-text">
171
+ {{ formatId(componentItem.id) }}
172
+ </span>
173
+ <v-icon icon="mdi-content-copy" size="10" color="white" class="ml-1" />
174
+ </v-col>
175
+ </template>
141
176
  </v-row>
142
177
  </GlassCard>
143
178
  </v-sheet>
@@ -19,7 +19,7 @@ const hybridViewerStore = useHybridViewerStore();
19
19
  const blocksVisibility = computed({
20
20
  get: () => dataStyleStore.modelComponentTypeVisibility(modelId, "Block"),
21
21
  set: async (newValue) => {
22
- await dataStyleStore.setModelComponentTypeVisibility(modelId, "Block", newValue);
22
+ await dataStyleStore.setModelBlocksVisibility(modelId, targetBlockIds, newValue);
23
23
  hybridViewerStore.remoteRender();
24
24
  },
25
25
  });
@@ -36,7 +36,7 @@ const blockVisibility = computed({
36
36
  const blocksColor = computed({
37
37
  get: () => dataStyleStore.modelComponentTypeColor(modelId, "Block"),
38
38
  set: async (color) => {
39
- await dataStyleStore.setModelComponentTypeColor(modelId, "Block", color);
39
+ await dataStyleStore.setModelBlocksColor(modelId, targetBlockIds, color);
40
40
  hybridViewerStore.remoteRender();
41
41
  },
42
42
  });
@@ -52,7 +52,7 @@ const blockColor = computed({
52
52
  const blocksActiveColoring = computed({
53
53
  get: () => dataStyleStore.getModelComponentTypeActiveColoring(modelId, "Block"),
54
54
  set: async (coloringType) => {
55
- await dataStyleStore.setModelComponentTypeActiveColoring(modelId, "Block", coloringType);
55
+ await dataStyleStore.setModelBlocksActiveColoring(modelId, targetBlockIds, coloringType);
56
56
  hybridViewerStore.remoteRender();
57
57
  },
58
58
  });
@@ -13,14 +13,13 @@ const { modelId, cornerId, targetCornerIds } = defineProps({
13
13
  });
14
14
 
15
15
  const dataStyleStore = useDataStyleStore();
16
- console.log("CornersOptions setup!");
17
16
  const hybridViewerStore = useHybridViewerStore();
18
17
 
19
18
  // Visibility
20
19
  const cornersVisibility = computed({
21
20
  get: () => dataStyleStore.modelComponentTypeVisibility(modelId, "Corner"),
22
21
  set: async (newValue) => {
23
- await dataStyleStore.setModelComponentTypeVisibility(modelId, "Corner", newValue);
22
+ await dataStyleStore.setModelCornersVisibility(modelId, targetCornerIds, newValue);
24
23
  hybridViewerStore.remoteRender();
25
24
  },
26
25
  });
@@ -37,7 +36,7 @@ const cornerVisibility = computed({
37
36
  const cornersColor = computed({
38
37
  get: () => dataStyleStore.modelComponentTypeColor(modelId, "Corner"),
39
38
  set: async (color) => {
40
- await dataStyleStore.setModelComponentTypeColor(modelId, "Corner", color);
39
+ await dataStyleStore.setModelCornersColor(modelId, targetCornerIds, color);
41
40
  hybridViewerStore.remoteRender();
42
41
  },
43
42
  });
@@ -53,7 +52,7 @@ const cornerColor = computed({
53
52
  const cornersActiveColoring = computed({
54
53
  get: () => dataStyleStore.getModelComponentTypeActiveColoring(modelId, "Corner"),
55
54
  set: async (coloringType) => {
56
- await dataStyleStore.setModelComponentTypeActiveColoring(modelId, "Corner", coloringType);
55
+ await dataStyleStore.setModelCornersActiveColoring(modelId, targetCornerIds, coloringType);
57
56
  hybridViewerStore.remoteRender();
58
57
  },
59
58
  });
@@ -19,7 +19,7 @@ const hybridViewerStore = useHybridViewerStore();
19
19
  const linesVisibility = computed({
20
20
  get: () => dataStyleStore.modelComponentTypeVisibility(modelId, "Line"),
21
21
  set: async (newValue) => {
22
- await dataStyleStore.setModelComponentTypeVisibility(modelId, "Line", newValue);
22
+ await dataStyleStore.setModelLinesVisibility(modelId, targetLineIds, newValue);
23
23
  hybridViewerStore.remoteRender();
24
24
  },
25
25
  });
@@ -36,7 +36,7 @@ const lineVisibility = computed({
36
36
  const linesColor = computed({
37
37
  get: () => dataStyleStore.modelComponentTypeColor(modelId, "Line"),
38
38
  set: async (color) => {
39
- await dataStyleStore.setModelComponentTypeColor(modelId, "Line", color);
39
+ await dataStyleStore.setModelLinesColor(modelId, targetLineIds, color);
40
40
  hybridViewerStore.remoteRender();
41
41
  },
42
42
  });
@@ -52,7 +52,7 @@ const lineColor = computed({
52
52
  const linesActiveColoring = computed({
53
53
  get: () => dataStyleStore.getModelComponentTypeActiveColoring(modelId, "Line"),
54
54
  set: async (coloringType) => {
55
- await dataStyleStore.setModelComponentTypeActiveColoring(modelId, "Line", coloringType);
55
+ await dataStyleStore.setModelLinesActiveColoring(modelId, targetLineIds, coloringType);
56
56
  hybridViewerStore.remoteRender();
57
57
  },
58
58
  });
@@ -63,9 +63,13 @@ watch(
63
63
 
64
64
  const targetComponentIds = ref([]);
65
65
  watch(
66
- () => [modelId.value, componentType.value],
66
+ () => [modelId.value, componentType.value, itemProps.meta_data.targetComponentIds],
67
67
  async () => {
68
68
  targetComponentIds.value = [];
69
+ if (itemProps.meta_data.targetComponentIds) {
70
+ targetComponentIds.value = itemProps.meta_data.targetComponentIds;
71
+ return;
72
+ }
69
73
  if (componentType.value && modelId.value) {
70
74
  const currentModelId = modelId.value;
71
75
  const currentType = componentType.value;
@@ -19,7 +19,7 @@ const hybridViewerStore = useHybridViewerStore();
19
19
  const surfacesVisibility = computed({
20
20
  get: () => dataStyleStore.modelComponentTypeVisibility(modelId, "Surface"),
21
21
  set: async (newValue) => {
22
- await dataStyleStore.setModelComponentTypeVisibility(modelId, "Surface", newValue);
22
+ await dataStyleStore.setModelSurfacesVisibility(modelId, targetSurfaceIds, newValue);
23
23
  hybridViewerStore.remoteRender();
24
24
  },
25
25
  });
@@ -36,7 +36,7 @@ const surfaceVisibility = computed({
36
36
  const surfacesColor = computed({
37
37
  get: () => dataStyleStore.modelComponentTypeColor(modelId, "Surface"),
38
38
  set: async (color) => {
39
- await dataStyleStore.setModelComponentTypeColor(modelId, "Surface", color);
39
+ await dataStyleStore.setModelSurfacesColor(modelId, targetSurfaceIds, color);
40
40
  hybridViewerStore.remoteRender();
41
41
  },
42
42
  });
@@ -52,7 +52,7 @@ const surfaceColor = computed({
52
52
  const surfacesActiveColoring = computed({
53
53
  get: () => dataStyleStore.getModelComponentTypeActiveColoring(modelId, "Surface"),
54
54
  set: async (coloringType) => {
55
- await dataStyleStore.setModelComponentTypeActiveColoring(modelId, "Surface", coloringType);
55
+ await dataStyleStore.setModelSurfacesActiveColoring(modelId, targetSurfaceIds, coloringType);
56
56
  hybridViewerStore.remoteRender();
57
57
  },
58
58
  });
@@ -79,7 +79,7 @@ const itemsForTreeView = computed(() => {
79
79
  for (const category of filteredCategories.value) {
80
80
  result.push({
81
81
  ...category,
82
- children: sortAndFormatItems(componentsCache.value?.[category.id], sortType.value),
82
+ children: sortAndFormatItems(componentsCache.value[category.id], sortType.value),
83
83
  });
84
84
  }
85
85
  return result;
@@ -87,12 +87,16 @@ const itemsForTreeView = computed(() => {
87
87
 
88
88
  function showContextMenu(event, item) {
89
89
  const actualItem = item.raw || item;
90
+ const typeId = actualItem.category || actualItem.id;
91
+ const typeItem = itemsForTreeView.value.find((type) => type.id === typeId);
92
+ const targetComponentIds = typeItem ? typeItem.children.map((child) => child.id) : undefined;
90
93
  emit("show-menu", {
91
94
  event,
92
95
  itemId: actualItem.category ? actualItem.id : id,
93
96
  context_type: actualItem.category ? "model_component" : "model_component_type",
94
97
  modelId: id,
95
98
  modelComponentType: actualItem.category ? undefined : actualItem.id,
99
+ targetComponentIds,
96
100
  });
97
101
  }
98
102
 
@@ -108,7 +112,7 @@ function handleHoverEnter({ item, immediate = false }) {
108
112
  () =>
109
113
  actualItem.category
110
114
  ? [actualItem.viewer_id]
111
- : actualItem.children?.map((child) => child.viewer_id) || [],
115
+ : actualItem.children.map((child) => child.viewer_id),
112
116
  "model",
113
117
  immediate,
114
118
  );
@@ -78,7 +78,8 @@ watch(filteredPresets, drawAllCanvases);
78
78
  <template>
79
79
  <GlassCard width="320" variant="panel" padding="pa-3" rounded="lg" class="overflow-hidden">
80
80
  <v-overlay
81
- v-model="loading"
81
+ v-if="loading"
82
+ data-testid="colorMapListLoading"
82
83
  contained
83
84
  persistent
84
85
  class="align-center justify-center"
@@ -87,9 +88,9 @@ watch(filteredPresets, drawAllCanvases);
87
88
  >
88
89
  <v-progress-circular indeterminate color="primary" />
89
90
  </v-overlay>
90
-
91
91
  <v-text-field
92
92
  v-model="filterText"
93
+ data-testid="colorMapListFilter"
93
94
  placeholder="Search presets..."
94
95
  density="compact"
95
96
  hide-details
package/app/stores/app.js CHANGED
@@ -196,7 +196,7 @@ export const useAppStore = defineStore("app", () => {
196
196
  }
197
197
 
198
198
  function upload(file, callbacks = {}) {
199
- const route = "/api/extensions/upload";
199
+ const route = "/api/microservice/extensions/upload";
200
200
  const store = useAppStore();
201
201
  return upload_file(
202
202
  store,
@@ -244,7 +244,7 @@ export const useAppStore = defineStore("app", () => {
244
244
  function createProjectFolder() {
245
245
  const { PROJECT } = useRuntimeConfig().public;
246
246
  const schema = {
247
- $id: "/api/app/project_folder_path",
247
+ $id: "/api/local/project_folder_path",
248
248
  methods: ["POST"],
249
249
  type: "object",
250
250
  properties: { PROJECT: { type: "string" } },
@@ -81,7 +81,7 @@ export const useBackStore = defineStore("back", {
81
81
  const appStore = useAppStore();
82
82
  const { COMMAND_BACK, NUXT_ROOT_PATH } = useRuntimeConfig().public;
83
83
  const schema = {
84
- $id: "/api/app/run_back",
84
+ $id: "/api/local/run_back",
85
85
  methods: ["POST"],
86
86
  type: "object",
87
87
  properties: {
@@ -12,7 +12,7 @@ export const useCloudStore = defineStore("cloud", {
12
12
  this.status = Status.CONNECTING;
13
13
  console.log("[CLOUD] Launching cloud backend...");
14
14
  const schema = {
15
- $id: "/api/app/run_cloud",
15
+ $id: "/api/serverless/run_cloud",
16
16
  methods: ["POST"],
17
17
  type: "object",
18
18
  properties: {
@@ -83,7 +83,7 @@ const Section_menu = [ModelEdgesOptions, ModelPointsOptions, ModelStyleOptions];
83
83
 
84
84
  const StructuralModel_menu = [ModelEdgesOptions, ModelPointsOptions, ModelStyleOptions];
85
85
 
86
- const ModelComponent_menu = [ModelStyleOptions];
86
+ const ModelComponent_menu = [ModelEdgesOptions, ModelPointsOptions, ModelStyleOptions];
87
87
 
88
88
  const menusData = {
89
89
  mesh: {
@@ -133,7 +133,7 @@ export const useViewerStore = defineStore(
133
133
 
134
134
  const { COMMAND_VIEWER, NUXT_ROOT_PATH } = useRuntimeConfig().public;
135
135
  const schema = {
136
- $id: "/api/app/run_viewer",
136
+ $id: "/api/local/run_viewer",
137
137
  methods: ["POST"],
138
138
  type: "object",
139
139
  properties: { COMMAND_VIEWER: { type: "string" }, NUXT_ROOT_PATH: { type: "string" } },
@@ -81,7 +81,7 @@ function runExtensions() {
81
81
  const params = { projectFolderPath, projectName };
82
82
 
83
83
  const schema = {
84
- $id: "/api/extensions/run",
84
+ $id: "/api/microservice/extensions/run",
85
85
  methods: ["POST"],
86
86
  type: "object",
87
87
  properties: {
@@ -104,7 +104,7 @@ function killExtension(extensionId) {
104
104
  console.log(`[AppStore] Killing extension: ${extensionId}`, { params });
105
105
 
106
106
  const schema = {
107
- $id: "/api/extensions/kill",
107
+ $id: "/api/microservice/extensions/kill",
108
108
  methods: ["POST"],
109
109
  type: "object",
110
110
  properties: {
@@ -13,6 +13,7 @@ import { executablePath } from "./path.js";
13
13
 
14
14
  const MILLISECONDS_PER_SECOND = 1000;
15
15
  const DEFAULT_TIMEOUT_SECONDS = 45;
16
+ const MAX_PORT_RETRIES = 1;
16
17
 
17
18
  async function runScript(
18
19
  execPath,
@@ -51,7 +52,11 @@ async function runScript(
51
52
  }
52
53
  }
53
54
 
54
- async function runBack(execName, execPath, args = {}) {
55
+ function isPortInUseError(errorMessage) {
56
+ return /EADDRINUSE|address already in use|port already in use/iu.test(errorMessage);
57
+ }
58
+
59
+ async function runBack(execName, execPath, args = {}, attempts = 0) {
55
60
  const { projectFolderPath } = args;
56
61
  if (!projectFolderPath) {
57
62
  throw new Error("projectFolderPath is required");
@@ -60,44 +65,68 @@ async function runBack(execName, execPath, args = {}) {
60
65
  if (!uploadFolderPath) {
61
66
  uploadFolderPath = path.join(projectFolderPath, "uploads");
62
67
  }
63
- const port = await getAvailablePort();
64
- const backArgs = [
65
- "--port",
66
- String(port),
67
- "--project_folder_path",
68
- projectFolderPath,
69
- "--upload_folder_path",
70
- uploadFolderPath,
71
- "--allowed_origins",
72
- "http://localhost:*",
73
- "--timeout",
74
- "0",
75
- ];
76
- if (process.env.NODE_ENV === "development" || !process.env.NODE_ENV) {
77
- backArgs.push("--debug");
68
+ try {
69
+ const port = await getAvailablePort();
70
+ const backArgs = [
71
+ "--port",
72
+ String(port),
73
+ "--project_folder_path",
74
+ projectFolderPath,
75
+ "--upload_folder_path",
76
+ uploadFolderPath,
77
+ "--allowed_origins",
78
+ "http://localhost:*",
79
+ "--timeout",
80
+ "0",
81
+ ];
82
+ if (process.env.NODE_ENV === "development" || !process.env.NODE_ENV) {
83
+ backArgs.push("--debug");
84
+ }
85
+ console.log("runBack", execPath, execName, backArgs);
86
+ await runScript(execPath, execName, backArgs, "Serving Flask app");
87
+ return port;
88
+ } catch (error) {
89
+ if (!isPortInUseError(error)) {
90
+ console.log("runBack error", error);
91
+ throw error;
92
+ }
93
+ if (attempts <= MAX_PORT_RETRIES) {
94
+ console.log("Retrying runBack on conflicting port", port);
95
+ const port = await runBack(execName, execPath, args, attempts + 1);
96
+ return port;
97
+ }
78
98
  }
79
- console.log("runBack", execPath, execName, backArgs);
80
- await runScript(execPath, execName, backArgs, "Serving Flask app");
81
- return port;
82
99
  }
83
100
 
84
- async function runViewer(execName, execPath, args = {}) {
101
+ async function runViewer(execName, execPath, args = {}, attempts = 0) {
85
102
  const { projectFolderPath } = args;
86
103
  if (!projectFolderPath) {
87
104
  throw new Error("projectFolderPath is required");
88
105
  }
89
- const port = await getAvailablePort();
90
- const viewerArgs = [
91
- "--port",
92
- String(port),
93
- "--project_folder_path",
94
- projectFolderPath,
95
- "--timeout",
96
- "0",
97
- ];
98
- console.log("runViewer", execPath, execName, viewerArgs);
99
- await runScript(execPath, execName, viewerArgs, "Starting factory");
100
- return port;
106
+ try {
107
+ const port = await getAvailablePort();
108
+ const viewerArgs = [
109
+ "--port",
110
+ String(port),
111
+ "--project_folder_path",
112
+ projectFolderPath,
113
+ "--timeout",
114
+ "0",
115
+ ];
116
+ console.log("runViewer", execPath, execName, viewerArgs);
117
+ await runScript(execPath, execName, viewerArgs, "Starting factory");
118
+ return port;
119
+ } catch (error) {
120
+ if (!isPortInUseError(error)) {
121
+ console.log("runBack error", error);
122
+ throw error;
123
+ }
124
+ if (attempts <= MAX_PORT_RETRIES) {
125
+ console.log("Retrying runViewer on conflicting port", port);
126
+ const port = await runViewer(execName, execPath, args, attempts + 1);
127
+ return port;
128
+ }
129
+ }
101
130
  }
102
131
 
103
132
  function addMicroserviceMetadatas(projectFolderPath, serviceObj) {
package/nuxt.config.js CHANGED
@@ -22,6 +22,8 @@ export default defineNuxtConfig({
22
22
  scan: false,
23
23
  },
24
24
 
25
+ ssr: false,
26
+
25
27
  alias: {
26
28
  "@ogw_front": path.resolve(__dirname, "app"),
27
29
  "@ogw_internal": path.resolve(__dirname, "internal"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geode/opengeodeweb-front",
3
- "version": "10.29.0-rc.1",
3
+ "version": "10.29.0-rc.10",
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": {
@@ -6,7 +6,7 @@ import { GoogleAuth } from "google-auth-library";
6
6
  import { ServicesClient } from "@google-cloud/run";
7
7
 
8
8
  // Local imports
9
- import { artifactImages, requestConfig } from "@ogw_server/utils/cloud";
9
+ import { artifactImage, requestConfig } from "@ogw_server/utils/cloud";
10
10
 
11
11
  export default defineEventHandler(async (event) => {
12
12
  try {
@@ -23,8 +23,8 @@ export default defineEventHandler(async (event) => {
23
23
  scopes: ["https://www.googleapis.com/auth/cloud-platform"],
24
24
  });
25
25
  const authClient = await auth.getClient();
26
- const [routerImage, backImage, viewerImage] = await artifactImages(parent, authClient);
27
- const request = requestConfig(parent, routerImage, backImage, viewerImage, email, projectName);
26
+ const image = await artifactImage(parent, authClient);
27
+ const request = requestConfig(parent, image, email, projectName);
28
28
  console.log({ request });
29
29
  const runClient = new ServicesClient({ authClient });
30
30
  const [operation] = await runClient.createService(request);
@@ -5,11 +5,16 @@ import { google } from "googleapis";
5
5
 
6
6
  // Local imports
7
7
 
8
- async function artifactImage(registry, parent, repo) {
8
+ async function artifactImage(parent, authClient) {
9
+ const projectName = process.env.PROJECT;
10
+ const registry = google.artifactregistry({
11
+ version: "v1",
12
+ auth: authClient,
13
+ });
9
14
  const branch = process.env.NETLIFY_BRANCH;
10
15
  const [_, projectId] = parent.split("/");
11
16
  const repository = `${parent}/repositories/github/packages/`;
12
- const name = `${repository}${repo}/tags/${branch}`;
17
+ const name = `${repository}${projectName}/tags/${branch}`;
13
18
  console.log({ name });
14
19
  const response = await registry.projects.locations.repositories.packages.tags.get({
15
20
  name,
@@ -17,24 +22,11 @@ async function artifactImage(registry, parent, repo) {
17
22
  console.log({ response });
18
23
  const digest = response.data.version.split("/").pop();
19
24
  const artifactRegistry = `europe-west9-docker.pkg.dev/${projectId}/github`;
20
- const image = `${artifactRegistry}/${repo}@${digest}`;
21
- console.log("Found image for", repo, image);
25
+ const image = `${artifactRegistry}/${projectName}@${digest}`;
26
+ console.log("Found image for", projectName, image);
22
27
  return image;
23
28
  }
24
29
 
25
- function artifactImages(parent, authClient) {
26
- const projectName = process.env.PROJECT;
27
- const registry = google.artifactregistry({
28
- version: "v1",
29
- auth: authClient,
30
- });
31
- return Promise.all([
32
- artifactImage(registry, parent, "opengeodeweb-router"),
33
- artifactImage(registry, parent, `${projectName}-back`),
34
- artifactImage(registry, parent, `${projectName}-viewer`),
35
- ]);
36
- }
37
-
38
30
  function sanitizeLabelValue(label) {
39
31
  console.log("label", label);
40
32
  const maxLabelLength = 63;
@@ -44,47 +36,35 @@ function sanitizeLabelValue(label) {
44
36
  .slice(0, maxLabelLength);
45
37
  }
46
38
 
47
- // oxlint-disable-next-line max-lines-per-function
48
- function requestConfig(parent, routerImage, backImage, viewerImage, email, projectName) {
39
+ function requestConfig(parent, image, email, projectName) {
49
40
  const resources = {
50
41
  limits: {
51
- cpu: "1000m",
52
- memory: "1Gi",
42
+ cpu: "2000m",
43
+ memory: "3Gi",
53
44
  },
45
+ cpuIdle: false,
46
+ startup_cpu_boost: true,
54
47
  };
55
- const volumeMounts = {
56
- name: "project",
57
- mountPath: "/project",
48
+ const labels = {
49
+ user: sanitizeLabelValue(email),
50
+ project: sanitizeLabelValue(projectName),
58
51
  };
59
52
  return {
60
53
  parent,
61
54
  service: {
62
55
  ingress: "INGRESS_TRAFFIC_ALL",
63
56
  invokerIamDisabled: true,
64
- labels: {
65
- user: sanitizeLabelValue(email),
66
- project: sanitizeLabelValue(projectName),
67
- },
57
+ labels,
68
58
  scaling: {
69
59
  scalingMode: "MANUAL",
70
60
  manualInstanceCount: 1,
71
61
  },
72
62
  template: {
73
- labels: {
74
- user: sanitizeLabelValue(email),
75
- project: sanitizeLabelValue(projectId),
76
- },
77
- volumes: [
78
- {
79
- name: "project",
80
- emptyDir: {
81
- medium: "MEMORY",
82
- },
83
- },
84
- ],
63
+ labels,
64
+ timeout: { seconds: 3600 },
85
65
  containers: [
86
66
  {
87
- image: routerImage,
67
+ image,
88
68
  ports: [
89
69
  {
90
70
  containerPort: 80,
@@ -106,20 +86,10 @@ function requestConfig(parent, routerImage, backImage, viewerImage, email, proje
106
86
  failureThreshold: 30,
107
87
  },
108
88
  },
109
- {
110
- image: backImage,
111
- resources,
112
- volumeMounts: [volumeMounts],
113
- },
114
- {
115
- image: viewerImage,
116
- resources,
117
- volumeMounts: [volumeMounts],
118
- },
119
89
  ],
120
90
  },
121
91
  },
122
92
  };
123
93
  }
124
94
 
125
- export { artifactImages, requestConfig };
95
+ export { artifactImage, requestConfig };
@@ -38,7 +38,7 @@ describe("cloud store", () => {
38
38
  const cloudStore = useCloudStore();
39
39
  const feedbackStore = useFeedbackStore();
40
40
 
41
- registerEndpoint("/api/app/run_cloud", {
41
+ registerEndpoint("/api/serverless/run_cloud", {
42
42
  method: "POST",
43
43
  handler: postFakeCall,
44
44
  });
@@ -58,7 +58,7 @@ describe("cloud store", () => {
58
58
  const cloudStore = useCloudStore();
59
59
  const feedbackStore = useFeedbackStore();
60
60
 
61
- registerEndpoint("/api/app/run_cloud", {
61
+ registerEndpoint("/api/serverless/run_cloud", {
62
62
  method: "POST",
63
63
  handler: postFakeCall,
64
64
  });
@@ -291,7 +291,7 @@ describe("infra store", () => {
291
291
 
292
292
  infraStore.app_mode = appMode.CLOUD;
293
293
  const url = "test.com";
294
- registerEndpoint("/api/app/run_cloud", {
294
+ registerEndpoint("/api/serverless/run_cloud", {
295
295
  method: "POST",
296
296
  handler: () => ({ url }),
297
297
  });
File without changes
File without changes
File without changes