fix: routerBasename setting (#4891)

This commit is contained in:
Bill Wallace 2025-03-27 16:47:16 -04:00 committed by GitHub
parent c368d763b0
commit 459b0d223a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
40 changed files with 299 additions and 229 deletions

View File

@ -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;

View File

@ -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"

View File

@ -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

268
bun.lock
View File

@ -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",

View File

@ -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()),
});
};

View File

@ -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: [
{

View File

@ -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}"];`

View File

@ -1,7 +1,7 @@
/** @type {AppTypes.Config} */
window.config = {
routerBasename: '/',
routerBasename: null,
extensions: [],
modes: [],
showStudyList: true,

View File

@ -1,6 +1,6 @@
/** @type {AppTypes.Config} */
window.config = {
routerBasename: '/',
routerBasename: null,
extensions: [],
modes: ['@ohif/mode-test'],
showStudyList: true,

View File

@ -2,7 +2,7 @@
window.config = {
name: 'config/default.js',
routerBasename: '/',
routerBasename: null,
// whiteLabeling: {},
extensions: [],
modes: [],

View File

@ -1,6 +1,6 @@
/** @type {AppTypes.Config} */
window.config = {
routerBasename: '/',
routerBasename: null,
// whiteLabeling: {},
extensions: [],
modes: [],

View File

@ -1,6 +1,6 @@
/** @type {AppTypes.Config} */
window.config = {
routerBasename: '/',
routerBasename: null,
modes: [],
extensions: [],
showStudyList: true,

View File

@ -1,6 +1,6 @@
/** @type {AppTypes.Config} */
window.config = {
routerBasename: '/',
routerBasename: null,
showStudyList: true,
extensions: [],
modes: [],

View File

@ -1,6 +1,6 @@
/** @type {AppTypes.Config} */
window.config = {
routerBasename: '/',
routerBasename: null,
showStudyList: true,
extensions: [],
modes: [],

View File

@ -1,6 +1,6 @@
/** @type {AppTypes.Config} */
window.config = {
routerBasename: '/',
routerBasename: null,
extensions: [],
modes: [],
showStudyList: true,

View File

@ -1,6 +1,6 @@
/** @type {AppTypes.Config} */
window.config = {
routerBasename: '/',
routerBasename: null,
extensions: [],
modes: [],
showStudyList: true,

View File

@ -1,6 +1,6 @@
/** @type {AppTypes.Config} */
window.config = {
routerBasename: '/',
routerBasename: null,
showStudyList: true,
extensions: [],
modes: [],

View File

@ -1,6 +1,6 @@
/** @type {AppTypes.Config} */
window.config = {
routerBasename: '/',
routerBasename: null,
showStudyList: true,
extensions: [],
modes: [],

View File

@ -17,7 +17,7 @@ if (window.location.search === '?today') {
/** @type {AppTypes.Config} */
window.config = {
routerBasename: '/',
routerBasename: null,
extensions: [],
modes: ['@ohif/mode-test'],
showStudyList: true,

View File

@ -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,

View File

@ -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,

View File

@ -2,7 +2,7 @@
window.config = {
name: 'config/kheops.js',
routerBasename: '/',
routerBasename: null,
extensions: [],
modes: ['@ohif/mode-test'],
customizationService: {},

View File

@ -1,6 +1,6 @@
/** @type {AppTypes.Config} */
window.config = {
routerBasename: '/',
routerBasename: null,
showStudyList: true,
extensions: [],
modes: [],

View File

@ -1,6 +1,6 @@
/** @type {AppTypes.Config} */
window.config = {
routerBasename: '/',
routerBasename: null,
extensions: [],
modes: [],
showStudyList: true,

View File

@ -1,6 +1,6 @@
/** @type {AppTypes.Config} */
window.config = {
routerBasename: '/',
routerBasename: null,
customizationService: ['@ohif/extension-default.customizationModule.helloPage'],
extensions: [],
modes: [],

View File

@ -3,7 +3,7 @@ window.config = {
// Activate the new HP mode....
isNewHP: true,
routerBasename: '/',
routerBasename: null,
customizationService: [
'@ohif/extension-default.customizationModule.datasources',
{

View File

@ -1,7 +1,7 @@
/** @type {AppTypes.Config} */
window.config = {
routerBasename: '/',
routerBasename: null,
extensions: [],
modes: [],
showStudyList: true,

View File

@ -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,

View File

@ -53,7 +53,7 @@ function App({
* Hosted at: https://ohif.org/where-i-host-the/viewer/
* Value: `/where-i-host-the/viewer/`
* */
routerBaseName: '/',
routerBasename: '/',
/**
*
*/

View File

@ -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.

View File

@ -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({
<Link
className={isValidMode ? '' : 'cursor-not-allowed'}
key={i}
to={`${publicUrl}${mode.routeName}${dataPath || ''}?${query.toString()}`}
to={`${mode.routeName}${dataPath || ''}?${query.toString()}`}
onClick={event => {
// 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.

View File

@ -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 = () => (

View File

@ -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,

View File

@ -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,

View File

@ -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 };

View File

@ -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',

View File

@ -123,7 +123,7 @@ configuration looks like:
```js
window.config = {
routerBasename: '/',
routerBasename: null,
extensions: [],
modes: [],
showStudyList: true,

View File

@ -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 **dont care where the assets are loaded from** (theyll 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 youre using our Dockerfile, youre 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, youll 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/` |

View File

@ -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=<Set by CircleCI>
BUILD_NUM=<Set by CircleCI>
# i18n

View File

@ -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',
],