Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
e455c5f
save wip [skip ci]
JulienChampagnol Jul 21, 2026
0720d3d
Merge branch 'next' of https://github.com/Geode-solutions/OpenGeodeWe…
JulienChampagnol Jul 22, 2026
2312492
[skip ci}
JulienChampagnol Jul 22, 2026
0b68e29
Merge branch 'next' of https://github.com/Geode-solutions/OpenGeodeWe…
JulienChampagnol Jul 23, 2026
e00fb6b
save wip [skip ci]
JulienChampagnol Jul 27, 2026
3cd2381
save wip [skip ci]
JulienChampagnol Jul 27, 2026
a7eabc0
Merge branch 'next' of https://github.com/Geode-solutions/OpenGeodeWe…
JulienChampagnol Jul 28, 2026
b242cf0
save wip [skip ci]
JulienChampagnol Jul 28, 2026
4bb0ea4
Merge branch 'next' of https://github.com/Geode-solutions/OpenGeodeWe…
JulienChampagnol Jul 29, 2026
ce2cc96
pull [skip ci]
JulienChampagnol Jul 29, 2026
488b1d9
save wip [skip ci]
JulienChampagnol Jul 30, 2026
f59ef89
Merge branch 'next' of https://github.com/Geode-solutions/OpenGeodeWe…
JulienChampagnol Jul 30, 2026
aa8fdda
cleanup [skip ci]
JulienChampagnol Jul 30, 2026
c072de8
cleanup [skip ci]
JulienChampagnol Jul 30, 2026
1a953cb
cleanup [skip ci]
JulienChampagnol Jul 31, 2026
8a5b6d9
v0 working
JulienChampagnol Jul 31, 2026
625287c
Merge branch 'next' of https://github.com/Geode-solutions/OpenGeodeWe…
JulienChampagnol Jul 31, 2026
f027995
fix(Refactor): refactor functions in shared
JulienChampagnol Jul 31, 2026
d3f5329
Apply prepare changes
JulienChampagnol Jul 31, 2026
4105b30
pr comments + oxlint [skip ci]
JulienChampagnol Jul 31, 2026
8a47ae7
pr comments + oxlint [skip ci]
JulienChampagnol Jul 31, 2026
4ed2928
trigger tests
JulienChampagnol Jul 31, 2026
9b08756
Apply prepare changes
JulienChampagnol Jul 31, 2026
578721c
oxlint & validate_schema is shared
JulienChampagnol Jul 31, 2026
ad16646
Merge branch 'feat/app_controller' of https://github.com/Geode-soluti…
JulienChampagnol Jul 31, 2026
147952e
oxlint
JulienChampagnol Jul 31, 2026
d9550da
Apply prepare changes
JulienChampagnol Jul 31, 2026
b8e2cf0
Merge branch 'next' of https://github.com/Geode-solutions/OpenGeodeWe…
JulienChampagnol Aug 3, 2026
c9a0fd9
oxlint
JulienChampagnol Aug 3, 2026
603f11d
harmonine functions
JulienChampagnol Aug 3, 2026
8c24121
cleanup before PR
JulienChampagnol Aug 3, 2026
7c01e63
Apply prepare changes
JulienChampagnol Aug 3, 2026
a2e3a4d
oxlint & fix imports
JulienChampagnol Aug 3, 2026
408a15e
Merge branch 'feat/app_controller' of https://github.com/Geode-soluti…
JulienChampagnol Aug 3, 2026
8aec83e
Merge branch 'next' of https://github.com/Geode-solutions/OpenGeodeWe…
JulienChampagnol Aug 3, 2026
4b26266
tests unit okay
JulienChampagnol Aug 3, 2026
4f588cb
Apply prepare changes
JulienChampagnol Aug 3, 2026
8c8032a
oxlint
JulienChampagnol Aug 3, 2026
82258f1
Merge branch 'feat/app_controller' of https://github.com/Geode-soluti…
JulienChampagnol Aug 3, 2026
9df748b
ogw_shared imports
JulienChampagnol Aug 3, 2026
6cfce5c
Merge branch 'next' of https://github.com/Geode-solutions/OpenGeodeWe…
JulienChampagnol Aug 4, 2026
e3c62ab
imports
JulienChampagnol Aug 4, 2026
fc3f4dd
save wip
JulienChampagnol Aug 4, 2026
5bc59b6
Merge branch 'next' of https://github.com/Geode-solutions/OpenGeodeWe…
JulienChampagnol Aug 4, 2026
aed4391
Apply prepare changes
JulienChampagnol Aug 4, 2026
92942d7
tests
JulienChampagnol Aug 4, 2026
1833a54
Merge branch 'feat/app_controller' of https://github.com/Geode-soluti…
JulienChampagnol Aug 4, 2026
6da1f68
Apply prepare changes
JulienChampagnol Aug 4, 2026
5f19f9d
refactor fetchSchema in import project
JulienChampagnol Aug 4, 2026
7eef825
Merge branch 'feat/app_controller' of https://github.com/Geode-soluti…
JulienChampagnol Aug 4, 2026
08dce19
test
JulienChampagnol Aug 4, 2026
7527bc3
trigger
BotellaA Aug 4, 2026
c46a512
test trigger
JulienChampagnol Aug 4, 2026
527b387
Merge branch 'feat/app_controller' of https://github.com/Geode-soluti…
JulienChampagnol Aug 4, 2026
3bd6a95
Merge branch 'next' into feat/app_controller
JulienChampagnol Aug 4, 2026
ba830e5
Apply prepare changes
JulienChampagnol Aug 4, 2026
7580dc2
passing tests
JulienChampagnol Aug 4, 2026
133adf5
Merge branch 'feat/app_controller' of https://github.com/Geode-soluti…
JulienChampagnol Aug 4, 2026
c2a95be
Apply prepare changes
JulienChampagnol Aug 4, 2026
e4cf3c3
Merge branch 'next' of https://github.com/Geode-solutions/OpenGeodeWe…
JulienChampagnol Aug 4, 2026
ce663e5
fix params project manager
JulienChampagnol Aug 4, 2026
83ae969
Merge branch 'feat/app_controller' of https://github.com/Geode-soluti…
JulienChampagnol Aug 4, 2026
d4f35dd
Apply prepare changes
JulienChampagnol Aug 4, 2026
b000deb
tests okay
JulienChampagnol Aug 4, 2026
273e274
Merge branch 'feat/app_controller' of https://github.com/Geode-soluti…
JulienChampagnol Aug 4, 2026
80a9fdb
fix app upload
BotellaA Aug 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 26 additions & 76 deletions app/components/ObjectSelector.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script setup>
import FetchingData from "@ogw_front/components/FetchingData.vue";
import { geode_objects } from "@ogw_front/assets/geode_objects";
import { resolveAllowedObjects } from "@ogw_shared/utils/response_handlers/load.js";
import schemas from "@geode/opengeodeweb-back/opengeodeweb_back_schemas.json";
import { useBackStore } from "@ogw_front/stores/back";

Expand All @@ -15,100 +16,49 @@ const { filenames } = defineProps({
const backStore = useBackStore();

const loading = ref(false);
const allowed_objects = ref({});
const toggle_loading = useToggle(loading);
const multiple_files_no_common = ref(false);
const allowedGeodeObjects = ref({});
const toggleLoading = useToggle(loading);
const multipleFilesNoCommon = ref(false);

function select_geode_object(object_map) {
const object_keys = Object.keys(object_map);
if (object_keys.length === 0) {
return undefined;
}
if (object_keys.length === 1 && object_map[object_keys[0]].is_loadable > 0) {
return object_keys[0];
}
const highest_load_score = Math.max(...object_keys.map((key) => object_map[key].is_loadable));
if (highest_load_score <= 0) {
return undefined;
}
const best_score_objects = object_keys.filter(
(key) => object_map[key].is_loadable === highest_load_score,
);
if (best_score_objects.length === 1) {
return best_score_objects[0];
}
const highest_priority = Math.max(
...best_score_objects.map((key) => object_map[key].object_priority ?? -Infinity),
);
const best_priority_objects = best_score_objects.filter(
(key) => object_map[key].object_priority === highest_priority,
);
if (highest_priority !== -Infinity && best_priority_objects.length === 1) {
return best_priority_objects[0];
}
return undefined;
}

function isCsvFile(filename) {
return filename.toLowerCase().endsWith(".csv") || filename.toLowerCase().endsWith(".csv.json");
}

async function get_allowed_objects() {
toggle_loading();
allowed_objects.value = {};
multiple_files_no_common.value = false;

const promise_array = filenames.map((filename) => {
async function fetchAllowedObjectsList() {
const promiseArray = filenames.map((filename) => {
const params = { filename };
return backStore.request({ schema, params });
});
const responses = await Promise.all(promise_array);
const allowed_objects_list = responses.map((response) => response.allowed_objects);
const all_keys = [...new Set(allowed_objects_list.flatMap((obj) => Object.keys(obj)))];
const common_keys = all_keys.filter((key) => allowed_objects_list.every((obj) => key in obj));
const responses = await Promise.all(promiseArray);
return responses.map((response) => response.allowed_objects);
}

if (filenames.length > 1 && all_keys.length > 0 && common_keys.length === 0) {
multiple_files_no_common.value = true;
}
async function getAllowedGeodeObjects() {
toggleLoading();
allowedGeodeObjects.value = {};
multipleFilesNoCommon.value = false;

const final_object = {};
for (const key of common_keys) {
const load_scores = allowed_objects_list.map((obj) => obj[key].is_loadable);
const priorities = allowed_objects_list
.map((obj) => obj[key].object_priority)
.filter((priority) => priority !== undefined);
final_object[key] = { is_loadable: Math.min(...load_scores) };
if (priorities.length > 0) {
final_object[key].object_priority = Math.max(...priorities);
}
}
const isCsv = filenames.some((filename) => isCsvFile(filename));
if (isCsv && !final_object["PointSet3D"]) {
final_object["PointSet3D"] = { is_loadable: 1, object_priority: 100 };
}
const allowedGeodeObjectsList = await fetchAllowedObjectsList();
const resolved = resolveAllowedObjects(filenames, allowedGeodeObjectsList);

allowed_objects.value = final_object;
const selected_object = select_geode_object(final_object);
if (selected_object) {
set_geode_object(selected_object);
allowedGeodeObjects.value = resolved.mergedAllowedObjects;
multipleFilesNoCommon.value = resolved.multipleFilesNoCommon;
if (resolved.selectedGeodeObject) {
setGeodeObject(resolved.selectedGeodeObject);
}
toggle_loading();
toggleLoading();
}

function set_geode_object(geode_object_type) {
function setGeodeObject(geode_object_type) {
if (geode_object_type) {
emit("update_values", { geode_object_type });
emit("increment_step");
}
}
// oxlint-disable-next-line no-top-level-await
await get_allowed_objects();
await getAllowedGeodeObjects();
</script>

<template>
<FetchingData v-if="loading" />
<v-row v-else-if="Object.keys(allowed_objects).length" class="justify-left">
<v-col v-for="(value, key) in allowed_objects" :key="key" cols="3" md="4">
<v-row v-else-if="Object.keys(allowedGeodeObjects).length" class="justify-left">
<v-col v-for="(value, key) in allowedGeodeObjects" :key="key" cols="3" md="4">
<v-tooltip
:text="
value['is_loadable']
Expand All @@ -124,7 +74,7 @@ await get_allowed_objects();
class="card ma-2"
hover
rounded
@click="set_geode_object(key)"
@click="setGeodeObject(key)"
:disabled="!value['is_loadable']"
:elevation="value['is_loadable'] ? 5 : 3"
>
Expand All @@ -139,7 +89,7 @@ await get_allowed_objects();
</v-tooltip>
</v-col>
</v-row>
<v-row v-else-if="multiple_files_no_common" class="pa-5">
<v-row v-else-if="multipleFilesNoCommon" class="pa-5">
<v-card class="card" variant="tonal" rounded>
<v-card-text>
These files cannot be loaded together because they don't share a common data type.
Expand Down
25 changes: 14 additions & 11 deletions app/composables/project_manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import back_schemas from "@geode/opengeodeweb-back/opengeodeweb_back_schemas.jso
import fileDownload from "js-file-download";
import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json";

import { fetchRaw } from "@ogw_shared/utils/fetch_raw";
import { importWorkflowFromSnapshot } from "@ogw_front/utils/import_workflow";

import { useAppStore } from "@ogw_front/stores/app";
import { useBackStore } from "@ogw_front/stores/back";
import { useDataStore } from "@ogw_front/stores/data";
Expand All @@ -21,12 +21,14 @@ async function exportProject() {
const snapshot = await appStore.exportStores();
const schema = back_schemas.opengeodeweb_back.export_project;
const defaultName = "project.vease";

const result = await $fetch(schema.$id, {
const params = { snapshot, filename: defaultName };
const result = await fetchRaw({
route: schema.$id,
params,
method: schema.methods[0],
baseURL: backStore.base_url,
method: schema.methods.find((method) => method !== "OPTIONS"),
body: { snapshot, filename: defaultName },
});

fileDownload(result, defaultName);
feedbackStore.add_success("Project exported successfully");
return { result };
Expand All @@ -46,26 +48,27 @@ async function importProject(file) {
if (client && client.getConnection && client.getConnection().getSession) {
await client.getConnection().getSession().call("opengeodeweb_viewer.release_database", [{}]);
}
const schema = viewer_schemas.opengeodeweb_viewer.viewer.reset_visualization;
const resetVisualizationSchema = viewer_schemas.opengeodeweb_viewer.viewer.reset_visualization;
const timeout = undefined;
await viewerStore.request({ schema, timeout });
await viewerStore.request({ schema: resetVisualizationSchema, timeout });

treeviewStore.clear();
dataStore.clear();
hybridViewerStore.clear();

const schemaImport = back_schemas.opengeodeweb_back.import_project;
const importProjectSchema = back_schemas.opengeodeweb_back.import_project;
const form = new FormData();
const originalFileName = file && file.name ? file.name : "project.vease";
if (!originalFileName.toLowerCase().endsWith(".vease")) {
throw new Error("Uploaded file must be a .vease");
}
form.append("file", file, originalFileName);

const result = await $fetch(schemaImport.$id, {
const result = await fetchRaw({
route: importProjectSchema.$id,
params: form,
method: importProjectSchema.methods[0],
baseURL: backStore.base_url,
method: "POST",
body: form,
});
const snapshot = result && result.snapshot ? result.snapshot : {};

Expand Down
15 changes: 8 additions & 7 deletions app/stores/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,13 +227,16 @@ export const useAppStore = defineStore("app", () => {
}

function upload(file, callbacks = {}) {
const route = "/api/local/extensions/upload";
const schema = {
$id: "/api/local/extensions/upload",
methods: ["OPTIONS", "PUT"],
};
const store = useAppStore();
const { PROJECT: projectName } = useRuntimeConfig().public;
const params = { projectName };
return upload_file(
store,
{ route, file, params },
{ schema, file, params },
{
...callbacks,
response_function: async (response) => {
Expand All @@ -247,16 +250,13 @@ export const useAppStore = defineStore("app", () => {
}

function request({ schema, params }, callbacks = {}) {
console.log("[APP] Request:", schema.$id);

const store = useAppStore();
return api_fetch(
store,
{ schema, params, headers: {} },
{ schema, params },
{
...callbacks,
response_function: async (response) => {
console.log("[APP] Request completed:", schema.$id);
if (callbacks.response_function) {
await callbacks.response_function(response);
}
Expand All @@ -274,7 +274,8 @@ export const useAppStore = defineStore("app", () => {
}
const is_busy = computed(() => request_counter.value > 0);

const projectFolderPath = ref(isCloudMode() ? "/project" : "");
const projectFolderPath = ref("");

function createProjectFolder() {
const { PROJECT } = useRuntimeConfig().public;
const schema = {
Expand Down
15 changes: 2 additions & 13 deletions app/stores/back.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,22 +104,12 @@ export const useBackStore = defineStore("back", {
return Promise.resolve();
},
request({ schema, params = {} }, callbacks = {}) {
console.log("[GEODE] Request:", schema.$id);
const start = Date.now();

return api_fetch(
this,
{ schema, params, headers: {} },
{
...callbacks,
response_function: async (response) => {
console.log(
"[GEODE] Request completed:",
schema.$id,
"in",
(Date.now() - start) / MILLISECONDS_IN_SECOND,
"s",
);
if (callbacks.response_function) {
await callbacks.response_function(response);
}
Expand All @@ -128,17 +118,16 @@ export const useBackStore = defineStore("back", {
);
},
upload(file, callbacks = {}) {
const route = back_schemas.opengeodeweb_back.upload_file.$id;
const schema = back_schemas.opengeodeweb_back.upload_file;
return upload_file(
this,
{
route,
schema,
file,
},
{
...callbacks,
response_function: async (response) => {
console.log("[GEODE] Request completed:", route);
if (callbacks.response_function) {
await callbacks.response_function(response);
}
Expand Down
3 changes: 3 additions & 0 deletions app/stores/cloud.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ export const useCloudStore = defineStore("cloud", {
domain_name: response.url,
});
setAppBaseUrl(appStore.base_url);
appStore.$patch({
projectFolderPath: "/project",
});
},
response_error_function: () => {
feedbackStore.$patch({ server_error: true });
Expand Down
5 changes: 0 additions & 5 deletions app/stores/infra.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,6 @@ export const useInfraStore = defineStore("infra", {
},
async create_connection() {
console.log("[INFRA] Starting create_connection");
console.log(
"[INFRA] Connecting microservices:",
this.microservices.map((store) => store.$id),
);

await Promise.all(
this.microservices.map(async (store) => {
console.log("[INFRA] Connecting to microservice:", store.$id);
Expand Down
12 changes: 0 additions & 12 deletions app/stores/viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,25 +156,13 @@ export const useViewerStore = defineStore(
}

function request({ schema, params = {}, timeout = request_timeout }, callbacks = {}) {
console.log("[VIEWER] Request:", schema.$id);
const start = Date.now();

// Get current store instance to pass to viewer_call
const store = useViewerStore();

return viewer_call(
store,
{ schema, params, timeout },
{
...callbacks,
response_function: async (response) => {
console.log(
"[VIEWER] Request completed:",
schema.$id,
"in",
(Date.now() - start) / MS_PER_SECOND,
"s",
);
if (callbacks.response_function) {
await callbacks.response_function(response);
}
Expand Down
10 changes: 1 addition & 9 deletions app/utils/import_workflow.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,6 @@ async function importWorkflow(files) {
return results;
}

function buildImportItemFromPayloadApi(value, geode_object_type) {
return {
geode_object_type,
...value,
};
}

async function importItem(item) {
const dataStore = useDataStore();
const dataStyleStore = useDataStyleStore();
Expand Down Expand Up @@ -94,8 +87,7 @@ async function importFile(filename, geode_object_type) {
filename,
};
const response = await backStore.request({ schema, params });
const item = buildImportItemFromPayloadApi(response, geode_object_type);
return importItem(item);
return importItem(response);
}

async function importWorkflowFromSnapshot(items) {
Expand Down
18 changes: 18 additions & 0 deletions app/utils/log.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
function startRequestLog(microservice, schema) {
console.log(`[${microservice.$id}] Request:`, schema.$id);
const requestStartingTime = new Date(Date.now());
return requestStartingTime;
}

function endRequestLog(microservice, schema, requestStartingTime) {
const requestEndingTime = new Date(Date.now());
console.log(
`[${microservice.$id}] Request completed:`,
schema.$id,
"in",
requestEndingTime.getSeconds() - requestStartingTime.getSeconds(),
"s",
);
}

export { startRequestLog, endRequestLog };
Loading
Loading