diff --git a/.docker/Viewer-v3.x/default.conf.template b/.docker/Viewer-v3.x/default.conf.template
index bbee32449..2266e8a5c 100644
--- a/.docker/Viewer-v3.x/default.conf.template
+++ b/.docker/Viewer-v3.x/default.conf.template
@@ -7,7 +7,7 @@ server {
location / {
root /usr/share/nginx/html;
index index.html index.htm;
- try_files $uri $uri/ /index.html;
+ try_files $uri $uri/ ${PUBLIC_URL}index.html;
add_header Cross-Origin-Resource-Policy same-origin;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
diff --git a/.docker/Viewer-v3.x/entrypoint.sh b/.docker/Viewer-v3.x/entrypoint.sh
index c0801a0dd..3e0d73019 100644
--- a/.docker/Viewer-v3.x/entrypoint.sh
+++ b/.docker/Viewer-v3.x/entrypoint.sh
@@ -2,12 +2,11 @@
if [ -n "$SSL_PORT" ]
then
- envsubst '${SSL_PORT}:${PORT}' < /usr/src/default.ssl.conf.template > /etc/nginx/conf.d/default.conf
+ envsubst '${SSL_PORT}:${PORT}' < /usr/src/default.ssl.conf.template | envsubst '${PUBLIC_URL}' > /etc/nginx/conf.d/default.conf
else
- envsubst '${PORT}' < /usr/src/default.conf.template > /etc/nginx/conf.d/default.conf
+ envsubst '${PORT}:${PUBLIC_URL}' < /usr/src/default.conf.template > /etc/nginx/conf.d/default.conf
fi
-
if [ -n "$APP_CONFIG" ]; then
echo "$APP_CONFIG" > /usr/share/nginx/html${PUBLIC_URL}app-config.js
echo "Using custom APP_CONFIG environment variable"
diff --git a/Dockerfile b/Dockerfile
index a3f8be304..1a313181a 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -62,9 +62,6 @@ RUN bun pm cache rm
RUN bun install
# Copy the local directory
COPY --link --exclude=yarn.lock --exclude=package.json --exclude=Dockerfile . .
-# Do a second install to finalize things after the copy
-RUN bun run show:config
-RUN bun install
# Build here
# After install it should hopefully be stable until the local directory changes
@@ -72,6 +69,7 @@ ENV QUICK_BUILD true
# ENV GENERATE_SOURCEMAP=false
ARG APP_CONFIG=config/default.js
ARG PUBLIC_URL=/
+ENV PUBLIC_URL=${PUBLIC_URL}
RUN bun run show:config
RUN bun run build
@@ -84,16 +82,19 @@ RUN ./.docker/compressDist.sh
# which runs Nginx using Alpine Linux
FROM nginxinc/nginx-unprivileged:1.27-alpine as final
#RUN apk add --no-cache bash
-ARG PORT=80
-ENV PORT=${PORT}
ARG PUBLIC_URL=/
ENV PUBLIC_URL=${PUBLIC_URL}
+ARG PORT=80
+ENV PORT=${PORT}
RUN rm /etc/nginx/conf.d/default.conf
USER nginx
COPY --chown=nginx:nginx .docker/Viewer-v3.x /usr/src
RUN chmod 777 /usr/src/entrypoint.sh
COPY --from=builder /usr/src/app/platform/app/dist /usr/share/nginx/html${PUBLIC_URL}
-COPY --from=builder /usr/src/app/platform/app/dist/index.html /usr/share/nginx/html
+# Copy paths that are renamed/redirected generally
+# Microscopy libraries depend on root level include, so must be copied
+COPY --from=builder /usr/src/app/platform/app/dist/dicom-microscopy-viewer /usr/share/nginx/html/dicom-microscopy-viewer
+
# In entrypoint.sh, app-config.js might be overwritten, so chmod it to be writeable.
# The nginx user cannot chmod it, so change to root.
USER root
diff --git a/bun.lock b/bun.lock
index 55f826d8d..74a3c3084 100644
--- a/bun.lock
+++ b/bun.lock
@@ -33,7 +33,7 @@
},
"addOns/externals/devDependencies": {
"name": "@externals/devDependencies",
- "version": "3.10.0-beta.138",
+ "version": "3.10.0-beta.139",
"dependencies": {
"@babel/runtime": "^7.20.13",
"@kitware/vtk.js": "32.12.0",
@@ -121,14 +121,14 @@
},
"addOns/externals/dicom-microscopy-viewer": {
"name": "@externals/dicom-microscopy-viewer",
- "version": "3.10.0-beta.138",
+ "version": "3.10.0-beta.139",
"dependencies": {
"dicom-microscopy-viewer": "^0.46.1",
},
},
"extensions/cornerstone": {
"name": "@ohif/extension-cornerstone",
- "version": "3.10.0-beta.138",
+ "version": "3.10.0-beta.139",
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/adapters": "^3.7.16",
@@ -153,8 +153,8 @@
"@cornerstonejs/codec-openjpeg": "^1.2.4",
"@cornerstonejs/codec-openjph": "^2.4.5",
"@cornerstonejs/dicom-image-loader": "^3.7.16",
- "@ohif/core": "3.10.0-beta.138",
- "@ohif/ui": "3.10.0-beta.138",
+ "@ohif/core": "3.10.0-beta.139",
+ "@ohif/ui": "3.10.0-beta.139",
"dcmjs": "*",
"dicom-parser": "^1.8.21",
"hammerjs": "^2.0.8",
@@ -166,7 +166,7 @@
},
"extensions/cornerstone-dicom-pmap": {
"name": "@ohif/extension-cornerstone-dicom-pmap",
- "version": "3.10.0-beta.138",
+ "version": "3.10.0-beta.139",
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/adapters": "^3.7.16",
@@ -175,10 +175,10 @@
"react-color": "^2.19.3",
},
"peerDependencies": {
- "@ohif/core": "3.10.0-beta.138",
- "@ohif/extension-cornerstone": "3.10.0-beta.138",
- "@ohif/extension-default": "3.10.0-beta.138",
- "@ohif/i18n": "3.10.0-beta.138",
+ "@ohif/core": "3.10.0-beta.139",
+ "@ohif/extension-cornerstone": "3.10.0-beta.139",
+ "@ohif/extension-default": "3.10.0-beta.139",
+ "@ohif/i18n": "3.10.0-beta.139",
"prop-types": "^15.6.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
@@ -189,16 +189,16 @@
},
"extensions/cornerstone-dicom-rt": {
"name": "@ohif/extension-cornerstone-dicom-rt",
- "version": "3.10.0-beta.138",
+ "version": "3.10.0-beta.139",
"dependencies": {
"@babel/runtime": "^7.20.13",
"react-color": "^2.19.3",
},
"peerDependencies": {
- "@ohif/core": "3.10.0-beta.138",
- "@ohif/extension-cornerstone": "3.10.0-beta.138",
- "@ohif/extension-default": "3.10.0-beta.138",
- "@ohif/i18n": "3.10.0-beta.138",
+ "@ohif/core": "3.10.0-beta.139",
+ "@ohif/extension-cornerstone": "3.10.0-beta.139",
+ "@ohif/extension-default": "3.10.0-beta.139",
+ "@ohif/i18n": "3.10.0-beta.139",
"prop-types": "^15.6.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
@@ -209,7 +209,7 @@
},
"extensions/cornerstone-dicom-seg": {
"name": "@ohif/extension-cornerstone-dicom-seg",
- "version": "3.10.0-beta.138",
+ "version": "3.10.0-beta.139",
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/adapters": "^3.7.16",
@@ -218,10 +218,10 @@
"react-color": "^2.19.3",
},
"peerDependencies": {
- "@ohif/core": "3.10.0-beta.138",
- "@ohif/extension-cornerstone": "3.10.0-beta.138",
- "@ohif/extension-default": "3.10.0-beta.138",
- "@ohif/i18n": "3.10.0-beta.138",
+ "@ohif/core": "3.10.0-beta.139",
+ "@ohif/extension-cornerstone": "3.10.0-beta.139",
+ "@ohif/extension-default": "3.10.0-beta.139",
+ "@ohif/i18n": "3.10.0-beta.139",
"prop-types": "^15.6.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
@@ -232,7 +232,7 @@
},
"extensions/cornerstone-dicom-sr": {
"name": "@ohif/extension-cornerstone-dicom-sr",
- "version": "3.10.0-beta.138",
+ "version": "3.10.0-beta.139",
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/adapters": "^3.7.16",
@@ -241,10 +241,10 @@
"classnames": "^2.3.2",
},
"peerDependencies": {
- "@ohif/core": "3.10.0-beta.138",
- "@ohif/extension-cornerstone": "3.10.0-beta.138",
- "@ohif/extension-measurement-tracking": "3.10.0-beta.138",
- "@ohif/ui": "3.10.0-beta.138",
+ "@ohif/core": "3.10.0-beta.139",
+ "@ohif/extension-cornerstone": "3.10.0-beta.139",
+ "@ohif/extension-measurement-tracking": "3.10.0-beta.139",
+ "@ohif/ui": "3.10.0-beta.139",
"dcmjs": "*",
"dicom-parser": "^1.8.9",
"hammerjs": "^2.0.8",
@@ -254,7 +254,7 @@
},
"extensions/cornerstone-dynamic-volume": {
"name": "@ohif/extension-cornerstone-dynamic-volume",
- "version": "3.10.0-beta.138",
+ "version": "3.10.0-beta.139",
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/core": "^3.7.16",
@@ -262,11 +262,11 @@
"classnames": "^2.3.2",
},
"peerDependencies": {
- "@ohif/core": "3.10.0-beta.138",
- "@ohif/extension-cornerstone": "3.10.0-beta.138",
- "@ohif/extension-default": "3.10.0-beta.138",
- "@ohif/i18n": "3.10.0-beta.138",
- "@ohif/ui": "3.10.0-beta.138",
+ "@ohif/core": "3.10.0-beta.139",
+ "@ohif/extension-cornerstone": "3.10.0-beta.139",
+ "@ohif/extension-default": "3.10.0-beta.139",
+ "@ohif/i18n": "3.10.0-beta.139",
+ "@ohif/ui": "3.10.0-beta.139",
"dcmjs": "*",
"dicom-parser": "^1.8.21",
"hammerjs": "^2.0.8",
@@ -276,7 +276,7 @@
},
"extensions/default": {
"name": "@ohif/extension-default",
- "version": "3.10.0-beta.138",
+ "version": "3.10.0-beta.139",
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/calculate-suv": "^1.1.0",
@@ -284,8 +284,8 @@
"lodash.uniqby": "^4.7.0",
},
"peerDependencies": {
- "@ohif/core": "3.10.0-beta.138",
- "@ohif/i18n": "3.10.0-beta.138",
+ "@ohif/core": "3.10.0-beta.139",
+ "@ohif/i18n": "3.10.0-beta.139",
"dcmjs": "*",
"dicomweb-client": "^0.10.4",
"prop-types": "^15.6.2",
@@ -299,7 +299,7 @@
},
"extensions/dicom-microscopy": {
"name": "@ohif/extension-dicom-microscopy",
- "version": "3.10.0-beta.138",
+ "version": "3.10.0-beta.139",
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/codec-charls": "^1.2.3",
@@ -310,10 +310,10 @@
"mathjs": "^12.4.2",
},
"peerDependencies": {
- "@ohif/core": "3.10.0-beta.138",
- "@ohif/extension-default": "3.10.0-beta.138",
- "@ohif/i18n": "3.10.0-beta.138",
- "@ohif/ui": "3.10.0-beta.138",
+ "@ohif/core": "3.10.0-beta.139",
+ "@ohif/extension-default": "3.10.0-beta.139",
+ "@ohif/i18n": "3.10.0-beta.139",
+ "@ohif/ui": "3.10.0-beta.139",
"prop-types": "^15.6.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
@@ -324,14 +324,14 @@
},
"extensions/dicom-pdf": {
"name": "@ohif/extension-dicom-pdf",
- "version": "3.10.0-beta.138",
+ "version": "3.10.0-beta.139",
"dependencies": {
"@babel/runtime": "^7.20.13",
"classnames": "^2.3.2",
},
"peerDependencies": {
- "@ohif/core": "3.10.0-beta.138",
- "@ohif/ui": "3.10.0-beta.138",
+ "@ohif/core": "3.10.0-beta.139",
+ "@ohif/ui": "3.10.0-beta.139",
"dcmjs": "*",
"dicom-parser": "^1.8.9",
"hammerjs": "^2.0.8",
@@ -341,14 +341,14 @@
},
"extensions/dicom-video": {
"name": "@ohif/extension-dicom-video",
- "version": "3.10.0-beta.138",
+ "version": "3.10.0-beta.139",
"dependencies": {
"@babel/runtime": "^7.20.13",
"classnames": "^2.3.2",
},
"peerDependencies": {
- "@ohif/core": "3.10.0-beta.138",
- "@ohif/ui": "3.10.0-beta.138",
+ "@ohif/core": "3.10.0-beta.139",
+ "@ohif/ui": "3.10.0-beta.139",
"dcmjs": "*",
"dicom-parser": "^1.8.9",
"hammerjs": "^2.0.8",
@@ -358,20 +358,20 @@
},
"extensions/measurement-tracking": {
"name": "@ohif/extension-measurement-tracking",
- "version": "3.10.0-beta.138",
+ "version": "3.10.0-beta.139",
"dependencies": {
"@babel/runtime": "^7.20.13",
- "@ohif/ui": "3.10.0-beta.138",
+ "@ohif/ui": "3.10.0-beta.139",
"@xstate/react": "^3.2.2",
"xstate": "^4.10.0",
},
"peerDependencies": {
"@cornerstonejs/core": "^3.7.16",
"@cornerstonejs/tools": "^3.7.16",
- "@ohif/core": "3.10.0-beta.138",
- "@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.138",
- "@ohif/extension-default": "3.10.0-beta.138",
- "@ohif/ui": "3.10.0-beta.138",
+ "@ohif/core": "3.10.0-beta.139",
+ "@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.139",
+ "@ohif/extension-default": "3.10.0-beta.139",
+ "@ohif/ui": "3.10.0-beta.139",
"classnames": "^2.3.2",
"dcmjs": "*",
"lodash.debounce": "^4.0.8",
@@ -384,14 +384,14 @@
},
"extensions/test-extension": {
"name": "@ohif/extension-test",
- "version": "3.10.0-beta.138",
+ "version": "3.10.0-beta.139",
"dependencies": {
"@babel/runtime": "^7.20.13",
"classnames": "^2.3.2",
},
"peerDependencies": {
- "@ohif/core": "3.10.0-beta.138",
- "@ohif/ui": "3.10.0-beta.138",
+ "@ohif/core": "3.10.0-beta.139",
+ "@ohif/ui": "3.10.0-beta.139",
"dcmjs": "0.38.0",
"dicom-parser": "^1.8.9",
"hammerjs": "^2.0.8",
@@ -401,14 +401,14 @@
},
"extensions/tmtv": {
"name": "@ohif/extension-tmtv",
- "version": "3.10.0-beta.138",
+ "version": "3.10.0-beta.139",
"dependencies": {
"@babel/runtime": "^7.20.13",
"classnames": "^2.3.2",
},
"peerDependencies": {
- "@ohif/core": "3.10.0-beta.138",
- "@ohif/ui": "3.10.0-beta.138",
+ "@ohif/core": "3.10.0-beta.139",
+ "@ohif/ui": "3.10.0-beta.139",
"dcmjs": "*",
"dicom-parser": "^1.8.9",
"hammerjs": "^2.0.8",
@@ -418,7 +418,7 @@
},
"modes/basic-dev-mode": {
"name": "@ohif/mode-basic-dev-mode",
- "version": "3.10.0-beta.138",
+ "version": "3.10.0-beta.139",
"dependencies": {
"@babel/runtime": "^7.20.13",
"i18next": "^17.0.3",
@@ -428,17 +428,17 @@
"webpack-merge": "^5.7.3",
},
"peerDependencies": {
- "@ohif/core": "3.10.0-beta.138",
- "@ohif/extension-cornerstone": "3.10.0-beta.138",
- "@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.138",
- "@ohif/extension-default": "3.10.0-beta.138",
- "@ohif/extension-dicom-pdf": "3.10.0-beta.138",
- "@ohif/extension-dicom-video": "3.10.0-beta.138",
+ "@ohif/core": "3.10.0-beta.139",
+ "@ohif/extension-cornerstone": "3.10.0-beta.139",
+ "@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.139",
+ "@ohif/extension-default": "3.10.0-beta.139",
+ "@ohif/extension-dicom-pdf": "3.10.0-beta.139",
+ "@ohif/extension-dicom-video": "3.10.0-beta.139",
},
},
"modes/basic-test-mode": {
"name": "@ohif/mode-test",
- "version": "3.10.0-beta.138",
+ "version": "3.10.0-beta.139",
"dependencies": {
"@babel/runtime": "^7.20.13",
"i18next": "^17.0.3",
@@ -448,19 +448,19 @@
"webpack-merge": "^5.7.3",
},
"peerDependencies": {
- "@ohif/core": "3.10.0-beta.138",
- "@ohif/extension-cornerstone": "3.10.0-beta.138",
- "@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.138",
- "@ohif/extension-default": "3.10.0-beta.138",
- "@ohif/extension-dicom-pdf": "3.10.0-beta.138",
- "@ohif/extension-dicom-video": "3.10.0-beta.138",
- "@ohif/extension-measurement-tracking": "3.10.0-beta.138",
- "@ohif/extension-test": "3.10.0-beta.138",
+ "@ohif/core": "3.10.0-beta.139",
+ "@ohif/extension-cornerstone": "3.10.0-beta.139",
+ "@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.139",
+ "@ohif/extension-default": "3.10.0-beta.139",
+ "@ohif/extension-dicom-pdf": "3.10.0-beta.139",
+ "@ohif/extension-dicom-video": "3.10.0-beta.139",
+ "@ohif/extension-measurement-tracking": "3.10.0-beta.139",
+ "@ohif/extension-test": "3.10.0-beta.139",
},
},
"modes/longitudinal": {
"name": "@ohif/mode-longitudinal",
- "version": "3.10.0-beta.138",
+ "version": "3.10.0-beta.139",
"dependencies": {
"@babel/runtime": "^7.20.13",
"i18next": "^17.0.3",
@@ -470,32 +470,32 @@
"webpack-merge": "^5.7.3",
},
"peerDependencies": {
- "@ohif/core": "3.10.0-beta.138",
- "@ohif/extension-cornerstone": "3.10.0-beta.138",
- "@ohif/extension-cornerstone-dicom-rt": "3.10.0-beta.138",
- "@ohif/extension-cornerstone-dicom-seg": "3.10.0-beta.138",
- "@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.138",
- "@ohif/extension-default": "3.10.0-beta.138",
- "@ohif/extension-dicom-pdf": "3.10.0-beta.138",
- "@ohif/extension-dicom-video": "3.10.0-beta.138",
- "@ohif/extension-measurement-tracking": "3.10.0-beta.138",
+ "@ohif/core": "3.10.0-beta.139",
+ "@ohif/extension-cornerstone": "3.10.0-beta.139",
+ "@ohif/extension-cornerstone-dicom-rt": "3.10.0-beta.139",
+ "@ohif/extension-cornerstone-dicom-seg": "3.10.0-beta.139",
+ "@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.139",
+ "@ohif/extension-default": "3.10.0-beta.139",
+ "@ohif/extension-dicom-pdf": "3.10.0-beta.139",
+ "@ohif/extension-dicom-video": "3.10.0-beta.139",
+ "@ohif/extension-measurement-tracking": "3.10.0-beta.139",
},
},
"modes/microscopy": {
"name": "@ohif/mode-microscopy",
- "version": "3.10.0-beta.138",
+ "version": "3.10.0-beta.139",
"dependencies": {
"@babel/runtime": "^7.20.13",
"i18next": "^17.0.3",
},
"peerDependencies": {
- "@ohif/core": "3.10.0-beta.138",
- "@ohif/extension-dicom-microscopy": "3.10.0-beta.138",
+ "@ohif/core": "3.10.0-beta.139",
+ "@ohif/extension-dicom-microscopy": "3.10.0-beta.139",
},
},
"modes/preclinical-4d": {
"name": "@ohif/mode-preclinical-4d",
- "version": "3.10.0-beta.138",
+ "version": "3.10.0-beta.139",
"dependencies": {
"@babel/runtime": "^7.20.13",
},
@@ -504,17 +504,17 @@
"webpack-merge": "^5.7.3",
},
"peerDependencies": {
- "@ohif/core": "3.10.0-beta.138",
- "@ohif/extension-cornerstone": "3.10.0-beta.138",
- "@ohif/extension-cornerstone-dicom-seg": "3.10.0-beta.138",
- "@ohif/extension-cornerstone-dynamic-volume": "3.10.0-beta.138",
- "@ohif/extension-default": "3.10.0-beta.138",
- "@ohif/extension-tmtv": "3.10.0-beta.138",
+ "@ohif/core": "3.10.0-beta.139",
+ "@ohif/extension-cornerstone": "3.10.0-beta.139",
+ "@ohif/extension-cornerstone-dicom-seg": "3.10.0-beta.139",
+ "@ohif/extension-cornerstone-dynamic-volume": "3.10.0-beta.139",
+ "@ohif/extension-default": "3.10.0-beta.139",
+ "@ohif/extension-tmtv": "3.10.0-beta.139",
},
},
"modes/segmentation": {
"name": "@ohif/mode-segmentation",
- "version": "3.10.0-beta.138",
+ "version": "3.10.0-beta.139",
"dependencies": {
"@babel/runtime": "^7.20.13",
"i18next": "^17.0.3",
@@ -546,19 +546,19 @@
"webpack-merge": "^5.7.3",
},
"peerDependencies": {
- "@ohif/core": "3.10.0-beta.138",
- "@ohif/extension-cornerstone": "3.10.0-beta.138",
- "@ohif/extension-cornerstone-dicom-rt": "3.10.0-beta.138",
- "@ohif/extension-cornerstone-dicom-seg": "3.10.0-beta.138",
- "@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.138",
- "@ohif/extension-default": "3.10.0-beta.138",
- "@ohif/extension-dicom-pdf": "3.10.0-beta.138",
- "@ohif/extension-dicom-video": "3.10.0-beta.138",
+ "@ohif/core": "3.10.0-beta.139",
+ "@ohif/extension-cornerstone": "3.10.0-beta.139",
+ "@ohif/extension-cornerstone-dicom-rt": "3.10.0-beta.139",
+ "@ohif/extension-cornerstone-dicom-seg": "3.10.0-beta.139",
+ "@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.139",
+ "@ohif/extension-default": "3.10.0-beta.139",
+ "@ohif/extension-dicom-pdf": "3.10.0-beta.139",
+ "@ohif/extension-dicom-video": "3.10.0-beta.139",
},
},
"modes/tmtv": {
"name": "@ohif/mode-tmtv",
- "version": "3.10.0-beta.138",
+ "version": "3.10.0-beta.139",
"dependencies": {
"@babel/runtime": "^7.20.13",
"i18next": "^17.0.3",
@@ -568,18 +568,18 @@
"webpack-merge": "^5.7.3",
},
"peerDependencies": {
- "@ohif/core": "3.10.0-beta.138",
- "@ohif/extension-cornerstone": "3.10.0-beta.138",
- "@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.138",
- "@ohif/extension-default": "3.10.0-beta.138",
- "@ohif/extension-dicom-pdf": "3.10.0-beta.138",
- "@ohif/extension-dicom-video": "3.10.0-beta.138",
- "@ohif/extension-measurement-tracking": "3.10.0-beta.138",
+ "@ohif/core": "3.10.0-beta.139",
+ "@ohif/extension-cornerstone": "3.10.0-beta.139",
+ "@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.139",
+ "@ohif/extension-default": "3.10.0-beta.139",
+ "@ohif/extension-dicom-pdf": "3.10.0-beta.139",
+ "@ohif/extension-dicom-video": "3.10.0-beta.139",
+ "@ohif/extension-measurement-tracking": "3.10.0-beta.139",
},
},
"platform/app": {
"name": "@ohif/app",
- "version": "3.10.0-beta.138",
+ "version": "3.10.0-beta.139",
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/codec-charls": "^1.2.3",
@@ -588,23 +588,23 @@
"@cornerstonejs/codec-openjph": "^2.4.5",
"@cornerstonejs/dicom-image-loader": "^3.7.16",
"@emotion/serialize": "^1.1.3",
- "@ohif/core": "3.10.0-beta.138",
- "@ohif/extension-cornerstone": "3.10.0-beta.138",
- "@ohif/extension-cornerstone-dicom-rt": "3.10.0-beta.138",
- "@ohif/extension-cornerstone-dicom-seg": "3.10.0-beta.138",
- "@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.138",
- "@ohif/extension-default": "3.10.0-beta.138",
- "@ohif/extension-dicom-microscopy": "3.10.0-beta.138",
- "@ohif/extension-dicom-pdf": "3.10.0-beta.138",
- "@ohif/extension-dicom-video": "3.10.0-beta.138",
- "@ohif/extension-test": "3.10.0-beta.138",
- "@ohif/i18n": "3.10.0-beta.138",
- "@ohif/mode-basic-dev-mode": "3.10.0-beta.138",
- "@ohif/mode-longitudinal": "3.10.0-beta.138",
- "@ohif/mode-microscopy": "3.10.0-beta.138",
- "@ohif/mode-test": "3.10.0-beta.138",
- "@ohif/ui": "3.10.0-beta.138",
- "@ohif/ui-next": "3.10.0-beta.138",
+ "@ohif/core": "3.10.0-beta.139",
+ "@ohif/extension-cornerstone": "3.10.0-beta.139",
+ "@ohif/extension-cornerstone-dicom-rt": "3.10.0-beta.139",
+ "@ohif/extension-cornerstone-dicom-seg": "3.10.0-beta.139",
+ "@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.139",
+ "@ohif/extension-default": "3.10.0-beta.139",
+ "@ohif/extension-dicom-microscopy": "3.10.0-beta.139",
+ "@ohif/extension-dicom-pdf": "3.10.0-beta.139",
+ "@ohif/extension-dicom-video": "3.10.0-beta.139",
+ "@ohif/extension-test": "3.10.0-beta.139",
+ "@ohif/i18n": "3.10.0-beta.139",
+ "@ohif/mode-basic-dev-mode": "3.10.0-beta.139",
+ "@ohif/mode-longitudinal": "3.10.0-beta.139",
+ "@ohif/mode-microscopy": "3.10.0-beta.139",
+ "@ohif/mode-test": "3.10.0-beta.139",
+ "@ohif/ui": "3.10.0-beta.139",
+ "@ohif/ui-next": "3.10.0-beta.139",
"@svgr/webpack": "^8.1.0",
"@types/react": "^18.3.3",
"classnames": "^2.3.2",
@@ -645,7 +645,7 @@
},
"platform/cli": {
"name": "@ohif/cli",
- "version": "3.10.0-beta.138",
+ "version": "3.10.0-beta.139",
"bin": {
"ohif-cli": "src/index.js",
},
@@ -669,7 +669,7 @@
},
"platform/core": {
"name": "@ohif/core",
- "version": "3.10.0-beta.138",
+ "version": "3.10.0-beta.139",
"dependencies": {
"@babel/runtime": "^7.20.13",
"dcmjs": "*",
@@ -695,14 +695,14 @@
"@cornerstonejs/codec-openjpeg": "^1.2.4",
"@cornerstonejs/codec-openjph": "^2.4.5",
"@cornerstonejs/dicom-image-loader": "^3.7.16",
- "@ohif/ui": "3.10.0-beta.138",
+ "@ohif/ui": "3.10.0-beta.139",
"cornerstone-math": "0.1.9",
"dicom-parser": "^1.8.21",
},
},
"platform/i18n": {
"name": "@ohif/i18n",
- "version": "3.10.0-beta.138",
+ "version": "3.10.0-beta.139",
"dependencies": {
"@babel/runtime": "^7.20.13",
"i18next-locize-backend": "^2.0.0",
@@ -727,7 +727,7 @@
},
"platform/ui": {
"name": "@ohif/ui",
- "version": "3.10.0-beta.138",
+ "version": "3.10.0-beta.139",
"dependencies": {
"@testing-library/react": "^13.1.0",
"browser-detect": "^0.2.28",
@@ -787,7 +787,7 @@
},
"platform/ui-next": {
"name": "@ohif/ui-next",
- "version": "3.10.0-beta.138",
+ "version": "3.10.0-beta.139",
"dependencies": {
"@radix-ui/react-accordion": "^1.2.0",
"@radix-ui/react-checkbox": "^1.1.1",
diff --git a/extensions/default/src/ViewerLayout/ViewerHeader.tsx b/extensions/default/src/ViewerLayout/ViewerHeader.tsx
index 65ecce4da..e2dce512d 100644
--- a/extensions/default/src/ViewerLayout/ViewerHeader.tsx
+++ b/extensions/default/src/ViewerLayout/ViewerHeader.tsx
@@ -7,7 +7,7 @@ import { useSystem } from '@ohif/core';
import { Toolbar } from '../Toolbar/Toolbar';
import HeaderPatientInfo from './HeaderPatientInfo';
import { PatientInfoVisibility } from './HeaderPatientInfo/HeaderPatientInfo';
-import { preserveQueryParameters, publicUrl } from '@ohif/app';
+import { preserveQueryParameters } from '@ohif/app';
function ViewerHeader({ appConfig }: withAppTypes<{ appConfig: AppTypes.Config }>) {
const { servicesManager, extensionManager, commandsManager } = useSystem();
@@ -30,7 +30,7 @@ function ViewerHeader({ appConfig }: withAppTypes<{ appConfig: AppTypes.Config }
preserveQueryParameters(searchQuery);
navigate({
- pathname: publicUrl,
+ pathname: '/',
search: decodeURIComponent(searchQuery.toString()),
});
};
diff --git a/platform/app/.webpack/webpack.pwa.js b/platform/app/.webpack/webpack.pwa.js
index 1d11c0dff..1a127a208 100644
--- a/platform/app/.webpack/webpack.pwa.js
+++ b/platform/app/.webpack/webpack.pwa.js
@@ -153,6 +153,12 @@ module.exports = (env, argv) => {
},
proxy: {
'/dicomweb': 'http://localhost:5000',
+ '/dicom-microscopy-viewer': {
+ target: 'http://localhost:3000',
+ pathRewrite: {
+ '^/dicom-microscopy-viewer': `/${PUBLIC_URL}/dicom-microscopy-viewer`,
+ },
+ },
},
static: [
{
diff --git a/platform/app/.webpack/writePluginImportsFile.js b/platform/app/.webpack/writePluginImportsFile.js
index 29accd913..ad02e63f0 100644
--- a/platform/app/.webpack/writePluginImportsFile.js
+++ b/platform/app/.webpack/writePluginImportsFile.js
@@ -1,7 +1,6 @@
const pluginConfig = require('../pluginConfig.json');
const fs = require('fs');
const os = require('os');
-const glob = require('glob');
const autogenerationDisclaimer = `
// THIS FILE IS AUTOGENERATED AS PART OF THE EXTENSION AND MODE PLUGIN PROCESS.
@@ -9,6 +8,12 @@ const autogenerationDisclaimer = `
const extractName = val => (typeof val === 'string' ? val : val.packageName);
+const publicURL = process.env.PUBLIC_URL || '/';
+
+function isAbsolutePath(path) {
+ return path.startsWith('http') || path.startsWith('/');
+}
+
function constructLines(input, categoryName) {
let pluginCount = 0;
@@ -72,7 +77,7 @@ function getRuntimeLoadModesExtensions(modules) {
if (module.importPath) {
dynamicLoad.push(
` if( module==="${packageName}") {`,
- ` const imported = await window.browserImportFunction('${module.importPath}');`,
+ ` const imported = await window.browserImportFunction('${isAbsolutePath(module.importPath) ? '' : publicURL}${module.importPath}');`,
' return ' +
(module.globalName
? `window["${module.globalName}"];`
diff --git a/platform/app/public/config/aws.js b/platform/app/public/config/aws.js
index be11fa859..5cd5f27d8 100644
--- a/platform/app/public/config/aws.js
+++ b/platform/app/public/config/aws.js
@@ -1,7 +1,7 @@
/** @type {AppTypes.Config} */
window.config = {
- routerBasename: '/',
+ routerBasename: null,
extensions: [],
modes: [],
showStudyList: true,
diff --git a/platform/app/public/config/customization.js b/platform/app/public/config/customization.js
index aee6a23ee..b1467b5cd 100644
--- a/platform/app/public/config/customization.js
+++ b/platform/app/public/config/customization.js
@@ -1,6 +1,6 @@
/** @type {AppTypes.Config} */
window.config = {
- routerBasename: '/',
+ routerBasename: null,
extensions: [],
modes: ['@ohif/mode-test'],
showStudyList: true,
diff --git a/platform/app/public/config/default.js b/platform/app/public/config/default.js
index 3da8ed66d..f612dc978 100644
--- a/platform/app/public/config/default.js
+++ b/platform/app/public/config/default.js
@@ -2,7 +2,7 @@
window.config = {
name: 'config/default.js',
- routerBasename: '/',
+ routerBasename: null,
// whiteLabeling: {},
extensions: [],
modes: [],
diff --git a/platform/app/public/config/default_16bit.js b/platform/app/public/config/default_16bit.js
index 6c08bd24b..1dfb9a829 100644
--- a/platform/app/public/config/default_16bit.js
+++ b/platform/app/public/config/default_16bit.js
@@ -1,6 +1,6 @@
/** @type {AppTypes.Config} */
window.config = {
- routerBasename: '/',
+ routerBasename: null,
// whiteLabeling: {},
extensions: [],
modes: [],
diff --git a/platform/app/public/config/demo.js b/platform/app/public/config/demo.js
index 791a5c3b7..4d780b698 100644
--- a/platform/app/public/config/demo.js
+++ b/platform/app/public/config/demo.js
@@ -1,6 +1,6 @@
/** @type {AppTypes.Config} */
window.config = {
- routerBasename: '/',
+ routerBasename: null,
modes: [],
extensions: [],
showStudyList: true,
diff --git a/platform/app/public/config/deprecated/docker_openresty-orthanc-keycloak.js b/platform/app/public/config/deprecated/docker_openresty-orthanc-keycloak.js
index d93a853d1..d9d5b62ce 100644
--- a/platform/app/public/config/deprecated/docker_openresty-orthanc-keycloak.js
+++ b/platform/app/public/config/deprecated/docker_openresty-orthanc-keycloak.js
@@ -1,6 +1,6 @@
/** @type {AppTypes.Config} */
window.config = {
- routerBasename: '/',
+ routerBasename: null,
showStudyList: true,
extensions: [],
modes: [],
diff --git a/platform/app/public/config/deprecated/docker_openresty-orthanc.js b/platform/app/public/config/deprecated/docker_openresty-orthanc.js
index 1acdff504..0694cbb42 100644
--- a/platform/app/public/config/deprecated/docker_openresty-orthanc.js
+++ b/platform/app/public/config/deprecated/docker_openresty-orthanc.js
@@ -1,6 +1,6 @@
/** @type {AppTypes.Config} */
window.config = {
- routerBasename: '/',
+ routerBasename: null,
showStudyList: true,
extensions: [],
modes: [],
diff --git a/platform/app/public/config/dicomweb-server.js b/platform/app/public/config/dicomweb-server.js
index 874e7507d..e08fae42d 100644
--- a/platform/app/public/config/dicomweb-server.js
+++ b/platform/app/public/config/dicomweb-server.js
@@ -1,6 +1,6 @@
/** @type {AppTypes.Config} */
window.config = {
- routerBasename: '/',
+ routerBasename: null,
extensions: [],
modes: [],
showStudyList: true,
diff --git a/platform/app/public/config/dicomweb_relative.js b/platform/app/public/config/dicomweb_relative.js
index a814ac9cb..115f5bd87 100644
--- a/platform/app/public/config/dicomweb_relative.js
+++ b/platform/app/public/config/dicomweb_relative.js
@@ -1,6 +1,6 @@
/** @type {AppTypes.Config} */
window.config = {
- routerBasename: '/',
+ routerBasename: null,
extensions: [],
modes: [],
showStudyList: true,
diff --git a/platform/app/public/config/docker-nginx-dcm4chee.js b/platform/app/public/config/docker-nginx-dcm4chee.js
index b44f35788..9f8ed6ecf 100644
--- a/platform/app/public/config/docker-nginx-dcm4chee.js
+++ b/platform/app/public/config/docker-nginx-dcm4chee.js
@@ -1,6 +1,6 @@
/** @type {AppTypes.Config} */
window.config = {
- routerBasename: '/',
+ routerBasename: null,
showStudyList: true,
extensions: [],
modes: [],
diff --git a/platform/app/public/config/docker-nginx-orthanc.js b/platform/app/public/config/docker-nginx-orthanc.js
index f4be9f944..90abe162e 100644
--- a/platform/app/public/config/docker-nginx-orthanc.js
+++ b/platform/app/public/config/docker-nginx-orthanc.js
@@ -1,6 +1,6 @@
/** @type {AppTypes.Config} */
window.config = {
- routerBasename: '/',
+ routerBasename: null,
showStudyList: true,
extensions: [],
modes: [],
diff --git a/platform/app/public/config/e2e.js b/platform/app/public/config/e2e.js
index 0173175f4..9ec0095c4 100644
--- a/platform/app/public/config/e2e.js
+++ b/platform/app/public/config/e2e.js
@@ -17,7 +17,7 @@ if (window.location.search === '?today') {
/** @type {AppTypes.Config} */
window.config = {
- routerBasename: '/',
+ routerBasename: null,
extensions: [],
modes: ['@ohif/mode-test'],
showStudyList: true,
diff --git a/platform/app/public/config/google.js b/platform/app/public/config/google.js
index 08799ff84..ea2e7637f 100644
--- a/platform/app/public/config/google.js
+++ b/platform/app/public/config/google.js
@@ -1,6 +1,6 @@
/** @type {AppTypes.Config} */
window.config = {
- routerBasename: '/',
+ routerBasename: null,
enableGoogleCloudAdapter: false,
// below flag is for performance reasons, but it might not work for all servers
showWarningMessageForCrossOrigin: true,
diff --git a/platform/app/public/config/idc.js b/platform/app/public/config/idc.js
index 3a4e55038..a99f5315d 100644
--- a/platform/app/public/config/idc.js
+++ b/platform/app/public/config/idc.js
@@ -1,6 +1,6 @@
/** @type {AppTypes.Config} */
window.config = {
- routerBasename: '/',
+ routerBasename: null,
enableGoogleCloudAdapter: true,
// below flag is for performance reasons, but it might not work for all servers
showWarningMessageForCrossOrigin: true,
diff --git a/platform/app/public/config/kheops.js b/platform/app/public/config/kheops.js
index d700b961c..1c32f20e2 100644
--- a/platform/app/public/config/kheops.js
+++ b/platform/app/public/config/kheops.js
@@ -2,7 +2,7 @@
window.config = {
name: 'config/kheops.js',
- routerBasename: '/',
+ routerBasename: null,
extensions: [],
modes: ['@ohif/mode-test'],
customizationService: {},
diff --git a/platform/app/public/config/local_dcm4chee.js b/platform/app/public/config/local_dcm4chee.js
index 1e223a4b9..054c12b73 100644
--- a/platform/app/public/config/local_dcm4chee.js
+++ b/platform/app/public/config/local_dcm4chee.js
@@ -1,6 +1,6 @@
/** @type {AppTypes.Config} */
window.config = {
- routerBasename: '/',
+ routerBasename: null,
showStudyList: true,
extensions: [],
modes: [],
diff --git a/platform/app/public/config/local_orthanc.js b/platform/app/public/config/local_orthanc.js
index 68d3b9b02..838ee8816 100644
--- a/platform/app/public/config/local_orthanc.js
+++ b/platform/app/public/config/local_orthanc.js
@@ -1,6 +1,6 @@
/** @type {AppTypes.Config} */
window.config = {
- routerBasename: '/',
+ routerBasename: null,
extensions: [],
modes: [],
showStudyList: true,
diff --git a/platform/app/public/config/local_static.js b/platform/app/public/config/local_static.js
index 696632ddb..32f3b3540 100644
--- a/platform/app/public/config/local_static.js
+++ b/platform/app/public/config/local_static.js
@@ -1,6 +1,6 @@
/** @type {AppTypes.Config} */
window.config = {
- routerBasename: '/',
+ routerBasename: null,
customizationService: ['@ohif/extension-default.customizationModule.helloPage'],
extensions: [],
modes: [],
diff --git a/platform/app/public/config/multiple.js b/platform/app/public/config/multiple.js
index 762c14c73..a20601be8 100644
--- a/platform/app/public/config/multiple.js
+++ b/platform/app/public/config/multiple.js
@@ -3,7 +3,7 @@ window.config = {
// Activate the new HP mode....
isNewHP: true,
- routerBasename: '/',
+ routerBasename: null,
customizationService: [
'@ohif/extension-default.customizationModule.datasources',
{
diff --git a/platform/app/public/config/netlify.js b/platform/app/public/config/netlify.js
index 6b4e3b9cf..a7eec5684 100644
--- a/platform/app/public/config/netlify.js
+++ b/platform/app/public/config/netlify.js
@@ -1,7 +1,7 @@
/** @type {AppTypes.Config} */
window.config = {
- routerBasename: '/',
+ routerBasename: null,
extensions: [],
modes: [],
showStudyList: true,
diff --git a/platform/app/public/config/public_dicomweb.js b/platform/app/public/config/public_dicomweb.js
index 9f1eb764d..76c803d6a 100644
--- a/platform/app/public/config/public_dicomweb.js
+++ b/platform/app/public/config/public_dicomweb.js
@@ -1,5 +1,5 @@
window.config = {
- routerBasename: '/',
+ routerBasename: null,
showStudyList: true,
// below flag is for performance reasons, but it might not work for all servers
showWarningMessageForCrossOrigin: true,
diff --git a/platform/app/src/App.tsx b/platform/app/src/App.tsx
index 851582860..2160ea539 100644
--- a/platform/app/src/App.tsx
+++ b/platform/app/src/App.tsx
@@ -53,7 +53,7 @@ function App({
* Hosted at: https://ohif.org/where-i-host-the/viewer/
* Value: `/where-i-host-the/viewer/`
* */
- routerBaseName: '/',
+ routerBasename: '/',
/**
*
*/
diff --git a/platform/app/src/index.js b/platform/app/src/index.js
index 4600014b8..14230134d 100644
--- a/platform/app/src/index.js
+++ b/platform/app/src/index.js
@@ -17,15 +17,16 @@ import React from 'react';
*/
import { modes as defaultModes, extensions as defaultExtensions } from './pluginImports';
import loadDynamicConfig from './loadDynamicConfig';
+import { publicUrl } from './utils/publicUrl';
export { history } from './utils/history';
export { preserveQueryParameters, preserveQueryStrings } from './utils/preserveQueryParameters';
-export { publicUrl } from './utils/publicUrl';
loadDynamicConfig(window.config).then(config_json => {
// Reset Dynamic config if defined
if (config_json !== null) {
window.config = config_json;
}
+ window.config.routerBasename ||= publicUrl;
/**
* Combine our appConfiguration with installed extensions and modes.
diff --git a/platform/app/src/routes/WorkList/WorkList.tsx b/platform/app/src/routes/WorkList/WorkList.tsx
index 685342ac9..5d5fbe772 100644
--- a/platform/app/src/routes/WorkList/WorkList.tsx
+++ b/platform/app/src/routes/WorkList/WorkList.tsx
@@ -11,7 +11,7 @@ import filtersMeta from './filtersMeta.js';
import { useAppConfig } from '@state';
import { useDebounce, useSearchParams } from '@hooks';
import { utils } from '@ohif/core';
-import publicUrl from '../../utils/publicUrl';
+import { routerBasename } from '../../utils/publicUrl';
import {
StudyListExpandedRow,
@@ -209,7 +209,7 @@ function WorkList({
skipEmptyString: true,
});
navigate({
- pathname: publicUrl,
+ pathname: '/',
search: search ? `?${search}` : undefined,
});
// eslint-disable-next-line react-hooks/exhaustive-deps
@@ -417,7 +417,7 @@ function WorkList({
{
// In case any event bubbles up for an invalid mode, prevent the navigation.
// For example, the event bubbles up when the icon embedded in the disabled button is clicked.
diff --git a/platform/app/src/routes/buildModeRoutes.tsx b/platform/app/src/routes/buildModeRoutes.tsx
index 2e60d42a4..6dca1896a 100644
--- a/platform/app/src/routes/buildModeRoutes.tsx
+++ b/platform/app/src/routes/buildModeRoutes.tsx
@@ -1,6 +1,5 @@
import React from 'react';
import ModeRoute from '@routes/Mode';
-import publicUrl from '../utils/publicUrl';
/*
Routes uniquely define an entry point to:
@@ -43,7 +42,7 @@ export default function buildModeRoutes({
modes.forEach(mode => {
// todo: for each route. add route to path.
dataSourceNames.forEach(dataSourceName => {
- const path = `${publicUrl}${mode.routeName}/${dataSourceName}`;
+ const path = `${mode.routeName}/${dataSourceName}`;
// TODO move up.
const children = () => (
@@ -66,7 +65,7 @@ export default function buildModeRoutes({
// Add active DataSource route.
// This is the DataSource route for the active data source defined in ExtensionManager.getActiveDataSource
- const path = `${publicUrl}${mode.routeName}`;
+ const path = `${mode.routeName}`;
// TODO move up.
const children = () => (
diff --git a/platform/app/src/routes/index.tsx b/platform/app/src/routes/index.tsx
index 1dd0c634f..138642a4d 100644
--- a/platform/app/src/routes/index.tsx
+++ b/platform/app/src/routes/index.tsx
@@ -11,7 +11,7 @@ import NotFound from './NotFound';
import buildModeRoutes from './buildModeRoutes';
import PrivateRoute from './PrivateRoute';
import PropTypes from 'prop-types';
-import publicUrl from '../utils/publicUrl';
+import { routerBase, routerBasename } from '../utils/publicUrl';
const NotFoundServer = ({
message = 'Unable to query for studies at this time. Check your data source configuration or network connection',
@@ -55,23 +55,23 @@ NotFoundStudy.propTypes = {
// TODO: Include "routes" debug route if dev build
const bakedInRoutes = [
{
- path: `${publicUrl}notfoundserver`,
+ path: `/notfoundserver`,
children: NotFoundServer,
},
{
- path: `${publicUrl}notfoundstudy`,
+ path: `/notfoundstudy`,
children: NotFoundStudy,
},
{
- path: `${publicUrl}debug`,
+ path: `/debug`,
children: Debug,
},
{
- path: `${publicUrl}local`,
+ path: `/local`,
children: Local.bind(null, { modePath: '' }), // navigate to the worklist
},
{
- path: `${publicUrl}localbasic`,
+ path: `/localbasic`,
children: Local.bind(null, { modePath: 'viewer/dicomlocal' }),
},
];
@@ -86,7 +86,6 @@ const createRoutes = ({
servicesManager,
commandsManager,
hotkeysManager,
- routerBasename,
showStudyList,
}: withAppTypes) => {
const routes =
@@ -101,8 +100,15 @@ const createRoutes = ({
const { customizationService } = servicesManager.services;
+ const path =
+ routerBasename.length > 1 && routerBasename.endsWith('/')
+ ? routerBasename.substring(0, routerBasename.length - 1)
+ : routerBasename;
+
+ console.log('Registering worklist route', routerBasename, path);
+
const WorkListRoute = {
- path: publicUrl,
+ path: '/',
children: DataSourceWrapper,
private: true,
props: { children: WorkList, servicesManager, extensionManager },
@@ -113,7 +119,6 @@ const createRoutes = ({
const allRoutes = [
...routes,
...(showStudyList ? [WorkListRoute] : []),
- ...(publicUrl !== '/' && showStudyList ? [{ ...WorkListRoute, path: publicUrl }] : []),
...(customRoutes?.routes || []),
...bakedInRoutes,
customRoutes?.notFoundRoute || notFoundRoute,
diff --git a/platform/app/src/utils/preserveQueryParameters.ts b/platform/app/src/utils/preserveQueryParameters.ts
index 405e9b93a..f50e978ad 100644
--- a/platform/app/src/utils/preserveQueryParameters.ts
+++ b/platform/app/src/utils/preserveQueryParameters.ts
@@ -5,7 +5,7 @@ function preserve(query, current, key) {
}
}
-export const preserveKeys = ['configUrl', 'multimonitor', 'screenNumber'];
+export const preserveKeys = ['configUrl', 'multimonitor', 'screenNumber', 'hangingProtocolId'];
export function preserveQueryParameters(
query,
diff --git a/platform/app/src/utils/publicUrl.ts b/platform/app/src/utils/publicUrl.ts
index 47ed7c697..489319ad5 100644
--- a/platform/app/src/utils/publicUrl.ts
+++ b/platform/app/src/utils/publicUrl.ts
@@ -1,4 +1,6 @@
const publicUrl = (window as any).PUBLIC_URL || '/';
+const routerBasename = (window as any).config?.routerBasename || publicUrl;
+
+export { publicUrl, routerBasename };
export default publicUrl;
-export { publicUrl };
diff --git a/platform/docs/docs/configuration/configurationFiles.md b/platform/docs/docs/configuration/configurationFiles.md
index db24e8da9..d3289dbb0 100644
--- a/platform/docs/docs/configuration/configurationFiles.md
+++ b/platform/docs/docs/configuration/configurationFiles.md
@@ -28,7 +28,7 @@ The simplest way is to update the existing default config:
```js title="platform/app/public/config/default.js"
window.config = {
- routerBasename: '/',
+ routerBasename: null,
extensions: [],
modes: [],
showStudyList: true,
@@ -81,7 +81,7 @@ window.config = ({ servicesManager } = {}) => {
}
},
},
- routerBasename: '/',
+ routerBasename: null,
dataSources: [
{
namespace: '@ohif/extension-default.dataSourcesModule.dicomweb',
diff --git a/platform/docs/docs/configuration/dataSources/dicom-web.md b/platform/docs/docs/configuration/dataSources/dicom-web.md
index 82fb703a1..2707370fe 100644
--- a/platform/docs/docs/configuration/dataSources/dicom-web.md
+++ b/platform/docs/docs/configuration/dataSources/dicom-web.md
@@ -123,7 +123,7 @@ configuration looks like:
```js
window.config = {
- routerBasename: '/',
+ routerBasename: null,
extensions: [],
modes: [],
showStudyList: true,
diff --git a/platform/docs/docs/deployment/custom-url-access.md b/platform/docs/docs/deployment/custom-url-access.md
index dfb1ddd61..c4639aedf 100644
--- a/platform/docs/docs/deployment/custom-url-access.md
+++ b/platform/docs/docs/deployment/custom-url-access.md
@@ -4,62 +4,113 @@ title: Custom URL Access/Build
---
-## Build for non-root path
+# Hosting the Web Viewer on a Custom URL Path
-Sometimes it is desired to access the viewer from a non-root path (e.g., `/my-awesome-viewer` instead of `/`).
-You can achieve so by using the `PUBLIC_URL` environment variable AND the `routerBasename` configuration option.
-
-1. use a config (e.g. `config/myConfig.js`) file that is using the `routerBasename` of your choice `/my-awesome-viewer` (note there is only one / - it is not /my-awesome-viewer/).
-2. build the viewer with `PUBLIC_URL=/my-awesome-viewer/` (note there are two / - it is not /my-awesome-viewer).
+You can host the viewer on a subpath like `/abc` instead of the root `/`. There are **two levels** of customization depending on how you want to serve your static assets.
-:::tip
-The PUBLIC_URL tells the application where to find the static assets and the routerBasename will tell the application how to handle the routes
-:::
+## Simple Setup (Recommended for Most Use Cases)
+If you want to make the viewer accessible from a custom path (e.g. `/abc`) and **don’t care where the assets are loaded from** (they’ll be fetched from the root `/`), this setup is for you.
-### Testing in Development
-For testing the build locally, you can use the following command:
+### What You Get
+
+- Viewer available at `https://yourdomain.com/abc`
+- All assets (JS, WASM, etc.) still loaded from the root (`/app.js`, `/viewer.wasm`, etc.)
+
+### How To Set It Up
+
+1. Set `routerBasename` in your config file (e.g., `config/myConfig.js`) to `/abc`
+2. Build the viewer with:
```bash
-# we use default config file, so we assume you have already set the routerBasename to /my-awesome-viewer in the default config as an example
-PUBLIC_URL=/my-awesome-viewer/ APP_CONFIG=config/default.js yarn dev
+APP_CONFIG=config/myConfig.js yarn build
```
-
-### Testing in Build (production)
-You need to build the viewer with the following command:
+### Local Development
```bash
-PUBLIC_URL=/my-awesome-viewer/ APP_CONFIG=config/default.js yarn build
+APP_CONFIG=config/myConfig.js yarn dev
```
-We can use the `npx serve` to serve the build folder. There are two things you need to consider however,
-1. You need to change the `public/serve.json` file to reflect the new routerBasename in the destination (see the example below)
+---
+## Advanced Setup (Custom Asset Path)
-```json
-// final serve.json
-{
- "rewrites": [{ "source": "*", "destination": "my-awesome-viewer/index.html" }],
+If you want to host the viewer at `/abc` **and** serve static assets from a different location (e.g. `/my-private-assets`), this is a more advanced scenario.
+
+### What You Get
+
+- Viewer accessible from `https://yourdomain.com/abc`
+- All assets loaded from `https://yourdomain.com/my-private-assets/`
+
+### Why This is Tricky
+
+Some libraries (especially ones using WASM) load assets using **relative paths**, which can break if not handled carefully. To solve this:
+
+- Set `routerBasename` to `/abc`
+- Set `PUBLIC_URL` to `/my-private-assets/`
+- Webpack will load assets from the specified public URL.
+
+### Local Development Notes
+
+In development, use proxy rewrites to handle relative asset paths. Example for `dicom-microscopy-viewer`:
+
+```js
+proxy: {
+ '/dicom-microscopy-viewer': {
+ target: 'http://localhost:3000',
+ pathRewrite: {
+ '^/dicom-microscopy-viewer': `/${PUBLIC_URL}/dicom-microscopy-viewer`,
+ },
+ },
}
```
+This ensures local development can find assets even when libraries expect them at certain paths.
+
+
+### Building and Serving in Production
+
+To build the viewer for production:
+
```bash
-cd platform/app;
-
-# rename the dist folder to my-awesome-viewer
-mv dist my-awesome-viewer
-
-# serve the folder with custom json, note that we are using ../public/serve.json and NOT public/serve.json
-npx serve -c ./public/serve.json
+PUBLIC_URL=/my-private-assets/ APP_CONFIG=config/myConfig.js yarn build
```
+If you're using `npx serve`, make sure to update `serve.json`:
-:::note
-When you want to authenticate against a sub path, there are a few things you should keep in mind:
+```json
+{
+ "rewrites": [{ "source": "*", "destination": "/abc/index.html" }]
+}
+```
-1. Set the `routerBasename` to the sub path and also update the `PUBLIC_URL` to match the sub path.
-2. Don't forget to modify the `serve.json` file as mentioned earlier.
-3. Ensure that the sub path is included in the list of allowed callback URLs. For example, in the Google Cloud dashboard, you can set it in the `Authorized redirect URIs` field under the `Credentials` section of the `APIs & Services` menu.
-:::
+Serve the viewer like this:
+
+```bash
+cd platform/app
+mv dist abc # Rename dist folder to match your viewer route
+npx serve -c ./public/serve.json
+```
+
+---
+
+### 🐳 Using Docker? You're Covered
+
+If you’re using our Dockerfile, you’re all set — it already handles copying specific asset folders (like `dicom-microscopy-viewer`) to the root:
+
+```Dockerfile
+COPY --from=builder /usr/src/app/platform/app/dist/dicom-microscopy-viewer /usr/share/nginx/html/dicom-microscopy-viewer
+```
+
+Keep an eye on the browser network tab for any assets that might fail to load — if any other libraries require similar treatment, you’ll need to handle those as well.
+
+---
+
+## Summary
+
+| Goal | routerBasename | PUBLIC_URL | Assets Load From |
+|-----------------------------------|----------------|-----------------------|--------------------------|
+| Viewer at `/abc`, assets from `/` | `/abc` | default | Root `/` |
+| Viewer at `/abc`, assets from `/my-private-assets` | `/abc` | `/my-private-assets/` | `/my-private-assets/` |
diff --git a/platform/docs/docs/platform/environment-variables.md b/platform/docs/docs/platform/environment-variables.md
index 1b08d5492..df5da9e03 100644
--- a/platform/docs/docs/platform/environment-variables.md
+++ b/platform/docs/docs/platform/environment-variables.md
@@ -12,6 +12,7 @@ NODE_ENV=< production | development >
DEBUG=< true | false >
APP_CONFIG=< relative path to application configuration file >
PUBLIC_URL=< relative path to application root - default / >
+ROUTER_BASENAME=< relative path to application root - default PUBLIC_URL >
VERSION_NUMBER=
BUILD_NUM=
# i18n
diff --git a/platform/docs/docs/platform/services/customization-service/customizationService.md b/platform/docs/docs/platform/services/customization-service/customizationService.md
index cda486984..afb57f2ff 100644
--- a/platform/docs/docs/platform/services/customization-service/customizationService.md
+++ b/platform/docs/docs/platform/services/customization-service/customizationService.md
@@ -172,7 +172,7 @@ Customizations can be declared at three different scopes, each with its own prio
```jsx
window.config = {
name: 'config/default.js',
- routerBasename: '/',
+ routerBasename: null,
customizationService: [
{
'studyBrowser.sortFunctions': {
@@ -194,7 +194,7 @@ Customizations can be declared at three different scopes, each with its own prio
```jsx
window.config = {
name: 'config/default.js',
- routerBasename: '/',
+ routerBasename: null,
customizationService: [
'@ohif/extension-cornerstone.customizationModule.newCustomization',
],