Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
df59e6d
save wip [skip ci]
JulienChampagnol Aug 5, 2026
5557c23
Merge branch 'next' of https://github.com/Geode-solutions/OpenGeodeWe…
JulienChampagnol Aug 5, 2026
971eecf
vite optimizeDeps in ogw-front
JulienChampagnol Aug 7, 2026
feaab68
refactor ws logic
JulienChampagnol Aug 7, 2026
e00a549
refactor ws logic
JulienChampagnol Aug 7, 2026
f15cb4e
store ws server client
JulienChampagnol Aug 7, 2026
391c17b
callRaw callable from cient and server side
JulienChampagnol Aug 7, 2026
01ce287
parse boolean
JulienChampagnol Aug 7, 2026
441ac11
wip [skip ci]
BotellaA Aug 7, 2026
9ece117
feat(Refactor): callRaw & callSchema, viewer events
JulienChampagnol Aug 10, 2026
b993041
Merge branch 'next' of https://github.com/Geode-solutions/OpenGeodeWe…
JulienChampagnol Aug 10, 2026
ac185ae
Apply prepare changes
JulienChampagnol Aug 10, 2026
8e8e7e8
Merge branch 'next' of https://github.com/Geode-solutions/OpenGeodeWe…
JulienChampagnol Aug 10, 2026
c72a8ee
Merge branch 'feat/viewer_app_controller' of https://github.com/Geode…
JulienChampagnol Aug 10, 2026
73ebc87
oxlint
JulienChampagnol Aug 10, 2026
260fc22
Apply prepare changes
JulienChampagnol Aug 10, 2026
4111dc6
Merge branch 'next' of https://github.com/Geode-solutions/OpenGeodeWe…
JulienChampagnol Aug 12, 2026
8179b33
import createServerWsRpcClient
JulienChampagnol Aug 12, 2026
2bdfc99
Merge branch 'next' of https://github.com/Geode-solutions/OpenGeodeWe…
JulienChampagnol Aug 17, 2026
488dcce
imports
JulienChampagnol Aug 17, 2026
fa17c41
ws_client onConnectionClose
JulienChampagnol Aug 17, 2026
cda0afb
test
JulienChampagnol Aug 18, 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
32 changes: 5 additions & 27 deletions app/stores/viewer.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
// Third party imports
import vtkWSLinkClient, { newInstance } from "@kitware/vtk.js/IO/Core/WSLinkClient";
import _ from "lodash";
// oxlint-disable-next-line no-unassigned-import
import "@kitware/vtk.js/Rendering/OpenGL/Profiles/Geometry";
import SmartConnect from "wslink/src/SmartConnect";
import { connectImageStream } from "@kitware/vtk.js/Rendering/Misc/RemoteView";

import { initWebSocketClient } from "@ogw_internal/utils/ws_client";
import opengeodeweb_front_schemas from "@geode/opengeodeweb-front/opengeodeweb_front_schemas.json" with { type: "json" };
import opengeodeweb_viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json" with { type: "json" };

Expand Down Expand Up @@ -37,7 +35,6 @@ export const useViewerStore = defineStore(
const request_counter = ref(0);
const status = ref(Status.NOT_CONNECTED);
const version = ref("0.0.0");
const busy = ref(0);

const protocol = computed(() => getWebsocketApiProtocol());

Expand Down Expand Up @@ -77,29 +74,10 @@ export const useViewerStore = defineStore(
try {
console.log("VIEWER LOCK GRANTED !", lock);
status.value = Status.CONNECTING;
vtkWSLinkClient.setSmartConnectClass(SmartConnect);

if (_.isEmpty(client.value)) {
client.value = newInstance();
}

client.value.onBusyChange((count) => {
busy.value = count;
});
client.value.onConnectionError((httpReq) => {
const message = httpReq?.response?.error || `Connection error`;
console.error(message);
});
client.value.onConnectionClose((httpReq) => {
const message = httpReq?.response?.error || `Connection close`;
status.value = Status.NOT_CONNECTED;
console.error(message);
});

client.value.beginBusy();
await client.value.connect({
application: "Viewer",
sessionURL: base_url.value,
client.value = await initWebSocketClient(base_url.value, client.value, {
onConnectionClose: () => {
status.value = Status.NOT_CONNECTED;
},
});
connectImageStream(client.value.getConnection().getSession());
client.value.endBusy();
Expand Down
7 changes: 6 additions & 1 deletion internal/stores/data_style/mesh/points/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ export function useMeshPointsCommonStyle() {
});
}

function mutateMeshPointsVisibility(response) {
return mutateMeshPointsStyle(response.id, { visibility: response.visibility });
}

function meshPointsStyle(id) {
return dataStyleState.getStyle(id).points;
}
Expand All @@ -26,7 +30,8 @@ export function useMeshPointsCommonStyle() {
return {
meshPointsStyle,
meshPointsColoring,
mutateMeshPointsStyle,
mutateMeshPointsColoring,
mutateMeshPointsStyle,
mutateMeshPointsVisibility,
};
}
4 changes: 3 additions & 1 deletion internal/stores/data_style/mesh/points/visibility.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ export function useMeshPointsVisibilityStyle() {
params,
},
{
response_function: () => meshPointsCommonStyle.mutateMeshPointsStyle(id, { visibility }),
response_function(response) {
return meshPointsCommonStyle.mutateMeshPointsVisibility(response);
},
},
);
}
Expand Down
2 changes: 1 addition & 1 deletion internal/utils/api_fetch.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ export function api_fetch(
return fetchSchema(
{
schema,
baseURL: microservice.base_url,
params,
baseURL: microservice.base_url,
headers,
max_retry: schema.max_retry,
timeout,
Expand Down
90 changes: 37 additions & 53 deletions internal/utils/viewer_call.js
Original file line number Diff line number Diff line change
@@ -1,65 +1,49 @@
// Third party imports
import pTimeout from "p-timeout";

// Local imports
import { endRequestLog, startRequestLog } from "@ogw_front/utils/log";
import { callSchema } from "@ogw_shared/utils/call_schema";
import { useFeedbackStore } from "@ogw_front/stores/feedback";
import { validate_schema } from "@ogw_shared/utils/validate_schema";

const ERROR_400 = 400;

export function viewer_call(
microservice,
{ schema, params = {}, timeout },
{ request_error_function, response_function, response_error_function } = {},
) {
const feedbackStore = useFeedbackStore();

const { valid, error: schema_error } = validate_schema(schema, params);

if (!valid) {
if (process.env.NODE_ENV !== "production") {
console.log("Bad request", schema_error, schema, params);
}
feedbackStore.add_error(ERROR_400, schema.$id, "Bad request", schema_error);
throw new Error(`${schema.$id}: ${schema_error}`);
}

const { client } = microservice;

async function performCall() {
if (!client.getConnection) {
return;
}
microservice.start_request();
const requestStart = startRequestLog(microservice, schema);
try {
const value = await client.getConnection().getSession().call(schema.$id, [params]);
endRequestLog(microservice, schema, requestStart);
if (response_function) {
await response_function(value);
}
return value;
} catch (error) {
feedbackStore.add_error(error.code, schema.$id, error.message, error.message);
if (request_error_function) {
request_error_function(error);
}
if (response_error_function) {
response_error_function(error);
}
throw error;
} finally {
microservice.stop_request();
}
}

if (timeout > 0) {
return pTimeout(performCall(), {
milliseconds: timeout,
message: `${schema.$id}: Timed out after ${timeout}ms`,
});
}

return performCall();
const requestStartingTime = startRequestLog(microservice, schema);
return callSchema(
{
schema,
params,
client,
timeout,
},
{
request_error_function(error) {
microservice.stop_request();
feedbackStore.add_error(error.code, schema.$id, error.message, error.message);
if (request_error_function) {
request_error_function(error);
}
},
response_function(data) {
endRequestLog(microservice, schema, requestStartingTime);
microservice.stop_request();
if (response_function) {
response_function(data);
}
},
response_error_function(response) {
microservice.stop_request();
feedbackStore.add_error(error.code, schema.$id, error.message, error.message);
if (response_error_function) {
response_error_function(response);
}
},
validation_error_function({ code, name, error }) {
microservice.stop_request();
feedbackStore.add_error(code, schema.$id, name, error);
},
},
);
}
29 changes: 29 additions & 0 deletions internal/utils/ws_client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Third party imports
import vtkWSLinkClient, { newInstance } from "@kitware/vtk.js/IO/Core/WSLinkClient";
import SmartConnect from "wslink/src/SmartConnect";
import _ from "lodash";

async function initWebSocketClient(baseUrl, initialClient = {}, { onConnectionClose } = {}) {
vtkWSLinkClient.setSmartConnectClass(SmartConnect);
const client = _.isEmpty(initialClient) ? newInstance() : initialClient;

client.onConnectionError((httpReq) => {
const message = httpReq?.response?.error || `Connection error`;
console.error(message);
});
client.onConnectionClose((httpReq) => {
const message = httpReq?.response?.error || `Connection close`;
onConnectionClose();
console.error(message);
});

client.beginBusy();
await client.connect({
application: "Viewer",
sessionURL: baseUrl,
});

return client;
}

export { initWebSocketClient };
25 changes: 24 additions & 1 deletion nuxt.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,36 @@ export default defineNuxtConfig({
vite: {
optimizeDeps: {
include: [
"@kitware/vtk.js",
"@kitware/vtk.js/Common/Core/Math",
"@kitware/vtk.js/IO/Core/WSLinkClient",
"@kitware/vtk.js/IO/XML/XMLPolyDataReader",
"@kitware/vtk.js/Rendering/Core/Actor",
"@kitware/vtk.js/Rendering/Core/AnnotatedCubeActor",
"@kitware/vtk.js/Rendering/Core/ColorTransferFunction",
"@kitware/vtk.js/Rendering/Core/Mapper",
"@kitware/vtk.js/Rendering/Misc/GenericRenderWindow",
"@kitware/vtk.js/Rendering/Misc/RemoteView",
"@kitware/vtk.js/Rendering/OpenGL/Profiles/Geometry",
"@kitware/vtk.js/Widgets/Core/WidgetManager",
"@kitware/vtk.js/Widgets/Widgets3D/ImplicitPlaneWidget",
"@vue/devtools-core",
"@vue/devtools-kit",
"ajv",
"fast-deep-equal",
"broadcast-channel",
"dexie",
"globalthis",
"h3",
"js-file-download",
"lodash",
"lodash/merge",
"p-timeout",
"seedrandom",
"spark-md5",
"uuid",
"wslink",
"wslink/src/SmartConnect",
"xmlbuilder2",
],
},
},
Expand Down
25 changes: 25 additions & 0 deletions server/utils/server_config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { createServerWsRpcClient } from "./ws_client.js";

const storage = new Map();

function getAppBaseUrl() {
Expand Down Expand Up @@ -25,13 +27,36 @@ function setIsAppReady(isAppReady) {
return storage.set("IS_APP_READY", isAppReady);
}

async function getViewerWebSocketClient() {
const viewerClient = storage.get("VIEWER_CLIENT") ?? undefined;
if (viewerClient?.isOpen()) {
return viewerClient;
}
const viewerBaseUrl = await getViewerBaseUrl();
return setViewerWebSocketClient(viewerBaseUrl);
}

async function setViewerWebSocketClient(baseUrl) {
const client = createServerWsRpcClient(baseUrl);
client.onConnectionClose(() => {
if (viewerClient === client) {
viewerClient = undefined;
}
});
await client.ready;
storage.set("VIEWER_CLIENT", client);
return client;
}

export {
getAppBaseUrl,
getBackBaseUrl,
getIsAppReady,
getViewerBaseUrl,
getViewerWebSocketClient,
setAppBaseUrl,
setBackBaseUrl,
setIsAppReady,
setViewerBaseUrl,
setViewerWebSocketClient,
};
Loading
Loading