diff --git a/.circleci/config.yml b/.circleci/config.yml index dca1d74507..be290b35a5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -53,11 +53,11 @@ commands: echo "Deployment project: ${PROJECT_ID}" echo "Deployment bucket: gs://${BUCKET}" -## https://github.com/cypress-io/circleci-orb -## -#orbs: -# codecov: codecov/codecov@1.0.5 -# cypress: cypress-io/cypress@3.3.1 + ## https://github.com/cypress-io/circleci-orb + ## + #orbs: + # codecov: codecov/codecov@1.0.5 + # cypress: cypress-io/cypress@3.3.1 deployment_config: steps: @@ -222,6 +222,7 @@ jobs: default: '' description: Directory containing package.json type: string + resource_class: large steps: - cypress/install: cypress-cache-key: << parameters.cypress-cache-key >> diff --git a/.env.example b/.env.example deleted file mode 100644 index 47bf9fb0f6..0000000000 --- a/.env.example +++ /dev/null @@ -1 +0,0 @@ -PERCY_TOKEN= diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml new file mode 100644 index 0000000000..6345b8272c --- /dev/null +++ b/.github/workflows/playwright.yml @@ -0,0 +1,63 @@ +name: Playwright Tests +on: + push: + branches: [main, master] + pull_request: + branches: [main, master] +jobs: + playwright-tests: + timeout-minutes: 60 + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + shardIndex: [1, 2, 3, 4, 5] + shardTotal: [5] + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 18 + - name: Install dependencies + run: yarn install --frozen-lockfile + - name: Install Playwright Browsers + run: npx playwright install --with-deps + - name: Run Playwright tests + run: export NODE_OPTIONS="--max_old_space_size=8192" && npx playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} + + - name: Upload blob report to GitHub Actions Artifacts + if: ${{ !cancelled() }} + uses: actions/upload-artifact@v4 + with: + name: blob-report-${{ matrix.shardIndex }} + path: blob-report + retention-days: 1 + + merge-reports: + if: ${{ !cancelled() }} + needs: [playwright-tests] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 18 + - name: Install dependencies + run: yarn install --frozen-lockfile + + - name: Download blob reports from GitHub Actions Artifacts + uses: actions/download-artifact@v4 + with: + path: all-blob-reports + pattern: blob-report-* + merge-multiple: true + + - name: Merge into HTML Report + run: npx playwright merge-reports --reporter html ./all-blob-reports + + - name: Upload HTML report + uses: actions/upload-artifact@v4 + with: + name: html-report--attempt-${{ github.run_attempt }} + path: playwright-report + retention-days: 14 diff --git a/.gitignore b/.gitignore index 245556be5f..af800d7ed5 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,8 @@ junit.xml coverage/ .docz/ .yarn/ +.nx/ +addOns/yarn.lock # YALC (for Erik) .yalc @@ -33,7 +35,7 @@ docker/dcm4che/dcm4che-arc # Cypress test results videos/ -screenshots/ + # Locize settings .locize @@ -41,8 +43,16 @@ screenshots/ # autogenerated files platform/app/src/pluginImports.js /Viewers.iml -platform/app/.recipes/Nginx-Dcm4Che/dcm4che/dcm4che-arc/* +platform/app/.recipes/Nginx-Dcm4Chee/logs/* platform/app/.recipes/OpenResty-Orthanc/logs/* .vercel .vs + +# PlayWright + +node_modules/ +tests/test-results/ +tests/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/.scripts/dicom-json-generator.js b/.scripts/dicom-json-generator.js index 5b9f45a16a..f9f5297476 100644 --- a/.scripts/dicom-json-generator.js +++ b/.scripts/dicom-json-generator.js @@ -4,26 +4,34 @@ * The JSON file can be used to load the study into the OHIF Viewer. You can get more detail * in the DICOM JSON Data source on docs.ohif.org * - * Usage: node dicomStudyToJSONLaunch.js + * Usage: node dicomStudyToJSONLaunch.js * * params: - * - studyFolder: path to the study folder + * - studyFolder: path to the study folder which contains the DICOM files * - urlPrefix: prefix to the url that will be used to load the study into the viewer. For instance * we use https://ohif-assets.s3.us-east-2.amazonaws.com/dicom-json/data as the urlPrefix for the * example since the data is hosted on S3 and each study is in a folder. So the url in the generated * json file for the first instance of the first series of the first study will be * dicomweb:https://ohif-assets.s3.us-east-2.amazonaws.com/dicom-json/data/Series1/Instance1 + * + * as you see the dicomweb is a prefix that is used to load the data into the viewer, which is suited when + * the .dcm file is hosted statically and can be accessed via a URL (like our example above) + * However, you can specify a new scheme bellow. + * * - outputJSONPath: path to the output JSON file + * - scheme: default dicomweb if not provided */ const dcmjs = require('dcmjs'); const path = require('path'); const fs = require('fs').promises; const args = process.argv.slice(2); -const [studyDirectory, urlPrefix, outputPath] = args; +const [studyDirectory, urlPrefix, outputPath, scheme = 'dicomweb'] = args; -if (args.length !== 3) { - console.error('Usage: node dicomStudyToJSONLaunch.js '); +if (args.length < 3 || args.length > 4) { + console.error( + 'Usage: node dicomStudyToJSONLaunch.js [scheme]' + ); process.exit(1); } @@ -31,7 +39,7 @@ const model = { studies: [], }; -async function convertDICOMToJSON(studyDirectory, urlPrefix, outputPath) { +async function convertDICOMToJSON(studyDirectory, urlPrefix, outputPath, scheme) { try { const files = await recursiveReadDir(studyDirectory); console.debug('Processing...'); @@ -42,7 +50,7 @@ async function convertDICOMToJSON(studyDirectory, urlPrefix, outputPath) { const dicomDict = dcmjs.data.DicomMessage.readFile(arrayBuffer.buffer); const instance = dcmjs.data.DicomMetaDictionary.naturalizeDataset(dicomDict.dict); - instance.fileLocation = createImageId(file, urlPrefix, studyDirectory); + instance.fileLocation = createImageId(file, urlPrefix, studyDirectory, scheme); processInstance(instance); } } @@ -77,10 +85,10 @@ async function recursiveReadDir(dir) { return results; } -function createImageId(fileLocation, urlPrefix, studyDirectory) { +function createImageId(fileLocation, urlPrefix, studyDirectory, scheme) { const relativePath = path.relative(studyDirectory, fileLocation); const normalizedPath = path.normalize(relativePath).replace(/\\/g, '/'); - return `dicomweb:${urlPrefix}${normalizedPath}`; + return `${scheme}:${urlPrefix}${normalizedPath}`; } function processInstance(instance) { @@ -262,4 +270,4 @@ function createInstanceMetaDataMultiFrame(instance) { return instances; } -convertDICOMToJSON(studyDirectory, urlPrefix, outputPath); +convertDICOMToJSON(studyDirectory, urlPrefix, outputPath, scheme); diff --git a/.webpack/webpack.base.js b/.webpack/webpack.base.js index aa48230d16..08f18c5ded 100644 --- a/.webpack/webpack.base.js +++ b/.webpack/webpack.base.js @@ -7,7 +7,7 @@ const fs = require('fs'); const webpack = require('webpack'); // ~~ PLUGINS -const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; +// const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; const TerserJSPlugin = require('terser-webpack-plugin'); // ~~ PackageJSON @@ -19,6 +19,8 @@ const loadWebWorkersRule = require('./rules/loadWebWorkers.js'); const transpileJavaScriptRule = require('./rules/transpileJavaScript.js'); const cssToJavaScript = require('./rules/cssToJavaScript.js'); const stylusToJavaScript = require('./rules/stylusToJavaScript.js'); +const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin'); + // ~~ ENV VARS const NODE_ENV = process.env.NODE_ENV; @@ -98,6 +100,46 @@ module.exports = (env, argv, { SRC_DIR, ENTRY }) => { module: { noParse: [/(codec)/, /(dicomicc)/], rules: [ + ...(isProdBuild ? [] : [{ + test: /\.[jt]sx?$/, + exclude: /node_modules/, + loader: 'babel-loader', + options: { + plugins: ['react-refresh/babel'], + }, + }]), + { + test: /\.svg?$/, + oneOf: [ + { + use: [ + { + loader: '@svgr/webpack', + options: { + svgoConfig: { + plugins: [ + { + name: 'preset-default', + params: { + overrides: { + removeViewBox: false + }, + }, + }, + ] + }, + prettier: false, + svgo: true, + titleProp: true, + }, + }, + ], + issuer: { + and: [/\.(ts|tsx|js|jsx|md|mdx)$/], + }, + }, + ], + }, { test: /\.js$/, enforce: 'pre', @@ -142,8 +184,6 @@ module.exports = (env, argv, { SRC_DIR, ENTRY }) => { '@hooks': path.resolve(__dirname, '../platform/app/src/hooks'), '@routes': path.resolve(__dirname, '../platform/app/src/routes'), '@state': path.resolve(__dirname, '../platform/app/src/state'), - 'dicom-microscopy-viewer': - 'dicom-microscopy-viewer/dist/dynamic-import/dicomMicroscopyViewer.min.js', '@cornerstonejs/dicom-image-loader': '@cornerstonejs/dicom-image-loader/dist/dynamic-import/cornerstoneDICOMImageLoader.min.js', }, @@ -173,6 +213,7 @@ module.exports = (env, argv, { SRC_DIR, ENTRY }) => { new webpack.ProvidePlugin({ Buffer: ['buffer', 'Buffer'], }), + ...(isProdBuild ? [] : [new ReactRefreshWebpackPlugin()]), // Uncomment to generate bundle analyzer // new BundleAnalyzerPlugin(), ], diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b1f4946d9..990bd042e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,879 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.9.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.70...v3.9.0-beta.71) (2024-07-30) + + +### Bug Fixes + +* ip SSRF improper categorization ([#4319](https://github.com/OHIF/Viewers/issues/4319)) ([aa0e5a5](https://github.com/OHIF/Viewers/commit/aa0e5a59379453bb8e6a4f286447576744ea6bf5)) + + + + + +# [3.9.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.69...v3.9.0-beta.70) (2024-07-30) + + +### Bug Fixes + +* **ui:** remove border-border class ([#4317](https://github.com/OHIF/Viewers/issues/4317)) ([d402ded](https://github.com/OHIF/Viewers/commit/d402ded8c36631f8009b7b15b2f1c7a02cd09f6c)) + + + + + +# [3.9.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.68...v3.9.0-beta.69) (2024-07-27) + +**Note:** Version bump only for package ohif-monorepo-root + + + + + +# [3.9.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.67...v3.9.0-beta.68) (2024-07-26) + + +### Bug Fixes + +* **dicom:** Update multiframe DICOM JSON parsing for correct image ID generation ([#4307](https://github.com/OHIF/Viewers/issues/4307)) ([16b7aa4](https://github.com/OHIF/Viewers/commit/16b7aa4f6538b81e5915e47b9209d74575895dfe)) + + + + + +# [3.9.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.66...v3.9.0-beta.67) (2024-07-26) + +**Note:** Version bump only for package ohif-monorepo-root + + + + + +# [3.9.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.65...v3.9.0-beta.66) (2024-07-24) + + +### Features + +* **pmap:** added support for parametric map ([#4284](https://github.com/OHIF/Viewers/issues/4284)) ([fc0064f](https://github.com/OHIF/Viewers/commit/fc0064fd9d8cdc8fde81b81f0e71fd5d077ca22b)) + + + + + +# [3.9.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.64...v3.9.0-beta.65) (2024-07-23) + + +### Features + +* **SR:** text structured report (TEXT, CODE, NUM, PNAME, DATE, TIME and DATETIME) ([#4287](https://github.com/OHIF/Viewers/issues/4287)) ([246ebab](https://github.com/OHIF/Viewers/commit/246ebab6ebf5431a704a1861a5804045b9644ba4)) + + + + + +# [3.9.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.63...v3.9.0-beta.64) (2024-07-19) + +**Note:** Version bump only for package ohif-monorepo-root + + + + + +# [3.9.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.62...v3.9.0-beta.63) (2024-07-10) + +**Note:** Version bump only for package ohif-monorepo-root + + + + + +# [3.9.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.61...v3.9.0-beta.62) (2024-07-09) + + +### Bug Fixes + +* the start/end command in TMTV for the ROIStartEndThreshold tools ([#4281](https://github.com/OHIF/Viewers/issues/4281)) ([38c19fa](https://github.com/OHIF/Viewers/commit/38c19fab77cdb21d14bdae35813d73f43012cbd7)) + + + + + +# [3.9.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.60...v3.9.0-beta.61) (2024-07-09) + + +### Features + +* **auth:** Add Authorization Code Flow and new Keycloak recipes with new video tutorials ([#4234](https://github.com/OHIF/Viewers/issues/4234)) ([aefa6d9](https://github.com/OHIF/Viewers/commit/aefa6d94dff82d34fa8358933fb1d5dec3f8246d)) + + + + + +# [3.9.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.59...v3.9.0-beta.60) (2024-07-09) + + +### Bug Fixes + +* Tests run against e2e config for both playwright and older tests ([#4283](https://github.com/OHIF/Viewers/issues/4283)) ([31271ae](https://github.com/OHIF/Viewers/commit/31271aeef727ec9cfa44fdf91f571a33b10cb3ab)) + + + + + +# [3.9.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.58...v3.9.0-beta.59) (2024-07-05) + + +### Bug Fixes + +* Cobb angle not working in basic-test mode and open contour ([#4280](https://github.com/OHIF/Viewers/issues/4280)) ([6fd3c7e](https://github.com/OHIF/Viewers/commit/6fd3c7e293fec851dd30e650c1347cc0bc7a99ee)) +* **image-orientation:** Prevent incorrect orientation marker display for single-slice US images ([#4275](https://github.com/OHIF/Viewers/issues/4275)) ([6d11048](https://github.com/OHIF/Viewers/commit/6d11048ca5ea66284948602613a63277083ec6a5)) +* webpack import bugs showing warnings on import ([#4265](https://github.com/OHIF/Viewers/issues/4265)) ([24c511f](https://github.com/OHIF/Viewers/commit/24c511f4bc04c4143bbd3d0d48029f41f7f36014)) + + +### Features + +* Add interleaved HTJ2K and volume progressive loading ([#4276](https://github.com/OHIF/Viewers/issues/4276)) ([a2084f3](https://github.com/OHIF/Viewers/commit/a2084f319b731d98b59485799fb80357094f8c38)) + + + + + +# [3.9.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.57...v3.9.0-beta.58) (2024-07-04) + + +### Bug Fixes + +* stdValue in TMTV mode ([#4278](https://github.com/OHIF/Viewers/issues/4278)) ([b2c6291](https://github.com/OHIF/Viewers/commit/b2c629123c5cf05afbeb19bd1424c327c1f5a606)) + + + + + +# [3.9.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.56...v3.9.0-beta.57) (2024-07-02) + +**Note:** Version bump only for package ohif-monorepo-root + + + + + +# [3.9.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.55...v3.9.0-beta.56) (2024-07-02) + +**Note:** Version bump only for package ohif-monorepo-root + + + + + +# [3.9.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.54...v3.9.0-beta.55) (2024-06-28) + +**Note:** Version bump only for package ohif-monorepo-root + + + + + +# [3.9.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.53...v3.9.0-beta.54) (2024-06-28) + + +### Features + +* **studyPrefetcher:** Study Prefetcher ([#4206](https://github.com/OHIF/Viewers/issues/4206)) ([2048b19](https://github.com/OHIF/Viewers/commit/2048b19484c0b1fae73f993cfaa814f861bbd230)) + + + + + +# [3.9.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.52...v3.9.0-beta.53) (2024-06-28) + +**Note:** Version bump only for package ohif-monorepo-root + + + + + +# [3.9.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.51...v3.9.0-beta.52) (2024-06-27) + + +### Bug Fixes + +* **cli:** missing js ([#4268](https://github.com/OHIF/Viewers/issues/4268)) ([f660f8e](https://github.com/OHIF/Viewers/commit/f660f8e970c0226b34a9de10e2c57429dcce6763)) + + + + + +# [3.9.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.50...v3.9.0-beta.51) (2024-06-27) + + +### Bug Fixes + +* **cli:** Fix the cli utilities which require full paths ([d09f8b5](https://github.com/OHIF/Viewers/commit/d09f8b5ba2dcc0c02beb405b8cfa79fbae5bdde8)), closes [#4267](https://github.com/OHIF/Viewers/issues/4267) + + + + + +# [3.9.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.49...v3.9.0-beta.50) (2024-06-26) + + +### Bug Fixes + +* **orthanc:** Correct bulkdata URL handling and add configuration example PDF ([#4262](https://github.com/OHIF/Viewers/issues/4262)) ([fdf883a](https://github.com/OHIF/Viewers/commit/fdf883ada880c0979acba8fdff9b542dc05b7706)) + + + + + +# [3.9.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.48...v3.9.0-beta.49) (2024-06-26) + +**Note:** Version bump only for package ohif-monorepo-root + + + + + +# [3.9.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.47...v3.9.0-beta.48) (2024-06-25) + +**Note:** Version bump only for package ohif-monorepo-root + + + + + +# [3.9.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.46...v3.9.0-beta.47) (2024-06-21) + + +### Bug Fixes + +* Allow the mode setup/creation to be async, and provide a few more values to extension/app config/mode setup. ([#4016](https://github.com/OHIF/Viewers/issues/4016)) ([88575c6](https://github.com/OHIF/Viewers/commit/88575c6c09fd778a31b2f91524163ce65d1639dd)) +* **code:** remove console log ([#4248](https://github.com/OHIF/Viewers/issues/4248)) ([f3bbfff](https://github.com/OHIF/Viewers/commit/f3bbfff09b66ee020daf503656a2b58e763634a3)) +* **CustomViewportOverlay:** pass accurate data to Custom Viewport Functions ([#4224](https://github.com/OHIF/Viewers/issues/4224)) ([aef00e9](https://github.com/OHIF/Viewers/commit/aef00e91d63e9bc2de289cc6f35975e36547fb20)) +* **studybrowser:** Differentiate recent and all in study panel based on a provided time period ([#4242](https://github.com/OHIF/Viewers/issues/4242)) ([6f93449](https://github.com/OHIF/Viewers/commit/6f9344914951c204feaff48aaeb43cd7d727623d)) + + +### Features + +* customization service append and customize functionality should run once ([#4238](https://github.com/OHIF/Viewers/issues/4238)) ([e462fd3](https://github.com/OHIF/Viewers/commit/e462fd31f7944acfee34f08cfbc28cfd9de16169)) +* **HP:** Frame View HP ([#4235](https://github.com/OHIF/Viewers/issues/4235)) ([d5d8214](https://github.com/OHIF/Viewers/commit/d5d821464acb0f89fc9b189bd245a06c209d77b4)) +* **sort:** custom series sort in study panel ([#4214](https://github.com/OHIF/Viewers/issues/4214)) ([a433d40](https://github.com/OHIF/Viewers/commit/a433d406e2cac13f644203996c682260b54e8865)) + + + + + +# [3.9.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.45...v3.9.0-beta.46) (2024-06-18) + + +### Bug Fixes + +* Use correct external URL for rendered responses with relative URI ([#4236](https://github.com/OHIF/Viewers/issues/4236)) ([d8f6991](https://github.com/OHIF/Viewers/commit/d8f6991dbe72465080cfc5de39c7ea225702f2e0)) + + + + + +# [3.9.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.44...v3.9.0-beta.45) (2024-06-18) + + +### Bug Fixes + +* Re-enable hpScale module ([#4237](https://github.com/OHIF/Viewers/issues/4237)) ([2eab049](https://github.com/OHIF/Viewers/commit/2eab049d7993bb834f7736093941c175f16d61fc)) + + + + + +# [3.9.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.43...v3.9.0-beta.44) (2024-06-17) + + +### Bug Fixes + +* **cli:** version txt had a new line which it should not ([#4233](https://github.com/OHIF/Viewers/issues/4233)) ([097ef76](https://github.com/OHIF/Viewers/commit/097ef7665559a672d73e1babfc42afccc3cdd41d)) +* **pdf-viewport:** Allow Drag and Drop on PDF Viewport ([#4225](https://github.com/OHIF/Viewers/issues/4225)) ([729efb6](https://github.com/OHIF/Viewers/commit/729efb6d766e0f72f1fd8adefbca6fb46b355b2b)) + + + + + +# [3.9.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.42...v3.9.0-beta.43) (2024-06-12) + + +### Bug Fixes + +* **sr:** rendering issue by running loadSR before updateSR ([#4226](https://github.com/OHIF/Viewers/issues/4226)) ([6971287](https://github.com/OHIF/Viewers/commit/69712874603109aa4f655d47daf15d72167a49ff)) + + + + + +# [3.9.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.41...v3.9.0-beta.42) (2024-06-12) + +**Note:** Version bump only for package ohif-monorepo-root + + + + + +# [3.9.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.40...v3.9.0-beta.41) (2024-06-12) + + +### Features + +* Add customization merge, append or replace functionality ([#3871](https://github.com/OHIF/Viewers/issues/3871)) ([55dcfa1](https://github.com/OHIF/Viewers/commit/55dcfa1f6994a7036e7e594efb23673382a41915)) + + + + + +# [3.9.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.39...v3.9.0-beta.40) (2024-06-12) + +**Note:** Version bump only for package ohif-monorepo-root + + + + + +# [3.9.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.38...v3.9.0-beta.39) (2024-06-08) + +**Note:** Version bump only for package ohif-monorepo-root + + + + + +# [3.9.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.37...v3.9.0-beta.38) (2024-06-07) + + +### Bug Fixes + +* **window-level:** move window level region to more tools menu ([#4215](https://github.com/OHIF/Viewers/issues/4215)) ([33f4c18](https://github.com/OHIF/Viewers/commit/33f4c18f2687d30a250fe7183df3daae8394a984)) + + + + + +# [3.9.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.36...v3.9.0-beta.37) (2024-06-05) + +**Note:** Version bump only for package ohif-monorepo-root + + + + + +# [3.9.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.35...v3.9.0-beta.36) (2024-06-05) + + +### Bug Fixes + +* get direct url pixel data should be optional for video ([#4152](https://github.com/OHIF/Viewers/issues/4152)) ([649ffab](https://github.com/OHIF/Viewers/commit/649ffab4d97be875d42e1a3473a4354aac14e87d)) + + + + + +# [3.9.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.34...v3.9.0-beta.35) (2024-06-05) + + +### Bug Fixes + +* **seg:** maintain algorithm name and algorithm type when DICOM seg is exported or downloaded ([#4203](https://github.com/OHIF/Viewers/issues/4203)) ([a29e94d](https://github.com/OHIF/Viewers/commit/a29e94de803f79bbb3372d00ad8eb14b4224edc2)) + + + + + +# [3.9.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.33...v3.9.0-beta.34) (2024-06-05) + + +### Bug Fixes + +* **hydration:** Maintain the same slice that the user was on pre hydration in post hydration for SR and SEG. ([#4200](https://github.com/OHIF/Viewers/issues/4200)) ([430330f](https://github.com/OHIF/Viewers/commit/430330f7e384d503cb6fc695a7a9642ddfaac313)) + + + + + +# [3.9.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.32...v3.9.0-beta.33) (2024-06-05) + + +### Features + +* **window-level-region:** add window level region tool ([#4127](https://github.com/OHIF/Viewers/issues/4127)) ([ab1a18a](https://github.com/OHIF/Viewers/commit/ab1a18af5a5b0f9086c080ed81c8fda9bfaa975b)) + + + + + +# [3.9.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.31...v3.9.0-beta.32) (2024-05-31) + + +### Bug Fixes + +* **tmtv:** crosshairs should not have viewport indicators ([#4197](https://github.com/OHIF/Viewers/issues/4197)) ([f85da32](https://github.com/OHIF/Viewers/commit/f85da32f34389ef7cecae03c07e0af26468b52a6)) + + + + + +# [3.9.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.30...v3.9.0-beta.31) (2024-05-30) + + +### Bug Fixes + +* **seg:** should be able to navigate outside toolbox and come back later ([#4196](https://github.com/OHIF/Viewers/issues/4196)) ([93e7609](https://github.com/OHIF/Viewers/commit/93e760937f6587ba7481fcf3484ba9004ba49a62)) + + + + + +# [3.9.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.29...v3.9.0-beta.30) (2024-05-30) + + +### Bug Fixes + +* **docker:** docker build was broken because of imports ([#4192](https://github.com/OHIF/Viewers/issues/4192)) ([d7aa386](https://github.com/OHIF/Viewers/commit/d7aa386800153e0bb9eea6bbf36c696c57750ad8)) +* segmentation creation and segmentation mode viewport rendering ([#4193](https://github.com/OHIF/Viewers/issues/4193)) ([2174026](https://github.com/OHIF/Viewers/commit/217402678981f74293dff615f6b6812e54216d37)) + + + + + +# [3.9.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.28...v3.9.0-beta.29) (2024-05-30) + + +### Bug Fixes + +* **tmtv:** side panel crashing when activeToolOptions is not an array ([#4189](https://github.com/OHIF/Viewers/issues/4189)) ([19b5b1c](https://github.com/OHIF/Viewers/commit/19b5b1c15cb29ddf1cfd9b608815199bc838f8b2)) + + + + + +# [3.9.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.27...v3.9.0-beta.28) (2024-05-30) + + +### Bug Fixes + +* **queryparam:** set all query params to lowercase by default ([#4190](https://github.com/OHIF/Viewers/issues/4190)) ([e073d19](https://github.com/OHIF/Viewers/commit/e073d195fdec7f8bdb67e5e3dae522a0fd121ad2)) + + + + + +# [3.9.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.26...v3.9.0-beta.27) (2024-05-29) + + +### Bug Fixes + +* **contour:** set renderFill to false for contour ([#4186](https://github.com/OHIF/Viewers/issues/4186)) ([731340d](https://github.com/OHIF/Viewers/commit/731340d70ab23e116dd23e80b880bd8a28526f19)) + + + + + +# [3.9.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.25...v3.9.0-beta.26) (2024-05-29) + + +### Features + +* **hp:** Add displayArea option for Hanging protocols and example with Mamo([#3808](https://github.com/OHIF/Viewers/issues/3808)) ([18ac08e](https://github.com/OHIF/Viewers/commit/18ac08ed860d119721c52e4ffc270332259100b6)) + + + + + +# [3.9.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.24...v3.9.0-beta.25) (2024-05-29) + + +### Bug Fixes + +* **ultrasound:** Upgrade cornerstone3D version to resolve coloring issues ([#4181](https://github.com/OHIF/Viewers/issues/4181)) ([75a71db](https://github.com/OHIF/Viewers/commit/75a71db7f89840250ad1c2b35df5a35aceb8be7d)) + + + + + +# [3.9.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.23...v3.9.0-beta.24) (2024-05-29) + + +### Features + +* **measurements:** show untracked measurements in measurement panel under additional findings ([#4160](https://github.com/OHIF/Viewers/issues/4160)) ([18686c2](https://github.com/OHIF/Viewers/commit/18686c2caf13ede3e881303100bd4cc34b8b135f)) + + + + + +# [3.9.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.22...v3.9.0-beta.23) (2024-05-28) + + +### Bug Fixes + +* **rt:** dont convert to volume for RTSTRUCT ([#4157](https://github.com/OHIF/Viewers/issues/4157)) ([7745c09](https://github.com/OHIF/Viewers/commit/7745c092bb3edf0090f32fbbbae2f0776128d5a2)) + + + + + +# [3.9.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.21...v3.9.0-beta.22) (2024-05-27) + + +### Features + +* **ui:** move to React 18 and base for using shadcn/ui ([#4174](https://github.com/OHIF/Viewers/issues/4174)) ([70f2c79](https://github.com/OHIF/Viewers/commit/70f2c797f42af603d7ea0eb8d23b4103aba66f77)) + + + + + +# [3.9.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.20...v3.9.0-beta.21) (2024-05-24) + + +### Features + +* **types:** typed app config ([#4171](https://github.com/OHIF/Viewers/issues/4171)) ([8960b89](https://github.com/OHIF/Viewers/commit/8960b89911a9342d93bf1a62bec97a696f101fd4)) + + + + + +# [3.9.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.19...v3.9.0-beta.20) (2024-05-24) + +**Note:** Version bump only for package ohif-monorepo-root + + + + + +# [3.9.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.18...v3.9.0-beta.19) (2024-05-24) + +**Note:** Version bump only for package ohif-monorepo-root + + + + + +# [3.9.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.17...v3.9.0-beta.18) (2024-05-24) + +**Note:** Version bump only for package ohif-monorepo-root + + + + + +# [3.9.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.16...v3.9.0-beta.17) (2024-05-23) + + +### Bug Fixes + +* **crosshairs:** reset angle, position, and slabthickness for crosshairs when reset viewport tool is used ([#4113](https://github.com/OHIF/Viewers/issues/4113)) ([73d9e99](https://github.com/OHIF/Viewers/commit/73d9e99d5d6f38ab6c36f4471d54f18798feacb4)) + + + + + +# [3.9.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.15...v3.9.0-beta.16) (2024-05-23) + + +### Bug Fixes + +* dicom json for orthanc by Update package versions for [@cornerstonejs](https://github.com/cornerstonejs) dependencies ([#4165](https://github.com/OHIF/Viewers/issues/4165)) ([34c7d72](https://github.com/OHIF/Viewers/commit/34c7d72142847486b98c9c52469940083eeaf87e)) + + + + + +# [3.9.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.14...v3.9.0-beta.15) (2024-05-22) + +**Note:** Version bump only for package ohif-monorepo-root + + + + + +# [3.9.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.13...v3.9.0-beta.14) (2024-05-21) + + +### Bug Fixes + +* **HangingProtocol:** fix hp when unsupported series load first ([#4145](https://github.com/OHIF/Viewers/issues/4145)) ([b124c91](https://github.com/OHIF/Viewers/commit/b124c91d8fa0def262d1fee8f105295b02864129)) + + + + + +# [3.9.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.12...v3.9.0-beta.13) (2024-05-21) + + +### Features + +* **rt:** allow rendering of points in RT Struct ([#4128](https://github.com/OHIF/Viewers/issues/4128)) ([5903b07](https://github.com/OHIF/Viewers/commit/5903b0749aa41112d2e991bf53ed29b1fd7bd13f)) + + + + + +# [3.9.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.11...v3.9.0-beta.12) (2024-05-21) + + +### Bug Fixes + +* **segmentation:** Address issue where segmentation creation failed on layout change ([#4153](https://github.com/OHIF/Viewers/issues/4153)) ([29944c8](https://github.com/OHIF/Viewers/commit/29944c8512c35718af03c03ef82bc43675ee1872)) + + + + + +# [3.9.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.10...v3.9.0-beta.11) (2024-05-21) + + +### Features + +* **test:** Playwright testing integration ([#4146](https://github.com/OHIF/Viewers/issues/4146)) ([fe1a706](https://github.com/OHIF/Viewers/commit/fe1a706446cc33670bf5fab8451e8281b487fcd6)) + + + + + +# [3.9.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.9...v3.9.0-beta.10) (2024-05-21) + + +### Bug Fixes + +* **stack-invalidation:** Resolve stack invalidation if metadata invalidated ([#4147](https://github.com/OHIF/Viewers/issues/4147)) ([70bb6c4](https://github.com/OHIF/Viewers/commit/70bb6c46267b3733a665f12534b849c890ce54ad)) + + + + + +# [3.9.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.8...v3.9.0-beta.9) (2024-05-17) + + +### Bug Fixes + +* **select:** utilize react portals for select component ([#4144](https://github.com/OHIF/Viewers/issues/4144)) ([dce1e7d](https://github.com/OHIF/Viewers/commit/dce1e7d423cb64ec0d4be7362ecbfd52db47ef36)) + + + + + +# [3.9.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.7...v3.9.0-beta.8) (2024-05-16) + +**Note:** Version bump only for package ohif-monorepo-root + + + + + +# [3.9.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.6...v3.9.0-beta.7) (2024-05-15) + + +### Bug Fixes + +* **tmtv:** threshold was crashing the side panel ([#4119](https://github.com/OHIF/Viewers/issues/4119)) ([8d5c676](https://github.com/OHIF/Viewers/commit/8d5c676a5e1f3eda664071c8aece313de766bd59)) + + + + + +# [3.9.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.5...v3.9.0-beta.6) (2024-05-15) + + +### Bug Fixes + +* 🐛 Overflow scroll list menu based on screen hight ([#4123](https://github.com/OHIF/Viewers/issues/4123)) ([6bba2e7](https://github.com/OHIF/Viewers/commit/6bba2e70f80d8eacc57c0e765013d9c10adf5413)) + + + + + +# [3.9.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.4...v3.9.0-beta.5) (2024-05-14) + +**Note:** Version bump only for package ohif-monorepo-root + + + + + +# [3.9.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.3...v3.9.0-beta.4) (2024-05-14) + + +### Bug Fixes + +* **auth:** bind handleUnauthenticated to correct context ([#4120](https://github.com/OHIF/Viewers/issues/4120)) ([8fa339f](https://github.com/OHIF/Viewers/commit/8fa339f296fd7e844f3879cfd81e47dbff315e66)) +* **DicomJSONDataSource:** Fix series filtering ([#4092](https://github.com/OHIF/Viewers/issues/4092)) ([2de102c](https://github.com/OHIF/Viewers/commit/2de102c73c795cfb48b49005b10aa788444a45b7)) + + + + + +# [3.9.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.2...v3.9.0-beta.3) (2024-05-08) + + +### Features + +* **typings:** Enhance typing support with withAppTypes and custom services throughout OHIF ([#4090](https://github.com/OHIF/Viewers/issues/4090)) ([374065b](https://github.com/OHIF/Viewers/commit/374065bc3bad9d212f9817a8d41546cc64cfabfb)) + + + + + +# [3.9.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.1...v3.9.0-beta.2) (2024-05-06) + + +### Bug Fixes + +* **bugs:** enhancements and bugs in several areas ([#4086](https://github.com/OHIF/Viewers/issues/4086)) ([730f434](https://github.com/OHIF/Viewers/commit/730f4349100f21b4489a21707dbb2dca9dbfbba2)) + + + + + +# [3.9.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.0...v3.9.0-beta.1) (2024-05-06) + + +### Bug Fixes + +* **rt:** enhanced RT support, utilize SVGs for rendering. ([#4074](https://github.com/OHIF/Viewers/issues/4074)) ([0156bc4](https://github.com/OHIF/Viewers/commit/0156bc426f1840ae0d090223e94a643726e856cb)) + + + + + +# [3.9.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.94...v3.9.0-beta.0) (2024-04-29) + +**Note:** Version bump only for package ohif-monorepo-root + + + + + +# [3.8.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0-beta.94) (2024-04-29) + +**Note:** Version bump only for package ohif-monorepo-root + + + + + +# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29) + + +### Bug Fixes + +* **toolbox:** Preserve user-specified tool state and streamline command execution ([#4063](https://github.com/OHIF/Viewers/issues/4063)) ([f1a736d](https://github.com/OHIF/Viewers/commit/f1a736d1934733a434cb87b2c284907a3122403f)) + + + + + +# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28) + + +### Bug Fixes + +* **bugs:** fix patient header for doc, track ball rotate resize observer and add segmentation button not being enabled on viewport data change ([#4068](https://github.com/OHIF/Viewers/issues/4068)) ([c09311d](https://github.com/OHIF/Viewers/commit/c09311d3b7df05fcd00a9f36a7233e9d7e5589d0)) + + + + + +# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25) + +**Note:** Version bump only for package ohif-monorepo-root + + + + + +# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22) + + +### Bug Fixes + +* **viewport-sync:** Enable re-sync image slices in a different position when needed ([#3984](https://github.com/OHIF/Viewers/issues/3984)) ([6ebd2cc](https://github.com/OHIF/Viewers/commit/6ebd2cc7cb70cd88fd01dc1e516077f27b201943)) + + + + + +# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22) + + +### Bug Fixes + +* **vewport:** Add missing blendmodes from cornerstonejs ([#4055](https://github.com/OHIF/Viewers/issues/4055)) ([3ec7e51](https://github.com/OHIF/Viewers/commit/3ec7e512169a07506388902acb5b2c118093fa50)) +* **viewport-webworker-segmentation:** Resolve issues with viewport detection, webworker termination, and segmentation panel layout change ([#4059](https://github.com/OHIF/Viewers/issues/4059)) ([52a0c59](https://github.com/OHIF/Viewers/commit/52a0c59294a4161fcca0a6708855549034849951)) + + + + + +# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22) + + +### Bug Fixes + +* **hp:** Fails to display any layouts in the layout selector if first layout has multiple stages ([#4058](https://github.com/OHIF/Viewers/issues/4058)) ([f0ed3fd](https://github.com/OHIF/Viewers/commit/f0ed3fd7b99b0e4e00b261ceb9888ba94726719c)) + + + + + +# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19) + + +### Features + +* **tmtv-mode:** Add Brush tools and move SUV peak calculation to web worker ([#4053](https://github.com/OHIF/Viewers/issues/4053)) ([8192e34](https://github.com/OHIF/Viewers/commit/8192e348eca993fec331d4963efe88f9a730eceb)) + + + + + +# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19) + + +### Bug Fixes + +* **layouts:** and fix thumbnail in touch and update migration guide for 3.8 release ([#4052](https://github.com/OHIF/Viewers/issues/4052)) ([d250d04](https://github.com/OHIF/Viewers/commit/d250d04580883446fcb8d748b2a97c5c198922af)) + + + + + +# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18) + +**Note:** Version bump only for package ohif-monorepo-root + + + + + +# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18) + + +### Bug Fixes + +* **bugs:** and replace seriesInstanceUID and seriesInstanceUIDs URL with seriesInstanceUIDs ([#4049](https://github.com/OHIF/Viewers/issues/4049)) ([da7c1a5](https://github.com/OHIF/Viewers/commit/da7c1a5d8c54bfa1d3f97bbc500386bf76e7fd9d)) + + + + + +# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18) + + +### Bug Fixes + +* **bugs:** enhancements and bug fixes - final ([#4048](https://github.com/OHIF/Viewers/issues/4048)) ([170bb96](https://github.com/OHIF/Viewers/commit/170bb96983082c39b22b7352e0c54aacf3e73b02)) + + + + + # [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17) diff --git a/README.md b/README.md index 5befea75c4..523d82834c 100644 --- a/README.md +++ b/README.md @@ -41,17 +41,19 @@ provided by the Open Health Imaging Foundation (OHIF | | | | | :-: | :--- | :--- | -| Measurement tracking | Measurement Tracking | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5) | -| Segmentations | Labelmap Segmentations | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.12.2.1107.5.2.32.35162.30000015050317233592200000046) | -| Hanging Protocols | Fusion and Custom Hanging protocols | [Demo](https://viewer.ohif.org/tmtv?StudyInstanceUIDs=1.3.6.1.4.1.14519.5.2.1.7009.2403.334240657131972136850343327463) | -| Microscopy | Slide Microscopy | [Demo](https://viewer.ohif.org/microscopy?StudyInstanceUIDs=2.25.275741864483510678566144889372061815320) | -| Volume Rendering | Volume Rendering | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5&hangingprotocolId=mprAnd3DVolumeViewport) | - - +| Measurement tracking | Measurement Tracking | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5) | +| Segmentations | Labelmap Segmentations | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.12.2.1107.5.2.32.35162.30000015050317233592200000046) | +| Hanging Protocols | Fusion and Custom Hanging protocols | [Demo](https://viewer.ohif.org/tmtv?StudyInstanceUIDs=1.3.6.1.4.1.14519.5.2.1.7009.2403.334240657131972136850343327463) | +| Volume Rendering | Volume Rendering | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5&hangingprotocolId=mprAnd3DVolumeViewport) | +| PDF | PDF | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=2.25.317377619501274872606137091638706705333) | +| RTSTRUCT | RT STRUCT | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.6.1.4.1.5962.99.1.2968617883.1314880426.1493322302363.3.0) | +| 4D | 4D | [Demo](https://viewer.ohif.org/dynamic-volume?StudyInstanceUIDs=2.25.232704420736447710317909004159492840763) | +| VIDEO | Video | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=2.25.96975534054447904995905761963464388233) | +| microscopy | Slide Microscopy | [Demo](https://viewer.ohif.org/microscopy?StudyInstanceUIDs=2.25.141277760791347900862109212450152067508) | ## About -The OHIF Medical Imaging Viewer is for viewing medical images. It can retrieve +The OHIF Viewer can retrieve and load images from most sources and formats; render sets in 2D, 3D, and reconstructed representations; allows for the manipulation, annotation, and serialization of observations; supports internationalization, OpenID Connect, @@ -116,19 +118,16 @@ This is typically where the latest development happens. Code that is in the mast Each package is tagged with beta version numbers, and published to npm such as `@ohif/ui@3.6.0-beta.1` -### `release` branch - The latest stable release - -This branch represents the latest stable version of the project that is considered ready for production. The code in this branch should be fully tested and vetted for release. Once the code in the master branch reaches a state where it's stable and ready to be released to users, -we do a comprehensive code review and QA testing. Once the code is approved, -we merge it into the release branch and tag a new release. +### `release/*` branches - The latest stable releases +Once the `master` branch code reaches a stable, release-ready state, we conduct a comprehensive code review and QA testing. Upon approval, we create a new release branch from `master`. These branches represent the latest stable version considered ready for production. -Each package is tagged with version numbers, and published to npm such as `@ohif/ui@3.5.0` +For example, `release/3.5` is the branch for version 3.5.0, and `release/3.6` is for version 3.6.0. After each release, we wait a few days to ensure no critical bugs. If any are found, we fix them in the release branch and create a new release with a minor version bump, e.g., 3.5.1 in the `release/3.5` branch. -Note: `master` is always ahead of `release` branch. We publish both docker builds for beta and stable releases. +Each package is tagged with version numbers and published to npm, such as `@ohif/ui@3.5.0`. Note that `master` is always ahead of the `release` branch. We publish docker builds for both beta and stable releases. Here is a schematic representation of our development workflow: -![Alt text](platform/docs/docs/assets/img/github-readme-branches.png) +![alt text](platform/docs/docs/assets/img/github-readme-branches-Jun2024.png) @@ -137,7 +136,7 @@ Here is a schematic representation of our development workflow: ### Requirements - [Yarn 1.17.3+](https://yarnpkg.com/en/docs/install) -- [Node 16+](https://nodejs.org/en/) +- [Node 18+](https://nodejs.org/en/) - Yarn Workspaces should be enabled on your machine: - `yarn config set workspaces-experimental true` diff --git a/addOns/README.md b/addOns/README.md new file mode 100644 index 0000000000..216a65e9a5 --- /dev/null +++ b/addOns/README.md @@ -0,0 +1,3 @@ +# External Dependencies + +This module contains optional dependencies and external dependencies for including in OHIF, such as the DICOM Microscopy Viewer component. diff --git a/addOns/externals/devDependencies/CHANGELOG.md b/addOns/externals/devDependencies/CHANGELOG.md new file mode 100644 index 0000000000..6981edd809 --- /dev/null +++ b/addOns/externals/devDependencies/CHANGELOG.md @@ -0,0 +1,203 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# [3.9.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.70...v3.9.0-beta.71) (2024-07-30) + +**Note:** Version bump only for package @externals/devDependencies + + + + + +# [3.9.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.69...v3.9.0-beta.70) (2024-07-30) + +**Note:** Version bump only for package @externals/devDependencies + + + + + +# [3.9.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.68...v3.9.0-beta.69) (2024-07-27) + +**Note:** Version bump only for package @externals/devDependencies + + + + + +# [3.9.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.67...v3.9.0-beta.68) (2024-07-26) + +**Note:** Version bump only for package @externals/devDependencies + + + + + +# [3.9.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.66...v3.9.0-beta.67) (2024-07-26) + +**Note:** Version bump only for package @externals/devDependencies + + + + + +# [3.9.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.65...v3.9.0-beta.66) (2024-07-24) + +**Note:** Version bump only for package @externals/devDependencies + + + + + +# [3.9.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.64...v3.9.0-beta.65) (2024-07-23) + +**Note:** Version bump only for package @externals/devDependencies + + + + + +# [3.9.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.63...v3.9.0-beta.64) (2024-07-19) + +**Note:** Version bump only for package @externals/devDependencies + + + + + +# [3.9.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.62...v3.9.0-beta.63) (2024-07-10) + +**Note:** Version bump only for package @externals/devDependencies + + + + + +# [3.9.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.61...v3.9.0-beta.62) (2024-07-09) + +**Note:** Version bump only for package @externals/devDependencies + + + + + +# [3.9.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.60...v3.9.0-beta.61) (2024-07-09) + +**Note:** Version bump only for package @externals/devDependencies + + + + + +# [3.9.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.59...v3.9.0-beta.60) (2024-07-09) + +**Note:** Version bump only for package @externals/devDependencies + + + + + +# [3.9.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.58...v3.9.0-beta.59) (2024-07-05) + +**Note:** Version bump only for package @externals/devDependencies + + + + + +# [3.9.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.57...v3.9.0-beta.58) (2024-07-04) + +**Note:** Version bump only for package @externals/devDependencies + + + + + +# [3.9.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.56...v3.9.0-beta.57) (2024-07-02) + +**Note:** Version bump only for package @externals/devDependencies + + + + + +# [3.9.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.55...v3.9.0-beta.56) (2024-07-02) + +**Note:** Version bump only for package @externals/devDependencies + + + + + +# [3.9.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.54...v3.9.0-beta.55) (2024-06-28) + +**Note:** Version bump only for package @externals/devDependencies + + + + + +# [3.9.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.53...v3.9.0-beta.54) (2024-06-28) + +**Note:** Version bump only for package @externals/devDependencies + + + + + +# [3.9.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.52...v3.9.0-beta.53) (2024-06-28) + +**Note:** Version bump only for package @externals/devDependencies + + + + + +# [3.9.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.51...v3.9.0-beta.52) (2024-06-27) + +**Note:** Version bump only for package @externals/devDependencies + + + + + +# [3.9.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.50...v3.9.0-beta.51) (2024-06-27) + +**Note:** Version bump only for package @externals/devDependencies + + + + + +# [3.9.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.49...v3.9.0-beta.50) (2024-06-26) + +**Note:** Version bump only for package @externals/devDependencies + + + + + +# [3.9.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.48...v3.9.0-beta.49) (2024-06-26) + +**Note:** Version bump only for package @externals/devDependencies + + + + + +# [3.9.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.47...v3.9.0-beta.48) (2024-06-25) + +**Note:** Version bump only for package @externals/devDependencies + + + + + +# [3.9.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.46...v3.9.0-beta.47) (2024-06-21) + + +### Bug Fixes + +* Allow the mode setup/creation to be async, and provide a few more values to extension/app config/mode setup. ([#4016](https://github.com/OHIF/Viewers/issues/4016)) ([88575c6](https://github.com/OHIF/Viewers/commit/88575c6c09fd778a31b2f91524163ce65d1639dd)) diff --git a/addOns/externals/devDependencies/package.json b/addOns/externals/devDependencies/package.json new file mode 100644 index 0000000000..ac32a902f5 --- /dev/null +++ b/addOns/externals/devDependencies/package.json @@ -0,0 +1,94 @@ +{ + "name": "@externals/devDependencies", + "description": "External dev dependencies - put dev build dependencies here", + "version": "3.9.0-beta.71", + "license": "MIT", + "private": true, + "engines": { + "node": ">=12", + "yarn": ">=1.19.1" + }, + "dependencies": { + "@babel/runtime": "^7.20.13", + "@kitware/vtk.js": "30.4.1", + "clsx": "^2.1.1", + "core-js": "^3.2.1", + "moment": "^2.9.4" + }, + "peerDependencies": { + "react": "^18.3.1", + "react-dom": "^18.3.1" + }, + "devDependencies": { + "@pmmmwh/react-refresh-webpack-plugin": "^0.5.15", + "@svgr/webpack": "^8.1.0", + "@types/jest": "^27.5.0", + "@typescript-eslint/eslint-plugin": "^6.3.0", + "@typescript-eslint/parser": "^6.3.0", + "autoprefixer": "^10.4.4", + "babel-eslint": "9.x", + "babel-loader": "^8.2.4", + "babel-plugin-module-resolver": "^5.0.0", + "clean-webpack-plugin": "^3.0.0", + "copy-webpack-plugin": "^9.0.1", + "cross-env": "^5.2.0", + "css-loader": "^6.8.1", + "dotenv": "^8.1.0", + "eslint": "^8.39.0", + "eslint-config-prettier": "^7.2.0", + "eslint-config-react-app": "^6.0.0", + "eslint-plugin-cypress": "^2.12.1", + "eslint-plugin-flowtype": "^7.0.0", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-prettier": "^5.0.0", + "eslint-plugin-promise": "^5.2.0", + "eslint-plugin-react": "^7.29.4", + "eslint-plugin-react-hooks": "^4.4.0", + "eslint-plugin-tsdoc": "^0.2.11", + "eslint-webpack-plugin": "^2.5.3", + "execa": "^8.0.1", + "extract-css-chunks-webpack-plugin": "^4.5.4", + "html-webpack-plugin": "^5.3.2", + "husky": "^3.0.0", + "jest": "^29.5.0", + "jest-canvas-mock": "^2.1.0", + "jest-environment-jsdom": "^29.5.0", + "jest-junit": "^6.4.0", + "lerna": "^7.2.0", + "lint-staged": "^9.0.2", + "mini-css-extract-plugin": "^2.1.0", + "optimize-css-assets-webpack-plugin": "^6.0.1", + "postcss": "^8.3.5", + "postcss-import": "^14.0.2", + "postcss-loader": "^6.1.1", + "postcss-preset-env": "^7.4.3", + "prettier": "^3.0.3", + "prettier-plugin-tailwindcss": "^0.5.4", + "react-refresh": "^0.14.2", + "semver": "^7.5.1", + "serve": "^14.2.0", + "shader-loader": "^1.3.1", + "shx": "^0.3.3", + "source-map-loader": "^4.0.1", + "start-server-and-test": "^1.10.0", + "style-loader": "^1.0.0", + "stylus": "^0.59.0", + "stylus-loader": "^7.1.3", + "terser-webpack-plugin": "^5.1.4", + "typescript": "4.6.4", + "unused-webpack-plugin": "2.4.0", + "webpack": "5.89.0", + "webpack-bundle-analyzer": "^4.8.0", + "webpack-cli": "^4.7.2", + "webpack-dev-server": "4.7.3", + "webpack-hot-middleware": "^2.25.0", + "webpack-merge": "^5.7.3", + "workbox-webpack-plugin": "^6.1.5", + "worker-loader": "^3.0.8" + }, + "scripts": { + "build": "Included as direct dependency" + } +} diff --git a/addOns/externals/dicom-microscopy-viewer/CHANGELOG.md b/addOns/externals/dicom-microscopy-viewer/CHANGELOG.md new file mode 100644 index 0000000000..508d8b9417 --- /dev/null +++ b/addOns/externals/dicom-microscopy-viewer/CHANGELOG.md @@ -0,0 +1,203 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# [3.9.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.70...v3.9.0-beta.71) (2024-07-30) + +**Note:** Version bump only for package @externals/dicom-microscopy-viewer + + + + + +# [3.9.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.69...v3.9.0-beta.70) (2024-07-30) + +**Note:** Version bump only for package @externals/dicom-microscopy-viewer + + + + + +# [3.9.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.68...v3.9.0-beta.69) (2024-07-27) + +**Note:** Version bump only for package @externals/dicom-microscopy-viewer + + + + + +# [3.9.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.67...v3.9.0-beta.68) (2024-07-26) + +**Note:** Version bump only for package @externals/dicom-microscopy-viewer + + + + + +# [3.9.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.66...v3.9.0-beta.67) (2024-07-26) + +**Note:** Version bump only for package @externals/dicom-microscopy-viewer + + + + + +# [3.9.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.65...v3.9.0-beta.66) (2024-07-24) + +**Note:** Version bump only for package @externals/dicom-microscopy-viewer + + + + + +# [3.9.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.64...v3.9.0-beta.65) (2024-07-23) + +**Note:** Version bump only for package @externals/dicom-microscopy-viewer + + + + + +# [3.9.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.63...v3.9.0-beta.64) (2024-07-19) + +**Note:** Version bump only for package @externals/dicom-microscopy-viewer + + + + + +# [3.9.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.62...v3.9.0-beta.63) (2024-07-10) + +**Note:** Version bump only for package @externals/dicom-microscopy-viewer + + + + + +# [3.9.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.61...v3.9.0-beta.62) (2024-07-09) + +**Note:** Version bump only for package @externals/dicom-microscopy-viewer + + + + + +# [3.9.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.60...v3.9.0-beta.61) (2024-07-09) + +**Note:** Version bump only for package @externals/dicom-microscopy-viewer + + + + + +# [3.9.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.59...v3.9.0-beta.60) (2024-07-09) + +**Note:** Version bump only for package @externals/dicom-microscopy-viewer + + + + + +# [3.9.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.58...v3.9.0-beta.59) (2024-07-05) + +**Note:** Version bump only for package @externals/dicom-microscopy-viewer + + + + + +# [3.9.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.57...v3.9.0-beta.58) (2024-07-04) + +**Note:** Version bump only for package @externals/dicom-microscopy-viewer + + + + + +# [3.9.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.56...v3.9.0-beta.57) (2024-07-02) + +**Note:** Version bump only for package @externals/dicom-microscopy-viewer + + + + + +# [3.9.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.55...v3.9.0-beta.56) (2024-07-02) + +**Note:** Version bump only for package @externals/dicom-microscopy-viewer + + + + + +# [3.9.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.54...v3.9.0-beta.55) (2024-06-28) + +**Note:** Version bump only for package @externals/dicom-microscopy-viewer + + + + + +# [3.9.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.53...v3.9.0-beta.54) (2024-06-28) + +**Note:** Version bump only for package @externals/dicom-microscopy-viewer + + + + + +# [3.9.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.52...v3.9.0-beta.53) (2024-06-28) + +**Note:** Version bump only for package @externals/dicom-microscopy-viewer + + + + + +# [3.9.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.51...v3.9.0-beta.52) (2024-06-27) + +**Note:** Version bump only for package @externals/dicom-microscopy-viewer + + + + + +# [3.9.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.50...v3.9.0-beta.51) (2024-06-27) + +**Note:** Version bump only for package @externals/dicom-microscopy-viewer + + + + + +# [3.9.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.49...v3.9.0-beta.50) (2024-06-26) + +**Note:** Version bump only for package @externals/dicom-microscopy-viewer + + + + + +# [3.9.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.48...v3.9.0-beta.49) (2024-06-26) + +**Note:** Version bump only for package @externals/dicom-microscopy-viewer + + + + + +# [3.9.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.47...v3.9.0-beta.48) (2024-06-25) + +**Note:** Version bump only for package @externals/dicom-microscopy-viewer + + + + + +# [3.9.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.46...v3.9.0-beta.47) (2024-06-21) + + +### Bug Fixes + +* Allow the mode setup/creation to be async, and provide a few more values to extension/app config/mode setup. ([#4016](https://github.com/OHIF/Viewers/issues/4016)) ([88575c6](https://github.com/OHIF/Viewers/commit/88575c6c09fd778a31b2f91524163ce65d1639dd)) diff --git a/addOns/externals/dicom-microscopy-viewer/package.json b/addOns/externals/dicom-microscopy-viewer/package.json new file mode 100644 index 0000000000..b307d8a912 --- /dev/null +++ b/addOns/externals/dicom-microscopy-viewer/package.json @@ -0,0 +1,9 @@ +{ + "name": "@externals/dicom-microscopy-viewer", + "description": "External reference to dicom-microscopy-viewer", + "version": "3.9.0-beta.71", + "license": "MIT", + "dependencies": { + "dicom-microscopy-viewer": "^0.46.1" + } +} diff --git a/addOns/package.json b/addOns/package.json new file mode 100644 index 0000000000..d3d71f401a --- /dev/null +++ b/addOns/package.json @@ -0,0 +1,51 @@ +{ + "name": "ohif-monorepo-root", + "private": true, + "packageManager": "yarn@1.22.22", + "workspaces": { + "packages": [ + "../platform/i18n", + "../platform/core", + "../platform/ui", + "../platform/ui-next", + "../platform/app", + "../extensions/*", + "../modes/*", + "../addOns/externals/*" + ], + "nohoist": [ + "**/html-minifier-terser" + ] + }, + "scripts": { + "preinstall": "cd .. && node preinstall.js" + }, + "devDependencies": { + "@babel/core": "7.24.7", + "@babel/plugin-proposal-class-properties": "^7.16.7", + "@babel/plugin-proposal-object-rest-spread": "^7.17.3", + "@babel/plugin-proposal-private-methods": "^7.18.6", + "@babel/plugin-proposal-private-property-in-object": "^7.21.11", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-arrow-functions": "^7.16.7", + "@babel/plugin-transform-regenerator": "^7.16.7", + "@babel/plugin-transform-runtime": "7.24.7", + "@babel/plugin-transform-typescript": "^7.13.0", + "@babel/preset-env": "7.24.7", + "@babel/preset-react": "^7.16.7", + "@babel/preset-typescript": "^7.13.0" + }, + "resolutions": { + "**/@babel/runtime": "^7.20.13", + "commander": "8.3.0", + "dcmjs": ">=0.33.0", + "dicomweb-client": ">=0.10.4", + "nth-check": "^2.1.1", + "trim-newlines": "^5.0.0", + "glob-parent": "^6.0.2", + "trim": "^1.0.0", + "package-json": "^8.1.0", + "typescript": "4.6.4", + "sharp": "^0.32.6" + } +} diff --git a/babel.config.js b/babel.config.js index 9fbd804637..f2d7c71b84 100644 --- a/babel.config.js +++ b/babel.config.js @@ -5,23 +5,6 @@ module.exports = { babelrcRoots: ['./platform/*', './extensions/*', './modes/*'], presets: ['@babel/preset-env', '@babel/preset-react', '@babel/preset-typescript'], plugins: [ - [ - 'inline-react-svg', - { - svgo: { - plugins: [ - { - name: 'preset-default', - params: { - overrides: { - removeViewBox: false, - }, - }, - }, - ], - }, - }, - ], ['@babel/plugin-proposal-class-properties', { loose: true }], '@babel/plugin-transform-typescript', ['@babel/plugin-proposal-private-property-in-object', { loose: true }], @@ -49,6 +32,7 @@ module.exports = { '@babel/transform-destructuring', '@babel/plugin-transform-runtime', '@babel/plugin-transform-typescript', + '@babel/plugin-transform-class-static-block', ], }, production: { @@ -67,7 +51,7 @@ module.exports = { '@babel/preset-react', '@babel/preset-typescript', ], - plugins: ['react-hot-loader/babel'], + plugins: ['react-refresh/babel'], ignore: ['**/*.test.jsx', '**/*.test.js', '__snapshots__', '__tests__'], }, }, diff --git a/commit.txt b/commit.txt index a9a5c49fe3..932dd4217e 100644 --- a/commit.txt +++ b/commit.txt @@ -1 +1 @@ -3754c224b4dab28182adb0a41e37d890942144d8 \ No newline at end of file +aa0e5a59379453bb8e6a4f286447576744ea6bf5 \ No newline at end of file diff --git a/extensions/cornerstone-dicom-pmap/.webpack/webpack.dev.js b/extensions/cornerstone-dicom-pmap/.webpack/webpack.dev.js new file mode 100644 index 0000000000..6aea859ca7 --- /dev/null +++ b/extensions/cornerstone-dicom-pmap/.webpack/webpack.dev.js @@ -0,0 +1,12 @@ +const path = require('path'); +const webpackCommon = require('./../../../.webpack/webpack.base.js'); +const SRC_DIR = path.join(__dirname, '../src'); +const DIST_DIR = path.join(__dirname, '../dist'); + +const ENTRY = { + app: `${SRC_DIR}/index.tsx`, +}; + +module.exports = (env, argv) => { + return webpackCommon(env, argv, { SRC_DIR, DIST_DIR, ENTRY }); +}; diff --git a/extensions/cornerstone-dicom-pmap/.webpack/webpack.prod.js b/extensions/cornerstone-dicom-pmap/.webpack/webpack.prod.js new file mode 100644 index 0000000000..0ae7d6c2db --- /dev/null +++ b/extensions/cornerstone-dicom-pmap/.webpack/webpack.prod.js @@ -0,0 +1,54 @@ +const webpack = require('webpack'); +const { merge } = require('webpack-merge'); +const path = require('path'); +const webpackCommon = require('./../../../.webpack/webpack.base.js'); +const MiniCssExtractPlugin = require('mini-css-extract-plugin'); + +const pkg = require('./../package.json'); + +const ROOT_DIR = path.join(__dirname, '../'); +const SRC_DIR = path.join(__dirname, '../src'); +const DIST_DIR = path.join(__dirname, '../dist'); +const ENTRY = { + app: `${SRC_DIR}/index.tsx`, +}; + +const outputName = `ohif-${pkg.name.split('/').pop()}`; + +module.exports = (env, argv) => { + const commonConfig = webpackCommon(env, argv, { SRC_DIR, DIST_DIR, ENTRY }); + + return merge(commonConfig, { + stats: { + colors: true, + hash: true, + timings: true, + assets: true, + chunks: false, + chunkModules: false, + modules: false, + children: false, + warnings: true, + }, + optimization: { + minimize: true, + sideEffects: true, + }, + output: { + path: ROOT_DIR, + library: 'ohif-extension-cornerstone-dicom-pmap', + libraryTarget: 'umd', + filename: pkg.main, + }, + externals: [/\b(vtk.js)/, /\b(dcmjs)/, /\b(gl-matrix)/, /^@ohif/, /^@cornerstonejs/], + plugins: [ + new webpack.optimize.LimitChunkCountPlugin({ + maxChunks: 1, + }), + new MiniCssExtractPlugin({ + filename: `./dist/${outputName}.css`, + chunkFilename: `./dist/${outputName}.css`, + }), + ], + }); +}; diff --git a/extensions/cornerstone-dicom-pmap/CHANGELOG.md b/extensions/cornerstone-dicom-pmap/CHANGELOG.md new file mode 100644 index 0000000000..a7dac50a79 --- /dev/null +++ b/extensions/cornerstone-dicom-pmap/CHANGELOG.md @@ -0,0 +1,51 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# [3.9.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.70...v3.9.0-beta.71) (2024-07-30) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap + + + + + +# [3.9.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.69...v3.9.0-beta.70) (2024-07-30) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap + + + + + +# [3.9.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.68...v3.9.0-beta.69) (2024-07-27) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap + + + + + +# [3.9.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.67...v3.9.0-beta.68) (2024-07-26) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap + + + + + +# [3.9.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.66...v3.9.0-beta.67) (2024-07-26) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap + + + + + +# [3.9.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.65...v3.9.0-beta.66) (2024-07-24) + + +### Features + +* **pmap:** added support for parametric map ([#4284](https://github.com/OHIF/Viewers/issues/4284)) ([fc0064f](https://github.com/OHIF/Viewers/commit/fc0064fd9d8cdc8fde81b81f0e71fd5d077ca22b)) diff --git a/extensions/cornerstone-dicom-pmap/LICENSE b/extensions/cornerstone-dicom-pmap/LICENSE new file mode 100644 index 0000000000..983c5ef342 --- /dev/null +++ b/extensions/cornerstone-dicom-pmap/LICENSE @@ -0,0 +1,20 @@ +MIT License + +Copyright (c) 2023 Open Health Imaging Foundation + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/extensions/cornerstone-dicom-pmap/README.md b/extensions/cornerstone-dicom-pmap/README.md new file mode 100644 index 0000000000..af903360c6 --- /dev/null +++ b/extensions/cornerstone-dicom-pmap/README.md @@ -0,0 +1,12 @@ +# dicom-pmap +## Description + +DICOM PMAP read workflow. This extension will allow you to load a DICOM Parametric +Map image and display it on OHIF. + +## Author + +OHIF + +## License +MIT diff --git a/extensions/cornerstone-dicom-pmap/babel.config.js b/extensions/cornerstone-dicom-pmap/babel.config.js new file mode 100644 index 0000000000..e514425519 --- /dev/null +++ b/extensions/cornerstone-dicom-pmap/babel.config.js @@ -0,0 +1,44 @@ +module.exports = { + plugins: ['@babel/plugin-proposal-class-properties'], + env: { + test: { + presets: [ + [ + // TODO: https://babeljs.io/blog/2019/03/19/7.4.0#migration-from-core-js-2 + '@babel/preset-env', + { + modules: 'commonjs', + debug: false, + }, + '@babel/preset-typescript', + ], + '@babel/preset-react', + ], + plugins: [ + '@babel/plugin-proposal-object-rest-spread', + '@babel/plugin-syntax-dynamic-import', + '@babel/plugin-transform-regenerator', + '@babel/plugin-transform-runtime', + ], + }, + production: { + presets: [ + // WebPack handles ES6 --> Target Syntax + ['@babel/preset-env', { modules: false }], + '@babel/preset-react', + '@babel/preset-typescript', + ], + ignore: ['**/*.test.jsx', '**/*.test.js', '__snapshots__', '__tests__'], + }, + development: { + presets: [ + // WebPack handles ES6 --> Target Syntax + ['@babel/preset-env', { modules: false }], + '@babel/preset-react', + '@babel/preset-typescript', + ], + plugins: ['react-hot-loader/babel'], + ignore: ['**/*.test.jsx', '**/*.test.js', '__snapshots__', '__tests__'], + }, + }, +}; diff --git a/extensions/cornerstone-dicom-pmap/package.json b/extensions/cornerstone-dicom-pmap/package.json new file mode 100644 index 0000000000..5dacba009c --- /dev/null +++ b/extensions/cornerstone-dicom-pmap/package.json @@ -0,0 +1,54 @@ +{ + "name": "@ohif/extension-cornerstone-dicom-pmap", + "version": "3.9.0-beta.71", + "description": "DICOM Parametric Map read workflow", + "author": "OHIF", + "license": "MIT", + "main": "dist/ohif-extension-cornerstone-dicom-pmap.umd.js", + "module": "src/index.tsx", + "files": [ + "dist/**", + "public/**", + "README.md" + ], + "repository": "OHIF/Viewers", + "keywords": [ + "ohif-extension" + ], + "publishConfig": { + "access": "public" + }, + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1.18.0" + }, + "scripts": { + "clean": "shx rm -rf dist", + "clean:deep": "yarn run clean && shx rm -rf node_modules", + "dev": "cross-env NODE_ENV=development webpack --config .webpack/webpack.dev.js --watch --output-pathinfo", + "dev:dicom-pmap": "yarn run dev", + "build": "cross-env NODE_ENV=production webpack --config .webpack/webpack.prod.js", + "build:package-1": "yarn run build", + "start": "yarn run dev" + }, + "peerDependencies": { + "@ohif/core": "3.9.0-beta.71", + "@ohif/extension-cornerstone": "3.9.0-beta.71", + "@ohif/extension-default": "3.9.0-beta.71", + "@ohif/i18n": "3.9.0-beta.71", + "prop-types": "^15.6.2", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-i18next": "^12.2.2", + "react-router": "^6.8.1", + "react-router-dom": "^6.8.1" + }, + "dependencies": { + "@babel/runtime": "^7.20.13", + "@cornerstonejs/adapters": "^1.77.6", + "@cornerstonejs/core": "^1.77.6", + "@kitware/vtk.js": "30.4.1", + "react-color": "^2.19.3" + } +} diff --git a/extensions/cornerstone-dicom-pmap/src/getSopClassHandlerModule.ts b/extensions/cornerstone-dicom-pmap/src/getSopClassHandlerModule.ts new file mode 100644 index 0000000000..6f446b0d09 --- /dev/null +++ b/extensions/cornerstone-dicom-pmap/src/getSopClassHandlerModule.ts @@ -0,0 +1,217 @@ +import { utils } from '@ohif/core'; +import { metaData, cache, utilities as csUtils, volumeLoader } from '@cornerstonejs/core'; +import { adaptersPMAP } from '@cornerstonejs/adapters'; +import { SOPClassHandlerId } from './id'; +import { dicomLoaderService } from '@ohif/extension-cornerstone'; + +const VOLUME_LOADER_SCHEME = 'cornerstoneStreamingImageVolume'; +const sopClassUids = ['1.2.840.10008.5.1.4.1.1.30']; + +function _getDisplaySetsFromSeries( + instances, + servicesManager: AppTypes.ServicesManager, + extensionManager +) { + const instance = instances[0]; + + const { + StudyInstanceUID, + SeriesInstanceUID, + SOPInstanceUID, + SeriesDescription, + SeriesNumber, + SeriesDate, + SOPClassUID, + wadoRoot, + wadoUri, + wadoUriRoot, + } = instance; + + const displaySet = { + // Parametric map use to have the same modality as its referenced volume but + // "PMAP" is used in the viewer even though this is not a valid DICOM modality + Modality: 'PMAP', + isReconstructable: true, // by default for now + displaySetInstanceUID: `pmap.${utils.guid()}`, + SeriesDescription, + SeriesNumber, + SeriesDate, + SOPInstanceUID, + SeriesInstanceUID, + StudyInstanceUID, + SOPClassHandlerId, + SOPClassUID, + referencedImages: null, + referencedSeriesInstanceUID: null, + referencedDisplaySetInstanceUID: null, + referencedVolumeURI: null, + referencedVolumeId: null, + isDerivedDisplaySet: true, + loadStatus: { + loading: false, + loaded: false, + }, + sopClassUids, + instance, + instances: [instance], + wadoRoot, + wadoUriRoot, + wadoUri, + isOverlayDisplaySet: true, + }; + + const referencedSeriesSequence = instance.ReferencedSeriesSequence; + + if (!referencedSeriesSequence) { + console.error('ReferencedSeriesSequence is missing for the parametric map'); + return; + } + + const referencedSeries = referencedSeriesSequence[0] || referencedSeriesSequence; + + displaySet.referencedImages = instance.ReferencedSeriesSequence.ReferencedInstanceSequence; + displaySet.referencedSeriesInstanceUID = referencedSeries.SeriesInstanceUID; + + // Does not get the referenced displaySet during parametric displaySet creation + // because it is still not available (getDisplaySetByUID returns `undefined`). + displaySet.getReferenceDisplaySet = () => { + const { displaySetService } = servicesManager.services; + + if (displaySet.referencedDisplaySetInstanceUID) { + return displaySetService.getDisplaySetByUID(displaySet.referencedDisplaySetInstanceUID); + } + + const referencedDisplaySets = displaySetService.getDisplaySetsForSeries( + displaySet.referencedSeriesInstanceUID + ); + + if (!referencedDisplaySets || referencedDisplaySets.length === 0) { + throw new Error('Referenced displaySet is missing for the parametric map'); + } + + const referencedDisplaySet = referencedDisplaySets[0]; + + displaySet.referencedDisplaySetInstanceUID = referencedDisplaySet.displaySetInstanceUID; + + return referencedDisplaySet; + }; + + // Does not get the referenced volumeId during parametric displaySet creation because the + // referenced displaySet is still not avaialble (getDisplaySetByUID returns `undefined`). + displaySet.getReferencedVolumeId = () => { + if (displaySet.referencedVolumeId) { + return displaySet.referencedVolumeId; + } + + const referencedDisplaySet = displaySet.getReferenceDisplaySet(); + const referencedVolumeURI = referencedDisplaySet.displaySetInstanceUID; + const referencedVolumeId = `${VOLUME_LOADER_SCHEME}:${referencedVolumeURI}`; + + displaySet.referencedVolumeURI = referencedVolumeURI; + displaySet.referencedVolumeId = referencedVolumeId; + + return referencedVolumeId; + }; + + displaySet.load = async ({ headers }) => + await _load(displaySet, servicesManager, extensionManager, headers); + + return [displaySet]; +} + +async function _load( + displaySet, + servicesManager: AppTypes.ServicesManager, + extensionManager, + headers +) { + const volumeId = `${VOLUME_LOADER_SCHEME}:${displaySet.displaySetInstanceUID}`; + const volumeLoadObject = cache.getVolumeLoadObject(volumeId); + + if (volumeLoadObject) { + return volumeLoadObject.promise; + } + + displaySet.loadStatus.loading = true; + + // We don't want to fire multiple loads, so we'll wait for the first to finish + // and also return the same promise to any other callers. + // loadPromises[SOPInstanceUID] = new Promise(async (resolve, reject) => { + const promise = _loadParametricMap({ + extensionManager, + displaySet, + headers, + }); + + cache.putVolumeLoadObject(volumeId, { promise }).catch(err => { + throw err; + }); + + promise + .then(() => { + displaySet.loadStatus.loading = false; + displaySet.loadStatus.loaded = true; + }) + .catch(err => { + displaySet.loadStatus.loading = false; + throw err; + }); + + return promise; +} + +async function _loadParametricMap({ extensionManager, displaySet, headers }: withAppTypes) { + const arrayBuffer = await dicomLoaderService.findDicomDataPromise(displaySet, null, headers); + const referencedVolumeId = displaySet.getReferencedVolumeId(); + const cachedReferencedVolume = cache.getVolume(referencedVolumeId); + + // Parametric map can be loaded only if its referenced volume exists otherwise it will fail + if (!cachedReferencedVolume) { + throw new Error( + 'Referenced Volume is missing for the PMAP, and stack viewport PMAP is not supported yet' + ); + } + + const { imageIds } = cachedReferencedVolume; + const results = await adaptersPMAP.Cornerstone3D.ParametricMap.generateToolState( + imageIds, + arrayBuffer, + metaData + ); + const { pixelData } = results; + const TypedArrayConstructor = pixelData.constructor; + const paramMapId = displaySet.displaySetInstanceUID; + + const derivedVolume = await volumeLoader.createAndCacheDerivedVolume(referencedVolumeId, { + volumeId: paramMapId, + targetBuffer: { + type: TypedArrayConstructor.name, + }, + }); + + derivedVolume.getScalarData().set(pixelData); + + const range = derivedVolume.imageData.getPointData().getScalars().getRange(); + const windowLevel = csUtils.windowLevel.toWindowLevel(range[0], range[1]); + + derivedVolume.metadata.voiLut = [windowLevel]; + derivedVolume.loadStatus = { loaded: true }; + + return derivedVolume; +} + +function getSopClassHandlerModule({ servicesManager, extensionManager }) { + const getDisplaySetsFromSeries = instances => { + return _getDisplaySetsFromSeries(instances, servicesManager, extensionManager); + }; + + return [ + { + name: 'dicom-pmap', + sopClassUids, + getDisplaySetsFromSeries, + }, + ]; +} + +export default getSopClassHandlerModule; diff --git a/extensions/cornerstone-dicom-pmap/src/id.js b/extensions/cornerstone-dicom-pmap/src/id.js new file mode 100644 index 0000000000..4ec5d59966 --- /dev/null +++ b/extensions/cornerstone-dicom-pmap/src/id.js @@ -0,0 +1,7 @@ +import packageJson from '../package.json'; + +const id = packageJson.name; +const SOPClassHandlerName = 'dicom-pmap'; +const SOPClassHandlerId = `${id}.sopClassHandlerModule.${SOPClassHandlerName}`; + +export { id, SOPClassHandlerId, SOPClassHandlerName }; diff --git a/extensions/cornerstone-dicom-pmap/src/index.tsx b/extensions/cornerstone-dicom-pmap/src/index.tsx new file mode 100644 index 0000000000..916f8a07f9 --- /dev/null +++ b/extensions/cornerstone-dicom-pmap/src/index.tsx @@ -0,0 +1,39 @@ +import { id } from './id'; +import React from 'react'; +import getSopClassHandlerModule from './getSopClassHandlerModule'; + +const Component = React.lazy(() => { + return import(/* webpackPrefetch: true */ './viewports/OHIFCornerstonePMAPViewport'); +}); + +const OHIFCornerstonePMAPViewport = props => { + return ( + Loading...}> + + + ); +}; + +/** + * You can remove any of the following modules if you don't need them. + */ +const extension = { + id, + getViewportModule({ servicesManager, extensionManager, commandsManager }) { + const ExtendedOHIFCornerstonePMAPViewport = props => { + return ( + + ); + }; + + return [{ name: 'dicom-pmap', component: ExtendedOHIFCornerstonePMAPViewport }]; + }, + getSopClassHandlerModule, +}; + +export default extension; diff --git a/extensions/cornerstone-dicom-pmap/src/utils/initPMAPToolGroup.ts b/extensions/cornerstone-dicom-pmap/src/utils/initPMAPToolGroup.ts new file mode 100644 index 0000000000..6f0aa581ea --- /dev/null +++ b/extensions/cornerstone-dicom-pmap/src/utils/initPMAPToolGroup.ts @@ -0,0 +1,6 @@ +function createPMAPToolGroupAndAddTools(ToolGroupService, customizationService, toolGroupId) { + const { tools } = customizationService.get('cornerstone.overlayViewportTools') ?? {}; + return ToolGroupService.createToolGroupAndAddTools(toolGroupId, tools); +} + +export default createPMAPToolGroupAndAddTools; diff --git a/extensions/cornerstone-dicom-pmap/src/viewports/OHIFCornerstonePMAPViewport.tsx b/extensions/cornerstone-dicom-pmap/src/viewports/OHIFCornerstonePMAPViewport.tsx new file mode 100644 index 0000000000..9e0ee919f9 --- /dev/null +++ b/extensions/cornerstone-dicom-pmap/src/viewports/OHIFCornerstonePMAPViewport.tsx @@ -0,0 +1,163 @@ +import PropTypes from 'prop-types'; +import React, { useCallback, useEffect, useRef } from 'react'; +import { useViewportGrid } from '@ohif/ui'; +import createPMAPToolGroupAndAddTools from '../utils/initPMAPToolGroup'; + +const PMAP_TOOLGROUP_BASE_NAME = 'PMAPToolGroup'; + +function OHIFCornerstonePMAPViewport(props: withAppTypes) { + const { displaySets, viewportOptions, displaySetOptions, servicesManager, extensionManager } = + props; + const viewportId = viewportOptions.viewportId; + const { displaySetService, toolGroupService, customizationService } = servicesManager.services; + const toolGroupId = `${PMAP_TOOLGROUP_BASE_NAME}-${viewportId}`; + + // PMAP viewport will always have a single display set + if (displaySets.length !== 1) { + throw new Error('PMAP viewport must have a single display set'); + } + + const pmapDisplaySet = displaySets[0]; + const [viewportGrid, viewportGridService] = useViewportGrid(); + const referencedDisplaySetRef = useRef(null); + const { viewports, activeViewportId } = viewportGrid; + const referencedDisplaySet = pmapDisplaySet.getReferenceDisplaySet(); + const referencedDisplaySetMetadata = _getReferencedDisplaySetMetadata( + referencedDisplaySet, + pmapDisplaySet + ); + + referencedDisplaySetRef.current = { + displaySet: referencedDisplaySet, + metadata: referencedDisplaySetMetadata, + }; + + const getCornerstoneViewport = useCallback(() => { + const { displaySet: referencedDisplaySet } = referencedDisplaySetRef.current; + const { component: Component } = extensionManager.getModuleEntry( + '@ohif/extension-cornerstone.viewportModule.cornerstone' + ); + + displaySetOptions.unshift({}); + const [pmapDisplaySetOptions] = displaySetOptions; + + // Make sure `options` exists + pmapDisplaySetOptions.options = pmapDisplaySetOptions.options ?? {}; + + Object.assign(pmapDisplaySetOptions.options, { + colormap: { + name: 'rainbow', + opacity: [ + { value: 0, opacity: 0.5 }, + { value: 1, opacity: 1 }, + ], + }, + }); + + return ( + + ); + }, [ + extensionManager, + displaySetOptions, + props, + pmapDisplaySet, + toolGroupId, + viewportOptions.orientation, + viewportOptions.viewportId, + ]); + + // Cleanup the PMAP viewport when the viewport is destroyed + useEffect(() => { + const onDisplaySetsRemovedSubscription = displaySetService.subscribe( + displaySetService.EVENTS.DISPLAY_SETS_REMOVED, + ({ displaySetInstanceUIDs }) => { + const activeViewport = viewports.get(activeViewportId); + if (displaySetInstanceUIDs.includes(activeViewport.displaySetInstanceUID)) { + viewportGridService.setDisplaySetsForViewport({ + viewportId: activeViewportId, + displaySetInstanceUIDs: [], + }); + } + } + ); + + return () => { + onDisplaySetsRemovedSubscription.unsubscribe(); + }; + }, [activeViewportId, displaySetService, viewportGridService, viewports]); + + useEffect(() => { + let toolGroup = toolGroupService.getToolGroup(toolGroupId); + + if (toolGroup) { + return; + } + + // This creates a custom tool group which has the lifetime of this view only + toolGroup = createPMAPToolGroupAndAddTools(toolGroupService, customizationService, toolGroupId); + + return () => toolGroupService.destroyToolGroup(toolGroupId); + }, [customizationService, toolGroupId, toolGroupService]); + + return ( + <> +
+ {getCornerstoneViewport()} +
+ + ); +} + +OHIFCornerstonePMAPViewport.propTypes = { + displaySets: PropTypes.arrayOf(PropTypes.object), + viewportId: PropTypes.string.isRequired, + dataSource: PropTypes.object, + children: PropTypes.node, +}; + +function _getReferencedDisplaySetMetadata(referencedDisplaySet, pmapDisplaySet) { + const { SharedFunctionalGroupsSequence } = pmapDisplaySet.instance; + + const SharedFunctionalGroup = Array.isArray(SharedFunctionalGroupsSequence) + ? SharedFunctionalGroupsSequence[0] + : SharedFunctionalGroupsSequence; + + const { PixelMeasuresSequence } = SharedFunctionalGroup; + + const PixelMeasures = Array.isArray(PixelMeasuresSequence) + ? PixelMeasuresSequence[0] + : PixelMeasuresSequence; + + const { SpacingBetweenSlices, SliceThickness } = PixelMeasures; + + const image0 = referencedDisplaySet.images[0]; + const referencedDisplaySetMetadata = { + PatientID: image0.PatientID, + PatientName: image0.PatientName, + PatientSex: image0.PatientSex, + PatientAge: image0.PatientAge, + SliceThickness: image0.SliceThickness || SliceThickness, + StudyDate: image0.StudyDate, + SeriesDescription: image0.SeriesDescription, + SeriesInstanceUID: image0.SeriesInstanceUID, + SeriesNumber: image0.SeriesNumber, + ManufacturerModelName: image0.ManufacturerModelName, + SpacingBetweenSlices: image0.SpacingBetweenSlices || SpacingBetweenSlices, + }; + + return referencedDisplaySetMetadata; +} + +export default OHIFCornerstonePMAPViewport; diff --git a/extensions/cornerstone-dicom-rt/CHANGELOG.md b/extensions/cornerstone-dicom-rt/CHANGELOG.md index 0243aed726..bb8eaeb61c 100644 --- a/extensions/cornerstone-dicom-rt/CHANGELOG.md +++ b/extensions/cornerstone-dicom-rt/CHANGELOG.md @@ -3,6 +3,693 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.9.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.70...v3.9.0-beta.71) (2024-07-30) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.69...v3.9.0-beta.70) (2024-07-30) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.68...v3.9.0-beta.69) (2024-07-27) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.67...v3.9.0-beta.68) (2024-07-26) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.66...v3.9.0-beta.67) (2024-07-26) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.65...v3.9.0-beta.66) (2024-07-24) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.64...v3.9.0-beta.65) (2024-07-23) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.63...v3.9.0-beta.64) (2024-07-19) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.62...v3.9.0-beta.63) (2024-07-10) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.61...v3.9.0-beta.62) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.60...v3.9.0-beta.61) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.59...v3.9.0-beta.60) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.58...v3.9.0-beta.59) (2024-07-05) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.57...v3.9.0-beta.58) (2024-07-04) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.56...v3.9.0-beta.57) (2024-07-02) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.55...v3.9.0-beta.56) (2024-07-02) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.54...v3.9.0-beta.55) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.53...v3.9.0-beta.54) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.52...v3.9.0-beta.53) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.51...v3.9.0-beta.52) (2024-06-27) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.50...v3.9.0-beta.51) (2024-06-27) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.49...v3.9.0-beta.50) (2024-06-26) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.48...v3.9.0-beta.49) (2024-06-26) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.47...v3.9.0-beta.48) (2024-06-25) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.46...v3.9.0-beta.47) (2024-06-21) + + +### Bug Fixes + +* Allow the mode setup/creation to be async, and provide a few more values to extension/app config/mode setup. ([#4016](https://github.com/OHIF/Viewers/issues/4016)) ([88575c6](https://github.com/OHIF/Viewers/commit/88575c6c09fd778a31b2f91524163ce65d1639dd)) + + + + + +# [3.9.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.45...v3.9.0-beta.46) (2024-06-18) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.44...v3.9.0-beta.45) (2024-06-18) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.43...v3.9.0-beta.44) (2024-06-17) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.42...v3.9.0-beta.43) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.41...v3.9.0-beta.42) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.40...v3.9.0-beta.41) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.39...v3.9.0-beta.40) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.38...v3.9.0-beta.39) (2024-06-08) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.37...v3.9.0-beta.38) (2024-06-07) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.36...v3.9.0-beta.37) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.35...v3.9.0-beta.36) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.34...v3.9.0-beta.35) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.33...v3.9.0-beta.34) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.32...v3.9.0-beta.33) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.31...v3.9.0-beta.32) (2024-05-31) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.30...v3.9.0-beta.31) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.29...v3.9.0-beta.30) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.28...v3.9.0-beta.29) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.27...v3.9.0-beta.28) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.26...v3.9.0-beta.27) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.25...v3.9.0-beta.26) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.24...v3.9.0-beta.25) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.23...v3.9.0-beta.24) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.22...v3.9.0-beta.23) (2024-05-28) + + +### Bug Fixes + +* **rt:** dont convert to volume for RTSTRUCT ([#4157](https://github.com/OHIF/Viewers/issues/4157)) ([7745c09](https://github.com/OHIF/Viewers/commit/7745c092bb3edf0090f32fbbbae2f0776128d5a2)) + + + + + +# [3.9.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.21...v3.9.0-beta.22) (2024-05-27) + + +### Features + +* **ui:** move to React 18 and base for using shadcn/ui ([#4174](https://github.com/OHIF/Viewers/issues/4174)) ([70f2c79](https://github.com/OHIF/Viewers/commit/70f2c797f42af603d7ea0eb8d23b4103aba66f77)) + + + + + +# [3.9.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.20...v3.9.0-beta.21) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.19...v3.9.0-beta.20) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.18...v3.9.0-beta.19) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.17...v3.9.0-beta.18) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.16...v3.9.0-beta.17) (2024-05-23) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.15...v3.9.0-beta.16) (2024-05-23) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.14...v3.9.0-beta.15) (2024-05-22) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.13...v3.9.0-beta.14) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.12...v3.9.0-beta.13) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.11...v3.9.0-beta.12) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.10...v3.9.0-beta.11) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.9...v3.9.0-beta.10) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.8...v3.9.0-beta.9) (2024-05-17) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.7...v3.9.0-beta.8) (2024-05-16) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.6...v3.9.0-beta.7) (2024-05-15) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.5...v3.9.0-beta.6) (2024-05-15) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.4...v3.9.0-beta.5) (2024-05-14) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.3...v3.9.0-beta.4) (2024-05-14) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.2...v3.9.0-beta.3) (2024-05-08) + + +### Features + +* **typings:** Enhance typing support with withAppTypes and custom services throughout OHIF ([#4090](https://github.com/OHIF/Viewers/issues/4090)) ([374065b](https://github.com/OHIF/Viewers/commit/374065bc3bad9d212f9817a8d41546cc64cfabfb)) + + + + + +# [3.9.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.1...v3.9.0-beta.2) (2024-05-06) + + +### Bug Fixes + +* **bugs:** enhancements and bugs in several areas ([#4086](https://github.com/OHIF/Viewers/issues/4086)) ([730f434](https://github.com/OHIF/Viewers/commit/730f4349100f21b4489a21707dbb2dca9dbfbba2)) + + + + + +# [3.9.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.0...v3.9.0-beta.1) (2024-05-06) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.9.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.94...v3.9.0-beta.0) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.8.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0-beta.94) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + +# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt + + + + + # [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17) **Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt diff --git a/extensions/cornerstone-dicom-rt/babel.config.js b/extensions/cornerstone-dicom-rt/babel.config.js index a38ddda212..9705ae6f28 100644 --- a/extensions/cornerstone-dicom-rt/babel.config.js +++ b/extensions/cornerstone-dicom-rt/babel.config.js @@ -1,5 +1,5 @@ module.exports = { - plugins: ['inline-react-svg', '@babel/plugin-proposal-class-properties'], + plugins: ['@babel/plugin-proposal-class-properties'], env: { test: { presets: [ @@ -37,7 +37,7 @@ module.exports = { '@babel/preset-react', '@babel/preset-typescript', ], - plugins: ['react-hot-loader/babel'], + plugins: ['react-refresh/babel'], ignore: ['**/*.test.jsx', '**/*.test.js', '__snapshots__', '__tests__'], }, }, diff --git a/extensions/cornerstone-dicom-rt/package.json b/extensions/cornerstone-dicom-rt/package.json index f399c3c3a8..0953af2ea1 100644 --- a/extensions/cornerstone-dicom-rt/package.json +++ b/extensions/cornerstone-dicom-rt/package.json @@ -1,6 +1,6 @@ { "name": "@ohif/extension-cornerstone-dicom-rt", - "version": "3.8.0-beta.82", + "version": "3.9.0-beta.71", "description": "DICOM RT read workflow", "author": "OHIF", "license": "MIT", @@ -33,16 +33,16 @@ "start": "yarn run dev" }, "peerDependencies": { - "@ohif/core": "3.8.0-beta.82", - "@ohif/extension-cornerstone": "3.8.0-beta.82", - "@ohif/extension-default": "3.8.0-beta.82", - "@ohif/i18n": "3.8.0-beta.82", + "@ohif/core": "3.9.0-beta.71", + "@ohif/extension-cornerstone": "3.9.0-beta.71", + "@ohif/extension-default": "3.9.0-beta.71", + "@ohif/i18n": "3.9.0-beta.71", "prop-types": "^15.6.2", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "react": "^18.3.1", + "react-dom": "^18.3.1", "react-i18next": "^10.11.0", - "react-router": "^6.3.0", - "react-router-dom": "^6.3.0" + "react-router": "^6.23.1", + "react-router-dom": "^6.23.1" }, "dependencies": { "@babel/runtime": "^7.20.13", diff --git a/extensions/cornerstone-dicom-rt/src/getSopClassHandlerModule.js b/extensions/cornerstone-dicom-rt/src/getSopClassHandlerModule.ts similarity index 91% rename from extensions/cornerstone-dicom-rt/src/getSopClassHandlerModule.js rename to extensions/cornerstone-dicom-rt/src/getSopClassHandlerModule.ts index a7a232f198..6f65a1bf51 100644 --- a/extensions/cornerstone-dicom-rt/src/getSopClassHandlerModule.js +++ b/extensions/cornerstone-dicom-rt/src/getSopClassHandlerModule.ts @@ -5,9 +5,13 @@ import loadRTStruct from './loadRTStruct'; const sopClassUids = ['1.2.840.10008.5.1.4.1.1.481.3']; -let loadPromises = {}; +const loadPromises = {}; -function _getDisplaySetsFromSeries(instances, servicesManager, extensionManager) { +function _getDisplaySetsFromSeries( + instances, + servicesManager: AppTypes.ServicesManager, + extensionManager +) { const instance = instances[0]; const { @@ -69,8 +73,8 @@ function _getDisplaySetsFromSeries(instances, servicesManager, extensionManager) displaySet.referencedSeriesInstanceUID = referencedSeries.SeriesInstanceUID; displaySet.getReferenceDisplaySet = () => { - const { DisplaySetService } = servicesManager.services; - const referencedDisplaySets = DisplaySetService.getDisplaySetsForSeries( + const { displaySetService } = servicesManager.services; + const referencedDisplaySets = displaySetService.getDisplaySetsForSeries( displaySet.referencedSeriesInstanceUID ); @@ -90,7 +94,7 @@ function _getDisplaySetsFromSeries(instances, servicesManager, extensionManager) return [displaySet]; } -function _load(rtDisplaySet, servicesManager, extensionManager, headers) { +function _load(rtDisplaySet, servicesManager: AppTypes.ServicesManager, extensionManager, headers) { const { SOPInstanceUID } = rtDisplaySet; const { segmentationService } = servicesManager.services; if ( @@ -168,7 +172,10 @@ function _deriveReferencedSeriesSequenceFromFrameOfReferenceSequence( return ReferencedSeriesSequence; } -function _segmentationExistsInCache(rtDisplaySet, segmentationService) { +function _segmentationExistsInCache( + rtDisplaySet, + segmentationService: AppTypes.SegmentationService +) { // Todo: fix this return false; // This should be abstracted with the CornerstoneCacheService diff --git a/extensions/cornerstone-dicom-rt/src/utils/promptHydrateRT.ts b/extensions/cornerstone-dicom-rt/src/utils/promptHydrateRT.ts index 2baa0305b3..972f62f25c 100644 --- a/extensions/cornerstone-dicom-rt/src/utils/promptHydrateRT.ts +++ b/extensions/cornerstone-dicom-rt/src/utils/promptHydrateRT.ts @@ -13,39 +13,46 @@ function promptHydrateRT({ toolGroupId = 'default', preHydrateCallbacks, hydrateRTDisplaySet, -}) { +}: withAppTypes) { const { uiViewportDialogService } = servicesManager.services; - + const extensionManager = servicesManager._extensionManager; + const appConfig = extensionManager._appConfig; return new Promise(async function (resolve, reject) { - const promptResult = await _askHydrate(uiViewportDialogService, viewportId); + const promptResult = appConfig?.disableConfirmationPrompts + ? RESPONSE.HYDRATE_SEG + : await _askHydrate(uiViewportDialogService, viewportId); if (promptResult === RESPONSE.HYDRATE_SEG) { preHydrateCallbacks?.forEach(callback => { callback(); }); - const isHydrated = await hydrateRTDisplaySet({ - rtDisplaySet, - viewportId, - toolGroupId, - servicesManager, - }); + window.setTimeout(async () => { + const isHydrated = await hydrateRTDisplaySet({ + rtDisplaySet, + viewportId, + toolGroupId, + servicesManager, + }); - resolve(isHydrated); + resolve(isHydrated); + }, 0); } }); } -function _askHydrate(uiViewportDialogService, viewportId) { +function _askHydrate(uiViewportDialogService: AppTypes.UIViewportDialogService, viewportId) { return new Promise(function (resolve, reject) { const message = 'Do you want to open this Segmentation?'; const actions = [ { + id: 'no-hydrate', type: ButtonEnums.type.secondary, text: 'No', value: RESPONSE.CANCEL, }, { + id: 'yes-hydrate', type: ButtonEnums.type.primary, text: 'Yes', value: RESPONSE.HYDRATE_SEG, @@ -57,6 +64,7 @@ function _askHydrate(uiViewportDialogService, viewportId) { }; uiViewportDialogService.show({ + id: 'promptHydrateRT', viewportId, type: 'info', message, diff --git a/extensions/cornerstone-dicom-rt/src/viewports/OHIFCornerstoneRTViewport.tsx b/extensions/cornerstone-dicom-rt/src/viewports/OHIFCornerstoneRTViewport.tsx index 1b2b42b22a..ab8ee32a59 100644 --- a/extensions/cornerstone-dicom-rt/src/viewports/OHIFCornerstoneRTViewport.tsx +++ b/extensions/cornerstone-dicom-rt/src/viewports/OHIFCornerstoneRTViewport.tsx @@ -8,7 +8,7 @@ import createRTToolGroupAndAddTools from '../utils/initRTToolGroup'; const RT_TOOLGROUP_BASE_NAME = 'RTToolGroup'; -function OHIFCornerstoneRTViewport(props) { +function OHIFCornerstoneRTViewport(props: withAppTypes) { const { children, displaySets, @@ -111,7 +111,7 @@ function OHIFCornerstoneRTViewport(props) { {...props} displaySets={[referencedDisplaySet, rtDisplaySet]} viewportOptions={{ - viewportType: 'volume', + viewportType: 'stack', toolGroupId: toolGroupId, orientation: viewportOptions.orientation, viewportId: viewportOptions.viewportId, @@ -358,11 +358,6 @@ OHIFCornerstoneRTViewport.propTypes = { viewportId: PropTypes.string.isRequired, dataSource: PropTypes.object, children: PropTypes.node, - customProps: PropTypes.object, -}; - -OHIFCornerstoneRTViewport.defaultProps = { - customProps: {}, }; function _getReferencedDisplaySetMetadata(referencedDisplaySet) { diff --git a/extensions/cornerstone-dicom-seg/CHANGELOG.md b/extensions/cornerstone-dicom-seg/CHANGELOG.md index 7535520fa4..e8e0340033 100644 --- a/extensions/cornerstone-dicom-seg/CHANGELOG.md +++ b/extensions/cornerstone-dicom-seg/CHANGELOG.md @@ -3,6 +3,744 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.9.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.70...v3.9.0-beta.71) (2024-07-30) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.69...v3.9.0-beta.70) (2024-07-30) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.68...v3.9.0-beta.69) (2024-07-27) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.67...v3.9.0-beta.68) (2024-07-26) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.66...v3.9.0-beta.67) (2024-07-26) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.65...v3.9.0-beta.66) (2024-07-24) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.64...v3.9.0-beta.65) (2024-07-23) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.63...v3.9.0-beta.64) (2024-07-19) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.62...v3.9.0-beta.63) (2024-07-10) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.61...v3.9.0-beta.62) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.60...v3.9.0-beta.61) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.59...v3.9.0-beta.60) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.58...v3.9.0-beta.59) (2024-07-05) + + +### Bug Fixes + +* Cobb angle not working in basic-test mode and open contour ([#4280](https://github.com/OHIF/Viewers/issues/4280)) ([6fd3c7e](https://github.com/OHIF/Viewers/commit/6fd3c7e293fec851dd30e650c1347cc0bc7a99ee)) + + + + + +# [3.9.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.57...v3.9.0-beta.58) (2024-07-04) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.56...v3.9.0-beta.57) (2024-07-02) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.55...v3.9.0-beta.56) (2024-07-02) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.54...v3.9.0-beta.55) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.53...v3.9.0-beta.54) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.52...v3.9.0-beta.53) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.51...v3.9.0-beta.52) (2024-06-27) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.50...v3.9.0-beta.51) (2024-06-27) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.49...v3.9.0-beta.50) (2024-06-26) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.48...v3.9.0-beta.49) (2024-06-26) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.47...v3.9.0-beta.48) (2024-06-25) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.46...v3.9.0-beta.47) (2024-06-21) + + +### Bug Fixes + +* Allow the mode setup/creation to be async, and provide a few more values to extension/app config/mode setup. ([#4016](https://github.com/OHIF/Viewers/issues/4016)) ([88575c6](https://github.com/OHIF/Viewers/commit/88575c6c09fd778a31b2f91524163ce65d1639dd)) + + + + + +# [3.9.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.45...v3.9.0-beta.46) (2024-06-18) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.44...v3.9.0-beta.45) (2024-06-18) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.43...v3.9.0-beta.44) (2024-06-17) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.42...v3.9.0-beta.43) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.41...v3.9.0-beta.42) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.40...v3.9.0-beta.41) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.39...v3.9.0-beta.40) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.38...v3.9.0-beta.39) (2024-06-08) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.37...v3.9.0-beta.38) (2024-06-07) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.36...v3.9.0-beta.37) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.35...v3.9.0-beta.36) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.34...v3.9.0-beta.35) (2024-06-05) + + +### Bug Fixes + +* **seg:** maintain algorithm name and algorithm type when DICOM seg is exported or downloaded ([#4203](https://github.com/OHIF/Viewers/issues/4203)) ([a29e94d](https://github.com/OHIF/Viewers/commit/a29e94de803f79bbb3372d00ad8eb14b4224edc2)) + + + + + +# [3.9.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.33...v3.9.0-beta.34) (2024-06-05) + + +### Bug Fixes + +* **hydration:** Maintain the same slice that the user was on pre hydration in post hydration for SR and SEG. ([#4200](https://github.com/OHIF/Viewers/issues/4200)) ([430330f](https://github.com/OHIF/Viewers/commit/430330f7e384d503cb6fc695a7a9642ddfaac313)) + + + + + +# [3.9.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.32...v3.9.0-beta.33) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.31...v3.9.0-beta.32) (2024-05-31) + + +### Bug Fixes + +* **tmtv:** crosshairs should not have viewport indicators ([#4197](https://github.com/OHIF/Viewers/issues/4197)) ([f85da32](https://github.com/OHIF/Viewers/commit/f85da32f34389ef7cecae03c07e0af26468b52a6)) + + + + + +# [3.9.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.30...v3.9.0-beta.31) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.29...v3.9.0-beta.30) (2024-05-30) + + +### Bug Fixes + +* segmentation creation and segmentation mode viewport rendering ([#4193](https://github.com/OHIF/Viewers/issues/4193)) ([2174026](https://github.com/OHIF/Viewers/commit/217402678981f74293dff615f6b6812e54216d37)) + + + + + +# [3.9.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.28...v3.9.0-beta.29) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.27...v3.9.0-beta.28) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.26...v3.9.0-beta.27) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.25...v3.9.0-beta.26) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.24...v3.9.0-beta.25) (2024-05-29) + + +### Bug Fixes + +* **ultrasound:** Upgrade cornerstone3D version to resolve coloring issues ([#4181](https://github.com/OHIF/Viewers/issues/4181)) ([75a71db](https://github.com/OHIF/Viewers/commit/75a71db7f89840250ad1c2b35df5a35aceb8be7d)) + + + + + +# [3.9.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.23...v3.9.0-beta.24) (2024-05-29) + + +### Features + +* **measurements:** show untracked measurements in measurement panel under additional findings ([#4160](https://github.com/OHIF/Viewers/issues/4160)) ([18686c2](https://github.com/OHIF/Viewers/commit/18686c2caf13ede3e881303100bd4cc34b8b135f)) + + + + + +# [3.9.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.22...v3.9.0-beta.23) (2024-05-28) + + +### Bug Fixes + +* **rt:** dont convert to volume for RTSTRUCT ([#4157](https://github.com/OHIF/Viewers/issues/4157)) ([7745c09](https://github.com/OHIF/Viewers/commit/7745c092bb3edf0090f32fbbbae2f0776128d5a2)) + + + + + +# [3.9.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.21...v3.9.0-beta.22) (2024-05-27) + + +### Features + +* **ui:** move to React 18 and base for using shadcn/ui ([#4174](https://github.com/OHIF/Viewers/issues/4174)) ([70f2c79](https://github.com/OHIF/Viewers/commit/70f2c797f42af603d7ea0eb8d23b4103aba66f77)) + + + + + +# [3.9.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.20...v3.9.0-beta.21) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.19...v3.9.0-beta.20) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.18...v3.9.0-beta.19) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.17...v3.9.0-beta.18) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.16...v3.9.0-beta.17) (2024-05-23) + + +### Bug Fixes + +* **crosshairs:** reset angle, position, and slabthickness for crosshairs when reset viewport tool is used ([#4113](https://github.com/OHIF/Viewers/issues/4113)) ([73d9e99](https://github.com/OHIF/Viewers/commit/73d9e99d5d6f38ab6c36f4471d54f18798feacb4)) + + + + + +# [3.9.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.15...v3.9.0-beta.16) (2024-05-23) + + +### Bug Fixes + +* dicom json for orthanc by Update package versions for [@cornerstonejs](https://github.com/cornerstonejs) dependencies ([#4165](https://github.com/OHIF/Viewers/issues/4165)) ([34c7d72](https://github.com/OHIF/Viewers/commit/34c7d72142847486b98c9c52469940083eeaf87e)) + + + + + +# [3.9.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.14...v3.9.0-beta.15) (2024-05-22) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.13...v3.9.0-beta.14) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.12...v3.9.0-beta.13) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.11...v3.9.0-beta.12) (2024-05-21) + + +### Bug Fixes + +* **segmentation:** Address issue where segmentation creation failed on layout change ([#4153](https://github.com/OHIF/Viewers/issues/4153)) ([29944c8](https://github.com/OHIF/Viewers/commit/29944c8512c35718af03c03ef82bc43675ee1872)) + + + + + +# [3.9.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.10...v3.9.0-beta.11) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.9...v3.9.0-beta.10) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.8...v3.9.0-beta.9) (2024-05-17) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.7...v3.9.0-beta.8) (2024-05-16) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.6...v3.9.0-beta.7) (2024-05-15) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.5...v3.9.0-beta.6) (2024-05-15) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.4...v3.9.0-beta.5) (2024-05-14) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.3...v3.9.0-beta.4) (2024-05-14) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.9.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.2...v3.9.0-beta.3) (2024-05-08) + + +### Features + +* **typings:** Enhance typing support with withAppTypes and custom services throughout OHIF ([#4090](https://github.com/OHIF/Viewers/issues/4090)) ([374065b](https://github.com/OHIF/Viewers/commit/374065bc3bad9d212f9817a8d41546cc64cfabfb)) + + + + + +# [3.9.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.1...v3.9.0-beta.2) (2024-05-06) + + +### Bug Fixes + +* **bugs:** enhancements and bugs in several areas ([#4086](https://github.com/OHIF/Viewers/issues/4086)) ([730f434](https://github.com/OHIF/Viewers/commit/730f4349100f21b4489a21707dbb2dca9dbfbba2)) + + + + + +# [3.9.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.0...v3.9.0-beta.1) (2024-05-06) + + +### Bug Fixes + +* **rt:** enhanced RT support, utilize SVGs for rendering. ([#4074](https://github.com/OHIF/Viewers/issues/4074)) ([0156bc4](https://github.com/OHIF/Viewers/commit/0156bc426f1840ae0d090223e94a643726e856cb)) + + + + + +# [3.9.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.94...v3.9.0-beta.0) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.8.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0-beta.94) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29) + + +### Bug Fixes + +* **toolbox:** Preserve user-specified tool state and streamline command execution ([#4063](https://github.com/OHIF/Viewers/issues/4063)) ([f1a736d](https://github.com/OHIF/Viewers/commit/f1a736d1934733a434cb87b2c284907a3122403f)) + + + + + +# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28) + + +### Bug Fixes + +* **bugs:** fix patient header for doc, track ball rotate resize observer and add segmentation button not being enabled on viewport data change ([#4068](https://github.com/OHIF/Viewers/issues/4068)) ([c09311d](https://github.com/OHIF/Viewers/commit/c09311d3b7df05fcd00a9f36a7233e9d7e5589d0)) + + + + + +# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22) + + +### Bug Fixes + +* **viewport-webworker-segmentation:** Resolve issues with viewport detection, webworker termination, and segmentation panel layout change ([#4059](https://github.com/OHIF/Viewers/issues/4059)) ([52a0c59](https://github.com/OHIF/Viewers/commit/52a0c59294a4161fcca0a6708855549034849951)) + + + + + +# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19) + + +### Features + +* **tmtv-mode:** Add Brush tools and move SUV peak calculation to web worker ([#4053](https://github.com/OHIF/Viewers/issues/4053)) ([8192e34](https://github.com/OHIF/Viewers/commit/8192e348eca993fec331d4963efe88f9a730eceb)) + + + + + +# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19) + + +### Bug Fixes + +* **layouts:** and fix thumbnail in touch and update migration guide for 3.8 release ([#4052](https://github.com/OHIF/Viewers/issues/4052)) ([d250d04](https://github.com/OHIF/Viewers/commit/d250d04580883446fcb8d748b2a97c5c198922af)) + + + + + +# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg + + + + + +# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18) + + +### Bug Fixes + +* **bugs:** enhancements and bug fixes - final ([#4048](https://github.com/OHIF/Viewers/issues/4048)) ([170bb96](https://github.com/OHIF/Viewers/commit/170bb96983082c39b22b7352e0c54aacf3e73b02)) + + + + + # [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17) **Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg diff --git a/extensions/cornerstone-dicom-seg/babel.config.js b/extensions/cornerstone-dicom-seg/babel.config.js index a38ddda212..9705ae6f28 100644 --- a/extensions/cornerstone-dicom-seg/babel.config.js +++ b/extensions/cornerstone-dicom-seg/babel.config.js @@ -1,5 +1,5 @@ module.exports = { - plugins: ['inline-react-svg', '@babel/plugin-proposal-class-properties'], + plugins: ['@babel/plugin-proposal-class-properties'], env: { test: { presets: [ @@ -37,7 +37,7 @@ module.exports = { '@babel/preset-react', '@babel/preset-typescript', ], - plugins: ['react-hot-loader/babel'], + plugins: ['react-refresh/babel'], ignore: ['**/*.test.jsx', '**/*.test.js', '__snapshots__', '__tests__'], }, }, diff --git a/extensions/cornerstone-dicom-seg/package.json b/extensions/cornerstone-dicom-seg/package.json index ef3f9b2a2c..ca522b679d 100644 --- a/extensions/cornerstone-dicom-seg/package.json +++ b/extensions/cornerstone-dicom-seg/package.json @@ -1,6 +1,6 @@ { "name": "@ohif/extension-cornerstone-dicom-seg", - "version": "3.8.0-beta.82", + "version": "3.9.0-beta.71", "description": "DICOM SEG read workflow", "author": "OHIF", "license": "MIT", @@ -33,22 +33,22 @@ "start": "yarn run dev" }, "peerDependencies": { - "@ohif/core": "3.8.0-beta.82", - "@ohif/extension-cornerstone": "3.8.0-beta.82", - "@ohif/extension-default": "3.8.0-beta.82", - "@ohif/i18n": "3.8.0-beta.82", + "@ohif/core": "3.9.0-beta.71", + "@ohif/extension-cornerstone": "3.9.0-beta.71", + "@ohif/extension-default": "3.9.0-beta.71", + "@ohif/i18n": "3.9.0-beta.71", "prop-types": "^15.6.2", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "react": "^18.3.1", + "react-dom": "^18.3.1", "react-i18next": "^12.2.2", - "react-router": "^6.8.1", - "react-router-dom": "^6.8.1" + "react-router": "^6.23.1", + "react-router-dom": "^6.23.1" }, "dependencies": { "@babel/runtime": "^7.20.13", - "@cornerstonejs/adapters": "^1.70.6", - "@cornerstonejs/core": "^1.70.6", - "@kitware/vtk.js": "30.3.3", + "@cornerstonejs/adapters": "^1.81.6", + "@cornerstonejs/core": "^1.81.6", + "@kitware/vtk.js": "30.4.1", "react-color": "^2.19.3" } } diff --git a/extensions/cornerstone-dicom-seg/src/commandsModule.ts b/extensions/cornerstone-dicom-seg/src/commandsModule.ts index 4a770d7e17..5aeac96d2c 100644 --- a/extensions/cornerstone-dicom-seg/src/commandsModule.ts +++ b/extensions/cornerstone-dicom-seg/src/commandsModule.ts @@ -1,6 +1,6 @@ import dcmjs from 'dcmjs'; import { createReportDialogPrompt } from '@ohif/extension-default'; -import { ServicesManager, Types } from '@ohif/core'; +import { Types } from '@ohif/core'; import { cache, metaData } from '@cornerstonejs/core'; import { segmentation as cornerstoneToolsSegmentation, @@ -48,7 +48,8 @@ const commandsModule = ({ displaySetService, viewportGridService, toolGroupService, - } = (servicesManager as ServicesManager).services; + cornerstoneViewportService, + } = servicesManager.services; const actions = { /** @@ -94,6 +95,7 @@ const commandsModule = ({ updateViewportsForSegmentationRendering({ viewportId, servicesManager, + displaySet, loadFn: async () => { const currentSegmentations = segmentationService.getSegmentations(); const segmentationId = await segmentationService.createSegmentationForDisplaySet( @@ -209,11 +211,13 @@ const commandsModule = ({ const referencedDisplaySet = displaySetService.getDisplaySetByUID( displaySet.referencedDisplaySetInstanceUID ); + const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId); + const initialSliceIndex = viewport.getSliceIndex(); updateViewportsForSegmentationRendering({ viewportId, servicesManager, - referencedDisplaySetInstanceUID: displaySet.referencedDisplaySetInstanceUID, + displaySet, loadFn: async () => { const segDisplaySet = displaySet; const suppressEvents = false; @@ -228,6 +232,7 @@ const commandsModule = ({ segmentation.description = `S${referencedDisplaySet.SeriesNumber}: ${referencedDisplaySet.SeriesDescription}`; return segmentationId; }, + initialSliceIndex, }); }, /** @@ -258,9 +263,12 @@ const commandsModule = ({ labelmapObj.metadata = []; const segmentationInOHIF = segmentationService.getSegmentation(segmentationId); - labelmapObj.segmentsOnLabelmap.forEach(segmentIndex => { + segmentationInOHIF.segments.forEach(segment => { // segmentation service already has a color for each segment - const segment = segmentationInOHIF?.segments[segmentIndex]; + if (!segment) { + return; + } + const segmentIndex = segment.segmentIndex; const { label, color } = segment; const RecommendedDisplayCIELabValue = dcmjs.data.Colors.rgb2DICOMLAB( @@ -270,8 +278,8 @@ const commandsModule = ({ const segmentMetadata = { SegmentNumber: segmentIndex.toString(), SegmentLabel: label, - SegmentAlgorithmType: 'MANUAL', - SegmentAlgorithmName: 'OHIF Brush', + SegmentAlgorithmType: segment?.algorithmType || 'MANUAL', + SegmentAlgorithmName: segment?.algorithmName || 'OHIF Brush', RecommendedDisplayCIELabValue, SegmentedPropertyCategoryCodeSequence: { CodeValue: 'T-D0050', diff --git a/extensions/cornerstone-dicom-seg/src/getPanelModule.tsx b/extensions/cornerstone-dicom-seg/src/getPanelModule.tsx index a86144d4fd..42c13fff3c 100644 --- a/extensions/cornerstone-dicom-seg/src/getPanelModule.tsx +++ b/extensions/cornerstone-dicom-seg/src/getPanelModule.tsx @@ -10,7 +10,7 @@ const getPanelModule = ({ extensionManager, configuration, title, -}) => { +}: withAppTypes) => { const { customizationService } = servicesManager.services; const wrappedPanelSegmentation = configuration => { diff --git a/extensions/cornerstone-dicom-seg/src/getSopClassHandlerModule.js b/extensions/cornerstone-dicom-seg/src/getSopClassHandlerModule.ts similarity index 93% rename from extensions/cornerstone-dicom-seg/src/getSopClassHandlerModule.js rename to extensions/cornerstone-dicom-seg/src/getSopClassHandlerModule.ts index d150201e06..96952db30f 100644 --- a/extensions/cornerstone-dicom-seg/src/getSopClassHandlerModule.js +++ b/extensions/cornerstone-dicom-seg/src/getSopClassHandlerModule.ts @@ -8,9 +8,13 @@ import { dicomlabToRGB } from './utils/dicomlabToRGB'; const sopClassUids = ['1.2.840.10008.5.1.4.1.1.66.4']; -let loadPromises = {}; +const loadPromises = {}; -function _getDisplaySetsFromSeries(instances, servicesManager, extensionManager) { +function _getDisplaySetsFromSeries( + instances, + servicesManager: AppTypes.ServicesManager, + extensionManager +) { const instance = instances[0]; const { @@ -95,7 +99,12 @@ function _getDisplaySetsFromSeries(instances, servicesManager, extensionManager) return [displaySet]; } -function _load(segDisplaySet, servicesManager, extensionManager, headers) { +function _load( + segDisplaySet, + servicesManager: AppTypes.ServicesManager, + extensionManager, + headers +) { const { SOPInstanceUID } = segDisplaySet; const { segmentationService } = servicesManager.services; @@ -137,7 +146,12 @@ function _load(segDisplaySet, servicesManager, extensionManager, headers) { return loadPromises[SOPInstanceUID]; } -async function _loadSegments({ extensionManager, servicesManager, segDisplaySet, headers }) { +async function _loadSegments({ + extensionManager, + servicesManager, + segDisplaySet, + headers, +}: withAppTypes) { const utilityModule = extensionManager.getModuleEntry( '@ohif/extension-cornerstone.utilityModule.common' ); @@ -212,7 +226,7 @@ async function _loadSegments({ extensionManager, servicesManager, segDisplaySet, Object.assign(segDisplaySet, results); } -function _segmentationExists(segDisplaySet, segmentationService) { +function _segmentationExists(segDisplaySet, segmentationService: AppTypes.SegmentationService) { // This should be abstracted with the CornerstoneCacheService return segmentationService.getSegmentation(segDisplaySet.displaySetInstanceUID); } diff --git a/extensions/cornerstone-dicom-seg/src/getToolbarModule.ts b/extensions/cornerstone-dicom-seg/src/getToolbarModule.ts index 8bfe0c1e16..e991d778cc 100644 --- a/extensions/cornerstone-dicom-seg/src/getToolbarModule.ts +++ b/extensions/cornerstone-dicom-seg/src/getToolbarModule.ts @@ -1,5 +1,5 @@ -export function getToolbarModule({ commandsManager, servicesManager }) { - const { segmentationService, toolGroupService } = servicesManager.services; +export function getToolbarModule({ servicesManager }: withAppTypes) { + const { segmentationService, toolbarService, toolGroupService } = servicesManager.services; return [ { name: 'evaluate.cornerstone.segmentation', @@ -20,12 +20,16 @@ export function getToolbarModule({ commandsManager, servicesManager }) { const toolGroup = toolGroupService.getToolGroupForViewport(viewportId); if (!toolGroup) { - return; + return { + disabled: true, + className: '!text-common-bright ohif-disabled', + disabledText: disabledText ?? 'Not available on the current viewport', + }; } - const toolName = getToolNameForButton(button); + const toolName = toolbarService.getToolNameForButton(button); - if (!toolGroup || !toolGroup.hasTool(toolName)) { + if (!toolGroup.hasTool(toolName) && !toolNames) { return { disabled: true, className: '!text-common-bright ohif-disabled', @@ -51,19 +55,3 @@ export function getToolbarModule({ commandsManager, servicesManager }) { }, ]; } - -// Todo: this is duplicate, we should move it to a shared location -function getToolNameForButton(button) { - const { props } = button; - - const commands = props?.commands || button.commands; - const commandsArray = Array.isArray(commands) ? commands : [commands]; - const firstCommand = commandsArray[0]; - - if (firstCommand?.commandOptions) { - return firstCommand.commandOptions.toolName ?? props?.id ?? button.id; - } - - // use id as a fallback for toolName - return props?.id ?? button.id; -} diff --git a/extensions/cornerstone-dicom-seg/src/panels/PanelSegmentation.tsx b/extensions/cornerstone-dicom-seg/src/panels/PanelSegmentation.tsx index e640ca3095..afe861947b 100644 --- a/extensions/cornerstone-dicom-seg/src/panels/PanelSegmentation.tsx +++ b/extensions/cornerstone-dicom-seg/src/panels/PanelSegmentation.tsx @@ -17,9 +17,14 @@ export default function PanelSegmentation({ commandsManager, extensionManager, configuration, -}) { - const { segmentationService, viewportGridService, uiDialogService, displaySetService } = - servicesManager.services; +}: withAppTypes) { + const { + segmentationService, + viewportGridService, + uiDialogService, + displaySetService, + cornerstoneViewportService, + } = servicesManager.services; const { t } = useTranslation('PanelSegmentation'); @@ -82,21 +87,33 @@ export default function PanelSegmentation({ // Handle initial state handleActiveViewportChange(); - const changed = viewportGridService.EVENTS.ACTIVE_VIEWPORT_ID_CHANGED; + const changedGrid = viewportGridService.EVENTS.ACTIVE_VIEWPORT_ID_CHANGED; const ready = viewportGridService.EVENTS.VIEWPORTS_READY; - const subs = []; - [ready, changed].forEach(evt => { + const subsGrid = []; + [ready, changedGrid].forEach(evt => { const { unsubscribe } = viewportGridService.subscribe(evt, ({ viewportId }) => { handleActiveViewportChange(viewportId); }); - subs.push(unsubscribe); + subsGrid.push(unsubscribe); + }); + + const changedData = cornerstoneViewportService.EVENTS.VIEWPORT_DATA_CHANGED; + + const subsData = []; + [changedData].forEach(evt => { + const { unsubscribe } = cornerstoneViewportService.subscribe(evt, () => { + handleActiveViewportChange(); + }); + + subsData.push(unsubscribe); }); // Clean up return () => { - subs.forEach(unsub => unsub()); + subsGrid.forEach(unsub => unsub()); + subsData.forEach(unsub => unsub()); }; }, []); @@ -107,7 +124,9 @@ export default function PanelSegmentation({ }; const onSegmentationAdd = async () => { - commandsManager.runCommand('createEmptySegmentationForViewport'); + commandsManager.runCommand('createEmptySegmentationForViewport', { + viewportId: viewportGridService.getActiveViewportId(), + }); }; const onSegmentationClick = (segmentationId: string) => { diff --git a/extensions/cornerstone-dicom-seg/src/utils/hydrationUtils.ts b/extensions/cornerstone-dicom-seg/src/utils/hydrationUtils.ts index ad5898ee94..6dd33c1b37 100644 --- a/extensions/cornerstone-dicom-seg/src/utils/hydrationUtils.ts +++ b/extensions/cornerstone-dicom-seg/src/utils/hydrationUtils.ts @@ -10,7 +10,8 @@ import { Enums, cache } from '@cornerstonejs/core'; * @param params.viewportId - ID of the viewport to be updated. * @param params.loadFn - Function to load the segmentation data. * @param params.servicesManager - The services manager. - * @param params.referencedDisplaySetInstanceUID - Optional UID for the referenced display set instance. + * @param params.displaySet - the display set. + * @param params.initialSliceIndex - The initial slice index. * * @returns Returns true upon successful update of viewports for segmentation rendering. */ @@ -18,12 +19,14 @@ async function updateViewportsForSegmentationRendering({ viewportId, loadFn, servicesManager, - referencedDisplaySetInstanceUID, + displaySet, + initialSliceIndex = null, }: { viewportId: string; loadFn: () => Promise; - servicesManager: any; - referencedDisplaySetInstanceUID?: string; + servicesManager: AppTypes.ServicesManager; + displaySet?: any; + initialSliceIndex?: number; }) { const { cornerstoneViewportService, segmentationService, viewportGridService } = servicesManager.services; @@ -31,13 +34,13 @@ async function updateViewportsForSegmentationRendering({ const viewport = getTargetViewport({ viewportId, viewportGridService }); const targetViewportId = viewport.viewportOptions.viewportId; - referencedDisplaySetInstanceUID = - referencedDisplaySetInstanceUID || viewport?.displaySetInstanceUIDs[0]; + const referencedDisplaySetInstanceUID = + displaySet?.referencedDisplaySetInstanceUID || viewport?.displaySetInstanceUIDs[0]; const updatedViewports = getUpdatedViewportsForSegmentation({ - servicesManager, viewportId, - referencedDisplaySetInstanceUID, + servicesManager, + displaySet, }); // create Segmentation callback which needs to be waited until @@ -56,17 +59,25 @@ async function updateViewportsForSegmentationRendering({ updatedViewports.forEach(async viewport => { viewport.viewportOptions = { ...viewport.viewportOptions, - viewportType: 'volume', + viewportType: displaySet?.Modality === 'RTSTRUCT' ? 'stack' : 'volume', needsRerendering: true, }; const viewportId = viewport.viewportId; + // maintain the prehydration slice on the target viewport only + if (viewportId === targetViewportId) { + viewport.viewportOptions.initialImageOptions = { + index: initialSliceIndex, + useOnce: true, + }; + } + const csViewport = cornerstoneViewportService.getCornerstoneViewport(viewportId); const prevCamera = csViewport.getCamera(); // only run the createSegmentationForVolume for the targetViewportId // since the rest will get handled by cornerstoneViewportService - if (volumeExists && viewportId === targetViewportId) { + if ((volumeExists || displaySet.Modality === 'RTSTRUCT') && viewportId === targetViewportId) { await createSegmentationForVolume(); return; } @@ -126,19 +137,19 @@ const getTargetViewport = ({ viewportId, viewportGridService }) => { * @param {Object} params - Parameters for the function. * @param params.viewportId - the ID of the viewport to be updated. * @param params.servicesManager - The services manager - * @param params.referencedDisplaySetInstanceUID - Optional UID for the referenced display set instance. + * @param params.displaySet - the display set. * * @returns {Array} Returns an array of viewports that require updates for segmentation rendering. */ function getUpdatedViewportsForSegmentation({ viewportId, servicesManager, - referencedDisplaySetInstanceUID, -}) { + displaySet, +}: withAppTypes) { const { hangingProtocolService, displaySetService, segmentationService, viewportGridService } = servicesManager.services; - const { viewports } = viewportGridService.getState(); + const { viewports, isHangingProtocolLayout } = viewportGridService.getState(); const viewport = getTargetViewport({ viewportId, viewportGridService }); const targetViewportId = viewport.viewportOptions.viewportId; @@ -146,14 +157,15 @@ function getUpdatedViewportsForSegmentation({ const displaySetInstanceUIDs = viewports.get(targetViewportId).displaySetInstanceUIDs; const referenceDisplaySetInstanceUID = - referencedDisplaySetInstanceUID || displaySetInstanceUIDs[0]; + displaySet?.referencedDisplaySetInstanceUID || displaySetInstanceUIDs[0]; const referencedDisplaySet = displaySetService.getDisplaySetByUID(referenceDisplaySetInstanceUID); const segmentationFrameOfReferenceUID = referencedDisplaySet.instances[0].FrameOfReferenceUID; const updatedViewports = hangingProtocolService.getViewportsRequireUpdate( targetViewportId, - referenceDisplaySetInstanceUID + referenceDisplaySetInstanceUID, + isHangingProtocolLayout ); viewports.forEach((viewport, viewportId) => { @@ -174,7 +186,7 @@ function getUpdatedViewportsForSegmentation({ viewportId, displaySetInstanceUIDs: viewport.displaySetInstanceUIDs, viewportOptions: { - viewportType: 'volume', + viewportType: displaySet?.Modality === 'RTSTRUCT' ? 'stack' : 'volume', needsRerendering: true, }, }); diff --git a/extensions/cornerstone-dicom-seg/src/utils/promptHydrateSEG.ts b/extensions/cornerstone-dicom-seg/src/utils/promptHydrateSEG.ts index c42b32e69f..d29a066b7d 100644 --- a/extensions/cornerstone-dicom-seg/src/utils/promptHydrateSEG.ts +++ b/extensions/cornerstone-dicom-seg/src/utils/promptHydrateSEG.ts @@ -12,23 +12,29 @@ function promptHydrateSEG({ viewportId, preHydrateCallbacks, hydrateSEGDisplaySet, -}) { +}: withAppTypes) { const { uiViewportDialogService } = servicesManager.services; + const extensionManager = servicesManager._extensionManager; + const appConfig = extensionManager._appConfig; return new Promise(async function (resolve, reject) { - const promptResult = await _askHydrate(uiViewportDialogService, viewportId); + const promptResult = appConfig?.disableConfirmationPrompts + ? RESPONSE.HYDRATE_SEG + : await _askHydrate(uiViewportDialogService, viewportId); if (promptResult === RESPONSE.HYDRATE_SEG) { preHydrateCallbacks?.forEach(callback => { callback(); }); - const isHydrated = await hydrateSEGDisplaySet({ - segDisplaySet, - viewportId, - }); + window.setTimeout(async () => { + const isHydrated = await hydrateSEGDisplaySet({ + segDisplaySet, + viewportId, + }); - resolve(isHydrated); + resolve(isHydrated); + }, 0); } }); } @@ -38,11 +44,13 @@ function _askHydrate(uiViewportDialogService, viewportId) { const message = 'Do you want to open this Segmentation?'; const actions = [ { + id: 'no-hydrate', type: ButtonEnums.type.secondary, text: 'No', value: RESPONSE.CANCEL, }, { + id: 'yes-hydrate', type: ButtonEnums.type.primary, text: 'Yes', value: RESPONSE.HYDRATE_SEG, diff --git a/extensions/cornerstone-dicom-seg/src/viewports/OHIFCornerstoneSEGViewport.tsx b/extensions/cornerstone-dicom-seg/src/viewports/OHIFCornerstoneSEGViewport.tsx index 894a4c4076..c78017edcb 100644 --- a/extensions/cornerstone-dicom-seg/src/viewports/OHIFCornerstoneSEGViewport.tsx +++ b/extensions/cornerstone-dicom-seg/src/viewports/OHIFCornerstoneSEGViewport.tsx @@ -8,7 +8,7 @@ import _getStatusComponent from './_getStatusComponent'; const SEG_TOOLGROUP_BASE_NAME = 'SEGToolGroup'; -function OHIFCornerstoneSEGViewport(props) { +function OHIFCornerstoneSEGViewport(props: withAppTypes) { const { children, displaySets, @@ -25,7 +25,6 @@ function OHIFCornerstoneSEGViewport(props) { displaySetService, toolGroupService, segmentationService, - uiNotificationService, customizationService, viewportActionCornersService, } = servicesManager.services; @@ -368,11 +367,6 @@ OHIFCornerstoneSEGViewport.propTypes = { viewportId: PropTypes.string.isRequired, dataSource: PropTypes.object, children: PropTypes.node, - customProps: PropTypes.object, -}; - -OHIFCornerstoneSEGViewport.defaultProps = { - customProps: {}, }; function _getReferencedDisplaySetMetadata(referencedDisplaySet, segDisplaySet) { diff --git a/extensions/cornerstone-dicom-sr/CHANGELOG.md b/extensions/cornerstone-dicom-sr/CHANGELOG.md index 694d051094..611202cf48 100644 --- a/extensions/cornerstone-dicom-sr/CHANGELOG.md +++ b/extensions/cornerstone-dicom-sr/CHANGELOG.md @@ -3,6 +3,739 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.9.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.70...v3.9.0-beta.71) (2024-07-30) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.69...v3.9.0-beta.70) (2024-07-30) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.68...v3.9.0-beta.69) (2024-07-27) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.67...v3.9.0-beta.68) (2024-07-26) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.66...v3.9.0-beta.67) (2024-07-26) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.65...v3.9.0-beta.66) (2024-07-24) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.64...v3.9.0-beta.65) (2024-07-23) + + +### Features + +* **SR:** text structured report (TEXT, CODE, NUM, PNAME, DATE, TIME and DATETIME) ([#4287](https://github.com/OHIF/Viewers/issues/4287)) ([246ebab](https://github.com/OHIF/Viewers/commit/246ebab6ebf5431a704a1861a5804045b9644ba4)) + + + + + +# [3.9.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.63...v3.9.0-beta.64) (2024-07-19) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.62...v3.9.0-beta.63) (2024-07-10) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.61...v3.9.0-beta.62) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.60...v3.9.0-beta.61) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.59...v3.9.0-beta.60) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.58...v3.9.0-beta.59) (2024-07-05) + + +### Bug Fixes + +* Cobb angle not working in basic-test mode and open contour ([#4280](https://github.com/OHIF/Viewers/issues/4280)) ([6fd3c7e](https://github.com/OHIF/Viewers/commit/6fd3c7e293fec851dd30e650c1347cc0bc7a99ee)) +* webpack import bugs showing warnings on import ([#4265](https://github.com/OHIF/Viewers/issues/4265)) ([24c511f](https://github.com/OHIF/Viewers/commit/24c511f4bc04c4143bbd3d0d48029f41f7f36014)) + + + + + +# [3.9.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.57...v3.9.0-beta.58) (2024-07-04) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.56...v3.9.0-beta.57) (2024-07-02) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.55...v3.9.0-beta.56) (2024-07-02) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.54...v3.9.0-beta.55) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.53...v3.9.0-beta.54) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.52...v3.9.0-beta.53) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.51...v3.9.0-beta.52) (2024-06-27) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.50...v3.9.0-beta.51) (2024-06-27) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.49...v3.9.0-beta.50) (2024-06-26) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.48...v3.9.0-beta.49) (2024-06-26) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.47...v3.9.0-beta.48) (2024-06-25) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.46...v3.9.0-beta.47) (2024-06-21) + + +### Bug Fixes + +* Allow the mode setup/creation to be async, and provide a few more values to extension/app config/mode setup. ([#4016](https://github.com/OHIF/Viewers/issues/4016)) ([88575c6](https://github.com/OHIF/Viewers/commit/88575c6c09fd778a31b2f91524163ce65d1639dd)) + + + + + +# [3.9.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.45...v3.9.0-beta.46) (2024-06-18) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.44...v3.9.0-beta.45) (2024-06-18) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.43...v3.9.0-beta.44) (2024-06-17) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.42...v3.9.0-beta.43) (2024-06-12) + + +### Bug Fixes + +* **sr:** rendering issue by running loadSR before updateSR ([#4226](https://github.com/OHIF/Viewers/issues/4226)) ([6971287](https://github.com/OHIF/Viewers/commit/69712874603109aa4f655d47daf15d72167a49ff)) + + + + + +# [3.9.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.41...v3.9.0-beta.42) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.40...v3.9.0-beta.41) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.39...v3.9.0-beta.40) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.38...v3.9.0-beta.39) (2024-06-08) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.37...v3.9.0-beta.38) (2024-06-07) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.36...v3.9.0-beta.37) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.35...v3.9.0-beta.36) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.34...v3.9.0-beta.35) (2024-06-05) + + +### Bug Fixes + +* **seg:** maintain algorithm name and algorithm type when DICOM seg is exported or downloaded ([#4203](https://github.com/OHIF/Viewers/issues/4203)) ([a29e94d](https://github.com/OHIF/Viewers/commit/a29e94de803f79bbb3372d00ad8eb14b4224edc2)) + + + + + +# [3.9.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.33...v3.9.0-beta.34) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.32...v3.9.0-beta.33) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.31...v3.9.0-beta.32) (2024-05-31) + + +### Bug Fixes + +* **tmtv:** crosshairs should not have viewport indicators ([#4197](https://github.com/OHIF/Viewers/issues/4197)) ([f85da32](https://github.com/OHIF/Viewers/commit/f85da32f34389ef7cecae03c07e0af26468b52a6)) + + + + + +# [3.9.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.30...v3.9.0-beta.31) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.29...v3.9.0-beta.30) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.28...v3.9.0-beta.29) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.27...v3.9.0-beta.28) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.26...v3.9.0-beta.27) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.25...v3.9.0-beta.26) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.24...v3.9.0-beta.25) (2024-05-29) + + +### Bug Fixes + +* **ultrasound:** Upgrade cornerstone3D version to resolve coloring issues ([#4181](https://github.com/OHIF/Viewers/issues/4181)) ([75a71db](https://github.com/OHIF/Viewers/commit/75a71db7f89840250ad1c2b35df5a35aceb8be7d)) + + + + + +# [3.9.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.23...v3.9.0-beta.24) (2024-05-29) + + +### Features + +* **measurements:** show untracked measurements in measurement panel under additional findings ([#4160](https://github.com/OHIF/Viewers/issues/4160)) ([18686c2](https://github.com/OHIF/Viewers/commit/18686c2caf13ede3e881303100bd4cc34b8b135f)) + + + + + +# [3.9.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.22...v3.9.0-beta.23) (2024-05-28) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.21...v3.9.0-beta.22) (2024-05-27) + + +### Features + +* **ui:** move to React 18 and base for using shadcn/ui ([#4174](https://github.com/OHIF/Viewers/issues/4174)) ([70f2c79](https://github.com/OHIF/Viewers/commit/70f2c797f42af603d7ea0eb8d23b4103aba66f77)) + + + + + +# [3.9.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.20...v3.9.0-beta.21) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.19...v3.9.0-beta.20) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.18...v3.9.0-beta.19) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.17...v3.9.0-beta.18) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.16...v3.9.0-beta.17) (2024-05-23) + + +### Bug Fixes + +* **crosshairs:** reset angle, position, and slabthickness for crosshairs when reset viewport tool is used ([#4113](https://github.com/OHIF/Viewers/issues/4113)) ([73d9e99](https://github.com/OHIF/Viewers/commit/73d9e99d5d6f38ab6c36f4471d54f18798feacb4)) + + + + + +# [3.9.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.15...v3.9.0-beta.16) (2024-05-23) + + +### Bug Fixes + +* dicom json for orthanc by Update package versions for [@cornerstonejs](https://github.com/cornerstonejs) dependencies ([#4165](https://github.com/OHIF/Viewers/issues/4165)) ([34c7d72](https://github.com/OHIF/Viewers/commit/34c7d72142847486b98c9c52469940083eeaf87e)) + + + + + +# [3.9.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.14...v3.9.0-beta.15) (2024-05-22) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.13...v3.9.0-beta.14) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.12...v3.9.0-beta.13) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.11...v3.9.0-beta.12) (2024-05-21) + + +### Bug Fixes + +* **segmentation:** Address issue where segmentation creation failed on layout change ([#4153](https://github.com/OHIF/Viewers/issues/4153)) ([29944c8](https://github.com/OHIF/Viewers/commit/29944c8512c35718af03c03ef82bc43675ee1872)) + + + + + +# [3.9.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.10...v3.9.0-beta.11) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.9...v3.9.0-beta.10) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.8...v3.9.0-beta.9) (2024-05-17) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.7...v3.9.0-beta.8) (2024-05-16) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.6...v3.9.0-beta.7) (2024-05-15) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.5...v3.9.0-beta.6) (2024-05-15) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.4...v3.9.0-beta.5) (2024-05-14) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.3...v3.9.0-beta.4) (2024-05-14) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.2...v3.9.0-beta.3) (2024-05-08) + + +### Features + +* **typings:** Enhance typing support with withAppTypes and custom services throughout OHIF ([#4090](https://github.com/OHIF/Viewers/issues/4090)) ([374065b](https://github.com/OHIF/Viewers/commit/374065bc3bad9d212f9817a8d41546cc64cfabfb)) + + + + + +# [3.9.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.1...v3.9.0-beta.2) (2024-05-06) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.9.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.0...v3.9.0-beta.1) (2024-05-06) + + +### Bug Fixes + +* **rt:** enhanced RT support, utilize SVGs for rendering. ([#4074](https://github.com/OHIF/Viewers/issues/4074)) ([0156bc4](https://github.com/OHIF/Viewers/commit/0156bc426f1840ae0d090223e94a643726e856cb)) + + + + + +# [3.9.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.94...v3.9.0-beta.0) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.8.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0-beta.94) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29) + + +### Bug Fixes + +* **toolbox:** Preserve user-specified tool state and streamline command execution ([#4063](https://github.com/OHIF/Viewers/issues/4063)) ([f1a736d](https://github.com/OHIF/Viewers/commit/f1a736d1934733a434cb87b2c284907a3122403f)) + + + + + +# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28) + + +### Bug Fixes + +* **bugs:** fix patient header for doc, track ball rotate resize observer and add segmentation button not being enabled on viewport data change ([#4068](https://github.com/OHIF/Viewers/issues/4068)) ([c09311d](https://github.com/OHIF/Viewers/commit/c09311d3b7df05fcd00a9f36a7233e9d7e5589d0)) + + + + + +# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22) + + +### Bug Fixes + +* **viewport-webworker-segmentation:** Resolve issues with viewport detection, webworker termination, and segmentation panel layout change ([#4059](https://github.com/OHIF/Viewers/issues/4059)) ([52a0c59](https://github.com/OHIF/Viewers/commit/52a0c59294a4161fcca0a6708855549034849951)) + + + + + +# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19) + + +### Features + +* **tmtv-mode:** Add Brush tools and move SUV peak calculation to web worker ([#4053](https://github.com/OHIF/Viewers/issues/4053)) ([8192e34](https://github.com/OHIF/Viewers/commit/8192e348eca993fec331d4963efe88f9a730eceb)) + + + + + +# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19) + + +### Bug Fixes + +* **layouts:** and fix thumbnail in touch and update migration guide for 3.8 release ([#4052](https://github.com/OHIF/Viewers/issues/4052)) ([d250d04](https://github.com/OHIF/Viewers/commit/d250d04580883446fcb8d748b2a97c5c198922af)) + + + + + +# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr + + + + + +# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18) + + +### Bug Fixes + +* **bugs:** enhancements and bug fixes - final ([#4048](https://github.com/OHIF/Viewers/issues/4048)) ([170bb96](https://github.com/OHIF/Viewers/commit/170bb96983082c39b22b7352e0c54aacf3e73b02)) + + + + + # [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17) **Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr diff --git a/extensions/cornerstone-dicom-sr/package.json b/extensions/cornerstone-dicom-sr/package.json index 20b10448e3..07da9488ad 100644 --- a/extensions/cornerstone-dicom-sr/package.json +++ b/extensions/cornerstone-dicom-sr/package.json @@ -1,6 +1,6 @@ { "name": "@ohif/extension-cornerstone-dicom-sr", - "version": "3.8.0-beta.82", + "version": "3.9.0-beta.71", "description": "OHIF extension for an SR Cornerstone Viewport", "author": "OHIF", "license": "MIT", @@ -34,21 +34,21 @@ "test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests" }, "peerDependencies": { - "@ohif/core": "3.8.0-beta.82", - "@ohif/extension-cornerstone": "3.8.0-beta.82", - "@ohif/extension-measurement-tracking": "3.8.0-beta.82", - "@ohif/ui": "3.8.0-beta.82", - "dcmjs": "^0.29.12", + "@ohif/core": "3.9.0-beta.71", + "@ohif/extension-cornerstone": "3.9.0-beta.71", + "@ohif/extension-measurement-tracking": "3.9.0-beta.71", + "@ohif/ui": "3.9.0-beta.71", + "dcmjs": "*", "dicom-parser": "^1.8.9", "hammerjs": "^2.0.8", "prop-types": "^15.6.2", - "react": "^17.0.2" + "react": "^18.3.1" }, "dependencies": { "@babel/runtime": "^7.20.13", - "@cornerstonejs/adapters": "^1.70.6", - "@cornerstonejs/core": "^1.70.6", - "@cornerstonejs/tools": "^1.70.6", + "@cornerstonejs/adapters": "^1.82.0", + "@cornerstonejs/core": "^1.82.0", + "@cornerstonejs/tools": "^1.82.0", "classnames": "^2.3.2" } } diff --git a/extensions/cornerstone-dicom-sr/src/commandsModule.js b/extensions/cornerstone-dicom-sr/src/commandsModule.ts similarity index 97% rename from extensions/cornerstone-dicom-sr/src/commandsModule.js rename to extensions/cornerstone-dicom-sr/src/commandsModule.ts index 2f355bc09d..e4cfb53b46 100644 --- a/extensions/cornerstone-dicom-sr/src/commandsModule.js +++ b/extensions/cornerstone-dicom-sr/src/commandsModule.ts @@ -40,7 +40,7 @@ const _generateReport = (measurementData, additionalFindingTypes, options = {}) return dataset; }; -const commandsModule = props => { +const commandsModule = (props: withAppTypes) => { const { servicesManager } = props; const { customizationService } = servicesManager.services; const actions = { @@ -57,7 +57,7 @@ const commandsModule = props => { const reportBlob = dcmjs.data.datasetToBlob(srDataset); //Create a URL for the binary. - var objectUrl = URL.createObjectURL(reportBlob); + const objectUrl = URL.createObjectURL(reportBlob); window.location.assign(objectUrl); }, diff --git a/extensions/cornerstone-dicom-sr/src/components/OHIFCornerstoneSRContainer.tsx b/extensions/cornerstone-dicom-sr/src/components/OHIFCornerstoneSRContainer.tsx new file mode 100644 index 0000000000..461eba1acf --- /dev/null +++ b/extensions/cornerstone-dicom-sr/src/components/OHIFCornerstoneSRContainer.tsx @@ -0,0 +1,78 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { OHIFCornerstoneSRContentItem } from './OHIFCornerstoneSRContentItem'; + +export function OHIFCornerstoneSRContainer(props) { + const { container, nodeIndexesTree = [0], containerNumberedTree = [1] } = props; + const { ContinuityOfContent, ConceptNameCodeSequence } = container; + const { CodeMeaning } = ConceptNameCodeSequence ?? {}; + let childContainerIndex = 1; + const contentItems = container.ContentSequence?.map((contentItem, i) => { + const { ValueType } = contentItem; + const childNodeLevel = [...nodeIndexesTree, i]; + const key = childNodeLevel.join('.'); + + let Component; + let componentProps; + + if (ValueType === 'CONTAINER') { + const childContainerNumberedTree = [...containerNumberedTree, childContainerIndex++]; + + Component = OHIFCornerstoneSRContainer; + componentProps = { + container: contentItem, + nodeIndexesTree: childNodeLevel, + containerNumberedTree: childContainerNumberedTree, + }; + } else { + Component = OHIFCornerstoneSRContentItem; + componentProps = { + contentItem, + nodeIndexesTree: childNodeLevel, + continuityOfContent: ContinuityOfContent, + }; + } + + return ( + + ); + }); + + return ( +
+
+ {containerNumberedTree.join('.')}.  + {CodeMeaning} +
+
{contentItems}
+
+ ); +} + +OHIFCornerstoneSRContainer.propTypes = { + /** + * A tree node that may contain another container or one or more content items + * (text, code, uidref, pname, etc.) + */ + container: PropTypes.object, + /** + * A 0-based index list + */ + nodeIndexesTree: PropTypes.arrayOf(PropTypes.number), + /** + * A 1-based index list that represents a container in a multi-level numbered + * list (tree). + * + * Example: + * 1. History + * 1.1. Chief Complaint + * 1.2. Present Illness + * 1.3. Past History + * 1.4. Family History + * 2. Findings + * */ + containerNumberedTree: PropTypes.arrayOf(PropTypes.number), +}; diff --git a/extensions/cornerstone-dicom-sr/src/components/OHIFCornerstoneSRContentItem.tsx b/extensions/cornerstone-dicom-sr/src/components/OHIFCornerstoneSRContentItem.tsx new file mode 100644 index 0000000000..b12aafb7bb --- /dev/null +++ b/extensions/cornerstone-dicom-sr/src/components/OHIFCornerstoneSRContentItem.tsx @@ -0,0 +1,63 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import CodeNameCodeSequenceValues from '../constants/CodeNameCodeSequenceValues'; +import formatContentItemValue from '../utils/formatContentItem'; + +const EMPTY_TAG_VALUE = '[empty]'; + +function OHIFCornerstoneSRContentItem(props) { + const { contentItem, nodeIndexesTree, continuityOfContent } = props; + const { ConceptNameCodeSequence } = contentItem; + const { CodeValue, CodeMeaning } = ConceptNameCodeSequence; + const isChildFirstNode = nodeIndexesTree[nodeIndexesTree.length - 1] === 0; + const formattedValue = formatContentItemValue(contentItem) ?? EMPTY_TAG_VALUE; + const startWithAlphaNumCharRegEx = /^[a-zA-Z0-9]/; + const isContinuous = continuityOfContent === 'CONTINUOUS'; + const isFinding = CodeValue === CodeNameCodeSequenceValues.Finding; + const addExtraSpace = + isContinuous && !isChildFirstNode && startWithAlphaNumCharRegEx.test(formattedValue?.[0]); + + // Collapse sequences of white space preserving newline characters + let className = 'whitespace-pre-line'; + + if (CodeValue === CodeNameCodeSequenceValues.Finding) { + // Preserve spaces because it is common to see tabular text in a + // "Findings" ConceptNameCodeSequence + className = 'whitespace-pre-wrap'; + } + + if (isContinuous) { + return ( + <> + + {addExtraSpace ? ' ' : ''} + {formattedValue} + + + ); + } + + return ( + <> +
+ {CodeMeaning}: + {isFinding ? ( +
{formattedValue}
+ ) : ( + {formattedValue} + )} +
+ + ); +} + +OHIFCornerstoneSRContentItem.propTypes = { + contentItem: PropTypes.object, + nodeIndexesTree: PropTypes.arrayOf(PropTypes.number), + continuityOfContent: PropTypes.string, +}; + +export { OHIFCornerstoneSRContentItem }; diff --git a/extensions/cornerstone-dicom-sr/src/viewports/OHIFCornerstoneSRViewport.tsx b/extensions/cornerstone-dicom-sr/src/components/OHIFCornerstoneSRMeasurementViewport.tsx similarity index 96% rename from extensions/cornerstone-dicom-sr/src/viewports/OHIFCornerstoneSRViewport.tsx rename to extensions/cornerstone-dicom-sr/src/components/OHIFCornerstoneSRMeasurementViewport.tsx index 6158df3317..e6f50fe228 100644 --- a/extensions/cornerstone-dicom-sr/src/viewports/OHIFCornerstoneSRViewport.tsx +++ b/extensions/cornerstone-dicom-sr/src/components/OHIFCornerstoneSRMeasurementViewport.tsx @@ -1,7 +1,7 @@ import PropTypes from 'prop-types'; import React, { useCallback, useContext, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { ServicesManager, ExtensionManager } from '@ohif/core'; +import { ExtensionManager } from '@ohif/core'; import { setTrackingUniqueIdentifiersForElement } from '../tools/modules/dicomSRModule'; @@ -14,7 +14,7 @@ const MEASUREMENT_TRACKING_EXTENSION_ID = '@ohif/extension-measurement-tracking' const SR_TOOLGROUP_BASE_NAME = 'SRToolGroup'; -function OHIFCornerstoneSRViewport(props) { +function OHIFCornerstoneSRMeasurementViewport(props: withAppTypes) { const { children, dataSource, displaySets, viewportOptions, servicesManager, extensionManager } = props; @@ -270,17 +270,23 @@ function OHIFCornerstoneSRViewport(props) { updateViewport(measurementSelected); }; loadSR(); - }, [dataSource, srDisplaySet]); + }, [srDisplaySet]); /** * Hook to update the tracking identifiers when the selected measurement changes or * the element changes */ useEffect(() => { - if (!element || !srDisplaySet.isLoaded) { - return; - } - setTrackingIdentifiers(measurementSelected); + const updateSR = async () => { + if (!srDisplaySet.isLoaded) { + await srDisplaySet.load(); + } + if (!element || !srDisplaySet.isLoaded) { + return; + } + setTrackingIdentifiers(measurementSelected); + }; + updateSR(); }, [measurementSelected, element, setTrackingIdentifiers, srDisplaySet]); /** @@ -361,22 +367,17 @@ function OHIFCornerstoneSRViewport(props) { ); } -OHIFCornerstoneSRViewport.propTypes = { +OHIFCornerstoneSRMeasurementViewport.propTypes = { displaySets: PropTypes.arrayOf(PropTypes.object), viewportId: PropTypes.string.isRequired, dataSource: PropTypes.object, children: PropTypes.node, viewportLabel: PropTypes.string, - customProps: PropTypes.object, viewportOptions: PropTypes.object, - servicesManager: PropTypes.instanceOf(ServicesManager).isRequired, + servicesManager: PropTypes.object.isRequired, extensionManager: PropTypes.instanceOf(ExtensionManager).isRequired, }; -OHIFCornerstoneSRViewport.defaultProps = { - customProps: {}, -}; - async function _getViewportReferencedDisplaySetData( displaySet, measurementSelected, @@ -507,4 +508,4 @@ function _getStatusComponent({ ); } -export default OHIFCornerstoneSRViewport; +export default OHIFCornerstoneSRMeasurementViewport; diff --git a/extensions/cornerstone-dicom-sr/src/components/OHIFCornerstoneSRTextViewport.tsx b/extensions/cornerstone-dicom-sr/src/components/OHIFCornerstoneSRTextViewport.tsx new file mode 100644 index 0000000000..78d4929b77 --- /dev/null +++ b/extensions/cornerstone-dicom-sr/src/components/OHIFCornerstoneSRTextViewport.tsx @@ -0,0 +1,32 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { ExtensionManager } from '@ohif/core'; +import { OHIFCornerstoneSRContainer } from './OHIFCornerstoneSRContainer'; + +function OHIFCornerstoneSRTextViewport(props: withAppTypes) { + const { displaySets } = props; + const displaySet = displaySets[0]; + const instance = displaySet.instances[0]; + + return ( +
+
+ {/* The root level is always a container */} + +
+
+ ); +} + +OHIFCornerstoneSRTextViewport.propTypes = { + displaySets: PropTypes.arrayOf(PropTypes.object), + viewportId: PropTypes.string.isRequired, + dataSource: PropTypes.object, + children: PropTypes.node, + viewportLabel: PropTypes.string, + viewportOptions: PropTypes.object, + servicesManager: PropTypes.object.isRequired, + extensionManager: PropTypes.instanceOf(ExtensionManager).isRequired, +}; + +export default OHIFCornerstoneSRTextViewport; diff --git a/extensions/cornerstone-dicom-sr/src/components/OHIFCornerstoneSRViewport.tsx b/extensions/cornerstone-dicom-sr/src/components/OHIFCornerstoneSRViewport.tsx new file mode 100644 index 0000000000..3bbb73a5b8 --- /dev/null +++ b/extensions/cornerstone-dicom-sr/src/components/OHIFCornerstoneSRViewport.tsx @@ -0,0 +1,30 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { ExtensionManager } from '@ohif/core'; + +import OHIFCornerstoneSRMeasurementViewport from './OHIFCornerstoneSRMeasurementViewport'; +import OHIFCornerstoneSRTextViewport from './OHIFCornerstoneSRTextViewport'; + +function OHIFCornerstoneSRViewport(props: withAppTypes) { + const { displaySets } = props; + const { isImagingMeasurementReport } = displaySets[0]; + + if (isImagingMeasurementReport) { + return ; + } + + return ; +} + +OHIFCornerstoneSRViewport.propTypes = { + displaySets: PropTypes.arrayOf(PropTypes.object), + viewportId: PropTypes.string.isRequired, + dataSource: PropTypes.object, + children: PropTypes.node, + viewportLabel: PropTypes.string, + viewportOptions: PropTypes.object, + servicesManager: PropTypes.object.isRequired, + extensionManager: PropTypes.instanceOf(ExtensionManager).isRequired, +}; + +export default OHIFCornerstoneSRViewport; diff --git a/extensions/cornerstone-dicom-sr/src/constants/CodeNameCodeSequenceValues.ts b/extensions/cornerstone-dicom-sr/src/constants/CodeNameCodeSequenceValues.ts new file mode 100644 index 0000000000..cba848cbe2 --- /dev/null +++ b/extensions/cornerstone-dicom-sr/src/constants/CodeNameCodeSequenceValues.ts @@ -0,0 +1,18 @@ +import { adaptersSR } from '@cornerstonejs/adapters'; + +const { CodeScheme: Cornerstone3DCodeScheme } = adaptersSR.Cornerstone3D; + +const CodeNameCodeSequenceValues = { + ImagingMeasurementReport: '126000', + ImageLibrary: '111028', + ImagingMeasurements: '126010', + MeasurementGroup: '125007', + ImageLibraryGroup: '126200', + TrackingUniqueIdentifier: '112040', + TrackingIdentifier: '112039', + Finding: '121071', + FindingSite: 'G-C0E3', // SRT + CornerstoneFreeText: Cornerstone3DCodeScheme.codeValues.CORNERSTONEFREETEXT, +}; + +export { CodeNameCodeSequenceValues as default }; diff --git a/extensions/cornerstone-dicom-sr/src/getSopClassHandlerModule.ts b/extensions/cornerstone-dicom-sr/src/getSopClassHandlerModule.ts index be946bcfb1..9c035faa24 100644 --- a/extensions/cornerstone-dicom-sr/src/getSopClassHandlerModule.ts +++ b/extensions/cornerstone-dicom-sr/src/getSopClassHandlerModule.ts @@ -3,6 +3,7 @@ import { utils, classes, DisplaySetService, Types } from '@ohif/core'; import addDICOMSRDisplayAnnotation from './utils/addDICOMSRDisplayAnnotation'; import isRehydratable from './utils/isRehydratable'; import { adaptersSR } from '@cornerstonejs/adapters'; +import CodeNameCodeSequenceValues from './constants/CodeNameCodeSequenceValues'; type InstanceMetadata = Types.InstanceMetadata; @@ -16,10 +17,11 @@ const { ImageSet, MetadataProvider: metadataProvider } = classes; // Get stacks from referenced displayInstanceUID and load into wrapped CornerStone viewport. const sopClassUids = [ - '1.2.840.10008.5.1.4.1.1.88.11', //BASIC_TEXT_SR: - '1.2.840.10008.5.1.4.1.1.88.22', //ENHANCED_SR: - '1.2.840.10008.5.1.4.1.1.88.33', //COMPREHENSIVE_SR: - '1.2.840.10008.5.1.4.1.1.88.34', //COMPREHENSIVE_3D_SR: + '1.2.840.10008.5.1.4.1.1.88.11', // BASIC TEXT SR + '1.2.840.10008.5.1.4.1.1.88.22', // ENHANCED SR + '1.2.840.10008.5.1.4.1.1.88.33', // COMPREHENSIVE SR + '1.2.840.10008.5.1.4.1.1.88.34', // Comprehensive 3D SR + // '1.2.840.10008.5.1.4.1.1.88.50', // Mammography CAD SR ]; const CORNERSTONE_3D_TOOLS_SOURCE_NAME = 'Cornerstone3DTools'; @@ -34,19 +36,6 @@ const validateSameStudyUID = (uid: string, instances): void => { }); }; -const CodeNameCodeSequenceValues = { - ImagingMeasurementReport: '126000', - ImageLibrary: '111028', - ImagingMeasurements: '126010', - MeasurementGroup: '125007', - ImageLibraryGroup: '126200', - TrackingUniqueIdentifier: '112040', - TrackingIdentifier: '112039', - Finding: '121071', - FindingSite: 'G-C0E3', // SRT - CornerstoneFreeText: Cornerstone3DCodeScheme.codeValues.CORNERSTONEFREETEXT, // -}; - const CodingSchemeDesignators = { SRT: 'SRT', CornerstoneCodeSchemes: [Cornerstone3DCodeScheme.CodingSchemeDesignator, 'CST4'], @@ -85,7 +74,11 @@ function addInstances(instances: InstanceMetadata[], displaySetService: DisplayS * @param servicesManager is the services that can be used for creating * @returns The list of display sets created for the given instances object */ -function _getDisplaySetsFromSeries(instances, servicesManager, extensionManager) { +function _getDisplaySetsFromSeries( + instances, + servicesManager: AppTypes.ServicesManager, + extensionManager +) { // If the series has no instances, stop here if (!instances || !instances.length) { throw new Error('No instances were provided'); @@ -109,22 +102,10 @@ function _getDisplaySetsFromSeries(instances, servicesManager, extensionManager) } = instance; validateSameStudyUID(instance.StudyInstanceUID, instances); - if ( - !ConceptNameCodeSequence || - ConceptNameCodeSequence.CodeValue !== CodeNameCodeSequenceValues.ImagingMeasurementReport - ) { - servicesManager.services.uiNotificationService.show({ - title: 'DICOM SR', - message: - 'OHIF only supports TID1500 Imaging Measurement Report Structured Reports. The SR you’re trying to view is not supported.', - type: 'warning', - duration: 6000, - }); - return []; - } + const isImagingMeasurementReport = + ConceptNameCodeSequence?.CodeValue === CodeNameCodeSequenceValues.ImagingMeasurementReport; const displaySet = { - //plugin: id, Modality: 'SR', displaySetInstanceUID: utils.guid(), SeriesDescription, @@ -140,6 +121,7 @@ function _getDisplaySetsFromSeries(instances, servicesManager, extensionManager) measurements: null, isDerivedDisplaySet: true, isLoaded: false, + isImagingMeasurementReport, sopClassUids, instance, addInstances, @@ -150,11 +132,10 @@ function _getDisplaySetsFromSeries(instances, servicesManager, extensionManager) return [displaySet]; } -async function _load(displaySet, servicesManager, extensionManager) { +async function _load(displaySet, servicesManager: AppTypes.ServicesManager, extensionManager) { const { displaySetService, measurementService } = servicesManager.services; const dataSources = extensionManager.getDataSources(); const dataSource = dataSources[0]; - const { ContentSequence } = displaySet.instance; async function retrieveBulkData(obj, parentObj = null, key = null) { @@ -181,8 +162,13 @@ async function _load(displaySet, servicesManager, extensionManager) { await retrieveBulkData(ContentSequence); } - displaySet.referencedImages = _getReferencedImagesList(ContentSequence); - displaySet.measurements = _getMeasurements(ContentSequence); + if (displaySet.isImagingMeasurementReport) { + displaySet.referencedImages = _getReferencedImagesList(ContentSequence); + displaySet.measurements = _getMeasurements(ContentSequence); + } else { + displaySet.referencedImages = []; + displaySet.measurements = []; + } const mappings = measurementService.getSourceMappings( CORNERSTONE_3D_TOOLS_SOURCE_NAME, @@ -223,7 +209,7 @@ function _checkIfCanAddMeasurementsToDisplaySet( srDisplaySet, newDisplaySet, dataSource, - servicesManager + servicesManager: AppTypes.ServicesManager ) { const { customizationService } = servicesManager.services; let unloadedMeasurements = srDisplaySet.measurements.filter( @@ -367,6 +353,10 @@ function _getMeasurements(ImagingMeasurementReportContentSequence) { item.ConceptNameCodeSequence.CodeValue === CodeNameCodeSequenceValues.ImagingMeasurements ); + if (!ImagingMeasurements) { + return []; + } + const MeasurementGroups = _getSequenceAsArray(ImagingMeasurements.ContentSequence).filter( item => item.ConceptNameCodeSequence.CodeValue === CodeNameCodeSequenceValues.MeasurementGroup ); @@ -621,6 +611,10 @@ function _getReferencedImagesList(ImagingMeasurementReportContentSequence) { item => item.ConceptNameCodeSequence.CodeValue === CodeNameCodeSequenceValues.ImageLibrary ); + if (!ImageLibrary) { + return []; + } + const ImageLibraryGroup = _getSequenceAsArray(ImageLibrary.ContentSequence).find( item => item.ConceptNameCodeSequence.CodeValue === CodeNameCodeSequenceValues.ImageLibraryGroup ); diff --git a/extensions/cornerstone-dicom-sr/src/index.tsx b/extensions/cornerstone-dicom-sr/src/index.tsx index b0b5e7abb1..e479307d23 100644 --- a/extensions/cornerstone-dicom-sr/src/index.tsx +++ b/extensions/cornerstone-dicom-sr/src/index.tsx @@ -10,7 +10,7 @@ import hydrateStructuredReport from './utils/hydrateStructuredReport'; import createReferencedImageDisplaySet from './utils/createReferencedImageDisplaySet'; const Component = React.lazy(() => { - return import(/* webpackPrefetch: true */ './viewports/OHIFCornerstoneSRViewport'); + return import(/* webpackPrefetch: true */ './components/OHIFCornerstoneSRViewport'); }); const OHIFCornerstoneSRViewport = props => { diff --git a/extensions/cornerstone-dicom-sr/src/utils/formatContentItem.ts b/extensions/cornerstone-dicom-sr/src/utils/formatContentItem.ts new file mode 100644 index 0000000000..1446077552 --- /dev/null +++ b/extensions/cornerstone-dicom-sr/src/utils/formatContentItem.ts @@ -0,0 +1,67 @@ +import { utils } from '@ohif/core'; + +/** + * Formatters used to format each of the content items (SR "nodes") which can be + * text, code, UID ref, number, person name, date, time and date time. Each + * formatter must be a function with the following signature: + * + * [VALUE_TYPE]: (contentItem) => string + * + */ +const contentItemFormatters = { + TEXT: contentItem => contentItem.TextValue, + CODE: contentItem => contentItem.ConceptCodeSequence?.[0]?.CodeMeaning, + UIDREF: contentItem => contentItem.UID, + NUM: contentItem => { + const measuredValue = contentItem.MeasuredValueSequence?.[0]; + + if (!measuredValue) { + return; + } + + const { NumericValue, MeasurementUnitsCodeSequence } = measuredValue; + const { CodeValue } = MeasurementUnitsCodeSequence; + + return `${NumericValue} ${CodeValue}`; + }, + PNAME: contentItem => { + const personName = contentItem.PersonName?.[0]?.Alphabetic; + return personName ? utils.formatPN(personName) : undefined; + }, + DATE: contentItem => { + const { Date } = contentItem; + return Date ? utils.formatDate(Date) : undefined; + }, + TIME: contentItem => { + const { Time } = contentItem; + return Time ? utils.formatTime(Time) : undefined; + }, + DATETIME: contentItem => { + const { DateTime } = contentItem; + + if (typeof DateTime !== 'string') { + return; + } + + // 14 characters because it should be something like 20180614113714 + if (DateTime.length < 14) { + return DateTime; + } + + const dicomDate = DateTime.substring(0, 8); + const dicomTime = DateTime.substring(8, 14); + const formattedDate = utils.formatDate(dicomDate); + const formattedTime = utils.formatTime(dicomTime); + + return `${formattedDate} ${formattedTime}`; + }, +}; + +function formatContentItemValue(contentItem) { + const { ValueType } = contentItem; + const fnFormat = contentItemFormatters[ValueType]; + + return fnFormat ? fnFormat(contentItem) : `[${ValueType} is not supported]`; +} + +export { formatContentItemValue as default, formatContentItemValue }; diff --git a/extensions/cornerstone-dicom-sr/src/utils/hydrateStructuredReport.js b/extensions/cornerstone-dicom-sr/src/utils/hydrateStructuredReport.ts similarity index 99% rename from extensions/cornerstone-dicom-sr/src/utils/hydrateStructuredReport.js rename to extensions/cornerstone-dicom-sr/src/utils/hydrateStructuredReport.ts index 7dc9e657ad..c254d1758c 100644 --- a/extensions/cornerstone-dicom-sr/src/utils/hydrateStructuredReport.js +++ b/extensions/cornerstone-dicom-sr/src/utils/hydrateStructuredReport.ts @@ -43,7 +43,7 @@ const convertSites = (codingValues, sites) => { * */ export default function hydrateStructuredReport( - { servicesManager, extensionManager, appConfig }, + { servicesManager, extensionManager, appConfig }: withAppTypes, displaySetInstanceUID ) { const annotationManager = CsAnnotation.state.getAnnotationManager(); diff --git a/extensions/cornerstone-dynamic-volume/CHANGELOG.md b/extensions/cornerstone-dynamic-volume/CHANGELOG.md index 23b8395f3a..e89536b94c 100644 --- a/extensions/cornerstone-dynamic-volume/CHANGELOG.md +++ b/extensions/cornerstone-dynamic-volume/CHANGELOG.md @@ -3,6 +3,741 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.9.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.70...v3.9.0-beta.71) (2024-07-30) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.69...v3.9.0-beta.70) (2024-07-30) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.68...v3.9.0-beta.69) (2024-07-27) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.67...v3.9.0-beta.68) (2024-07-26) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.66...v3.9.0-beta.67) (2024-07-26) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.65...v3.9.0-beta.66) (2024-07-24) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.64...v3.9.0-beta.65) (2024-07-23) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.63...v3.9.0-beta.64) (2024-07-19) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.62...v3.9.0-beta.63) (2024-07-10) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.61...v3.9.0-beta.62) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.60...v3.9.0-beta.61) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.59...v3.9.0-beta.60) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.58...v3.9.0-beta.59) (2024-07-05) + + +### Bug Fixes + +* Cobb angle not working in basic-test mode and open contour ([#4280](https://github.com/OHIF/Viewers/issues/4280)) ([6fd3c7e](https://github.com/OHIF/Viewers/commit/6fd3c7e293fec851dd30e650c1347cc0bc7a99ee)) +* webpack import bugs showing warnings on import ([#4265](https://github.com/OHIF/Viewers/issues/4265)) ([24c511f](https://github.com/OHIF/Viewers/commit/24c511f4bc04c4143bbd3d0d48029f41f7f36014)) + + + + + +# [3.9.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.57...v3.9.0-beta.58) (2024-07-04) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.56...v3.9.0-beta.57) (2024-07-02) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.55...v3.9.0-beta.56) (2024-07-02) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.54...v3.9.0-beta.55) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.53...v3.9.0-beta.54) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.52...v3.9.0-beta.53) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.51...v3.9.0-beta.52) (2024-06-27) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.50...v3.9.0-beta.51) (2024-06-27) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.49...v3.9.0-beta.50) (2024-06-26) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.48...v3.9.0-beta.49) (2024-06-26) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.47...v3.9.0-beta.48) (2024-06-25) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.46...v3.9.0-beta.47) (2024-06-21) + + +### Bug Fixes + +* Allow the mode setup/creation to be async, and provide a few more values to extension/app config/mode setup. ([#4016](https://github.com/OHIF/Viewers/issues/4016)) ([88575c6](https://github.com/OHIF/Viewers/commit/88575c6c09fd778a31b2f91524163ce65d1639dd)) + + +### Features + +* customization service append and customize functionality should run once ([#4238](https://github.com/OHIF/Viewers/issues/4238)) ([e462fd3](https://github.com/OHIF/Viewers/commit/e462fd31f7944acfee34f08cfbc28cfd9de16169)) + + + + + +# [3.9.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.45...v3.9.0-beta.46) (2024-06-18) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.44...v3.9.0-beta.45) (2024-06-18) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.43...v3.9.0-beta.44) (2024-06-17) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.42...v3.9.0-beta.43) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.41...v3.9.0-beta.42) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.40...v3.9.0-beta.41) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.39...v3.9.0-beta.40) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.38...v3.9.0-beta.39) (2024-06-08) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.37...v3.9.0-beta.38) (2024-06-07) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.36...v3.9.0-beta.37) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.35...v3.9.0-beta.36) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.34...v3.9.0-beta.35) (2024-06-05) + + +### Bug Fixes + +* **seg:** maintain algorithm name and algorithm type when DICOM seg is exported or downloaded ([#4203](https://github.com/OHIF/Viewers/issues/4203)) ([a29e94d](https://github.com/OHIF/Viewers/commit/a29e94de803f79bbb3372d00ad8eb14b4224edc2)) + + + + + +# [3.9.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.33...v3.9.0-beta.34) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.32...v3.9.0-beta.33) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.31...v3.9.0-beta.32) (2024-05-31) + + +### Bug Fixes + +* **tmtv:** crosshairs should not have viewport indicators ([#4197](https://github.com/OHIF/Viewers/issues/4197)) ([f85da32](https://github.com/OHIF/Viewers/commit/f85da32f34389ef7cecae03c07e0af26468b52a6)) + + + + + +# [3.9.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.30...v3.9.0-beta.31) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.29...v3.9.0-beta.30) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.28...v3.9.0-beta.29) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.27...v3.9.0-beta.28) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.26...v3.9.0-beta.27) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.25...v3.9.0-beta.26) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.24...v3.9.0-beta.25) (2024-05-29) + + +### Bug Fixes + +* **ultrasound:** Upgrade cornerstone3D version to resolve coloring issues ([#4181](https://github.com/OHIF/Viewers/issues/4181)) ([75a71db](https://github.com/OHIF/Viewers/commit/75a71db7f89840250ad1c2b35df5a35aceb8be7d)) + + + + + +# [3.9.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.23...v3.9.0-beta.24) (2024-05-29) + + +### Features + +* **measurements:** show untracked measurements in measurement panel under additional findings ([#4160](https://github.com/OHIF/Viewers/issues/4160)) ([18686c2](https://github.com/OHIF/Viewers/commit/18686c2caf13ede3e881303100bd4cc34b8b135f)) + + + + + +# [3.9.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.22...v3.9.0-beta.23) (2024-05-28) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.21...v3.9.0-beta.22) (2024-05-27) + + +### Features + +* **ui:** move to React 18 and base for using shadcn/ui ([#4174](https://github.com/OHIF/Viewers/issues/4174)) ([70f2c79](https://github.com/OHIF/Viewers/commit/70f2c797f42af603d7ea0eb8d23b4103aba66f77)) + + + + + +# [3.9.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.20...v3.9.0-beta.21) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.19...v3.9.0-beta.20) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.18...v3.9.0-beta.19) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.17...v3.9.0-beta.18) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.16...v3.9.0-beta.17) (2024-05-23) + + +### Bug Fixes + +* **crosshairs:** reset angle, position, and slabthickness for crosshairs when reset viewport tool is used ([#4113](https://github.com/OHIF/Viewers/issues/4113)) ([73d9e99](https://github.com/OHIF/Viewers/commit/73d9e99d5d6f38ab6c36f4471d54f18798feacb4)) + + + + + +# [3.9.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.15...v3.9.0-beta.16) (2024-05-23) + + +### Bug Fixes + +* dicom json for orthanc by Update package versions for [@cornerstonejs](https://github.com/cornerstonejs) dependencies ([#4165](https://github.com/OHIF/Viewers/issues/4165)) ([34c7d72](https://github.com/OHIF/Viewers/commit/34c7d72142847486b98c9c52469940083eeaf87e)) + + + + + +# [3.9.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.14...v3.9.0-beta.15) (2024-05-22) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.13...v3.9.0-beta.14) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.12...v3.9.0-beta.13) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.11...v3.9.0-beta.12) (2024-05-21) + + +### Bug Fixes + +* **segmentation:** Address issue where segmentation creation failed on layout change ([#4153](https://github.com/OHIF/Viewers/issues/4153)) ([29944c8](https://github.com/OHIF/Viewers/commit/29944c8512c35718af03c03ef82bc43675ee1872)) + + + + + +# [3.9.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.10...v3.9.0-beta.11) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.9...v3.9.0-beta.10) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.8...v3.9.0-beta.9) (2024-05-17) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.7...v3.9.0-beta.8) (2024-05-16) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.6...v3.9.0-beta.7) (2024-05-15) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.5...v3.9.0-beta.6) (2024-05-15) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.4...v3.9.0-beta.5) (2024-05-14) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.3...v3.9.0-beta.4) (2024-05-14) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.2...v3.9.0-beta.3) (2024-05-08) + + +### Features + +* **typings:** Enhance typing support with withAppTypes and custom services throughout OHIF ([#4090](https://github.com/OHIF/Viewers/issues/4090)) ([374065b](https://github.com/OHIF/Viewers/commit/374065bc3bad9d212f9817a8d41546cc64cfabfb)) + + + + + +# [3.9.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.1...v3.9.0-beta.2) (2024-05-06) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.9.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.0...v3.9.0-beta.1) (2024-05-06) + + +### Bug Fixes + +* **rt:** enhanced RT support, utilize SVGs for rendering. ([#4074](https://github.com/OHIF/Viewers/issues/4074)) ([0156bc4](https://github.com/OHIF/Viewers/commit/0156bc426f1840ae0d090223e94a643726e856cb)) + + + + + +# [3.9.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.94...v3.9.0-beta.0) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.8.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0-beta.94) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29) + + +### Bug Fixes + +* **toolbox:** Preserve user-specified tool state and streamline command execution ([#4063](https://github.com/OHIF/Viewers/issues/4063)) ([f1a736d](https://github.com/OHIF/Viewers/commit/f1a736d1934733a434cb87b2c284907a3122403f)) + + + + + +# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28) + + +### Bug Fixes + +* **bugs:** fix patient header for doc, track ball rotate resize observer and add segmentation button not being enabled on viewport data change ([#4068](https://github.com/OHIF/Viewers/issues/4068)) ([c09311d](https://github.com/OHIF/Viewers/commit/c09311d3b7df05fcd00a9f36a7233e9d7e5589d0)) + + + + + +# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22) + + +### Bug Fixes + +* **viewport-webworker-segmentation:** Resolve issues with viewport detection, webworker termination, and segmentation panel layout change ([#4059](https://github.com/OHIF/Viewers/issues/4059)) ([52a0c59](https://github.com/OHIF/Viewers/commit/52a0c59294a4161fcca0a6708855549034849951)) + + + + + +# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19) + + +### Features + +* **tmtv-mode:** Add Brush tools and move SUV peak calculation to web worker ([#4053](https://github.com/OHIF/Viewers/issues/4053)) ([8192e34](https://github.com/OHIF/Viewers/commit/8192e348eca993fec331d4963efe88f9a730eceb)) + + + + + +# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19) + + +### Bug Fixes + +* **layouts:** and fix thumbnail in touch and update migration guide for 3.8 release ([#4052](https://github.com/OHIF/Viewers/issues/4052)) ([d250d04](https://github.com/OHIF/Viewers/commit/d250d04580883446fcb8d748b2a97c5c198922af)) + + + + + +# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18) + +**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume + + + + + +# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18) + + +### Bug Fixes + +* **bugs:** and replace seriesInstanceUID and seriesInstanceUIDs URL with seriesInstanceUIDs ([#4049](https://github.com/OHIF/Viewers/issues/4049)) ([da7c1a5](https://github.com/OHIF/Viewers/commit/da7c1a5d8c54bfa1d3f97bbc500386bf76e7fd9d)) + + + + + +# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18) + + +### Bug Fixes + +* **bugs:** enhancements and bug fixes - final ([#4048](https://github.com/OHIF/Viewers/issues/4048)) ([170bb96](https://github.com/OHIF/Viewers/commit/170bb96983082c39b22b7352e0c54aacf3e73b02)) + + + + + # [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17) diff --git a/extensions/cornerstone-dynamic-volume/package.json b/extensions/cornerstone-dynamic-volume/package.json index 1c0ba18c14..bb5295ef27 100644 --- a/extensions/cornerstone-dynamic-volume/package.json +++ b/extensions/cornerstone-dynamic-volume/package.json @@ -1,6 +1,6 @@ { "name": "@ohif/extension-cornerstone-dynamic-volume", - "version": "3.8.0-beta.82", + "version": "3.9.0-beta.71", "description": "OHIF extension for 4D volumes data", "author": "OHIF", "license": "MIT", @@ -29,22 +29,22 @@ "test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests" }, "peerDependencies": { - "@ohif/core": "3.8.0-beta.82", - "@ohif/extension-cornerstone": "3.8.0-beta.82", - "@ohif/extension-default": "3.8.0-beta.82", - "@ohif/i18n": "3.8.0-beta.82", - "@ohif/ui": "3.8.0-beta.82", - "dcmjs": "^0.29.5", + "@ohif/core": "3.9.0-beta.71", + "@ohif/extension-cornerstone": "3.9.0-beta.71", + "@ohif/extension-default": "3.9.0-beta.71", + "@ohif/i18n": "3.9.0-beta.71", + "@ohif/ui": "3.9.0-beta.71", + "dcmjs": "*", "dicom-parser": "^1.8.21", "hammerjs": "^2.0.8", "prop-types": "^15.6.2", - "react": "^17.0.2" + "react": "^18.3.1" }, "dependencies": { "@babel/runtime": "^7.20.13", - "@cornerstonejs/core": "^1.70.6", - "@cornerstonejs/streaming-image-volume-loader": "^1.70.6", - "@cornerstonejs/tools": "^1.70.6", + "@cornerstonejs/core": "^1.82.0", + "@cornerstonejs/streaming-image-volume-loader": "^1.82.0", + "@cornerstonejs/tools": "^1.82.0", "classnames": "^2.3.2" } } diff --git a/extensions/cornerstone-dynamic-volume/src/actions/updateSegmentationsChartDisplaySet.ts b/extensions/cornerstone-dynamic-volume/src/actions/updateSegmentationsChartDisplaySet.ts index 810d98488a..1f013d9861 100644 --- a/extensions/cornerstone-dynamic-volume/src/actions/updateSegmentationsChartDisplaySet.ts +++ b/extensions/cornerstone-dynamic-volume/src/actions/updateSegmentationsChartDisplaySet.ts @@ -265,7 +265,7 @@ function _getInstanceFromSegmentations(segmentations, displaySetService) { return { seriesMetadata, instance }; } -function updateSegmentationsChartDisplaySet({ servicesManager }): void { +function updateSegmentationsChartDisplaySet({ servicesManager }: withAppTypes): void { const { segmentationService, displaySetService } = servicesManager.services; const segmentations = segmentationService.getSegmentations(); const { seriesMetadata, instance } = diff --git a/extensions/cornerstone-dynamic-volume/src/commandsModule.ts b/extensions/cornerstone-dynamic-volume/src/commandsModule.ts index a6cdf6cda3..7828dd3f63 100644 --- a/extensions/cornerstone-dynamic-volume/src/commandsModule.ts +++ b/extensions/cornerstone-dynamic-volume/src/commandsModule.ts @@ -4,7 +4,7 @@ import { cache } from '@cornerstonejs/core'; const LABELMAP = Enums.SegmentationRepresentations.Labelmap; -const commandsModule = ({ commandsManager, servicesManager }) => { +const commandsModule = ({ commandsManager, servicesManager }: withAppTypes) => { const services = servicesManager.services; const { displaySetService, viewportGridService, segmentationService } = services; diff --git a/extensions/cornerstone-dynamic-volume/src/getPanelModule.tsx b/extensions/cornerstone-dynamic-volume/src/getPanelModule.tsx index a32b5243d5..41f4538479 100644 --- a/extensions/cornerstone-dynamic-volume/src/getPanelModule.tsx +++ b/extensions/cornerstone-dynamic-volume/src/getPanelModule.tsx @@ -43,21 +43,21 @@ function getPanelModule({ commandsManager, extensionManager, servicesManager }) return [ { name: 'dynamic-volume', - iconName: 'group-layers', + iconName: 'tab-4d', iconLabel: '4D Workflow', label: '4D Workflow', component: wrappedDynamicDataPanel, }, { name: 'dynamic-toolbox', - iconName: 'group-layers', + iconName: 'tab-4d', iconLabel: '4D Workflow', label: 'Dynamic Toolbox', component: wrappedDynamicToolbox, }, { name: 'dynamic-export', - iconName: 'group-layers', + iconName: 'tab-4d', iconLabel: '4D Workflow', label: '4D Workflow', component: wrappedDynamicExport, diff --git a/extensions/cornerstone-dynamic-volume/src/panels/DynamicDataPanel.tsx b/extensions/cornerstone-dynamic-volume/src/panels/DynamicDataPanel.tsx index 6be93c1d36..d885d2e957 100644 --- a/extensions/cornerstone-dynamic-volume/src/panels/DynamicDataPanel.tsx +++ b/extensions/cornerstone-dynamic-volume/src/panels/DynamicDataPanel.tsx @@ -4,7 +4,7 @@ import PanelGenerateImage from './PanelGenerateImage'; function DynamicDataPanel({ servicesManager, commandsManager }) { return (
{ - const defaultComponents = extensionManager.getModuleEntry( - '@ohif/extension-default.customizationModule.default' - ).value; - - return defaultComponents.find( - component => component.id === 'progressDropdownWithServiceComponent' +function WorkflowPanel({ servicesManager }: { servicesManager: ServicesManager }) { + const ProgressDropdownWithService = + servicesManager.services.customizationService.getCustomization( + 'progressDropdownWithServiceComponent' ).component; - }, [extensionManager]); return (
{ +const OHIFCornerstoneViewport = React.memo((props: withAppTypes) => { const { displaySets, dataSource, @@ -108,11 +107,13 @@ const OHIFCornerstoneViewport = React.memo(props => { displaySetOptions, servicesManager, onElementEnabled, + // eslint-disable-next-line react/prop-types onElementDisabled, - isJumpToMeasurementDisabled, + isJumpToMeasurementDisabled = false, // Note: you SHOULD NOT use the initialImageIdOrIndex for manipulation // of the imageData in the OHIFCornerstoneViewport. This prop is used // to set the initial state of the viewport's first image to render + // eslint-disable-next-line react/prop-types initialImageIndex, // if the viewport is part of a hanging protocol layout // we should not really rely on the old synchronizers and @@ -120,6 +121,7 @@ const OHIFCornerstoneViewport = React.memo(props => { // is not part of the hanging protocol layout. HPs should // define their own synchronizers. Since the synchronizers are // viewportId dependent and + // eslint-disable-next-line react/prop-types isHangingProtocolLayout, } = props; @@ -129,16 +131,21 @@ const OHIFCornerstoneViewport = React.memo(props => { throw new Error('Viewport ID is required'); } + // Make sure displaySetOptions has one object per displaySet + while (displaySetOptions.length < displaySets.length) { + displaySetOptions.push({}); + } + // Since we only have support for dynamic data in volume viewports, we should // handle this case here and set the viewportType to volume if any of the // displaySets are dynamic volumes - viewportOptions.viewportType = displaySets.some(ds => ds.isDynamicVolume) + viewportOptions.viewportType = displaySets.some(ds => ds.isDynamicVolume && ds.isReconstructable) ? 'volume' : viewportOptions.viewportType; const [scrollbarHeight, setScrollbarHeight] = useState('100px'); const [enabledVPElement, setEnabledVPElement] = useState(null); - const elementRef = useRef(); + const elementRef = useRef() as React.MutableRefObject; const [appConfig] = useAppConfig(); const { @@ -152,7 +159,7 @@ const OHIFCornerstoneViewport = React.memo(props => { viewportGridService, stateSyncService, viewportActionCornersService, - } = servicesManager.services as CornerstoneServices; + } = servicesManager.services; const [viewportDialogState] = useViewportDialog(); // useCallback for scroll bar height calculation @@ -415,19 +422,21 @@ const OHIFCornerstoneViewport = React.memo(props => { }); }, [displaySets, viewportId, viewportActionCornersService, servicesManager, commandsManager]); + const { ref: resizeRef } = useResizeDetector({ + onResize, + }); return (
-
e.preventDefault()} onMouseDown={e => e.preventDefault()} - ref={elementRef} + ref={el => { + resizeRef.current = el; + elementRef.current = el; + }} >
i.SOPInstanceUID === SOPInstanceUID ); + // the index is reversed in the volume viewport + // imageIdIndex = referencedDisplaySet.images.length - 1 - imageIdIndex; + const { viewPlaneNormal: viewportViewPlane } = viewport.getCamera(); // should compare abs for both planes since the direction can be flipped @@ -675,10 +690,6 @@ function _rehydrateSynchronizers( // Component displayName OHIFCornerstoneViewport.displayName = 'OHIFCornerstoneViewport'; -OHIFCornerstoneViewport.defaultProps = { - isJumpToMeasurementDisabled: false, -}; - OHIFCornerstoneViewport.propTypes = { displaySets: PropTypes.array.isRequired, dataSource: PropTypes.object.isRequired, diff --git a/extensions/cornerstone/src/Viewport/Overlays/CornerstoneOverlays.tsx b/extensions/cornerstone/src/Viewport/Overlays/CornerstoneOverlays.tsx index 69f7b10faa..43ec800c45 100644 --- a/extensions/cornerstone/src/Viewport/Overlays/CornerstoneOverlays.tsx +++ b/extensions/cornerstone/src/Viewport/Overlays/CornerstoneOverlays.tsx @@ -5,7 +5,7 @@ import CustomizableViewportOverlay from './CustomizableViewportOverlay'; import ViewportOrientationMarkers from './ViewportOrientationMarkers'; import ViewportImageSliceLoadingIndicator from './ViewportImageSliceLoadingIndicator'; -function CornerstoneOverlays(props) { +function CornerstoneOverlays(props: withAppTypes) { const { viewportId, element, scrollbarHeight, servicesManager } = props; const { cornerstoneViewportService } = servicesManager.services; const [imageSliceData, setImageSliceData] = useState({ diff --git a/extensions/cornerstone/src/Viewport/Overlays/CustomizableViewportOverlay.tsx b/extensions/cornerstone/src/Viewport/Overlays/CustomizableViewportOverlay.tsx index 19647b732c..9436c1fa39 100644 --- a/extensions/cornerstone/src/Viewport/Overlays/CustomizableViewportOverlay.tsx +++ b/extensions/cornerstone/src/Viewport/Overlays/CustomizableViewportOverlay.tsx @@ -4,7 +4,6 @@ import PropTypes from 'prop-types'; import { metaData, Enums, utilities } from '@cornerstonejs/core'; import { ImageSliceData } from '@cornerstonejs/core/dist/esm/types'; import { ViewportOverlay } from '@ohif/ui'; -import { ServicesManager } from '@ohif/core'; import { InstanceMetadata } from '@ohif/core/src/types'; import { formatPN, formatDICOMDate, formatDICOMTime, formatNumberPrecision } from './utils'; import { StackViewportData, VolumeViewportData } from '../../types/CornerstoneCacheService'; @@ -19,7 +18,7 @@ interface OverlayItemProps { element: HTMLElement; viewportData: ViewportData; imageSliceData: ImageSliceData; - servicesManager: ServicesManager; + servicesManager: AppTypes.ServicesManager; viewportId: string; instance: InstanceMetadata; customization: any; @@ -40,11 +39,82 @@ interface OverlayItemProps { } const OverlayItemComponents = { + 'ohif.overlayItem': OverlayItem, 'ohif.overlayItem.windowLevel': VOIOverlayItem, 'ohif.overlayItem.zoomLevel': ZoomOverlayItem, 'ohif.overlayItem.instanceNumber': InstanceNumberOverlayItem, }; + +const studyDateItem = { + id: 'StudyDate', + customizationType: 'ohif.overlayItem', + label: '', + title: 'Study date', + condition: ({ referenceInstance }) => referenceInstance?.StudyDate, + contentF: ({ referenceInstance, formatters: { formatDate } }) => formatDate(referenceInstance.StudyDate), +}; + +const seriesDescriptionItem = { + id: 'SeriesDescription', + customizationType: 'ohif.overlayItem', + label: '', + title: 'Series description', + condition: ({ referenceInstance }) => { + return referenceInstance && referenceInstance.SeriesDescription; + }, + contentF: ({ referenceInstance }) => referenceInstance.SeriesDescription +}; + +const topLeftItems = { id: 'cornerstoneOverlayTopLeft', items: [studyDateItem, seriesDescriptionItem] }; + +const topRightItems = { id: 'cornerstoneOverlayTopRight', items: [] }; + +const bottomLeftItems = { + id: 'cornerstoneOverlayBottomLeft', items: [ + { + id: 'WindowLevel', + customizationType: 'ohif.overlayItem.windowLevel', + }, + { + id: 'ZoomLevel', + customizationType: 'ohif.overlayItem.zoomLevel', + condition: (props) => { + const activeToolName = props.toolGroupService.getActiveToolForViewport(props.viewportId); + return activeToolName === 'Zoom'; + }, + }, + ] +}; + +const bottomRightItems = { + id: 'cornerstoneOverlayBottomRight', + items: [ + { + id: 'InstanceNumber', + customizationType: 'ohif.overlayItem.instanceNumber', + }, + ] +}; + +/** + * The @ohif/cornerstoneOverlay is a default value for a customization + * for the cornerstone overlays. The intent is to allow it to be extended + * without needing to re-write the individual overlays by using the append + * mechanism. Individual attributes can be modified individually without + * affecting the other items by using the append as well, with position + * based replacement. + * This is used as a default in the getCustomizationModule so that it + * is available early for additional customization extensions. + */ +const CornerstoneOverlay = { + id: '@ohif/cornerstoneOverlay', + topLeftItems, + topRightItems, + bottomLeftItems, + bottomRightItems, +}; + /** * Customizable Viewport Overlay */ @@ -59,34 +129,35 @@ function CustomizableViewportOverlay({ viewportData: ViewportData; imageSliceData: ImageSliceData; viewportId: string; - servicesManager: ServicesManager; + servicesManager: AppTypes.ServicesManager; }) { - const { cornerstoneViewportService, customizationService, toolGroupService } = + const { cornerstoneViewportService, customizationService, toolGroupService, displaySetService } = servicesManager.services; const [voi, setVOI] = useState({ windowCenter: null, windowWidth: null }); const [scale, setScale] = useState(1); const { imageIndex } = imageSliceData; - const topLeftCustomization = customizationService.getModeCustomization( + // The new customization is 'cornerstoneOverlay', with an append or replace + // on the individual items rather than defining individual items. + const cornerstoneOverlay = customizationService.getCustomization('@ohif/cornerstoneOverlay'); + + // Historical usage defined the overlays as separate items due to lack of + // append functionality. This code enables the historical usage, but + // the recommended functionality is to append to the default values in + // cornerstoneOverlay rather than defining individual items. + const topLeftCustomization = customizationService.getCustomization( 'cornerstoneOverlayTopLeft' - ); - const topRightCustomization = customizationService.getModeCustomization( + ) || cornerstoneOverlay?.topLeftItems; + const topRightCustomization = customizationService.getCustomization( 'cornerstoneOverlayTopRight' - ); - const bottomLeftCustomization = customizationService.getModeCustomization( + ) || cornerstoneOverlay?.topRightItems; + const bottomLeftCustomization = customizationService.getCustomization( 'cornerstoneOverlayBottomLeft' - ); - const bottomRightCustomization = customizationService.getModeCustomization( + ) || cornerstoneOverlay?.bottomLeftItems; + const bottomRightCustomization = customizationService.getCustomization( 'cornerstoneOverlayBottomRight' - ); + ) || cornerstoneOverlay?.bottomRightItems; - const instances = useMemo(() => { - if (viewportData != null) { - return _getViewportInstances(viewportData); - } else { - return null; - } - }, [viewportData, imageIndex]); const instanceNumber = useMemo( () => @@ -96,6 +167,23 @@ function CustomizableViewportOverlay({ [viewportData, viewportId, imageIndex, cornerstoneViewportService] ); + const displaySetProps = useMemo(() => { + const displaySets = getDisplaySets(viewportData, displaySetService); + if (!displaySets) { + return null; + } + const [displaySet] = displaySets; + const { instances, instance: referenceInstance } = displaySet; + return { + displaySets, + displaySet, + instance: instances[imageIndex], + instances, + referenceInstance, + }; + }, [viewportData, viewportId, instanceNumber, cornerstoneViewportService]); + + /** * Updating the VOI when the viewport changes its voi */ @@ -137,20 +225,8 @@ function CustomizableViewportOverlay({ return; } - const imageData = viewport.getImageData(); - - if (!imageData) { - return; - } - - if (camera.scale) { - setScale(camera.scale); - return; - } + const scale = viewport.getZoom(); - const { spacing } = imageData; - // convert parallel scale to scale - const scale = (element.clientHeight * spacing[0] * 0.5) / camera.parallelScale; setScale(scale); } }; @@ -163,8 +239,9 @@ function CustomizableViewportOverlay({ }, [viewportId, viewportData, cornerstoneViewportService, element]); const _renderOverlayItem = useCallback( - item => { + (item, props) => { const overlayItemProps = { + ...props, element, viewportData, imageSliceData, @@ -177,10 +254,6 @@ function CustomizableViewportOverlay({ formatTime: formatDICOMTime, formatNumberPrecision, }, - instance: instances ? instances[item?.instanceIndex] : null, - voi, - scale, - instanceNumber, }; if (!item) { @@ -195,8 +268,8 @@ function CustomizableViewportOverlay({ } else { const renderItem = customizationService.transform(item); - if (typeof renderItem.content === 'function') { - return renderItem.content(overlayItemProps); + if (typeof renderItem.contentF === 'function') { + return renderItem.contentF(overlayItemProps); } } }, @@ -207,7 +280,7 @@ function CustomizableViewportOverlay({ viewportId, servicesManager, customizationService, - instances, + displaySetProps, voi, scale, instanceNumber, @@ -215,20 +288,26 @@ function CustomizableViewportOverlay({ ); const getContent = useCallback( - (customization, defaultItems, keyPrefix) => { - const items = customization?.items ?? defaultItems; + (customization, keyPrefix) => { + if (!customization?.items) { + return null; + } + const { items } = customization; + const props = { + ...displaySetProps, + formatters: { formatDate: formatDICOMDate }, + voi, + scale, + instanceNumber, + viewportId, + toolGroupService, + }; + return ( <> {items.map((item, index) => (
- {item?.condition - ? item.condition({ - instance: instances ? instances[item?.instanceIndex] : null, - formatters: { formatDate: formatDICOMDate }, - }) - ? _renderOverlayItem(item) - : null - : _renderOverlayItem(item)} + {(!item?.condition || item.condition(props)) && _renderOverlayItem(item, props) || null}
))} @@ -237,104 +316,30 @@ function CustomizableViewportOverlay({ [_renderOverlayItem] ); - const studyDateItem = { - id: 'StudyDate', - customizationType: 'ohif.overlayItem', - label: '', - title: 'Study date', - condition: ({ instance }) => instance && instance.StudyDate, - contentF: ({ instance, formatters: { formatDate } }) => formatDate(instance.StudyDate), - }; - - const seriesDescriptionItem = { - id: 'SeriesDescription', - customizationType: 'ohif.overlayItem', - label: '', - title: 'Series description', - attribute: 'SeriesDescription', - condition: ({ instance }) => { - return instance && instance.SeriesDescription; - }, - }; - - const topLeftItems = instances - ? instances - .map((instance, index) => { - return [ - { - ...studyDateItem, - instanceIndex: index, - }, - { - ...seriesDescriptionItem, - instanceIndex: index, - }, - ]; - }) - .flat() - : []; return ( { - const activeToolName = toolGroupService.getActiveToolForViewport(viewportId); - return activeToolName === 'Zoom'; - }, - }, - ], - 'bottomLeftOverlayItem' - )} - bottomRight={getContent( - bottomRightCustomization, - [ - { - id: 'InstanceNumber', - customizationType: 'ohif.overlayItem.instanceNumber', - }, - ], - 'bottomRightOverlayItem' - )} + topLeft={getContent(topLeftCustomization, 'topLeftOverlayItem')} + topRight={getContent(topRightCustomization, 'topRightOverlayItem')} + bottomLeft={getContent(bottomLeftCustomization, 'bottomLeftOverlayItem')} + bottomRight={getContent(bottomRightCustomization, 'bottomRightOverlayItem')} /> ); } -function _getViewportInstances(viewportData) { - const imageIds = []; - if (viewportData.viewportType === Enums.ViewportType.STACK) { - imageIds.push(viewportData.data.imageIds[0]); - } else if (viewportData.viewportType === Enums.ViewportType.ORTHOGRAPHIC) { - const volumes = viewportData.data; - volumes.forEach(volume => { - if (!volume?.imageIds || volume.imageIds.length === 0) { - return; - } - imageIds.push(volume.imageIds[0]); - }); +/** + * Gets an array of display sets for the given viewport, based on the viewport data. + * Returns null if none found. + */ +function getDisplaySets(viewportData, displaySetService) { + if (!viewportData?.data?.length) { + return null; } - const instances = []; - - imageIds.forEach(imageId => { - const instance = metaData.get('instance', imageId) || {}; - instances.push(instance); - }); - return instances; + const displaySets = viewportData.data.map(datum => displaySetService.getDisplaySetByUID(datum.displaySetInstanceUID)).filter(it => !!it); + if (!displaySets.length) { + return null; + } + return displaySets; } const getInstanceNumber = (viewportData, viewportId, imageIndex, cornerstoneViewportService) => { @@ -358,7 +363,7 @@ const getInstanceNumber = (viewportData, viewportId, imageIndex, cornerstoneView }; function _getInstanceNumberFromStack(viewportData, imageIndex) { - const imageIds = viewportData.data.imageIds; + const imageIds = viewportData.data[0].imageIds; const imageId = imageIds[imageIndex]; if (!imageId) { @@ -377,6 +382,7 @@ function _getInstanceNumberFromStack(viewportData, imageIndex) { return parseInt(instanceNumber); } + // Since volume viewports can be in any view direction, they can render // a reconstructed image which don't have imageIds; therefore, no instance and instanceNumber // Here we check if viewport is in the acquisition direction and if so, we get the instanceNumber @@ -424,6 +430,24 @@ function _getInstanceNumberFromVolume( } } +function OverlayItem(props) { + const { instance, customization = {} } = props; + const { color, attribute, title, label, background } = customization; + const value = customization.contentF?.(props, customization) ?? instance?.[attribute]; + if (value === undefined || value === null) { + return null; + } + return ( +
+ {label ? ({label}) : null} + {value} +
); +} + /** * Window Level / Center Overlay item */ @@ -436,7 +460,7 @@ function VOIOverlayItem({ voi, customization }: OverlayItemProps) { return (
W: {windowWidth.toFixed(0)} @@ -497,3 +521,5 @@ CustomizableViewportOverlay.propTypes = { }; export default CustomizableViewportOverlay; + +export { CustomizableViewportOverlay, CornerstoneOverlay }; diff --git a/extensions/cornerstone/src/Viewport/Overlays/ViewportImageScrollbar.tsx b/extensions/cornerstone/src/Viewport/Overlays/ViewportImageScrollbar.tsx index 2f7b71a45d..4de7545522 100644 --- a/extensions/cornerstone/src/Viewport/Overlays/ViewportImageScrollbar.tsx +++ b/extensions/cornerstone/src/Viewport/Overlays/ViewportImageScrollbar.tsx @@ -3,7 +3,6 @@ import PropTypes from 'prop-types'; import { Enums, Types, utilities } from '@cornerstonejs/core'; import { utilities as csToolsUtils } from '@cornerstonejs/tools'; import { ImageScrollbar } from '@ohif/ui'; -import { ServicesManger } from '@ohif/core'; function CornerstoneImageScrollbar({ viewportData, @@ -13,8 +12,8 @@ function CornerstoneImageScrollbar({ setImageSliceData, scrollbarHeight, servicesManager, -}) { - const { cineService, cornerstoneViewportService } = (servicesManager as ServicesManger).services; +}: withAppTypes) { + const { cineService, cornerstoneViewportService } = servicesManager.services; const onImageScrollbarChange = (imageIndex, viewportId) => { const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId); @@ -23,7 +22,7 @@ function CornerstoneImageScrollbar({ if (isCineEnabled) { // on image scrollbar change, stop the CINE if it is playing - cineService.stopClip(element); + cineService.stopClip(element, { viewportId }); cineService.setCine({ id: viewportId, isPlaying: false }); } @@ -49,7 +48,7 @@ function CornerstoneImageScrollbar({ setImageSliceData({ imageIndex: imageIndex, - numberOfSlices: viewportData.data.imageIds.length, + numberOfSlices: viewportData.data[0].imageIds.length, }); return; @@ -79,7 +78,7 @@ function CornerstoneImageScrollbar({ // find the index of imageId in the imageIds setImageSliceData({ imageIndex: newImageIdIndex, - numberOfSlices: viewportData.data.imageIds.length, + numberOfSlices: viewportData.data[0].imageIds.length, }); }; diff --git a/extensions/cornerstone/src/Viewport/Overlays/ViewportImageSliceLoadingIndicator.tsx b/extensions/cornerstone/src/Viewport/Overlays/ViewportImageSliceLoadingIndicator.tsx index 70e03e534c..429fea2cb6 100644 --- a/extensions/cornerstone/src/Viewport/Overlays/ViewportImageSliceLoadingIndicator.tsx +++ b/extensions/cornerstone/src/Viewport/Overlays/ViewportImageSliceLoadingIndicator.tsx @@ -78,14 +78,8 @@ function ViewportImageSliceLoadingIndicator({ viewportData, element }) { } ViewportImageSliceLoadingIndicator.propTypes = { - percentComplete: PropTypes.number, error: PropTypes.object, element: PropTypes.object, }; -ViewportImageSliceLoadingIndicator.defaultProps = { - percentComplete: 0, - error: null, -}; - export default ViewportImageSliceLoadingIndicator; diff --git a/extensions/cornerstone/src/Viewport/Overlays/ViewportOrientationMarkers.tsx b/extensions/cornerstone/src/Viewport/Overlays/ViewportOrientationMarkers.tsx index 45b85b7050..178705f400 100644 --- a/extensions/cornerstone/src/Viewport/Overlays/ViewportOrientationMarkers.tsx +++ b/extensions/cornerstone/src/Viewport/Overlays/ViewportOrientationMarkers.tsx @@ -22,7 +22,7 @@ function ViewportOrientationMarkers({ viewportId, servicesManager, orientationMarkers = ['top', 'left'], -}) { +}: withAppTypes) { // Rotation is in degrees const [rotation, setRotation] = useState(0); const [flipHorizontal, setFlipHorizontal] = useState(false); @@ -64,17 +64,17 @@ function ViewportOrientationMarkers({ return ''; } - let rowCosines, columnCosines; + let rowCosines, columnCosines, isDefaultValueSetForRowCosine, isDefaultValueSetForColumnCosine; if (viewportData.viewportType === 'stack') { const imageIndex = imageSliceData.imageIndex; - const imageId = viewportData.data.imageIds?.[imageIndex]; + const imageId = viewportData.data[0].imageIds?.[imageIndex]; // Workaround for below TODO stub if (!imageId) { return false; } - ({ rowCosines, columnCosines } = metaData.get('imagePlaneModule', imageId) || {}); + ({ rowCosines, columnCosines, isDefaultValueSetForColumnCosine, isDefaultValueSetForColumnCosine } = metaData.get('imagePlaneModule', imageId) || {}); } else { if (!element || !getEnabledElement(element)) { return ''; @@ -90,7 +90,7 @@ function ViewportOrientationMarkers({ rowCosines = viewRight; } - if (!rowCosines || !columnCosines || rotation === undefined) { + if (!rowCosines || !columnCosines || rotation === undefined || isDefaultValueSetForRowCosine || isDefaultValueSetForColumnCosine) { return ''; } @@ -136,16 +136,6 @@ function ViewportOrientationMarkers({ return
{markers}
; } -ViewportOrientationMarkers.propTypes = { - percentComplete: PropTypes.number, - error: PropTypes.object, -}; - -ViewportOrientationMarkers.defaultProps = { - percentComplete: 0, - error: null, -}; - /** * * Computes the orientation labels on a Cornerstone-enabled Viewport element diff --git a/extensions/cornerstone/src/Viewport/Overlays/utils.ts b/extensions/cornerstone/src/Viewport/Overlays/utils.ts index 54f164add3..d8795f3b3b 100644 --- a/extensions/cornerstone/src/Viewport/Overlays/utils.ts +++ b/extensions/cornerstone/src/Viewport/Overlays/utils.ts @@ -62,6 +62,12 @@ export function formatPN(name) { if (!name) { return ''; } + if (typeof name === 'object') { + name = name.Alphabetic; + if (!name) { + return ''; + } + } const cleaned = name .split('^') diff --git a/extensions/cornerstone/src/commandsModule.ts b/extensions/cornerstone/src/commandsModule.ts index f72a710510..69f51168a7 100644 --- a/extensions/cornerstone/src/commandsModule.ts +++ b/extensions/cornerstone/src/commandsModule.ts @@ -20,7 +20,6 @@ import { callLabelAutocompleteDialog, showLabelAnnotationPopup } from './utils/c import toggleImageSliceSync from './utils/imageSliceSync/toggleImageSliceSync'; import { getFirstAnnotationSelected } from './utils/measurementServiceMappings/utils/selection'; import getActiveViewportEnabledElement from './utils/getActiveViewportEnabledElement'; -import { CornerstoneServices } from './types'; import toggleVOISliceSync from './utils/toggleVOISliceSync'; const toggleSyncFunctions = { @@ -44,7 +43,7 @@ function commandsModule({ colorbarService, hangingProtocolService, syncGroupService, - } = servicesManager.services as CornerstoneServices; + } = servicesManager.services; const { measurementServiceSource } = this; @@ -346,9 +345,9 @@ function commandsModule({ } } }, - setToolActiveToolbar: ({ value, itemId, toolGroupIds = [] }) => { + setToolActiveToolbar: ({ value, itemId, toolName, toolGroupIds = [] }) => { // Sometimes it is passed as value (tools with options), sometimes as itemId (toolbar buttons) - const toolName = itemId || value; + toolName = toolName || itemId || value; toolGroupIds = toolGroupIds.length ? toolGroupIds : toolGroupService.getToolGroupIds(); diff --git a/extensions/cornerstone/src/components/ActiveViewportWindowLevel/ActiveViewportWindowLevel.tsx b/extensions/cornerstone/src/components/ActiveViewportWindowLevel/ActiveViewportWindowLevel.tsx index 4a301679fa..295d6bd60a 100644 --- a/extensions/cornerstone/src/components/ActiveViewportWindowLevel/ActiveViewportWindowLevel.tsx +++ b/extensions/cornerstone/src/components/ActiveViewportWindowLevel/ActiveViewportWindowLevel.tsx @@ -1,14 +1,9 @@ import React, { ReactElement } from 'react'; import PropTypes from 'prop-types'; -import { ServicesManager } from '@ohif/core'; import { useViewportGrid } from '@ohif/ui'; import ViewportWindowLevel from '../ViewportWindowLevel/ViewportWindowLevel'; -const ActiveViewportWindowLevel = ({ - servicesManager, -}: { - servicesManager: ServicesManager; -}): ReactElement => { +const ActiveViewportWindowLevel = ({ servicesManager }: withAppTypes): ReactElement => { const [viewportGrid] = useViewportGrid(); const { activeViewportId } = viewportGrid; @@ -25,7 +20,7 @@ const ActiveViewportWindowLevel = ({ }; ActiveViewportWindowLevel.propTypes = { - servicesManager: PropTypes.instanceOf(ServicesManager), + servicesManager: PropTypes.object.isRequired, }; export default ActiveViewportWindowLevel; diff --git a/extensions/cornerstone/src/components/CinePlayer/CinePlayer.tsx b/extensions/cornerstone/src/components/CinePlayer/CinePlayer.tsx index 795ec55295..af78066ab9 100644 --- a/extensions/cornerstone/src/components/CinePlayer/CinePlayer.tsx +++ b/extensions/cornerstone/src/components/CinePlayer/CinePlayer.tsx @@ -4,7 +4,14 @@ import { Enums, eventTarget, cache } from '@cornerstonejs/core'; import { Enums as StreamingEnums } from '@cornerstonejs/streaming-image-volume-loader'; import { useAppConfig } from '@state'; -function WrappedCinePlayer({ enabledVPElement, viewportId, servicesManager }) { +function WrappedCinePlayer({ + enabledVPElement, + viewportId, + servicesManager, +}: withAppTypes<{ + enabledVPElement: HTMLElement; + viewportId: string; +}>) { const { customizationService, displaySetService, viewportGridService } = servicesManager.services; const [{ isCineEnabled, cines }, cineService] = useCine(); const [newStackFrameRate, setNewStackFrameRate] = useState(24); @@ -66,7 +73,7 @@ function WrappedCinePlayer({ enabledVPElement, viewportId, servicesManager }) { } cineService.setCine({ id: viewportId, isPlaying, frameRate }); setNewStackFrameRate(frameRate); - }, [displaySetService, viewportId, viewportGridService, cines, isCineEnabled]); + }, [displaySetService, viewportId, viewportGridService, cines, isCineEnabled, enabledVPElement]); useEffect(() => { isMountedRef.current = true; @@ -78,6 +85,14 @@ function WrappedCinePlayer({ enabledVPElement, viewportId, servicesManager }) { }; }, [isCineEnabled, newDisplaySetHandler]); + useEffect(() => { + if (!isCineEnabled) { + return; + } + + cineHandler(); + }, [isCineEnabled, cineHandler, enabledVPElement]); + /** * Use effect for handling new display set */ @@ -112,7 +127,7 @@ function WrappedCinePlayer({ enabledVPElement, viewportId, servicesManager }) { cineHandler(); return () => { - cineService.stopClip(enabledVPElement); + cineService.stopClip(enabledVPElement, { viewportId }); }; }, [cines, viewportId, cineService, enabledVPElement, cineHandler]); diff --git a/extensions/cornerstone/src/components/ViewportWindowLevel/ViewportWindowLevel.tsx b/extensions/cornerstone/src/components/ViewportWindowLevel/ViewportWindowLevel.tsx index d4e193dd91..5220229654 100644 --- a/extensions/cornerstone/src/components/ViewportWindowLevel/ViewportWindowLevel.tsx +++ b/extensions/cornerstone/src/components/ViewportWindowLevel/ViewportWindowLevel.tsx @@ -1,7 +1,6 @@ import React, { useEffect, useCallback, useState, ReactElement } from 'react'; import PropTypes from 'prop-types'; import debounce from 'lodash.debounce'; -import { ServicesManager } from '@ohif/core'; import { PanelSection, WindowLevel } from '@ohif/ui'; import vtkColorMaps from '@kitware/vtk.js/Rendering/Core/ColorTransferFunction/ColorMaps'; import { Enums, eventTarget, cache as cs3DCache, utilities as csUtils } from '@cornerstonejs/core'; @@ -12,10 +11,9 @@ const { Events } = Enums; const ViewportWindowLevel = ({ servicesManager, viewportId, -}: { - servicesManager: ServicesManager; +}: withAppTypes<{ viewportId: string; -}): ReactElement => { +}>): ReactElement => { const { cornerstoneViewportService } = servicesManager.services; const [windowLevels, setWindowLevels] = useState([]); const [cachedHistograms, setCachedHistograms] = useState({}); @@ -380,7 +378,7 @@ const ViewportWindowLevel = ({ }; ViewportWindowLevel.propTypes = { - servicesManager: PropTypes.instanceOf(ServicesManager), + servicesManager: PropTypes.object.isRequired, viewportId: PropTypes.string.isRequired, }; diff --git a/extensions/cornerstone/src/components/ViewportWindowLevel/getViewportVolumeHistogram.ts b/extensions/cornerstone/src/components/ViewportWindowLevel/getViewportVolumeHistogram.ts index 2d72229fc9..167d49f8a0 100644 --- a/extensions/cornerstone/src/components/ViewportWindowLevel/getViewportVolumeHistogram.ts +++ b/extensions/cornerstone/src/components/ViewportWindowLevel/getViewportVolumeHistogram.ts @@ -2,10 +2,12 @@ import { getWebWorkerManager } from '@cornerstonejs/core'; const workerManager = getWebWorkerManager(); -const options = { - // maxWorkerInstances: 1, - // overwrite: false - autoTerminationOnIdle: 1000, +const WorkerOptions = { + maxWorkerInstances: 1, + autoTerminateOnIdle: { + enabled: true, + idleTimeThreshold: 1000, + }, }; // Register the task @@ -15,9 +17,9 @@ const workerFn = () => { }); }; -workerManager.registerWorker('histogram-worker', workerFn, options); - const getViewportVolumeHistogram = async (viewport, volume, options?) => { + workerManager.registerWorker('histogram-worker', workerFn, WorkerOptions); + if (!volume?.loadStatus.loaded) { return undefined; } diff --git a/extensions/cornerstone/src/components/WindowLevelActionMenu/Colorbar.tsx b/extensions/cornerstone/src/components/WindowLevelActionMenu/Colorbar.tsx index 91493b0728..298c2ae843 100644 --- a/extensions/cornerstone/src/components/WindowLevelActionMenu/Colorbar.tsx +++ b/extensions/cornerstone/src/components/WindowLevelActionMenu/Colorbar.tsx @@ -8,10 +8,10 @@ export function setViewportColorbar( viewportId, displaySets, commandsManager, - serviceManager, + servicesManager: AppTypes.ServicesManager, colorbarOptions ) { - const { cornerstoneViewportService } = serviceManager.services; + const { cornerstoneViewportService } = servicesManager.services; const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId); const viewportInfo = cornerstoneViewportService.getViewportInfo(viewportId); @@ -59,10 +59,10 @@ export function Colorbar({ viewportId, displaySets, commandsManager, - serviceManager, + servicesManager, colorbarProperties, -}: ColorbarProps): ReactElement { - const { colorbarService } = serviceManager.services; +}: withAppTypes): ReactElement { + const { colorbarService } = servicesManager.services; const { width: colorbarWidth, colorbarTickPosition, @@ -73,7 +73,7 @@ export function Colorbar({ const [showColorbar, setShowColorbar] = useState(colorbarService.hasColorbar(viewportId)); const onSetColorbar = useCallback(() => { - setViewportColorbar(viewportId, displaySets, commandsManager, serviceManager, { + setViewportColorbar(viewportId, displaySets, commandsManager, servicesManager, { viewportId, colormaps, ticks: { diff --git a/extensions/cornerstone/src/components/WindowLevelActionMenu/Colormap.tsx b/extensions/cornerstone/src/components/WindowLevelActionMenu/Colormap.tsx index a37eae3a9b..51764c956a 100644 --- a/extensions/cornerstone/src/components/WindowLevelActionMenu/Colormap.tsx +++ b/extensions/cornerstone/src/components/WindowLevelActionMenu/Colormap.tsx @@ -8,9 +8,9 @@ export function Colormap({ viewportId, displaySets, commandsManager, - serviceManager, + servicesManager, }: ColormapProps): ReactElement { - const { cornerstoneViewportService } = serviceManager.services; + const { cornerstoneViewportService } = servicesManager.services; const [activeDisplaySet, setActiveDisplaySet] = useState(displaySets[0]); diff --git a/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeLighting.tsx b/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeLighting.tsx index 7cd7d4f853..6aa6f5610a 100644 --- a/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeLighting.tsx +++ b/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeLighting.tsx @@ -2,11 +2,11 @@ import React, { ReactElement, useState, useEffect, useCallback } from 'react'; import { VolumeLightingProps } from '../../types/ViewportPresets'; export function VolumeLighting({ - serviceManager, + servicesManager, commandsManager, viewportId, }: VolumeLightingProps): ReactElement { - const { cornerstoneViewportService } = serviceManager.services; + const { cornerstoneViewportService } = servicesManager.services; const [ambient, setAmbient] = useState(null); const [diffuse, setDiffuse] = useState(null); const [specular, setSpecular] = useState(null); diff --git a/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeRenderingOptions.tsx b/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeRenderingOptions.tsx index 1e0901ad31..c62515cc83 100644 --- a/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeRenderingOptions.tsx +++ b/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeRenderingOptions.tsx @@ -9,21 +9,21 @@ export function VolumeRenderingOptions({ viewportId, commandsManager, volumeRenderingQualityRange, - serviceManager, + servicesManager, }: VolumeRenderingOptionsProps): ReactElement { return (
LIGHTING
@@ -32,14 +32,14 @@ export function VolumeRenderingOptions({
); diff --git a/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeRenderingPresets.tsx b/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeRenderingPresets.tsx index bbf2c57054..031e5bdc46 100644 --- a/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeRenderingPresets.tsx +++ b/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeRenderingPresets.tsx @@ -5,11 +5,11 @@ import { VolumeRenderingPresetsContent } from './VolumeRenderingPresetsContent'; export function VolumeRenderingPresets({ viewportId, - serviceManager, + servicesManager, commandsManager, volumeRenderingPresets, }: VolumeRenderingPresetsProps): ReactElement { - const { uiModalService } = serviceManager.services; + const { uiModalService } = servicesManager.services; const onClickPresets = () => { uiModalService.show({ diff --git a/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeRenderingQuality.tsx b/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeRenderingQuality.tsx index 7a6fce9a66..01864812e1 100644 --- a/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeRenderingQuality.tsx +++ b/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeRenderingQuality.tsx @@ -4,10 +4,10 @@ import { VolumeRenderingQualityProps } from '../../types/ViewportPresets'; export function VolumeRenderingQuality({ volumeRenderingQualityRange, commandsManager, - serviceManager, + servicesManager, viewportId, }: VolumeRenderingQualityProps): ReactElement { - const { cornerstoneViewportService } = serviceManager.services; + const { cornerstoneViewportService } = servicesManager.services; const { min, max, step } = volumeRenderingQualityRange; const [quality, setQuality] = useState(null); diff --git a/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeShade.tsx b/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeShade.tsx index 319158dab5..4ef52c0b2e 100644 --- a/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeShade.tsx +++ b/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeShade.tsx @@ -5,9 +5,9 @@ import { VolumeShadeProps } from '../../types/ViewportPresets'; export function VolumeShade({ commandsManager, viewportId, - serviceManager, + servicesManager, }: VolumeShadeProps): ReactElement { - const { cornerstoneViewportService } = serviceManager.services; + const { cornerstoneViewportService } = servicesManager.services; const [shade, setShade] = useState(true); const [key, setKey] = useState(0); diff --git a/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeShift.tsx b/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeShift.tsx index 274f71599e..353126901f 100644 --- a/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeShift.tsx +++ b/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeShift.tsx @@ -4,9 +4,9 @@ import { VolumeShiftProps } from '../../types/ViewportPresets'; export function VolumeShift({ viewportId, commandsManager, - serviceManager, + servicesManager, }: VolumeShiftProps): ReactElement { - const { cornerstoneViewportService } = serviceManager.services; + const { cornerstoneViewportService } = servicesManager.services; const [minShift, setMinShift] = useState(null); const [maxShift, setMaxShift] = useState(null); const [shift, setShift] = useState( diff --git a/extensions/cornerstone/src/components/WindowLevelActionMenu/WindowLevelActionMenu.tsx b/extensions/cornerstone/src/components/WindowLevelActionMenu/WindowLevelActionMenu.tsx index c6f20158fc..55b4d53b9f 100644 --- a/extensions/cornerstone/src/components/WindowLevelActionMenu/WindowLevelActionMenu.tsx +++ b/extensions/cornerstone/src/components/WindowLevelActionMenu/WindowLevelActionMenu.tsx @@ -2,7 +2,6 @@ import React, { ReactElement, useCallback, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import classNames from 'classnames'; import { AllInOneMenu, useViewportGrid } from '@ohif/ui'; -import { CommandsManager, ServicesManager } from '@ohif/core'; import { Colormap } from './Colormap'; import { Colorbar } from './Colorbar'; import { setViewportColorbar } from './Colorbar'; @@ -22,8 +21,6 @@ export type WindowLevelActionMenuProps = { presets: Array>>; verticalDirection: AllInOneMenu.VerticalDirection; horizontalDirection: AllInOneMenu.HorizontalDirection; - commandsManager: CommandsManager; - serviceManager: ServicesManager; colorbarProperties: ColorbarProperties; displaySets: Array; volumeRenderingPresets: Array; @@ -37,12 +34,12 @@ export function WindowLevelActionMenu({ verticalDirection, horizontalDirection, commandsManager, - serviceManager, + servicesManager, colorbarProperties, displaySets, volumeRenderingPresets, volumeRenderingQualityRange, -}: WindowLevelActionMenuProps): ReactElement { +}: withAppTypes): ReactElement { const { colormaps, colorbarContainerPosition, @@ -50,7 +47,7 @@ export function WindowLevelActionMenu({ colorbarTickPosition, width: colorbarWidth, } = colorbarProperties; - const { colorbarService, cornerstoneViewportService } = serviceManager.services; + const { colorbarService, cornerstoneViewportService } = servicesManager.services; const viewportInfo = cornerstoneViewportService.getViewportInfo(viewportId); const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId); const backgroundColor = viewportInfo.getViewportOptions().background; @@ -68,7 +65,7 @@ export function WindowLevelActionMenu({ const [is3DVolume, setIs3DVolume] = useState(false); const onSetColorbar = useCallback(() => { - setViewportColorbar(viewportId, displaySets, commandsManager, serviceManager, { + setViewportColorbar(viewportId, displaySets, commandsManager, servicesManager, { colormaps, ticks: { position: colorbarTickPosition, @@ -138,7 +135,7 @@ export function WindowLevelActionMenu({ viewportId={viewportId} displaySets={displaySets.filter(ds => !nonImageModalities.includes(ds.Modality))} commandsManager={commandsManager} - serviceManager={serviceManager} + servicesManager={servicesManager} colorbarProperties={colorbarProperties} /> )} @@ -154,7 +151,7 @@ export function WindowLevelActionMenu({ viewportId={viewportId} displaySets={displaySets.filter(ds => !nonImageModalities.includes(ds.Modality))} commandsManager={commandsManager} - serviceManager={serviceManager} + servicesManager={servicesManager} /> )} @@ -175,7 +172,7 @@ export function WindowLevelActionMenu({ {volumeRenderingPresets && is3DVolume && ( )} diff --git a/extensions/cornerstone/src/components/WindowLevelActionMenu/getWindowLevelActionMenu.tsx b/extensions/cornerstone/src/components/WindowLevelActionMenu/getWindowLevelActionMenu.tsx index b07fa78991..c18176a586 100644 --- a/extensions/cornerstone/src/components/WindowLevelActionMenu/getWindowLevelActionMenu.tsx +++ b/extensions/cornerstone/src/components/WindowLevelActionMenu/getWindowLevelActionMenu.tsx @@ -9,7 +9,7 @@ export function getWindowLevelActionMenu({ commandsManager, verticalDirection, horizontalDirection, -}): ReactNode { +}: withAppTypes): ReactNode { const { customizationService } = servicesManager.services; const { presets } = customizationService.get('cornerstone.windowLevelPresets'); @@ -32,7 +32,7 @@ export function getWindowLevelActionMenu({ verticalDirection={verticalDirection} horizontalDirection={horizontalDirection} commandsManager={commandsManager} - serviceManager={servicesManager} + servicesManager={servicesManager} colorbarProperties={colorbarProperties} displaySets={displaySets} volumeRenderingPresets={volumeRenderingPresets} diff --git a/extensions/cornerstone/src/getCustomizationModule.ts b/extensions/cornerstone/src/getCustomizationModule.ts index ea07e96946..02cc7a0f70 100644 --- a/extensions/cornerstone/src/getCustomizationModule.ts +++ b/extensions/cornerstone/src/getCustomizationModule.ts @@ -4,6 +4,7 @@ import DicomUpload from './components/DicomUpload/DicomUpload'; import defaultWindowLevelPresets from './components/WindowLevelActionMenu/defaultWindowLevelPresets'; import { colormaps } from './utils/colormaps'; import { CONSTANTS } from '@cornerstonejs/core'; +import { CornerstoneOverlay } from './Viewport/Overlays/CustomizableViewportOverlay'; const DefaultColormap = 'Grayscale'; const { VIEWPORT_PRESETS } = CONSTANTS; @@ -24,7 +25,15 @@ const tools = { }, { toolName: toolNames.StackScrollMouseWheel, bindings: [] }, ], - enabled: [{ toolName: toolNames.SegmentationDisplay }], + enabled: [ + { toolName: toolNames.SegmentationDisplay }, + { + toolName: toolNames.PlanarFreehandContourSegmentation, + configuration: { + displayOnePointAsCrosshairs: true, + }, + }, + ], }; function getCustomizationModule() { @@ -39,6 +48,7 @@ function getCustomizationModule() { { name: 'default', value: [ + CornerstoneOverlay, { id: 'cornerstone.overlayViewportTools', tools, @@ -136,6 +146,13 @@ function getCustomizationModule() { ], }, PlanarFreehandROI: { + displayTextOpen: [ + { + displayName: 'Length', + value: 'length', + type: 'value', + }, + ], displayText: [ { displayName: 'Mean', diff --git a/extensions/cornerstone/src/getHangingProtocolModule.ts b/extensions/cornerstone/src/getHangingProtocolModule.ts index 4f2b3ececf..6a1fc8a1c0 100644 --- a/extensions/cornerstone/src/getHangingProtocolModule.ts +++ b/extensions/cornerstone/src/getHangingProtocolModule.ts @@ -5,6 +5,7 @@ import { mprAnd3DVolumeViewport } from './hps/mprAnd3DVolumeViewport'; import { only3D } from './hps/only3D'; import { primary3D } from './hps/primary3D'; import { primaryAxial } from './hps/primaryAxial'; +import { frameView } from './hps/frameView'; function getHangingProtocolModule() { return [ @@ -36,6 +37,10 @@ function getHangingProtocolModule() { name: primary3D.id, protocol: primary3D, }, + { + name: frameView.id, + protocol: frameView, + }, ]; } diff --git a/extensions/cornerstone/src/getToolbarModule.tsx b/extensions/cornerstone/src/getToolbarModule.tsx index 2f2de94664..6c99065eb4 100644 --- a/extensions/cornerstone/src/getToolbarModule.tsx +++ b/extensions/cornerstone/src/getToolbarModule.tsx @@ -6,9 +6,10 @@ const getToggledClassName = (isToggled: boolean) => { : '!text-common-bright hover:!bg-primary-dark hover:text-primary-light'; }; -export default function getToolbarModule({ commandsManager, servicesManager }) { +export default function getToolbarModule({ commandsManager, servicesManager }: withAppTypes) { const { toolGroupService, + toolbarService, syncGroupService, cornerstoneViewportService, hangingProtocolService, @@ -21,16 +22,16 @@ export default function getToolbarModule({ commandsManager, servicesManager }) { // enabled or not { name: 'evaluate.cornerstoneTool', - evaluate: ({ viewportId, button, disabledText }) => { + evaluate: ({ viewportId, button, toolNames, disabledText }) => { const toolGroup = toolGroupService.getToolGroupForViewport(viewportId); if (!toolGroup) { return; } - const toolName = getToolNameForButton(button); + const toolName = toolbarService.getToolNameForButton(button); - if (!toolGroup || !toolGroup.hasTool(toolName)) { + if (!toolGroup || (!toolGroup.hasTool(toolName) && !toolNames)) { return { disabled: true, className: '!text-common-bright ohif-disabled', @@ -38,7 +39,9 @@ export default function getToolbarModule({ commandsManager, servicesManager }) { }; } - const isPrimaryActive = toolGroup.getActivePrimaryMouseButtonTool() === toolName; + const isPrimaryActive = toolNames + ? toolNames.includes(toolGroup.getActivePrimaryMouseButtonTool()) + : toolGroup.getActivePrimaryMouseButtonTool() === toolName; return { disabled: false, @@ -71,7 +74,7 @@ export default function getToolbarModule({ commandsManager, servicesManager }) { // check if the active toolName is part of the items then we need // to move it to the primary button const activeToolIndex = items.findIndex(item => { - const toolName = getToolNameForButton(item); + const toolName = toolbarService.getToolNameForButton(item); return toolName === activeToolName; }); @@ -114,6 +117,7 @@ export default function getToolbarModule({ commandsManager, servicesManager }) { _evaluateToggle({ viewportId, button, + toolbarService, disabledText, offModes: [Enums.ToolModes.Disabled], toolGroupService, @@ -125,6 +129,7 @@ export default function getToolbarModule({ commandsManager, servicesManager }) { _evaluateToggle({ viewportId, button, + toolbarService, disabledText, offModes: [Enums.ToolModes.Disabled, Enums.ToolModes.Passive], toolGroupService, @@ -245,7 +250,7 @@ export default function getToolbarModule({ commandsManager, servicesManager }) { const displaySets = displaySetUIDs.map(displaySetService.getDisplaySetByUID); const areReconstructable = displaySets.every(displaySet => { - return displaySet.isReconstructable; + return displaySet?.isReconstructable; }); if (!areReconstructable) { @@ -267,13 +272,20 @@ export default function getToolbarModule({ commandsManager, servicesManager }) { ]; } -function _evaluateToggle({ viewportId, button, disabledText, offModes, toolGroupService }) { +function _evaluateToggle({ + viewportId, + toolbarService, + button, + disabledText, + offModes, + toolGroupService, +}) { const toolGroup = toolGroupService.getToolGroupForViewport(viewportId); if (!toolGroup) { return; } - const toolName = getToolNameForButton(button); + const toolName = toolbarService.getToolNameForButton(button); if (!toolGroup.hasTool(toolName)) { return { @@ -289,19 +301,3 @@ function _evaluateToggle({ viewportId, button, disabledText, offModes, toolGroup className: getToggledClassName(!isOff), }; } - -// Todo: this is duplicate, we should move it to a shared location -function getToolNameForButton(button) { - const { props } = button; - - const commands = props?.commands || button.commands; - const commandsArray = Array.isArray(commands) ? commands : [commands]; - const firstCommand = commandsArray[0]; - - if (firstCommand?.commandOptions) { - return firstCommand.commandOptions.toolName ?? props?.id ?? button.id; - } - - // use id as a fallback for toolName - return props?.id ?? button.id; -} diff --git a/extensions/cornerstone/src/hps/frameView.ts b/extensions/cornerstone/src/hps/frameView.ts new file mode 100644 index 0000000000..cf80aa2a16 --- /dev/null +++ b/extensions/cornerstone/src/hps/frameView.ts @@ -0,0 +1,1566 @@ +import { Types } from '@ohif/core'; + +const frameView: Types.HangingProtocol.Protocol = { + id: '@ohif/frameView', + description: 'Frame view for the active series', + name: 'Frame View', + icon: 'tool-stack-scroll', + isPreset: true, + toolGroupIds: ['default'], + protocolMatchingRules: [], + displaySetSelectors: { + defaultDisplaySetId: { + seriesMatchingRules: [ + { + attribute: 'numImageFrames', + constraint: { + greaterThan: { value: 16 }, + }, + required: true, + }, + { + attribute: 'isDisplaySetFromUrl', + weight: 10, + constraint: { + equals: true, + }, + }, + ], + }, + }, + defaultViewport: { + viewportOptions: { + viewportType: 'stack', + toolGroupId: 'default', + allowUnmatchedView: true, + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + matchedDisplaySetsIndex: -1, + }, + ], + }, + stages: [ + { + name: 'frameView', + id: '4x4', + viewportStructure: { + layoutType: 'grid', + properties: { + rows: 4, + columns: 4, + }, + }, + viewports: [ + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 0, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 1, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 2, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 3, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 4, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 5, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 6, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 7, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 8, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 9, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 10, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 11, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 12, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 13, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 14, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 15, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + ], + }, + { + name: 'frameView', + id: '3x3', + viewportStructure: { + layoutType: 'grid', + properties: { + rows: 3, + columns: 3, + }, + }, + viewports: [ + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 0, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 1, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 2, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 3, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 4, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 5, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 6, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 7, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 8, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + ], + }, + { + name: 'frameView', + id: '3x2', + viewportStructure: { + layoutType: 'grid', + properties: { + rows: 2, + columns: 3, + }, + }, + viewports: [ + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 0, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 1, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 2, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 3, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 4, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 5, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + ], + }, + { + name: 'frameView', + id: '2x2', + viewportStructure: { + layoutType: 'grid', + properties: { + rows: 2, + columns: 2, + }, + }, + viewports: [ + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 0, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 1, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 2, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 3, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + ], + }, + { + name: 'frameView', + id: '1x3', + viewportStructure: { + layoutType: 'grid', + properties: { + rows: 1, + columns: 3, + }, + }, + viewports: [ + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 0, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 1, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 2, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + ], + }, + { + name: 'frameView', + id: '1x2', + viewportStructure: { + layoutType: 'grid', + properties: { + rows: 1, + columns: 2, + }, + }, + viewports: [ + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 0, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + syncGroups: [ + { + type: 'zoompan', + id: 'zoompansync', + source: true, + target: true, + }, + { + type: 'voi', + id: 'wlsync', + source: true, + target: true, + options: { + syncColormap: true, + }, + }, + { + type: 'frameview', + id: 'frameViewSync', + source: true, + target: true, + options: { + viewportIndex: 1, + }, + }, + ], + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + ], + }, + ], +}; + +export { frameView }; diff --git a/extensions/cornerstone/src/hps/mpr.ts b/extensions/cornerstone/src/hps/mpr.ts index ea2219163f..fa54ffde6d 100644 --- a/extensions/cornerstone/src/hps/mpr.ts +++ b/extensions/cornerstone/src/hps/mpr.ts @@ -14,17 +14,7 @@ export const mpr: Types.HangingProtocol.Protocol = { numberOfPriorsReferenced: 0, protocolMatchingRules: [], imageLoadStrategy: 'nth', - callbacks: { - // Switches out of MPR mode when the layout change button is used - onLayoutChange: [ - { - commandName: 'toggleHangingProtocol', - commandOptions: { protocolId: 'mpr' }, - context: 'DEFAULT', - }, - ], - // Turns off crosshairs when switching out of MPR mode - }, + callbacks: {}, displaySetSelectors: { activeDisplaySet: { seriesMatchingRules: [ diff --git a/extensions/cornerstone/src/index.tsx b/extensions/cornerstone/src/index.tsx index a8ef8ac47e..934f3de52e 100644 --- a/extensions/cornerstone/src/index.tsx +++ b/extensions/cornerstone/src/index.tsx @@ -8,7 +8,7 @@ import { } from '@cornerstonejs/core'; import * as csStreamingImageVolumeLoader from '@cornerstonejs/streaming-image-volume-loader'; import { Enums as cs3DToolsEnums } from '@cornerstonejs/tools'; -import { ServicesManager, Types } from '@ohif/core'; +import { Types } from '@ohif/core'; import init from './init'; import getCustomizationModule from './getCustomizationModule'; @@ -24,7 +24,7 @@ import ColorbarService from './services/ColorbarService'; import * as CornerstoneExtensionTypes from './types'; import { toolNames } from './initCornerstoneTools'; -import { getEnabledElement, reset as enabledElementReset } from './state'; +import { getEnabledElement, reset as enabledElementReset, setEnabledElement } from './state'; import dicomLoaderService from './utils/dicomLoaderService'; import getActiveViewportEnabledElement from './utils/getActiveViewportEnabledElement'; @@ -36,9 +36,13 @@ import { showLabelAnnotationPopup } from './utils/callInputDialog'; import ViewportActionCornersService from './services/ViewportActionCornersService/ViewportActionCornersService'; import { ViewportActionCornersProvider } from './contextProviders/ViewportActionCornersProvider'; import ActiveViewportWindowLevel from './components/ActiveViewportWindowLevel'; +import getSOPInstanceAttributes from './utils/measurementServiceMappings/utils/getSOPInstanceAttributes'; +import { findNearbyToolData } from './utils/findNearbyToolData'; +import { createFrameViewSynchronizer } from './synchronizers/frameViewSynchronizer'; const { helpers: volumeLoaderHelpers } = csStreamingImageVolumeLoader; const { getDynamicVolumeInfo } = volumeLoaderHelpers ?? {}; +const { imageRetrieveMetadataProvider } = cornerstone.utilities; const Component = React.lazy(() => { return import(/* webpackPrefetch: true */ './Viewport/OHIFCornerstoneViewport'); @@ -52,6 +56,15 @@ const OHIFCornerstoneViewport = props => { ); }; +const stackRetrieveOptions = { + retrieveOptions: { + single: { + streaming: true, + decodeLevel: 1, + }, + }, +}; + /** * */ @@ -61,7 +74,40 @@ const cornerstoneExtension: Types.Extensions.Extension = { */ id, - onModeExit: ({ servicesManager }): void => { + onModeEnter: ({ servicesManager }: withAppTypes): void => { + const { cornerstoneViewportService, toolbarService, segmentationService } = + servicesManager.services; + toolbarService.registerEventForToolbarUpdate(cornerstoneViewportService, [ + cornerstoneViewportService.EVENTS.VIEWPORT_DATA_CHANGED, + ]); + + toolbarService.registerEventForToolbarUpdate(segmentationService, [ + segmentationService.EVENTS.SEGMENTATION_ADDED, + segmentationService.EVENTS.SEGMENTATION_REMOVED, + segmentationService.EVENTS.SEGMENTATION_UPDATED, + ]); + + toolbarService.registerEventForToolbarUpdate(cornerstone.eventTarget, [ + cornerstoneTools.Enums.Events.TOOL_ACTIVATED, + ]); + + // Configure the interleaved/HTJ2K loader + imageRetrieveMetadataProvider.clear(); + // The default volume interleaved options are to interleave the + // image retrieve, but don't perform progressive loading per image + // This interleaves images and replicates them for low-resolution depth volume + // reconstruction, which progressively improves + imageRetrieveMetadataProvider.add( + 'volume', + cornerstone.ProgressiveRetrieveImages.interleavedRetrieveStages + ); + // The default stack loading option is to progressive load HTJ2K images + // There are other possible options, but these need more thought about + // how to define them. + imageRetrieveMetadataProvider.add('stack', stackRetrieveOptions); + }, + + onModeExit: ({ servicesManager }: withAppTypes): void => { const { cineService } = servicesManager.services; // Empty out the image load and retrieval pools to prevent memory leaks // on the mode exits @@ -94,6 +140,9 @@ const cornerstoneExtension: Types.Extensions.Extension = { ViewportActionCornersService.REGISTRATION.name, ViewportActionCornersProvider ); + + const { syncGroupService } = servicesManager.services; + syncGroupService.registerCustomSynchronizer('frameview', createFrameViewSynchronizer); return init.call(this, props); }, @@ -114,7 +163,7 @@ const cornerstoneExtension: Types.Extensions.Extension = { // const onNewImageHandler = jumpData => { // commandsManager.runCommand('jumpToImage', jumpData); // }; - const { toolbarService } = (servicesManager as ServicesManager).services; + const { toolbarService } = servicesManager.services; return ( { // Note: this should run first before initializing the cornerstone // DO NOT CHANGE THE ORDER @@ -69,6 +67,7 @@ export default async function init({ preferSizeOverAccuracy: Boolean(appConfig.preferSizeOverAccuracy), useNorm16Texture: Boolean(appConfig.useNorm16Texture), }, + peerImport: appConfig.peerImport, }); // For debugging e2e tests that are failing on CI @@ -99,25 +98,10 @@ export default async function init({ uiNotificationService, cornerstoneViewportService, hangingProtocolService, - toolbarService, viewportGridService, stateSyncService, - segmentationService, - } = servicesManager.services as CornerstoneServices; - - toolbarService.registerEventForToolbarUpdate(cornerstoneViewportService, [ - cornerstoneViewportService.EVENTS.VIEWPORT_DATA_CHANGED, - ]); - - toolbarService.registerEventForToolbarUpdate(segmentationService, [ - segmentationService.EVENTS.SEGMENTATION_ADDED, - segmentationService.EVENTS.SEGMENTATION_REMOVED, - segmentationService.EVENTS.SEGMENTATION_UPDATED, - ]); - - toolbarService.registerEventForToolbarUpdate(eventTarget, [ - cornerstoneTools.Enums.Events.TOOL_ACTIVATED, - ]); + studyPrefetcherService, + } = servicesManager.services; window.services = servicesManager.services; window.extensionManager = extensionManager; @@ -160,6 +144,7 @@ export default async function init({ }); const labelmapRepresentation = cornerstoneTools.Enums.SegmentationRepresentations.Labelmap; + const contourRepresentation = cornerstoneTools.Enums.SegmentationRepresentations.Contour; cornerstoneTools.segmentation.config.setGlobalRepresentationConfig(labelmapRepresentation, { fillAlpha: 0.5, @@ -168,6 +153,10 @@ export default async function init({ outlineOpacityInactive: 0.65, }); + cornerstoneTools.segmentation.config.setGlobalRepresentationConfig(contourRepresentation, { + renderFill: false, + }); + const metadataProvider = OHIF.classes.MetadataProvider; volumeLoader.registerVolumeLoader( @@ -192,10 +181,12 @@ export default async function init({ ); // this provider is required for Calibration tool metaData.addProvider(metadataProvider.get.bind(metadataProvider), 9999); + // These are set reasonably low to allow for interleaved retrieves and slower + // connections. imageLoadPoolManager.maxNumRequests = { - interaction: appConfig?.maxNumRequests?.interaction || 100, - thumbnail: appConfig?.maxNumRequests?.thumbnail || 75, - prefetch: appConfig?.maxNumRequests?.prefetch || 10, + interaction: appConfig?.maxNumRequests?.interaction || 10, + thumbnail: appConfig?.maxNumRequests?.thumbnail || 5, + prefetch: appConfig?.maxNumRequests?.prefetch || 5, }; initWADOImageLoader(userAuthenticationService, appConfig, extensionManager); @@ -204,6 +195,7 @@ export default async function init({ this.measurementServiceSource = connectToolsToMeasurementService(servicesManager); initCineService(servicesManager); + initStudyPrefetcherService(servicesManager); // When a custom image load is performed, update the relevant viewports hangingProtocolService.subscribe( @@ -269,7 +261,11 @@ export default async function init({ element.addEventListener(EVENTS.CAMERA_RESET, evt => { const { element } = evt.detail; - const { viewportId } = getEnabledElement(element); + const enabledElement = getEnabledElement(element); + if (!enabledElement) { + return; + } + const { viewportId } = enabledElement; commandsManager.runCommand('resetCrosshairs', { viewportId }); }); @@ -295,19 +291,18 @@ export default async function init({ eventTarget.addEventListener(EVENTS.ELEMENT_DISABLED, elementDisabledHandler.bind(null)); colormaps.forEach(registerColormap); - // Create a debounced function that shows the notification - const debouncedShowNotification = debounce(detail => { - uiNotificationService.show({ - title: detail.type, - message: detail.message, - type: 'error', - }); - }, 300); - // Event listener - eventTarget.addEventListener(EVENTS.ERROR_EVENT, ({ detail }) => { - debouncedShowNotification(detail); - }); + eventTarget.addEventListenerDebounced( + EVENTS.ERROR_EVENT, + ({ detail }) => { + uiNotificationService.show({ + title: detail.type, + message: detail.message, + type: 'error', + }); + }, + 1000 + ); } function CPUModal() { diff --git a/extensions/cornerstone/src/initCineService.ts b/extensions/cornerstone/src/initCineService.ts index 5e3246135f..b98c2f2816 100644 --- a/extensions/cornerstone/src/initCineService.ts +++ b/extensions/cornerstone/src/initCineService.ts @@ -6,7 +6,7 @@ function _getVolumesFromViewport(viewport) { } function _getVolumeFromViewport(viewport) { - const volumes = _getVolumesFromViewport(viewport); + const volumes = _getVolumesFromViewport(viewport).filter(volume => volume); const dynamicVolume = volumes.find(volume => volume.isDynamicVolume()); return dynamicVolume ?? volumes[0]; @@ -19,7 +19,7 @@ function _getVolumeFromViewport(viewport) { * @param srcViewportIndex Source viewport index * @returns array with viewport information. */ -function _getSyncedViewports(servicesManager, srcViewportId) { +function _getSyncedViewports(servicesManager: AppTypes.ServicesManager, srcViewportId) { const { viewportGridService, cornerstoneViewportService } = servicesManager.services; const { viewports: viewportsStates } = viewportGridService.getState(); @@ -48,7 +48,7 @@ function _getSyncedViewports(servicesManager, srcViewportId) { .map(({ viewportId }) => ({ viewportId })); } -function initCineService(servicesManager) { +function initCineService(servicesManager: AppTypes.ServicesManager) { const { cineService } = servicesManager.services; const getSyncedViewports = viewportId => { diff --git a/extensions/cornerstone/src/initCornerstoneTools.js b/extensions/cornerstone/src/initCornerstoneTools.js index b40946ff9f..bfabc4a014 100644 --- a/extensions/cornerstone/src/initCornerstoneTools.js +++ b/extensions/cornerstone/src/initCornerstoneTools.js @@ -33,9 +33,11 @@ import { AdvancedMagnifyTool, UltrasoundDirectionalTool, PlanarFreehandROITool, + PlanarFreehandContourSegmentationTool, SplineROITool, LivewireContourTool, OrientationMarkerTool, + WindowLevelRegionTool, } from '@cornerstonejs/tools'; import CalibrationLineTool from './tools/CalibrationLineTool'; @@ -44,6 +46,7 @@ import ImageOverlayViewerTool from './tools/ImageOverlayViewerTool'; export default function initCornerstoneTools(configuration = {}) { CrosshairsTool.isAnnotation = false; ReferenceLinesTool.isAnnotation = false; + AdvancedMagnifyTool.isAnnotation = false; init(configuration); addTool(PanTool); @@ -82,6 +85,8 @@ export default function initCornerstoneTools(configuration = {}) { addTool(SplineROITool); addTool(LivewireContourTool); addTool(OrientationMarkerTool); + addTool(WindowLevelRegionTool); + addTool(PlanarFreehandContourSegmentationTool); // Modify annotation tools to use dashed lines on SR const annotationStyle = { @@ -135,6 +140,8 @@ const toolNames = { LivewireContour: LivewireContourTool.toolName, PlanarFreehandROI: PlanarFreehandROITool.toolName, OrientationMarker: OrientationMarkerTool.toolName, + WindowLevelRegion: WindowLevelRegionTool.toolName, + PlanarFreehandContourSegmentation: PlanarFreehandContourSegmentationTool.toolName, }; export { toolNames }; diff --git a/extensions/cornerstone/src/initMeasurementService.js b/extensions/cornerstone/src/initMeasurementService.ts similarity index 99% rename from extensions/cornerstone/src/initMeasurementService.js rename to extensions/cornerstone/src/initMeasurementService.ts index 79d94f78f5..b2682953b7 100644 --- a/extensions/cornerstone/src/initMeasurementService.js +++ b/extensions/cornerstone/src/initMeasurementService.ts @@ -178,7 +178,7 @@ const initMeasurementService = ( return csTools3DVer1MeasurementSource; }; -const connectToolsToMeasurementService = servicesManager => { +const connectToolsToMeasurementService = (servicesManager: AppTypes.ServicesManager) => { const { measurementService, displaySetService, diff --git a/extensions/cornerstone/src/initStudyPrefetcherService.ts b/extensions/cornerstone/src/initStudyPrefetcherService.ts new file mode 100644 index 0000000000..78020f4366 --- /dev/null +++ b/extensions/cornerstone/src/initStudyPrefetcherService.ts @@ -0,0 +1,33 @@ +import { cache, imageLoadPoolManager, imageLoader, Enums, eventTarget, EVENTS as csEvents } from '@cornerstonejs/core'; + +function initStudyPrefetcherService(servicesManager: AppTypes.ServicesManager) { + const { studyPrefetcherService } = servicesManager.services; + + studyPrefetcherService.requestType = Enums.RequestType.Prefetch; + studyPrefetcherService.imageLoadPoolManager = imageLoadPoolManager; + studyPrefetcherService.imageLoader = imageLoader; + + studyPrefetcherService.cache = { + isImageCached(imageId: string): boolean { + return !!cache.getImageLoadObject(imageId); + } + } + + studyPrefetcherService.imageLoadEventsManager = { + addEventListeners(onImageLoaded, onImageLoadFailed) { + eventTarget.addEventListener(csEvents.IMAGE_LOADED, onImageLoaded); + eventTarget.addEventListener(csEvents.IMAGE_LOAD_FAILED, onImageLoadFailed); + + return [ + { + unsubscribe: () => eventTarget.removeEventListener(csEvents.IMAGE_LOADED, onImageLoaded) + }, + { + unsubscribe: () => eventTarget.removeEventListener(csEvents.IMAGE_LOAD_FAILED, onImageLoadFailed) + }, + ] + } + } +} + +export default initStudyPrefetcherService; diff --git a/extensions/cornerstone/src/services/CornerstoneCacheService/CornerstoneCacheService.ts b/extensions/cornerstone/src/services/CornerstoneCacheService/CornerstoneCacheService.ts index a8d40b3d08..09c0d8c2b7 100644 --- a/extensions/cornerstone/src/services/CornerstoneCacheService/CornerstoneCacheService.ts +++ b/extensions/cornerstone/src/services/CornerstoneCacheService/CornerstoneCacheService.ts @@ -1,4 +1,4 @@ -import { ServicesManager, Types } from '@ohif/core'; +import { Types } from '@ohif/core'; import { cache as cs3DCache, Enums, volumeLoader, utilities as utils } from '@cornerstonejs/core'; import getCornerstoneViewportType from '../../utils/getCornerstoneViewportType'; @@ -17,9 +17,9 @@ class CornerstoneCacheService { stackImageIds: Map = new Map(); volumeImageIds: Map = new Map(); - readonly servicesManager: ServicesManager; + readonly servicesManager: AppTypes.ServicesManager; - constructor(servicesManager: ServicesManager) { + constructor(servicesManager: AppTypes.ServicesManager) { this.servicesManager = servicesManager; } @@ -84,12 +84,26 @@ class CornerstoneCacheService { invalidatedDisplaySetInstanceUID: string, dataSource, displaySetService - ) { + ): Promise { if (viewportData.viewportType === Enums.ViewportType.STACK) { - return this._getCornerstoneStackImageIds( - displaySetService.getDisplaySetByUID(invalidatedDisplaySetInstanceUID), - dataSource - ); + const displaySet = displaySetService.getDisplaySetByUID(invalidatedDisplaySetInstanceUID); + const imageIds = this._getCornerstoneStackImageIds(displaySet, dataSource); + + // remove images from the cache to be able to re-load them + imageIds.forEach(imageId => { + if (cs3DCache.getImageLoadObject(imageId)) { + cs3DCache.removeImageLoadObject(imageId); + } + }); + + return { + viewportType: Enums.ViewportType.STACK, + data: { + StudyInstanceUID: displaySet.StudyInstanceUID, + displaySetInstanceUID: invalidatedDisplaySetInstanceUID, + imageIds, + }, + }; } // Todo: grab the volume and get the id from the viewport itself @@ -98,7 +112,21 @@ class CornerstoneCacheService { const volume = cs3DCache.getVolume(volumeId); if (volume) { - cs3DCache.removeVolumeLoadObject(volumeId); + if (volume.imageIds) { + // also for each imageId in the volume, remove the imageId from the cache + // since that will hold the old metadata as well + + volume.imageIds.forEach(imageId => { + if (cs3DCache.getImageLoadObject(imageId)) { + cs3DCache.removeImageLoadObject(imageId); + } + }); + } + + // this shouldn't be via removeVolumeLoadObject, since that will + // remove the texture as well, but here we really just need a remove + // from registry so that we load it again + cs3DCache._volumeCache.delete(volumeId); this.volumeImageIds.delete(volumeId); } @@ -115,14 +143,25 @@ class CornerstoneCacheService { return newViewportData; } - private _getStackViewportData( + private async _getStackViewportData( dataSource, displaySets, initialImageIndex, viewportType: Enums.ViewportType - ): StackViewportData { - // For Stack Viewport we don't have fusion currently - const displaySet = displaySets[0]; + ): Promise { + const overlayDisplaySets = displaySets.filter(ds => ds.isOverlayDisplaySet); + const nonOverlayDisplaySets = displaySets.filter(ds => !ds.isOverlayDisplaySet); + + // load overlays if they are not loaded + for (const overlayDisplaySet of overlayDisplaySets) { + if (overlayDisplaySet.load && overlayDisplaySet.load instanceof Function) { + const { userAuthenticationService } = this.servicesManager.services; + const headers = userAuthenticationService.getAuthorizationHeader(); + await overlayDisplaySet.load({ headers }); + } + } + + const displaySet = nonOverlayDisplaySets[0]; let stackImageIds = this.stackImageIds.get(displaySet.displaySetInstanceUID); @@ -131,23 +170,23 @@ class CornerstoneCacheService { this.stackImageIds.set(displaySet.displaySetInstanceUID, stackImageIds); } - const { displaySetInstanceUID, StudyInstanceUID, isCompositeStack } = displaySet; + // Ensuring the first non-overlay `displaySet` is always the primary one + const StackViewportData = [displaySet, ...overlayDisplaySets].map(ds => { + const { displaySetInstanceUID, StudyInstanceUID, isCompositeStack } = ds; - const StackViewportData: StackViewportData = { - viewportType, - data: { + return { StudyInstanceUID, displaySetInstanceUID, isCompositeStack, imageIds: stackImageIds, - }, - }; - - if (typeof initialImageIndex === 'number') { - StackViewportData.data.initialImageIndex = initialImageIndex; - } + initialImageIndex, + }; + }); - return StackViewportData; + return { + viewportType, + data: StackViewportData, + }; } private async _getVolumeViewportData( @@ -161,6 +200,9 @@ class CornerstoneCacheService { const volumeData = []; for (const displaySet of displaySets) { + const { Modality } = displaySet; + const isParametricMap = Modality === 'PMAP'; + // Don't create volumes for the displaySets that have custom load // function (e.g., SEG, RT, since they rely on the reference volumes // and they take care of their own loading after they are created in their @@ -171,24 +213,27 @@ class CornerstoneCacheService { const headers = userAuthenticationService.getAuthorizationHeader(); await displaySet.load({ headers }); - volumeData.push({ - studyInstanceUID: displaySet.StudyInstanceUID, - displaySetInstanceUID: displaySet.displaySetInstanceUID, - }); - - // Todo: do some cache check and empty the cache if needed - continue; + // Parametric maps have a `load` method but it should not be loaded in the + // same way as SEG and RTSTRUCT but like a normal volume + if (!isParametricMap) { + volumeData.push({ + studyInstanceUID: displaySet.StudyInstanceUID, + displaySetInstanceUID: displaySet.displaySetInstanceUID, + }); + + // Todo: do some cache check and empty the cache if needed + continue; + } } const volumeLoaderSchema = displaySet.volumeLoaderSchema ?? VOLUME_LOADER_SCHEME; - const volumeId = `${volumeLoaderSchema}:${displaySet.displaySetInstanceUID}`; - let volumeImageIds = this.volumeImageIds.get(displaySet.displaySetInstanceUID); - let volume = cs3DCache.getVolume(volumeId); - if (!volumeImageIds || !volume) { + // Parametric maps do not have image ids but they already have volume data + // therefore a new volume should not be created. + if (!isParametricMap && (!volumeImageIds || !volume)) { volumeImageIds = this._getCornerstoneVolumeImageIds(displaySet, dataSource); volume = await volumeLoader.createAndCacheVolume(volumeId, { diff --git a/extensions/cornerstone/src/services/SegmentationService/SegmentationService.ts b/extensions/cornerstone/src/services/SegmentationService/SegmentationService.ts index 579dc93bd0..af98398ff2 100644 --- a/extensions/cornerstone/src/services/SegmentationService/SegmentationService.ts +++ b/extensions/cornerstone/src/services/SegmentationService/SegmentationService.ts @@ -1,4 +1,4 @@ -import { Types as OhifTypes, ServicesManager, PubSubService } from '@ohif/core'; +import { Types as OhifTypes, PubSubService } from '@ohif/core'; import { cache, Enums as csEnums, @@ -7,6 +7,7 @@ import { getEnabledElementByIds, utilities as csUtils, volumeLoader, + StackViewport, } from '@cornerstonejs/core'; import { Enums as csToolsEnums, @@ -60,7 +61,7 @@ class SegmentationService extends PubSubService { }; segmentations: Record; - readonly servicesManager: ServicesManager; + readonly servicesManager: AppTypes.ServicesManager; highlightIntervalId = null; readonly EVENTS = EVENTS; @@ -568,7 +569,7 @@ class SegmentationService extends PubSubService { rgba, } = segmentInfo; - const { x, y, z } = segDisplaySet.centroids.get(segmentIndex); + const { x, y, z } = segDisplaySet.centroids.get(segmentIndex) || { x: 0, y: 0, z: 0 }; const centerWorld = derivedVolume.imageData.indexToWorld([x, y, z]); segmentation.cachedStats = { @@ -770,8 +771,8 @@ class SegmentationService extends PubSubService { const segmentIndices = segmentIndex ? [segmentIndex] : segmentation.segments - .filter(segment => segment?.segmentIndex) - .map(segment => segment.segmentIndex); + .filter(segment => segment?.segmentIndex) + .map(segment => segment.segmentIndex); const segmentIndicesSet = new Set(segmentIndices); @@ -884,7 +885,13 @@ class SegmentationService extends PubSubService { // @ts-ignore for (const { viewportId, renderingEngineId } of viewportsInfo) { const { viewport } = getEnabledElementByIds(viewportId, renderingEngineId); - cstUtils.viewport.jumpToWorld(viewport, world); + if (viewport instanceof StackViewport) { + const { element } = viewport; + const index = csUtils.getClosestStackImageIndexForPoint(world, viewport) + cstUtils.viewport.jumpToSlice(element, { imageIndex: index }) + } else { + cstUtils.viewport.jumpToWorld(viewport, world); + } } if (highlightSegment) { @@ -1015,6 +1022,8 @@ class SegmentationService extends PubSubService { ): Promise => { const segmentation = this.getSegmentation(segmentationId); + toolGroupId = toolGroupId || this._getApplicableToolGroupId(); + if (!segmentation) { throw new Error(`Segmentation with segmentationId ${segmentationId} not found.`); } @@ -1147,6 +1156,10 @@ class SegmentationService extends PubSubService { displaySet.isHydrated = isHydrated; displaySetService.setDisplaySetMetadataInvalidated(displaySetUID, false); + + this._broadcastEvent(this.EVENTS.SEGMENTATION_UPDATED, { + segmentation: this.getSegmentation(displaySetUID), + }); } private _highlightLabelmap( @@ -1244,6 +1257,7 @@ class SegmentationService extends PubSubService { { [segmentIndex]: { CONTOUR: { + outlineOpacity: reversedProgress, fillAlpha: reversedProgress, }, }, diff --git a/extensions/cornerstone/src/services/SegmentationService/SegmentationServiceTypes.ts b/extensions/cornerstone/src/services/SegmentationService/SegmentationServiceTypes.ts index cb65154d26..68c6540cb0 100644 --- a/extensions/cornerstone/src/services/SegmentationService/SegmentationServiceTypes.ts +++ b/extensions/cornerstone/src/services/SegmentationService/SegmentationServiceTypes.ts @@ -22,6 +22,10 @@ type Segment = { isLocked: boolean; // display texts displayText?: string[]; + // The name of algorithm used to generate the segment. (0062,0009) + algorithmName?: string; + // Type of algorithm used to generate the segment. (0062,0008) + algorithmType?: string; }; type Segmentation = { diff --git a/extensions/cornerstone/src/services/SyncGroupService/SyncGroupService.ts b/extensions/cornerstone/src/services/SyncGroupService/SyncGroupService.ts index 0c1536be7a..030dd72d81 100644 --- a/extensions/cornerstone/src/services/SyncGroupService/SyncGroupService.ts +++ b/extensions/cornerstone/src/services/SyncGroupService/SyncGroupService.ts @@ -1,7 +1,7 @@ import { synchronizers, SynchronizerManager, Synchronizer } from '@cornerstonejs/tools'; -import { getRenderingEngines } from '@cornerstonejs/core'; +import { getRenderingEngines, utilities } from '@cornerstonejs/core'; -import { pubSubServiceInterface, Types, ServicesManager } from '@ohif/core'; +import { pubSubServiceInterface, Types } from '@ohif/core'; const EVENTS = { TOOL_GROUP_CREATED: 'event::cornerstone::syncgroupservice:toolgroupcreated', @@ -40,7 +40,7 @@ export default class SyncGroupService { }, }; - servicesManager: ServicesManager; + servicesManager: AppTypes.ServicesManager; listeners: { [key: string]: (...args: any[]) => void } = {}; EVENTS: { [key: string]: string }; synchronizerCreators: Record = { @@ -55,8 +55,8 @@ export default class SyncGroupService { synchronizersByType: { [key: string]: Synchronizer[] } = {}; - constructor(serviceManager: ServicesManager) { - this.servicesManager = serviceManager; + constructor(servicesManager: AppTypes.ServicesManager) { + this.servicesManager = servicesManager; this.listeners = {}; this.EVENTS = EVENTS; // @@ -98,6 +98,15 @@ export default class SyncGroupService { return SynchronizerManager.getSynchronizer(id); } + /** + * Registers a custom synchronizer. + * @param id - The id of the synchronizer. + * @param createFunction - The function that creates the synchronizer. + */ + public registerCustomSynchronizer(id: string, createFunction: SyncCreator): void { + this.synchronizerCreators[id] = createFunction; + } + /** * Retrieves an array of synchronizers of a specific type. * @param type - The type of synchronizers to retrieve. @@ -184,6 +193,11 @@ export default class SyncGroupService { return; } + // Only image slice synchronizer register spatial registration + if (this.isImageSliceSyncronizer(synchronizer)) { + this.unRegisterSpatialRegistration(synchronizer); + } + synchronizer.remove({ viewportId, renderingEngineId, @@ -198,4 +212,45 @@ export default class SyncGroupService { } }); } + /** + * Clean up the spatial registration metadata created by synchronizer + * This is needed to be able to re-sync images slices if needed + * @param synchronizer + */ + unRegisterSpatialRegistration(synchronizer: Synchronizer) { + const sourceViewports = synchronizer.getSourceViewports().map(vp => vp.viewportId); + const targetViewports = synchronizer.getTargetViewports().map(vp => vp.viewportId); + + // Create an array of pair of viewports to remove from spatialRegistrationMetadataProvider + // All sourceViewports combined with all targetViewports + const toUnregister = sourceViewports + .map((sourceViewportId: string) => { + return targetViewports.map(targetViewportId => [targetViewportId, sourceViewportId]); + }) + .reduce((acc, c) => acc.concat(c), []); + + toUnregister.forEach(viewportIdPair => { + utilities.spatialRegistrationMetadataProvider.add(viewportIdPair, undefined); + }); + } + /** + * Check if the synchronizer type is IMAGE_SLICE + * Need to convert to lowercase here because the types are lowercase + * e.g: synchronizerCreators + * @param synchronizer + */ + isImageSliceSyncronizer(synchronizer: Synchronizer) { + return this.getSynchronizerType(synchronizer).toLowerCase() === IMAGE_SLICE; + } + /** + * Returns the syncronizer type + * @param synchronizer + */ + getSynchronizerType(synchronizer: Synchronizer): string { + const synchronizerTypes = Object.keys(this.synchronizersByType); + const syncType = synchronizerTypes.find(syncType => + this.getSynchronizersOfType(syncType).includes(synchronizer) + ); + return syncType; + } } diff --git a/extensions/cornerstone/src/services/ToolGroupService/ToolGroupService.ts b/extensions/cornerstone/src/services/ToolGroupService/ToolGroupService.ts index a6926ad2c0..298f28612d 100644 --- a/extensions/cornerstone/src/services/ToolGroupService/ToolGroupService.ts +++ b/extensions/cornerstone/src/services/ToolGroupService/ToolGroupService.ts @@ -32,7 +32,10 @@ export default class ToolGroupService { }, }; - serviceManager: any; + servicesManager: AppTypes.ServicesManager; + cornerstoneViewportService: any; + viewportGridService: any; + uiNotificationService: any; private toolGroupIds: Set = new Set(); /** * Service-specific @@ -40,9 +43,9 @@ export default class ToolGroupService { listeners: { [key: string]: Function[] }; EVENTS: { [key: string]: string }; - constructor(serviceManager) { + constructor(servicesManager: AppTypes.ServicesManager) { const { cornerstoneViewportService, viewportGridService, uiNotificationService } = - serviceManager.services; + servicesManager.services; this.cornerstoneViewportService = cornerstoneViewportService; this.viewportGridService = viewportGridService; this.uiNotificationService = uiNotificationService; diff --git a/extensions/cornerstone/src/services/ViewportService/CornerstoneViewportService.ts b/extensions/cornerstone/src/services/ViewportService/CornerstoneViewportService.ts index 3f63bcdcd2..6dd645bce9 100644 --- a/extensions/cornerstone/src/services/ViewportService/CornerstoneViewportService.ts +++ b/extensions/cornerstone/src/services/ViewportService/CornerstoneViewportService.ts @@ -1,5 +1,5 @@ -import { PubSubService, ServicesManager } from '@ohif/core'; -import * as OhifTypes from '@ohif/core/types'; +import { PubSubService } from '@ohif/core'; +import { Types as OhifTypes } from '@ohif/core'; import { RenderingEngine, StackViewport, @@ -52,14 +52,14 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi enableResizeDetector: true; resizeRefreshRateMs: 200; resizeRefreshMode: 'debounce'; - servicesManager = null; + servicesManager: AppTypes.ServicesManager = null; resizeQueue = []; viewportResizeTimer = null; gridResizeDelay = 50; gridResizeTimeOut = null; - constructor(servicesManager: ServicesManager) { + constructor(servicesManager: AppTypes.ServicesManager) { super(EVENTS); this.renderingEngine = null; this.viewportGridResizeObserver = null; @@ -532,6 +532,11 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi cameraProps: unknown ): string { const viewportInfo = this.getViewportInfo(activeViewportId); + + if (viewportInfo.getViewportType() === csEnums.ViewportType.VOLUME_3D) { + return null; + } + const { referencedImageId } = cameraProps; if (viewportInfo?.contains(displaySetInstanceUID, referencedImageId)) { return activeViewportId; @@ -552,9 +557,14 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi ): Promise { const displaySetOptions = viewportInfo.getDisplaySetOptions(); - const { imageIds, initialImageIndex, displaySetInstanceUID } = viewportData.data; + const displaySetInstanceUIDs = viewportData.data.map(data => data.displaySetInstanceUID); - this.viewportsDisplaySets.set(viewport.id, [displaySetInstanceUID]); + // based on the cache service construct always the first one is the non-overlay + // and the rest are overlays + + this.viewportsDisplaySets.set(viewport.id, [...displaySetInstanceUIDs]); + + const { initialImageIndex, imageIds } = viewportData.data[0]; let initialImageIndexToUse = presentations?.positionPresentation?.initialImageIndex ?? initialImageIndex; @@ -563,6 +573,8 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi initialImageIndexToUse = this._getInitialImageIndexForViewport(viewportInfo, imageIds) || 0; } + const { rotation, flipHorizontal, displayArea } = viewportInfo.getViewportOptions(); + const properties = { ...presentations.lutPresentation?.properties }; if (!presentations.lutPresentation?.properties) { const { voi, voiInverted, colormap } = displaySetOptions[0]; @@ -583,9 +595,20 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi } } + this._handleOverlays(viewport); + return viewport.setStack(imageIds, initialImageIndexToUse).then(() => { viewport.setProperties({ ...properties }); this.setPresentations(viewport.id, presentations); + if (displayArea) { + viewport.setDisplayArea(displayArea); + } + if (rotation) { + viewport.setProperties({ rotation }); + } + if (flipHorizontal) { + viewport.setCamera({ flipHorizontal: true }); + } }); } @@ -594,11 +617,9 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi imageIds?: string[] ): number { const initialImageOptions = viewportInfo.getInitialImageOptions(); - if (!initialImageOptions) { return; } - const { index, preset } = initialImageOptions; const viewportType = viewportInfo.getViewportType(); @@ -767,24 +788,7 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi this.setPresentations(viewport.id, presentations); - // load any secondary displaySets - const displaySetInstanceUIDs = this.viewportsDisplaySets.get(viewport.id); - - // can be SEG or RTSTRUCT for now - const overlayDisplaySet = displaySetInstanceUIDs - .map(displaySetService.getDisplaySetByUID) - .find(displaySet => displaySet?.isOverlayDisplaySet); - - if (overlayDisplaySet) { - this.addOverlayRepresentationForDisplaySet(overlayDisplaySet, viewport); - } else { - // If the displaySet is not a SEG displaySet we assume it is a primary displaySet - // and we can look into hydrated segmentations to check if any of them are - // associated with the primary displaySet - - // get segmentations only returns the hydrated segmentations - this._addSegmentationRepresentationToToolGroupIfNecessary(displaySetInstanceUIDs, viewport); - } + this._handleOverlays(viewport); const toolGroup = toolGroupService.getToolGroupForViewport(viewport.id); csToolsUtils.segmentation.triggerSegmentationRender(toolGroup.id); @@ -804,6 +808,32 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi }); } + private _handleOverlays(viewport: Types.IStackViewport | Types.IVolumeViewport) { + const { displaySetService } = this.servicesManager.services; + + // load any secondary displaySets + const displaySetInstanceUIDs = this.viewportsDisplaySets.get(viewport.id); + + // Can be SEG or RTSTRUCT for now but not PMAP + const segOrRTSOverlayDisplaySet = displaySetInstanceUIDs + .map(displaySetService.getDisplaySetByUID) + .find( + displaySet => + displaySet?.isOverlayDisplaySet && ['SEG', 'RTSTRUCT'].includes(displaySet.Modality) + ); + + if (segOrRTSOverlayDisplaySet) { + this.addOverlayRepresentationForDisplaySet(segOrRTSOverlayDisplaySet, viewport); + } else { + // If the displaySet is not a SEG displaySet we assume it is a primary displaySet + // and we can look into hydrated segmentations to check if any of them are + // associated with the primary displaySet + + // get segmentations only returns the hydrated segmentations + this._addSegmentationRepresentationToToolGroupIfNecessary(displaySetInstanceUIDs, viewport); + } + } + private _addSegmentationRepresentationToToolGroupIfNecessary( displaySetInstanceUIDs: string[], viewport: any @@ -1034,28 +1064,33 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi private performResize() { const isImmediate = false; - const viewports = this.getRenderingEngine().getViewports(); + try { + const viewports = this.getRenderingEngine().getViewports(); - // Store the current position presentations for each viewport. - viewports.forEach(({ id }) => { - const presentation = this.getPositionPresentation(id); - this.beforeResizePositionPresentations.set(id, presentation); - }); + // Store the current position presentations for each viewport. + viewports.forEach(({ id }) => { + const presentation = this.getPositionPresentation(id); + this.beforeResizePositionPresentations.set(id, presentation); + }); - // Resize the rendering engine and render. - const renderingEngine = this.renderingEngine; - renderingEngine.resize(isImmediate); - renderingEngine.render(); + // Resize the rendering engine and render. + const renderingEngine = this.renderingEngine; + renderingEngine.resize(isImmediate); + renderingEngine.render(); - // Reset the camera for viewports that should reset their camera on resize, - // which means only those viewports that have a zoom level of 1. - this.beforeResizePositionPresentations.forEach((positionPresentation, viewportId) => { - this.setPresentations(viewportId, { positionPresentation }); - }); + // Reset the camera for viewports that should reset their camera on resize, + // which means only those viewports that have a zoom level of 1. + this.beforeResizePositionPresentations.forEach((positionPresentation, viewportId) => { + this.setPresentations(viewportId, { positionPresentation }); + }); - // Resize and render the rendering engine again. - renderingEngine.resize(isImmediate); - renderingEngine.render(); + // Resize and render the rendering engine again. + renderingEngine.resize(isImmediate); + renderingEngine.render(); + } catch (e) { + // This can happen if the resize is too close to navigation or shutdown + console.warn('Caught resize exception', e); + } } private resetGridResizeTimeout() { diff --git a/extensions/cornerstone/src/services/ViewportService/IViewportService.ts b/extensions/cornerstone/src/services/ViewportService/IViewportService.ts index b16fa989f6..46d4acd5b7 100644 --- a/extensions/cornerstone/src/services/ViewportService/IViewportService.ts +++ b/extensions/cornerstone/src/services/ViewportService/IViewportService.ts @@ -8,7 +8,7 @@ import { Presentations } from '../../types/Presentation'; * updating the viewport. */ export interface IViewportService { - servicesManager: unknown; + servicesManager: AppTypes.ServicesManager; hangingProtocolService: unknown; renderingEngine: unknown; viewportGridResizeObserver: unknown; diff --git a/extensions/cornerstone/src/services/ViewportService/Viewport.ts b/extensions/cornerstone/src/services/ViewportService/Viewport.ts index 2ec852492a..6245c69ffe 100644 --- a/extensions/cornerstone/src/services/ViewportService/Viewport.ts +++ b/extensions/cornerstone/src/services/ViewportService/Viewport.ts @@ -1,4 +1,10 @@ -import { Types, Enums } from '@cornerstonejs/core'; +import { + Types, + Enums, + getEnabledElementByViewportId, + VolumeViewport, + utilities, +} from '@cornerstonejs/core'; import { Types as CoreTypes } from '@ohif/core'; import { StackViewportData, VolumeViewportData } from '../../types/CornerstoneCacheService'; import getCornerstoneBlendMode from '../../utils/getCornerstoneBlendMode'; @@ -10,6 +16,7 @@ import { SyncGroup } from '../SyncGroupService/SyncGroupService'; export type InitialImageOptions = { index?: number; preset?: JumpPresets; + useOnce?: boolean; }; export type ViewportOptions = { @@ -89,13 +96,30 @@ const DEFAULT_TOOLGROUP_ID = 'default'; // Return true if the data contains the given display set UID OR the imageId // if it is a composite object. -const dataContains = (data, displaySetUID: string, imageId?: string): boolean => { - if (data.displaySetInstanceUID === displaySetUID) { - return true; - } +const dataContains = ({ data, displaySetUID, imageId, viewport }): boolean => { if (imageId && data.isCompositeStack && data.imageIds) { return !!data.imageIds.find(dataId => dataId === imageId); } + + if (imageId && (data.volumeId || viewport instanceof VolumeViewport)) { + const isAcquisition = !!viewport.getCurrentImageId(); + + if (!isAcquisition) { + return false; + } + + const imageURI = utilities.imageIdToURI(imageId); + const hasImageId = viewport.hasImageURI(imageURI); + + if (hasImageId) { + return true; + } + } + + if (data.displaySetInstanceUID === displaySetUID) { + return true; + } + return false; }; @@ -122,10 +146,20 @@ class ViewportInfo { return false; } + const { viewport } = getEnabledElementByViewportId(this.viewportId) || {}; + if (this.viewportData.data.length) { - return !!this.viewportData.data.find(data => dataContains(data, displaySetUID, imageId)); + return !!this.viewportData.data.find(data => + dataContains({ data, displaySetUID, imageId, viewport }) + ); } - return dataContains(this.viewportData.data, displaySetUID, imageId); + + return dataContains({ + data: this.viewportData.data, + displaySetUID, + imageId, + viewport, + }); } public destroy = (): void => { diff --git a/extensions/cornerstone/src/synchronizers/frameViewSynchronizer.ts b/extensions/cornerstone/src/synchronizers/frameViewSynchronizer.ts new file mode 100644 index 0000000000..8f125d1b6f --- /dev/null +++ b/extensions/cornerstone/src/synchronizers/frameViewSynchronizer.ts @@ -0,0 +1,51 @@ +import { SynchronizerManager, Synchronizer, utilities } from '@cornerstonejs/tools'; +import { EVENTS, getRenderingEngine, Types } from '@cornerstonejs/core'; + +const frameViewSyncCallback = ( + synchronizerInstance: Synchronizer, + sourceViewport: Types.IViewportId, + targetViewport: Types.IViewportId +) => { + const renderingEngine = getRenderingEngine(targetViewport.renderingEngineId); + if (!renderingEngine) { + throw new Error(`No RenderingEngine for Id: ${targetViewport.renderingEngineId}`); + } + const sViewport = renderingEngine.getViewport(sourceViewport.viewportId) as Types.IStackViewport; + + const { viewportIndex: targetViewportIndex } = synchronizerInstance.getOptions( + targetViewport.viewportId + ); + + const { viewportIndex: sourceViewportIndex } = synchronizerInstance.getOptions( + sourceViewport.viewportId + ); + + if (targetViewportIndex === undefined || sourceViewportIndex === undefined) { + throw new Error('No viewportIndex provided'); + } + + const tViewport = renderingEngine.getViewport(targetViewport.viewportId) as Types.IStackViewport; + + const sourceSliceIndex = sViewport.getSliceIndex(); + const sliceDifference = Number(targetViewportIndex) - Number(sourceViewportIndex); + const targetSliceIndex = sourceSliceIndex + sliceDifference; + + if (targetSliceIndex === tViewport.getSliceIndex()) { + return; + } + + utilities.jumpToSlice(tViewport.element, { + imageIndex: targetSliceIndex, + }); +}; + +const createFrameViewSynchronizer = (synchronizerName: string): Synchronizer => { + const synchronizer = SynchronizerManager.createSynchronizer( + synchronizerName, + EVENTS.CAMERA_MODIFIED, + frameViewSyncCallback + ); + return synchronizer; +}; + +export { createFrameViewSynchronizer }; diff --git a/extensions/cornerstone/src/tools/CalibrationLineTool.ts b/extensions/cornerstone/src/tools/CalibrationLineTool.ts index c9e008fc61..6c77fbe79a 100644 --- a/extensions/cornerstone/src/tools/CalibrationLineTool.ts +++ b/extensions/cornerstone/src/tools/CalibrationLineTool.ts @@ -1,4 +1,3 @@ -import { metaData } from '@cornerstonejs/core'; import { LengthTool, utilities } from '@cornerstonejs/tools'; import callInputDialog from '../utils/callInputDialog'; import getActiveViewportEnabledElement from '../utils/getActiveViewportEnabledElement'; @@ -49,7 +48,10 @@ function calculateLength3(pos1, pos2) { export default CalibrationLineTool; -export function onCompletedCalibrationLine(servicesManager, csToolsEvent) { +export function onCompletedCalibrationLine( + servicesManager: AppTypes.ServicesManager, + csToolsEvent +) { const { uiDialogService, viewportGridService } = servicesManager.services; // calculate length (mm) with the current Pixel Spacing diff --git a/extensions/cornerstone/src/types/AppTypes.ts b/extensions/cornerstone/src/types/AppTypes.ts new file mode 100644 index 0000000000..90997eb273 --- /dev/null +++ b/extensions/cornerstone/src/types/AppTypes.ts @@ -0,0 +1,37 @@ +/* eslint-disable @typescript-eslint/no-namespace */ +import CornerstoneCacheServiceType from '../services/CornerstoneCacheService'; +import CornerstoneViewportServiceType from '../services/ViewportService/CornerstoneViewportService'; +import SegmentationServiceType from '../services/SegmentationService'; +import SyncGroupServiceType from '../services/SyncGroupService'; +import ToolGroupServiceType from '../services/ToolGroupService'; +import ViewportActionCornersServiceType from '../services/ViewportActionCornersService/ViewportActionCornersService'; +import ColorbarServiceType from '../services/ColorbarService'; +import * as cornerstone from '@cornerstonejs/core'; +import * as cornerstoneTools from '@cornerstonejs/tools'; + +declare global { + namespace AppTypes { + export type CornerstoneCacheService = CornerstoneCacheServiceType; + export type CornerstoneViewportService = CornerstoneViewportServiceType; + export type SegmentationService = SegmentationServiceType; + export type SyncGroupService = SyncGroupServiceType; + export type ToolGroupService = ToolGroupServiceType; + export type ViewportActionCornersService = ViewportActionCornersServiceType; + export type ColorbarService = ColorbarServiceType; + export interface Services { + cornerstoneViewportService?: CornerstoneViewportServiceType; + toolGroupService?: ToolGroupServiceType; + syncGroupService?: SyncGroupServiceType; + segmentationService?: SegmentationServiceType; + cornerstoneCacheService?: CornerstoneCacheServiceType; + viewportActionCornersService?: ViewportActionCornersServiceType; + colorbarService?: ColorbarServiceType; + } + + export interface Test { + services?: Services; + cornerstone?: typeof cornerstone; + cornerstoneTools?: typeof cornerstoneTools; + } + } +} diff --git a/extensions/cornerstone/src/types/Colorbar.ts b/extensions/cornerstone/src/types/Colorbar.ts index 79beb199f9..9eea7553ce 100644 --- a/extensions/cornerstone/src/types/Colorbar.ts +++ b/extensions/cornerstone/src/types/Colorbar.ts @@ -1,5 +1,4 @@ import { ColorMapPreset } from './Colormap'; -import { CommandsManager, ServicesManager } from '@ohif/core'; export type ColorbarOptions = { position: string; @@ -11,8 +10,6 @@ export type ColorbarOptions = { export type ColorbarProps = { viewportId: string; - commandsManager: CommandsManager; - serviceManager: ServicesManager; displaySets: Array; colorbarProperties: ColorbarProperties; }; diff --git a/extensions/cornerstone/src/types/Colormap.ts b/extensions/cornerstone/src/types/Colormap.ts index d0cf1b22a4..6e3032243f 100644 --- a/extensions/cornerstone/src/types/Colormap.ts +++ b/extensions/cornerstone/src/types/Colormap.ts @@ -1,4 +1,4 @@ -import { CommandsManager, ServicesManager } from '@ohif/core'; +import { CommandsManager } from '@ohif/core'; export type ColorMapPreset = { ColorSpace; @@ -10,7 +10,7 @@ export type ColorMapPreset = { export type ColormapProps = { viewportId: string; commandsManager: CommandsManager; - serviceManager: ServicesManager; + servicesManager: AppTypes.ServicesManager; colormaps: Array; displaySets: Array; }; diff --git a/extensions/cornerstone/src/types/CornerstoneCacheService.ts b/extensions/cornerstone/src/types/CornerstoneCacheService.ts index ba79745a0d..3fef228b21 100644 --- a/extensions/cornerstone/src/types/CornerstoneCacheService.ts +++ b/extensions/cornerstone/src/types/CornerstoneCacheService.ts @@ -22,7 +22,7 @@ type VolumeData = { type StackViewportData = { viewportType: Enums.ViewportType; - data: StackData; + data: StackData[]; }; type VolumeViewportData = { diff --git a/extensions/cornerstone/src/types/CornerstoneServices.ts b/extensions/cornerstone/src/types/CornerstoneServices.ts index a55b4ab47c..b11dc97ee7 100644 --- a/extensions/cornerstone/src/types/CornerstoneServices.ts +++ b/extensions/cornerstone/src/types/CornerstoneServices.ts @@ -5,6 +5,7 @@ import SegmentationService from '../services/SegmentationService'; import CornerstoneCacheService from '../services/CornerstoneCacheService'; import CornerstoneViewportService from '../services/ViewportService/CornerstoneViewportService'; import ViewportActionCornersService from '../services/ViewportActionCornersService/ViewportActionCornersService'; +import ColorbarService from '../services/ColorbarService'; interface CornerstoneServices extends Types.Services { cornerstoneViewportService: CornerstoneViewportService; @@ -13,6 +14,7 @@ interface CornerstoneServices extends Types.Services { segmentationService: SegmentationService; cornerstoneCacheService: CornerstoneCacheService; viewportActionCornersService: ViewportActionCornersService; + colorbarService: ColorbarService; } export default CornerstoneServices; diff --git a/extensions/cornerstone/src/types/ViewportPresets.ts b/extensions/cornerstone/src/types/ViewportPresets.ts index 070a6bbde9..e954c2292c 100644 --- a/extensions/cornerstone/src/types/ViewportPresets.ts +++ b/extensions/cornerstone/src/types/ViewportPresets.ts @@ -1,4 +1,4 @@ -import { ServicesManager, CommandsManager } from '@ohif/core'; +import { CommandsManager } from '@ohif/core'; export type ViewportPreset = { name: string; @@ -15,7 +15,7 @@ export type ViewportPreset = { export type VolumeRenderingPresetsProps = { viewportId: string; - serviceManager: ServicesManager; + servicesManager: AppTypes.ServicesManager; commandsManager: CommandsManager; volumeRenderingPresets: ViewportPreset[]; }; @@ -30,7 +30,7 @@ export type VolumeRenderingPresetsContentProps = { export type VolumeRenderingOptionsProps = { viewportId: string; commandsManager: CommandsManager; - serviceManager: ServicesManager; + servicesManager: AppTypes.ServicesManager; volumeRenderingQualityRange: VolumeRenderingQualityRange; }; @@ -43,24 +43,24 @@ export type VolumeRenderingQualityRange = { export type VolumeRenderingQualityProps = { viewportId: string; commandsManager: CommandsManager; - serviceManager: ServicesManager; + servicesManager: AppTypes.ServicesManager; volumeRenderingQualityRange: VolumeRenderingQualityRange; }; export type VolumeShiftProps = { viewportId: string; commandsManager: CommandsManager; - serviceManager: ServicesManager; + servicesManager: AppTypes.ServicesManager; }; export type VolumeShadeProps = { viewportId: string; commandsManager: CommandsManager; - serviceManager: ServicesManager; + servicesManager: AppTypes.ServicesManager; }; export type VolumeLightingProps = { viewportId: string; commandsManager: CommandsManager; - serviceManager: ServicesManager; + servicesManager: AppTypes.ServicesManager; }; diff --git a/extensions/cornerstone/src/utils/CornerstoneViewportDownloadForm.tsx b/extensions/cornerstone/src/utils/CornerstoneViewportDownloadForm.tsx index f4eaa13e81..0d512dfe87 100644 --- a/extensions/cornerstone/src/utils/CornerstoneViewportDownloadForm.tsx +++ b/extensions/cornerstone/src/utils/CornerstoneViewportDownloadForm.tsx @@ -128,7 +128,9 @@ const CornerstoneViewportDownloadForm = ({ // for some reason we need a reset camera here, and I don't know why downloadViewport.resetCamera(); const presentation = activeViewport.getViewPresentation(); - downloadViewport.setView(activeViewport.getViewReference(), presentation); + if (downloadViewport.setView) { + downloadViewport.setView(activeViewport.getViewReference(), presentation); + } downloadViewport.render(); } ); diff --git a/extensions/cornerstone/src/utils/getCornerstoneBlendMode.ts b/extensions/cornerstone/src/utils/getCornerstoneBlendMode.ts index 37dca4c10b..11ff71021c 100644 --- a/extensions/cornerstone/src/utils/getCornerstoneBlendMode.ts +++ b/extensions/cornerstone/src/utils/getCornerstoneBlendMode.ts @@ -1,6 +1,8 @@ import { Enums } from '@cornerstonejs/core'; const MIP = 'mip'; +const MINIP = 'minip'; +const AVG = 'avg'; export default function getCornerstoneBlendMode(blendMode: string): Enums.BlendModes { if (!blendMode) { @@ -11,5 +13,13 @@ export default function getCornerstoneBlendMode(blendMode: string): Enums.BlendM return Enums.BlendModes.MAXIMUM_INTENSITY_BLEND; } - throw new Error(); + if (blendMode.toLowerCase() === MINIP) { + return Enums.BlendModes.MINIMUM_INTENSITY_BLEND; + } + + if (blendMode.toLowerCase() === AVG) { + return Enums.BlendModes.AVERAGE_INTENSITY_BLEND; + } + + throw new Error(`Unsupported blend mode: ${blendMode}`); } diff --git a/extensions/cornerstone/src/utils/imageSliceSync/toggleImageSliceSync.ts b/extensions/cornerstone/src/utils/imageSliceSync/toggleImageSliceSync.ts index 1a8e8cd780..1ba3931ffc 100644 --- a/extensions/cornerstone/src/utils/imageSliceSync/toggleImageSliceSync.ts +++ b/extensions/cornerstone/src/utils/imageSliceSync/toggleImageSliceSync.ts @@ -1,10 +1,12 @@ +import { DisplaySetService, ViewportGridService } from '@ohif/core'; + const IMAGE_SLICE_SYNC_NAME = 'IMAGE_SLICE_SYNC'; export default function toggleImageSliceSync({ servicesManager, viewports: providedViewports, syncId, -}) { +}: withAppTypes) { const { syncGroupService, viewportGridService, displaySetService, cornerstoneViewportService } = servicesManager.services; @@ -46,7 +48,7 @@ export default function toggleImageSliceSync({ }); } -function disableSync(syncName, servicesManager) { +function disableSync(syncName, servicesManager: AppTypes.ServicesManager) { const { syncGroupService, viewportGridService, displaySetService, cornerstoneViewportService } = servicesManager.services; const viewports = getReconstructableStackViewports(viewportGridService, displaySetService); @@ -68,7 +70,10 @@ function disableSync(syncName, servicesManager) { * Gets the consistent spacing stack viewport types, which are the ones which * can be navigated using the stack image sync right now. */ -function getReconstructableStackViewports(viewportGridService, displaySetService) { +function getReconstructableStackViewports( + viewportGridService: ViewportGridService, + displaySetService: DisplaySetService +) { let { viewports } = viewportGridService.getState(); viewports = [...viewports.values()]; diff --git a/extensions/cornerstone/src/utils/measurementServiceMappings/Angle.ts b/extensions/cornerstone/src/utils/measurementServiceMappings/Angle.ts index 2e178f2d55..1ef0ecf49b 100644 --- a/extensions/cornerstone/src/utils/measurementServiceMappings/Angle.ts +++ b/extensions/cornerstone/src/utils/measurementServiceMappings/Angle.ts @@ -36,8 +36,8 @@ const Angle = { const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes( referencedImageId, - CornerstoneViewportService, - viewportId + displaySetService, + annotation ); let displaySet; @@ -48,7 +48,7 @@ const Angle = { SeriesInstanceUID ); } else { - displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID); + displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID)[0]; } const { points, textBox } = data.handles; @@ -76,11 +76,12 @@ const Angle = { data: data.cachedStats, type: getValueTypeFromToolType(toolName), getReport, + referencedImageId, }; }, }; -function getMappedAnnotations(annotation, DisplaySetService) { +function getMappedAnnotations(annotation, displaySetService) { const { metadata, data } = annotation; const { cachedStats } = data; const { referencedImageId } = metadata; @@ -94,19 +95,14 @@ function getMappedAnnotations(annotation, DisplaySetService) { Object.keys(cachedStats).forEach(targetId => { const targetStats = cachedStats[targetId]; - if (!referencedImageId) { - throw new Error('Non-acquisition plane measurement mapping not supported'); - } - - const { SOPInstanceUID, SeriesInstanceUID, frameNumber } = - getSOPInstanceAttributes(referencedImageId); - - const displaySet = DisplaySetService.getDisplaySetForSOPInstanceUID( - SOPInstanceUID, - SeriesInstanceUID, - frameNumber + const { SOPInstanceUID, SeriesInstanceUID, frameNumber } = getSOPInstanceAttributes( + referencedImageId, + displaySetService, + annotation ); + const displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID)[0]; + const { SeriesNumber } = displaySet; const { angle } = targetStats; const unit = '\u00B0'; diff --git a/extensions/cornerstone/src/utils/measurementServiceMappings/ArrowAnnotate.ts b/extensions/cornerstone/src/utils/measurementServiceMappings/ArrowAnnotate.ts index 373bd115ce..18aee0c238 100644 --- a/extensions/cornerstone/src/utils/measurementServiceMappings/ArrowAnnotate.ts +++ b/extensions/cornerstone/src/utils/measurementServiceMappings/ArrowAnnotate.ts @@ -34,8 +34,8 @@ const Length = { const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes( referencedImageId, - cornerstoneViewportService, - viewportId + displaySetService, + annotation ); let displaySet; @@ -46,7 +46,7 @@ const Length = { SeriesInstanceUID ); } else { - displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID); + displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID)[0]; } const { points, textBox } = data.handles; @@ -64,6 +64,7 @@ const Length = { metadata, referenceSeriesUID: SeriesInstanceUID, referenceStudyUID: StudyInstanceUID, + referencedImageId, frameNumber: mappedAnnotations[0]?.frameNumber || 1, toolName: metadata.toolName, displaySetInstanceUID: displaySet.displaySetInstanceUID, @@ -85,15 +86,14 @@ function getMappedAnnotations(annotation, displaySetService) { const annotations = []; - const { SOPInstanceUID, SeriesInstanceUID, frameNumber } = - getSOPInstanceAttributes(referencedImageId); - - const displaySet = displaySetService.getDisplaySetForSOPInstanceUID( - SOPInstanceUID, - SeriesInstanceUID, - frameNumber + const { SOPInstanceUID, SeriesInstanceUID, frameNumber } = getSOPInstanceAttributes( + referencedImageId, + displaySetService, + annotation ); + const displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID)[0]; + const { SeriesNumber } = displaySet; annotations.push({ diff --git a/extensions/cornerstone/src/utils/measurementServiceMappings/Bidirectional.ts b/extensions/cornerstone/src/utils/measurementServiceMappings/Bidirectional.ts index 6517445d21..d2b1f81f95 100644 --- a/extensions/cornerstone/src/utils/measurementServiceMappings/Bidirectional.ts +++ b/extensions/cornerstone/src/utils/measurementServiceMappings/Bidirectional.ts @@ -31,8 +31,8 @@ const Bidirectional = { const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes( referencedImageId, - cornerstoneViewportService, - viewportId + displaySetService, + annotation ); let displaySet; @@ -43,7 +43,7 @@ const Bidirectional = { SeriesInstanceUID ); } else { - displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID); + displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID)[0]; } const { points, textBox } = data.handles; @@ -63,6 +63,7 @@ const Bidirectional = { metadata, referenceSeriesUID: SeriesInstanceUID, referenceStudyUID: StudyInstanceUID, + referencedImageId, frameNumber: mappedAnnotations[0]?.frameNumber || 1, toolName: metadata.toolName, displaySetInstanceUID: displaySet.displaySetInstanceUID, @@ -89,19 +90,14 @@ function getMappedAnnotations(annotation, displaySetService) { Object.keys(cachedStats).forEach(targetId => { const targetStats = cachedStats[targetId]; - if (!referencedImageId) { - throw new Error('Non-acquisition plane measurement mapping not supported'); - } - - const { SOPInstanceUID, SeriesInstanceUID, frameNumber } = - getSOPInstanceAttributes(referencedImageId); - - const displaySet = displaySetService.getDisplaySetForSOPInstanceUID( - SOPInstanceUID, - SeriesInstanceUID, - frameNumber + const { SOPInstanceUID, SeriesInstanceUID, frameNumber } = getSOPInstanceAttributes( + referencedImageId, + displaySetService, + annotation ); + const displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID)[0]; + const { SeriesNumber } = displaySet; const { length, width, unit } = targetStats; diff --git a/extensions/cornerstone/src/utils/measurementServiceMappings/CircleROI.ts b/extensions/cornerstone/src/utils/measurementServiceMappings/CircleROI.ts index c995fb171a..1e2e85a3f8 100644 --- a/extensions/cornerstone/src/utils/measurementServiceMappings/CircleROI.ts +++ b/extensions/cornerstone/src/utils/measurementServiceMappings/CircleROI.ts @@ -2,12 +2,13 @@ import SUPPORTED_TOOLS from './constants/supportedTools'; import { getDisplayUnit } from './utils'; import getSOPInstanceAttributes from './utils/getSOPInstanceAttributes'; import { utils } from '@ohif/core'; +import { getStatisticDisplayString } from './utils/getValueDisplayString'; const CircleROI = { toAnnotation: measurement => {}, toMeasurement: ( csToolsEventDetail, - DisplaySetService, + displaySetService, CornerstoneViewportService, getValueTypeFromToolType, customizationService @@ -29,24 +30,24 @@ const CircleROI = { const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes( referencedImageId, - CornerstoneViewportService, - viewportId + displaySetService, + annotation ); let displaySet; if (SOPInstanceUID) { - displaySet = DisplaySetService.getDisplaySetForSOPInstanceUID( + displaySet = displaySetService.getDisplaySetForSOPInstanceUID( SOPInstanceUID, SeriesInstanceUID ); } else { - displaySet = DisplaySetService.getDisplaySetsForSeries(SeriesInstanceUID); + displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID)[0]; } const { points, textBox } = data.handles; - const mappedAnnotations = getMappedAnnotations(annotation, DisplaySetService); + const mappedAnnotations = getMappedAnnotations(annotation, displaySetService); const displayText = getDisplayText(mappedAnnotations, displaySet, customizationService); const getReport = () => @@ -61,6 +62,7 @@ const CircleROI = { metadata, referenceSeriesUID: SeriesInstanceUID, referenceStudyUID: StudyInstanceUID, + referencedImageId, frameNumber: mappedAnnotations[0]?.frameNumber || 1, toolName: metadata.toolName, displaySetInstanceUID: displaySet.displaySetInstanceUID, @@ -73,7 +75,7 @@ const CircleROI = { }, }; -function getMappedAnnotations(annotation, DisplaySetService) { +function getMappedAnnotations(annotation, displaySetService) { const { metadata, data } = annotation; const { cachedStats } = data; const { referencedImageId } = metadata; @@ -87,20 +89,14 @@ function getMappedAnnotations(annotation, DisplaySetService) { Object.keys(cachedStats).forEach(targetId => { const targetStats = cachedStats[targetId]; - if (!referencedImageId) { - // Todo: Non-acquisition plane measurement mapping not supported yet - throw new Error('Non-acquisition plane measurement mapping not supported'); - } - - const { SOPInstanceUID, SeriesInstanceUID, frameNumber } = - getSOPInstanceAttributes(referencedImageId); - - const displaySet = DisplaySetService.getDisplaySetForSOPInstanceUID( - SOPInstanceUID, - SeriesInstanceUID, - frameNumber + const { SOPInstanceUID, SeriesInstanceUID, frameNumber } = getSOPInstanceAttributes( + referencedImageId, + displaySetService, + annotation ); + const displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID)[0]; + const { SeriesNumber } = displaySet; const { mean, stdDev, max, area, Modality, areaUnit, modalityUnit } = targetStats; @@ -193,11 +189,7 @@ function getDisplayText(mappedAnnotations, displaySet, customizationService) { mappedAnnotations.forEach(mappedAnnotation => { const { unit, max, SeriesNumber } = mappedAnnotation; - let maxStr = ''; - if (max) { - const roundedMax = utils.roundNumber(max, 2); - maxStr = `Max: ${roundedMax} ${getDisplayUnit(unit)} `; - } + const maxStr = getStatisticDisplayString(max, unit, 'max'); const str = `${maxStr}(S:${SeriesNumber}${instanceText}${frameText})`; if (!displayText.includes(str)) { diff --git a/extensions/cornerstone/src/utils/measurementServiceMappings/CobbAngle.ts b/extensions/cornerstone/src/utils/measurementServiceMappings/CobbAngle.ts index 631f0d029e..91f2c1576f 100644 --- a/extensions/cornerstone/src/utils/measurementServiceMappings/CobbAngle.ts +++ b/extensions/cornerstone/src/utils/measurementServiceMappings/CobbAngle.ts @@ -36,8 +36,8 @@ const CobbAngle = { const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes( referencedImageId, - CornerstoneViewportService, - viewportId + displaySetService, + annotation ); let displaySet; @@ -48,7 +48,7 @@ const CobbAngle = { SeriesInstanceUID ); } else { - displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID); + displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID)[0]; } const { points, textBox } = data.handles; @@ -68,6 +68,7 @@ const CobbAngle = { metadata, referenceSeriesUID: SeriesInstanceUID, referenceStudyUID: StudyInstanceUID, + referencedImageId, frameNumber: mappedAnnotations?.[0]?.frameNumber || 1, toolName: metadata.toolName, displaySetInstanceUID: displaySet.displaySetInstanceUID, @@ -80,7 +81,7 @@ const CobbAngle = { }, }; -function getMappedAnnotations(annotation, DisplaySetService) { +function getMappedAnnotations(annotation, displaySetService) { const { metadata, data } = annotation; const { cachedStats } = data; const { referencedImageId } = metadata; @@ -94,19 +95,14 @@ function getMappedAnnotations(annotation, DisplaySetService) { Object.keys(cachedStats).forEach(targetId => { const targetStats = cachedStats[targetId]; - if (!referencedImageId) { - throw new Error('Non-acquisition plane measurement mapping not supported'); - } - - const { SOPInstanceUID, SeriesInstanceUID, frameNumber } = - getSOPInstanceAttributes(referencedImageId); - - const displaySet = DisplaySetService.getDisplaySetForSOPInstanceUID( - SOPInstanceUID, - SeriesInstanceUID, - frameNumber + const { SOPInstanceUID, SeriesInstanceUID, frameNumber } = getSOPInstanceAttributes( + referencedImageId, + displaySetService, + annotation ); + const displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID)[0]; + const { SeriesNumber } = displaySet; const { angle } = targetStats; const unit = '\u00B0'; diff --git a/extensions/cornerstone/src/utils/measurementServiceMappings/EllipticalROI.ts b/extensions/cornerstone/src/utils/measurementServiceMappings/EllipticalROI.ts index 30a925dd1f..54f156abbd 100644 --- a/extensions/cornerstone/src/utils/measurementServiceMappings/EllipticalROI.ts +++ b/extensions/cornerstone/src/utils/measurementServiceMappings/EllipticalROI.ts @@ -2,6 +2,7 @@ import SUPPORTED_TOOLS from './constants/supportedTools'; import { getDisplayUnit } from './utils'; import getSOPInstanceAttributes from './utils/getSOPInstanceAttributes'; import { utils } from '@ohif/core'; +import { getStatisticDisplayString } from './utils/getValueDisplayString'; const EllipticalROI = { toAnnotation: measurement => {}, @@ -29,8 +30,8 @@ const EllipticalROI = { const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes( referencedImageId, - cornerstoneViewportService, - viewportId + displaySetService, + annotation ); let displaySet; @@ -41,7 +42,7 @@ const EllipticalROI = { SeriesInstanceUID ); } else { - displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID); + displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID)[0]; } const { points, textBox } = data.handles; @@ -61,6 +62,7 @@ const EllipticalROI = { metadata, referenceSeriesUID: SeriesInstanceUID, referenceStudyUID: StudyInstanceUID, + referencedImageId, frameNumber: mappedAnnotations[0]?.frameNumber || 1, toolName: metadata.toolName, displaySetInstanceUID: displaySet.displaySetInstanceUID, @@ -87,20 +89,14 @@ function getMappedAnnotations(annotation, displaySetService) { Object.keys(cachedStats).forEach(targetId => { const targetStats = cachedStats[targetId]; - if (!referencedImageId) { - // Todo: Non-acquisition plane measurement mapping not supported yet - throw new Error('Non-acquisition plane measurement mapping not supported'); - } - - const { SOPInstanceUID, SeriesInstanceUID, frameNumber } = - getSOPInstanceAttributes(referencedImageId); - - const displaySet = displaySetService.getDisplaySetForSOPInstanceUID( - SOPInstanceUID, - SeriesInstanceUID, - frameNumber + const { SOPInstanceUID, SeriesInstanceUID, frameNumber } = getSOPInstanceAttributes( + referencedImageId, + displaySetService, + annotation ); + const displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID)[0]; + const { SeriesNumber } = displaySet; const { mean, stdDev, max, area, Modality, areaUnit, modalityUnit } = targetStats; @@ -192,12 +188,7 @@ function getDisplayText(mappedAnnotations, displaySet, customizationService) { mappedAnnotations.forEach(mappedAnnotation => { const { unit, max, SeriesNumber } = mappedAnnotation; - let maxStr = ''; - if (max) { - const roundedMax = utils.roundNumber(max, 2); - maxStr = `Max: ${roundedMax} ${getDisplayUnit(unit)} `; - } - + const maxStr = getStatisticDisplayString(max, unit, 'max'); const str = `${maxStr}(S:${SeriesNumber}${instanceText}${frameText})`; if (!displayText.includes(str)) { displayText.push(str); diff --git a/extensions/cornerstone/src/utils/measurementServiceMappings/Length.ts b/extensions/cornerstone/src/utils/measurementServiceMappings/Length.ts index bb1319b240..9ebad2b48a 100644 --- a/extensions/cornerstone/src/utils/measurementServiceMappings/Length.ts +++ b/extensions/cornerstone/src/utils/measurementServiceMappings/Length.ts @@ -35,8 +35,8 @@ const Length = { const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes( referencedImageId, - cornerstoneViewportService, - viewportId + displaySetService, + annotation ); let displaySet; @@ -47,7 +47,7 @@ const Length = { SeriesInstanceUID ); } else { - displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID); + displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID)[0]; } const { points, textBox } = data.handles; @@ -67,6 +67,7 @@ const Length = { metadata, referenceSeriesUID: SeriesInstanceUID, referenceStudyUID: StudyInstanceUID, + referencedImageId, frameNumber: mappedAnnotations[0]?.frameNumber || 1, toolName: metadata.toolName, displaySetInstanceUID: displaySet.displaySetInstanceUID, @@ -93,19 +94,14 @@ function getMappedAnnotations(annotation, displaySetService) { Object.keys(cachedStats).forEach(targetId => { const targetStats = cachedStats[targetId]; - if (!referencedImageId) { - throw new Error('Non-acquisition plane measurement mapping not supported'); - } - - const { SOPInstanceUID, SeriesInstanceUID, frameNumber } = - getSOPInstanceAttributes(referencedImageId); - - const displaySet = displaySetService.getDisplaySetForSOPInstanceUID( - SOPInstanceUID, - SeriesInstanceUID, - frameNumber + const { SOPInstanceUID, SeriesInstanceUID, frameNumber } = getSOPInstanceAttributes( + referencedImageId, + displaySetService, + annotation ); + const displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID)[0]; + const { SeriesNumber } = displaySet; const { length, unit = 'mm' } = targetStats; diff --git a/extensions/cornerstone/src/utils/measurementServiceMappings/PlanarFreehandROI.ts b/extensions/cornerstone/src/utils/measurementServiceMappings/PlanarFreehandROI.ts index d3c837c2aa..bad6062b93 100644 --- a/extensions/cornerstone/src/utils/measurementServiceMappings/PlanarFreehandROI.ts +++ b/extensions/cornerstone/src/utils/measurementServiceMappings/PlanarFreehandROI.ts @@ -1,6 +1,5 @@ import SUPPORTED_TOOLS from './constants/supportedTools'; import getSOPInstanceAttributes from './utils/getSOPInstanceAttributes'; -import { getDisplayUnit } from './utils'; import { utils } from '@ohif/core'; /** @@ -20,7 +19,7 @@ const PlanarFreehandROI = { */ toMeasurement: ( csToolsEventDetail, - DisplaySetService, + displaySetService, CornerstoneViewportService, getValueTypeFromToolType, customizationService @@ -40,16 +39,16 @@ const PlanarFreehandROI = { } const { SOPInstanceUID, SeriesInstanceUID, frameNumber, StudyInstanceUID } = - getSOPInstanceAttributes(referencedImageId); + getSOPInstanceAttributes(referencedImageId, displaySetService, annotation); let displaySet; if (SOPInstanceUID) { - displaySet = DisplaySetService.getDisplaySetForSOPInstanceUID( + displaySet = displaySetService.getDisplaySetForSOPInstanceUID( SOPInstanceUID, SeriesInstanceUID ); } else { - displaySet = DisplaySetService.getDisplaySetsForSeries(SeriesInstanceUID); + displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID)[0]; } return { @@ -62,10 +61,11 @@ const PlanarFreehandROI = { frameNumber, referenceSeriesUID: SeriesInstanceUID, referenceStudyUID: StudyInstanceUID, + referencedImageId, toolName: metadata.toolName, displaySetInstanceUID: displaySet.displaySetInstanceUID, label: data.label, - displayText: getDisplayText(annotation, displaySet, customizationService), + displayText: getDisplayText(annotation, displaySet, customizationService, displaySetService), data: data.cachedStats, type: getValueTypeFromToolType(toolName), getReport: () => getColumnValueReport(annotation, customizationService), @@ -122,17 +122,20 @@ function getColumnValueReport(annotation, customizationService) { * @param {Object} displaySet - The display set object. * @returns {string[]} - An array of display text. */ -function getDisplayText(annotation, displaySet, customizationService) { +function getDisplayText(annotation, displaySet, customizationService, displaySetService) { const { PlanarFreehandROI } = customizationService.get('cornerstone.measurements'); - const { displayText } = PlanarFreehandROI; + const { displayText: displayTextClosed, displayTextOpen } = PlanarFreehandROI; const { metadata, data } = annotation; - if (!data.cachedStats || !data.cachedStats[`imageId:${metadata.referencedImageId}`]) { - return []; - } + const isClosed = data.contour?.closed; + const displayText = isClosed ? displayTextClosed : displayTextOpen; - const { SOPInstanceUID, frameNumber } = getSOPInstanceAttributes(metadata.referencedImageId); + const { SOPInstanceUID, frameNumber } = getSOPInstanceAttributes( + metadata.referencedImageId, + displaySetService, + annotation + ); const displayTextArray = []; @@ -150,7 +153,13 @@ function getDisplayText(annotation, displaySet, customizationService) { displayTextArray.push(`S: ${SeriesNumber}${instanceText}${frameText}`); } - const stats = data.cachedStats[`imageId:${metadata.referencedImageId}`]; + const stats = + data.cachedStats[`imageId:${metadata.referencedImageId}`] || + Array.from(Object.values(data.cachedStats))[0]; + + if (!stats) { + return displayTextArray; + } const roundValues = values => { if (Array.isArray(values)) { @@ -158,10 +167,10 @@ function getDisplayText(annotation, displaySet, customizationService) { if (isNaN(value)) { return value; } - return utils.roundNumber(value); + return utils.roundNumber(value, 2); }); } - return isNaN(values) ? values : utils.roundNumber(values); + return isNaN(values) ? [values] : [utils.roundNumber(values, 2)]; }; const findUnitForValue = (displayTextItems, value) => @@ -169,7 +178,7 @@ function getDisplayText(annotation, displaySet, customizationService) { ?.value; const formatDisplayText = (displayName, result, unit) => - `${displayName}: ${Array.isArray(result) ? roundValues(result).join(', ') : roundValues(result)} ${unit}`; + `${displayName}: ${roundValues(result).join(', ')} ${unit}`; displayText.forEach(({ displayName, value, type }) => { if (type === 'value') { diff --git a/extensions/cornerstone/src/utils/measurementServiceMappings/Probe.ts b/extensions/cornerstone/src/utils/measurementServiceMappings/Probe.ts index 554df18421..7d0c89c29d 100644 --- a/extensions/cornerstone/src/utils/measurementServiceMappings/Probe.ts +++ b/extensions/cornerstone/src/utils/measurementServiceMappings/Probe.ts @@ -34,8 +34,11 @@ const Probe = { throw new Error('Tool not supported'); } - const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = - getSOPInstanceAttributes(referencedImageId); + const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes( + referencedImageId, + displaySetService, + annotation + ); let displaySet; @@ -45,7 +48,7 @@ const Probe = { SeriesInstanceUID ); } else { - displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID); + displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID)[0]; } const { points } = data.handles; @@ -64,6 +67,7 @@ const Probe = { metadata, referenceSeriesUID: SeriesInstanceUID, referenceStudyUID: StudyInstanceUID, + referencedImageId, frameNumber: mappedAnnotations?.[0]?.frameNumber || 1, toolName: metadata.toolName, displaySetInstanceUID: displaySet.displaySetInstanceUID, @@ -76,7 +80,7 @@ const Probe = { }, }; -function getMappedAnnotations(annotation, DisplaySetService) { +function getMappedAnnotations(annotation, displaySetService) { const { metadata, data } = annotation; const { cachedStats } = data; const { referencedImageId } = metadata; @@ -90,19 +94,14 @@ function getMappedAnnotations(annotation, DisplaySetService) { Object.keys(cachedStats).forEach(targetId => { const targetStats = cachedStats[targetId]; - if (!referencedImageId) { - throw new Error('Non-acquisition plane measurement mapping not supported'); - } - - const { SOPInstanceUID, SeriesInstanceUID, frameNumber } = - getSOPInstanceAttributes(referencedImageId); - - const displaySet = DisplaySetService.getDisplaySetForSOPInstanceUID( - SOPInstanceUID, - SeriesInstanceUID, - frameNumber + const { SOPInstanceUID, SeriesInstanceUID, frameNumber } = getSOPInstanceAttributes( + referencedImageId, + displaySetService, + annotation ); + const displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID)[0]; + const { SeriesNumber } = displaySet; const { value } = targetStats; const unit = 'HU'; diff --git a/extensions/cornerstone/src/utils/measurementServiceMappings/RectangleROI.ts b/extensions/cornerstone/src/utils/measurementServiceMappings/RectangleROI.ts index 943822de74..61b2e1c476 100644 --- a/extensions/cornerstone/src/utils/measurementServiceMappings/RectangleROI.ts +++ b/extensions/cornerstone/src/utils/measurementServiceMappings/RectangleROI.ts @@ -2,12 +2,13 @@ import SUPPORTED_TOOLS from './constants/supportedTools'; import { getDisplayUnit } from './utils'; import getSOPInstanceAttributes from './utils/getSOPInstanceAttributes'; import { utils } from '@ohif/core'; +import { getStatisticDisplayString } from './utils/getValueDisplayString'; const RectangleROI = { toAnnotation: measurement => {}, toMeasurement: ( csToolsEventDetail, - DisplaySetService, + displaySetService, CornerstoneViewportService, getValueTypeFromToolType, customizationService @@ -29,24 +30,24 @@ const RectangleROI = { const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes( referencedImageId, - CornerstoneViewportService, - viewportId + displaySetService, + annotation ); let displaySet; if (SOPInstanceUID) { - displaySet = DisplaySetService.getDisplaySetForSOPInstanceUID( + displaySet = displaySetService.getDisplaySetForSOPInstanceUID( SOPInstanceUID, SeriesInstanceUID ); } else { - displaySet = DisplaySetService.getDisplaySetsForSeries(SeriesInstanceUID); + displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID)[0]; } const { points, textBox } = data.handles; - const mappedAnnotations = getMappedAnnotations(annotation, DisplaySetService); + const mappedAnnotations = getMappedAnnotations(annotation, displaySetService); const displayText = getDisplayText(mappedAnnotations, displaySet, customizationService); const getReport = () => @@ -61,6 +62,7 @@ const RectangleROI = { metadata, referenceSeriesUID: SeriesInstanceUID, referenceStudyUID: StudyInstanceUID, + referencedImageId, frameNumber: mappedAnnotations[0]?.frameNumber || 1, toolName: metadata.toolName, displaySetInstanceUID: displaySet.displaySetInstanceUID, @@ -73,7 +75,7 @@ const RectangleROI = { }, }; -function getMappedAnnotations(annotation, DisplaySetService) { +function getMappedAnnotations(annotation, displaySetService) { const { metadata, data } = annotation; const { cachedStats } = data; const { referencedImageId } = metadata; @@ -87,20 +89,14 @@ function getMappedAnnotations(annotation, DisplaySetService) { Object.keys(cachedStats).forEach(targetId => { const targetStats = cachedStats[targetId]; - if (!referencedImageId) { - // Todo: Non-acquisition plane measurement mapping not supported yet - throw new Error('Non-acquisition plane measurement mapping not supported'); - } - - const { SOPInstanceUID, SeriesInstanceUID, frameNumber } = - getSOPInstanceAttributes(referencedImageId); - - const displaySet = DisplaySetService.getDisplaySetForSOPInstanceUID( - SOPInstanceUID, - SeriesInstanceUID, - frameNumber + const { SOPInstanceUID, SeriesInstanceUID, frameNumber } = getSOPInstanceAttributes( + referencedImageId, + displaySetService, + annotation ); + const displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID)[0]; + const { SeriesNumber } = displaySet; const { mean, stdDev, max, area, Modality, modalityUnit, areaUnit } = targetStats; @@ -113,6 +109,7 @@ function getMappedAnnotations(annotation, DisplaySetService) { unit: modalityUnit, mean, stdDev, + metadata, max, area, areaUnit, @@ -193,11 +190,7 @@ function getDisplayText(mappedAnnotations, displaySet, customizationService) { mappedAnnotations.forEach(mappedAnnotation => { const { unit, max, SeriesNumber } = mappedAnnotation; - let maxStr = ''; - if (max) { - const roundedMax = utils.roundNumber(max, 2); - maxStr = `Max: ${roundedMax} ${getDisplayUnit(unit)} `; - } + const maxStr = getStatisticDisplayString(max, unit, 'max'); const str = `${maxStr}(S:${SeriesNumber}${instanceText}${frameText})`; if (!displayText.includes(str)) { diff --git a/extensions/cornerstone/src/utils/measurementServiceMappings/SplineROI.ts b/extensions/cornerstone/src/utils/measurementServiceMappings/SplineROI.ts index 05ed5b1dc6..b1bac9f546 100644 --- a/extensions/cornerstone/src/utils/measurementServiceMappings/SplineROI.ts +++ b/extensions/cornerstone/src/utils/measurementServiceMappings/SplineROI.ts @@ -1,6 +1,5 @@ import SUPPORTED_TOOLS from './constants/supportedTools'; import getSOPInstanceAttributes from './utils/getSOPInstanceAttributes'; -import { getDisplayUnit } from './utils'; import { utils } from '@ohif/core'; /** diff --git a/extensions/cornerstone/src/utils/measurementServiceMappings/utils/getSOPInstanceAttributes.js b/extensions/cornerstone/src/utils/measurementServiceMappings/utils/getSOPInstanceAttributes.js index dd6992b831..101ef2117e 100644 --- a/extensions/cornerstone/src/utils/measurementServiceMappings/utils/getSOPInstanceAttributes.js +++ b/extensions/cornerstone/src/utils/measurementServiceMappings/utils/getSOPInstanceAttributes.js @@ -7,12 +7,24 @@ import * as cornerstone from '@cornerstonejs/core'; * @param {string} imageId The image id of the referenced image * @returns */ -export default function getSOPInstanceAttributes(imageId) { +export default function getSOPInstanceAttributes(imageId, displaySetService, annotation) { if (imageId) { return _getUIDFromImageID(imageId); } - // Todo: implement for volume viewports and use the referencedSeriesInstanceUID + const { metadata } = annotation; + const { volumeId } = metadata; + + const displaySet = displaySetService.getDisplaySetsBy(displaySet => + volumeId.includes(displaySet.uid) + )[0]; + const { StudyInstanceUID, SeriesInstanceUID } = displaySet; + + return { + SOPInstanceUID: undefined, + SeriesInstanceUID, + StudyInstanceUID, + }; } function _getUIDFromImageID(imageId) { diff --git a/extensions/cornerstone/src/utils/measurementServiceMappings/utils/getValueDisplayString.js b/extensions/cornerstone/src/utils/measurementServiceMappings/utils/getValueDisplayString.js new file mode 100644 index 0000000000..aa0fe316cb --- /dev/null +++ b/extensions/cornerstone/src/utils/measurementServiceMappings/utils/getValueDisplayString.js @@ -0,0 +1,12 @@ +import { utils } from '@ohif/core'; +import getDisplayUnit from './getDisplayUnit'; + +export const getStatisticDisplayString = (numbers, unit, key) => { + if (Array.isArray(numbers) && numbers.length > 0) { + const results = numbers.map(number => utils.roundNumber(number, 2)); + return `${key.charAt(0).toUpperCase() + key.slice(1)}: ${results.join(', ')} ${getDisplayUnit(unit)}`; + } + + const result = utils.roundNumber(numbers, 2); + return `${key.charAt(0).toUpperCase() + key.slice(1)}: ${result} ${getDisplayUnit(unit)}`; +}; diff --git a/extensions/cornerstone/src/utils/toggleVOISliceSync.ts b/extensions/cornerstone/src/utils/toggleVOISliceSync.ts index 0677cff37c..57e23d1163 100644 --- a/extensions/cornerstone/src/utils/toggleVOISliceSync.ts +++ b/extensions/cornerstone/src/utils/toggleVOISliceSync.ts @@ -1,3 +1,5 @@ +import { DisplaySetService, ViewportGridService } from '@ohif/core'; + const VOI_SYNC_NAME = 'VOI_SYNC'; const getSyncId = modality => `${VOI_SYNC_NAME}_${modality}`; @@ -6,7 +8,7 @@ export default function toggleVOISliceSync({ servicesManager, viewports: providedViewports, syncId, -}) { +}: withAppTypes) { const { syncGroupService, viewportGridService, displaySetService, cornerstoneViewportService } = servicesManager.services; @@ -52,7 +54,7 @@ export default function toggleVOISliceSync({ } } -function disableSync(modalityViewports, syncId, servicesManager) { +function disableSync(modalityViewports, syncId, servicesManager: AppTypes.ServicesManager) { const { syncGroupService, cornerstoneViewportService } = servicesManager.services; const viewports = modalityViewports; @@ -70,7 +72,10 @@ function disableSync(modalityViewports, syncId, servicesManager) { }); } -function groupViewportsByModality(viewportGridService, displaySetService) { +function groupViewportsByModality( + viewportGridService: ViewportGridService, + displaySetService: DisplaySetService +) { let { viewports } = viewportGridService.getState(); viewports = [...viewports.values()]; diff --git a/extensions/default/CHANGELOG.md b/extensions/default/CHANGELOG.md index c423452bb1..df54e0aa88 100644 --- a/extensions/default/CHANGELOG.md +++ b/extensions/default/CHANGELOG.md @@ -3,6 +3,749 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.9.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.70...v3.9.0-beta.71) (2024-07-30) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.69...v3.9.0-beta.70) (2024-07-30) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.68...v3.9.0-beta.69) (2024-07-27) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.67...v3.9.0-beta.68) (2024-07-26) + + +### Bug Fixes + +* **dicom:** Update multiframe DICOM JSON parsing for correct image ID generation ([#4307](https://github.com/OHIF/Viewers/issues/4307)) ([16b7aa4](https://github.com/OHIF/Viewers/commit/16b7aa4f6538b81e5915e47b9209d74575895dfe)) + + + + + +# [3.9.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.66...v3.9.0-beta.67) (2024-07-26) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.65...v3.9.0-beta.66) (2024-07-24) + + +### Features + +* **pmap:** added support for parametric map ([#4284](https://github.com/OHIF/Viewers/issues/4284)) ([fc0064f](https://github.com/OHIF/Viewers/commit/fc0064fd9d8cdc8fde81b81f0e71fd5d077ca22b)) + + + + + +# [3.9.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.64...v3.9.0-beta.65) (2024-07-23) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.63...v3.9.0-beta.64) (2024-07-19) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.62...v3.9.0-beta.63) (2024-07-10) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.61...v3.9.0-beta.62) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.60...v3.9.0-beta.61) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.59...v3.9.0-beta.60) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.58...v3.9.0-beta.59) (2024-07-05) + + +### Features + +* Add interleaved HTJ2K and volume progressive loading ([#4276](https://github.com/OHIF/Viewers/issues/4276)) ([a2084f3](https://github.com/OHIF/Viewers/commit/a2084f319b731d98b59485799fb80357094f8c38)) + + + + + +# [3.9.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.57...v3.9.0-beta.58) (2024-07-04) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.56...v3.9.0-beta.57) (2024-07-02) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.55...v3.9.0-beta.56) (2024-07-02) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.54...v3.9.0-beta.55) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.53...v3.9.0-beta.54) (2024-06-28) + + +### Features + +* **studyPrefetcher:** Study Prefetcher ([#4206](https://github.com/OHIF/Viewers/issues/4206)) ([2048b19](https://github.com/OHIF/Viewers/commit/2048b19484c0b1fae73f993cfaa814f861bbd230)) + + + + + +# [3.9.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.52...v3.9.0-beta.53) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.51...v3.9.0-beta.52) (2024-06-27) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.50...v3.9.0-beta.51) (2024-06-27) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.49...v3.9.0-beta.50) (2024-06-26) + + +### Bug Fixes + +* **orthanc:** Correct bulkdata URL handling and add configuration example PDF ([#4262](https://github.com/OHIF/Viewers/issues/4262)) ([fdf883a](https://github.com/OHIF/Viewers/commit/fdf883ada880c0979acba8fdff9b542dc05b7706)) + + + + + +# [3.9.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.48...v3.9.0-beta.49) (2024-06-26) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.47...v3.9.0-beta.48) (2024-06-25) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.46...v3.9.0-beta.47) (2024-06-21) + + +### Bug Fixes + +* Allow the mode setup/creation to be async, and provide a few more values to extension/app config/mode setup. ([#4016](https://github.com/OHIF/Viewers/issues/4016)) ([88575c6](https://github.com/OHIF/Viewers/commit/88575c6c09fd778a31b2f91524163ce65d1639dd)) +* **CustomViewportOverlay:** pass accurate data to Custom Viewport Functions ([#4224](https://github.com/OHIF/Viewers/issues/4224)) ([aef00e9](https://github.com/OHIF/Viewers/commit/aef00e91d63e9bc2de289cc6f35975e36547fb20)) +* **studybrowser:** Differentiate recent and all in study panel based on a provided time period ([#4242](https://github.com/OHIF/Viewers/issues/4242)) ([6f93449](https://github.com/OHIF/Viewers/commit/6f9344914951c204feaff48aaeb43cd7d727623d)) + + +### Features + +* **sort:** custom series sort in study panel ([#4214](https://github.com/OHIF/Viewers/issues/4214)) ([a433d40](https://github.com/OHIF/Viewers/commit/a433d406e2cac13f644203996c682260b54e8865)) + + + + + +# [3.9.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.45...v3.9.0-beta.46) (2024-06-18) + + +### Bug Fixes + +* Use correct external URL for rendered responses with relative URI ([#4236](https://github.com/OHIF/Viewers/issues/4236)) ([d8f6991](https://github.com/OHIF/Viewers/commit/d8f6991dbe72465080cfc5de39c7ea225702f2e0)) + + + + + +# [3.9.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.44...v3.9.0-beta.45) (2024-06-18) + + +### Bug Fixes + +* Re-enable hpScale module ([#4237](https://github.com/OHIF/Viewers/issues/4237)) ([2eab049](https://github.com/OHIF/Viewers/commit/2eab049d7993bb834f7736093941c175f16d61fc)) + + + + + +# [3.9.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.43...v3.9.0-beta.44) (2024-06-17) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.42...v3.9.0-beta.43) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.41...v3.9.0-beta.42) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.40...v3.9.0-beta.41) (2024-06-12) + + +### Features + +* Add customization merge, append or replace functionality ([#3871](https://github.com/OHIF/Viewers/issues/3871)) ([55dcfa1](https://github.com/OHIF/Viewers/commit/55dcfa1f6994a7036e7e594efb23673382a41915)) + + + + + +# [3.9.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.39...v3.9.0-beta.40) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.38...v3.9.0-beta.39) (2024-06-08) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.37...v3.9.0-beta.38) (2024-06-07) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.36...v3.9.0-beta.37) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.35...v3.9.0-beta.36) (2024-06-05) + + +### Bug Fixes + +* get direct url pixel data should be optional for video ([#4152](https://github.com/OHIF/Viewers/issues/4152)) ([649ffab](https://github.com/OHIF/Viewers/commit/649ffab4d97be875d42e1a3473a4354aac14e87d)) + + + + + +# [3.9.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.34...v3.9.0-beta.35) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.33...v3.9.0-beta.34) (2024-06-05) + + +### Bug Fixes + +* **hydration:** Maintain the same slice that the user was on pre hydration in post hydration for SR and SEG. ([#4200](https://github.com/OHIF/Viewers/issues/4200)) ([430330f](https://github.com/OHIF/Viewers/commit/430330f7e384d503cb6fc695a7a9642ddfaac313)) + + + + + +# [3.9.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.32...v3.9.0-beta.33) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.31...v3.9.0-beta.32) (2024-05-31) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.30...v3.9.0-beta.31) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.29...v3.9.0-beta.30) (2024-05-30) + + +### Bug Fixes + +* **docker:** docker build was broken because of imports ([#4192](https://github.com/OHIF/Viewers/issues/4192)) ([d7aa386](https://github.com/OHIF/Viewers/commit/d7aa386800153e0bb9eea6bbf36c696c57750ad8)) +* segmentation creation and segmentation mode viewport rendering ([#4193](https://github.com/OHIF/Viewers/issues/4193)) ([2174026](https://github.com/OHIF/Viewers/commit/217402678981f74293dff615f6b6812e54216d37)) + + + + + +# [3.9.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.28...v3.9.0-beta.29) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.27...v3.9.0-beta.28) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.26...v3.9.0-beta.27) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.25...v3.9.0-beta.26) (2024-05-29) + + +### Features + +* **hp:** Add displayArea option for Hanging protocols and example with Mamo([#3808](https://github.com/OHIF/Viewers/issues/3808)) ([18ac08e](https://github.com/OHIF/Viewers/commit/18ac08ed860d119721c52e4ffc270332259100b6)) + + + + + +# [3.9.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.24...v3.9.0-beta.25) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.23...v3.9.0-beta.24) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.22...v3.9.0-beta.23) (2024-05-28) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.21...v3.9.0-beta.22) (2024-05-27) + + +### Features + +* **ui:** move to React 18 and base for using shadcn/ui ([#4174](https://github.com/OHIF/Viewers/issues/4174)) ([70f2c79](https://github.com/OHIF/Viewers/commit/70f2c797f42af603d7ea0eb8d23b4103aba66f77)) + + + + + +# [3.9.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.20...v3.9.0-beta.21) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.19...v3.9.0-beta.20) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.18...v3.9.0-beta.19) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.17...v3.9.0-beta.18) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.16...v3.9.0-beta.17) (2024-05-23) + + +### Bug Fixes + +* **crosshairs:** reset angle, position, and slabthickness for crosshairs when reset viewport tool is used ([#4113](https://github.com/OHIF/Viewers/issues/4113)) ([73d9e99](https://github.com/OHIF/Viewers/commit/73d9e99d5d6f38ab6c36f4471d54f18798feacb4)) + + + + + +# [3.9.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.15...v3.9.0-beta.16) (2024-05-23) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.14...v3.9.0-beta.15) (2024-05-22) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.13...v3.9.0-beta.14) (2024-05-21) + + +### Bug Fixes + +* **HangingProtocol:** fix hp when unsupported series load first ([#4145](https://github.com/OHIF/Viewers/issues/4145)) ([b124c91](https://github.com/OHIF/Viewers/commit/b124c91d8fa0def262d1fee8f105295b02864129)) + + + + + +# [3.9.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.12...v3.9.0-beta.13) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.11...v3.9.0-beta.12) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.10...v3.9.0-beta.11) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.9...v3.9.0-beta.10) (2024-05-21) + + +### Bug Fixes + +* **stack-invalidation:** Resolve stack invalidation if metadata invalidated ([#4147](https://github.com/OHIF/Viewers/issues/4147)) ([70bb6c4](https://github.com/OHIF/Viewers/commit/70bb6c46267b3733a665f12534b849c890ce54ad)) + + + + + +# [3.9.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.8...v3.9.0-beta.9) (2024-05-17) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.7...v3.9.0-beta.8) (2024-05-16) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.6...v3.9.0-beta.7) (2024-05-15) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.5...v3.9.0-beta.6) (2024-05-15) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.4...v3.9.0-beta.5) (2024-05-14) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.3...v3.9.0-beta.4) (2024-05-14) + + +### Bug Fixes + +* **DicomJSONDataSource:** Fix series filtering ([#4092](https://github.com/OHIF/Viewers/issues/4092)) ([2de102c](https://github.com/OHIF/Viewers/commit/2de102c73c795cfb48b49005b10aa788444a45b7)) + + + + + +# [3.9.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.2...v3.9.0-beta.3) (2024-05-08) + + +### Features + +* **typings:** Enhance typing support with withAppTypes and custom services throughout OHIF ([#4090](https://github.com/OHIF/Viewers/issues/4090)) ([374065b](https://github.com/OHIF/Viewers/commit/374065bc3bad9d212f9817a8d41546cc64cfabfb)) + + + + + +# [3.9.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.1...v3.9.0-beta.2) (2024-05-06) + + +### Bug Fixes + +* **bugs:** enhancements and bugs in several areas ([#4086](https://github.com/OHIF/Viewers/issues/4086)) ([730f434](https://github.com/OHIF/Viewers/commit/730f4349100f21b4489a21707dbb2dca9dbfbba2)) + + + + + +# [3.9.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.0...v3.9.0-beta.1) (2024-05-06) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.9.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.94...v3.9.0-beta.0) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.8.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0-beta.94) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19) + + +### Bug Fixes + +* **layouts:** and fix thumbnail in touch and update migration guide for 3.8 release ([#4052](https://github.com/OHIF/Viewers/issues/4052)) ([d250d04](https://github.com/OHIF/Viewers/commit/d250d04580883446fcb8d748b2a97c5c198922af)) + + + + + +# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18) + +**Note:** Version bump only for package @ohif/extension-default + + + + + +# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18) + +**Note:** Version bump only for package @ohif/extension-default + + + + + # [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17) diff --git a/extensions/default/assets/images/action-new-dialog.svg b/extensions/default/assets/images/action-new-dialog.svg new file mode 100644 index 0000000000..89331dc6b5 --- /dev/null +++ b/extensions/default/assets/images/action-new-dialog.svg @@ -0,0 +1,14 @@ + + + action-new-dialog + + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/arrow-down.svg b/extensions/default/assets/images/arrow-down.svg new file mode 100644 index 0000000000..5064d51e42 --- /dev/null +++ b/extensions/default/assets/images/arrow-down.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/extensions/default/assets/images/arrow-left-small.svg b/extensions/default/assets/images/arrow-left-small.svg new file mode 100644 index 0000000000..4a86c50e23 --- /dev/null +++ b/extensions/default/assets/images/arrow-left-small.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/default/assets/images/arrow-left.svg b/extensions/default/assets/images/arrow-left.svg new file mode 100644 index 0000000000..307f8ffdf4 --- /dev/null +++ b/extensions/default/assets/images/arrow-left.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/default/assets/images/arrow-right-small.svg b/extensions/default/assets/images/arrow-right-small.svg new file mode 100644 index 0000000000..6d72336f60 --- /dev/null +++ b/extensions/default/assets/images/arrow-right-small.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/default/assets/images/arrow-right.svg b/extensions/default/assets/images/arrow-right.svg new file mode 100644 index 0000000000..307f8ffdf4 --- /dev/null +++ b/extensions/default/assets/images/arrow-right.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/default/assets/images/calendar.svg b/extensions/default/assets/images/calendar.svg new file mode 100644 index 0000000000..af83a587fc --- /dev/null +++ b/extensions/default/assets/images/calendar.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/extensions/default/assets/images/cancel.svg b/extensions/default/assets/images/cancel.svg new file mode 100644 index 0000000000..dbf6c1df11 --- /dev/null +++ b/extensions/default/assets/images/cancel.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/extensions/default/assets/images/checkbox-active.svg b/extensions/default/assets/images/checkbox-active.svg new file mode 100644 index 0000000000..a56c13f5c7 --- /dev/null +++ b/extensions/default/assets/images/checkbox-active.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/extensions/default/assets/images/checkbox-checked.svg b/extensions/default/assets/images/checkbox-checked.svg new file mode 100644 index 0000000000..e9aeb91451 --- /dev/null +++ b/extensions/default/assets/images/checkbox-checked.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/extensions/default/assets/images/checkbox-default.svg b/extensions/default/assets/images/checkbox-default.svg new file mode 100644 index 0000000000..3fd0791532 --- /dev/null +++ b/extensions/default/assets/images/checkbox-default.svg @@ -0,0 +1,3 @@ + + + diff --git a/extensions/default/assets/images/checkbox-unchecked.svg b/extensions/default/assets/images/checkbox-unchecked.svg new file mode 100644 index 0000000000..99779d52e5 --- /dev/null +++ b/extensions/default/assets/images/checkbox-unchecked.svg @@ -0,0 +1,3 @@ + + + diff --git a/extensions/default/assets/images/chevron-down.svg b/extensions/default/assets/images/chevron-down.svg new file mode 100644 index 0000000000..01aea1b304 --- /dev/null +++ b/extensions/default/assets/images/chevron-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/extensions/default/assets/images/chevron-left.svg b/extensions/default/assets/images/chevron-left.svg new file mode 100644 index 0000000000..e9951716ba --- /dev/null +++ b/extensions/default/assets/images/chevron-left.svg @@ -0,0 +1,3 @@ + + + diff --git a/extensions/default/assets/images/chevron-menu.svg b/extensions/default/assets/images/chevron-menu.svg new file mode 100644 index 0000000000..7e0d9054df --- /dev/null +++ b/extensions/default/assets/images/chevron-menu.svg @@ -0,0 +1,12 @@ + + + chevron-menu + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/chevron-next.svg b/extensions/default/assets/images/chevron-next.svg new file mode 100644 index 0000000000..197f3f2d42 --- /dev/null +++ b/extensions/default/assets/images/chevron-next.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/default/assets/images/chevron-prev.svg b/extensions/default/assets/images/chevron-prev.svg new file mode 100644 index 0000000000..dcd01a2b8c --- /dev/null +++ b/extensions/default/assets/images/chevron-prev.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/default/assets/images/chevron-right.svg b/extensions/default/assets/images/chevron-right.svg new file mode 100644 index 0000000000..355ccbff15 --- /dev/null +++ b/extensions/default/assets/images/chevron-right.svg @@ -0,0 +1,3 @@ + + + diff --git a/extensions/default/assets/images/circled-checkmark.svg b/extensions/default/assets/images/circled-checkmark.svg new file mode 100644 index 0000000000..a45ac3e51c --- /dev/null +++ b/extensions/default/assets/images/circled-checkmark.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/default/assets/images/clipboard.svg b/extensions/default/assets/images/clipboard.svg new file mode 100644 index 0000000000..850511a0b8 --- /dev/null +++ b/extensions/default/assets/images/clipboard.svg @@ -0,0 +1 @@ + diff --git a/extensions/default/assets/images/closeIcon.svg b/extensions/default/assets/images/closeIcon.svg new file mode 100644 index 0000000000..4760717a4b --- /dev/null +++ b/extensions/default/assets/images/closeIcon.svg @@ -0,0 +1,3 @@ + + + diff --git a/extensions/default/assets/images/content-next.svg b/extensions/default/assets/images/content-next.svg new file mode 100644 index 0000000000..45f0b39856 --- /dev/null +++ b/extensions/default/assets/images/content-next.svg @@ -0,0 +1,9 @@ + + + chevron-next + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/content-prev.svg b/extensions/default/assets/images/content-prev.svg new file mode 100644 index 0000000000..a01164b6ba --- /dev/null +++ b/extensions/default/assets/images/content-prev.svg @@ -0,0 +1,9 @@ + + + chevron-prev + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/database.svg b/extensions/default/assets/images/database.svg new file mode 100644 index 0000000000..79fd60ef69 --- /dev/null +++ b/extensions/default/assets/images/database.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/extensions/default/assets/images/dotted-circle.svg b/extensions/default/assets/images/dotted-circle.svg new file mode 100644 index 0000000000..9fcbdcf5a3 --- /dev/null +++ b/extensions/default/assets/images/dotted-circle.svg @@ -0,0 +1,3 @@ + + + diff --git a/extensions/default/assets/images/edit-patient.svg b/extensions/default/assets/images/edit-patient.svg new file mode 100644 index 0000000000..cd37992127 --- /dev/null +++ b/extensions/default/assets/images/edit-patient.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/extensions/default/assets/images/exclamation.svg b/extensions/default/assets/images/exclamation.svg new file mode 100644 index 0000000000..5b6ae388b2 --- /dev/null +++ b/extensions/default/assets/images/exclamation.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/extensions/default/assets/images/external-link.svg b/extensions/default/assets/images/external-link.svg new file mode 100644 index 0000000000..e2407a154d --- /dev/null +++ b/extensions/default/assets/images/external-link.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/extensions/default/assets/images/eye-hidden.svg b/extensions/default/assets/images/eye-hidden.svg new file mode 100644 index 0000000000..df364aeb69 --- /dev/null +++ b/extensions/default/assets/images/eye-hidden.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/extensions/default/assets/images/eye-visible.svg b/extensions/default/assets/images/eye-visible.svg new file mode 100644 index 0000000000..91e3efb805 --- /dev/null +++ b/extensions/default/assets/images/eye-visible.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/default/assets/images/focus-frame-target.svg b/extensions/default/assets/images/focus-frame-target.svg new file mode 100644 index 0000000000..1139d858c6 --- /dev/null +++ b/extensions/default/assets/images/focus-frame-target.svg @@ -0,0 +1,13 @@ + + + focus-frame-target + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/group-layers.svg b/extensions/default/assets/images/group-layers.svg new file mode 100644 index 0000000000..f4b0592151 --- /dev/null +++ b/extensions/default/assets/images/group-layers.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/default/assets/images/icon-add.svg b/extensions/default/assets/images/icon-add.svg new file mode 100644 index 0000000000..cc62a07ad4 --- /dev/null +++ b/extensions/default/assets/images/icon-add.svg @@ -0,0 +1,15 @@ + + + icon-add + + + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/icon-alert-small.svg b/extensions/default/assets/images/icon-alert-small.svg new file mode 100644 index 0000000000..51151d7092 --- /dev/null +++ b/extensions/default/assets/images/icon-alert-small.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/extensions/default/assets/images/icon-chevron-patient.svg b/extensions/default/assets/images/icon-chevron-patient.svg new file mode 100644 index 0000000000..b96478759b --- /dev/null +++ b/extensions/default/assets/images/icon-chevron-patient.svg @@ -0,0 +1,12 @@ + + + icon-chevron-patient + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/icon-clear-field.svg b/extensions/default/assets/images/icon-clear-field.svg new file mode 100644 index 0000000000..faf0195004 --- /dev/null +++ b/extensions/default/assets/images/icon-clear-field.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/extensions/default/assets/images/icon-close.svg b/extensions/default/assets/images/icon-close.svg new file mode 100644 index 0000000000..75066f4d00 --- /dev/null +++ b/extensions/default/assets/images/icon-close.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/extensions/default/assets/images/icon-color-lut.svg b/extensions/default/assets/images/icon-color-lut.svg new file mode 100644 index 0000000000..a339125e7f --- /dev/null +++ b/extensions/default/assets/images/icon-color-lut.svg @@ -0,0 +1,23 @@ + + + icon-color-lut + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/icon-delete.svg b/extensions/default/assets/images/icon-delete.svg new file mode 100644 index 0000000000..c55f7a27f0 --- /dev/null +++ b/extensions/default/assets/images/icon-delete.svg @@ -0,0 +1,17 @@ + + + icon-delete + + + + + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/icon-disclosure-close.svg b/extensions/default/assets/images/icon-disclosure-close.svg new file mode 100644 index 0000000000..dd6078c55c --- /dev/null +++ b/extensions/default/assets/images/icon-disclosure-close.svg @@ -0,0 +1,12 @@ + + + icon-disclosure-close + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/icon-disclosure-open.svg b/extensions/default/assets/images/icon-disclosure-open.svg new file mode 100644 index 0000000000..7dae7c9ec4 --- /dev/null +++ b/extensions/default/assets/images/icon-disclosure-open.svg @@ -0,0 +1,12 @@ + + + icon-disclosure-open + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/icon-display-settings.svg b/extensions/default/assets/images/icon-display-settings.svg new file mode 100644 index 0000000000..90adb8b5cc --- /dev/null +++ b/extensions/default/assets/images/icon-display-settings.svg @@ -0,0 +1,21 @@ + + + icon-display-settings + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/icon-more-menu.svg b/extensions/default/assets/images/icon-more-menu.svg new file mode 100644 index 0000000000..32f655b0d2 --- /dev/null +++ b/extensions/default/assets/images/icon-more-menu.svg @@ -0,0 +1,17 @@ + + + icon-more-menu + + + + + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/icon-mpr-alt.svg b/extensions/default/assets/images/icon-mpr-alt.svg new file mode 100644 index 0000000000..74c7550b45 --- /dev/null +++ b/extensions/default/assets/images/icon-mpr-alt.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/extensions/default/assets/images/icon-multiple-patients.svg b/extensions/default/assets/images/icon-multiple-patients.svg new file mode 100644 index 0000000000..276662f9a9 --- /dev/null +++ b/extensions/default/assets/images/icon-multiple-patients.svg @@ -0,0 +1,21 @@ + + + icon-multiple-patients + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/icon-next-inactive.svg b/extensions/default/assets/images/icon-next-inactive.svg new file mode 100644 index 0000000000..9071554487 --- /dev/null +++ b/extensions/default/assets/images/icon-next-inactive.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/default/assets/images/icon-next.svg b/extensions/default/assets/images/icon-next.svg new file mode 100644 index 0000000000..0a475ea0b1 --- /dev/null +++ b/extensions/default/assets/images/icon-next.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/default/assets/images/icon-patient.svg b/extensions/default/assets/images/icon-patient.svg new file mode 100644 index 0000000000..0ddc8f7e65 --- /dev/null +++ b/extensions/default/assets/images/icon-patient.svg @@ -0,0 +1,13 @@ + + + icon-patient + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/icon-pause.svg b/extensions/default/assets/images/icon-pause.svg new file mode 100644 index 0000000000..00f45ac298 --- /dev/null +++ b/extensions/default/assets/images/icon-pause.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/default/assets/images/icon-play.svg b/extensions/default/assets/images/icon-play.svg new file mode 100644 index 0000000000..226ae614d2 --- /dev/null +++ b/extensions/default/assets/images/icon-play.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/default/assets/images/icon-prev-inactive.svg b/extensions/default/assets/images/icon-prev-inactive.svg new file mode 100644 index 0000000000..2d0df2da12 --- /dev/null +++ b/extensions/default/assets/images/icon-prev-inactive.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/default/assets/images/icon-prev.svg b/extensions/default/assets/images/icon-prev.svg new file mode 100644 index 0000000000..bd77818049 --- /dev/null +++ b/extensions/default/assets/images/icon-prev.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/default/assets/images/icon-rename.svg b/extensions/default/assets/images/icon-rename.svg new file mode 100644 index 0000000000..6ccfa0432e --- /dev/null +++ b/extensions/default/assets/images/icon-rename.svg @@ -0,0 +1,15 @@ + + + icon-rename + + + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/icon-search.svg b/extensions/default/assets/images/icon-search.svg new file mode 100644 index 0000000000..2a960ddd32 --- /dev/null +++ b/extensions/default/assets/images/icon-search.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/extensions/default/assets/images/icon-settings.svg b/extensions/default/assets/images/icon-settings.svg new file mode 100644 index 0000000000..381dae6f2e --- /dev/null +++ b/extensions/default/assets/images/icon-settings.svg @@ -0,0 +1,13 @@ + + + icon-settings + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/icon-status-alert.svg b/extensions/default/assets/images/icon-status-alert.svg new file mode 100644 index 0000000000..615d4a2fdb --- /dev/null +++ b/extensions/default/assets/images/icon-status-alert.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/extensions/default/assets/images/icon-tool-scissor.svg b/extensions/default/assets/images/icon-tool-scissor.svg new file mode 100644 index 0000000000..8559d25154 --- /dev/null +++ b/extensions/default/assets/images/icon-tool-scissor.svg @@ -0,0 +1,17 @@ + + + icon-tool-scissor + + + + + + + + + + + + + + diff --git a/extensions/default/assets/images/icon-toolbar-back.svg b/extensions/default/assets/images/icon-toolbar-back.svg new file mode 100644 index 0000000000..8ee453b2c1 --- /dev/null +++ b/extensions/default/assets/images/icon-toolbar-back.svg @@ -0,0 +1,12 @@ + + + icon-toolbar-back + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/icon-transferring.svg b/extensions/default/assets/images/icon-transferring.svg new file mode 100644 index 0000000000..86379e138e --- /dev/null +++ b/extensions/default/assets/images/icon-transferring.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/default/assets/images/icon-upload.svg b/extensions/default/assets/images/icon-upload.svg new file mode 100644 index 0000000000..cdd1366fa3 --- /dev/null +++ b/extensions/default/assets/images/icon-upload.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/default/assets/images/icons-alert-outline.svg b/extensions/default/assets/images/icons-alert-outline.svg new file mode 100644 index 0000000000..747b65c78e --- /dev/null +++ b/extensions/default/assets/images/icons-alert-outline.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/extensions/default/assets/images/illustration-investigational-use.svg b/extensions/default/assets/images/illustration-investigational-use.svg new file mode 100644 index 0000000000..5ca03db687 --- /dev/null +++ b/extensions/default/assets/images/illustration-investigational-use.svg @@ -0,0 +1,20 @@ + + + illustration-investigational-use + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/info-action.svg b/extensions/default/assets/images/info-action.svg new file mode 100644 index 0000000000..305a6c385a --- /dev/null +++ b/extensions/default/assets/images/info-action.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/extensions/default/assets/images/info-link.svg b/extensions/default/assets/images/info-link.svg new file mode 100644 index 0000000000..743fdbb6b6 --- /dev/null +++ b/extensions/default/assets/images/info-link.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/extensions/default/assets/images/info.svg b/extensions/default/assets/images/info.svg new file mode 100644 index 0000000000..8874e2a8dd --- /dev/null +++ b/extensions/default/assets/images/info.svg @@ -0,0 +1,3 @@ + + + diff --git a/extensions/default/assets/images/launch-arrow.svg b/extensions/default/assets/images/launch-arrow.svg new file mode 100644 index 0000000000..0f55172d87 --- /dev/null +++ b/extensions/default/assets/images/launch-arrow.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/extensions/default/assets/images/launch-info.svg b/extensions/default/assets/images/launch-info.svg new file mode 100644 index 0000000000..6e999dc357 --- /dev/null +++ b/extensions/default/assets/images/launch-info.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/extensions/default/assets/images/layout-advanced-3d-four-up.svg b/extensions/default/assets/images/layout-advanced-3d-four-up.svg new file mode 100644 index 0000000000..f9f445ee13 --- /dev/null +++ b/extensions/default/assets/images/layout-advanced-3d-four-up.svg @@ -0,0 +1,13 @@ + + + layout-advanced-3d-four-up + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/layout-advanced-3d-main.svg b/extensions/default/assets/images/layout-advanced-3d-main.svg new file mode 100644 index 0000000000..15b5d31cca --- /dev/null +++ b/extensions/default/assets/images/layout-advanced-3d-main.svg @@ -0,0 +1,12 @@ + + + layout-advanced-3d-main + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/layout-advanced-3d-only.svg b/extensions/default/assets/images/layout-advanced-3d-only.svg new file mode 100644 index 0000000000..8ee7a74315 --- /dev/null +++ b/extensions/default/assets/images/layout-advanced-3d-only.svg @@ -0,0 +1,9 @@ + + + layout-advanced-3d-only + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/layout-advanced-3d-primary.svg b/extensions/default/assets/images/layout-advanced-3d-primary.svg new file mode 100644 index 0000000000..e77ecc9d65 --- /dev/null +++ b/extensions/default/assets/images/layout-advanced-3d-primary.svg @@ -0,0 +1,12 @@ + + + layout-advanced-3d-primary + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/layout-advanced-axial-primary.svg b/extensions/default/assets/images/layout-advanced-axial-primary.svg new file mode 100644 index 0000000000..79a34077a9 --- /dev/null +++ b/extensions/default/assets/images/layout-advanced-axial-primary.svg @@ -0,0 +1,11 @@ + + + layout-advanced-axial-primary + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/layout-advanced-mpr.svg b/extensions/default/assets/images/layout-advanced-mpr.svg new file mode 100644 index 0000000000..d23b2fbf45 --- /dev/null +++ b/extensions/default/assets/images/layout-advanced-mpr.svg @@ -0,0 +1,11 @@ + + + layout-advanced-mpr + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/layout-common-1x1.svg b/extensions/default/assets/images/layout-common-1x1.svg new file mode 100644 index 0000000000..537c7a86cf --- /dev/null +++ b/extensions/default/assets/images/layout-common-1x1.svg @@ -0,0 +1,9 @@ + + + layout-common-1x1 + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/layout-common-1x2.svg b/extensions/default/assets/images/layout-common-1x2.svg new file mode 100644 index 0000000000..db5aca3627 --- /dev/null +++ b/extensions/default/assets/images/layout-common-1x2.svg @@ -0,0 +1,10 @@ + + + layout-common-1x2 + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/layout-common-2x2.svg b/extensions/default/assets/images/layout-common-2x2.svg new file mode 100644 index 0000000000..8dfe00701f --- /dev/null +++ b/extensions/default/assets/images/layout-common-2x2.svg @@ -0,0 +1,11 @@ + + + layout-common-2x2 + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/layout-common-2x3.svg b/extensions/default/assets/images/layout-common-2x3.svg new file mode 100644 index 0000000000..3cb298eec5 --- /dev/null +++ b/extensions/default/assets/images/layout-common-2x3.svg @@ -0,0 +1,12 @@ + + + layout-common-2x3 + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/list-bullets.svg b/extensions/default/assets/images/list-bullets.svg new file mode 100644 index 0000000000..25949de56d --- /dev/null +++ b/extensions/default/assets/images/list-bullets.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/extensions/default/assets/images/loading-ohif-mark.svg b/extensions/default/assets/images/loading-ohif-mark.svg new file mode 100644 index 0000000000..181e275eb1 --- /dev/null +++ b/extensions/default/assets/images/loading-ohif-mark.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/extensions/default/assets/images/lock.svg b/extensions/default/assets/images/lock.svg new file mode 100644 index 0000000000..e3eaf48b68 --- /dev/null +++ b/extensions/default/assets/images/lock.svg @@ -0,0 +1 @@ + diff --git a/extensions/default/assets/images/logo-ohif-small.svg b/extensions/default/assets/images/logo-ohif-small.svg new file mode 100644 index 0000000000..6a8f669f66 --- /dev/null +++ b/extensions/default/assets/images/logo-ohif-small.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/extensions/default/assets/images/magnifier.svg b/extensions/default/assets/images/magnifier.svg new file mode 100644 index 0000000000..7d199db880 --- /dev/null +++ b/extensions/default/assets/images/magnifier.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/extensions/default/assets/images/navigation-panel-right-hide.svg b/extensions/default/assets/images/navigation-panel-right-hide.svg new file mode 100644 index 0000000000..7394397813 --- /dev/null +++ b/extensions/default/assets/images/navigation-panel-right-hide.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/extensions/default/assets/images/navigation-panel-right-reveal.svg b/extensions/default/assets/images/navigation-panel-right-reveal.svg new file mode 100644 index 0000000000..5d5f03544c --- /dev/null +++ b/extensions/default/assets/images/navigation-panel-right-reveal.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/extensions/default/assets/images/next-arrow.svg b/extensions/default/assets/images/next-arrow.svg new file mode 100644 index 0000000000..027a17de37 --- /dev/null +++ b/extensions/default/assets/images/next-arrow.svg @@ -0,0 +1,12 @@ + + + arrow-right + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/notifications-error.svg b/extensions/default/assets/images/notifications-error.svg new file mode 100644 index 0000000000..615d4a2fdb --- /dev/null +++ b/extensions/default/assets/images/notifications-error.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/extensions/default/assets/images/notifications-info.svg b/extensions/default/assets/images/notifications-info.svg new file mode 100644 index 0000000000..c3dd49c07a --- /dev/null +++ b/extensions/default/assets/images/notifications-info.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/extensions/default/assets/images/notifications-success.svg b/extensions/default/assets/images/notifications-success.svg new file mode 100644 index 0000000000..38096d3d79 --- /dev/null +++ b/extensions/default/assets/images/notifications-success.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/default/assets/images/notifications-warning.svg b/extensions/default/assets/images/notifications-warning.svg new file mode 100644 index 0000000000..a3f435647b --- /dev/null +++ b/extensions/default/assets/images/notifications-warning.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/extensions/default/assets/images/notificationwarning-diamond.svg b/extensions/default/assets/images/notificationwarning-diamond.svg new file mode 100644 index 0000000000..3ab48f2b90 --- /dev/null +++ b/extensions/default/assets/images/notificationwarning-diamond.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/extensions/default/assets/images/ohif-logo-color-darkbg.svg b/extensions/default/assets/images/ohif-logo-color-darkbg.svg new file mode 100644 index 0000000000..5458381274 --- /dev/null +++ b/extensions/default/assets/images/ohif-logo-color-darkbg.svg @@ -0,0 +1,20 @@ + + + ohif-logo-color-darkbg + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/old-play.svg b/extensions/default/assets/images/old-play.svg new file mode 100644 index 0000000000..b947e19343 --- /dev/null +++ b/extensions/default/assets/images/old-play.svg @@ -0,0 +1,9 @@ + + Play + + diff --git a/extensions/default/assets/images/old-stop.svg b/extensions/default/assets/images/old-stop.svg new file mode 100644 index 0000000000..264d09a2f8 --- /dev/null +++ b/extensions/default/assets/images/old-stop.svg @@ -0,0 +1,9 @@ + + Stop + + diff --git a/extensions/default/assets/images/old-trash.svg b/extensions/default/assets/images/old-trash.svg new file mode 100644 index 0000000000..f3033a083c --- /dev/null +++ b/extensions/default/assets/images/old-trash.svg @@ -0,0 +1,9 @@ + + Trash + + diff --git a/extensions/default/assets/images/panel-group-more.svg b/extensions/default/assets/images/panel-group-more.svg new file mode 100644 index 0000000000..a8b496e524 --- /dev/null +++ b/extensions/default/assets/images/panel-group-more.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/default/assets/images/panel-group-open-close.svg b/extensions/default/assets/images/panel-group-open-close.svg new file mode 100644 index 0000000000..5bed02f11a --- /dev/null +++ b/extensions/default/assets/images/panel-group-open-close.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/default/assets/images/pencil.svg b/extensions/default/assets/images/pencil.svg new file mode 100644 index 0000000000..1b643bfecb --- /dev/null +++ b/extensions/default/assets/images/pencil.svg @@ -0,0 +1,4 @@ + + + diff --git a/extensions/default/assets/images/power-off.svg b/extensions/default/assets/images/power-off.svg new file mode 100644 index 0000000000..3dd5dcf20d --- /dev/null +++ b/extensions/default/assets/images/power-off.svg @@ -0,0 +1,11 @@ + + Power Off + + diff --git a/extensions/default/assets/images/prev-arrow.svg b/extensions/default/assets/images/prev-arrow.svg new file mode 100644 index 0000000000..455afb6bfb --- /dev/null +++ b/extensions/default/assets/images/prev-arrow.svg @@ -0,0 +1,12 @@ + + + arrow-left + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/profile.svg b/extensions/default/assets/images/profile.svg new file mode 100644 index 0000000000..6d07ec81ea --- /dev/null +++ b/extensions/default/assets/images/profile.svg @@ -0,0 +1 @@ + diff --git a/extensions/default/assets/images/push-left.svg b/extensions/default/assets/images/push-left.svg new file mode 100644 index 0000000000..3569a0a406 --- /dev/null +++ b/extensions/default/assets/images/push-left.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/extensions/default/assets/images/push-right.svg b/extensions/default/assets/images/push-right.svg new file mode 100644 index 0000000000..af673fe3a3 --- /dev/null +++ b/extensions/default/assets/images/push-right.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/extensions/default/assets/images/row-add.svg b/extensions/default/assets/images/row-add.svg new file mode 100644 index 0000000000..490ede8bd1 --- /dev/null +++ b/extensions/default/assets/images/row-add.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/extensions/default/assets/images/row-edit.svg b/extensions/default/assets/images/row-edit.svg new file mode 100644 index 0000000000..5195a9628a --- /dev/null +++ b/extensions/default/assets/images/row-edit.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/extensions/default/assets/images/row-hidden.svg b/extensions/default/assets/images/row-hidden.svg new file mode 100644 index 0000000000..fdb63b0788 --- /dev/null +++ b/extensions/default/assets/images/row-hidden.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/extensions/default/assets/images/row-lock.svg b/extensions/default/assets/images/row-lock.svg new file mode 100644 index 0000000000..2cc3780e79 --- /dev/null +++ b/extensions/default/assets/images/row-lock.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/extensions/default/assets/images/row-shown.svg b/extensions/default/assets/images/row-shown.svg new file mode 100644 index 0000000000..de7cef9d62 --- /dev/null +++ b/extensions/default/assets/images/row-shown.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/extensions/default/assets/images/row-unlock.svg b/extensions/default/assets/images/row-unlock.svg new file mode 100644 index 0000000000..ed05e36747 --- /dev/null +++ b/extensions/default/assets/images/row-unlock.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/extensions/default/assets/images/settings.svg b/extensions/default/assets/images/settings.svg new file mode 100644 index 0000000000..a59f13eeb4 --- /dev/null +++ b/extensions/default/assets/images/settings.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/default/assets/images/side-panel-close-left.svg b/extensions/default/assets/images/side-panel-close-left.svg new file mode 100644 index 0000000000..ef901e0a83 --- /dev/null +++ b/extensions/default/assets/images/side-panel-close-left.svg @@ -0,0 +1,14 @@ + + + icon-panel-close-left + + + + + + + + + + + diff --git a/extensions/default/assets/images/side-panel-close-right.svg b/extensions/default/assets/images/side-panel-close-right.svg new file mode 100644 index 0000000000..d455e2abc2 --- /dev/null +++ b/extensions/default/assets/images/side-panel-close-right.svg @@ -0,0 +1,14 @@ + + + icon-panel-close-right + + + + + + + + + + + diff --git a/extensions/default/assets/images/sorting-active-down.svg b/extensions/default/assets/images/sorting-active-down.svg new file mode 100644 index 0000000000..78ed531021 --- /dev/null +++ b/extensions/default/assets/images/sorting-active-down.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/default/assets/images/sorting-active-up.svg b/extensions/default/assets/images/sorting-active-up.svg new file mode 100644 index 0000000000..f322f393b5 --- /dev/null +++ b/extensions/default/assets/images/sorting-active-up.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/default/assets/images/sorting.svg b/extensions/default/assets/images/sorting.svg new file mode 100644 index 0000000000..cdd422f34a --- /dev/null +++ b/extensions/default/assets/images/sorting.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/default/assets/images/status-alert-warning.svg b/extensions/default/assets/images/status-alert-warning.svg new file mode 100644 index 0000000000..6339753510 --- /dev/null +++ b/extensions/default/assets/images/status-alert-warning.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/extensions/default/assets/images/status-alert.svg b/extensions/default/assets/images/status-alert.svg new file mode 100644 index 0000000000..3a88223e96 --- /dev/null +++ b/extensions/default/assets/images/status-alert.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/extensions/default/assets/images/status-locked.svg b/extensions/default/assets/images/status-locked.svg new file mode 100644 index 0000000000..344ffe329e --- /dev/null +++ b/extensions/default/assets/images/status-locked.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/extensions/default/assets/images/status-tracked.svg b/extensions/default/assets/images/status-tracked.svg new file mode 100644 index 0000000000..549063a496 --- /dev/null +++ b/extensions/default/assets/images/status-tracked.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/extensions/default/assets/images/status-untracked.svg b/extensions/default/assets/images/status-untracked.svg new file mode 100644 index 0000000000..a4186231a1 --- /dev/null +++ b/extensions/default/assets/images/status-untracked.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/default/assets/images/tab-4d.svg b/extensions/default/assets/images/tab-4d.svg new file mode 100644 index 0000000000..e8eb101c21 --- /dev/null +++ b/extensions/default/assets/images/tab-4d.svg @@ -0,0 +1,13 @@ + + + tab-4d + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tab-linear.svg b/extensions/default/assets/images/tab-linear.svg new file mode 100644 index 0000000000..b03c552963 --- /dev/null +++ b/extensions/default/assets/images/tab-linear.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/extensions/default/assets/images/tab-patient-info.svg b/extensions/default/assets/images/tab-patient-info.svg new file mode 100644 index 0000000000..f74a7d079e --- /dev/null +++ b/extensions/default/assets/images/tab-patient-info.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/extensions/default/assets/images/tab-roi-threshold.svg b/extensions/default/assets/images/tab-roi-threshold.svg new file mode 100644 index 0000000000..2680ceab54 --- /dev/null +++ b/extensions/default/assets/images/tab-roi-threshold.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/extensions/default/assets/images/tab-segmentation.svg b/extensions/default/assets/images/tab-segmentation.svg new file mode 100644 index 0000000000..0a7a3377a2 --- /dev/null +++ b/extensions/default/assets/images/tab-segmentation.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/extensions/default/assets/images/tab-studies.svg b/extensions/default/assets/images/tab-studies.svg new file mode 100644 index 0000000000..7e3e1ce3e3 --- /dev/null +++ b/extensions/default/assets/images/tab-studies.svg @@ -0,0 +1,13 @@ + + + tab-studies + + + + + + + + + + diff --git a/extensions/default/assets/images/tool-3d-rotate.svg b/extensions/default/assets/images/tool-3d-rotate.svg new file mode 100644 index 0000000000..20d190cad1 --- /dev/null +++ b/extensions/default/assets/images/tool-3d-rotate.svg @@ -0,0 +1,20 @@ + + + tool-3d-rotate + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-angle.svg b/extensions/default/assets/images/tool-angle.svg new file mode 100644 index 0000000000..064a1502f8 --- /dev/null +++ b/extensions/default/assets/images/tool-angle.svg @@ -0,0 +1,12 @@ + + + tool-angle + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-annotate.svg b/extensions/default/assets/images/tool-annotate.svg new file mode 100644 index 0000000000..b10a8ad529 --- /dev/null +++ b/extensions/default/assets/images/tool-annotate.svg @@ -0,0 +1,11 @@ + + + tool-annotate + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-bidirectional.svg b/extensions/default/assets/images/tool-bidirectional.svg new file mode 100644 index 0000000000..4f77aa51b8 --- /dev/null +++ b/extensions/default/assets/images/tool-bidirectional.svg @@ -0,0 +1,21 @@ + + + tool-bidirectional + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-calibrate.svg b/extensions/default/assets/images/tool-calibrate.svg new file mode 100644 index 0000000000..7fd8966db6 --- /dev/null +++ b/extensions/default/assets/images/tool-calibrate.svg @@ -0,0 +1,19 @@ + + + tool-calibrate + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-capture.svg b/extensions/default/assets/images/tool-capture.svg new file mode 100644 index 0000000000..391cb892e3 --- /dev/null +++ b/extensions/default/assets/images/tool-capture.svg @@ -0,0 +1,10 @@ + + + tool- + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-cine.svg b/extensions/default/assets/images/tool-cine.svg new file mode 100644 index 0000000000..e3da518d30 --- /dev/null +++ b/extensions/default/assets/images/tool-cine.svg @@ -0,0 +1,9 @@ + + + tool-cine + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-circle.svg b/extensions/default/assets/images/tool-circle.svg new file mode 100644 index 0000000000..011ec55073 --- /dev/null +++ b/extensions/default/assets/images/tool-circle.svg @@ -0,0 +1,8 @@ + + + tool-circle + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-cobb-angle.svg b/extensions/default/assets/images/tool-cobb-angle.svg new file mode 100644 index 0000000000..debb0397b2 --- /dev/null +++ b/extensions/default/assets/images/tool-cobb-angle.svg @@ -0,0 +1,14 @@ + + + tool-cobb-angle + + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-create-threshold.svg b/extensions/default/assets/images/tool-create-threshold.svg new file mode 100644 index 0000000000..2385f80739 --- /dev/null +++ b/extensions/default/assets/images/tool-create-threshold.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/extensions/default/assets/images/tool-crosshair.svg b/extensions/default/assets/images/tool-crosshair.svg new file mode 100644 index 0000000000..ebbd617f25 --- /dev/null +++ b/extensions/default/assets/images/tool-crosshair.svg @@ -0,0 +1,14 @@ + + + tool-crosshair + + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-dicom-tag-browser.svg b/extensions/default/assets/images/tool-dicom-tag-browser.svg new file mode 100644 index 0000000000..f87608015b --- /dev/null +++ b/extensions/default/assets/images/tool-dicom-tag-browser.svg @@ -0,0 +1,15 @@ + + + tool-dicom-tag-browser + + + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-flip-horizontal.svg b/extensions/default/assets/images/tool-flip-horizontal.svg new file mode 100644 index 0000000000..f3ab15fe54 --- /dev/null +++ b/extensions/default/assets/images/tool-flip-horizontal.svg @@ -0,0 +1,10 @@ + + + tool-flip-horizontal + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-freehand-polygon.svg b/extensions/default/assets/images/tool-freehand-polygon.svg new file mode 100644 index 0000000000..bfc1b0dcd5 --- /dev/null +++ b/extensions/default/assets/images/tool-freehand-polygon.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/extensions/default/assets/images/tool-freehand-roi.svg b/extensions/default/assets/images/tool-freehand-roi.svg new file mode 100644 index 0000000000..42160326ed --- /dev/null +++ b/extensions/default/assets/images/tool-freehand-roi.svg @@ -0,0 +1,12 @@ + + + tool-freehand-roi + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-freehand.svg b/extensions/default/assets/images/tool-freehand.svg new file mode 100644 index 0000000000..2159f91505 --- /dev/null +++ b/extensions/default/assets/images/tool-freehand.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/extensions/default/assets/images/tool-fusion-color.svg b/extensions/default/assets/images/tool-fusion-color.svg new file mode 100644 index 0000000000..a09783d8c1 --- /dev/null +++ b/extensions/default/assets/images/tool-fusion-color.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/extensions/default/assets/images/tool-invert.svg b/extensions/default/assets/images/tool-invert.svg new file mode 100644 index 0000000000..9b5047ca29 --- /dev/null +++ b/extensions/default/assets/images/tool-invert.svg @@ -0,0 +1,10 @@ + + + tool-invert + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-layout-default.svg b/extensions/default/assets/images/tool-layout-default.svg new file mode 100644 index 0000000000..2ebbcabc6f --- /dev/null +++ b/extensions/default/assets/images/tool-layout-default.svg @@ -0,0 +1,22 @@ + + + tool-layout + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-length.svg b/extensions/default/assets/images/tool-length.svg new file mode 100644 index 0000000000..5ede3069da --- /dev/null +++ b/extensions/default/assets/images/tool-length.svg @@ -0,0 +1,16 @@ + + + tool-length + + + + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-magnetic-roi.svg b/extensions/default/assets/images/tool-magnetic-roi.svg new file mode 100644 index 0000000000..fbcb25bce2 --- /dev/null +++ b/extensions/default/assets/images/tool-magnetic-roi.svg @@ -0,0 +1,17 @@ + + + tool-livewire + + + + + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-magnify.svg b/extensions/default/assets/images/tool-magnify.svg new file mode 100644 index 0000000000..cb3ad1e612 --- /dev/null +++ b/extensions/default/assets/images/tool-magnify.svg @@ -0,0 +1,7 @@ + + + tool-magnify-area + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-measure-elipse.svg b/extensions/default/assets/images/tool-measure-elipse.svg new file mode 100644 index 0000000000..5198db687a --- /dev/null +++ b/extensions/default/assets/images/tool-measure-elipse.svg @@ -0,0 +1,12 @@ + + + tool-measure-elipse + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-more-menu.svg b/extensions/default/assets/images/tool-more-menu.svg new file mode 100644 index 0000000000..4ae8ca6944 --- /dev/null +++ b/extensions/default/assets/images/tool-more-menu.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/default/assets/images/tool-move.svg b/extensions/default/assets/images/tool-move.svg new file mode 100644 index 0000000000..411e95194e --- /dev/null +++ b/extensions/default/assets/images/tool-move.svg @@ -0,0 +1,13 @@ + + + tool-move + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-polygon.svg b/extensions/default/assets/images/tool-polygon.svg new file mode 100644 index 0000000000..ff2f9e0299 --- /dev/null +++ b/extensions/default/assets/images/tool-polygon.svg @@ -0,0 +1,3 @@ + + + diff --git a/extensions/default/assets/images/tool-quick-magnify.svg b/extensions/default/assets/images/tool-quick-magnify.svg new file mode 100644 index 0000000000..7a4766a7e7 --- /dev/null +++ b/extensions/default/assets/images/tool-quick-magnify.svg @@ -0,0 +1,11 @@ + + + tool-zoom-in + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-rectangle.svg b/extensions/default/assets/images/tool-rectangle.svg new file mode 100644 index 0000000000..d534c8ad5c --- /dev/null +++ b/extensions/default/assets/images/tool-rectangle.svg @@ -0,0 +1,12 @@ + + + tool-rectangle + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-reference-lines.svg b/extensions/default/assets/images/tool-reference-lines.svg new file mode 100644 index 0000000000..6329d81cbc --- /dev/null +++ b/extensions/default/assets/images/tool-reference-lines.svg @@ -0,0 +1,13 @@ + + + tool-reference-lines + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-reset.svg b/extensions/default/assets/images/tool-reset.svg new file mode 100644 index 0000000000..5c6d49fe4c --- /dev/null +++ b/extensions/default/assets/images/tool-reset.svg @@ -0,0 +1,9 @@ + + + tool-reset + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-rotate-right.svg b/extensions/default/assets/images/tool-rotate-right.svg new file mode 100644 index 0000000000..7ee9942197 --- /dev/null +++ b/extensions/default/assets/images/tool-rotate-right.svg @@ -0,0 +1,12 @@ + + + tool-rotate-right + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-seg-brush.svg b/extensions/default/assets/images/tool-seg-brush.svg new file mode 100644 index 0000000000..2258260d96 --- /dev/null +++ b/extensions/default/assets/images/tool-seg-brush.svg @@ -0,0 +1,9 @@ + + + tool-seg-brush + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-seg-eraser.svg b/extensions/default/assets/images/tool-seg-eraser.svg new file mode 100644 index 0000000000..a1f78fed4e --- /dev/null +++ b/extensions/default/assets/images/tool-seg-eraser.svg @@ -0,0 +1,10 @@ + + + tool-seg-eraser + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-seg-shape.svg b/extensions/default/assets/images/tool-seg-shape.svg new file mode 100644 index 0000000000..290d156e6c --- /dev/null +++ b/extensions/default/assets/images/tool-seg-shape.svg @@ -0,0 +1,9 @@ + + + tool-seg-shape + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-seg-threshold.svg b/extensions/default/assets/images/tool-seg-threshold.svg new file mode 100644 index 0000000000..4870fa5a49 --- /dev/null +++ b/extensions/default/assets/images/tool-seg-threshold.svg @@ -0,0 +1,17 @@ + + + tool-seg-threshold + + + + + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-spline-roi.svg b/extensions/default/assets/images/tool-spline-roi.svg new file mode 100644 index 0000000000..9266c536c3 --- /dev/null +++ b/extensions/default/assets/images/tool-spline-roi.svg @@ -0,0 +1,14 @@ + + + tool-spline-roi + + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-stack-image-sync.svg b/extensions/default/assets/images/tool-stack-image-sync.svg new file mode 100644 index 0000000000..d09d4861b8 --- /dev/null +++ b/extensions/default/assets/images/tool-stack-image-sync.svg @@ -0,0 +1,10 @@ + + + tool-stack-image-sync + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-stack-scroll.svg b/extensions/default/assets/images/tool-stack-scroll.svg new file mode 100644 index 0000000000..795da7701d --- /dev/null +++ b/extensions/default/assets/images/tool-stack-scroll.svg @@ -0,0 +1,10 @@ + + + tool-stack-scroll + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-toggle-dicom-overlay.svg b/extensions/default/assets/images/tool-toggle-dicom-overlay.svg new file mode 100644 index 0000000000..6cd55e57a4 --- /dev/null +++ b/extensions/default/assets/images/tool-toggle-dicom-overlay.svg @@ -0,0 +1,9 @@ + + + tool-toggle-dicom-overlay + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-ultrasound-bidirectional.svg b/extensions/default/assets/images/tool-ultrasound-bidirectional.svg new file mode 100644 index 0000000000..8ec735b1aa --- /dev/null +++ b/extensions/default/assets/images/tool-ultrasound-bidirectional.svg @@ -0,0 +1,15 @@ + + + tool-ultrasound-bidirectional + + + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-window-level.svg b/extensions/default/assets/images/tool-window-level.svg new file mode 100644 index 0000000000..fd63f1b6ea --- /dev/null +++ b/extensions/default/assets/images/tool-window-level.svg @@ -0,0 +1,9 @@ + + + tool-window-level + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-window-region.svg b/extensions/default/assets/images/tool-window-region.svg new file mode 100644 index 0000000000..29230e82cc --- /dev/null +++ b/extensions/default/assets/images/tool-window-region.svg @@ -0,0 +1,12 @@ + + + tool-window-region + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tool-zoom.svg b/extensions/default/assets/images/tool-zoom.svg new file mode 100644 index 0000000000..c6fbfebc60 --- /dev/null +++ b/extensions/default/assets/images/tool-zoom.svg @@ -0,0 +1,9 @@ + + + tool-zoom + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/tracked.svg b/extensions/default/assets/images/tracked.svg new file mode 100644 index 0000000000..a45ac3e51c --- /dev/null +++ b/extensions/default/assets/images/tracked.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/default/assets/images/ui-arrow-down.svg b/extensions/default/assets/images/ui-arrow-down.svg new file mode 100644 index 0000000000..de013233ef --- /dev/null +++ b/extensions/default/assets/images/ui-arrow-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/extensions/default/assets/images/ui-arrow-left.svg b/extensions/default/assets/images/ui-arrow-left.svg new file mode 100644 index 0000000000..43bd4ace4f --- /dev/null +++ b/extensions/default/assets/images/ui-arrow-left.svg @@ -0,0 +1,3 @@ + + + diff --git a/extensions/default/assets/images/ui-arrow-right.svg b/extensions/default/assets/images/ui-arrow-right.svg new file mode 100644 index 0000000000..756a9e2cd7 --- /dev/null +++ b/extensions/default/assets/images/ui-arrow-right.svg @@ -0,0 +1,3 @@ + + + diff --git a/extensions/default/assets/images/ui-arrow-up.svg b/extensions/default/assets/images/ui-arrow-up.svg new file mode 100644 index 0000000000..9a6aa6014d --- /dev/null +++ b/extensions/default/assets/images/ui-arrow-up.svg @@ -0,0 +1,3 @@ + + + diff --git a/extensions/default/assets/images/unlink.svg b/extensions/default/assets/images/unlink.svg new file mode 100644 index 0000000000..ed9526b7f4 --- /dev/null +++ b/extensions/default/assets/images/unlink.svg @@ -0,0 +1,9 @@ + + Unlink + + diff --git a/extensions/default/assets/images/viewport-status-tracked.svg b/extensions/default/assets/images/viewport-status-tracked.svg new file mode 100644 index 0000000000..68185761a8 --- /dev/null +++ b/extensions/default/assets/images/viewport-status-tracked.svg @@ -0,0 +1,13 @@ + + + viewport-status-tracfked + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/assets/images/viewport-window-level.svg b/extensions/default/assets/images/viewport-window-level.svg new file mode 100644 index 0000000000..ce0a562b2f --- /dev/null +++ b/extensions/default/assets/images/viewport-window-level.svg @@ -0,0 +1,17 @@ + + + viewport-window-level + + + + + + + + + + + + + + \ No newline at end of file diff --git a/extensions/default/package.json b/extensions/default/package.json index 94a359845d..5e9a94fe70 100644 --- a/extensions/default/package.json +++ b/extensions/default/package.json @@ -1,6 +1,6 @@ { "name": "@ohif/extension-default", - "version": "3.8.0-beta.82", + "version": "3.9.0-beta.71", "description": "Common/default features and functionality for basic image viewing", "author": "OHIF Core Team", "license": "MIT", @@ -32,16 +32,16 @@ "start": "yarn run dev" }, "peerDependencies": { - "@ohif/core": "3.8.0-beta.82", - "@ohif/i18n": "3.8.0-beta.82", - "dcmjs": "^0.29.12", + "@ohif/core": "3.9.0-beta.71", + "@ohif/i18n": "3.9.0-beta.71", + "dcmjs": "*", "dicomweb-client": "^0.10.4", "prop-types": "^15.6.2", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "react": "^18.3.1", + "react-dom": "^18.3.1", "react-i18next": "^12.2.2", "react-window": "^1.8.9", - "webpack": "^5.50.0", + "webpack": "5.89.0", "webpack-merge": "^5.7.3" }, "dependencies": { diff --git a/extensions/default/src/Actions/createReportAsync.tsx b/extensions/default/src/Actions/createReportAsync.tsx index d0f34a48a2..360894437f 100644 --- a/extensions/default/src/Actions/createReportAsync.tsx +++ b/extensions/default/src/Actions/createReportAsync.tsx @@ -5,7 +5,11 @@ import { DicomMetadataStore } from '@ohif/core'; * * @param {*} servicesManager */ -async function createReportAsync({ servicesManager, getReport, reportType = 'measurement' }) { +async function createReportAsync({ + servicesManager, + getReport, + reportType = 'measurement', +}: withAppTypes) { const { displaySetService, uiNotificationService, uiDialogService } = servicesManager.services; const loadingDialogId = uiDialogService.create({ showOverlay: true, @@ -39,6 +43,7 @@ async function createReportAsync({ servicesManager, getReport, reportType = 'mea message: error.message || `Failed to store ${reportType}`, type: 'error', }); + throw new Error(`Failed to store ${reportType}. Error: ${error.message || 'Unknown error'}`); } finally { uiDialogService.dismiss({ id: loadingDialogId }); } diff --git a/extensions/default/src/Components/DataSourceConfigurationComponent.tsx b/extensions/default/src/Components/DataSourceConfigurationComponent.tsx index 97896a92c7..dd61dc5517 100644 --- a/extensions/default/src/Components/DataSourceConfigurationComponent.tsx +++ b/extensions/default/src/Components/DataSourceConfigurationComponent.tsx @@ -1,18 +1,13 @@ import React, { ReactElement, useCallback, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Icon, useModal } from '@ohif/ui'; -import { ExtensionManager, ServicesManager, Types } from '@ohif/core'; +import { Types } from '@ohif/core'; import DataSourceConfigurationModalComponent from './DataSourceConfigurationModalComponent'; -type DataSourceConfigurationComponentProps = { - servicesManager: ServicesManager; - extensionManager: ExtensionManager; -}; - function DataSourceConfigurationComponent({ servicesManager, extensionManager, -}: DataSourceConfigurationComponentProps): ReactElement { +}: withAppTypes): ReactElement { const { t } = useTranslation('DataSourceConfiguration'); const { show, hide } = useModal(); diff --git a/extensions/default/src/components/ProgressDropdownWithService/ProgressDropdownWithService.tsx b/extensions/default/src/Components/ProgressDropdownWithService.tsx similarity index 93% rename from extensions/default/src/components/ProgressDropdownWithService/ProgressDropdownWithService.tsx rename to extensions/default/src/Components/ProgressDropdownWithService.tsx index e3ed34f3fc..d8720b4cc4 100644 --- a/extensions/default/src/components/ProgressDropdownWithService/ProgressDropdownWithService.tsx +++ b/extensions/default/src/Components/ProgressDropdownWithService.tsx @@ -1,5 +1,4 @@ import React, { useEffect, useState, useCallback, ReactElement } from 'react'; -import { ServicesManager } from '@ohif/core'; import { ProgressDropdown } from '@ohif/ui'; const workflowStepsToDropdownOptions = (steps = []) => @@ -11,11 +10,7 @@ const workflowStepsToDropdownOptions = (steps = []) => completed: false, })); -function ProgressDropdownWithService({ - servicesManager, -}: { - servicesManager: ServicesManager; -}): ReactElement { +export function ProgressDropdownWithService({ servicesManager }: withAppTypes): ReactElement { const { workflowStepsService } = servicesManager.services; const [activeStepId, setActiveStepId] = useState(workflowStepsService.activeWorkflowStep?.id); @@ -105,5 +100,3 @@ function ProgressDropdownWithService({ /> ); } - -export default ProgressDropdownWithService; diff --git a/extensions/default/src/Components/SidePanelWithServices.tsx b/extensions/default/src/Components/SidePanelWithServices.tsx index 5ca05df4e0..48fb98652f 100644 --- a/extensions/default/src/Components/SidePanelWithServices.tsx +++ b/extensions/default/src/Components/SidePanelWithServices.tsx @@ -1,9 +1,9 @@ import React, { useEffect, useState, useCallback } from 'react'; import { SidePanel } from '@ohif/ui'; -import { PanelService, ServicesManager, Types } from '@ohif/core'; +import { Types } from '@ohif/core'; export type SidePanelWithServicesProps = { - servicesManager: ServicesManager; + servicesManager: AppTypes.ServicesManager; side: 'left' | 'right'; className: string; activeTabIndex: number; @@ -19,7 +19,7 @@ const SidePanelWithServices = ({ expandedWidth, ...props }: SidePanelWithServicesProps) => { - const panelService: PanelService = servicesManager?.services?.panelService; + const panelService = servicesManager?.services?.panelService; // Tracks whether this SidePanel has been opened at least once since this SidePanel was inserted into the DOM. // Thus going to the Study List page and back to the viewer resets this flag for a SidePanel. diff --git a/extensions/default/src/CustomizableContextMenu/ContextMenuController.tsx b/extensions/default/src/CustomizableContextMenu/ContextMenuController.tsx index 2e0a73819a..2e7af439c4 100644 --- a/extensions/default/src/CustomizableContextMenu/ContextMenuController.tsx +++ b/extensions/default/src/CustomizableContextMenu/ContextMenuController.tsx @@ -1,6 +1,6 @@ import * as ContextMenuItemsBuilder from './ContextMenuItemsBuilder'; import ContextMenu from '../../../../platform/ui/src/components/ContextMenu/ContextMenu'; -import { CommandsManager, ServicesManager, Types } from '@ohif/core'; +import { CommandsManager } from '@ohif/core'; import { annotation as CsAnnotation } from '@cornerstonejs/tools'; import { Menu, MenuItem, Point, ContextMenuProps } from './types'; @@ -17,11 +17,11 @@ import { Menu, MenuItem, Point, ContextMenuProps } from './types'; */ export default class ContextMenuController { commandsManager: CommandsManager; - services: Types.Services; + services: AppTypes.Services; menuItems: Menu[] | MenuItem[]; - constructor(servicesManager: ServicesManager, commandsManager: CommandsManager) { - this.services = servicesManager.services as Obj; + constructor(servicesManager: AppTypes.ServicesManager, commandsManager: CommandsManager) { + this.services = servicesManager.services; this.commandsManager = commandsManager; } diff --git a/extensions/default/src/DataSourceConfigurationAPI/GoogleCloudDataSourceConfigurationAPI.ts b/extensions/default/src/DataSourceConfigurationAPI/GoogleCloudDataSourceConfigurationAPI.ts index 4e02cafae9..1be638df41 100644 --- a/extensions/default/src/DataSourceConfigurationAPI/GoogleCloudDataSourceConfigurationAPI.ts +++ b/extensions/default/src/DataSourceConfigurationAPI/GoogleCloudDataSourceConfigurationAPI.ts @@ -42,7 +42,7 @@ class GoogleCloudDataSourceConfigurationAPI implements Types.BaseDataSourceConfi private _fetchOptions: { method: string; headers: unknown }; private _dataSourceName: string; - constructor(dataSourceName, servicesManager, extensionManager) { + constructor(dataSourceName, servicesManager: AppTypes.ServicesManager, extensionManager) { this._dataSourceName = dataSourceName; this._extensionManager = extensionManager; const userAuthenticationService = servicesManager.services.userAuthenticationService; diff --git a/extensions/default/src/DicomJSONDataSource/index.js b/extensions/default/src/DicomJSONDataSource/index.js index deb50e2528..969144d066 100644 --- a/extensions/default/src/DicomJSONDataSource/index.js +++ b/extensions/default/src/DicomJSONDataSource/index.js @@ -59,8 +59,6 @@ const findStudies = (key, value) => { }; function createDicomJSONApi(dicomJsonConfig) { - const { wadoRoot } = dicomJsonConfig; - const implementation = { initialize: async ({ query, url }) => { if (!url) { @@ -89,7 +87,8 @@ function createDicomJSONApi(dicomJsonConfig) { SeriesInstanceUID = series.SeriesInstanceUID; series.instances.forEach(instance => { - const { url: imageId, metadata: naturalizedDicom } = instance; + const { metadata: naturalizedDicom } = instance; + const imageId = getImageId({ instance, config: dicomJsonConfig }); // Add imageId specific mapping to this data as the URL isn't necessarliy WADO-URI. metadataProvider.addImageIdToUIDs(imageId, { @@ -169,7 +168,7 @@ function createDicomJSONApi(dicomJsonConfig) { return getDirectURL(dicomJsonConfig, params); }, series: { - metadata: async ({ StudyInstanceUID, madeInClient = false, customSort } = {}) => { + metadata: async ({ filters, StudyInstanceUID, madeInClient = false, customSort } = {}) => { if (!StudyInstanceUID) { throw new Error('Unable to query for SeriesMetadata without StudyInstanceUID'); } @@ -183,6 +182,18 @@ function createDicomJSONApi(dicomJsonConfig) { series = study.series; } + const seriesKeys = [ + 'SeriesInstanceUID', + 'SeriesInstanceUIDs', + 'seriesInstanceUID', + 'seriesInstanceUIDs', + ]; + const seriesFilter = seriesKeys.find(key => filters[key]); + if (seriesFilter) { + const seriesUIDs = filters[seriesFilter]; + series = series.filter(s => seriesUIDs.includes(s.SeriesInstanceUID)); + } + const seriesSummaryMetadata = series.map(series => { const seriesSummary = { StudyInstanceUID: study.StudyInstanceUID, @@ -216,7 +227,7 @@ function createDicomJSONApi(dicomJsonConfig) { const obj = { ...modifiedMetadata, url: instance.url, - imageId: instance.url, + imageId: getImageId({ instance, config: dicomJsonConfig }), ...series, ...study, }; @@ -245,7 +256,15 @@ function createDicomJSONApi(dicomJsonConfig) { return imageIds; } - displaySet.images.forEach(instance => { + const { StudyInstanceUID, SeriesInstanceUID } = displaySet; + const study = findStudies('StudyInstanceUID', StudyInstanceUID)[0]; + const series = study.series.find(s => s.SeriesInstanceUID === SeriesInstanceUID); + let instances = displaySet.images; + if (series.instances.length > displaySet.images.length) { + instances = series.instances; + } + + instances.forEach(instance => { const NumberOfFrames = instance.NumberOfFrames; if (NumberOfFrames > 1) { diff --git a/extensions/default/src/DicomWebDataSource/index.js b/extensions/default/src/DicomWebDataSource/index.js index 23c5329c40..5e9a35bfb2 100644 --- a/extensions/default/src/DicomWebDataSource/index.js +++ b/extensions/default/src/DicomWebDataSource/index.js @@ -8,9 +8,9 @@ import { processResults, processSeriesResults, } from './qido.js'; -import dcm4cheeReject from './dcm4cheeReject'; +import dcm4cheeReject from './dcm4cheeReject.js'; -import getImageId from './utils/getImageId'; +import getImageId from './utils/getImageId.js'; import dcmjs from 'dcmjs'; import { retrieveStudyMetadata, deleteStudyMetadataPromise } from './retrieveStudyMetadata.js'; import StaticWadoClient from './utils/StaticWadoClient'; @@ -89,9 +89,9 @@ function createDicomWebApi(dicomWebConfig, servicesManager) { }; generateWadoHeader = () => { - let authorizationHeader = getAuthrorizationHeader(); + const authorizationHeader = getAuthrorizationHeader(); //Generate accept header depending on config params - let formattedAcceptHeader = utils.generateAcceptHeader( + const formattedAcceptHeader = utils.generateAcceptHeader( dicomWebConfig.acceptHeader, dicomWebConfig.requestTransferSyntaxUID, dicomWebConfig.omitQuotationForMultipartRequest @@ -393,10 +393,10 @@ function createDicomWebApi(dicomWebConfig, servicesManager) { // The value.Value will be set with the bulkdata read value // in which case it isn't necessary to re-read this. if (value && value.BulkDataURI && !value.Value) { + // handle the scenarios where bulkDataURI is relative path + fixBulkDataURI(value, naturalized, dicomWebConfig); // Provide a method to fetch bulkdata value.retrieveBulkData = (options = {}) => { - // handle the scenarios where bulkDataURI is relative path - fixBulkDataURI(value, naturalized, dicomWebConfig); const { mediaType } = options; const useOptions = { @@ -415,7 +415,6 @@ function createDicomWebApi(dicomWebConfig, servicesManager) { : undefined, ...options, }; - // Todo: this needs to be from wado dicom web client return qidoDicomWebClient.retrieveBulkData(useOptions).then(val => { // There are DICOM PDF cases where the first ArrayBuffer in the array is // the bulk data and DICOM video cases where the second ArrayBuffer is diff --git a/extensions/default/src/DicomWebDataSource/utils/fixBulkDataURI.ts b/extensions/default/src/DicomWebDataSource/utils/fixBulkDataURI.ts index 2e592c7570..49c622916c 100644 --- a/extensions/default/src/DicomWebDataSource/utils/fixBulkDataURI.ts +++ b/extensions/default/src/DicomWebDataSource/utils/fixBulkDataURI.ts @@ -20,30 +20,47 @@ function fixBulkDataURI(value, instance, dicomWebConfig) { // in case of the relative path, make it absolute. The current DICOM standard says // the bulkdataURI is relative to the series. However, there are situations where // it can be relative to the study too - if (!value.BulkDataURI.startsWith('http') && !value.BulkDataURI.startsWith('/')) { - if (dicomWebConfig.bulkDataURI?.relativeResolution === 'studies') { - value.BulkDataURI = `${dicomWebConfig.wadoRoot}/studies/${instance.StudyInstanceUID}/${value.BulkDataURI}`; + let { BulkDataURI } = value; + const { bulkDataURI: uriConfig = {} } = dicomWebConfig; + + // Handle incorrectly prefixed origins + const { startsWith, prefixWith = '' } = uriConfig; + if (startsWith && BulkDataURI.startsWith(startsWith)) { + BulkDataURI = prefixWith + BulkDataURI.substring(startsWith.length); + value.BulkDataURI = BulkDataURI; + } + + if (!BulkDataURI.startsWith('http') && !value.BulkDataURI.startsWith('/')) { + const { StudyInstanceUID, SeriesInstanceUID } = instance; + const isInstanceStart = BulkDataURI.startsWith('instances/') || BulkDataURI.startsWith('../'); + if ( + BulkDataURI.startsWith('series/') || + BulkDataURI.startsWith('bulkdata/') || + (uriConfig.relativeResolution === 'studies' && isInstanceStart) + ) { + value.BulkDataURI = `${dicomWebConfig.wadoRoot}/studies/${StudyInstanceUID}/${BulkDataURI}`; } else if ( - dicomWebConfig.bulkDataURI?.relativeResolution === 'series' || - !dicomWebConfig.bulkDataURI?.relativeResolution + isInstanceStart || + uriConfig.relativeResolution === 'series' || + !uriConfig.relativeResolution ) { - value.BulkDataURI = `${dicomWebConfig.wadoRoot}/studies/${instance.StudyInstanceUID}/series/${instance.SeriesInstanceUID}/${value.BulkDataURI}`; + value.BulkDataURI = `${dicomWebConfig.wadoRoot}/studies/${StudyInstanceUID}/series/${SeriesInstanceUID}/${BulkDataURI}`; } - return; } + // in case it is relative path but starts at the server (e.g., /bulk/1e, note the missing http // in the beginning and the first character is /) There are two scenarios, whether the wado root // is absolute or relative. In case of absolute, we need to prepend the wado root to the bulkdata // uri (e.g., bulkData: /bulk/1e, wado root: http://myserver.com/dicomweb, output: http://myserver.com/bulk/1e) // and in case of relative wado root, we need to prepend the bulkdata uri to the wado root (e.g,. bulkData: /bulk/1e // wado root: /dicomweb, output: /bulk/1e) - if (value.BulkDataURI[0] === '/') { + if (BulkDataURI[0] === '/') { if (dicomWebConfig.wadoRoot.startsWith('http')) { // Absolute wado root const url = new URL(dicomWebConfig.wadoRoot); - value.BulkDataURI = `${url.origin}${value.BulkDataURI}`; + value.BulkDataURI = `${url.origin}${BulkDataURI}`; } else { // Relative wado root, we don't need to do anything, bulkdata uri is already correct } diff --git a/extensions/default/src/DicomWebProxyDataSource/index.js b/extensions/default/src/DicomWebProxyDataSource/index.ts similarity index 97% rename from extensions/default/src/DicomWebProxyDataSource/index.js rename to extensions/default/src/DicomWebProxyDataSource/index.ts index 99007de3e0..8dad9cfb4b 100644 --- a/extensions/default/src/DicomWebProxyDataSource/index.js +++ b/extensions/default/src/DicomWebProxyDataSource/index.ts @@ -9,7 +9,7 @@ import { createDicomWebApi } from '../DicomWebDataSource/index'; * dicomWeb configuration array * */ -function createDicomWebProxyApi(dicomWebProxyConfig, servicesManager) { +function createDicomWebProxyApi(dicomWebProxyConfig, servicesManager: AppTypes.ServicesManager) { const { name } = dicomWebProxyConfig; let dicomWebDelegate = undefined; @@ -21,7 +21,7 @@ function createDicomWebProxyApi(dicomWebProxyConfig, servicesManager) { throw new Error(`No url for '${name}'`); } else { const response = await fetch(url); - let data = await response.json(); + const data = await response.json(); if (!data.servers?.dicomWeb?.[0]) { throw new Error('Invalid configuration returned by url'); } diff --git a/extensions/default/src/MergeDataSource/index.ts b/extensions/default/src/MergeDataSource/index.ts index 42e49c6941..607427b5c4 100644 --- a/extensions/default/src/MergeDataSource/index.ts +++ b/extensions/default/src/MergeDataSource/index.ts @@ -167,7 +167,7 @@ export const callByRetrieveAETitle = ({ function createMergeDataSourceApi( mergeConfig: MergeConfig, - servicesManager: unknown, + servicesManager: AppTypes.ServicesManager, extensionManager ) { const { seriesMerge } = mergeConfig; diff --git a/extensions/default/src/Panels/PanelMeasurementTable.tsx b/extensions/default/src/Panels/PanelMeasurementTable.tsx index 7cb491660c..3c49a48db4 100644 --- a/extensions/default/src/Panels/PanelMeasurementTable.tsx +++ b/extensions/default/src/Panels/PanelMeasurementTable.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useState } from 'react'; import PropTypes from 'prop-types'; import { useTranslation } from 'react-i18next'; -import { utils, ServicesManager } from '@ohif/core'; +import { utils } from '@ohif/core'; import { MeasurementTable, Dialog, @@ -24,14 +24,13 @@ export default function PanelMeasurementTable({ servicesManager, commandsManager, extensionManager, -}): React.FunctionComponent { +}: withAppTypes): React.FunctionComponent { const { t } = useTranslation('MeasurementTable'); const [viewportGrid, viewportGridService] = useViewportGrid(); const { activeViewportId, viewports } = viewportGrid; - const { measurementService, uiDialogService, uiNotificationService, displaySetService } = ( - servicesManager as ServicesManager - ).services; + const { measurementService, uiDialogService, uiNotificationService, displaySetService } = + servicesManager.services; const [displayMeasurements, setDisplayMeasurements] = useState([]); useEffect(() => { @@ -245,7 +244,7 @@ export default function PanelMeasurementTable({ } PanelMeasurementTable.propTypes = { - servicesManager: PropTypes.instanceOf(ServicesManager).isRequired, + servicesManager: PropTypes.object.isRequired, }; function _getMappedMeasurements(measurementService) { diff --git a/extensions/default/src/Panels/PanelStudyBrowser.tsx b/extensions/default/src/Panels/PanelStudyBrowser.tsx index e1b65d4019..bbb7c4b775 100644 --- a/extensions/default/src/Panels/PanelStudyBrowser.tsx +++ b/extensions/default/src/Panels/PanelStudyBrowser.tsx @@ -4,7 +4,7 @@ import { StudyBrowser, useImageViewer, useViewportGrid } from '@ohif/ui'; import { utils } from '@ohif/core'; import { useNavigate } from 'react-router-dom'; -const { sortStudyInstances, formatDate } = utils; +const { sortStudyInstances, formatDate, createStudyBrowserTabs } = utils; /** * @@ -16,7 +16,7 @@ function PanelStudyBrowser({ getStudiesForPatientByMRN, requestDisplaySetCreationForStudy, dataSource, -}) { +}: withAppTypes) { const { hangingProtocolService, displaySetService, uiNotificationService } = servicesManager.services; const navigate = useNavigate(); @@ -25,11 +25,13 @@ function PanelStudyBrowser({ // doesn't have to have such an intense shape. This works well enough for now. // Tabs --> Studies --> DisplaySets --> Thumbnails const { StudyInstanceUIDs } = useImageViewer(); - const [{ activeViewportId, viewports }, viewportGridService] = useViewportGrid(); + const [{ activeViewportId, viewports, isHangingProtocolLayout }, viewportGridService] = + useViewportGrid(); const [activeTabName, setActiveTabName] = useState('primary'); const [expandedStudyInstanceUIDs, setExpandedStudyInstanceUIDs] = useState([ ...StudyInstanceUIDs, ]); + const [hasLoadedViewports, setHasLoadedViewports] = useState(false); const [studyDisplayList, setStudyDisplayList] = useState([]); const [displaySets, setDisplaySets] = useState([]); const [thumbnailImageSrcMap, setThumbnailImageSrcMap] = useState({}); @@ -40,7 +42,8 @@ function PanelStudyBrowser({ try { updatedViewports = hangingProtocolService.getViewportsRequireUpdate( viewportId, - displaySetInstanceUID + displaySetInstanceUID, + isHangingProtocolLayout ); } catch (error) { console.warn(error); @@ -106,6 +109,18 @@ function PanelStudyBrowser({ // // ~~ Initial Thumbnails useEffect(() => { + if (!hasLoadedViewports) { + if (activeViewportId) { + // Once there is an active viewport id, it means the layout is ready + // so wait a bit of time to allow the viewports preferential loading + // which improves user experience of responsiveness significantly on slower + // systems. + window.setTimeout(() => setHasLoadedViewports(true), 250); + } + + return; + } + const currentDisplaySets = displaySetService.activeDisplaySets; currentDisplaySets.forEach(async dSet => { const newImageSrcEntry = {}; @@ -124,7 +139,14 @@ function PanelStudyBrowser({ return { ...prevState, ...newImageSrcEntry }; }); }); - }, [StudyInstanceUIDs, dataSource, displaySetService, getImageSrc]); + }, [ + StudyInstanceUIDs, + dataSource, + displaySetService, + getImageSrc, + hasLoadedViewports, + activeViewportId, + ]); // ~~ displaySets useEffect(() => { @@ -142,6 +164,9 @@ function PanelStudyBrowser({ const SubscriptionDisplaySetsAdded = displaySetService.subscribe( displaySetService.EVENTS.DISPLAY_SETS_ADDED, data => { + if (!hasLoadedViewports) { + return; + } const { displaySetsAdded, options } = data; displaySetsAdded.forEach(async dSet => { const newImageSrcEntry = {}; @@ -204,14 +229,14 @@ function PanelStudyBrowser({ }; }, [StudyInstanceUIDs, thumbnailImageSrcMap, displaySetService]); - const tabs = _createStudyBrowserTabs(StudyInstanceUIDs, studyDisplayList, displaySets); + const tabs = createStudyBrowserTabs(StudyInstanceUIDs, studyDisplayList, displaySets); // TODO: Should not fire this on "close" function _handleStudyClick(StudyInstanceUID) { const shouldCollapseStudy = expandedStudyInstanceUIDs.includes(StudyInstanceUID); const updatedExpandedStudyInstanceUIDs = shouldCollapseStudy ? // eslint-disable-next-line prettier/prettier - [...expandedStudyInstanceUIDs.filter(stdyUid => stdyUid !== StudyInstanceUID)] + [...expandedStudyInstanceUIDs.filter(stdyUid => stdyUid !== StudyInstanceUID)] : [...expandedStudyInstanceUIDs, StudyInstanceUID]; setExpandedStudyInstanceUIDs(updatedExpandedStudyInstanceUIDs); @@ -322,58 +347,3 @@ function _getComponentType(ds) { return 'thumbnail'; } - -/** - * - * @param {string[]} primaryStudyInstanceUIDs - * @param {object[]} studyDisplayList - * @param {string} studyDisplayList.studyInstanceUid - * @param {string} studyDisplayList.date - * @param {string} studyDisplayList.description - * @param {string} studyDisplayList.modalities - * @param {number} studyDisplayList.numInstances - * @param {object[]} displaySets - * @returns tabs - The prop object expected by the StudyBrowser component - */ -function _createStudyBrowserTabs(primaryStudyInstanceUIDs, studyDisplayList, displaySets) { - const primaryStudies = []; - const recentStudies = []; - const allStudies = []; - - studyDisplayList.forEach(study => { - const displaySetsForStudy = displaySets.filter( - ds => ds.StudyInstanceUID === study.studyInstanceUid - ); - const tabStudy = Object.assign({}, study, { - displaySets: displaySetsForStudy, - }); - - if (primaryStudyInstanceUIDs.includes(study.studyInstanceUid)) { - primaryStudies.push(tabStudy); - } else { - // TODO: Filter allStudies to dates within one year of current date - recentStudies.push(tabStudy); - allStudies.push(tabStudy); - } - }); - - const tabs = [ - { - name: 'primary', - label: 'Primary', - studies: primaryStudies, - }, - { - name: 'recent', - label: 'Recent', - studies: recentStudies, - }, - { - name: 'all', - label: 'All', - studies: allStudies, - }, - ]; - - return tabs; -} diff --git a/extensions/default/src/Toolbar/LegacyLayoutSelector.tsx b/extensions/default/src/Toolbar/LegacyLayoutSelector.tsx index 341f6686ec..e87b2e4de1 100644 --- a/extensions/default/src/Toolbar/LegacyLayoutSelector.tsx +++ b/extensions/default/src/Toolbar/LegacyLayoutSelector.tsx @@ -1,9 +1,14 @@ import React, { useEffect, useState, useCallback } from 'react'; import PropTypes from 'prop-types'; import { LayoutSelector as OHIFLayoutSelector, ToolbarButton } from '@ohif/ui'; -import { ServicesManager } from '@ohif/core'; -function LegacyLayoutSelectorWithServices({ servicesManager, ...props }) { +function LegacyLayoutSelectorWithServices({ + servicesManager, + rows = 3, + columns = 3, + onLayoutChange = () => {}, + ...props +}) { const { toolbarService } = servicesManager.services; const onSelection = useCallback( @@ -76,13 +81,7 @@ LayoutSelector.propTypes = { rows: PropTypes.number, columns: PropTypes.number, onLayoutChange: PropTypes.func, - servicesManager: PropTypes.instanceOf(ServicesManager), -}; - -LayoutSelector.defaultProps = { - rows: 3, - columns: 3, - onLayoutChange: () => {}, + servicesManager: PropTypes.object.isRequired, }; export default LegacyLayoutSelectorWithServices; diff --git a/extensions/default/src/Toolbar/ToolbarLayoutSelector.tsx b/extensions/default/src/Toolbar/ToolbarLayoutSelector.tsx index e39066d217..6a4f8fdba2 100644 --- a/extensions/default/src/Toolbar/ToolbarLayoutSelector.tsx +++ b/extensions/default/src/Toolbar/ToolbarLayoutSelector.tsx @@ -1,7 +1,6 @@ -import React, { useEffect, useState, useCallback } from 'react'; +import React, { useEffect, useState, useCallback, useRef } from 'react'; import PropTypes from 'prop-types'; import { LayoutSelector as OHIFLayoutSelector, ToolbarButton, LayoutPreset } from '@ohif/ui'; -import { ServicesManager } from '@ohif/core'; const defaultCommonPresets = [ { @@ -45,7 +44,7 @@ const _areSelectorsValid = (hp, displaySets, hangingProtocolService) => { ); }; -const generateAdvancedPresets = ({ servicesManager }) => { +const generateAdvancedPresets = ({ servicesManager }: withAppTypes) => { const { hangingProtocolService, viewportGridService, displaySetService } = servicesManager.services; @@ -58,6 +57,10 @@ const generateAdvancedPresets = ({ servicesManager }) => { } const displaySetInsaneUIDs = viewportGridService.getDisplaySetsUIDsForViewport(viewportId); + if (!displaySetInsaneUIDs) { + return []; + } + const displaySets = displaySetInsaneUIDs.map(uid => displaySetService.getDisplaySetByUID(uid)); return hangingProtocols @@ -80,7 +83,11 @@ const generateAdvancedPresets = ({ servicesManager }) => { .filter(preset => preset !== null); }; -function ToolbarLayoutSelectorWithServices({ commandsManager, servicesManager, ...props }) { +function ToolbarLayoutSelectorWithServices({ + commandsManager, + servicesManager, + ...props +}: withAppTypes) { const [isDisabled, setIsDisabled] = useState(false); const handleMouseEnter = () => { @@ -117,32 +124,41 @@ function ToolbarLayoutSelectorWithServices({ commandsManager, servicesManager, . } function LayoutSelector({ - rows, - columns, + rows = 3, + columns = 4, + onLayoutChange = () => {}, className, onSelection, onSelectionPreset, servicesManager, tooltipDisabled, ...rest -}) { +}: withAppTypes) { const [isOpen, setIsOpen] = useState(false); + const dropdownRef = useRef(null); const { customizationService } = servicesManager.services; const commonPresets = customizationService.get('commonPresets') || defaultCommonPresets; const advancedPresets = customizationService.get('advancedPresets') || generateAdvancedPresets({ servicesManager }); - const closeOnOutsideClick = () => { - if (isOpen) { + const closeOnOutsideClick = event => { + if (isOpen && dropdownRef.current) { setIsOpen(false); } }; useEffect(() => { - window.addEventListener('click', closeOnOutsideClick); + if (!isOpen) { + return; + } + + setTimeout(() => { + window.addEventListener('click', closeOnOutsideClick); + }, 0); return () => { window.removeEventListener('click', closeOnOutsideClick); + dropdownRef.current = null; }; }, [isOpen]); @@ -162,7 +178,10 @@ function LayoutSelector({ disableToolTip={tooltipDisabled} dropdownContent={ DropdownContent !== null && ( -
+
Common
@@ -221,13 +240,7 @@ LayoutSelector.propTypes = { rows: PropTypes.number, columns: PropTypes.number, onLayoutChange: PropTypes.func, - servicesManager: PropTypes.instanceOf(ServicesManager), -}; - -LayoutSelector.defaultProps = { - columns: 4, - rows: 3, - onLayoutChange: () => {}, + servicesManager: PropTypes.object.isRequired, }; export default ToolbarLayoutSelectorWithServices; diff --git a/extensions/default/src/Toolbar/ToolbarSplitButtonWithServices.tsx b/extensions/default/src/Toolbar/ToolbarSplitButtonWithServices.tsx index 5dfee4ad5e..ccd3870eaa 100644 --- a/extensions/default/src/Toolbar/ToolbarSplitButtonWithServices.tsx +++ b/extensions/default/src/Toolbar/ToolbarSplitButtonWithServices.tsx @@ -10,7 +10,7 @@ function ToolbarSplitButtonWithServices({ renderer, onInteraction, servicesManager, -}) { +}: withAppTypes) { const { toolbarService } = servicesManager?.services; /* Bubbles up individual item clicks */ @@ -27,7 +27,7 @@ function ToolbarSplitButtonWithServices({ }); }, })), - [] + [groupId, onInteraction] ); const PrimaryButtonComponent = @@ -54,7 +54,6 @@ function ToolbarSplitButtonWithServices({ } ToolbarSplitButtonWithServices.propTypes = { - isRadio: PropTypes.bool, groupId: PropTypes.string, primary: PropTypes.shape({ id: PropTypes.string.isRequired, @@ -87,9 +86,4 @@ ToolbarSplitButtonWithServices.propTypes = { }), }; -ToolbarSplitButtonWithServices.defaultProps = { - isRadio: false, - isAction: false, -}; - export default ToolbarSplitButtonWithServices; diff --git a/extensions/default/src/ViewerLayout/ToolbarButtonNestedMenu.tsx b/extensions/default/src/ViewerLayout/ToolbarButtonNestedMenu.tsx index 47e6a3a9b4..40ef8195da 100644 --- a/extensions/default/src/ViewerLayout/ToolbarButtonNestedMenu.tsx +++ b/extensions/default/src/ViewerLayout/ToolbarButtonNestedMenu.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react'; import PropTypes from 'prop-types'; import { ToolbarButton } from '@ohif/ui'; -function NestedMenu({ children, label, icon, isActive }) { +function NestedMenu({ children, label = 'More', icon = 'tool-more-menu', isActive }) { const [isOpen, setIsOpen] = useState(false); const toggleNestedMenu = () => setIsOpen(!isOpen); @@ -39,9 +39,4 @@ NestedMenu.propTypes = { label: PropTypes.string, }; -NestedMenu.defaultProps = { - icon: 'tool-more-menu', - label: 'More', -}; - export default NestedMenu; diff --git a/extensions/default/src/ViewerLayout/ViewerHeader.tsx b/extensions/default/src/ViewerLayout/ViewerHeader.tsx index 6dd130dd9e..851db7f14c 100644 --- a/extensions/default/src/ViewerLayout/ViewerHeader.tsx +++ b/extensions/default/src/ViewerLayout/ViewerHeader.tsx @@ -10,7 +10,12 @@ import { Toolbar } from '../Toolbar/Toolbar'; const { availableLanguages, defaultLanguage, currentLanguage } = i18n; -function ViewerHeader({ hotkeysManager, extensionManager, servicesManager, appConfig }) { +function ViewerHeader({ + hotkeysManager, + extensionManager, + servicesManager, + appConfig, +}: withAppTypes) { const navigate = useNavigate(); const location = useLocation(); diff --git a/extensions/default/src/ViewerLayout/index.tsx b/extensions/default/src/ViewerLayout/index.tsx index b47cca83b8..d39d6e1814 100644 --- a/extensions/default/src/ViewerLayout/index.tsx +++ b/extensions/default/src/ViewerLayout/index.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useState, useCallback } from 'react'; import PropTypes from 'prop-types'; import { ErrorBoundary, LoadingIndicatorProgress, InvestigationalUseDialog } from '@ohif/ui'; -import { ServicesManager, HangingProtocolService, CommandsManager } from '@ohif/core'; +import { HangingProtocolService, CommandsManager } from '@ohif/core'; import { useAppConfig } from '@state'; import ViewerHeader from './ViewerHeader'; import SidePanelWithServices from '../Components/SidePanelWithServices'; @@ -18,7 +18,7 @@ function ViewerLayout({ ViewportGridComp, leftPanelClosed = false, rightPanelClosed = false, -}): React.FunctionComponent { +}: withAppTypes): React.FunctionComponent { const [appConfig] = useAppConfig(); const { panelService, hangingProtocolService } = servicesManager.services; @@ -167,7 +167,7 @@ ViewerLayout.propTypes = { getModuleEntry: PropTypes.func.isRequired, }).isRequired, commandsManager: PropTypes.instanceOf(CommandsManager), - servicesManager: PropTypes.instanceOf(ServicesManager), + servicesManager: PropTypes.object.isRequired, // From modes leftPanels: PropTypes.array, rightPanels: PropTypes.array, diff --git a/extensions/default/src/commandsModule.ts b/extensions/default/src/commandsModule.ts index e302e860b7..1b0941ad9b 100644 --- a/extensions/default/src/commandsModule.ts +++ b/extensions/default/src/commandsModule.ts @@ -1,4 +1,4 @@ -import { ServicesManager, utils, Types } from '@ohif/core'; +import { utils, Types } from '@ohif/core'; import { ContextMenuController, defaultContextMenu } from './CustomizableContextMenu'; import DicomTagBrowser from './DicomTagBrowser/DicomTagBrowser'; @@ -12,7 +12,6 @@ import { NavigateHistory } from './types/commandModuleTypes'; import { history } from '@ohif/app'; const { subscribeToNextViewportGridChange } = utils; - export type HangingProtocolParams = { protocolId?: string; stageIndex?: number; @@ -38,7 +37,7 @@ const commandsModule = ({ viewportGridService, displaySetService, stateSyncService, - } = (servicesManager as ServicesManager).services; + } = servicesManager.services; // Define a context menu controller for use with any context menus const contextMenuController = new ContextMenuController(servicesManager, commandsManager); @@ -286,6 +285,7 @@ const commandsModule = ({ const findOrCreateViewport = layoutFindOrCreate.bind( null, hangingProtocolService, + isHangingProtocolLayout, stateReduce.viewportsByPosition ); @@ -303,7 +303,7 @@ const commandsModule = ({ toggleOneUp() { const viewportGridState = viewportGridService.getState(); - const { activeViewportId, viewports, layout } = viewportGridState; + const { activeViewportId, viewports, layout, isHangingProtocolLayout } = viewportGridState; const { displaySetInstanceUIDs, displaySetOptions, viewportOptions } = viewports.get(activeViewportId); @@ -330,7 +330,8 @@ const commandsModule = ({ .map(displaySetInstanceUID => hangingProtocolService.getViewportsRequireUpdate( viewportIdToUpdate, - displaySetInstanceUID + displaySetInstanceUID, + isHangingProtocolLayout ) ) .flat(); @@ -504,14 +505,10 @@ const commandsModule = ({ }: UpdateViewportDisplaySetParams) => { const nonImageModalities = ['SR', 'SEG', 'SM', 'RTSTRUCT', 'RTPLAN', 'RTDOSE']; - // Sort the display sets as per the hanging protocol service viewport/display set scoring system. - // The thumbnail list uses the same sorting. - const dsSortFn = hangingProtocolService.getDisplaySetSortFunction(); const currentDisplaySets = [...displaySetService.activeDisplaySets]; - currentDisplaySets.sort(dsSortFn); - - const { activeViewportId, viewports } = viewportGridService.getState(); + const { activeViewportId, viewports, isHangingProtocolLayout } = + viewportGridService.getState(); const { displaySetInstanceUIDs } = viewports.get(activeViewportId); @@ -545,7 +542,8 @@ const commandsModule = ({ try { updatedViewports = hangingProtocolService.getViewportsRequireUpdate( activeViewportId, - displaySetInstanceUID + displaySetInstanceUID, + isHangingProtocolLayout ); } catch (error) { console.warn(error); diff --git a/extensions/default/src/components/ProgressDropdownWithService/index.js b/extensions/default/src/components/ProgressDropdownWithService/index.js deleted file mode 100644 index c609cf0146..0000000000 --- a/extensions/default/src/components/ProgressDropdownWithService/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './ProgressDropdownWithService'; diff --git a/extensions/default/src/findViewportsByPosition.ts b/extensions/default/src/findViewportsByPosition.ts index c5fbafd35c..7d0d10f83e 100644 --- a/extensions/default/src/findViewportsByPosition.ts +++ b/extensions/default/src/findViewportsByPosition.ts @@ -16,6 +16,7 @@ import { StateSyncService } from '@ohif/core'; */ export const findOrCreateViewport = ( hangingProtocolService, + isHangingProtocolLayout, viewportsByPosition, position: number, positionId: string, @@ -31,8 +32,13 @@ export const findOrCreateViewport = ( if (!options.inDisplay) { options.inDisplay = [...viewportsByPosition.initialInDisplay]; } - // See if there is a default viewport for new views. - const missing = hangingProtocolService.getMissingViewport(protocolId, stageIndex, options); + + // See if there is a default viewport for new views + const missing = hangingProtocolService.getMissingViewport( + isHangingProtocolLayout ? protocolId : 'default', + stageIndex, + options + ); if (missing) { const displaySetInstanceUIDs = missing.displaySetsInfo.map(it => it.displaySetInstanceUID); options.inDisplay.push(...displaySetInstanceUIDs); diff --git a/extensions/default/src/getCustomizationModule.tsx b/extensions/default/src/getCustomizationModule.tsx index b2d4715949..75de9b03dd 100644 --- a/extensions/default/src/getCustomizationModule.tsx +++ b/extensions/default/src/getCustomizationModule.tsx @@ -1,9 +1,12 @@ import { CustomizationService } from '@ohif/core'; import React from 'react'; import DataSourceSelector from './Panels/DataSourceSelector'; -import ProgressDropdownWithService from './components/ProgressDropdownWithService'; +import { ProgressDropdownWithService } from './Components/ProgressDropdownWithService'; import DataSourceConfigurationComponent from './Components/DataSourceConfigurationComponent'; import { GoogleCloudDataSourceConfigurationAPI } from './DataSourceConfigurationAPI/GoogleCloudDataSourceConfigurationAPI'; +import { utils } from '@ohif/core'; + +const formatDate = utils.formatDate; /** * @@ -18,6 +21,7 @@ export default function getCustomizationModule({ servicesManager, extensionManag return [ { name: 'helloPage', + merge: 'Append', value: { id: 'customRoutes', routes: [ @@ -32,6 +36,7 @@ export default function getCustomizationModule({ servicesManager, extensionManag // Example customization to list a set of datasources { name: 'datasources', + merge: 'Append', value: { id: 'customRoutes', routes: [ @@ -160,6 +165,25 @@ export default function getCustomizationModule({ servicesManager, extensionManag id: 'progressDropdownWithServiceComponent', component: ProgressDropdownWithService, }, + { + id: 'studyBrowser.sortFunctions', + values: [ + { + label: 'Series Number', + sortFunction: (a, b) => { + return a?.SeriesNumber - b?.SeriesNumber; + }, + }, + { + label: 'Series Date', + sortFunction: (a, b) => { + const dateA = new Date(formatDate(a?.SeriesDate)); + const dateB = new Date(formatDate(b?.SeriesDate)); + return dateB.getTime() - dateA.getTime(); + }, + }, + ], + }, ], }, ]; diff --git a/extensions/default/src/getDataSourcesModule.js b/extensions/default/src/getDataSourcesModule.js index 8c918e0c6a..cc4aee56fc 100644 --- a/extensions/default/src/getDataSourcesModule.js +++ b/extensions/default/src/getDataSourcesModule.js @@ -5,7 +5,7 @@ import { createDicomWebApi } from './DicomWebDataSource/index.js'; import { createDicomJSONApi } from './DicomJSONDataSource/index.js'; import { createDicomLocalApi } from './DicomLocalDataSource/index.js'; -import { createDicomWebProxyApi } from './DicomWebProxyDataSource/index.js'; +import { createDicomWebProxyApi } from './DicomWebProxyDataSource/index'; import { createMergeDataSourceApi } from './MergeDataSource/index'; /** diff --git a/extensions/default/src/getHangingProtocolModule.js b/extensions/default/src/getHangingProtocolModule.js index f9ad9bbbb3..6673bbc4e9 100644 --- a/extensions/default/src/getHangingProtocolModule.js +++ b/extensions/default/src/getHangingProtocolModule.js @@ -1,5 +1,7 @@ -import hpMNGrid from './hpMNGrid'; -import hpMNCompare from './hpCompare'; +import hpMNGrid from './hangingprotocols/hpMNGrid'; +import hpMNCompare from './hangingprotocols/hpCompare'; +import hpMammography from './hangingprotocols/hpMammo'; +import hpScale from './hangingprotocols/hpScale'; const defaultProtocol = { id: 'default', @@ -14,7 +16,6 @@ const defaultProtocol = { editableBy: {}, protocolMatchingRules: [], toolGroupIds: ['default'], - hpInitiationCriteria: { minSeriesLoaded: 1 }, // -1 would be used to indicate active only, whereas other values are // the number of required priors referenced - so 0 means active with // 0 or more priors. @@ -41,6 +42,7 @@ const defaultProtocol = { // Try to match series with images by default, to prevent weird display // on SEG/SR containing studies { + weight: 10, attribute: 'numImageFrames', constraint: { greaterThan: { value: 0 }, @@ -105,16 +107,24 @@ function getHangingProtocolModule() { name: defaultProtocol.id, protocol: defaultProtocol, }, - // Create a MxN hanging protocol available by default - { - name: hpMNGrid.id, - protocol: hpMNGrid, - }, // Create a MxN comparison hanging protocol available by default { name: hpMNCompare.id, protocol: hpMNCompare, }, + { + name: hpMammography.id, + protocol: hpMammography, + }, + { + name: hpScale.id, + protocol: hpScale, + }, + // Create a MxN hanging protocol available by default + { + name: hpMNGrid.id, + protocol: hpMNGrid, + }, ]; } diff --git a/extensions/default/src/getPTImageIdInstanceMetadata.ts b/extensions/default/src/getPTImageIdInstanceMetadata.ts index bacad3dbfc..4a9e114e0a 100644 --- a/extensions/default/src/getPTImageIdInstanceMetadata.ts +++ b/extensions/default/src/getPTImageIdInstanceMetadata.ts @@ -17,14 +17,14 @@ export default function getPTImageIdInstanceMetadata(imageId: string): InstanceM dicomMetaData.CorrectedImage === undefined || dicomMetaData.Units === undefined || !dicomMetaData.RadiopharmaceuticalInformationSequence || - dicomMetaData.RadiopharmaceuticalInformationSequence[0].RadionuclideHalfLife === undefined || - dicomMetaData.RadiopharmaceuticalInformationSequence[0].RadionuclideTotalDose === undefined || + dicomMetaData.RadiopharmaceuticalInformationSequence.RadionuclideHalfLife === undefined || + dicomMetaData.RadiopharmaceuticalInformationSequence.RadionuclideTotalDose === undefined || dicomMetaData.DecayCorrection === undefined || dicomMetaData.AcquisitionDate === undefined || dicomMetaData.AcquisitionTime === undefined || - (dicomMetaData.RadiopharmaceuticalInformationSequence[0].RadiopharmaceuticalStartDateTime === + (dicomMetaData.RadiopharmaceuticalInformationSequence.RadiopharmaceuticalStartDateTime === undefined && - dicomMetaData.RadiopharmaceuticalInformationSequence[0].RadiopharmaceuticalStartTime === + dicomMetaData.RadiopharmaceuticalInformationSequence.RadiopharmaceuticalStartTime === undefined) ) { throw new Error('required metadata are missing'); @@ -37,14 +37,13 @@ export default function getPTImageIdInstanceMetadata(imageId: string): InstanceM const instanceMetadata: InstanceMetadata = { CorrectedImage: dicomMetaData.CorrectedImage, Units: dicomMetaData.Units, - RadionuclideHalfLife: - dicomMetaData.RadiopharmaceuticalInformationSequence[0].RadionuclideHalfLife, + RadionuclideHalfLife: dicomMetaData.RadiopharmaceuticalInformationSequence.RadionuclideHalfLife, RadionuclideTotalDose: - dicomMetaData.RadiopharmaceuticalInformationSequence[0].RadionuclideTotalDose, + dicomMetaData.RadiopharmaceuticalInformationSequence.RadionuclideTotalDose, RadiopharmaceuticalStartDateTime: - dicomMetaData.RadiopharmaceuticalInformationSequence[0].RadiopharmaceuticalStartDateTime, + dicomMetaData.RadiopharmaceuticalInformationSequence.RadiopharmaceuticalStartDateTime, RadiopharmaceuticalStartTime: - dicomMetaData.RadiopharmaceuticalInformationSequence[0].RadiopharmaceuticalStartTime, + dicomMetaData.RadiopharmaceuticalInformationSequence.RadiopharmaceuticalStartTime, DecayCorrection: dicomMetaData.DecayCorrection, PatientWeight: dicomMetaData.PatientWeight, SeriesDate: dicomMetaData.SeriesDate, diff --git a/extensions/default/src/getPanelModule.tsx b/extensions/default/src/getPanelModule.tsx index e294805dfb..138a8d193f 100644 --- a/extensions/default/src/getPanelModule.tsx +++ b/extensions/default/src/getPanelModule.tsx @@ -31,7 +31,7 @@ function getPanelModule({ commandsManager, extensionManager, servicesManager }) }), }, { - name: 'measure', + name: 'measurements', iconName: 'tab-linear', iconLabel: 'Measure', label: i18n.t('SidePanel:Measurements'), diff --git a/extensions/default/src/getSopClassHandlerModule.js b/extensions/default/src/getSopClassHandlerModule.js index bdbb7057dc..28a677ff7f 100644 --- a/extensions/default/src/getSopClassHandlerModule.js +++ b/extensions/default/src/getSopClassHandlerModule.js @@ -37,6 +37,8 @@ function getDisplaySetInfo(instances) { const { isDynamicVolume, timePoints } = dynamicVolumeInfo; let displaySetInfo; + const { appConfig } = appContext; + if (isDynamicVolume) { const timePoint = timePoints[0]; const instancesMap = new Map(); @@ -46,9 +48,9 @@ function getDisplaySetInfo(instances) { const firstTimePointInstances = timePoint.map(imageId => instancesMap.get(imageId)); - displaySetInfo = isDisplaySetReconstructable(firstTimePointInstances); + displaySetInfo = isDisplaySetReconstructable(firstTimePointInstances, appConfig); } else { - displaySetInfo = isDisplaySetReconstructable(instances); + displaySetInfo = isDisplaySetReconstructable(instances, appConfig); } return { diff --git a/extensions/default/src/getToolbarModule.tsx b/extensions/default/src/getToolbarModule.tsx index 762aea9f03..d84aad9f96 100644 --- a/extensions/default/src/getToolbarModule.tsx +++ b/extensions/default/src/getToolbarModule.tsx @@ -3,7 +3,7 @@ import ToolbarLayoutSelectorWithServices from './Toolbar/ToolbarLayoutSelector'; import ToolbarSplitButtonWithServices from './Toolbar/ToolbarSplitButtonWithServices'; import ToolbarButtonGroupWithServices from './Toolbar/ToolbarButtonGroupWithServices'; import { ToolbarButton } from '@ohif/ui'; -import ProgressDropdownWithService from './components/ProgressDropdownWithService'; +import { ProgressDropdownWithService } from './Components/ProgressDropdownWithService'; const getClassName = isToggled => { return { @@ -13,7 +13,7 @@ const getClassName = isToggled => { }; }; -export default function getToolbarModule({ commandsManager, servicesManager }) { +export default function getToolbarModule({ commandsManager, servicesManager }: withAppTypes) { const { cineService } = servicesManager.services; return [ { diff --git a/extensions/default/src/getViewportModule.tsx b/extensions/default/src/getViewportModule.tsx index 7ac8adb647..c3ca1efbb7 100644 --- a/extensions/default/src/getViewportModule.tsx +++ b/extensions/default/src/getViewportModule.tsx @@ -1,4 +1,4 @@ -import { ServicesManager, CommandsManager, ExtensionManager } from '@ohif/core'; +import { CommandsManager, ExtensionManager } from '@ohif/core'; import LineChartViewport from './Components/LineChartViewport/index'; const getViewportModule = ({ @@ -6,7 +6,7 @@ const getViewportModule = ({ commandsManager, extensionManager, }: { - servicesManager: ServicesManager; + servicesManager: AppTypes.ServicesManager; commandsManager: CommandsManager; extensionManager: ExtensionManager; }) => { diff --git a/extensions/default/src/hpCompare.ts b/extensions/default/src/hangingprotocols/hpCompare.ts similarity index 96% rename from extensions/default/src/hpCompare.ts rename to extensions/default/src/hangingprotocols/hpCompare.ts index 7bd934be11..87a4f5e027 100644 --- a/extensions/default/src/hpCompare.ts +++ b/extensions/default/src/hangingprotocols/hpCompare.ts @@ -120,9 +120,9 @@ const hpMNCompare: Types.HangingProtocol.Protocol = { { id: 'Two Studies', weight: 1000, + // is there a second study or in another work the attribute + // studyInstanceUIDsIndex that we get from prior should not be null attribute: 'StudyInstanceUID', - // The 'from' attribute says where to get the 'attribute' value from. In this case - // prior means the second study in the study list. from: 'prior', required: true, constraint: { diff --git a/extensions/default/src/hpMNGrid.ts b/extensions/default/src/hangingprotocols/hpMNGrid.ts similarity index 100% rename from extensions/default/src/hpMNGrid.ts rename to extensions/default/src/hangingprotocols/hpMNGrid.ts diff --git a/extensions/default/src/hangingprotocols/hpMammo.ts b/extensions/default/src/hangingprotocols/hpMammo.ts new file mode 100644 index 0000000000..8890b68432 --- /dev/null +++ b/extensions/default/src/hangingprotocols/hpMammo.ts @@ -0,0 +1,201 @@ +import { + RCC, + RMLO, + LCC, + LMLO, + RCCPrior, + LCCPrior, + RMLOPrior, + LMLOPrior, +} from './mammoDisplaySetSelector'; + +const rightDisplayArea = { + storeAsInitialCamera: true, + imageArea: [0.8, 0.8], + imageCanvasPoint: { + imagePoint: [0, 0.5], + canvasPoint: [0, 0.5], + }, +}; + +const leftDisplayArea = { + storeAsInitialCamera: true, + imageArea: [0.8, 0.8], + imageCanvasPoint: { + imagePoint: [1, 0.5], + canvasPoint: [1, 0.5], + }, +}; + +const hpMammography = { + id: '@ohif/hpMammo', + hasUpdatedPriorsInformation: false, + name: 'Mammography Breast Screening', + protocolMatchingRules: [ + { + id: 'Mammography', + weight: 150, + attribute: 'ModalitiesInStudy', + constraint: { + contains: 'MG', + }, + required: true, + }, + { + id: 'numberOfImages', + attribute: 'numberOfDisplaySetsWithImages', + constraint: { + greaterThan: 2, + }, + required: true, + }, + ], + toolGroupIds: ['default'], + displaySetSelectors: { + RCC, + LCC, + RMLO, + LMLO, + RCCPrior, + LCCPrior, + RMLOPrior, + LMLOPrior, + }, + + stages: [ + { + name: 'CC/MLO', + viewportStructure: { + type: 'grid', + layoutType: 'grid', + properties: { + rows: 2, + columns: 2, + }, + }, + viewports: [ + { + viewportOptions: { + toolGroupId: 'default', + displayArea: leftDisplayArea, + // flipHorizontal: true, + // rotation: 180, + allowUnmatchedView: true, + }, + displaySets: [ + { + id: 'RCC', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + // flipHorizontal: true, + displayArea: rightDisplayArea, + allowUnmatchedView: true, + }, + displaySets: [ + { + id: 'LCC', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + displayArea: leftDisplayArea, + // rotation: 180, + // flipHorizontal: true, + allowUnmatchedView: true, + }, + displaySets: [ + { + id: 'RMLO', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + displayArea: rightDisplayArea, + // flipHorizontal: true, + allowUnmatchedView: true, + }, + displaySets: [ + { + id: 'LMLO', + }, + ], + }, + ], + }, + + // Compare CC current/prior top/bottom + { + name: 'CC compare', + viewportStructure: { + type: 'grid', + layoutType: 'grid', + properties: { + rows: 2, + columns: 2, + }, + }, + viewports: [ + { + viewportOptions: { + toolGroupId: 'default', + displayArea: leftDisplayArea, + flipHorizontal: true, + rotation: 180, + }, + displaySets: [ + { + id: 'RCC', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + flipHorizontal: true, + displayArea: rightDisplayArea, + }, + displaySets: [ + { + id: 'LCC', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + displayArea: leftDisplayArea, + flipHorizontal: true, + }, + displaySets: [ + { + id: 'RCCPrior', + }, + ], + }, + { + viewportOptions: { + toolGroupId: 'default', + displayArea: rightDisplayArea, + }, + displaySets: [ + { + id: 'LCCPrior', + }, + ], + }, + ], + }, + ], + // Indicates it is prior aware, but will work with no priors + numberOfPriorsReferenced: 0, +}; + +export default hpMammography; diff --git a/extensions/default/src/hangingprotocols/hpScale.ts b/extensions/default/src/hangingprotocols/hpScale.ts new file mode 100644 index 0000000000..651413c24e --- /dev/null +++ b/extensions/default/src/hangingprotocols/hpScale.ts @@ -0,0 +1,132 @@ +import { Types } from '@ohif/core'; + +const displayAreaScale1: Types.HangingProtocol.DisplayArea = { + type: 'SCALE', + scale: 1, + storeAsInitialCamera: true, +}; +const displayAreaScale15: Types.HangingProtocol.DisplayArea = { ...displayAreaScale1, scale: 15 }; + +/** + * This hanging protocol can be activated on the primary mode by directly + * referencing it in a URL or by directly including it within a mode, e.g.: + * `&hangingProtocolId=@ohif/mnGrid` added to the viewer URL + * It is not included in the viewer mode by default. + */ +const hpScale: Types.HangingProtocol.Protocol = { + id: '@ohif/hpScale', + description: 'Has various hanging protocol grid layouts', + name: 'Scale Images', + protocolMatchingRules: [ + { + id: 'OneOrMoreSeries', + weight: 25, + attribute: 'numberOfDisplaySetsWithImages', + constraint: { + greaterThan: 0, + }, + }, + ], + toolGroupIds: ['default'], + displaySetSelectors: { + defaultDisplaySetId: { + seriesMatchingRules: [ + { + weight: 1, + attribute: 'numImageFrames', + constraint: { + greaterThan: { value: 0 }, + }, + required: true, + }, + // This display set will select the specified items by preference + // It has no affect if nothing is specified in the URL. + { + attribute: 'isDisplaySetFromUrl', + weight: 10, + constraint: { + equals: true, + }, + }, + ], + }, + }, + defaultViewport: { + viewportOptions: { + viewportType: 'stack', + toolGroupId: 'default', + displayArea: displayAreaScale1, + allowUnmatchedView: true, + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + matchedDisplaySetsIndex: -1, + }, + ], + }, + stages: [ + // A 1x1 stage - should be automatically activated if there is only 1 viewable instance + { + name: 'Scale 1:1', + stageActivation: { + enabled: { + minViewportsMatched: 1, + }, + }, + viewportStructure: { + layoutType: 'grid', + properties: { + rows: 1, + columns: 1, + }, + }, + viewports: [ + { + viewportOptions: { + toolGroupId: 'default', + allowUnmatchedView: true, + displayArea: displayAreaScale1, + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + ], + }, + { + name: 'Scale 1:15', + stageActivation: { + enabled: { + minViewportsMatched: 1, + }, + }, + viewportStructure: { + layoutType: 'grid', + properties: { + rows: 1, + columns: 1, + }, + }, + viewports: [ + { + viewportOptions: { + toolGroupId: 'default', + allowUnmatchedView: true, + displayArea: displayAreaScale15, + }, + displaySets: [ + { + id: 'defaultDisplaySetId', + }, + ], + }, + ], + }, + ], + numberOfPriorsReferenced: -1, +}; + +export default hpScale; diff --git a/extensions/default/src/hangingprotocols/index.ts b/extensions/default/src/hangingprotocols/index.ts new file mode 100644 index 0000000000..ab5b11f232 --- /dev/null +++ b/extensions/default/src/hangingprotocols/index.ts @@ -0,0 +1,15 @@ +import viewCodeAttribute from './viewCode'; +import lateralityAttribute from './laterality'; +import registerHangingProtocolAttributes from './registerHangingProtocolAttributes'; +import hpMammography from './hpMammo'; +import hpMNGrid from './hpMNGrid'; +import hpCompare from './hpCompare'; + +export { + viewCodeAttribute, + lateralityAttribute, + hpMammography as hpMammo, + hpMNGrid, + hpCompare, + registerHangingProtocolAttributes, +}; diff --git a/extensions/default/src/hangingprotocols/laterality.ts b/extensions/default/src/hangingprotocols/laterality.ts new file mode 100644 index 0000000000..59f8a4ebe1 --- /dev/null +++ b/extensions/default/src/hangingprotocols/laterality.ts @@ -0,0 +1,9 @@ +export default displaySet => { + const frameAnatomy = + displaySet?.images?.[0]?.SharedFunctionalGroupsSequence?.[0]?.FrameAnatomySequence?.[0]; + if (!frameAnatomy) { + return undefined; + } + const laterality = frameAnatomy?.FrameLaterality; + return laterality; +}; diff --git a/extensions/default/src/hangingprotocols/mammoDisplaySetSelector.ts b/extensions/default/src/hangingprotocols/mammoDisplaySetSelector.ts new file mode 100644 index 0000000000..720d5a1524 --- /dev/null +++ b/extensions/default/src/hangingprotocols/mammoDisplaySetSelector.ts @@ -0,0 +1,214 @@ +const priorStudyMatchingRules = [ + { + // The priorInstance is a study counter that indicates what position this study is in + // and the value comes from the options parameter. + attribute: 'studyInstanceUIDsIndex', + from: 'options', + required: true, + constraint: { + equals: { value: 1 }, + }, + }, +]; + +const currentStudyMatchingRules = [ + { + // The priorInstance is a study counter that indicates what position this study is in + // and the value comes from the options parameter. + attribute: 'studyInstanceUIDsIndex', + from: 'options', + required: true, + constraint: { + equals: { value: 0 }, + }, + }, +]; + +const LCCSeriesMatchingRules = [ + { + weight: 10, + attribute: 'ViewCode', + constraint: { + contains: 'SCT:399162004', + }, + }, + { + weight: 5, + attribute: 'PatientOrientation', + constraint: { + contains: 'L', + }, + }, + { + weight: 20, + attribute: 'SeriesDescription', + constraint: { + contains: 'L CC', + }, + }, +]; + +const RCCSeriesMatchingRules = [ + { + weight: 10, + attribute: 'ViewCode', + constraint: { + contains: 'SCT:399162004', + }, + }, + { + weight: 5, + attribute: 'PatientOrientation', + constraint: { + equals: ['P', 'L'], + }, + }, + { + attribute: 'PatientOrientation', + constraint: { + doesNotEqual: ['A', 'R'], + }, + required: true, + }, + { + weight: 20, + attribute: 'SeriesDescription', + constraint: { + contains: 'CC', + }, + }, +]; + +const LMLOSeriesMatchingRules = [ + { + weight: 10, + attribute: 'ViewCode', + constraint: { + contains: 'SCT:399368009', + }, + }, + { + weight: 0, + attribute: 'ViewCode', + constraint: { + doesNotEqual: 'SCT:399162004', + }, + required: true, + }, + { + weight: 5, + attribute: 'PatientOrientation', + constraint: { + equals: ['A', 'R'], + }, + }, + { + weight: 20, + attribute: 'SeriesDescription', + constraint: { + contains: 'L MLO', + }, + }, +]; + +const RMLOSeriesMatchingRules = [ + { + weight: 10, + attribute: 'ViewCode', + constraint: { + contains: 'SCT:399368009', + }, + }, + { + attribute: 'ViewCode', + constraint: { + doesNotEqual: 'SCT:399162004', + }, + required: true, + }, + { + attribute: 'PatientOrientation', + constraint: { + doesNotContain: ['P', 'FL'], + }, + required: true, + }, + { + weight: 5, + attribute: 'PatientOrientation', + constraint: { + equals: ['P', 'L'], + }, + }, + { + weight: 5, + attribute: 'PatientOrientation', + constraint: { + equals: ['A', 'FR'], + }, + }, + { + weight: 20, + attribute: 'SeriesDescription', + constraint: { + contains: 'R MLO', + }, + }, + { + attribute: 'SeriesDescription', + required: true, + constraint: { + doesNotContain: 'CC', + }, + }, + { + attribute: 'SeriesDescription', + required: true, + constraint: { + doesNotEqual: 'L MLO', + }, + required: true, + }, +]; + +const RCC = { + seriesMatchingRules: RCCSeriesMatchingRules, + studyMatchingRules: currentStudyMatchingRules, +}; + +const RCCPrior = { + seriesMatchingRules: RCCSeriesMatchingRules, + studyMatchingRules: priorStudyMatchingRules, +}; + +const LCC = { + seriesMatchingRules: LCCSeriesMatchingRules, + studyMatchingRules: currentStudyMatchingRules, +}; + +const LCCPrior = { + seriesMatchingRules: LCCSeriesMatchingRules, + studyMatchingRules: priorStudyMatchingRules, +}; + +const RMLO = { + seriesMatchingRules: RMLOSeriesMatchingRules, + studyMatchingRules: currentStudyMatchingRules, +}; + +const RMLOPrior = { + seriesMatchingRules: RMLOSeriesMatchingRules, + studyMatchingRules: priorStudyMatchingRules, +}; + +const LMLO = { + seriesMatchingRules: LMLOSeriesMatchingRules, + studyMatchingRules: currentStudyMatchingRules, +}; + +const LMLOPrior = { + seriesMatchingRules: LMLOSeriesMatchingRules, + studyMatchingRules: priorStudyMatchingRules, +}; + +export { RCC, LCC, RMLO, LMLO, RCCPrior, LCCPrior, RMLOPrior, LMLOPrior }; diff --git a/extensions/default/src/hangingprotocols/registerHangingProtocolAttributes.ts b/extensions/default/src/hangingprotocols/registerHangingProtocolAttributes.ts new file mode 100644 index 0000000000..6c598009c4 --- /dev/null +++ b/extensions/default/src/hangingprotocols/registerHangingProtocolAttributes.ts @@ -0,0 +1,8 @@ +import viewCode from './viewCode'; +import laterality from './laterality'; + +export default function registerHangingProtocolAttributes({ servicesManager }) { + const { hangingProtocolService } = servicesManager.services; + hangingProtocolService.addCustomAttribute('ViewCode', 'View Code Designator:Value', viewCode); + hangingProtocolService.addCustomAttribute('Laterality', 'Laterality of object', laterality); +} diff --git a/extensions/default/src/hangingprotocols/viewCode.ts b/extensions/default/src/hangingprotocols/viewCode.ts new file mode 100644 index 0000000000..0f2251e8e3 --- /dev/null +++ b/extensions/default/src/hangingprotocols/viewCode.ts @@ -0,0 +1,11 @@ +export default displaySet => { + const ViewCodeSequence = displaySet?.images[0]?.ViewCodeSequence[0]; + if (!ViewCodeSequence) { + return undefined; + } + const { CodingSchemeDesignator, CodeValue } = ViewCodeSequence; + if (!CodingSchemeDesignator || !CodeValue) { + return undefined; + } + return `${CodingSchemeDesignator}:${CodeValue}`; +}; diff --git a/extensions/default/src/init.ts b/extensions/default/src/init.ts index 4821e15ad6..2e5e831c8e 100644 --- a/extensions/default/src/init.ts +++ b/extensions/default/src/init.ts @@ -2,6 +2,7 @@ import { DicomMetadataStore, classes } from '@ohif/core'; import { calculateSUVScalingFactors } from '@cornerstonejs/calculate-suv'; import getPTImageIdInstanceMetadata from './getPTImageIdInstanceMetadata'; +import { registerHangingProtocolAttributes } from './hangingprotocols'; const metadataProvider = classes.MetadataProvider; @@ -10,7 +11,11 @@ const metadataProvider = classes.MetadataProvider; * @param {Object} servicesManager * @param {Object} configuration */ -export default function init({ servicesManager, configuration = {}, commandsManager }): void { +export default function init({ + servicesManager, + configuration = {}, + commandsManager, +}: withAppTypes): void { const { stateSyncService, toolbarService, cineService, viewportGridService } = servicesManager.services; @@ -56,6 +61,9 @@ export default function init({ servicesManager, configuration = {}, commandsMana // afterwards. stateSyncService.register('viewportsByPosition', { clearOnModeExit: true }); + // Adds extra custom attributes for use by hanging protocols + registerHangingProtocolAttributes({ servicesManager }); + // Function to process and subscribe to events for a given set of commands and listeners const subscribeToEvents = listeners => { Object.entries(listeners).forEach(([event, commands]) => { diff --git a/extensions/default/src/utils/createRenderedRetrieve.js b/extensions/default/src/utils/createRenderedRetrieve.js new file mode 100644 index 0000000000..ff490400c2 --- /dev/null +++ b/extensions/default/src/utils/createRenderedRetrieve.js @@ -0,0 +1,32 @@ +/** + * Generates the rendered URL that can be used for direct retrieve of the pixel data binary stream. + * + * @param {object} config - The configuration object. + * @param {string} config.wadoRoot - The root URL for the WADO service. + * @param {object} params - The parameters object. + * @param {string} params.tag - The tag name of the URL to retrieve. + * @param {string} params.defaultPath - The path for the pixel data URL. + * @param {object} params.instance - The instance object that the tag is in. + * @param {string} params.defaultType - The mime type of the response. + * @param {string} params.singlepart - The type of the part to retrieve. + * @param {string} params.fetchPart - Unknown parameter. + * @param {string} params.url - Unknown parameter. + * @returns {string|Promise} - An absolute URL to the binary stream. + */ +const createRenderedRetrieve = (config, params) => { + const { wadoRoot } = config; + const { instance, tag = 'PixelData' } = params; + const { StudyInstanceUID, SeriesInstanceUID, SOPInstanceUID } = instance; + const bulkDataURI = instance[tag]?.BulkDataURI ?? ''; + + if (bulkDataURI?.indexOf('?') !== -1) { + // The value instance has parameters, so it should not revert to the rendered + return; + } + + if (tag === 'PixelData' || tag === 'EncapsulatedDocument') { + return `${wadoRoot}/studies/${StudyInstanceUID}/series/${SeriesInstanceUID}/instances/${SOPInstanceUID}/rendered`; + } +}; + +export default createRenderedRetrieve; diff --git a/extensions/default/src/utils/createRenderedRetrieve.test.js b/extensions/default/src/utils/createRenderedRetrieve.test.js new file mode 100644 index 0000000000..f0d7bec6a5 --- /dev/null +++ b/extensions/default/src/utils/createRenderedRetrieve.test.js @@ -0,0 +1,46 @@ +import createRenderedRetrieve from './createRenderedRetrieve'; + +describe('createRenderedRetrieve', () => { + const config = { + wadoRoot: 'https://example.com/wado', + }; + + const params = { + instance: { + StudyInstanceUID: 'study-uid', + SeriesInstanceUID: 'series-uid', + SOPInstanceUID: 'sop-uid', + }, + }; + + it('should return the rendered URL for PixelData tag', () => { + const result = createRenderedRetrieve(config, { + ...params, + tag: 'PixelData', + }); + + expect(result).toBe( + 'https://example.com/wado/studies/study-uid/series/series-uid/instances/sop-uid/rendered' + ); + }); + + it('should return the rendered URL for EncapsulatedDocument tag', () => { + const result = createRenderedRetrieve(config, { + ...params, + tag: 'EncapsulatedDocument', + }); + + expect(result).toBe( + 'https://example.com/wado/studies/study-uid/series/series-uid/instances/sop-uid/rendered' + ); + }); + + it('should return undefined for unknown tag', () => { + const result = createRenderedRetrieve(config, { + ...params, + tag: 'UnknownTag', + }); + + expect(result).toBeUndefined(); + }); +}); diff --git a/extensions/default/src/utils/getBulkdataValue.js b/extensions/default/src/utils/getBulkdataValue.js new file mode 100644 index 0000000000..8857babcf1 --- /dev/null +++ b/extensions/default/src/utils/getBulkdataValue.js @@ -0,0 +1,45 @@ +/** + * Generates a URL that can be used for direct retrieve of the bulkdata. + * + * @param {object} config - The configuration object. + * @param {object} params - The parameters object. + * @param {string} params.tag - The tag name of the URL to retrieve. + * @param {string} params.defaultPath - The path for the pixel data URL. + * @param {object} params.instance - The instance object that the tag is in. + * @param {string} params.defaultType - The mime type of the response. + * @param {string} params.singlepart - The type of the part to retrieve. + * @param {string} params.fetchPart - Unknown. + * @returns {string|Promise} - An absolute URL to the resource, if the absolute URL can be retrieved as singlepart, + * or is already retrieved, or a promise to a URL for such use if a BulkDataURI. + */ +const getBulkdataValue = (config, params) => { + const { + instance, + tag = 'PixelData', + defaultPath = '/pixeldata', + defaultType = 'video/mp4', + } = params; + + const value = instance[tag]; + + const { StudyInstanceUID, SeriesInstanceUID, SOPInstanceUID } = instance; + + const BulkDataURI = + (value && value.BulkDataURI) || + `series/${SeriesInstanceUID}/instances/${SOPInstanceUID}${defaultPath}`; + const hasQuery = BulkDataURI.indexOf('?') !== -1; + const hasAccept = BulkDataURI.indexOf('accept=') !== -1; + const acceptUri = + BulkDataURI + (hasAccept ? '' : (hasQuery ? '&' : '?') + `accept=${defaultType}`); + + if (acceptUri.startsWith('series/')) { + const { wadoRoot } = config; + return `${wadoRoot}/studies/${StudyInstanceUID}/${acceptUri}`; + } + + // The DICOMweb standard states that the default is multipart related, and then + // separately states that the accept parameter is the URL parameter equivalent of the accept header. + return acceptUri; +}; + +export default getBulkdataValue; diff --git a/extensions/default/src/utils/getBulkdataValue.test.js b/extensions/default/src/utils/getBulkdataValue.test.js new file mode 100644 index 0000000000..542358aacb --- /dev/null +++ b/extensions/default/src/utils/getBulkdataValue.test.js @@ -0,0 +1,105 @@ +import getBulkdataValue from './getBulkdataValue'; + +jest.mock('@ohif/core'); + +global.URL.createObjectURL = jest.fn(() => 'blob:'); + +describe('getBulkdataValue', () => { + const config = { + singlepart: true, + }; + + const params = { + instance: { + StudyInstanceUID: 'study-uid', + SeriesInstanceUID: 'series-uid', + SOPInstanceUID: 'sop-uid', + }, + }; + + it('should return the BulkDataURI with defaultType if singlepart is true without accept', () => { + const value = { + BulkDataURI: 'https://example.com/bulkdata', + retrieveBulkData: jest.fn().mockResolvedValueOnce(new Uint8Array([0, 1, 2])), + }; + + const result = getBulkdataValue(config, { + ...params, + tag: 'PixelData', + instance: { + ...params.instance, + PixelData: value, + }, + }); + + expect(result).toContain(value.BulkDataURI); + expect(result).toContain('accept=video/mp4'); + const acceptCount = result.match(/accept=video\/mp4/g)?.length || 0; + expect(acceptCount).toBe(1); + }); + + it('should return the BulkDataURI with accept', () => { + const value = { + BulkDataURI: 'https://example.com/bulkdata?accept=video/mp4', + }; + + const result = getBulkdataValue(config, { + ...params, + tag: 'PixelData', + instance: { + ...params.instance, + PixelData: value, + }, + }); + + expect(result).toContain(value.BulkDataURI); + expect(result).toContain('accept=video/mp4'); + const acceptCount = result.match(/accept=video\/mp4/g)?.length || 0; + expect(acceptCount).toBe(1); + }); + + it('should return the BulkDataURI with accept and query params', () => { + const value = { + BulkDataURI: 'https://example.com/bulkdata?test=123', + }; + + const result = getBulkdataValue(config, { + ...params, + tag: 'PixelData', + instance: { + ...params.instance, + PixelData: value, + }, + }); + + expect(result).toContain(value.BulkDataURI); + expect(result).toContain('accept=video/mp4'); + expect(result).toContain('test=123'); + const acceptCount = result.match(/accept=video\/mp4/g)?.length || 0; + expect(acceptCount).toBe(1); + }); + + it('should return default path with accept', () => { + const value = { + BulkDataURI: null, + }; + + const defaultPath = '/testing'; + const defaultURI = `series/${params.instance.SeriesInstanceUID}/instances/${params.instance.SOPInstanceUID}${defaultPath}`; + + const result = getBulkdataValue(config, { + ...params, + defaultPath, + tag: 'PixelData', + instance: { + ...params.instance, + PixelData: value, + }, + }); + + expect(result).toContain(defaultURI); + expect(result).toContain('accept=video/mp4'); + const acceptCount = result.match(/accept=video\/mp4/g)?.length || 0; + expect(acceptCount).toBe(1); + }); +}); diff --git a/extensions/default/src/utils/getDirectURL.js b/extensions/default/src/utils/getDirectURL.js deleted file mode 100644 index d9ea924992..0000000000 --- a/extensions/default/src/utils/getDirectURL.js +++ /dev/null @@ -1,77 +0,0 @@ -import { utils } from '@ohif/core'; - -/** - * Generates a URL that can be used for direct retrieve of the bulkdata - * - * @param {object} params - * @param {string} params.tag is the tag name of the URL to retrieve - * @param {string} params.defaultPath path for the pixel data url - * @param {object} params.instance is the instance object that the tag is in - * @param {string} params.defaultType is the mime type of the response - * @param {string} params.singlepart is the type of the part to retrieve - * @param {string} params.fetchPart unknown? - * @param {string} params.url unknown? - * @returns an absolute URL to the resource, if the absolute URL can be retrieved as singlepart, - * or is already retrieved, or a promise to a URL for such use if a BulkDataURI - */ -const getDirectURL = (config, params) => { - const { wadoRoot, singlepart } = config; - const { - instance, - tag = 'PixelData', - defaultPath = '/pixeldata', - defaultType = 'video/mp4', - singlepart: fetchPart = 'video', - url = null, - } = params; - if (url) { - return url; - } - - const value = instance[tag]; - if (!value) { - return undefined; - } - - if (value.DirectRetrieveURL) { - return value.DirectRetrieveURL; - } - if (value.InlineBinary) { - const blob = utils.b64toBlob(value.InlineBinary, defaultType); - value.DirectRetrieveURL = URL.createObjectURL(blob); - return value.DirectRetrieveURL; - } - if (!singlepart || (singlepart !== true && singlepart.indexOf(fetchPart) === -1)) { - if (value.retrieveBulkData) { - // Try the specified retrieve type. - const options = { - mediaType: defaultType, - }; - return value.retrieveBulkData(options).then(arr => { - value.DirectRetrieveURL = URL.createObjectURL(new Blob([arr], { type: defaultType })); - return value.DirectRetrieveURL; - }); - } - console.warn('Unable to retrieve', tag, 'from', instance); - return undefined; - } - - const { StudyInstanceUID, SeriesInstanceUID, SOPInstanceUID } = instance; - const BulkDataURI = - (value && value.BulkDataURI) || - `series/${SeriesInstanceUID}/instances/${SOPInstanceUID}${defaultPath}`; - const hasQuery = BulkDataURI.indexOf('?') !== -1; - const hasAccept = BulkDataURI.indexOf('accept=') !== -1; - const acceptUri = - BulkDataURI + (hasAccept ? '' : (hasQuery ? '&' : '?') + `accept=${defaultType}`); - - if (tag === 'PixelData' || tag === 'EncapsulatedDocument') { - return `${wadoRoot}/studies/${StudyInstanceUID}/series/${SeriesInstanceUID}/instances/${SOPInstanceUID}/rendered`; - } - - // The DICOMweb standard states that the default is multipart related, and then - // separately states that the accept parameter is the URL parameter equivalent of the accept header. - return acceptUri; -}; - -export default getDirectURL; diff --git a/extensions/default/src/utils/getDirectURL.test.js b/extensions/default/src/utils/getDirectURL.test.js new file mode 100644 index 0000000000..eb13e5ac9f --- /dev/null +++ b/extensions/default/src/utils/getDirectURL.test.js @@ -0,0 +1,169 @@ +import getDirectURL from './getDirectURL'; +import getBulkdataValue from './getBulkdataValue'; +import createRenderedRetrieve from './createRenderedRetrieve'; + +jest.mock('@ohif/core'); +jest.mock('./getBulkdataValue'); +jest.mock('./createRenderedRetrieve'); + +global.URL.createObjectURL = jest.fn(() => 'blob:'); + +describe('getDirectURL', () => { + const config = { + singlepart: true, + defaultType: 'video/mp4', + }; + + const params = { + tag: 'PixelData', + defaultPath: '/path/to/pixeldata', + instance: { + StudyInstanceUID: 'study-uid', + SeriesInstanceUID: 'series-uid', + SOPInstanceUID: 'sop-uid', + }, + }; + + it('should return the provided URL if it exists', () => { + const url = 'https://example.com/direct-retrieve'; + + const result = getDirectURL(config, { + ...params, + url: 'https://example.com/direct-retrieve', + }); + + expect(result).toBe(url); + }); + + it('should return the DirectRetrieveURL if it exists', () => { + const value = { + DirectRetrieveURL: 'https://example.com/direct-retrieve', + }; + + const result = getDirectURL(config, { + ...params, + tag: 'PixelData', + instance: { + ...params.instance, + PixelData: value, + }, + }); + + expect(result).toBe(value.DirectRetrieveURL); + }); + + it('should return the URL for InlineBinary', () => { + const value = { + InlineBinary: 'base64-encoded-data', + }; + + const result = getDirectURL(config, { + ...params, + tag: 'PixelData', + instance: { + ...params.instance, + PixelData: value, + }, + }); + + expect(result).toContain('blob:'); + }); + + it('should return the BulkDataURI with defaultType if singlepart is false and there is no retrieveBulkData', () => { + const value = { + BulkDataURI: 'https://example.com/bulkdata', + }; + + const result = getDirectURL( + { + ...config, + singlepart: false, + }, + { + ...params, + tag: 'PixelData', + instance: { + ...params.instance, + PixelData: value, + }, + } + ); + + expect(result).toBeUndefined(); + }); + + it('should return the BulkDataURI with defaultType if singlepart is false with retrieveBulkData', async () => { + const value = { + BulkDataURI: 'https://example.com/bulkdata', + retrieveBulkData: jest.fn().mockResolvedValueOnce(new Uint8Array([0, 1, 2])), + }; + + const result = await getDirectURL( + { + ...config, + singlepart: false, + }, + { + ...params, + tag: 'PixelData', + instance: { + ...params.instance, + PixelData: value, + }, + } + ); + + expect(result).toContain('blob:'); + }); + + it('should return the BulkDataURI with defaultType if singlepart does not include fetchPart', async () => { + const arr = new Uint8Array([0, 1, 2]); + + const value = { + BulkDataURI: 'https://example.com/bulkdata', + retrieveBulkData: jest.fn().mockResolvedValueOnce(arr), + }; + + const result = await getDirectURL( + { + ...config, + singlepart: ['audio'], + }, + { + ...params, + tag: 'PixelData', + instance: { + ...params.instance, + PixelData: value, + }, + } + ); + + expect(result).toContain('blob:'); + expect(URL.createObjectURL).toHaveBeenCalledWith(new Blob([arr], { type: 'accept=video/mp4' })); + }); + + it('should return the URL from getBulkdataValue if it exists', () => { + const bulkDataURL = 'https://example.com/bulkdata'; + + getBulkdataValue.mockReturnValueOnce(bulkDataURL); + + const result = getDirectURL(config, params); + + expect(getBulkdataValue).toHaveBeenCalledWith(config, params); + expect(result).toBe(bulkDataURL); + }); + + it('should return the URL from createRenderedRetrieve if getBulkdataValue returns falsy', () => { + const renderedRetrieveURL = 'https://example.com/rendered-retrieve'; + + getBulkdataValue.mockReturnValueOnce(null); + createRenderedRetrieve.mockReturnValueOnce(renderedRetrieveURL); + + const result = getDirectURL(config, params); + + expect(getBulkdataValue).toHaveBeenCalledWith(config, params); + expect(createRenderedRetrieve).toHaveBeenCalledWith(config, params); + expect(result).toBe(renderedRetrieveURL); + }); +}); diff --git a/extensions/default/src/utils/getDirectURL.ts b/extensions/default/src/utils/getDirectURL.ts new file mode 100644 index 0000000000..54e7745c9f --- /dev/null +++ b/extensions/default/src/utils/getDirectURL.ts @@ -0,0 +1,65 @@ +import { utils } from '@ohif/core'; + +import getBulkdataValue from './getBulkdataValue'; +import createRenderedRetrieve from './createRenderedRetrieve'; + +/** + * Generates a URL that can be used for direct retrieve of the bulkdata + * + * @param {object} params + * @param {string} params.tag is the tag name of the URL to retrieve + * @param {string} params.defaultPath path for the pixel data url + * @param {object} params.instance is the instance object that the tag is in + * @param {string} params.defaultType is the mime type of the response + * @param {string} params.singlepart is the type of the part to retrieve + * @param {string} params.fetchPart unknown? + * @param {string} params.url unknown? + * @returns an absolute URL to the resource, if the absolute URL can be retrieved as singlepart, + * or is already retrieved, or a promise to a URL for such use if a BulkDataURI + */ +const getDirectURL = (config, params) => { + const { singlepart } = config; + const { + instance, + tag = 'PixelData', + defaultType = 'video/mp4', + singlepart: fetchPart = 'video', + url = null, + } = params; + + if (url) { + return url; + } + + const value = instance[tag]; + if (value) { + if (value.DirectRetrieveURL) { + return value.DirectRetrieveURL; + } + + if (value.InlineBinary) { + const blob = utils.b64toBlob(value.InlineBinary, defaultType); + value.DirectRetrieveURL = URL.createObjectURL(blob); + return value.DirectRetrieveURL; + } + + if (!singlepart || (singlepart !== true && singlepart.indexOf(fetchPart) === -1)) { + if (value.retrieveBulkData) { + // Try the specified retrieve type. + const options = { + mediaType: defaultType, + }; + return value.retrieveBulkData(options).then(arr => { + value.DirectRetrieveURL = URL.createObjectURL(new Blob([arr], { type: defaultType })); + return value.DirectRetrieveURL; + }); + } + console.warn('Unable to retrieve', tag, 'from', instance); + return undefined; + } + } + + return createRenderedRetrieve(config, params) || getBulkdataValue(config, params); +}; + +export default getDirectURL; diff --git a/extensions/dicom-microscopy/.webpack/webpack.prod.js b/extensions/dicom-microscopy/.webpack/webpack.prod.js index cedfa6d10b..540fb81ca3 100644 --- a/extensions/dicom-microscopy/.webpack/webpack.prod.js +++ b/extensions/dicom-microscopy/.webpack/webpack.prod.js @@ -43,7 +43,6 @@ module.exports = (env, argv) => { externals: [ /\b(vtk.js)/, /\b(dcmjs)/, - /\b(dicom-microscopy-viewer)/, /\b(gl-matrix)/, /^@ohif/, /^@cornerstonejs/, diff --git a/extensions/dicom-microscopy/CHANGELOG.md b/extensions/dicom-microscopy/CHANGELOG.md index 21d2e0d9ae..08e272b7e4 100644 --- a/extensions/dicom-microscopy/CHANGELOG.md +++ b/extensions/dicom-microscopy/CHANGELOG.md @@ -3,6 +3,693 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.9.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.70...v3.9.0-beta.71) (2024-07-30) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.69...v3.9.0-beta.70) (2024-07-30) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.68...v3.9.0-beta.69) (2024-07-27) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.67...v3.9.0-beta.68) (2024-07-26) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.66...v3.9.0-beta.67) (2024-07-26) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.65...v3.9.0-beta.66) (2024-07-24) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.64...v3.9.0-beta.65) (2024-07-23) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.63...v3.9.0-beta.64) (2024-07-19) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.62...v3.9.0-beta.63) (2024-07-10) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.61...v3.9.0-beta.62) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.60...v3.9.0-beta.61) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.59...v3.9.0-beta.60) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.58...v3.9.0-beta.59) (2024-07-05) + + +### Bug Fixes + +* webpack import bugs showing warnings on import ([#4265](https://github.com/OHIF/Viewers/issues/4265)) ([24c511f](https://github.com/OHIF/Viewers/commit/24c511f4bc04c4143bbd3d0d48029f41f7f36014)) + + + + + +# [3.9.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.57...v3.9.0-beta.58) (2024-07-04) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.56...v3.9.0-beta.57) (2024-07-02) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.55...v3.9.0-beta.56) (2024-07-02) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.54...v3.9.0-beta.55) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.53...v3.9.0-beta.54) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.52...v3.9.0-beta.53) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.51...v3.9.0-beta.52) (2024-06-27) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.50...v3.9.0-beta.51) (2024-06-27) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.49...v3.9.0-beta.50) (2024-06-26) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.48...v3.9.0-beta.49) (2024-06-26) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.47...v3.9.0-beta.48) (2024-06-25) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.46...v3.9.0-beta.47) (2024-06-21) + + +### Bug Fixes + +* Allow the mode setup/creation to be async, and provide a few more values to extension/app config/mode setup. ([#4016](https://github.com/OHIF/Viewers/issues/4016)) ([88575c6](https://github.com/OHIF/Viewers/commit/88575c6c09fd778a31b2f91524163ce65d1639dd)) + + + + + +# [3.9.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.45...v3.9.0-beta.46) (2024-06-18) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.44...v3.9.0-beta.45) (2024-06-18) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.43...v3.9.0-beta.44) (2024-06-17) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.42...v3.9.0-beta.43) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.41...v3.9.0-beta.42) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.40...v3.9.0-beta.41) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.39...v3.9.0-beta.40) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.38...v3.9.0-beta.39) (2024-06-08) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.37...v3.9.0-beta.38) (2024-06-07) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.36...v3.9.0-beta.37) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.35...v3.9.0-beta.36) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.34...v3.9.0-beta.35) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.33...v3.9.0-beta.34) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.32...v3.9.0-beta.33) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.31...v3.9.0-beta.32) (2024-05-31) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.30...v3.9.0-beta.31) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.29...v3.9.0-beta.30) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.28...v3.9.0-beta.29) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.27...v3.9.0-beta.28) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.26...v3.9.0-beta.27) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.25...v3.9.0-beta.26) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.24...v3.9.0-beta.25) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.23...v3.9.0-beta.24) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.22...v3.9.0-beta.23) (2024-05-28) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.21...v3.9.0-beta.22) (2024-05-27) + + +### Features + +* **ui:** move to React 18 and base for using shadcn/ui ([#4174](https://github.com/OHIF/Viewers/issues/4174)) ([70f2c79](https://github.com/OHIF/Viewers/commit/70f2c797f42af603d7ea0eb8d23b4103aba66f77)) + + + + + +# [3.9.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.20...v3.9.0-beta.21) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.19...v3.9.0-beta.20) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.18...v3.9.0-beta.19) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.17...v3.9.0-beta.18) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.16...v3.9.0-beta.17) (2024-05-23) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.15...v3.9.0-beta.16) (2024-05-23) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.14...v3.9.0-beta.15) (2024-05-22) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.13...v3.9.0-beta.14) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.12...v3.9.0-beta.13) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.11...v3.9.0-beta.12) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.10...v3.9.0-beta.11) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.9...v3.9.0-beta.10) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.8...v3.9.0-beta.9) (2024-05-17) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.7...v3.9.0-beta.8) (2024-05-16) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.6...v3.9.0-beta.7) (2024-05-15) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.5...v3.9.0-beta.6) (2024-05-15) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.4...v3.9.0-beta.5) (2024-05-14) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.3...v3.9.0-beta.4) (2024-05-14) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.2...v3.9.0-beta.3) (2024-05-08) + + +### Features + +* **typings:** Enhance typing support with withAppTypes and custom services throughout OHIF ([#4090](https://github.com/OHIF/Viewers/issues/4090)) ([374065b](https://github.com/OHIF/Viewers/commit/374065bc3bad9d212f9817a8d41546cc64cfabfb)) + + + + + +# [3.9.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.1...v3.9.0-beta.2) (2024-05-06) + + +### Bug Fixes + +* **bugs:** enhancements and bugs in several areas ([#4086](https://github.com/OHIF/Viewers/issues/4086)) ([730f434](https://github.com/OHIF/Viewers/commit/730f4349100f21b4489a21707dbb2dca9dbfbba2)) + + + + + +# [3.9.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.0...v3.9.0-beta.1) (2024-05-06) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.9.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.94...v3.9.0-beta.0) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.8.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0-beta.94) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + +# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18) + +**Note:** Version bump only for package @ohif/extension-dicom-microscopy + + + + + # [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17) **Note:** Version bump only for package @ohif/extension-dicom-microscopy diff --git a/extensions/dicom-microscopy/babel.config.js b/extensions/dicom-microscopy/babel.config.js index a38ddda212..9705ae6f28 100644 --- a/extensions/dicom-microscopy/babel.config.js +++ b/extensions/dicom-microscopy/babel.config.js @@ -1,5 +1,5 @@ module.exports = { - plugins: ['inline-react-svg', '@babel/plugin-proposal-class-properties'], + plugins: ['@babel/plugin-proposal-class-properties'], env: { test: { presets: [ @@ -37,7 +37,7 @@ module.exports = { '@babel/preset-react', '@babel/preset-typescript', ], - plugins: ['react-hot-loader/babel'], + plugins: ['react-refresh/babel'], ignore: ['**/*.test.jsx', '**/*.test.js', '__snapshots__', '__tests__'], }, }, diff --git a/extensions/dicom-microscopy/package.json b/extensions/dicom-microscopy/package.json index d8e310ca97..ecbba3af91 100644 --- a/extensions/dicom-microscopy/package.json +++ b/extensions/dicom-microscopy/package.json @@ -1,6 +1,6 @@ { "name": "@ohif/extension-dicom-microscopy", - "version": "3.8.0-beta.82", + "version": "3.9.0-beta.71", "description": "OHIF extension for DICOM microscopy", "author": "Bill Wallace, md-prog", "license": "MIT", @@ -30,16 +30,16 @@ "start": "yarn run dev" }, "peerDependencies": { - "@ohif/core": "3.8.0-beta.82", - "@ohif/extension-default": "3.8.0-beta.82", - "@ohif/i18n": "3.8.0-beta.82", - "@ohif/ui": "3.8.0-beta.82", + "@ohif/core": "3.9.0-beta.71", + "@ohif/extension-default": "3.9.0-beta.71", + "@ohif/i18n": "3.9.0-beta.71", + "@ohif/ui": "3.9.0-beta.71", "prop-types": "^15.6.2", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "react": "^18.3.1", + "react-dom": "^18.3.1", "react-i18next": "^10.11.0", - "react-router": "^6.8.1", - "react-router-dom": "^6.8.1" + "react-router": "^6.23.1", + "react-router-dom": "^6.23.1" }, "dependencies": { "@babel/runtime": "^7.20.13", @@ -47,7 +47,6 @@ "@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2", "@cornerstonejs/codec-openjpeg": "^1.2.2", "colormap": "^2.3", - "dicom-microscopy-viewer": "^0.44.0", - "dicomicc": "^0.1" + "mathjs": "^12.4.2" } } diff --git a/extensions/dicom-microscopy/src/DicomMicroscopyViewport.tsx b/extensions/dicom-microscopy/src/DicomMicroscopyViewport.tsx index fd44e21f76..3ebe0c6032 100644 --- a/extensions/dicom-microscopy/src/DicomMicroscopyViewport.tsx +++ b/extensions/dicom-microscopy/src/DicomMicroscopyViewport.tsx @@ -1,7 +1,5 @@ import React, { Component } from 'react'; -import ReactResizeDetector from 'react-resize-detector'; import PropTypes from 'prop-types'; -import debounce from 'lodash.debounce'; import { LoadingIndicatorProgress } from '@ohif/ui'; import './DicomMicroscopyViewport.css'; @@ -23,18 +21,12 @@ class DicomMicroscopyViewport extends Component { container = React.createRef(); overlayElement = React.createRef(); - debouncedResize: () => any; constructor(props: any) { super(props); const { microscopyService } = this.props.servicesManager.services; this.microscopyService = microscopyService; - this.debouncedResize = debounce(() => { - if (this.viewer) { - this.viewer.resize(); - } - }, 100); } static propTypes = { @@ -54,8 +46,10 @@ class DicomMicroscopyViewport extends Component { servicesManager: PropTypes.object, extensionManager: PropTypes.object, commandsManager: PropTypes.object, + resizeRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({ current: PropTypes.any })]), }; + /** * Get the nearest ROI from the mouse click point * @@ -93,9 +87,9 @@ class DicomMicroscopyViewport extends Component { // you should only do this once. async installOpenLayersRenderer(container, displaySet) { const loadViewer = async metadata => { - const { viewer: DicomMicroscopyViewer, metadata: metadataUtils } = await import( - /* webpackChunkName: "dicom-microscopy-viewer" */ 'dicom-microscopy-viewer' - ); + const dicomMicroscopyModule = await this.microscopyService.importDicomMicroscopyViewer(); + const { viewer: DicomMicroscopyViewer, metadata: metadataUtils } = dicomMicroscopyModule; + const microscopyViewer = DicomMicroscopyViewer.VolumeImageViewer; const client = getDicomWebClient({ @@ -298,13 +292,16 @@ class DicomMicroscopyViewport extends Component {
- {ReactResizeDetector && ( - - )} {this.state.error ? (

{JSON.stringify(this.state.error)}

) : ( -
+
{ + this.container.current = ref; + this.props.resizeRef.current = ref; + }} + /> )} {this.state.isLoaded ? null : ( @@ -312,10 +309,6 @@ class DicomMicroscopyViewport extends Component {
); } - - onWindowResize = () => { - this.debouncedResize(); - }; } export default DicomMicroscopyViewport; diff --git a/extensions/dicom-microscopy/src/components/MicroscopyPanel/MicroscopyPanel.tsx b/extensions/dicom-microscopy/src/components/MicroscopyPanel/MicroscopyPanel.tsx index 3da3b5d4be..c0c983a4cb 100644 --- a/extensions/dicom-microscopy/src/components/MicroscopyPanel/MicroscopyPanel.tsx +++ b/extensions/dicom-microscopy/src/components/MicroscopyPanel/MicroscopyPanel.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect } from 'react'; import PropTypes from 'prop-types'; -import { ServicesManager, ExtensionManager, CommandsManager, DicomMetadataStore } from '@ohif/core'; +import { ExtensionManager, CommandsManager, DicomMetadataStore } from '@ohif/core'; import { MeasurementTable } from '@ohif/ui'; import { withTranslation, WithTranslation } from 'react-i18next'; import { EVENTS as MicroscopyEvents } from '../../services/MicroscopyService'; @@ -53,7 +53,7 @@ interface IMicroscopyPanelProps extends WithTranslation { onRejectComplete?: PropTypes.func; // callback when rejected annotations // - servicesManager: ServicesManager; + servicesManager: AppTypes.ServicesManager; extensionManager: ExtensionManager; commandsManager: CommandsManager; } diff --git a/extensions/dicom-microscopy/src/getCommandsModule.ts b/extensions/dicom-microscopy/src/getCommandsModule.ts index 02d7ee8b8d..28750f9179 100644 --- a/extensions/dicom-microscopy/src/getCommandsModule.ts +++ b/extensions/dicom-microscopy/src/getCommandsModule.ts @@ -1,4 +1,4 @@ -import { ServicesManager, CommandsManager, ExtensionManager } from '@ohif/core'; +import { CommandsManager, ExtensionManager } from '@ohif/core'; import styles from './utils/styles'; import callInputDialog from './utils/callInputDialog'; @@ -7,7 +7,7 @@ export default function getCommandsModule({ commandsManager, extensionManager, }: { - servicesManager: ServicesManager; + servicesManager: AppTypes.ServicesManager; commandsManager: CommandsManager; extensionManager: ExtensionManager; }) { diff --git a/extensions/dicom-microscopy/src/getPanelModule.tsx b/extensions/dicom-microscopy/src/getPanelModule.tsx index 58e4f2f09c..a515363aac 100644 --- a/extensions/dicom-microscopy/src/getPanelModule.tsx +++ b/extensions/dicom-microscopy/src/getPanelModule.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { ServicesManager, CommandsManager, ExtensionManager } from '@ohif/core'; +import type { Types } from '@ohif/core'; import { useViewportGrid } from '@ohif/ui'; import MicroscopyPanel from './components/MicroscopyPanel/MicroscopyPanel'; @@ -12,11 +12,7 @@ export default function getPanelModule({ commandsManager, extensionManager, servicesManager, -}: { - servicesManager: ServicesManager; - commandsManager: CommandsManager; - extensionManager: ExtensionManager; -}) { +}: Types.Extensions.ExtensionParams) { const wrappedMeasurementPanel = () => { const [{ activeViewportId, viewports }] = useViewportGrid(); diff --git a/extensions/dicom-microscopy/src/index.tsx b/extensions/dicom-microscopy/src/index.tsx index bd26b5c3e2..ce87687450 100644 --- a/extensions/dicom-microscopy/src/index.tsx +++ b/extensions/dicom-microscopy/src/index.tsx @@ -8,6 +8,8 @@ import { useViewportGrid } from '@ohif/ui'; import getDicomMicroscopySopClassHandler from './DicomMicroscopySopClassHandler'; import getDicomMicroscopySRSopClassHandler from './DicomMicroscopySRSopClassHandler'; import MicroscopyService from './services/MicroscopyService'; +import { useResizeDetector } from 'react-resize-detector'; +import debounce from 'lodash.debounce'; const Component = React.lazy(() => { return import('./DicomMicroscopyViewport'); @@ -42,6 +44,7 @@ const extension: Types.Extensions.Extension = { * that is provided by the Cornerstone extension in OHIF. */ getViewportModule({ servicesManager, extensionManager, commandsManager }) { + /** * * @param props {*} @@ -59,14 +62,25 @@ const extension: Types.Extensions.Extension = { const [viewportGrid, viewportGridService] = useViewportGrid(); const { activeViewportId } = viewportGrid; - // a unique identifier based on the contents of displaySets. - // since we changed our rendering pipeline and if there is no - // element size change nor viewportId change we won't re-render - // we need a way to force re-rendering when displaySets change. const displaySetsKey = useMemo(() => { return props.displaySets.map(ds => ds.displaySetInstanceUID).join('-'); }, [props.displaySets]); + const onResize = debounce(() => { + const { microscopyService } = servicesManager.services; + const managedViewer = microscopyService.getAllManagedViewers(); + + if (managedViewer && managedViewer.length > 0) { + managedViewer[0].viewer.resize(); + } + }, 100); + + const { ref: resizeRef } = useResizeDetector({ + onResize, + handleHeight: true, + handleWidth: true, + }); + return ( ); @@ -99,7 +114,9 @@ const extension: Types.Extensions.Extension = { const { microscopyService } = servicesManager.services; const activeInteractions = microscopyService.getActiveInteractions(); - + if (!activeInteractions) { + return false; + } const isPrimaryActive = activeInteractions.find(interactions => { const sameMouseButton = interactions[1].bindings.mouseButtons.includes('left'); diff --git a/extensions/dicom-microscopy/src/services/MicroscopyService.ts b/extensions/dicom-microscopy/src/services/MicroscopyService.ts index 0f6005f5d4..e59f048af6 100644 --- a/extensions/dicom-microscopy/src/services/MicroscopyService.ts +++ b/extensions/dicom-microscopy/src/services/MicroscopyService.ts @@ -18,17 +18,17 @@ const EVENTS = { * ROI annotations relevant to the application */ export default class MicroscopyService extends PubSubService { - public static REGISTRATION = serviceManager => { + public static REGISTRATION = servicesManager => { return { name: 'microscopyService', altName: 'MicroscopyService', - create: ({ configuration = {} }) => { - return new MicroscopyService(serviceManager); + create: (props) => { + return new MicroscopyService(props); }, }; }; - serviceManager: any; + servicesManager: any; managedViewers = new Set(); roiUids = new Set(); @@ -36,9 +36,10 @@ export default class MicroscopyService extends PubSubService { selectedAnnotation = null; pendingFocus = false; - constructor(serviceManager) { + constructor({ servicesManager, extensionManager }) { super(EVENTS); - this.serviceManager = serviceManager; + this.servicesManager = servicesManager; + this.peerImport = extensionManager.appConfig.peerImport; this._onRoiAdded = this._onRoiAdded.bind(this); this._onRoiModified = this._onRoiModified.bind(this); this._onRoiRemoved = this._onRoiRemoved.bind(this); @@ -69,6 +70,10 @@ export default class MicroscopyService extends PubSubService { }); } + public importDicomMicroscopyViewer(): Promise { + return this.peerImport("dicom-microscopy-viewer"); + } + /** * Observes when a ROI graphic is added, creating the correspondent annotation * with the current graphic and view state. @@ -628,6 +633,15 @@ export default class MicroscopyService extends PubSubService { setROIStyle(uid, styleOptions) { this.managedViewers.forEach(mv => mv.setROIStyle(uid, styleOptions)); } + + /** + * Get all managed viewers + * + * @returns {Array} managedViewers + */ + getAllManagedViewers() { + return Array.from(this.managedViewers); + } } export { EVENTS }; diff --git a/extensions/dicom-microscopy/src/types/AppTypes.ts b/extensions/dicom-microscopy/src/types/AppTypes.ts new file mode 100644 index 0000000000..87fe897603 --- /dev/null +++ b/extensions/dicom-microscopy/src/types/AppTypes.ts @@ -0,0 +1,11 @@ +/* eslint-disable @typescript-eslint/no-namespace */ +import MicroscopyServiceType from '../services/MicroscopyService'; + +declare global { + namespace AppTypes { + export type MicroscopyService = MicroscopyServiceType; + export interface Services { + microscopyService?: MicroscopyServiceType; + } + } +} diff --git a/extensions/dicom-microscopy/src/utils/dicomWebClient.ts b/extensions/dicom-microscopy/src/utils/dicomWebClient.ts index dc906b1207..42455fe0cd 100644 --- a/extensions/dicom-microscopy/src/utils/dicomWebClient.ts +++ b/extensions/dicom-microscopy/src/utils/dicomWebClient.ts @@ -9,7 +9,7 @@ import { StaticWadoClient } from '@ohif/extension-default'; * @param param0 * @returns */ -export default function getDicomWebClient({ extensionManager, servicesManager }) { +export default function getDicomWebClient({ extensionManager, servicesManager }: withAppTypes) { const dataSourceConfig = window.config.dataSources.find( ds => ds.sourceName === extensionManager.activeDataSource ); diff --git a/extensions/dicom-microscopy/src/utils/loadSR.js b/extensions/dicom-microscopy/src/utils/loadSR.ts similarity index 94% rename from extensions/dicom-microscopy/src/utils/loadSR.js rename to extensions/dicom-microscopy/src/utils/loadSR.ts index c300b6f5e8..c6d280230c 100644 --- a/extensions/dicom-microscopy/src/utils/loadSR.js +++ b/extensions/dicom-microscopy/src/utils/loadSR.ts @@ -23,7 +23,7 @@ export default async function loadSR( microscopySRDisplaySet.isLoaded = true; - const { rois, labels } = await _getROIsFromToolState(naturalizedDataset, FrameOfReferenceUID); + const { rois, labels } = await _getROIsFromToolState(microscopyService, naturalizedDataset, FrameOfReferenceUID); const managedViewer = managedViewers[0]; @@ -44,13 +44,11 @@ export default async function loadSR( } } -async function _getROIsFromToolState(naturalizedDataset, FrameOfReferenceUID) { +async function _getROIsFromToolState(microscopyService, naturalizedDataset, FrameOfReferenceUID) { const toolState = MeasurementReport.generateToolState(naturalizedDataset); const tools = Object.getOwnPropertyNames(toolState); - - const DICOMMicroscopyViewer = await import( - /* webpackChunkName: "dicom-microscopy-viewer" */ 'dicom-microscopy-viewer' - ); + // Does a dynamic import to prevent webpack from rebuilding the library + const DICOMMicroscopyViewer = await microscopyService.importDicomMicroscopyViewer(); const measurementGroupContentItems = _getMeasurementGroups(naturalizedDataset); diff --git a/extensions/dicom-microscopy/tsconfig.json b/extensions/dicom-microscopy/tsconfig.json deleted file mode 100644 index e8977ec34b..0000000000 --- a/extensions/dicom-microscopy/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "compilerOptions": { - "outDir": "./dist/", - "noImplicitAny": true, - "module": "es6", - "target": "es5", - "jsx": "react", - "allowJs": true, - "moduleResolution": "node" - } -} diff --git a/extensions/dicom-pdf/.webpack/webpack.prod.js b/extensions/dicom-pdf/.webpack/webpack.prod.js index eb47972e1a..7957a5153e 100644 --- a/extensions/dicom-pdf/.webpack/webpack.prod.js +++ b/extensions/dicom-pdf/.webpack/webpack.prod.js @@ -3,6 +3,8 @@ const { merge } = require('webpack-merge'); const path = require('path'); const webpackCommon = require('./../../../.webpack/webpack.base.js'); const pkg = require('./../package.json'); +const MiniCssExtractPlugin = require('mini-css-extract-plugin'); + const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; const ROOT_DIR = path.join(__dirname, './..'); @@ -12,6 +14,8 @@ const ENTRY = { app: `${SRC_DIR}/index.tsx`, }; +const outputName = `ohif-${pkg.name.split('/').pop()}`; + module.exports = (env, argv) => { const commonConfig = webpackCommon(env, argv, { SRC_DIR, ENTRY, DIST_DIR }); @@ -42,6 +46,10 @@ module.exports = (env, argv) => { new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1, }), + new MiniCssExtractPlugin({ + filename: `./dist/${outputName}.css`, + chunkFilename: `./dist/${outputName}.css`, + }), // new BundleAnalyzerPlugin(), ], }); diff --git a/extensions/dicom-pdf/CHANGELOG.md b/extensions/dicom-pdf/CHANGELOG.md index 0292212324..8c05eb1411 100644 --- a/extensions/dicom-pdf/CHANGELOG.md +++ b/extensions/dicom-pdf/CHANGELOG.md @@ -3,6 +3,688 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.9.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.70...v3.9.0-beta.71) (2024-07-30) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.69...v3.9.0-beta.70) (2024-07-30) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.68...v3.9.0-beta.69) (2024-07-27) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.67...v3.9.0-beta.68) (2024-07-26) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.66...v3.9.0-beta.67) (2024-07-26) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.65...v3.9.0-beta.66) (2024-07-24) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.64...v3.9.0-beta.65) (2024-07-23) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.63...v3.9.0-beta.64) (2024-07-19) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.62...v3.9.0-beta.63) (2024-07-10) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.61...v3.9.0-beta.62) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.60...v3.9.0-beta.61) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.59...v3.9.0-beta.60) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.58...v3.9.0-beta.59) (2024-07-05) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.57...v3.9.0-beta.58) (2024-07-04) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.56...v3.9.0-beta.57) (2024-07-02) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.55...v3.9.0-beta.56) (2024-07-02) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.54...v3.9.0-beta.55) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.53...v3.9.0-beta.54) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.52...v3.9.0-beta.53) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.51...v3.9.0-beta.52) (2024-06-27) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.50...v3.9.0-beta.51) (2024-06-27) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.49...v3.9.0-beta.50) (2024-06-26) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.48...v3.9.0-beta.49) (2024-06-26) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.47...v3.9.0-beta.48) (2024-06-25) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.46...v3.9.0-beta.47) (2024-06-21) + + +### Bug Fixes + +* Allow the mode setup/creation to be async, and provide a few more values to extension/app config/mode setup. ([#4016](https://github.com/OHIF/Viewers/issues/4016)) ([88575c6](https://github.com/OHIF/Viewers/commit/88575c6c09fd778a31b2f91524163ce65d1639dd)) + + + + + +# [3.9.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.45...v3.9.0-beta.46) (2024-06-18) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.44...v3.9.0-beta.45) (2024-06-18) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.43...v3.9.0-beta.44) (2024-06-17) + + +### Bug Fixes + +* **cli:** version txt had a new line which it should not ([#4233](https://github.com/OHIF/Viewers/issues/4233)) ([097ef76](https://github.com/OHIF/Viewers/commit/097ef7665559a672d73e1babfc42afccc3cdd41d)) +* **pdf-viewport:** Allow Drag and Drop on PDF Viewport ([#4225](https://github.com/OHIF/Viewers/issues/4225)) ([729efb6](https://github.com/OHIF/Viewers/commit/729efb6d766e0f72f1fd8adefbca6fb46b355b2b)) + + + + + +# [3.9.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.42...v3.9.0-beta.43) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.41...v3.9.0-beta.42) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.40...v3.9.0-beta.41) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.39...v3.9.0-beta.40) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.38...v3.9.0-beta.39) (2024-06-08) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.37...v3.9.0-beta.38) (2024-06-07) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.36...v3.9.0-beta.37) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.35...v3.9.0-beta.36) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.34...v3.9.0-beta.35) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.33...v3.9.0-beta.34) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.32...v3.9.0-beta.33) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.31...v3.9.0-beta.32) (2024-05-31) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.30...v3.9.0-beta.31) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.29...v3.9.0-beta.30) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.28...v3.9.0-beta.29) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.27...v3.9.0-beta.28) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.26...v3.9.0-beta.27) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.25...v3.9.0-beta.26) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.24...v3.9.0-beta.25) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.23...v3.9.0-beta.24) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.22...v3.9.0-beta.23) (2024-05-28) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.21...v3.9.0-beta.22) (2024-05-27) + + +### Features + +* **ui:** move to React 18 and base for using shadcn/ui ([#4174](https://github.com/OHIF/Viewers/issues/4174)) ([70f2c79](https://github.com/OHIF/Viewers/commit/70f2c797f42af603d7ea0eb8d23b4103aba66f77)) + + + + + +# [3.9.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.20...v3.9.0-beta.21) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.19...v3.9.0-beta.20) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.18...v3.9.0-beta.19) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.17...v3.9.0-beta.18) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.16...v3.9.0-beta.17) (2024-05-23) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.15...v3.9.0-beta.16) (2024-05-23) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.14...v3.9.0-beta.15) (2024-05-22) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.13...v3.9.0-beta.14) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.12...v3.9.0-beta.13) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.11...v3.9.0-beta.12) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.10...v3.9.0-beta.11) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.9...v3.9.0-beta.10) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.8...v3.9.0-beta.9) (2024-05-17) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.7...v3.9.0-beta.8) (2024-05-16) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.6...v3.9.0-beta.7) (2024-05-15) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.5...v3.9.0-beta.6) (2024-05-15) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.4...v3.9.0-beta.5) (2024-05-14) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.3...v3.9.0-beta.4) (2024-05-14) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.2...v3.9.0-beta.3) (2024-05-08) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.1...v3.9.0-beta.2) (2024-05-06) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.0...v3.9.0-beta.1) (2024-05-06) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.9.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.94...v3.9.0-beta.0) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.8.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0-beta.94) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + +# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18) + +**Note:** Version bump only for package @ohif/extension-dicom-pdf + + + + + # [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17) **Note:** Version bump only for package @ohif/extension-dicom-pdf diff --git a/extensions/dicom-pdf/package.json b/extensions/dicom-pdf/package.json index 5ce9e47e8c..fb11f44ed7 100644 --- a/extensions/dicom-pdf/package.json +++ b/extensions/dicom-pdf/package.json @@ -1,6 +1,6 @@ { "name": "@ohif/extension-dicom-pdf", - "version": "3.8.0-beta.82", + "version": "3.9.0-beta.71", "description": "OHIF extension for PDF display", "author": "OHIF", "license": "MIT", @@ -30,13 +30,13 @@ "test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests" }, "peerDependencies": { - "@ohif/core": "3.8.0-beta.82", - "@ohif/ui": "3.8.0-beta.82", - "dcmjs": "^0.29.12", + "@ohif/core": "3.9.0-beta.71", + "@ohif/ui": "3.9.0-beta.71", + "dcmjs": "*", "dicom-parser": "^1.8.9", "hammerjs": "^2.0.8", "prop-types": "^15.6.2", - "react": "^17.0.2" + "react": "^18.3.1" }, "dependencies": { "@babel/runtime": "^7.20.13", diff --git a/extensions/dicom-pdf/src/getSopClassHandlerModule.js b/extensions/dicom-pdf/src/getSopClassHandlerModule.js index 8e7e902525..e0ef0e255a 100644 --- a/extensions/dicom-pdf/src/getSopClassHandlerModule.js +++ b/extensions/dicom-pdf/src/getSopClassHandlerModule.js @@ -12,7 +12,7 @@ const sopClassUids = Object.values(SOP_CLASS_UIDS); const _getDisplaySetsFromSeries = (instances, servicesManager, extensionManager) => { const dataSource = extensionManager.getActiveDataSource()[0]; return instances.map(instance => { - const { Modality, SOPInstanceUID, EncapsulatedDocument } = instance; + const { Modality, SOPInstanceUID } = instance; const { SeriesDescription = 'PDF', MIMETypeOfEncapsulatedDocument } = instance; const { SeriesNumber, SeriesDate, SeriesInstanceUID, StudyInstanceUID, SOPClassUID } = instance; const pdfUrl = dataSource.retrieve.directURL({ diff --git a/extensions/dicom-pdf/src/viewports/OHIFCornerstonePdfViewport.css b/extensions/dicom-pdf/src/viewports/OHIFCornerstonePdfViewport.css new file mode 100644 index 0000000000..1837c21922 --- /dev/null +++ b/extensions/dicom-pdf/src/viewports/OHIFCornerstonePdfViewport.css @@ -0,0 +1,11 @@ +.pdf-no-click { + pointer-events: none; + height: 100%; + width: 100%; +} + +.pdf-yes-click { + pointer-events: auto; + height: 100%; + width: 100%; +} diff --git a/extensions/dicom-pdf/src/viewports/OHIFCornerstonePdfViewport.tsx b/extensions/dicom-pdf/src/viewports/OHIFCornerstonePdfViewport.tsx index e4e2bac4bb..8c60fd92ac 100644 --- a/extensions/dicom-pdf/src/viewports/OHIFCornerstonePdfViewport.tsx +++ b/extensions/dicom-pdf/src/viewports/OHIFCornerstonePdfViewport.tsx @@ -1,9 +1,27 @@ import React, { useEffect, useState } from 'react'; import PropTypes from 'prop-types'; +import './OHIFCornerstonePdfViewport.css'; function OHIFCornerstonePdfViewport({ displaySets }) { const [url, setUrl] = useState(null); + useEffect(() => { + document.body.addEventListener('drag', makePdfDropTarget); + return function cleanup() { + document.body.removeEventListener('drag', makePdfDropTarget); + }; + }, []); + + const [style, setStyle] = useState('pdf-yes-click'); + + const makePdfScrollable = () => { + setStyle('pdf-yes-click'); + }; + + const makePdfDropTarget = () => { + setStyle('pdf-no-click'); + }; + if (displaySets && displaySets.length > 1) { throw new Error( 'OHIFCornerstonePdfViewport: only one display set is supported for dicom pdf right now' @@ -21,11 +39,14 @@ function OHIFCornerstonePdfViewport({ displaySets }) { }, [pdfUrl]); return ( -
+
No online PDF viewer installed
diff --git a/extensions/dicom-video/CHANGELOG.md b/extensions/dicom-video/CHANGELOG.md index 358a20df61..f9fa0580d6 100644 --- a/extensions/dicom-video/CHANGELOG.md +++ b/extensions/dicom-video/CHANGELOG.md @@ -3,6 +3,687 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.9.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.70...v3.9.0-beta.71) (2024-07-30) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.69...v3.9.0-beta.70) (2024-07-30) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.68...v3.9.0-beta.69) (2024-07-27) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.67...v3.9.0-beta.68) (2024-07-26) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.66...v3.9.0-beta.67) (2024-07-26) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.65...v3.9.0-beta.66) (2024-07-24) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.64...v3.9.0-beta.65) (2024-07-23) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.63...v3.9.0-beta.64) (2024-07-19) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.62...v3.9.0-beta.63) (2024-07-10) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.61...v3.9.0-beta.62) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.60...v3.9.0-beta.61) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.59...v3.9.0-beta.60) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.58...v3.9.0-beta.59) (2024-07-05) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.57...v3.9.0-beta.58) (2024-07-04) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.56...v3.9.0-beta.57) (2024-07-02) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.55...v3.9.0-beta.56) (2024-07-02) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.54...v3.9.0-beta.55) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.53...v3.9.0-beta.54) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.52...v3.9.0-beta.53) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.51...v3.9.0-beta.52) (2024-06-27) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.50...v3.9.0-beta.51) (2024-06-27) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.49...v3.9.0-beta.50) (2024-06-26) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.48...v3.9.0-beta.49) (2024-06-26) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.47...v3.9.0-beta.48) (2024-06-25) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.46...v3.9.0-beta.47) (2024-06-21) + + +### Bug Fixes + +* Allow the mode setup/creation to be async, and provide a few more values to extension/app config/mode setup. ([#4016](https://github.com/OHIF/Viewers/issues/4016)) ([88575c6](https://github.com/OHIF/Viewers/commit/88575c6c09fd778a31b2f91524163ce65d1639dd)) + + + + + +# [3.9.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.45...v3.9.0-beta.46) (2024-06-18) + + +### Bug Fixes + +* Use correct external URL for rendered responses with relative URI ([#4236](https://github.com/OHIF/Viewers/issues/4236)) ([d8f6991](https://github.com/OHIF/Viewers/commit/d8f6991dbe72465080cfc5de39c7ea225702f2e0)) + + + + + +# [3.9.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.44...v3.9.0-beta.45) (2024-06-18) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.43...v3.9.0-beta.44) (2024-06-17) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.42...v3.9.0-beta.43) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.41...v3.9.0-beta.42) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.40...v3.9.0-beta.41) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.39...v3.9.0-beta.40) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.38...v3.9.0-beta.39) (2024-06-08) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.37...v3.9.0-beta.38) (2024-06-07) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.36...v3.9.0-beta.37) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.35...v3.9.0-beta.36) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.34...v3.9.0-beta.35) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.33...v3.9.0-beta.34) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.32...v3.9.0-beta.33) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.31...v3.9.0-beta.32) (2024-05-31) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.30...v3.9.0-beta.31) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.29...v3.9.0-beta.30) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.28...v3.9.0-beta.29) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.27...v3.9.0-beta.28) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.26...v3.9.0-beta.27) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.25...v3.9.0-beta.26) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.24...v3.9.0-beta.25) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.23...v3.9.0-beta.24) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.22...v3.9.0-beta.23) (2024-05-28) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.21...v3.9.0-beta.22) (2024-05-27) + + +### Features + +* **ui:** move to React 18 and base for using shadcn/ui ([#4174](https://github.com/OHIF/Viewers/issues/4174)) ([70f2c79](https://github.com/OHIF/Viewers/commit/70f2c797f42af603d7ea0eb8d23b4103aba66f77)) + + + + + +# [3.9.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.20...v3.9.0-beta.21) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.19...v3.9.0-beta.20) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.18...v3.9.0-beta.19) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.17...v3.9.0-beta.18) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.16...v3.9.0-beta.17) (2024-05-23) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.15...v3.9.0-beta.16) (2024-05-23) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.14...v3.9.0-beta.15) (2024-05-22) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.13...v3.9.0-beta.14) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.12...v3.9.0-beta.13) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.11...v3.9.0-beta.12) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.10...v3.9.0-beta.11) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.9...v3.9.0-beta.10) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.8...v3.9.0-beta.9) (2024-05-17) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.7...v3.9.0-beta.8) (2024-05-16) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.6...v3.9.0-beta.7) (2024-05-15) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.5...v3.9.0-beta.6) (2024-05-15) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.4...v3.9.0-beta.5) (2024-05-14) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.3...v3.9.0-beta.4) (2024-05-14) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.2...v3.9.0-beta.3) (2024-05-08) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.1...v3.9.0-beta.2) (2024-05-06) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.0...v3.9.0-beta.1) (2024-05-06) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.9.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.94...v3.9.0-beta.0) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.8.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0-beta.94) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + +# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18) + +**Note:** Version bump only for package @ohif/extension-dicom-video + + + + + # [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17) **Note:** Version bump only for package @ohif/extension-dicom-video diff --git a/extensions/dicom-video/package.json b/extensions/dicom-video/package.json index 26b93b6773..669b32ed00 100644 --- a/extensions/dicom-video/package.json +++ b/extensions/dicom-video/package.json @@ -1,6 +1,6 @@ { "name": "@ohif/extension-dicom-video", - "version": "3.8.0-beta.82", + "version": "3.9.0-beta.71", "description": "OHIF extension for video display", "author": "OHIF", "license": "MIT", @@ -30,13 +30,13 @@ "test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests" }, "peerDependencies": { - "@ohif/core": "3.8.0-beta.82", - "@ohif/ui": "3.8.0-beta.82", - "dcmjs": "^0.29.12", + "@ohif/core": "3.9.0-beta.71", + "@ohif/ui": "3.9.0-beta.71", + "dcmjs": "*", "dicom-parser": "^1.8.9", "hammerjs": "^2.0.8", "prop-types": "^15.6.2", - "react": "^17.0.2" + "react": "^18.3.1" }, "dependencies": { "@babel/runtime": "^7.20.13", diff --git a/extensions/dicom-video/src/getSopClassHandlerModule.js b/extensions/dicom-video/src/getSopClassHandlerModule.js index 5b0a2162e3..e2db17632b 100644 --- a/extensions/dicom-video/src/getSopClassHandlerModule.js +++ b/extensions/dicom-video/src/getSopClassHandlerModule.js @@ -53,6 +53,12 @@ const _getDisplaySetsFromSeries = (instances, servicesManager, extensionManager) const { Modality, SOPInstanceUID, SeriesDescription = 'VIDEO' } = instance; const { SeriesNumber, SeriesDate, SeriesInstanceUID, StudyInstanceUID, NumberOfFrames, url } = instance; + const videoUrl = dataSource.retrieve.directURL({ + instance, + singlepart: 'video', + tag: 'PixelData', + url, + }); const displaySet = { //plugin: id, Modality, @@ -66,12 +72,7 @@ const _getDisplaySetsFromSeries = (instances, servicesManager, extensionManager) SOPClassHandlerId, referencedImages: null, measurements: null, - videoUrl: dataSource.retrieve.directURL({ - instance, - singlepart: 'video', - tag: 'PixelData', - url, - }), + videoUrl, instances: [instance], thumbnailSrc: dataSource.retrieve.directURL({ instance, diff --git a/extensions/measurement-tracking/CHANGELOG.md b/extensions/measurement-tracking/CHANGELOG.md index b54111e1aa..de4ce2cf0f 100644 --- a/extensions/measurement-tracking/CHANGELOG.md +++ b/extensions/measurement-tracking/CHANGELOG.md @@ -3,6 +3,759 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.9.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.70...v3.9.0-beta.71) (2024-07-30) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.69...v3.9.0-beta.70) (2024-07-30) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.68...v3.9.0-beta.69) (2024-07-27) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.67...v3.9.0-beta.68) (2024-07-26) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.66...v3.9.0-beta.67) (2024-07-26) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.65...v3.9.0-beta.66) (2024-07-24) + + +### Features + +* **pmap:** added support for parametric map ([#4284](https://github.com/OHIF/Viewers/issues/4284)) ([fc0064f](https://github.com/OHIF/Viewers/commit/fc0064fd9d8cdc8fde81b81f0e71fd5d077ca22b)) + + + + + +# [3.9.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.64...v3.9.0-beta.65) (2024-07-23) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.63...v3.9.0-beta.64) (2024-07-19) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.62...v3.9.0-beta.63) (2024-07-10) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.61...v3.9.0-beta.62) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.60...v3.9.0-beta.61) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.59...v3.9.0-beta.60) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.58...v3.9.0-beta.59) (2024-07-05) + + +### Bug Fixes + +* Cobb angle not working in basic-test mode and open contour ([#4280](https://github.com/OHIF/Viewers/issues/4280)) ([6fd3c7e](https://github.com/OHIF/Viewers/commit/6fd3c7e293fec851dd30e650c1347cc0bc7a99ee)) +* webpack import bugs showing warnings on import ([#4265](https://github.com/OHIF/Viewers/issues/4265)) ([24c511f](https://github.com/OHIF/Viewers/commit/24c511f4bc04c4143bbd3d0d48029f41f7f36014)) + + +### Features + +* Add interleaved HTJ2K and volume progressive loading ([#4276](https://github.com/OHIF/Viewers/issues/4276)) ([a2084f3](https://github.com/OHIF/Viewers/commit/a2084f319b731d98b59485799fb80357094f8c38)) + + + + + +# [3.9.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.57...v3.9.0-beta.58) (2024-07-04) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.56...v3.9.0-beta.57) (2024-07-02) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.55...v3.9.0-beta.56) (2024-07-02) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.54...v3.9.0-beta.55) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.53...v3.9.0-beta.54) (2024-06-28) + + +### Features + +* **studyPrefetcher:** Study Prefetcher ([#4206](https://github.com/OHIF/Viewers/issues/4206)) ([2048b19](https://github.com/OHIF/Viewers/commit/2048b19484c0b1fae73f993cfaa814f861bbd230)) + + + + + +# [3.9.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.52...v3.9.0-beta.53) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.51...v3.9.0-beta.52) (2024-06-27) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.50...v3.9.0-beta.51) (2024-06-27) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.49...v3.9.0-beta.50) (2024-06-26) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.48...v3.9.0-beta.49) (2024-06-26) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.47...v3.9.0-beta.48) (2024-06-25) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.46...v3.9.0-beta.47) (2024-06-21) + + +### Bug Fixes + +* Allow the mode setup/creation to be async, and provide a few more values to extension/app config/mode setup. ([#4016](https://github.com/OHIF/Viewers/issues/4016)) ([88575c6](https://github.com/OHIF/Viewers/commit/88575c6c09fd778a31b2f91524163ce65d1639dd)) +* **studybrowser:** Differentiate recent and all in study panel based on a provided time period ([#4242](https://github.com/OHIF/Viewers/issues/4242)) ([6f93449](https://github.com/OHIF/Viewers/commit/6f9344914951c204feaff48aaeb43cd7d727623d)) + + +### Features + +* **sort:** custom series sort in study panel ([#4214](https://github.com/OHIF/Viewers/issues/4214)) ([a433d40](https://github.com/OHIF/Viewers/commit/a433d406e2cac13f644203996c682260b54e8865)) + + + + + +# [3.9.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.45...v3.9.0-beta.46) (2024-06-18) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.44...v3.9.0-beta.45) (2024-06-18) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.43...v3.9.0-beta.44) (2024-06-17) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.42...v3.9.0-beta.43) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.41...v3.9.0-beta.42) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.40...v3.9.0-beta.41) (2024-06-12) + + +### Features + +* Add customization merge, append or replace functionality ([#3871](https://github.com/OHIF/Viewers/issues/3871)) ([55dcfa1](https://github.com/OHIF/Viewers/commit/55dcfa1f6994a7036e7e594efb23673382a41915)) + + + + + +# [3.9.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.39...v3.9.0-beta.40) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.38...v3.9.0-beta.39) (2024-06-08) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.37...v3.9.0-beta.38) (2024-06-07) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.36...v3.9.0-beta.37) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.35...v3.9.0-beta.36) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.34...v3.9.0-beta.35) (2024-06-05) + + +### Bug Fixes + +* **seg:** maintain algorithm name and algorithm type when DICOM seg is exported or downloaded ([#4203](https://github.com/OHIF/Viewers/issues/4203)) ([a29e94d](https://github.com/OHIF/Viewers/commit/a29e94de803f79bbb3372d00ad8eb14b4224edc2)) + + + + + +# [3.9.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.33...v3.9.0-beta.34) (2024-06-05) + + +### Bug Fixes + +* **hydration:** Maintain the same slice that the user was on pre hydration in post hydration for SR and SEG. ([#4200](https://github.com/OHIF/Viewers/issues/4200)) ([430330f](https://github.com/OHIF/Viewers/commit/430330f7e384d503cb6fc695a7a9642ddfaac313)) + + + + + +# [3.9.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.32...v3.9.0-beta.33) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.31...v3.9.0-beta.32) (2024-05-31) + + +### Bug Fixes + +* **tmtv:** crosshairs should not have viewport indicators ([#4197](https://github.com/OHIF/Viewers/issues/4197)) ([f85da32](https://github.com/OHIF/Viewers/commit/f85da32f34389ef7cecae03c07e0af26468b52a6)) + + + + + +# [3.9.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.30...v3.9.0-beta.31) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.29...v3.9.0-beta.30) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.28...v3.9.0-beta.29) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.27...v3.9.0-beta.28) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.26...v3.9.0-beta.27) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.25...v3.9.0-beta.26) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.24...v3.9.0-beta.25) (2024-05-29) + + +### Bug Fixes + +* **ultrasound:** Upgrade cornerstone3D version to resolve coloring issues ([#4181](https://github.com/OHIF/Viewers/issues/4181)) ([75a71db](https://github.com/OHIF/Viewers/commit/75a71db7f89840250ad1c2b35df5a35aceb8be7d)) + + + + + +# [3.9.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.23...v3.9.0-beta.24) (2024-05-29) + + +### Features + +* **measurements:** show untracked measurements in measurement panel under additional findings ([#4160](https://github.com/OHIF/Viewers/issues/4160)) ([18686c2](https://github.com/OHIF/Viewers/commit/18686c2caf13ede3e881303100bd4cc34b8b135f)) + + + + + +# [3.9.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.22...v3.9.0-beta.23) (2024-05-28) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.21...v3.9.0-beta.22) (2024-05-27) + + +### Features + +* **ui:** move to React 18 and base for using shadcn/ui ([#4174](https://github.com/OHIF/Viewers/issues/4174)) ([70f2c79](https://github.com/OHIF/Viewers/commit/70f2c797f42af603d7ea0eb8d23b4103aba66f77)) + + + + + +# [3.9.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.20...v3.9.0-beta.21) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.19...v3.9.0-beta.20) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.18...v3.9.0-beta.19) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.17...v3.9.0-beta.18) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.16...v3.9.0-beta.17) (2024-05-23) + + +### Bug Fixes + +* **crosshairs:** reset angle, position, and slabthickness for crosshairs when reset viewport tool is used ([#4113](https://github.com/OHIF/Viewers/issues/4113)) ([73d9e99](https://github.com/OHIF/Viewers/commit/73d9e99d5d6f38ab6c36f4471d54f18798feacb4)) + + + + + +# [3.9.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.15...v3.9.0-beta.16) (2024-05-23) + + +### Bug Fixes + +* dicom json for orthanc by Update package versions for [@cornerstonejs](https://github.com/cornerstonejs) dependencies ([#4165](https://github.com/OHIF/Viewers/issues/4165)) ([34c7d72](https://github.com/OHIF/Viewers/commit/34c7d72142847486b98c9c52469940083eeaf87e)) + + + + + +# [3.9.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.14...v3.9.0-beta.15) (2024-05-22) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.13...v3.9.0-beta.14) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.12...v3.9.0-beta.13) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.11...v3.9.0-beta.12) (2024-05-21) + + +### Bug Fixes + +* **segmentation:** Address issue where segmentation creation failed on layout change ([#4153](https://github.com/OHIF/Viewers/issues/4153)) ([29944c8](https://github.com/OHIF/Viewers/commit/29944c8512c35718af03c03ef82bc43675ee1872)) + + + + + +# [3.9.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.10...v3.9.0-beta.11) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.9...v3.9.0-beta.10) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.8...v3.9.0-beta.9) (2024-05-17) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.7...v3.9.0-beta.8) (2024-05-16) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.6...v3.9.0-beta.7) (2024-05-15) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.5...v3.9.0-beta.6) (2024-05-15) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.4...v3.9.0-beta.5) (2024-05-14) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.3...v3.9.0-beta.4) (2024-05-14) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.9.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.2...v3.9.0-beta.3) (2024-05-08) + + +### Features + +* **typings:** Enhance typing support with withAppTypes and custom services throughout OHIF ([#4090](https://github.com/OHIF/Viewers/issues/4090)) ([374065b](https://github.com/OHIF/Viewers/commit/374065bc3bad9d212f9817a8d41546cc64cfabfb)) + + + + + +# [3.9.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.1...v3.9.0-beta.2) (2024-05-06) + + +### Bug Fixes + +* **bugs:** enhancements and bugs in several areas ([#4086](https://github.com/OHIF/Viewers/issues/4086)) ([730f434](https://github.com/OHIF/Viewers/commit/730f4349100f21b4489a21707dbb2dca9dbfbba2)) + + + + + +# [3.9.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.0...v3.9.0-beta.1) (2024-05-06) + + +### Bug Fixes + +* **rt:** enhanced RT support, utilize SVGs for rendering. ([#4074](https://github.com/OHIF/Viewers/issues/4074)) ([0156bc4](https://github.com/OHIF/Viewers/commit/0156bc426f1840ae0d090223e94a643726e856cb)) + + + + + +# [3.9.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.94...v3.9.0-beta.0) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.8.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0-beta.94) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29) + + +### Bug Fixes + +* **toolbox:** Preserve user-specified tool state and streamline command execution ([#4063](https://github.com/OHIF/Viewers/issues/4063)) ([f1a736d](https://github.com/OHIF/Viewers/commit/f1a736d1934733a434cb87b2c284907a3122403f)) + + + + + +# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28) + + +### Bug Fixes + +* **bugs:** fix patient header for doc, track ball rotate resize observer and add segmentation button not being enabled on viewport data change ([#4068](https://github.com/OHIF/Viewers/issues/4068)) ([c09311d](https://github.com/OHIF/Viewers/commit/c09311d3b7df05fcd00a9f36a7233e9d7e5589d0)) + + + + + +# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22) + + +### Bug Fixes + +* **viewport-webworker-segmentation:** Resolve issues with viewport detection, webworker termination, and segmentation panel layout change ([#4059](https://github.com/OHIF/Viewers/issues/4059)) ([52a0c59](https://github.com/OHIF/Viewers/commit/52a0c59294a4161fcca0a6708855549034849951)) + + + + + +# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19) + + +### Features + +* **tmtv-mode:** Add Brush tools and move SUV peak calculation to web worker ([#4053](https://github.com/OHIF/Viewers/issues/4053)) ([8192e34](https://github.com/OHIF/Viewers/commit/8192e348eca993fec331d4963efe88f9a730eceb)) + + + + + +# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19) + + +### Bug Fixes + +* **layouts:** and fix thumbnail in touch and update migration guide for 3.8 release ([#4052](https://github.com/OHIF/Viewers/issues/4052)) ([d250d04](https://github.com/OHIF/Viewers/commit/d250d04580883446fcb8d748b2a97c5c198922af)) + + + + + +# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18) + +**Note:** Version bump only for package @ohif/extension-measurement-tracking + + + + + +# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18) + + +### Bug Fixes + +* **bugs:** enhancements and bug fixes - final ([#4048](https://github.com/OHIF/Viewers/issues/4048)) ([170bb96](https://github.com/OHIF/Viewers/commit/170bb96983082c39b22b7352e0c54aacf3e73b02)) + + + + + # [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17) **Note:** Version bump only for package @ohif/extension-measurement-tracking diff --git a/extensions/measurement-tracking/package.json b/extensions/measurement-tracking/package.json index 609d377118..174f337826 100644 --- a/extensions/measurement-tracking/package.json +++ b/extensions/measurement-tracking/package.json @@ -1,6 +1,6 @@ { "name": "@ohif/extension-measurement-tracking", - "version": "3.8.0-beta.82", + "version": "3.9.0-beta.71", "description": "Tracking features and functionality for basic image viewing", "author": "OHIF Core Team", "license": "MIT", @@ -32,23 +32,23 @@ "start": "yarn run dev" }, "peerDependencies": { - "@cornerstonejs/core": "^1.70.6", - "@cornerstonejs/tools": "^1.70.6", - "@ohif/core": "3.8.0-beta.82", - "@ohif/extension-cornerstone-dicom-sr": "3.8.0-beta.82", - "@ohif/ui": "3.8.0-beta.82", + "@cornerstonejs/core": "^1.82.0", + "@cornerstonejs/tools": "^1.82.0", + "@ohif/core": "3.9.0-beta.71", + "@ohif/extension-cornerstone-dicom-sr": "3.9.0-beta.71", + "@ohif/ui": "3.9.0-beta.71", "classnames": "^2.3.2", - "dcmjs": "^0.29.12", - "lodash.debounce": "^4.17.21", + "dcmjs": "*", + "lodash.debounce": "^4.0.8", "prop-types": "^15.6.2", - "react": "^17.0.2", - "react-dom": "^17.0.2", - "webpack": "^5.50.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "webpack": "5.89.0", "webpack-merge": "^5.7.3" }, "dependencies": { "@babel/runtime": "^7.20.13", - "@ohif/ui": "3.8.0-beta.82", + "@ohif/ui": "3.9.0-beta.71", "@xstate/react": "^3.2.2", "xstate": "^4.10.0" } diff --git a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/TrackedMeasurementsContext.tsx b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/TrackedMeasurementsContext.tsx index 74657e85d4..7e89712ee7 100644 --- a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/TrackedMeasurementsContext.tsx +++ b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/TrackedMeasurementsContext.tsx @@ -24,14 +24,19 @@ const SR_SOPCLASSHANDLERID = '@ohif/extension-cornerstone-dicom-sr.sopClassHandl * @param {*} param0 */ function TrackedMeasurementsContextProvider( - { servicesManager, commandsManager, extensionManager }, // Bound by consumer + { servicesManager, commandsManager, extensionManager }: withAppTypes, // Bound by consumer { children } // Component props ) { const [appConfig] = useAppConfig(); const [viewportGrid, viewportGridService] = useViewportGrid(); const { activeViewportId, viewports } = viewportGrid; - const { measurementService, displaySetService, customizationService } = servicesManager.services; + const { + measurementService, + displaySetService, + customizationService, + cornerstoneViewportService, + } = servicesManager.services; const machineOptions = Object.assign({}, defaultOptions); machineOptions.actions = Object.assign({}, machineOptions.actions, { @@ -81,6 +86,29 @@ function TrackedMeasurementsContextProvider( }, }); }, + + jumpToSameImageInActiveViewport: (ctx, evt) => { + const { trackedStudy, trackedSeries, activeViewportId } = ctx; + const measurements = measurementService.getMeasurements(); + const trackedMeasurements = measurements.filter( + m => trackedStudy === m.referenceStudyUID && trackedSeries.includes(m.referenceSeriesUID) + ); + + const trackedMeasurement = trackedMeasurements[0]; + const referencedDisplaySetUID = trackedMeasurement.displaySetInstanceUID; + const viewport = cornerstoneViewportService.getCornerstoneViewport(activeViewportId); + const imageIndex = viewport.getCurrentImageIdIndex(); + + viewportGridService.setDisplaySetsForViewport({ + viewportId: activeViewportId, + displaySetInstanceUIDs: [referencedDisplaySetUID], + viewportOptions: { + initialImageOptions: { + index: imageIndex, + }, + }, + }); + }, showStructuredReportDisplaySetInActiveViewport: (ctx, evt) => { if (evt.data.createdDisplaySetInstanceUIDs.length > 0) { const StructuredReportDisplaySetInstanceUID = evt.data.createdDisplaySetInstanceUIDs[0]; diff --git a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/hydrateStructuredReport.tsx b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/hydrateStructuredReport.tsx index 480b333106..caf57c2e88 100644 --- a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/hydrateStructuredReport.tsx +++ b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/hydrateStructuredReport.tsx @@ -1,6 +1,10 @@ import { hydrateStructuredReport as baseHydrateStructuredReport } from '@ohif/extension-cornerstone-dicom-sr'; -function hydrateStructuredReport({ servicesManager, extensionManager, appConfig }, ctx, evt) { +function hydrateStructuredReport( + { servicesManager, extensionManager, appConfig }: withAppTypes, + ctx, + evt +) { const { displaySetService } = servicesManager.services; const { viewportId, displaySetInstanceUID } = evt; const srDisplaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID); diff --git a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/measurementTrackingMachine.js b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/measurementTrackingMachine.js index fce9930d30..d53408e3ca 100644 --- a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/measurementTrackingMachine.js +++ b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/measurementTrackingMachine.js @@ -250,7 +250,7 @@ const machineConfiguration = { target: 'tracking', actions: [ 'setTrackedStudyAndMultipleSeries', - 'jumpToFirstMeasurementInActiveViewport', + 'jumpToSameImageInActiveViewport', 'setIsDirtyToClean', ], cond: 'shouldHydrateStructuredReport', @@ -274,7 +274,7 @@ const machineConfiguration = { target: 'tracking', actions: [ 'setTrackedStudyAndMultipleSeries', - 'jumpToFirstMeasurementInActiveViewport', + 'jumpToSameImageInActiveViewport', 'setIsDirtyToClean', ], }, diff --git a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptBeginTracking.js b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptBeginTracking.js index d8bb02b996..2638206e68 100644 --- a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptBeginTracking.js +++ b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptBeginTracking.js @@ -11,12 +11,15 @@ const RESPONSE = { function promptBeginTracking({ servicesManager, extensionManager }, ctx, evt) { const { uiViewportDialogService } = servicesManager.services; + const appConfig = extensionManager._appConfig; // When the state change happens after a promise, the state machine sends the retult in evt.data; // In case of direct transition to the state, the state machine sends the data in evt; const { viewportId, StudyInstanceUID, SeriesInstanceUID } = evt.data || evt; return new Promise(async function (resolve, reject) { - let promptResult = await _askTrackMeasurements(uiViewportDialogService, viewportId); + let promptResult = appConfig?.disableConfirmationPrompts + ? RESPONSE.SET_STUDY_AND_SERIES + : await _askTrackMeasurements(uiViewportDialogService, viewportId); resolve({ userResponse: promptResult, diff --git a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptHydrateStructuredReport.js b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptHydrateStructuredReport.js index 579ff9c7b3..2f26970169 100644 --- a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptHydrateStructuredReport.js +++ b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptHydrateStructuredReport.js @@ -15,9 +15,10 @@ function promptHydrateStructuredReport({ servicesManager, extensionManager, appC const { uiViewportDialogService, displaySetService } = servicesManager.services; const { viewportId, displaySetInstanceUID } = evt; const srDisplaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID); - return new Promise(async function (resolve, reject) { - const promptResult = await _askTrackMeasurements(uiViewportDialogService, viewportId); + const promptResult = appConfig?.disableConfirmationPrompts + ? RESPONSE.HYDRATE_REPORT + : await _askTrackMeasurements(uiViewportDialogService, viewportId); // Need to do action here... So we can set state... let StudyInstanceUID, SeriesInstanceUIDs; @@ -49,11 +50,13 @@ function _askTrackMeasurements(uiViewportDialogService, viewportId) { const message = 'Do you want to continue tracking measurements for this study?'; const actions = [ { + id: 'no-hydrate', type: ButtonEnums.type.secondary, text: 'No', value: RESPONSE.CANCEL, }, { + id: 'yes-hydrate', type: ButtonEnums.type.primary, text: 'Yes', value: RESPONSE.HYDRATE_REPORT, diff --git a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptSaveReport.js b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptSaveReport.js index 1719c56dd3..3e98bcb2bb 100644 --- a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptSaveReport.js +++ b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptSaveReport.js @@ -2,7 +2,7 @@ import { createReportAsync, createReportDialogPrompt } from '@ohif/extension-def import getNextSRSeriesNumber from '../../_shared/getNextSRSeriesNumber'; import RESPONSE from '../../_shared/PROMPT_RESPONSES'; -function promptSaveReport({ servicesManager, commandsManager, extensionManager }, ctx, evt) { +async function promptSaveReport({ servicesManager, commandsManager, extensionManager }, ctx, evt) { const { uiDialogService, measurementService, displaySetService } = servicesManager.services; const viewportId = evt.viewportId === undefined ? evt.data.viewportId : evt.viewportId; const isBackupSave = evt.isBackupSave === undefined ? evt.data.isBackupSave : evt.isBackupSave; @@ -12,8 +12,7 @@ function promptSaveReport({ servicesManager, commandsManager, extensionManager } const { trackedStudy, trackedSeries } = ctx; let displaySetInstanceUIDs; - return new Promise(async function (resolve, reject) { - // TODO: Fallback if (uiDialogService) { + try { const promptResult = await createReportDialogPrompt(uiDialogService, { extensionManager, }); @@ -22,9 +21,11 @@ function promptSaveReport({ servicesManager, commandsManager, extensionManager } const dataSources = extensionManager.getDataSources(); const dataSource = dataSources[0]; const measurements = measurementService.getMeasurements(); - const trackedMeasurements = measurements.filter( - m => trackedStudy === m.referenceStudyUID && trackedSeries.includes(m.referenceSeriesUID) - ); + const trackedMeasurements = measurements + .filter( + m => trackedStudy === m.referenceStudyUID && trackedSeries.includes(m.referenceSeriesUID) + ) + .filter(m => m.referencedImageId != null); const SeriesDescription = // isUndefinedOrEmpty @@ -57,15 +58,17 @@ function promptSaveReport({ servicesManager, commandsManager, extensionManager } // Do nothing } - resolve({ + return { userResponse: promptResult.action, createdDisplaySetInstanceUIDs: displaySetInstanceUIDs, StudyInstanceUID, SeriesInstanceUID, viewportId, isBackupSave, - }); - }); + }; + } catch (error) { + return null; + } } export default promptSaveReport; diff --git a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptTrackNewStudy.js b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptTrackNewStudy.ts similarity index 86% rename from extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptTrackNewStudy.js rename to extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptTrackNewStudy.ts index b590af3f69..1ce5869998 100644 --- a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptTrackNewStudy.js +++ b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptTrackNewStudy.ts @@ -9,18 +9,18 @@ const RESPONSE = { NO_NOT_FOR_SERIES: 4, }; -function promptTrackNewStudy({ servicesManager, extensionManager }, ctx, evt) { - const { UIViewportDialogService } = servicesManager.services; +function promptTrackNewStudy({ servicesManager, extensionManager }: withAppTypes, ctx, evt) { + const { uiViewportDialogService } = servicesManager.services; // When the state change happens after a promise, the state machine sends the retult in evt.data; // In case of direct transition to the state, the state machine sends the data in evt; const { viewportId, StudyInstanceUID, SeriesInstanceUID } = evt.data || evt; return new Promise(async function (resolve, reject) { - let promptResult = await _askTrackMeasurements(UIViewportDialogService, viewportId); + let promptResult = await _askTrackMeasurements(uiViewportDialogService, viewportId); if (promptResult === RESPONSE.SET_STUDY_AND_SERIES) { promptResult = ctx.isDirty - ? await _askSaveDiscardOrCancel(UIViewportDialogService, viewportId) + ? await _askSaveDiscardOrCancel(uiViewportDialogService, viewportId) : RESPONSE.SET_STUDY_AND_SERIES; } @@ -34,7 +34,10 @@ function promptTrackNewStudy({ servicesManager, extensionManager }, ctx, evt) { }); } -function _askTrackMeasurements(UIViewportDialogService, viewportId) { +function _askTrackMeasurements( + UIViewportDialogService: AppTypes.UIViewportDialogService, + viewportId +) { return new Promise(function (resolve, reject) { const message = i18n.t('MeasurementTable:Track measurements for this series?'); const actions = [ @@ -75,7 +78,10 @@ function _askTrackMeasurements(UIViewportDialogService, viewportId) { }); } -function _askSaveDiscardOrCancel(UIViewportDialogService, viewportId) { +function _askSaveDiscardOrCancel( + UIViewportDialogService: AppTypes.UIViewportDialogService, + viewportId +) { return new Promise(function (resolve, reject) { const message = 'Measurements cannot span across multiple studies. Do you want to save your tracked measurements?'; diff --git a/extensions/measurement-tracking/src/panels/PanelMeasurementTableTracking/index.tsx b/extensions/measurement-tracking/src/panels/PanelMeasurementTableTracking/index.tsx index 6d7fbf31d2..6ab9b41345 100644 --- a/extensions/measurement-tracking/src/panels/PanelMeasurementTableTracking/index.tsx +++ b/extensions/measurement-tracking/src/panels/PanelMeasurementTableTracking/index.tsx @@ -18,7 +18,7 @@ const DISPLAY_STUDY_SUMMARY_INITIAL_VALUE = { description: '', // 'CHEST/ABD/PELVIS W CONTRAST', }; -function PanelMeasurementTableTracking({ servicesManager, extensionManager }) { +function PanelMeasurementTableTracking({ servicesManager, extensionManager }: withAppTypes) { const [viewportGrid] = useViewportGrid(); const { t } = useTranslation('MeasurementTable'); const [measurementChangeTimestamp, setMeasurementsUpdated] = useState(Date.now().toString()); @@ -161,14 +161,18 @@ function PanelMeasurementTableTracking({ servicesManager, extensionManager }) { }; const displayMeasurementsWithoutFindings = displayMeasurements.filter( - dm => dm.measurementType !== measurementService.VALUE_TYPES.POINT + dm => dm.measurementType !== measurementService.VALUE_TYPES.POINT && dm.referencedImageId ); const additionalFindings = displayMeasurements.filter( - dm => dm.measurementType === measurementService.VALUE_TYPES.POINT + dm => dm.measurementType === measurementService.VALUE_TYPES.POINT && dm.referencedImageId ); + const nonAcquisitionMeasurements = displayMeasurements.filter(dm => dm.referencedImageId == null); + const disabled = - additionalFindings.length === 0 && displayMeasurementsWithoutFindings.length === 0; + additionalFindings.length === 0 && + displayMeasurementsWithoutFindings.length === 0 && + nonAcquisitionMeasurements.length === 0; return ( <> @@ -200,6 +204,15 @@ function PanelMeasurementTableTracking({ servicesManager, extensionManager }) { onEdit={onMeasurementItemEditHandler} /> )} + {nonAcquisitionMeasurements.length !== 0 && ( + + )}
{!appConfig?.disableEditing && (
@@ -207,7 +220,7 @@ function PanelMeasurementTableTracking({ servicesManager, extensionManager }) { t={t} actions={[ { - label: 'Export', + label: 'Download CSV', onClick: exportReport, }, { @@ -266,6 +279,7 @@ function _mapMeasurementToDisplay(measurement, types, displaySetService) { selected, findingSites, finding, + referencedImageId, } = measurement; const firstSite = findingSites?.[0]; @@ -294,6 +308,7 @@ function _mapMeasurementToDisplay(measurement, types, displaySetService) { isActive: selected, finding, findingSites, + referencedImageId, }; } diff --git a/extensions/measurement-tracking/src/panels/PanelStudyBrowserTracking/PanelStudyBrowserTracking.tsx b/extensions/measurement-tracking/src/panels/PanelStudyBrowserTracking/PanelStudyBrowserTracking.tsx index 4d9dc3a4d5..5920e70296 100644 --- a/extensions/measurement-tracking/src/panels/PanelStudyBrowserTracking/PanelStudyBrowserTracking.tsx +++ b/extensions/measurement-tracking/src/panels/PanelStudyBrowserTracking/PanelStudyBrowserTracking.tsx @@ -6,7 +6,7 @@ import { utils } from '@ohif/core'; import { StudyBrowser, useImageViewer, useViewportGrid, Dialog, ButtonEnums } from '@ohif/ui'; import { useTrackedMeasurements } from '../../getContextModule'; -const { formatDate } = utils; +const { formatDate, createStudyBrowserTabs } = utils; /** * @@ -18,13 +18,14 @@ function PanelStudyBrowserTracking({ getStudiesForPatientByMRN, requestDisplaySetCreationForStudy, dataSource, -}) { +}: withAppTypes) { const { displaySetService, uiDialogService, hangingProtocolService, uiNotificationService, measurementService, + studyPrefetcherService, } = servicesManager.services; const navigate = useNavigate(); @@ -34,14 +35,17 @@ function PanelStudyBrowserTracking({ // doesn't have to have such an intense shape. This works well enough for now. // Tabs --> Studies --> DisplaySets --> Thumbnails const { StudyInstanceUIDs } = useImageViewer(); - const [{ activeViewportId, viewports }, viewportGridService] = useViewportGrid(); + const [{ activeViewportId, viewports, isHangingProtocolLayout }, viewportGridService] = + useViewportGrid(); const [trackedMeasurements, sendTrackedMeasurementsEvent] = useTrackedMeasurements(); const [activeTabName, setActiveTabName] = useState('primary'); const [expandedStudyInstanceUIDs, setExpandedStudyInstanceUIDs] = useState([ ...StudyInstanceUIDs, ]); const [studyDisplayList, setStudyDisplayList] = useState([]); + const [hasLoadedViewports, setHasLoadedViewports] = useState(false); const [displaySets, setDisplaySets] = useState([]); + const [displaySetsLoadingState, setDisplaySetsLoadingState] = useState({}); const [thumbnailImageSrcMap, setThumbnailImageSrcMap] = useState({}); const [jumpToDisplaySet, setJumpToDisplaySet] = useState(null); @@ -51,7 +55,8 @@ function PanelStudyBrowserTracking({ try { updatedViewports = hangingProtocolService.getViewportsRequireUpdate( viewportId, - displaySetInstanceUID + displaySetInstanceUID, + isHangingProtocolLayout ); } catch (error) { console.warn(error); @@ -124,6 +129,18 @@ function PanelStudyBrowserTracking({ // ~~ Initial Thumbnails useEffect(() => { + if (!hasLoadedViewports) { + if (activeViewportId) { + // Once there is an active viewport id, it means the layout is ready + // so wait a bit of time to allow the viewports preferential loading + // which improves user experience of responsiveness significantly on slower + // systems. + window.setTimeout(() => setHasLoadedViewports(true), 250); + } + + return; + } + const currentDisplaySets = displaySetService.activeDisplaySets; if (!currentDisplaySets.length) { @@ -148,7 +165,7 @@ function PanelStudyBrowserTracking({ return { ...prevState, ...newImageSrcEntry }; }); }); - }, [displaySetService, dataSource, getImageSrc]); + }, [displaySetService, dataSource, getImageSrc, activeViewportId, hasLoadedViewports]); // ~~ displaySets useEffect(() => { @@ -160,6 +177,7 @@ function PanelStudyBrowserTracking({ const mappedDisplaySets = _mapDisplaySets( currentDisplaySets, + displaySetsLoadingState, thumbnailImageSrcMap, trackedSeries, viewports, @@ -174,18 +192,39 @@ function PanelStudyBrowserTracking({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [ displaySetService.activeDisplaySets, + displaySetsLoadingState, trackedSeries, viewports, dataSource, thumbnailImageSrcMap, ]); + // -- displaySetsLoadingState + useEffect(() => { + const { unsubscribe } = studyPrefetcherService.subscribe( + studyPrefetcherService.EVENTS.DISPLAYSET_LOAD_PROGRESS, + updatedDisplaySetLoadingState => { + const { displaySetInstanceUID, loadingProgress } = updatedDisplaySetLoadingState; + + setDisplaySetsLoadingState(prevState => ({ + ...prevState, + [displaySetInstanceUID]: loadingProgress, + })); + } + ); + + return () => unsubscribe(); + }, [studyPrefetcherService]); + // ~~ subscriptions --> displaySets useEffect(() => { // DISPLAY_SETS_ADDED returns an array of DisplaySets that were added const SubscriptionDisplaySetsAdded = displaySetService.subscribe( displaySetService.EVENTS.DISPLAY_SETS_ADDED, data => { + if (!hasLoadedViewports) { + return; + } const { displaySetsAdded, options } = data; displaySetsAdded.forEach(async dSet => { const displaySetInstanceUID = dSet.displaySetInstanceUID; @@ -231,6 +270,7 @@ function PanelStudyBrowserTracking({ changedDisplaySets => { const mappedDisplaySets = _mapDisplaySets( changedDisplaySets, + displaySetsLoadingState, thumbnailImageSrcMap, trackedSeries, viewports, @@ -250,6 +290,7 @@ function PanelStudyBrowserTracking({ () => { const mappedDisplaySets = _mapDisplaySets( displaySetService.getActiveDisplaySets(), + displaySetsLoadingState, thumbnailImageSrcMap, trackedSeries, viewports, @@ -268,14 +309,16 @@ function PanelStudyBrowserTracking({ SubscriptionDisplaySetsChanged.unsubscribe(); SubscriptionDisplaySetMetaDataInvalidated.unsubscribe(); }; - }, [thumbnailImageSrcMap, trackedSeries, viewports, dataSource, displaySetService]); + }, [ + displaySetsLoadingState, + thumbnailImageSrcMap, + trackedSeries, + viewports, + dataSource, + displaySetService, + ]); - const tabs = _createStudyBrowserTabs( - StudyInstanceUIDs, - studyDisplayList, - displaySets, - hangingProtocolService - ); + const tabs = createStudyBrowserTabs(StudyInstanceUIDs, studyDisplayList, displaySets); // TODO: Should not fire this on "close" function _handleStudyClick(StudyInstanceUID) { @@ -457,6 +500,7 @@ function _mapDataSourceStudies(studies) { function _mapDisplaySets( displaySets, + displaySetLoadingState, thumbnailImageSrcMap, trackedSeriesInstanceUIDs, viewports, // TODO: make array of `displaySetInstanceUIDs`? @@ -479,6 +523,7 @@ function _mapDisplaySets( componentType === 'thumbnailTracked' ? thumbnailDisplaySets : thumbnailNoImageDisplaySets; const { displaySetInstanceUID } = ds; + const loadingProgress = displaySetLoadingState?.[displaySetInstanceUID]; const thumbnailProps = { displaySetInstanceUID, @@ -487,6 +532,7 @@ function _mapDisplaySets( modality: ds.Modality, seriesDate: formatDate(ds.SeriesDate), numInstances: ds.numImageFrames, + loadingProgress, countIcon: ds.countIcon, messages: ds.messages, StudyInstanceUID: ds.StudyInstanceUID, @@ -578,7 +624,17 @@ function _mapDisplaySets( return [...thumbnailDisplaySets, ...thumbnailNoImageDisplaySets]; } -const thumbnailNoImageModalities = ['SR', 'SEG', 'SM', 'RTSTRUCT', 'RTPLAN', 'RTDOSE', 'DOC', 'OT']; +const thumbnailNoImageModalities = [ + 'SR', + 'SEG', + 'SM', + 'RTSTRUCT', + 'RTPLAN', + 'RTDOSE', + 'DOC', + 'OT', + 'PMAP', +]; function _getComponentType(ds) { if (thumbnailNoImageModalities.includes(ds.Modality) || ds?.unsupported) { @@ -588,97 +644,6 @@ function _getComponentType(ds) { return 'thumbnailTracked'; } -/** - * - * @param {string[]} primaryStudyInstanceUIDs - * @param {object[]} studyDisplayList - * @param {string} studyDisplayList.studyInstanceUid - * @param {string} studyDisplayList.date - * @param {string} studyDisplayList.description - * @param {string} studyDisplayList.modalities - * @param {number} studyDisplayList.numInstances - * @param {object[]} displaySets - * @returns tabs - The prop object expected by the StudyBrowser component - */ -function _createStudyBrowserTabs( - primaryStudyInstanceUIDs, - studyDisplayList, - displaySets, - hangingProtocolService -) { - const primaryStudies = []; - const recentStudies = []; - const allStudies = []; - - // Iterate over each study... - studyDisplayList.forEach(study => { - // Find it's display sets - const displaySetsForStudy = displaySets.filter( - ds => ds.StudyInstanceUID === study.studyInstanceUid - ); - - // Sort them - const dsSortFn = hangingProtocolService.getDisplaySetSortFunction(); - displaySetsForStudy.sort(dsSortFn); - - /* Sort by series number, then by series date - displaySetsForStudy.sort((a, b) => { - if (a.seriesNumber !== b.seriesNumber) { - return a.seriesNumber - b.seriesNumber; - } - - const seriesDateA = Date.parse(a.seriesDate); - const seriesDateB = Date.parse(b.seriesDate); - - return seriesDateA - seriesDateB; - }); - */ - - // Map the study to it's tab/view representation - const tabStudy = Object.assign({}, study, { - displaySets: displaySetsForStudy, - }); - - // Add the "tab study" to the 'primary', 'recent', and/or 'all' tab group(s) - if (primaryStudyInstanceUIDs.includes(study.studyInstanceUid)) { - primaryStudies.push(tabStudy); - allStudies.push(tabStudy); - } else { - // TODO: Filter allStudies to dates within one year of current date - recentStudies.push(tabStudy); - allStudies.push(tabStudy); - } - }); - - // Newest first - const _byDate = (a, b) => { - const dateA = Date.parse(a); - const dateB = Date.parse(b); - - return dateB - dateA; - }; - - const tabs = [ - { - name: 'primary', - label: 'Primary', - studies: primaryStudies.sort((studyA, studyB) => _byDate(studyA.date, studyB.date)), - }, - { - name: 'recent', - label: 'Recent', - studies: recentStudies.sort((studyA, studyB) => _byDate(studyA.date, studyB.date)), - }, - { - name: 'all', - label: 'All', - studies: allStudies.sort((studyA, studyB) => _byDate(studyA.date, studyB.date)), - }, - ]; - - return tabs; -} - function _findTabAndStudyOfDisplaySet(displaySetInstanceUID, tabs) { for (let t = 0; t < tabs.length; t++) { const { studies } = tabs[t]; diff --git a/extensions/measurement-tracking/src/panels/PanelStudyBrowserTracking/index.tsx b/extensions/measurement-tracking/src/panels/PanelStudyBrowserTracking/index.tsx index cffd41bb07..b276579db1 100644 --- a/extensions/measurement-tracking/src/panels/PanelStudyBrowserTracking/index.tsx +++ b/extensions/measurement-tracking/src/panels/PanelStudyBrowserTracking/index.tsx @@ -21,7 +21,11 @@ function _getStudyForPatientUtility(extensionManager) { * @param {object} commandsManager * @param {object} extensionManager */ -function WrappedPanelStudyBrowserTracking({ commandsManager, extensionManager, servicesManager }) { +function WrappedPanelStudyBrowserTracking({ + commandsManager, + extensionManager, + servicesManager, +}: withAppTypes) { const dataSource = extensionManager.getActiveDataSource()[0]; const getStudiesForPatientByMRN = _getStudyForPatientUtility(extensionManager); diff --git a/extensions/measurement-tracking/src/viewports/TrackedCornerstoneViewport.tsx b/extensions/measurement-tracking/src/viewports/TrackedCornerstoneViewport.tsx index 94ca843bb5..f0c7cdac0d 100644 --- a/extensions/measurement-tracking/src/viewports/TrackedCornerstoneViewport.tsx +++ b/extensions/measurement-tracking/src/viewports/TrackedCornerstoneViewport.tsx @@ -8,7 +8,7 @@ import { useTrackedMeasurements } from './../getContextModule'; import { BaseVolumeViewport, Enums } from '@cornerstonejs/core'; import { useTranslation } from 'react-i18next'; -function TrackedCornerstoneViewport(props) { +function TrackedCornerstoneViewport(props: withAppTypes) { const { displaySets, viewportId, servicesManager, extensionManager } = props; const { @@ -242,16 +242,11 @@ TrackedCornerstoneViewport.propTypes = { viewportId: PropTypes.string.isRequired, dataSource: PropTypes.object, children: PropTypes.node, - customProps: PropTypes.object, -}; - -TrackedCornerstoneViewport.defaultProps = { - customProps: {}, }; function _getNextMeasurementUID( direction, - servicesManager, + servicesManager: AppTypes.ServicesManager, trackedMeasurementId, trackedMeasurements ) { diff --git a/extensions/test-extension/CHANGELOG.md b/extensions/test-extension/CHANGELOG.md index 563eb3d14b..f2a7ffdf46 100644 --- a/extensions/test-extension/CHANGELOG.md +++ b/extensions/test-extension/CHANGELOG.md @@ -3,6 +3,684 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.9.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.70...v3.9.0-beta.71) (2024-07-30) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.69...v3.9.0-beta.70) (2024-07-30) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.68...v3.9.0-beta.69) (2024-07-27) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.67...v3.9.0-beta.68) (2024-07-26) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.66...v3.9.0-beta.67) (2024-07-26) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.65...v3.9.0-beta.66) (2024-07-24) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.64...v3.9.0-beta.65) (2024-07-23) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.63...v3.9.0-beta.64) (2024-07-19) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.62...v3.9.0-beta.63) (2024-07-10) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.61...v3.9.0-beta.62) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.60...v3.9.0-beta.61) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.59...v3.9.0-beta.60) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.58...v3.9.0-beta.59) (2024-07-05) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.57...v3.9.0-beta.58) (2024-07-04) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.56...v3.9.0-beta.57) (2024-07-02) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.55...v3.9.0-beta.56) (2024-07-02) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.54...v3.9.0-beta.55) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.53...v3.9.0-beta.54) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.52...v3.9.0-beta.53) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.51...v3.9.0-beta.52) (2024-06-27) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.50...v3.9.0-beta.51) (2024-06-27) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.49...v3.9.0-beta.50) (2024-06-26) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.48...v3.9.0-beta.49) (2024-06-26) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.47...v3.9.0-beta.48) (2024-06-25) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.46...v3.9.0-beta.47) (2024-06-21) + + +### Bug Fixes + +* Allow the mode setup/creation to be async, and provide a few more values to extension/app config/mode setup. ([#4016](https://github.com/OHIF/Viewers/issues/4016)) ([88575c6](https://github.com/OHIF/Viewers/commit/88575c6c09fd778a31b2f91524163ce65d1639dd)) + + + + + +# [3.9.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.45...v3.9.0-beta.46) (2024-06-18) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.44...v3.9.0-beta.45) (2024-06-18) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.43...v3.9.0-beta.44) (2024-06-17) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.42...v3.9.0-beta.43) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.41...v3.9.0-beta.42) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.40...v3.9.0-beta.41) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.39...v3.9.0-beta.40) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.38...v3.9.0-beta.39) (2024-06-08) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.37...v3.9.0-beta.38) (2024-06-07) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.36...v3.9.0-beta.37) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.35...v3.9.0-beta.36) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.34...v3.9.0-beta.35) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.33...v3.9.0-beta.34) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.32...v3.9.0-beta.33) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.31...v3.9.0-beta.32) (2024-05-31) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.30...v3.9.0-beta.31) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.29...v3.9.0-beta.30) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.28...v3.9.0-beta.29) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.27...v3.9.0-beta.28) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.26...v3.9.0-beta.27) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.25...v3.9.0-beta.26) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.24...v3.9.0-beta.25) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.23...v3.9.0-beta.24) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.22...v3.9.0-beta.23) (2024-05-28) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.21...v3.9.0-beta.22) (2024-05-27) + + +### Features + +* **ui:** move to React 18 and base for using shadcn/ui ([#4174](https://github.com/OHIF/Viewers/issues/4174)) ([70f2c79](https://github.com/OHIF/Viewers/commit/70f2c797f42af603d7ea0eb8d23b4103aba66f77)) + + + + + +# [3.9.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.20...v3.9.0-beta.21) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.19...v3.9.0-beta.20) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.18...v3.9.0-beta.19) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.17...v3.9.0-beta.18) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.16...v3.9.0-beta.17) (2024-05-23) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.15...v3.9.0-beta.16) (2024-05-23) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.14...v3.9.0-beta.15) (2024-05-22) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.13...v3.9.0-beta.14) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.12...v3.9.0-beta.13) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.11...v3.9.0-beta.12) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.10...v3.9.0-beta.11) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.9...v3.9.0-beta.10) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.8...v3.9.0-beta.9) (2024-05-17) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.7...v3.9.0-beta.8) (2024-05-16) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.6...v3.9.0-beta.7) (2024-05-15) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.5...v3.9.0-beta.6) (2024-05-15) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.4...v3.9.0-beta.5) (2024-05-14) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.3...v3.9.0-beta.4) (2024-05-14) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.2...v3.9.0-beta.3) (2024-05-08) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.1...v3.9.0-beta.2) (2024-05-06) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.0...v3.9.0-beta.1) (2024-05-06) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.9.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.94...v3.9.0-beta.0) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.8.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0-beta.94) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18) + +**Note:** Version bump only for package @ohif/extension-test + + + + + +# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18) + +**Note:** Version bump only for package @ohif/extension-test + + + + + # [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17) **Note:** Version bump only for package @ohif/extension-test diff --git a/extensions/test-extension/package.json b/extensions/test-extension/package.json index 272049d4c7..7050a3c683 100644 --- a/extensions/test-extension/package.json +++ b/extensions/test-extension/package.json @@ -1,6 +1,6 @@ { "name": "@ohif/extension-test", - "version": "3.8.0-beta.82", + "version": "3.9.0-beta.71", "description": "OHIF extension used inside e2e testing", "author": "OHIF", "license": "MIT", @@ -30,13 +30,13 @@ "test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests" }, "peerDependencies": { - "@ohif/core": "3.8.0-beta.82", - "@ohif/ui": "3.8.0-beta.82", + "@ohif/core": "3.9.0-beta.71", + "@ohif/ui": "3.9.0-beta.71", "dcmjs": "0.29.11", "dicom-parser": "^1.8.9", "hammerjs": "^2.0.8", "prop-types": "^15.6.2", - "react": "^17.0.2" + "react": "^18.3.1" }, "dependencies": { "@babel/runtime": "^7.20.13", diff --git a/extensions/test-extension/src/getCustomizationModule.ts b/extensions/test-extension/src/getCustomizationModule.ts index 49ffadb03c..0a81cd6dec 100644 --- a/extensions/test-extension/src/getCustomizationModule.ts +++ b/extensions/test-extension/src/getCustomizationModule.ts @@ -6,5 +6,9 @@ export default function getCustomizationModule() { name: 'custom-context-menu', value: [codingValues, contextMenuCodeItem, findingsContextMenu], }, + { + name: 'contextMenuCodeItem', + value: [contextMenuCodeItem], + }, ]; } diff --git a/extensions/tmtv/CHANGELOG.md b/extensions/tmtv/CHANGELOG.md index 75e862f0b5..19fc49d369 100644 --- a/extensions/tmtv/CHANGELOG.md +++ b/extensions/tmtv/CHANGELOG.md @@ -3,6 +3,702 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.9.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.70...v3.9.0-beta.71) (2024-07-30) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.69...v3.9.0-beta.70) (2024-07-30) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.68...v3.9.0-beta.69) (2024-07-27) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.67...v3.9.0-beta.68) (2024-07-26) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.66...v3.9.0-beta.67) (2024-07-26) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.65...v3.9.0-beta.66) (2024-07-24) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.64...v3.9.0-beta.65) (2024-07-23) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.63...v3.9.0-beta.64) (2024-07-19) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.62...v3.9.0-beta.63) (2024-07-10) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.61...v3.9.0-beta.62) (2024-07-09) + + +### Bug Fixes + +* the start/end command in TMTV for the ROIStartEndThreshold tools ([#4281](https://github.com/OHIF/Viewers/issues/4281)) ([38c19fa](https://github.com/OHIF/Viewers/commit/38c19fab77cdb21d14bdae35813d73f43012cbd7)) + + + + + +# [3.9.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.60...v3.9.0-beta.61) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.59...v3.9.0-beta.60) (2024-07-09) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.58...v3.9.0-beta.59) (2024-07-05) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.57...v3.9.0-beta.58) (2024-07-04) + + +### Bug Fixes + +* stdValue in TMTV mode ([#4278](https://github.com/OHIF/Viewers/issues/4278)) ([b2c6291](https://github.com/OHIF/Viewers/commit/b2c629123c5cf05afbeb19bd1424c327c1f5a606)) + + + + + +# [3.9.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.56...v3.9.0-beta.57) (2024-07-02) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.55...v3.9.0-beta.56) (2024-07-02) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.54...v3.9.0-beta.55) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.53...v3.9.0-beta.54) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.52...v3.9.0-beta.53) (2024-06-28) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.51...v3.9.0-beta.52) (2024-06-27) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.50...v3.9.0-beta.51) (2024-06-27) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.49...v3.9.0-beta.50) (2024-06-26) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.48...v3.9.0-beta.49) (2024-06-26) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.47...v3.9.0-beta.48) (2024-06-25) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.46...v3.9.0-beta.47) (2024-06-21) + + +### Bug Fixes + +* Allow the mode setup/creation to be async, and provide a few more values to extension/app config/mode setup. ([#4016](https://github.com/OHIF/Viewers/issues/4016)) ([88575c6](https://github.com/OHIF/Viewers/commit/88575c6c09fd778a31b2f91524163ce65d1639dd)) + + + + + +# [3.9.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.45...v3.9.0-beta.46) (2024-06-18) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.44...v3.9.0-beta.45) (2024-06-18) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.43...v3.9.0-beta.44) (2024-06-17) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.42...v3.9.0-beta.43) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.41...v3.9.0-beta.42) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.40...v3.9.0-beta.41) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.39...v3.9.0-beta.40) (2024-06-12) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.38...v3.9.0-beta.39) (2024-06-08) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.37...v3.9.0-beta.38) (2024-06-07) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.36...v3.9.0-beta.37) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.35...v3.9.0-beta.36) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.34...v3.9.0-beta.35) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.33...v3.9.0-beta.34) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.32...v3.9.0-beta.33) (2024-06-05) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.31...v3.9.0-beta.32) (2024-05-31) + + +### Bug Fixes + +* **tmtv:** crosshairs should not have viewport indicators ([#4197](https://github.com/OHIF/Viewers/issues/4197)) ([f85da32](https://github.com/OHIF/Viewers/commit/f85da32f34389ef7cecae03c07e0af26468b52a6)) + + + + + +# [3.9.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.30...v3.9.0-beta.31) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.29...v3.9.0-beta.30) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.28...v3.9.0-beta.29) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.27...v3.9.0-beta.28) (2024-05-30) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.26...v3.9.0-beta.27) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.25...v3.9.0-beta.26) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.24...v3.9.0-beta.25) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.23...v3.9.0-beta.24) (2024-05-29) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.22...v3.9.0-beta.23) (2024-05-28) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.21...v3.9.0-beta.22) (2024-05-27) + + +### Features + +* **ui:** move to React 18 and base for using shadcn/ui ([#4174](https://github.com/OHIF/Viewers/issues/4174)) ([70f2c79](https://github.com/OHIF/Viewers/commit/70f2c797f42af603d7ea0eb8d23b4103aba66f77)) + + + + + +# [3.9.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.20...v3.9.0-beta.21) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.19...v3.9.0-beta.20) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.18...v3.9.0-beta.19) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.17...v3.9.0-beta.18) (2024-05-24) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.16...v3.9.0-beta.17) (2024-05-23) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.15...v3.9.0-beta.16) (2024-05-23) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.14...v3.9.0-beta.15) (2024-05-22) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.13...v3.9.0-beta.14) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.12...v3.9.0-beta.13) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.11...v3.9.0-beta.12) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.10...v3.9.0-beta.11) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.9...v3.9.0-beta.10) (2024-05-21) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.8...v3.9.0-beta.9) (2024-05-17) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.7...v3.9.0-beta.8) (2024-05-16) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.6...v3.9.0-beta.7) (2024-05-15) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.5...v3.9.0-beta.6) (2024-05-15) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.4...v3.9.0-beta.5) (2024-05-14) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.3...v3.9.0-beta.4) (2024-05-14) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.2...v3.9.0-beta.3) (2024-05-08) + + +### Features + +* **typings:** Enhance typing support with withAppTypes and custom services throughout OHIF ([#4090](https://github.com/OHIF/Viewers/issues/4090)) ([374065b](https://github.com/OHIF/Viewers/commit/374065bc3bad9d212f9817a8d41546cc64cfabfb)) + + + + + +# [3.9.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.1...v3.9.0-beta.2) (2024-05-06) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.0...v3.9.0-beta.1) (2024-05-06) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.9.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.94...v3.9.0-beta.0) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.8.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0-beta.94) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22) + + +### Bug Fixes + +* **viewport-webworker-segmentation:** Resolve issues with viewport detection, webworker termination, and segmentation panel layout change ([#4059](https://github.com/OHIF/Viewers/issues/4059)) ([52a0c59](https://github.com/OHIF/Viewers/commit/52a0c59294a4161fcca0a6708855549034849951)) + + + + + +# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19) + + +### Features + +* **tmtv-mode:** Add Brush tools and move SUV peak calculation to web worker ([#4053](https://github.com/OHIF/Viewers/issues/4053)) ([8192e34](https://github.com/OHIF/Viewers/commit/8192e348eca993fec331d4963efe88f9a730eceb)) + + + + + +# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + +# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18) + +**Note:** Version bump only for package @ohif/extension-tmtv + + + + + # [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17) diff --git a/extensions/tmtv/package.json b/extensions/tmtv/package.json index 5498e5ea1a..b71389b1a6 100644 --- a/extensions/tmtv/package.json +++ b/extensions/tmtv/package.json @@ -1,6 +1,6 @@ { "name": "@ohif/extension-tmtv", - "version": "3.8.0-beta.82", + "version": "3.9.0-beta.71", "description": "OHIF extension for Total Metabolic Tumor Volume", "author": "OHIF", "license": "MIT", @@ -30,13 +30,13 @@ "test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests" }, "peerDependencies": { - "@ohif/core": "3.8.0-beta.82", - "@ohif/ui": "3.8.0-beta.82", - "dcmjs": "^0.29.12", + "@ohif/core": "3.9.0-beta.71", + "@ohif/ui": "3.9.0-beta.71", + "dcmjs": "*", "dicom-parser": "^1.8.9", "hammerjs": "^2.0.8", "prop-types": "^15.6.2", - "react": "^17.0.2" + "react": "^18.3.1" }, "dependencies": { "@babel/runtime": "^7.20.13", diff --git a/extensions/tmtv/src/Panels/PanelPetSUV.tsx b/extensions/tmtv/src/Panels/PanelPetSUV.tsx index eccd76afbf..07c3e4578a 100644 --- a/extensions/tmtv/src/Panels/PanelPetSUV.tsx +++ b/extensions/tmtv/src/Panels/PanelPetSUV.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useState } from 'react'; import PropTypes from 'prop-types'; import { PanelSection, Input, Button } from '@ohif/ui'; -import { DicomMetadataStore, ServicesManager } from '@ohif/core'; +import { DicomMetadataStore } from '@ohif/core'; import { useTranslation } from 'react-i18next'; const DEFAULT_MEATADATA = { @@ -22,11 +22,10 @@ const DEFAULT_MEATADATA = { * @param param0 * @returns */ -export default function PanelPetSUV({ servicesManager, commandsManager }) { +export default function PanelPetSUV({ servicesManager, commandsManager }: withAppTypes) { const { t } = useTranslation('PanelSUV'); - const { displaySetService, toolGroupService, toolbarService, hangingProtocolService } = ( - servicesManager as ServicesManager - ).services; + const { displaySetService, toolGroupService, toolbarService, hangingProtocolService } = + servicesManager.services; const [metadata, setMetadata] = useState(DEFAULT_MEATADATA); const [ptDisplaySet, setPtDisplaySet] = useState(null); @@ -155,6 +154,7 @@ export default function PanelPetSUV({ servicesManager, commandsManager }) { PatientWeight: e.target.value, }); }} + id="weight-input" /> segmentationService.getSegmentations()); + const [activeSegmentation, setActiveSegmentation] = useState(null); /** * Update UI based on segmentation changes (added, removed, updated) @@ -22,7 +30,11 @@ export default function PanelRoiThresholdSegmentation({ servicesManager, command const { unsubscribe } = segmentationService.subscribe(evt, () => { const segmentations = segmentationService.getSegmentations(); setSegmentations(segmentations); + + const activeSegmentation = segmentations.filter(seg => seg.isActive); + setActiveSegmentation(activeSegmentation[0]); }); + subscriptions.push(unsubscribe); }); @@ -33,26 +45,53 @@ export default function PanelRoiThresholdSegmentation({ servicesManager, command }; }, []); - const tmtvValue = segmentations?.[0]?.cachedStats?.tmtv?.value || null; - const config = segmentations?.[0]?.cachedStats?.tmtv?.config || {}; - - segmentations.forEach(segmentation => { - const { cachedStats } = segmentation; - if (!cachedStats) { - return; - } + useEffect(() => { + const callback = async evt => { + const { detail } = evt; + const { segmentationId } = detail; - // segment 1 - const suvPeak = cachedStats?.['1']?.suvPeak?.suvPeak; + if (!segmentationId) { + return; + } - if (Number.isNaN(suvPeak)) { - uiNotificationService.show({ - title: 'SUV Peak', - message: 'Segmented volume does not allow SUV Peak calculation', - type: 'warning', + await handleROIThresholding({ + segmentationId, + commandsManager, + segmentationService, }); - } - }); + + const segmentation = segmentationService.getSegmentation(segmentationId); + + const { cachedStats } = segmentation; + if (!cachedStats) { + return; + } + + // segment 1 + const suvPeak = cachedStats?.['1']?.suvPeak?.suvPeak; + + if (Number.isNaN(suvPeak)) { + uiNotificationService.show({ + title: 'SUV Peak', + message: 'Segmented volume does not allow SUV Peak calculation', + type: 'warning', + }); + } + }; + + eventTarget.addEventListenerDebounced(Enums.Events.SEGMENTATION_DATA_MODIFIED, callback, 250); + + return () => { + eventTarget.removeEventListenerDebounced(Enums.Events.SEGMENTATION_DATA_MODIFIED, callback); + }; + }, []); + + if (!activeSegmentation) { + return null; + } + + const tmtvValue = activeSegmentation.cachedStats?.tmtv?.value || null; + const config = activeSegmentation.cachedStats?.tmtv?.config || {}; const actions = [ { @@ -67,7 +106,7 @@ export default function PanelRoiThresholdSegmentation({ servicesManager, command disabled: tmtvValue === null, }, { - label: 'Create RT Report', + label: 'Export RT Report', onClick: () => { commandsManager.runCommand('createTMTVRTReport'); }, @@ -80,7 +119,7 @@ export default function PanelRoiThresholdSegmentation({ servicesManager, command
{tmtvValue !== null ? ( -
+
{'TMTV:'} diff --git a/extensions/tmtv/src/Panels/PanelROIThresholdSegmentation/segmentationEditHandler.tsx b/extensions/tmtv/src/Panels/PanelROIThresholdSegmentation/segmentationEditHandler.tsx index c17e0a5112..1ec15652e6 100644 --- a/extensions/tmtv/src/Panels/PanelROIThresholdSegmentation/segmentationEditHandler.tsx +++ b/extensions/tmtv/src/Panels/PanelROIThresholdSegmentation/segmentationEditHandler.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { Input, Dialog, ButtonEnums } from '@ohif/ui'; -function segmentationItemEditHandler({ id, servicesManager }) { +function segmentationItemEditHandler({ id, servicesManager }: withAppTypes) { const { segmentationService, uiDialogService } = servicesManager.services; const segmentation = segmentationService.getSegmentation(id); diff --git a/extensions/tmtv/src/Panels/RectangleROIOptions.tsx b/extensions/tmtv/src/Panels/RectangleROIOptions.tsx index 602bb5531d..85d13821a0 100644 --- a/extensions/tmtv/src/Panels/RectangleROIOptions.tsx +++ b/extensions/tmtv/src/Panels/RectangleROIOptions.tsx @@ -40,7 +40,7 @@ function reducer(state, action) { } } -function RectangleROIOptions({ servicesManager, commandsManager }) { +function RectangleROIOptions({ servicesManager, commandsManager }: withAppTypes) { const { segmentationService } = servicesManager.services; const [selectedSegmentationId, setSelectedSegmentationId] = useState(null); @@ -62,72 +62,16 @@ function RectangleROIOptions({ servicesManager, commandsManager }) { const handleROIThresholding = useCallback(() => { const segmentationId = selectedSegmentationId; - - const segmentation = segmentationService.getSegmentation(segmentationId); const activeSegmentIndex = cs3dTools.segmentation.segmentIndex.getActiveSegmentIndex(segmentationId); // run the threshold based on the active segment index // Todo: later find a way to associate each rectangle with a segment (e.g., maybe with color?) - const labelmap = runCommand('thresholdSegmentationByRectangleROITool', { + runCommand('thresholdSegmentationByRectangleROITool', { segmentationId, config, segmentIndex: activeSegmentIndex, }); - - // re-calculating the cached stats for the active segmentation - const updatedPerSegmentCachedStats = {}; - segmentation.segments = segmentation.segments.map(segment => { - if (!segment || !segment.segmentIndex) { - return segment; - } - - const segmentIndex = segment.segmentIndex; - - const lesionStats = runCommand('getLesionStats', { labelmap, segmentIndex }); - const suvPeak = runCommand('calculateSuvPeak', { labelmap, segmentIndex }); - const lesionGlyoclysisStats = lesionStats.volume * lesionStats.meanValue; - - // update segDetails with the suv peak for the active segmentation - const cachedStats = { - lesionStats, - suvPeak, - lesionGlyoclysisStats, - }; - - segment.cachedStats = cachedStats; - segment.displayText = [ - `SUV Peak: ${suvPeak.suvPeak.toFixed(2)}`, - `Volume: ${lesionStats.volume.toFixed(2)} mm3`, - ]; - updatedPerSegmentCachedStats[segmentIndex] = cachedStats; - - return segment; - }); - - const notYetUpdatedAtSource = true; - - const segmentations = segmentationService.getSegmentations(); - const tmtv = runCommand('calculateTMTV', { segmentations }); - - segmentation.cachedStats = Object.assign( - segmentation.cachedStats, - updatedPerSegmentCachedStats, - { - tmtv: { - value: tmtv.toFixed(3), - config: { ...config }, - }, - } - ); - - segmentationService.addOrUpdateSegmentation( - { - ...segmentation, - }, - false, // don't suppress events - notYetUpdatedAtSource - ); }, [selectedSegmentationId, config]); useEffect(() => { @@ -171,27 +115,6 @@ function RectangleROIOptions({ servicesManager, commandsManager }) { }; }, []); - useEffect(() => { - const { unsubscribe } = segmentationService.subscribe( - segmentationService.EVENTS.SEGMENTATION_REMOVED, - () => { - const segmentations = segmentationService.getSegmentations(); - - if (segmentations.length > 0) { - setSelectedSegmentationId(segmentations[0].id); - handleROIThresholding(); - } else { - setSelectedSegmentationId(null); - handleROIThresholding(); - } - } - ); - - return () => { - unsubscribe(); - }; - }, []); - return (
{ +const workerManager = getWebWorkerManager(); + +const options = { + maxWorkerInstances: 1, + autoTerminateOnIdle: { + enabled: true, + idleTimeThreshold: 3000, + }, +}; + +// Register the task +const workerFn = () => { + return new Worker(new URL('./utils/calculateSUVPeakWorker.js', import.meta.url), { + name: 'suv-peak-worker', // name used by the browser to name the worker + }); +}; + +const commandsModule = ({ servicesManager, commandsManager, extensionManager }: withAppTypes) => { const { viewportGridService, uiNotificationService, @@ -186,7 +205,7 @@ const commandsModule = ({ servicesManager, commandsManager, extensionManager }) const { referencedVolumeId } = cs.cache.getVolume(segVolumeId); const annotationUIDs = _getAnnotationsSelectedByToolNames( - RECTANGLE_ROI_THRESHOLD_MANUAL_TOOL_IDS + ROI_THRESHOLD_MANUAL_TOOL_IDS ); if (annotationUIDs.length === 0) { @@ -265,19 +284,64 @@ const commandsModule = ({ servicesManager, commandsManager, extensionManager }) { overwrite: true, segmentIndex } ); }, - calculateSuvPeak: ({ labelmap, segmentIndex }) => { + calculateSuvPeak: async ({ labelmap, segmentIndex }) => { + // if we put it in the top, it will appear in other modes + workerManager.registerWorker('suv-peak-worker', workerFn, options); + const { referencedVolumeId } = labelmap; const referencedVolume = cs.cache.getVolume(referencedVolumeId); const annotationUIDs = _getAnnotationsSelectedByToolNames( - RECTANGLE_ROI_THRESHOLD_MANUAL_TOOL_IDS + ROI_THRESHOLD_MANUAL_TOOL_IDS ); const annotations = annotationUIDs.map(annotationUID => csTools.annotation.state.getAnnotation(annotationUID) ); - const suvPeak = calculateSuvPeak(labelmap, referencedVolume, annotations, segmentIndex); + const labelmapProps = { + dimensions: labelmap.dimensions, + origin: labelmap.origin, + direction: labelmap.direction, + spacing: labelmap.spacing, + scalarData: labelmap.scalarData, + metadata: labelmap.metadata, + }; + + const referenceVolumeProps = { + dimensions: referencedVolume.dimensions, + origin: referencedVolume.origin, + direction: referencedVolume.direction, + spacing: referencedVolume.spacing, + scalarData: referencedVolume.scalarData, + metadata: referencedVolume.metadata, + }; + + // metadata in annotations has enabledElement which is not serializable + // we need to remove it + // Todo: we should probably have a sanitization function for this + const annotationsToSend = annotations.map(annotation => { + return { + ...annotation, + metadata: { + ...annotation.metadata, + enabledElement: { + ...annotation.metadata.enabledElement, + viewport: null, + renderingEngine: null, + element: null, + }, + }, + }; + }); + + const suvPeak = await workerManager.executeTask('suv-peak-worker', 'calculateSuvPeak', { + labelmapProps, + referenceVolumeProps, + annotations: annotationsToSend, + segmentIndex, + }); + return { suvPeak: suvPeak.mean, suvMax: suvPeak.max, @@ -291,7 +355,7 @@ const commandsModule = ({ servicesManager, commandsManager, extensionManager }) let segmentationMax = -Infinity; let segmentationMin = Infinity; - let segmentationValues = []; + const segmentationValues = []; let voxelCount = 0; for (let i = 0; i < scalarData.length; i++) { @@ -307,15 +371,16 @@ const commandsModule = ({ servicesManager, commandsManager, extensionManager }) voxelCount++; } } + const mean = segmentationValues.reduce((a, b) => a + b, 0) / voxelCount; const stats = { minValue: segmentationMin, maxValue: segmentationMax, - meanValue: segmentationValues.reduce((a, b) => a + b, 0) / voxelCount, + meanValue: mean, stdValue: Math.sqrt( - segmentationValues.reduce((a, b) => a + b * b, 0) / voxelCount - - segmentationValues.reduce((a, b) => a + b, 0) / voxelCount ** 2 - ), + segmentationValues + .map((k) => (k - mean) ** 2) + .reduce((acc, curr) => acc + curr, 0) / voxelCount), volume: voxelCount * spacing[0] * spacing[1] * spacing[2] * 1e-3, }; @@ -405,38 +470,18 @@ const commandsModule = ({ servicesManager, commandsManager, extensionManager }) }, setStartSliceForROIThresholdTool: () => { const { viewport } = _getActiveViewportsEnabledElement(); - const { focalPoint, viewPlaneNormal } = viewport.getCamera(); + const { focalPoint } = viewport.getCamera(); const selectedAnnotationUIDs = _getAnnotationsSelectedByToolNames( - RECTANGLE_ROI_THRESHOLD_MANUAL_TOOL_IDS + ROI_THRESHOLD_MANUAL_TOOL_IDS ); const annotationUID = selectedAnnotationUIDs[0]; const annotation = csTools.annotation.state.getAnnotation(annotationUID); - const { handles } = annotation.data; - const { points } = handles; - - // get the current slice Index - const sliceIndex = viewport.getCurrentImageIdIndex(); - annotation.data.startSlice = sliceIndex; - - // distance between camera focal point and each point on the rectangle - const newPoints = points.map(point => { - const distance = vec3.create(); - vec3.subtract(distance, focalPoint, point); - // distance in the direction of the viewPlaneNormal - const distanceInViewPlane = vec3.dot(distance, viewPlaneNormal); - // new point is current point minus distanceInViewPlane - const newPoint = vec3.create(); - vec3.scaleAndAdd(newPoint, point, viewPlaneNormal, distanceInViewPlane); - - return newPoint; - // - }); - - handles.points = newPoints; + // set the current focalpoint + annotation.data.startCoordinate = focalPoint; // IMPORTANT: invalidate the toolData for the cached stat to get updated // and re-calculate the projection points annotation.invalidated = true; @@ -446,16 +491,16 @@ const commandsModule = ({ servicesManager, commandsManager, extensionManager }) const { viewport } = _getActiveViewportsEnabledElement(); const selectedAnnotationUIDs = _getAnnotationsSelectedByToolNames( - RECTANGLE_ROI_THRESHOLD_MANUAL_TOOL_IDS + ROI_THRESHOLD_MANUAL_TOOL_IDS ); const annotationUID = selectedAnnotationUIDs[0]; const annotation = csTools.annotation.state.getAnnotation(annotationUID); - // get the current slice Index - const sliceIndex = viewport.getCurrentImageIdIndex(); - annotation.data.endSlice = sliceIndex; + // get the current focalpoint + const focalPointToEnd = viewport.getCamera().focalPoint; + annotation.data.endCoordinate = focalPointToEnd; // IMPORTANT: invalidate the toolData for the cached stat to get updated // and re-calculate the projection points @@ -471,7 +516,7 @@ const commandsModule = ({ servicesManager, commandsManager, extensionManager }) Object.keys(stateManager.annotations).forEach(frameOfReferenceUID => { const forAnnotations = stateManager.annotations[frameOfReferenceUID]; - const ROIAnnotations = RECTANGLE_ROI_THRESHOLD_MANUAL_TOOL_IDS.reduce( + const ROIAnnotations = ROI_THRESHOLD_MANUAL_TOOL_IDS.reduce( (annotations, toolName) => [...annotations, ...(forAnnotations[toolName] ?? [])], [] ); @@ -488,7 +533,7 @@ const commandsModule = ({ servicesManager, commandsManager, extensionManager }) segmentations = segmentationService.getSegmentations(); } - let report = {}; + const report = {}; for (const segmentation of segmentations) { const { id, label, cachedStats: data } = segmentation; @@ -570,7 +615,7 @@ const commandsModule = ({ servicesManager, commandsManager, extensionManager }) const fusionViewportIds = toolGroup.getViewportIds(); - let viewports = []; + const viewports = []; fusionViewportIds.forEach(viewportId => { commandsManager.runCommand('setViewportColormap', { viewportId, diff --git a/extensions/tmtv/src/init.js b/extensions/tmtv/src/init.js index eaa4615332..57ca26cd50 100644 --- a/extensions/tmtv/src/init.js +++ b/extensions/tmtv/src/init.js @@ -1,4 +1,4 @@ -import { addTool, RectangleROIStartEndThresholdTool } from '@cornerstonejs/tools'; +import { addTool, RectangleROIStartEndThresholdTool, CircleROIStartEndThresholdTool } from '@cornerstonejs/tools'; import measurementServiceMappingsFactory from './utils/measurementServiceMappings/measurementServiceMappingsFactory'; @@ -15,8 +15,9 @@ export default function init({ servicesManager }) { servicesManager.services; addTool(RectangleROIStartEndThresholdTool); + addTool(CircleROIStartEndThresholdTool); - const { RectangleROIStartEndThreshold } = measurementServiceMappingsFactory( + const { RectangleROIStartEndThreshold, CircleROIStartEndThreshold } = measurementServiceMappingsFactory( measurementService, displaySetService, cornerstoneViewportService @@ -34,4 +35,12 @@ export default function init({ servicesManager }) { RectangleROIStartEndThreshold.toAnnotation, RectangleROIStartEndThreshold.toMeasurement ); + + measurementService.addMapping( + csTools3DVer1MeasurementSource, + 'CircleROIStartEndThreshold', + CircleROIStartEndThreshold.matchingCriteria, + CircleROIStartEndThreshold.toAnnotation, + CircleROIStartEndThreshold.toMeasurement + ); } diff --git a/extensions/tmtv/src/utils/calculateSUVPeak.ts b/extensions/tmtv/src/utils/calculateSUVPeakWorker.js similarity index 74% rename from extensions/tmtv/src/utils/calculateSUVPeak.ts rename to extensions/tmtv/src/utils/calculateSUVPeakWorker.js index 6627d2e2b0..638ec9d4f8 100644 --- a/extensions/tmtv/src/utils/calculateSUVPeak.ts +++ b/extensions/tmtv/src/utils/calculateSUVPeakWorker.js @@ -1,18 +1,32 @@ -import { Types } from '@cornerstonejs/core'; import { utilities } from '@cornerstonejs/tools'; import { vec3 } from 'gl-matrix'; +import vtkImageData from '@kitware/vtk.js/Common/DataModel/ImageData'; +import vtkDataArray from '@kitware/vtk.js/Common/Core/DataArray'; +import { expose } from 'comlink'; -type AnnotationsForThresholding = { - data: { - handles: { - points: Types.Point3[]; - }; - cachedStats?: { - projectionPoints?: Types.Point3[][]; - }; +const createVolume = ({ dimensions, origin, direction, spacing, scalarData, metadata }) => { + const imageData = vtkImageData.newInstance(); + imageData.setDimensions(dimensions); + imageData.setOrigin(origin); + imageData.setDirection(direction); + imageData.setSpacing(spacing); + + const scalarArray = vtkDataArray.newInstance({ + name: 'Pixels', + numberOfComponents: 1, + values: scalarData, + }); + + imageData.getPointData().setScalars(scalarArray); + + imageData.modified(); + + return { + imageData, + metadata, + getScalarData: () => scalarData, }; }; - /** * This method calculates the SUV peak on a segmented ROI from a reference PET * volume. If a rectangle annotation is provided, the peak is calculated within that @@ -25,17 +39,10 @@ type AnnotationsForThresholding = { * @param segmentIndex The index of the segment to use for masking * @returns */ -function calculateSuvPeak( - labelmap: Types.IImageVolume, - referenceVolume: Types.IImageVolume, - annotations?: AnnotationsForThresholding[], - segmentIndex = 1 -): { - max: number; - maxIJK: Types.Point3; - maxLPS: Types.Point3; - mean: number; -} { +function calculateSuvPeak({ labelmapProps, referenceVolumeProps, annotations, segmentIndex = 1 }) { + const labelmap = createVolume(labelmapProps); + const referenceVolume = createVolume(referenceVolumeProps); + if (referenceVolume.metadata.Modality !== 'PT') { return; } @@ -59,7 +66,7 @@ function calculateSuvPeak( const rectangleCornersIJK = pointsToUse.map(world => { const ijk = vec3.fromValues(0, 0, 0); referenceVolumeImageData.worldToIndex(world, ijk); - return ijk as Types.Point3; + return ijk; }); boundsIJK = utilities.boundingBox.getBoundingBoxAroundShape(rectangleCornersIJK, dimensions); @@ -88,7 +95,7 @@ function calculateSuvPeak( utilities.pointInShapeCallback(labelmapImageData, () => true, callback, boundsIJK); - const direction = labelmapImageData.getDirection().slice(0, 3) as Types.Point3; + const direction = labelmapImageData.getDirection().slice(0, 3); /** * 2. Find the bottom and top of the great circle for the second sphere (1cc sphere) @@ -100,10 +107,10 @@ function calculateSuvPeak( const secondaryCircleWorld = vec3.create(); const bottomWorld = vec3.create(); const topWorld = vec3.create(); - referenceVolumeImageData.indexToWorld(maxIJK as vec3, secondaryCircleWorld); + referenceVolumeImageData.indexToWorld(maxIJK, secondaryCircleWorld); vec3.scaleAndAdd(bottomWorld, secondaryCircleWorld, direction, -diameter / 2); vec3.scaleAndAdd(topWorld, secondaryCircleWorld, direction, diameter / 2); - const suvPeakCirclePoints = [bottomWorld, topWorld] as [Types.Point3, Types.Point3]; + const suvPeakCirclePoints = [bottomWorld, topWorld]; /** * 3. Find the Mean and Max of the 1cc sphere centered on the suv Max of the previous @@ -132,4 +139,8 @@ function calculateSuvPeak( }; } -export default calculateSuvPeak; +const obj = { + calculateSuvPeak, +}; + +expose(obj); diff --git a/extensions/tmtv/src/utils/handleROIThresholding.ts b/extensions/tmtv/src/utils/handleROIThresholding.ts new file mode 100644 index 0000000000..ab47fa0326 --- /dev/null +++ b/extensions/tmtv/src/utils/handleROIThresholding.ts @@ -0,0 +1,64 @@ +import { cache } from '@cornerstonejs/core'; + +export const handleROIThresholding = async ({ + segmentationId, + commandsManager, + segmentationService, + config = {}, +}) => { + const segmentation = segmentationService.getSegmentation(segmentationId); + + // re-calculating the cached stats for the active segmentation + const updatedPerSegmentCachedStats = {}; + segmentation.segments = await Promise.all( + segmentation.segments.map(async segment => { + if (!segment || !segment.segmentIndex) { + return segment; + } + + const labelmap = cache.getVolume(segmentationId); + + const segmentIndex = segment.segmentIndex; + + const lesionStats = commandsManager.run('getLesionStats', { labelmap, segmentIndex }); + const suvPeak = await commandsManager.run('calculateSuvPeak', { labelmap, segmentIndex }); + const lesionGlyoclysisStats = lesionStats.volume * lesionStats.meanValue; + + // update segDetails with the suv peak for the active segmentation + const cachedStats = { + lesionStats, + suvPeak, + lesionGlyoclysisStats, + }; + + segment.cachedStats = cachedStats; + segment.displayText = [ + `SUV Peak: ${suvPeak.suvPeak.toFixed(2)}`, + `Volume: ${lesionStats.volume.toFixed(2)} mm3`, + ]; + updatedPerSegmentCachedStats[segmentIndex] = cachedStats; + + return segment; + }) + ); + + const notYetUpdatedAtSource = true; + + const segmentations = segmentationService.getSegmentations(); + const tmtv = commandsManager.run('calculateTMTV', { segmentations }); + + segmentation.cachedStats = Object.assign(segmentation.cachedStats, updatedPerSegmentCachedStats, { + tmtv: { + value: tmtv.toFixed(3), + config: { ...config }, + }, + }); + + segmentationService.addOrUpdateSegmentation( + { + ...segmentation, + }, + false, // don't suppress events + notYetUpdatedAtSource + ); +}; diff --git a/extensions/tmtv/src/utils/hpViewports.ts b/extensions/tmtv/src/utils/hpViewports.ts index a933921702..8b76cf89c8 100644 --- a/extensions/tmtv/src/utils/hpViewports.ts +++ b/extensions/tmtv/src/utils/hpViewports.ts @@ -127,7 +127,7 @@ const ptAXIAL = { source: true, target: false, options: { - syncInvertState: false, + syncColormap: false, }, }, ], @@ -174,7 +174,7 @@ const ptSAGITTAL = { source: true, target: false, options: { - syncInvertState: false, + syncColormap: false, }, }, ], @@ -221,7 +221,7 @@ const ptCORONAL = { source: true, target: false, options: { - syncInvertState: false, + syncColormap: false, }, }, ], @@ -277,7 +277,7 @@ const fusionAXIAL = { source: false, target: true, options: { - syncInvertState: false, + syncColormap: false, }, }, ], @@ -343,7 +343,7 @@ const fusionSAGITTAL = { source: false, target: true, options: { - syncInvertState: false, + syncColormap: false, }, }, ], @@ -409,7 +409,7 @@ const fusionCORONAL = { source: false, target: true, options: { - syncInvertState: false, + syncColormap: false, }, }, ], @@ -460,7 +460,7 @@ const mipSAGITTAL = { source: true, target: false, options: { - syncInvertState: false, + syncColormap: false, }, }, ], diff --git a/extensions/tmtv/src/utils/measurementServiceMappings/CircleROIStartEndThreshold.js b/extensions/tmtv/src/utils/measurementServiceMappings/CircleROIStartEndThreshold.js new file mode 100644 index 0000000000..bcd9485897 --- /dev/null +++ b/extensions/tmtv/src/utils/measurementServiceMappings/CircleROIStartEndThreshold.js @@ -0,0 +1,67 @@ +import SUPPORTED_TOOLS from './constants/supportedTools'; +import getSOPInstanceAttributes from './utils/getSOPInstanceAttributes'; + +const CircleROIStartEndThreshold = { + toAnnotation: (measurement, definition) => { }, + + /** + * Maps cornerstone annotation event data to measurement service format. + * + * @param {Object} cornerstone Cornerstone event data + * @return {Measurement} Measurement instance + */ + toMeasurement: (csToolsEventDetail, displaySetService, cornerstoneViewportService) => { + const { annotation, viewportId } = csToolsEventDetail; + const { metadata, data, annotationUID } = annotation; + + if (!metadata || !data) { + console.warn('Length tool: Missing metadata or data'); + return null; + } + + const { toolName, referencedImageId, FrameOfReferenceUID } = metadata; + const validToolType = SUPPORTED_TOOLS.includes(toolName); + + if (!validToolType) { + throw new Error('Tool not supported'); + } + + const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes( + referencedImageId, + cornerstoneViewportService, + viewportId + ); + + let displaySet; + + if (SOPInstanceUID) { + displaySet = displaySetService.getDisplaySetForSOPInstanceUID( + SOPInstanceUID, + SeriesInstanceUID + ); + } else { + displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID); + } + + const { cachedStats } = data; + + return { + uid: annotationUID, + SOPInstanceUID, + FrameOfReferenceUID, + // points, + metadata, + referenceSeriesUID: SeriesInstanceUID, + referenceStudyUID: StudyInstanceUID, + toolName: metadata.toolName, + displaySetInstanceUID: displaySet.displaySetInstanceUID, + label: metadata.label, + // displayText: displayText, + data: data.cachedStats, + type: 'CircleROIStartEndThreshold', + // getReport, + }; + }, +}; + +export default CircleROIStartEndThreshold; diff --git a/extensions/tmtv/src/utils/measurementServiceMappings/measurementServiceMappingsFactory.js b/extensions/tmtv/src/utils/measurementServiceMappings/measurementServiceMappingsFactory.js index f99b956a14..af19d43d96 100644 --- a/extensions/tmtv/src/utils/measurementServiceMappings/measurementServiceMappingsFactory.js +++ b/extensions/tmtv/src/utils/measurementServiceMappings/measurementServiceMappingsFactory.js @@ -1,4 +1,5 @@ import RectangleROIStartEndThreshold from './RectangleROIStartEndThreshold'; +import CircleROIStartEndThreshold from './CircleROIStartEndThreshold' const measurementServiceMappingsFactory = ( measurementService, @@ -20,6 +21,20 @@ const measurementServiceMappingsFactory = ( }, ], }, + CircleROIStartEndThreshold: { + toAnnotation: CircleROIStartEndThreshold.toAnnotation, + toMeasurement: csToolsAnnotation => + CircleROIStartEndThreshold.toMeasurement( + csToolsAnnotation, + displaySetService, + cornerstoneViewportService + ), + matchingCriteria: [ + { + valueType: measurementService.VALUE_TYPES.ROI_THRESHOLD_MANUAL, + }, + ], + }, }; }; diff --git a/lerna.json b/lerna.json index 1cb80fb600..116653ade6 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "3.8.0-beta.82", - "packages": ["extensions/*", "platform/*", "modes/*"], + "version": "3.9.0-beta.71", + "packages": ["extensions/*", "platform/*", "modes/*", "addOns/externals/*"], "npmClient": "yarn" } diff --git a/modes/basic-dev-mode/.webpack/webpack.dev.js b/modes/basic-dev-mode/.webpack/webpack.dev.js index 4bf848b6c5..1b8e34cfd1 100644 --- a/modes/basic-dev-mode/.webpack/webpack.dev.js +++ b/modes/basic-dev-mode/.webpack/webpack.dev.js @@ -4,7 +4,7 @@ const SRC_DIR = path.join(__dirname, '../src'); const DIST_DIR = path.join(__dirname, '../dist'); const ENTRY = { - app: `${SRC_DIR}/index.js`, + app: `${SRC_DIR}/index.ts`, }; module.exports = (env, argv) => { diff --git a/modes/basic-dev-mode/.webpack/webpack.prod.js b/modes/basic-dev-mode/.webpack/webpack.prod.js index 26c62c7d4a..a835b9a23e 100644 --- a/modes/basic-dev-mode/.webpack/webpack.prod.js +++ b/modes/basic-dev-mode/.webpack/webpack.prod.js @@ -9,7 +9,7 @@ const SRC_DIR = path.join(__dirname, '../src'); const DIST_DIR = path.join(__dirname, '../dist'); const ENTRY = { - app: `${SRC_DIR}/index.js`, + app: `${SRC_DIR}/index.ts`, }; module.exports = (env, argv) => { diff --git a/modes/basic-dev-mode/CHANGELOG.md b/modes/basic-dev-mode/CHANGELOG.md index 5531b28a56..5b1362bb20 100644 --- a/modes/basic-dev-mode/CHANGELOG.md +++ b/modes/basic-dev-mode/CHANGELOG.md @@ -3,6 +3,684 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.9.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.70...v3.9.0-beta.71) (2024-07-30) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.69...v3.9.0-beta.70) (2024-07-30) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.68...v3.9.0-beta.69) (2024-07-27) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.67...v3.9.0-beta.68) (2024-07-26) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.66...v3.9.0-beta.67) (2024-07-26) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.65...v3.9.0-beta.66) (2024-07-24) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.64...v3.9.0-beta.65) (2024-07-23) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.63...v3.9.0-beta.64) (2024-07-19) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.62...v3.9.0-beta.63) (2024-07-10) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.61...v3.9.0-beta.62) (2024-07-09) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.60...v3.9.0-beta.61) (2024-07-09) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.59...v3.9.0-beta.60) (2024-07-09) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.58...v3.9.0-beta.59) (2024-07-05) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.57...v3.9.0-beta.58) (2024-07-04) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.56...v3.9.0-beta.57) (2024-07-02) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.55...v3.9.0-beta.56) (2024-07-02) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.54...v3.9.0-beta.55) (2024-06-28) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.53...v3.9.0-beta.54) (2024-06-28) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.52...v3.9.0-beta.53) (2024-06-28) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.51...v3.9.0-beta.52) (2024-06-27) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.50...v3.9.0-beta.51) (2024-06-27) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.49...v3.9.0-beta.50) (2024-06-26) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.48...v3.9.0-beta.49) (2024-06-26) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.47...v3.9.0-beta.48) (2024-06-25) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.46...v3.9.0-beta.47) (2024-06-21) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.45...v3.9.0-beta.46) (2024-06-18) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.44...v3.9.0-beta.45) (2024-06-18) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.43...v3.9.0-beta.44) (2024-06-17) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.42...v3.9.0-beta.43) (2024-06-12) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.41...v3.9.0-beta.42) (2024-06-12) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.40...v3.9.0-beta.41) (2024-06-12) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.39...v3.9.0-beta.40) (2024-06-12) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.38...v3.9.0-beta.39) (2024-06-08) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.37...v3.9.0-beta.38) (2024-06-07) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.36...v3.9.0-beta.37) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.35...v3.9.0-beta.36) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.34...v3.9.0-beta.35) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.33...v3.9.0-beta.34) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.32...v3.9.0-beta.33) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.31...v3.9.0-beta.32) (2024-05-31) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.30...v3.9.0-beta.31) (2024-05-30) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.29...v3.9.0-beta.30) (2024-05-30) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.28...v3.9.0-beta.29) (2024-05-30) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.27...v3.9.0-beta.28) (2024-05-30) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.26...v3.9.0-beta.27) (2024-05-29) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.25...v3.9.0-beta.26) (2024-05-29) + + +### Features + +* **hp:** Add displayArea option for Hanging protocols and example with Mamo([#3808](https://github.com/OHIF/Viewers/issues/3808)) ([18ac08e](https://github.com/OHIF/Viewers/commit/18ac08ed860d119721c52e4ffc270332259100b6)) + + + + + +# [3.9.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.24...v3.9.0-beta.25) (2024-05-29) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.23...v3.9.0-beta.24) (2024-05-29) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.22...v3.9.0-beta.23) (2024-05-28) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.21...v3.9.0-beta.22) (2024-05-27) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.20...v3.9.0-beta.21) (2024-05-24) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.19...v3.9.0-beta.20) (2024-05-24) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.18...v3.9.0-beta.19) (2024-05-24) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.17...v3.9.0-beta.18) (2024-05-24) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.16...v3.9.0-beta.17) (2024-05-23) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.15...v3.9.0-beta.16) (2024-05-23) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.14...v3.9.0-beta.15) (2024-05-22) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.13...v3.9.0-beta.14) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.12...v3.9.0-beta.13) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.11...v3.9.0-beta.12) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.10...v3.9.0-beta.11) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.9...v3.9.0-beta.10) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.8...v3.9.0-beta.9) (2024-05-17) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.7...v3.9.0-beta.8) (2024-05-16) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.6...v3.9.0-beta.7) (2024-05-15) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.5...v3.9.0-beta.6) (2024-05-15) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.4...v3.9.0-beta.5) (2024-05-14) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.3...v3.9.0-beta.4) (2024-05-14) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.2...v3.9.0-beta.3) (2024-05-08) + + +### Features + +* **typings:** Enhance typing support with withAppTypes and custom services throughout OHIF ([#4090](https://github.com/OHIF/Viewers/issues/4090)) ([374065b](https://github.com/OHIF/Viewers/commit/374065bc3bad9d212f9817a8d41546cc64cfabfb)) + + + + + +# [3.9.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.1...v3.9.0-beta.2) (2024-05-06) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.0...v3.9.0-beta.1) (2024-05-06) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.9.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.94...v3.9.0-beta.0) (2024-04-29) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.8.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0-beta.94) (2024-04-29) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + +# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18) + +**Note:** Version bump only for package @ohif/mode-basic-dev-mode + + + + + # [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17) **Note:** Version bump only for package @ohif/mode-basic-dev-mode diff --git a/modes/basic-dev-mode/package.json b/modes/basic-dev-mode/package.json index f7f4deac32..406414c3aa 100644 --- a/modes/basic-dev-mode/package.json +++ b/modes/basic-dev-mode/package.json @@ -1,12 +1,12 @@ { "name": "@ohif/mode-basic-dev-mode", - "version": "3.8.0-beta.82", + "version": "3.9.0-beta.71", "description": "Basic OHIF Viewer Using Cornerstone", "author": "OHIF", "license": "MIT", "repository": "OHIF/Viewers", "main": "dist/ohif-mode-basic-dev-mode.umd.js", - "module": "src/index.js", + "module": "src/index.ts", "engines": { "node": ">=10", "npm": ">=6", @@ -31,19 +31,19 @@ "test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests" }, "peerDependencies": { - "@ohif/core": "3.8.0-beta.82", - "@ohif/extension-cornerstone": "3.8.0-beta.82", - "@ohif/extension-cornerstone-dicom-sr": "3.8.0-beta.82", - "@ohif/extension-default": "3.8.0-beta.82", - "@ohif/extension-dicom-pdf": "3.8.0-beta.82", - "@ohif/extension-dicom-video": "3.8.0-beta.82" + "@ohif/core": "3.9.0-beta.71", + "@ohif/extension-cornerstone": "3.9.0-beta.71", + "@ohif/extension-cornerstone-dicom-sr": "3.9.0-beta.71", + "@ohif/extension-default": "3.9.0-beta.71", + "@ohif/extension-dicom-pdf": "3.9.0-beta.71", + "@ohif/extension-dicom-video": "3.9.0-beta.71" }, "dependencies": { "@babel/runtime": "^7.20.13", "i18next": "^17.0.3" }, "devDependencies": { - "webpack": "^5.50.0", + "webpack": "5.89.0", "webpack-merge": "^5.7.3" } } diff --git a/modes/basic-dev-mode/src/index.js b/modes/basic-dev-mode/src/index.ts similarity index 97% rename from modes/basic-dev-mode/src/index.js rename to modes/basic-dev-mode/src/index.ts index 4bc20e8438..649dd81cd1 100644 --- a/modes/basic-dev-mode/src/index.js +++ b/modes/basic-dev-mode/src/index.ts @@ -50,7 +50,7 @@ function modeFactory({ modeConfiguration }) { /** * Lifecycle hooks */ - onModeEnter: ({ servicesManager, extensionManager }) => { + onModeEnter: ({ servicesManager, extensionManager }: withAppTypes) => { const { toolbarService, toolGroupService } = servicesManager.services; const utilityModule = extensionManager.getModuleEntry( '@ohif/extension-cornerstone.utilityModule.tools' @@ -101,7 +101,7 @@ function modeFactory({ modeConfiguration }) { 'MoreTools', ]); }, - onModeExit: ({ servicesManager }) => { + onModeExit: ({ servicesManager }: withAppTypes) => { const { toolGroupService, measurementService, diff --git a/modes/basic-test-mode/CHANGELOG.md b/modes/basic-test-mode/CHANGELOG.md index a851318c35..757e832118 100644 --- a/modes/basic-test-mode/CHANGELOG.md +++ b/modes/basic-test-mode/CHANGELOG.md @@ -3,6 +3,707 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.9.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.70...v3.9.0-beta.71) (2024-07-30) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.69...v3.9.0-beta.70) (2024-07-30) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.68...v3.9.0-beta.69) (2024-07-27) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.67...v3.9.0-beta.68) (2024-07-26) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.66...v3.9.0-beta.67) (2024-07-26) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.65...v3.9.0-beta.66) (2024-07-24) + + +### Features + +* **pmap:** added support for parametric map ([#4284](https://github.com/OHIF/Viewers/issues/4284)) ([fc0064f](https://github.com/OHIF/Viewers/commit/fc0064fd9d8cdc8fde81b81f0e71fd5d077ca22b)) + + + + + +# [3.9.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.64...v3.9.0-beta.65) (2024-07-23) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.63...v3.9.0-beta.64) (2024-07-19) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.62...v3.9.0-beta.63) (2024-07-10) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.61...v3.9.0-beta.62) (2024-07-09) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.60...v3.9.0-beta.61) (2024-07-09) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.59...v3.9.0-beta.60) (2024-07-09) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.58...v3.9.0-beta.59) (2024-07-05) + + +### Bug Fixes + +* Cobb angle not working in basic-test mode and open contour ([#4280](https://github.com/OHIF/Viewers/issues/4280)) ([6fd3c7e](https://github.com/OHIF/Viewers/commit/6fd3c7e293fec851dd30e650c1347cc0bc7a99ee)) + + +### Features + +* Add interleaved HTJ2K and volume progressive loading ([#4276](https://github.com/OHIF/Viewers/issues/4276)) ([a2084f3](https://github.com/OHIF/Viewers/commit/a2084f319b731d98b59485799fb80357094f8c38)) + + + + + +# [3.9.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.57...v3.9.0-beta.58) (2024-07-04) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.56...v3.9.0-beta.57) (2024-07-02) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.55...v3.9.0-beta.56) (2024-07-02) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.54...v3.9.0-beta.55) (2024-06-28) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.53...v3.9.0-beta.54) (2024-06-28) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.52...v3.9.0-beta.53) (2024-06-28) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.51...v3.9.0-beta.52) (2024-06-27) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.50...v3.9.0-beta.51) (2024-06-27) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.49...v3.9.0-beta.50) (2024-06-26) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.48...v3.9.0-beta.49) (2024-06-26) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.47...v3.9.0-beta.48) (2024-06-25) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.46...v3.9.0-beta.47) (2024-06-21) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.45...v3.9.0-beta.46) (2024-06-18) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.44...v3.9.0-beta.45) (2024-06-18) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.43...v3.9.0-beta.44) (2024-06-17) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.42...v3.9.0-beta.43) (2024-06-12) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.41...v3.9.0-beta.42) (2024-06-12) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.40...v3.9.0-beta.41) (2024-06-12) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.39...v3.9.0-beta.40) (2024-06-12) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.38...v3.9.0-beta.39) (2024-06-08) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.37...v3.9.0-beta.38) (2024-06-07) + + +### Bug Fixes + +* **window-level:** move window level region to more tools menu ([#4215](https://github.com/OHIF/Viewers/issues/4215)) ([33f4c18](https://github.com/OHIF/Viewers/commit/33f4c18f2687d30a250fe7183df3daae8394a984)) + + + + + +# [3.9.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.36...v3.9.0-beta.37) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.35...v3.9.0-beta.36) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.34...v3.9.0-beta.35) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.33...v3.9.0-beta.34) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.32...v3.9.0-beta.33) (2024-06-05) + + +### Features + +* **window-level-region:** add window level region tool ([#4127](https://github.com/OHIF/Viewers/issues/4127)) ([ab1a18a](https://github.com/OHIF/Viewers/commit/ab1a18af5a5b0f9086c080ed81c8fda9bfaa975b)) + + + + + +# [3.9.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.31...v3.9.0-beta.32) (2024-05-31) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.30...v3.9.0-beta.31) (2024-05-30) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.29...v3.9.0-beta.30) (2024-05-30) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.28...v3.9.0-beta.29) (2024-05-30) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.27...v3.9.0-beta.28) (2024-05-30) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.26...v3.9.0-beta.27) (2024-05-29) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.25...v3.9.0-beta.26) (2024-05-29) + + +### Features + +* **hp:** Add displayArea option for Hanging protocols and example with Mamo([#3808](https://github.com/OHIF/Viewers/issues/3808)) ([18ac08e](https://github.com/OHIF/Viewers/commit/18ac08ed860d119721c52e4ffc270332259100b6)) + + + + + +# [3.9.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.24...v3.9.0-beta.25) (2024-05-29) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.23...v3.9.0-beta.24) (2024-05-29) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.22...v3.9.0-beta.23) (2024-05-28) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.21...v3.9.0-beta.22) (2024-05-27) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.20...v3.9.0-beta.21) (2024-05-24) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.19...v3.9.0-beta.20) (2024-05-24) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.18...v3.9.0-beta.19) (2024-05-24) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.17...v3.9.0-beta.18) (2024-05-24) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.16...v3.9.0-beta.17) (2024-05-23) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.15...v3.9.0-beta.16) (2024-05-23) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.14...v3.9.0-beta.15) (2024-05-22) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.13...v3.9.0-beta.14) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.12...v3.9.0-beta.13) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.11...v3.9.0-beta.12) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.10...v3.9.0-beta.11) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.9...v3.9.0-beta.10) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.8...v3.9.0-beta.9) (2024-05-17) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.7...v3.9.0-beta.8) (2024-05-16) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.6...v3.9.0-beta.7) (2024-05-15) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.5...v3.9.0-beta.6) (2024-05-15) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.4...v3.9.0-beta.5) (2024-05-14) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.3...v3.9.0-beta.4) (2024-05-14) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.2...v3.9.0-beta.3) (2024-05-08) + + +### Features + +* **typings:** Enhance typing support with withAppTypes and custom services throughout OHIF ([#4090](https://github.com/OHIF/Viewers/issues/4090)) ([374065b](https://github.com/OHIF/Viewers/commit/374065bc3bad9d212f9817a8d41546cc64cfabfb)) + + + + + +# [3.9.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.1...v3.9.0-beta.2) (2024-05-06) + + +### Bug Fixes + +* **bugs:** enhancements and bugs in several areas ([#4086](https://github.com/OHIF/Viewers/issues/4086)) ([730f434](https://github.com/OHIF/Viewers/commit/730f4349100f21b4489a21707dbb2dca9dbfbba2)) + + + + + +# [3.9.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.0...v3.9.0-beta.1) (2024-05-06) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.9.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.94...v3.9.0-beta.0) (2024-04-29) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.8.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0-beta.94) (2024-04-29) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19) + + +### Bug Fixes + +* **layouts:** and fix thumbnail in touch and update migration guide for 3.8 release ([#4052](https://github.com/OHIF/Viewers/issues/4052)) ([d250d04](https://github.com/OHIF/Viewers/commit/d250d04580883446fcb8d748b2a97c5c198922af)) + + + + + +# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18) + +**Note:** Version bump only for package @ohif/mode-test + + + + + +# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18) + +**Note:** Version bump only for package @ohif/mode-test + + + + + # [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17) **Note:** Version bump only for package @ohif/mode-test diff --git a/modes/basic-test-mode/package.json b/modes/basic-test-mode/package.json index deb1a6c57f..dafc02f3ef 100644 --- a/modes/basic-test-mode/package.json +++ b/modes/basic-test-mode/package.json @@ -1,6 +1,6 @@ { "name": "@ohif/mode-test", - "version": "3.8.0-beta.82", + "version": "3.9.0-beta.71", "description": "Basic mode for testing", "author": "OHIF", "license": "MIT", @@ -34,21 +34,21 @@ "test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests" }, "peerDependencies": { - "@ohif/core": "3.8.0-beta.82", - "@ohif/extension-cornerstone": "3.8.0-beta.82", - "@ohif/extension-cornerstone-dicom-sr": "3.8.0-beta.82", - "@ohif/extension-default": "3.8.0-beta.82", - "@ohif/extension-dicom-pdf": "3.8.0-beta.82", - "@ohif/extension-dicom-video": "3.8.0-beta.82", - "@ohif/extension-measurement-tracking": "3.8.0-beta.82", - "@ohif/extension-test": "3.8.0-beta.82" + "@ohif/core": "3.9.0-beta.71", + "@ohif/extension-cornerstone": "3.9.0-beta.71", + "@ohif/extension-cornerstone-dicom-sr": "3.9.0-beta.71", + "@ohif/extension-default": "3.9.0-beta.71", + "@ohif/extension-dicom-pdf": "3.9.0-beta.71", + "@ohif/extension-dicom-video": "3.9.0-beta.71", + "@ohif/extension-measurement-tracking": "3.9.0-beta.71", + "@ohif/extension-test": "3.9.0-beta.71" }, "dependencies": { "@babel/runtime": "^7.20.13", "i18next": "^17.0.3" }, "devDependencies": { - "webpack": "^5.50.0", + "webpack": "5.89.0", "webpack-merge": "^5.7.3" } } diff --git a/modes/basic-test-mode/src/index.ts b/modes/basic-test-mode/src/index.ts index 52dc5ebc17..9098989778 100644 --- a/modes/basic-test-mode/src/index.ts +++ b/modes/basic-test-mode/src/index.ts @@ -13,6 +13,7 @@ const ohif = { layout: '@ohif/extension-default.layoutTemplateModule.viewerLayout', sopClassHandler: '@ohif/extension-default.sopClassHandlerModule.stack', thumbnailList: '@ohif/extension-default.panelModule.seriesList', + measurements: '@ohif/extension-default.panelModule.measurements', }; const tracked = { @@ -42,6 +43,11 @@ const dicomSeg = { panel: '@ohif/extension-cornerstone-dicom-seg.panelModule.panelSegmentation', }; +const dicomPmap = { + sopClassHandler: '@ohif/extension-cornerstone-dicom-pmap.sopClassHandlerModule.dicom-pmap', + viewport: '@ohif/extension-cornerstone-dicom-pmap.viewportModule.dicom-pmap', +}; + const extensionDependencies = { // Can derive the versions at least process.env.from npm_package_version '@ohif/extension-default': '^3.0.0', @@ -49,6 +55,7 @@ const extensionDependencies = { '@ohif/extension-measurement-tracking': '^3.0.0', '@ohif/extension-cornerstone-dicom-sr': '^3.0.0', '@ohif/extension-cornerstone-dicom-seg': '^3.0.0', + '@ohif/extension-cornerstone-dicom-pmap': '^3.0.0', '@ohif/extension-dicom-pdf': '^3.0.1', '@ohif/extension-dicom-video': '^3.0.1', '@ohif/extension-test': '^0.0.1', @@ -64,7 +71,7 @@ function modeFactory() { /** * Lifecycle hooks */ - onModeEnter: ({ servicesManager, extensionManager, commandsManager }) => { + onModeEnter: ({ servicesManager, extensionManager, commandsManager }: withAppTypes) => { const { measurementService, toolbarService, toolGroupService, customizationService } = servicesManager.services; @@ -91,7 +98,7 @@ function modeFactory() { 'MoreTools', ]); }, - onModeExit: ({ servicesManager }) => { + onModeExit: ({ servicesManager }: withAppTypes) => { const { toolGroupService, syncGroupService, @@ -134,6 +141,9 @@ function modeFactory() { return { id: ohif.layout, props: { + // Use the first two for an untracked view + // leftPanels: [ohif.thumbnailList], + // rightPanels: [dicomSeg.panel, ohif.measurements], leftPanels: [tracked.thumbnailList], rightPanels: [dicomSeg.panel, tracked.measurements], // rightPanelClosed: true, // optional prop to start with collapse panels @@ -158,6 +168,10 @@ function modeFactory() { namespace: dicomSeg.viewport, displaySetsToDisplay: [dicomSeg.sopClassHandler], }, + { + namespace: dicomPmap.viewport, + displaySetsToDisplay: [dicomPmap.sopClassHandler], + }, ], }, }; diff --git a/modes/basic-test-mode/src/initToolGroups.ts b/modes/basic-test-mode/src/initToolGroups.ts index db956dd553..7c183d5202 100644 --- a/modes/basic-test-mode/src/initToolGroups.ts +++ b/modes/basic-test-mode/src/initToolGroups.ts @@ -1,3 +1,15 @@ +const colours = { + 'viewport-0': 'rgb(200, 0, 0)', + 'viewport-1': 'rgb(200, 200, 0)', + 'viewport-2': 'rgb(0, 200, 0)', +}; + +const colorsByOrientation = { + axial: 'rgb(200, 0, 0)', + sagittal: 'rgb(200, 200, 0)', + coronal: 'rgb(0, 200, 0)', +}; + function initDefaultToolGroup(extensionManager, toolGroupService, commandsManager, toolGroupId) { const utilityModule = extensionManager.getModuleEntry( '@ohif/extension-cornerstone.utilityModule.tools' @@ -48,9 +60,10 @@ function initDefaultToolGroup(extensionManager, toolGroupService, commandsManage { toolName: toolNames.RectangleROI }, { toolName: toolNames.StackScroll }, { toolName: toolNames.Angle }, + { toolName: toolNames.CobbAngle }, { toolName: toolNames.Magnify }, { toolName: toolNames.SegmentationDisplay }, - + { toolName: toolNames.WindowLevelRegion }, { toolName: toolNames.UltrasoundDirectional }, { toolName: toolNames.PlanarFreehandROI }, { toolName: toolNames.SplineROI }, @@ -113,6 +126,7 @@ function initSRToolGroup(extensionManager, toolGroupService, commandsManager) { { toolName: SRToolNames.SRBidirectional }, { toolName: SRToolNames.SREllipticalROI }, { toolName: SRToolNames.SRCircleROI }, + { toolName: toolNames.WindowLevelRegion }, ], enabled: [ { @@ -132,6 +146,9 @@ function initMPRToolGroup(extensionManager, toolGroupService, commandsManager) { '@ohif/extension-cornerstone.utilityModule.tools' ); + const serviceManager = extensionManager._servicesManager; + const { cornerstoneViewportService } = serviceManager.services; + const { toolNames, Enums } = utilityModule.exports; const tools = { @@ -178,6 +195,7 @@ function initMPRToolGroup(extensionManager, toolGroupService, commandsManager) { { toolName: toolNames.StackScroll }, { toolName: toolNames.Angle }, { toolName: toolNames.SegmentationDisplay }, + { toolName: toolNames.WindowLevelRegion }, ], disabled: [ { @@ -188,6 +206,20 @@ function initMPRToolGroup(extensionManager, toolGroupService, commandsManager) { enabled: false, panSize: 10, }, + getReferenceLineColor: viewportId => { + const viewportInfo = cornerstoneViewportService.getViewportInfo(viewportId); + const viewportOptions = viewportInfo?.viewportOptions; + if (viewportOptions) { + return ( + colours[viewportOptions.id] || + colorsByOrientation[viewportOptions.orientation] || + '#0c0' + ); + } else { + console.warn('missing viewport?', viewportId); + return '#0c0'; + } + }, }, }, { toolName: toolNames.ReferenceLines }, diff --git a/modes/basic-test-mode/src/moreTools.ts b/modes/basic-test-mode/src/moreTools.ts index d1f34ec095..204bac680d 100644 --- a/modes/basic-test-mode/src/moreTools.ts +++ b/modes/basic-test-mode/src/moreTools.ts @@ -135,11 +135,19 @@ const moreTools = [ commands: setToolActiveToolbar, evaluate: 'evaluate.cornerstoneTool', }), + createButton({ + id: 'CobbAngle', + icon: 'icon-tool-cobb-angle', + label: 'Cobb Angle', + tooltip: 'Cobb Angle', + commands: setToolActiveToolbar, + evaluate: 'evaluate.cornerstoneTool', + }), createButton({ id: 'Magnify', icon: 'tool-magnify', - label: 'Magnify', - tooltip: 'Magnify', + label: 'Zoom-in', + tooltip: 'Zoom-in', commands: setToolActiveToolbar, evaluate: 'evaluate.cornerstoneTool', }), @@ -169,8 +177,8 @@ const moreTools = [ createButton({ id: 'AdvancedMagnify', icon: 'icon-tool-loupe', - label: 'Loupe', - tooltip: 'Loupe', + label: 'Magnify Probe', + tooltip: 'Magnify Probe', commands: 'toggleActiveDisabledToolbar', evaluate: 'evaluate.cornerstoneTool.toggle.ifStrictlyDisabled', }), @@ -182,6 +190,14 @@ const moreTools = [ commands: setToolActiveToolbar, evaluate: ['evaluate.cornerstoneTool', 'evaluate.isUS'], }), + createButton({ + id: 'WindowLevelRegion', + icon: 'icon-tool-window-region', + label: 'Window Level Region', + tooltip: 'Window Level Region', + commands: setToolActiveToolbar, + evaluate: 'evaluate.cornerstoneTool', + }), ], }, }, diff --git a/modes/longitudinal/.webpack/webpack.dev.js b/modes/longitudinal/.webpack/webpack.dev.js index 4bf848b6c5..1b8e34cfd1 100644 --- a/modes/longitudinal/.webpack/webpack.dev.js +++ b/modes/longitudinal/.webpack/webpack.dev.js @@ -4,7 +4,7 @@ const SRC_DIR = path.join(__dirname, '../src'); const DIST_DIR = path.join(__dirname, '../dist'); const ENTRY = { - app: `${SRC_DIR}/index.js`, + app: `${SRC_DIR}/index.ts`, }; module.exports = (env, argv) => { diff --git a/modes/longitudinal/.webpack/webpack.prod.js b/modes/longitudinal/.webpack/webpack.prod.js index 6b84361f24..b60b8908ae 100644 --- a/modes/longitudinal/.webpack/webpack.prod.js +++ b/modes/longitudinal/.webpack/webpack.prod.js @@ -10,7 +10,7 @@ const ROOT_DIR = path.join(__dirname, './../'); const SRC_DIR = path.join(__dirname, '../src'); const DIST_DIR = path.join(__dirname, '../dist'); const ENTRY = { - app: `${SRC_DIR}/index.js`, + app: `${SRC_DIR}/index.ts`, }; module.exports = (env, argv) => { diff --git a/modes/longitudinal/CHANGELOG.md b/modes/longitudinal/CHANGELOG.md index 4c27f96494..0295ce1309 100644 --- a/modes/longitudinal/CHANGELOG.md +++ b/modes/longitudinal/CHANGELOG.md @@ -3,6 +3,711 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.9.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.70...v3.9.0-beta.71) (2024-07-30) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.69...v3.9.0-beta.70) (2024-07-30) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.68...v3.9.0-beta.69) (2024-07-27) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.67...v3.9.0-beta.68) (2024-07-26) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.66...v3.9.0-beta.67) (2024-07-26) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.65...v3.9.0-beta.66) (2024-07-24) + + +### Features + +* **pmap:** added support for parametric map ([#4284](https://github.com/OHIF/Viewers/issues/4284)) ([fc0064f](https://github.com/OHIF/Viewers/commit/fc0064fd9d8cdc8fde81b81f0e71fd5d077ca22b)) + + + + + +# [3.9.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.64...v3.9.0-beta.65) (2024-07-23) + + +### Features + +* **SR:** text structured report (TEXT, CODE, NUM, PNAME, DATE, TIME and DATETIME) ([#4287](https://github.com/OHIF/Viewers/issues/4287)) ([246ebab](https://github.com/OHIF/Viewers/commit/246ebab6ebf5431a704a1861a5804045b9644ba4)) + + + + + +# [3.9.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.63...v3.9.0-beta.64) (2024-07-19) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.62...v3.9.0-beta.63) (2024-07-10) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.61...v3.9.0-beta.62) (2024-07-09) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.60...v3.9.0-beta.61) (2024-07-09) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.59...v3.9.0-beta.60) (2024-07-09) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.58...v3.9.0-beta.59) (2024-07-05) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.57...v3.9.0-beta.58) (2024-07-04) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.56...v3.9.0-beta.57) (2024-07-02) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.55...v3.9.0-beta.56) (2024-07-02) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.54...v3.9.0-beta.55) (2024-06-28) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.53...v3.9.0-beta.54) (2024-06-28) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.52...v3.9.0-beta.53) (2024-06-28) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.51...v3.9.0-beta.52) (2024-06-27) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.50...v3.9.0-beta.51) (2024-06-27) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.49...v3.9.0-beta.50) (2024-06-26) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.48...v3.9.0-beta.49) (2024-06-26) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.47...v3.9.0-beta.48) (2024-06-25) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.46...v3.9.0-beta.47) (2024-06-21) + + +### Features + +* **sort:** custom series sort in study panel ([#4214](https://github.com/OHIF/Viewers/issues/4214)) ([a433d40](https://github.com/OHIF/Viewers/commit/a433d406e2cac13f644203996c682260b54e8865)) + + + + + +# [3.9.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.45...v3.9.0-beta.46) (2024-06-18) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.44...v3.9.0-beta.45) (2024-06-18) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.43...v3.9.0-beta.44) (2024-06-17) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.42...v3.9.0-beta.43) (2024-06-12) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.41...v3.9.0-beta.42) (2024-06-12) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.40...v3.9.0-beta.41) (2024-06-12) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.39...v3.9.0-beta.40) (2024-06-12) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.38...v3.9.0-beta.39) (2024-06-08) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.37...v3.9.0-beta.38) (2024-06-07) + + +### Bug Fixes + +* **window-level:** move window level region to more tools menu ([#4215](https://github.com/OHIF/Viewers/issues/4215)) ([33f4c18](https://github.com/OHIF/Viewers/commit/33f4c18f2687d30a250fe7183df3daae8394a984)) + + + + + +# [3.9.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.36...v3.9.0-beta.37) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.35...v3.9.0-beta.36) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.34...v3.9.0-beta.35) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.33...v3.9.0-beta.34) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.32...v3.9.0-beta.33) (2024-06-05) + + +### Features + +* **window-level-region:** add window level region tool ([#4127](https://github.com/OHIF/Viewers/issues/4127)) ([ab1a18a](https://github.com/OHIF/Viewers/commit/ab1a18af5a5b0f9086c080ed81c8fda9bfaa975b)) + + + + + +# [3.9.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.31...v3.9.0-beta.32) (2024-05-31) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.30...v3.9.0-beta.31) (2024-05-30) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.29...v3.9.0-beta.30) (2024-05-30) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.28...v3.9.0-beta.29) (2024-05-30) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.27...v3.9.0-beta.28) (2024-05-30) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.26...v3.9.0-beta.27) (2024-05-29) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.25...v3.9.0-beta.26) (2024-05-29) + + +### Features + +* **hp:** Add displayArea option for Hanging protocols and example with Mamo([#3808](https://github.com/OHIF/Viewers/issues/3808)) ([18ac08e](https://github.com/OHIF/Viewers/commit/18ac08ed860d119721c52e4ffc270332259100b6)) + + + + + +# [3.9.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.24...v3.9.0-beta.25) (2024-05-29) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.23...v3.9.0-beta.24) (2024-05-29) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.22...v3.9.0-beta.23) (2024-05-28) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.21...v3.9.0-beta.22) (2024-05-27) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.20...v3.9.0-beta.21) (2024-05-24) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.19...v3.9.0-beta.20) (2024-05-24) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.18...v3.9.0-beta.19) (2024-05-24) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.17...v3.9.0-beta.18) (2024-05-24) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.16...v3.9.0-beta.17) (2024-05-23) + + +### Bug Fixes + +* **crosshairs:** reset angle, position, and slabthickness for crosshairs when reset viewport tool is used ([#4113](https://github.com/OHIF/Viewers/issues/4113)) ([73d9e99](https://github.com/OHIF/Viewers/commit/73d9e99d5d6f38ab6c36f4471d54f18798feacb4)) + + + + + +# [3.9.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.15...v3.9.0-beta.16) (2024-05-23) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.14...v3.9.0-beta.15) (2024-05-22) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.13...v3.9.0-beta.14) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.12...v3.9.0-beta.13) (2024-05-21) + + +### Features + +* **rt:** allow rendering of points in RT Struct ([#4128](https://github.com/OHIF/Viewers/issues/4128)) ([5903b07](https://github.com/OHIF/Viewers/commit/5903b0749aa41112d2e991bf53ed29b1fd7bd13f)) + + + + + +# [3.9.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.11...v3.9.0-beta.12) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.10...v3.9.0-beta.11) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.9...v3.9.0-beta.10) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.8...v3.9.0-beta.9) (2024-05-17) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.7...v3.9.0-beta.8) (2024-05-16) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.6...v3.9.0-beta.7) (2024-05-15) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.5...v3.9.0-beta.6) (2024-05-15) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.4...v3.9.0-beta.5) (2024-05-14) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.3...v3.9.0-beta.4) (2024-05-14) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.2...v3.9.0-beta.3) (2024-05-08) + + +### Features + +* **typings:** Enhance typing support with withAppTypes and custom services throughout OHIF ([#4090](https://github.com/OHIF/Viewers/issues/4090)) ([374065b](https://github.com/OHIF/Viewers/commit/374065bc3bad9d212f9817a8d41546cc64cfabfb)) + + + + + +# [3.9.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.1...v3.9.0-beta.2) (2024-05-06) + + +### Bug Fixes + +* **bugs:** enhancements and bugs in several areas ([#4086](https://github.com/OHIF/Viewers/issues/4086)) ([730f434](https://github.com/OHIF/Viewers/commit/730f4349100f21b4489a21707dbb2dca9dbfbba2)) + + + + + +# [3.9.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.0...v3.9.0-beta.1) (2024-05-06) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.9.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.94...v3.9.0-beta.0) (2024-04-29) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.8.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0-beta.94) (2024-04-29) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19) + + +### Bug Fixes + +* **layouts:** and fix thumbnail in touch and update migration guide for 3.8 release ([#4052](https://github.com/OHIF/Viewers/issues/4052)) ([d250d04](https://github.com/OHIF/Viewers/commit/d250d04580883446fcb8d748b2a97c5c198922af)) + + + + + +# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + +# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18) + +**Note:** Version bump only for package @ohif/mode-longitudinal + + + + + # [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17) **Note:** Version bump only for package @ohif/mode-longitudinal diff --git a/modes/longitudinal/package.json b/modes/longitudinal/package.json index 74f928eec6..fc0c348e11 100644 --- a/modes/longitudinal/package.json +++ b/modes/longitudinal/package.json @@ -1,12 +1,12 @@ { "name": "@ohif/mode-longitudinal", - "version": "3.8.0-beta.82", + "version": "3.9.0-beta.71", "description": "Longitudinal Workflow", "author": "OHIF", "license": "MIT", "repository": "OHIF/Viewers", "main": "dist/ohif-mode-longitudinal.js", - "module": "src/index.js", + "module": "src/index.ts", "engines": { "node": ">=14", "npm": ">=6", @@ -34,22 +34,22 @@ "test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests" }, "peerDependencies": { - "@ohif/core": "3.8.0-beta.82", - "@ohif/extension-cornerstone": "3.8.0-beta.82", - "@ohif/extension-cornerstone-dicom-rt": "3.8.0-beta.82", - "@ohif/extension-cornerstone-dicom-seg": "3.8.0-beta.82", - "@ohif/extension-cornerstone-dicom-sr": "3.8.0-beta.82", - "@ohif/extension-default": "3.8.0-beta.82", - "@ohif/extension-dicom-pdf": "3.8.0-beta.82", - "@ohif/extension-dicom-video": "3.8.0-beta.82", - "@ohif/extension-measurement-tracking": "3.8.0-beta.82" + "@ohif/core": "3.9.0-beta.71", + "@ohif/extension-cornerstone": "3.9.0-beta.71", + "@ohif/extension-cornerstone-dicom-rt": "3.9.0-beta.71", + "@ohif/extension-cornerstone-dicom-seg": "3.9.0-beta.71", + "@ohif/extension-cornerstone-dicom-sr": "3.9.0-beta.71", + "@ohif/extension-default": "3.9.0-beta.71", + "@ohif/extension-dicom-pdf": "3.9.0-beta.71", + "@ohif/extension-dicom-video": "3.9.0-beta.71", + "@ohif/extension-measurement-tracking": "3.9.0-beta.71" }, "dependencies": { "@babel/runtime": "^7.20.13", "i18next": "^17.0.3" }, "devDependencies": { - "webpack": "^5.50.0", + "webpack": "5.89.0", "webpack-merge": "^5.7.3" } } diff --git a/modes/longitudinal/src/index.js b/modes/longitudinal/src/index.ts similarity index 92% rename from modes/longitudinal/src/index.js rename to modes/longitudinal/src/index.ts index bfa6792ca2..4ad67f50da 100644 --- a/modes/longitudinal/src/index.js +++ b/modes/longitudinal/src/index.ts @@ -7,7 +7,7 @@ import moreTools from './moreTools'; // Allow this mode by excluding non-imaging modalities such as SR, SEG // Also, SM is not a simple imaging modalities, so exclude it. -const NON_IMAGE_MODALITIES = ['SM', 'ECG', 'SR', 'SEG', 'RTSTRUCT']; +const NON_IMAGE_MODALITIES = ['SM', 'ECG', 'SEG', 'RTSTRUCT']; const ohif = { layout: '@ohif/extension-default.layoutTemplateModule.viewerLayout', @@ -42,6 +42,11 @@ const dicomSeg = { panel: '@ohif/extension-cornerstone-dicom-seg.panelModule.panelSegmentation', }; +const dicomPmap = { + sopClassHandler: '@ohif/extension-cornerstone-dicom-pmap.sopClassHandlerModule.dicom-pmap', + viewport: '@ohif/extension-cornerstone-dicom-pmap.viewportModule.dicom-pmap', +}; + const dicomRT = { viewport: '@ohif/extension-cornerstone-dicom-rt.viewportModule.dicom-rt', sopClassHandler: '@ohif/extension-cornerstone-dicom-rt.sopClassHandlerModule.dicom-rt', @@ -54,6 +59,7 @@ const extensionDependencies = { '@ohif/extension-measurement-tracking': '^3.0.0', '@ohif/extension-cornerstone-dicom-sr': '^3.0.0', '@ohif/extension-cornerstone-dicom-seg': '^3.0.0', + '@ohif/extension-cornerstone-dicom-pmap': '^3.0.0', '@ohif/extension-cornerstone-dicom-rt': '^3.0.0', '@ohif/extension-dicom-pdf': '^3.0.1', '@ohif/extension-dicom-video': '^3.0.1', @@ -70,7 +76,7 @@ function modeFactory({ modeConfiguration }) { /** * Lifecycle hooks */ - onModeEnter: function ({ servicesManager, extensionManager, commandsManager }) { + onModeEnter: function ({ servicesManager, extensionManager, commandsManager }: withAppTypes) { const { measurementService, toolbarService, toolGroupService, customizationService } = servicesManager.services; @@ -90,6 +96,7 @@ function modeFactory({ modeConfiguration }) { // }, // ]); + // Init Default and SR ToolGroups initToolGroups(extensionManager, toolGroupService, commandsManager, this.labelConfig); @@ -135,7 +142,7 @@ function modeFactory({ modeConfiguration }) { // ]), // ]; }, - onModeExit: ({ servicesManager }) => { + onModeExit: ({ servicesManager }: withAppTypes) => { const { toolGroupService, syncGroupService, @@ -168,7 +175,7 @@ function modeFactory({ modeConfiguration }) { valid: !!modalities_list.filter(modality => NON_IMAGE_MODALITIES.indexOf(modality) === -1) .length, description: - 'The mode does not support studies that ONLY include the following modalities: SM, ECG, SR, SEG, RTSTRUCT', + 'The mode does not support studies that ONLY include the following modalities: SM, ECG, SEG, RTSTRUCT', }; }, routes: [ @@ -205,6 +212,10 @@ function modeFactory({ modeConfiguration }) { namespace: dicomSeg.viewport, displaySetsToDisplay: [dicomSeg.sopClassHandler], }, + { + namespace: dicomPmap.viewport, + displaySetsToDisplay: [dicomPmap.sopClassHandler], + }, { namespace: dicomRT.viewport, displaySetsToDisplay: [dicomRT.sopClassHandler], @@ -225,6 +236,7 @@ function modeFactory({ modeConfiguration }) { sopClassHandlers: [ dicomvideo.sopClassHandler, dicomSeg.sopClassHandler, + dicomPmap.sopClassHandler, ohif.sopClassHandler, dicompdf.sopClassHandler, dicomsr.sopClassHandler, diff --git a/modes/longitudinal/src/initToolGroups.js b/modes/longitudinal/src/initToolGroups.js index 983f1f56a6..d50bf4fe9c 100644 --- a/modes/longitudinal/src/initToolGroups.js +++ b/modes/longitudinal/src/initToolGroups.js @@ -1,3 +1,15 @@ +const colours = { + 'viewport-0': 'rgb(200, 0, 0)', + 'viewport-1': 'rgb(200, 200, 0)', + 'viewport-2': 'rgb(0, 200, 0)', +}; + +const colorsByOrientation = { + axial: 'rgb(200, 0, 0)', + sagittal: 'rgb(200, 200, 0)', + coronal: 'rgb(0, 200, 0)', +}; + function initDefaultToolGroup( extensionManager, toolGroupService, @@ -65,11 +77,17 @@ function initDefaultToolGroup( { toolName: toolNames.Magnify }, { toolName: toolNames.SegmentationDisplay }, { toolName: toolNames.CalibrationLine }, - + { + toolName: toolNames.PlanarFreehandContourSegmentation, + configuration: { + displayOnePointAsCrosshairs: true, + }, + }, { toolName: toolNames.UltrasoundDirectional }, { toolName: toolNames.PlanarFreehandROI }, { toolName: toolNames.SplineROI }, { toolName: toolNames.LivewireContour }, + { toolName: toolNames.WindowLevelRegion }, ], enabled: [{ toolName: toolNames.ImageOverlayViewer }, { toolName: toolNames.ReferenceLines }], disabled: [ @@ -136,6 +154,13 @@ function initSRToolGroup(extensionManager, toolGroupService) { { toolName: SRToolNames.SRCircleROI }, { toolName: SRToolNames.SRPlanarFreehandROI }, { toolName: SRToolNames.SRRectangleROI }, + { toolName: toolNames.WindowLevelRegion }, + { + toolName: SRToolNames.SRPlanarFreehandContourSegmentation, + configuration: { + displayOnePointAsCrosshairs: true, + }, + }, ], enabled: [ { @@ -155,6 +180,9 @@ function initMPRToolGroup(extensionManager, toolGroupService, commandsManager, m '@ohif/extension-cornerstone.utilityModule.tools' ); + const serviceManager = extensionManager._servicesManager; + const { cornerstoneViewportService } = serviceManager.services; + const { toolNames, Enums } = utilityModule.exports; const tools = { @@ -210,17 +238,43 @@ function initMPRToolGroup(extensionManager, toolGroupService, commandsManager, m { toolName: toolNames.CobbAngle }, { toolName: toolNames.PlanarFreehandROI }, { toolName: toolNames.SegmentationDisplay }, + { toolName: toolNames.WindowLevelRegion }, + { + toolName: toolNames.PlanarFreehandContourSegmentation, + configuration: { + displayOnePointAsCrosshairs: true, + }, + }, ], disabled: [ { toolName: toolNames.Crosshairs, configuration: { - viewportIndicators: false, + viewportIndicators: true, + viewportIndicatorsConfig: { + circleRadius: 5, + xOffset: 0.95, + yOffset: 0.05, + }, disableOnPassive: true, autoPan: { enabled: false, panSize: 10, }, + getReferenceLineColor: viewportId => { + const viewportInfo = cornerstoneViewportService.getViewportInfo(viewportId); + const viewportOptions = viewportInfo?.viewportOptions; + if (viewportOptions) { + return ( + colours[viewportOptions.id] || + colorsByOrientation[viewportOptions.orientation] || + '#0c0' + ); + } else { + console.warn('missing viewport?', viewportId); + return '#0c0'; + } + }, }, }, { diff --git a/modes/longitudinal/src/moreTools.ts b/modes/longitudinal/src/moreTools.ts index 101aebf803..3c4ca9310d 100644 --- a/modes/longitudinal/src/moreTools.ts +++ b/modes/longitudinal/src/moreTools.ts @@ -135,11 +135,19 @@ const moreTools = [ commands: setToolActiveToolbar, evaluate: 'evaluate.cornerstoneTool', }), + createButton({ + id: 'CobbAngle', + icon: 'icon-tool-cobb-angle', + label: 'Cobb Angle', + tooltip: 'Cobb Angle', + commands: setToolActiveToolbar, + evaluate: 'evaluate.cornerstoneTool', + }), createButton({ id: 'Magnify', icon: 'tool-magnify', - label: 'Magnify', - tooltip: 'Magnify', + label: 'Zoom-in', + tooltip: 'Zoom-in', commands: setToolActiveToolbar, evaluate: 'evaluate.cornerstoneTool', }), @@ -161,8 +169,8 @@ const moreTools = [ createButton({ id: 'AdvancedMagnify', icon: 'icon-tool-loupe', - label: 'Loupe', - tooltip: 'Loupe', + label: 'Magnify Probe', + tooltip: 'Magnify Probe', commands: 'toggleActiveDisabledToolbar', evaluate: 'evaluate.cornerstoneTool.toggle.ifStrictlyDisabled', }), @@ -174,6 +182,14 @@ const moreTools = [ commands: setToolActiveToolbar, evaluate: ['evaluate.cornerstoneTool', 'evaluate.isUS'], }), + createButton({ + id: 'WindowLevelRegion', + icon: 'icon-tool-window-region', + label: 'Window Level Region', + tooltip: 'Window Level Region', + commands: setToolActiveToolbar, + evaluate: 'evaluate.cornerstoneTool', + }), ], }, }, diff --git a/modes/microscopy/CHANGELOG.md b/modes/microscopy/CHANGELOG.md index 29126be6ba..44639e2ac1 100644 --- a/modes/microscopy/CHANGELOG.md +++ b/modes/microscopy/CHANGELOG.md @@ -3,6 +3,690 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.9.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.70...v3.9.0-beta.71) (2024-07-30) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.69...v3.9.0-beta.70) (2024-07-30) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.68...v3.9.0-beta.69) (2024-07-27) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.67...v3.9.0-beta.68) (2024-07-26) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.66...v3.9.0-beta.67) (2024-07-26) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.65...v3.9.0-beta.66) (2024-07-24) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.64...v3.9.0-beta.65) (2024-07-23) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.63...v3.9.0-beta.64) (2024-07-19) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.62...v3.9.0-beta.63) (2024-07-10) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.61...v3.9.0-beta.62) (2024-07-09) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.60...v3.9.0-beta.61) (2024-07-09) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.59...v3.9.0-beta.60) (2024-07-09) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.58...v3.9.0-beta.59) (2024-07-05) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.57...v3.9.0-beta.58) (2024-07-04) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.56...v3.9.0-beta.57) (2024-07-02) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.55...v3.9.0-beta.56) (2024-07-02) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.54...v3.9.0-beta.55) (2024-06-28) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.53...v3.9.0-beta.54) (2024-06-28) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.52...v3.9.0-beta.53) (2024-06-28) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.51...v3.9.0-beta.52) (2024-06-27) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.50...v3.9.0-beta.51) (2024-06-27) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.49...v3.9.0-beta.50) (2024-06-26) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.48...v3.9.0-beta.49) (2024-06-26) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.47...v3.9.0-beta.48) (2024-06-25) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.46...v3.9.0-beta.47) (2024-06-21) + + +### Bug Fixes + +* Allow the mode setup/creation to be async, and provide a few more values to extension/app config/mode setup. ([#4016](https://github.com/OHIF/Viewers/issues/4016)) ([88575c6](https://github.com/OHIF/Viewers/commit/88575c6c09fd778a31b2f91524163ce65d1639dd)) + + + + + +# [3.9.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.45...v3.9.0-beta.46) (2024-06-18) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.44...v3.9.0-beta.45) (2024-06-18) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.43...v3.9.0-beta.44) (2024-06-17) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.42...v3.9.0-beta.43) (2024-06-12) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.41...v3.9.0-beta.42) (2024-06-12) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.40...v3.9.0-beta.41) (2024-06-12) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.39...v3.9.0-beta.40) (2024-06-12) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.38...v3.9.0-beta.39) (2024-06-08) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.37...v3.9.0-beta.38) (2024-06-07) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.36...v3.9.0-beta.37) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.35...v3.9.0-beta.36) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.34...v3.9.0-beta.35) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.33...v3.9.0-beta.34) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.32...v3.9.0-beta.33) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.31...v3.9.0-beta.32) (2024-05-31) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.30...v3.9.0-beta.31) (2024-05-30) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.29...v3.9.0-beta.30) (2024-05-30) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.28...v3.9.0-beta.29) (2024-05-30) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.27...v3.9.0-beta.28) (2024-05-30) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.26...v3.9.0-beta.27) (2024-05-29) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.25...v3.9.0-beta.26) (2024-05-29) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.24...v3.9.0-beta.25) (2024-05-29) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.23...v3.9.0-beta.24) (2024-05-29) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.22...v3.9.0-beta.23) (2024-05-28) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.21...v3.9.0-beta.22) (2024-05-27) + + +### Features + +* **ui:** move to React 18 and base for using shadcn/ui ([#4174](https://github.com/OHIF/Viewers/issues/4174)) ([70f2c79](https://github.com/OHIF/Viewers/commit/70f2c797f42af603d7ea0eb8d23b4103aba66f77)) + + + + + +# [3.9.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.20...v3.9.0-beta.21) (2024-05-24) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.19...v3.9.0-beta.20) (2024-05-24) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.18...v3.9.0-beta.19) (2024-05-24) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.17...v3.9.0-beta.18) (2024-05-24) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.16...v3.9.0-beta.17) (2024-05-23) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.15...v3.9.0-beta.16) (2024-05-23) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.14...v3.9.0-beta.15) (2024-05-22) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.13...v3.9.0-beta.14) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.12...v3.9.0-beta.13) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.11...v3.9.0-beta.12) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.10...v3.9.0-beta.11) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.9...v3.9.0-beta.10) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.8...v3.9.0-beta.9) (2024-05-17) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.7...v3.9.0-beta.8) (2024-05-16) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.6...v3.9.0-beta.7) (2024-05-15) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.5...v3.9.0-beta.6) (2024-05-15) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.4...v3.9.0-beta.5) (2024-05-14) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.3...v3.9.0-beta.4) (2024-05-14) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.2...v3.9.0-beta.3) (2024-05-08) + + +### Features + +* **typings:** Enhance typing support with withAppTypes and custom services throughout OHIF ([#4090](https://github.com/OHIF/Viewers/issues/4090)) ([374065b](https://github.com/OHIF/Viewers/commit/374065bc3bad9d212f9817a8d41546cc64cfabfb)) + + + + + +# [3.9.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.1...v3.9.0-beta.2) (2024-05-06) + + +### Bug Fixes + +* **bugs:** enhancements and bugs in several areas ([#4086](https://github.com/OHIF/Viewers/issues/4086)) ([730f434](https://github.com/OHIF/Viewers/commit/730f4349100f21b4489a21707dbb2dca9dbfbba2)) + + + + + +# [3.9.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.0...v3.9.0-beta.1) (2024-05-06) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.9.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.94...v3.9.0-beta.0) (2024-04-29) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.8.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0-beta.94) (2024-04-29) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + +# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18) + +**Note:** Version bump only for package @ohif/mode-microscopy + + + + + # [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17) **Note:** Version bump only for package @ohif/mode-microscopy diff --git a/modes/microscopy/babel.config.js b/modes/microscopy/babel.config.js index a38ddda212..9705ae6f28 100644 --- a/modes/microscopy/babel.config.js +++ b/modes/microscopy/babel.config.js @@ -1,5 +1,5 @@ module.exports = { - plugins: ['inline-react-svg', '@babel/plugin-proposal-class-properties'], + plugins: ['@babel/plugin-proposal-class-properties'], env: { test: { presets: [ @@ -37,7 +37,7 @@ module.exports = { '@babel/preset-react', '@babel/preset-typescript', ], - plugins: ['react-hot-loader/babel'], + plugins: ['react-refresh/babel'], ignore: ['**/*.test.jsx', '**/*.test.js', '__snapshots__', '__tests__'], }, }, diff --git a/modes/microscopy/package.json b/modes/microscopy/package.json index 387b605ba2..35047d4382 100644 --- a/modes/microscopy/package.json +++ b/modes/microscopy/package.json @@ -1,6 +1,6 @@ { "name": "@ohif/mode-microscopy", - "version": "3.8.0-beta.82", + "version": "3.9.0-beta.71", "description": "OHIF mode for DICOM microscopy", "author": "OHIF", "license": "MIT", @@ -35,8 +35,8 @@ "test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests" }, "peerDependencies": { - "@ohif/core": "3.8.0-beta.82", - "@ohif/extension-dicom-microscopy": "3.8.0-beta.82" + "@ohif/core": "3.9.0-beta.71", + "@ohif/extension-dicom-microscopy": "3.9.0-beta.71" }, "dependencies": { "@babel/runtime": "^7.20.13", diff --git a/modes/microscopy/src/index.tsx b/modes/microscopy/src/index.tsx index 5c0bdba805..50b19e7663 100644 --- a/modes/microscopy/src/index.tsx +++ b/modes/microscopy/src/index.tsx @@ -47,14 +47,14 @@ function modeFactory({ modeConfiguration }) { /** * Lifecycle hooks */ - onModeEnter: ({ servicesManager, extensionManager, commandsManager }) => { + onModeEnter: ({ servicesManager, extensionManager, commandsManager }: withAppTypes) => { const { toolbarService } = servicesManager.services; toolbarService.addButtons(toolbarButtons); - toolbarService.createButtonSection('primary', ['MeasurementTools', 'dragPan']); + toolbarService.createButtonSection('primary', ['MeasurementTools', 'dragPan', 'TagBrowser']); }, - onModeExit: ({ servicesManager }) => { + onModeExit: ({ servicesManager }: withAppTypes) => { const { toolbarService, uiDialogService, uiModalService } = servicesManager.services; uiDialogService.dismissAll(); @@ -113,7 +113,6 @@ function modeFactory({ modeConfiguration }) { }, ], extensions: extensionDependencies, - hangingProtocols: [ohif.hangingProtocols], hangingProtocol: ['default'], // Order is important in sop class handlers when two handlers both use diff --git a/modes/microscopy/src/toolbarButtons.js b/modes/microscopy/src/toolbarButtons.js index 9954089d7d..82c774683d 100644 --- a/modes/microscopy/src/toolbarButtons.js +++ b/modes/microscopy/src/toolbarButtons.js @@ -145,6 +145,20 @@ const toolbarButtons = [ evaluate: 'evaluate.microscopyTool', }, }, + { + id: 'TagBrowser', + uiType: 'ohif.radioGroup', + props: { + icon: 'dicom-tag-browser', + label: 'Dicom Tag Browser', + commands: [ + { + commandName: 'openDICOMTagViewer', + }, + ], + evaluate: 'evaluate.action', + }, + }, ]; export default toolbarButtons; diff --git a/modes/preclinical-4d/CHANGELOG.md b/modes/preclinical-4d/CHANGELOG.md index 155a1959dd..677bc6d718 100644 --- a/modes/preclinical-4d/CHANGELOG.md +++ b/modes/preclinical-4d/CHANGELOG.md @@ -3,6 +3,699 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.9.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.70...v3.9.0-beta.71) (2024-07-30) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.69...v3.9.0-beta.70) (2024-07-30) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.68...v3.9.0-beta.69) (2024-07-27) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.67...v3.9.0-beta.68) (2024-07-26) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.66...v3.9.0-beta.67) (2024-07-26) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.65...v3.9.0-beta.66) (2024-07-24) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.64...v3.9.0-beta.65) (2024-07-23) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.63...v3.9.0-beta.64) (2024-07-19) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.62...v3.9.0-beta.63) (2024-07-10) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.61...v3.9.0-beta.62) (2024-07-09) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.60...v3.9.0-beta.61) (2024-07-09) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.59...v3.9.0-beta.60) (2024-07-09) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.58...v3.9.0-beta.59) (2024-07-05) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.57...v3.9.0-beta.58) (2024-07-04) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.56...v3.9.0-beta.57) (2024-07-02) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.55...v3.9.0-beta.56) (2024-07-02) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.54...v3.9.0-beta.55) (2024-06-28) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.53...v3.9.0-beta.54) (2024-06-28) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.52...v3.9.0-beta.53) (2024-06-28) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.51...v3.9.0-beta.52) (2024-06-27) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.50...v3.9.0-beta.51) (2024-06-27) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.49...v3.9.0-beta.50) (2024-06-26) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.48...v3.9.0-beta.49) (2024-06-26) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.47...v3.9.0-beta.48) (2024-06-25) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.46...v3.9.0-beta.47) (2024-06-21) + + +### Bug Fixes + +* Allow the mode setup/creation to be async, and provide a few more values to extension/app config/mode setup. ([#4016](https://github.com/OHIF/Viewers/issues/4016)) ([88575c6](https://github.com/OHIF/Viewers/commit/88575c6c09fd778a31b2f91524163ce65d1639dd)) + + + + + +# [3.9.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.45...v3.9.0-beta.46) (2024-06-18) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.44...v3.9.0-beta.45) (2024-06-18) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.43...v3.9.0-beta.44) (2024-06-17) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.42...v3.9.0-beta.43) (2024-06-12) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.41...v3.9.0-beta.42) (2024-06-12) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.40...v3.9.0-beta.41) (2024-06-12) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.39...v3.9.0-beta.40) (2024-06-12) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.38...v3.9.0-beta.39) (2024-06-08) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.37...v3.9.0-beta.38) (2024-06-07) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.36...v3.9.0-beta.37) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.35...v3.9.0-beta.36) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.34...v3.9.0-beta.35) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.33...v3.9.0-beta.34) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.32...v3.9.0-beta.33) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.31...v3.9.0-beta.32) (2024-05-31) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.30...v3.9.0-beta.31) (2024-05-30) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.29...v3.9.0-beta.30) (2024-05-30) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.28...v3.9.0-beta.29) (2024-05-30) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.27...v3.9.0-beta.28) (2024-05-30) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.26...v3.9.0-beta.27) (2024-05-29) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.25...v3.9.0-beta.26) (2024-05-29) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.24...v3.9.0-beta.25) (2024-05-29) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.23...v3.9.0-beta.24) (2024-05-29) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.22...v3.9.0-beta.23) (2024-05-28) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.21...v3.9.0-beta.22) (2024-05-27) + + +### Features + +* **ui:** move to React 18 and base for using shadcn/ui ([#4174](https://github.com/OHIF/Viewers/issues/4174)) ([70f2c79](https://github.com/OHIF/Viewers/commit/70f2c797f42af603d7ea0eb8d23b4103aba66f77)) + + + + + +# [3.9.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.20...v3.9.0-beta.21) (2024-05-24) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.19...v3.9.0-beta.20) (2024-05-24) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.18...v3.9.0-beta.19) (2024-05-24) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.17...v3.9.0-beta.18) (2024-05-24) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.16...v3.9.0-beta.17) (2024-05-23) + + +### Bug Fixes + +* **crosshairs:** reset angle, position, and slabthickness for crosshairs when reset viewport tool is used ([#4113](https://github.com/OHIF/Viewers/issues/4113)) ([73d9e99](https://github.com/OHIF/Viewers/commit/73d9e99d5d6f38ab6c36f4471d54f18798feacb4)) + + + + + +# [3.9.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.15...v3.9.0-beta.16) (2024-05-23) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.14...v3.9.0-beta.15) (2024-05-22) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.13...v3.9.0-beta.14) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.12...v3.9.0-beta.13) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.11...v3.9.0-beta.12) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.10...v3.9.0-beta.11) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.9...v3.9.0-beta.10) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.8...v3.9.0-beta.9) (2024-05-17) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.7...v3.9.0-beta.8) (2024-05-16) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.6...v3.9.0-beta.7) (2024-05-15) + + +### Bug Fixes + +* **tmtv:** threshold was crashing the side panel ([#4119](https://github.com/OHIF/Viewers/issues/4119)) ([8d5c676](https://github.com/OHIF/Viewers/commit/8d5c676a5e1f3eda664071c8aece313de766bd59)) + + + + + +# [3.9.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.5...v3.9.0-beta.6) (2024-05-15) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.4...v3.9.0-beta.5) (2024-05-14) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.3...v3.9.0-beta.4) (2024-05-14) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.2...v3.9.0-beta.3) (2024-05-08) + + +### Features + +* **typings:** Enhance typing support with withAppTypes and custom services throughout OHIF ([#4090](https://github.com/OHIF/Viewers/issues/4090)) ([374065b](https://github.com/OHIF/Viewers/commit/374065bc3bad9d212f9817a8d41546cc64cfabfb)) + + + + + +# [3.9.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.1...v3.9.0-beta.2) (2024-05-06) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.0...v3.9.0-beta.1) (2024-05-06) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.9.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.94...v3.9.0-beta.0) (2024-04-29) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.8.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0-beta.94) (2024-04-29) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29) + + +### Bug Fixes + +* **toolbox:** Preserve user-specified tool state and streamline command execution ([#4063](https://github.com/OHIF/Viewers/issues/4063)) ([f1a736d](https://github.com/OHIF/Viewers/commit/f1a736d1934733a434cb87b2c284907a3122403f)) + + + + + +# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19) + + +### Features + +* **tmtv-mode:** Add Brush tools and move SUV peak calculation to web worker ([#4053](https://github.com/OHIF/Viewers/issues/4053)) ([8192e34](https://github.com/OHIF/Viewers/commit/8192e348eca993fec331d4963efe88f9a730eceb)) + + + + + +# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + +# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18) + +**Note:** Version bump only for package @ohif/mode-preclinical-4d + + + + + # [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17) **Note:** Version bump only for package @ohif/mode-preclinical-4d diff --git a/modes/preclinical-4d/babel.config.js b/modes/preclinical-4d/babel.config.js index a38ddda212..9705ae6f28 100644 --- a/modes/preclinical-4d/babel.config.js +++ b/modes/preclinical-4d/babel.config.js @@ -1,5 +1,5 @@ module.exports = { - plugins: ['inline-react-svg', '@babel/plugin-proposal-class-properties'], + plugins: ['@babel/plugin-proposal-class-properties'], env: { test: { presets: [ @@ -37,7 +37,7 @@ module.exports = { '@babel/preset-react', '@babel/preset-typescript', ], - plugins: ['react-hot-loader/babel'], + plugins: ['react-refresh/babel'], ignore: ['**/*.test.jsx', '**/*.test.js', '__snapshots__', '__tests__'], }, }, diff --git a/modes/preclinical-4d/package.json b/modes/preclinical-4d/package.json index 4c2bc7a7a6..1b74d85ead 100644 --- a/modes/preclinical-4d/package.json +++ b/modes/preclinical-4d/package.json @@ -1,6 +1,6 @@ { "name": "@ohif/mode-preclinical-4d", - "version": "3.8.0-beta.82", + "version": "3.9.0-beta.71", "description": "4D Workflow", "author": "OHIF", "license": "MIT", @@ -30,18 +30,18 @@ "test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests" }, "peerDependencies": { - "@ohif/core": "3.8.0-beta.82", - "@ohif/extension-cornerstone": "3.8.0-beta.82", - "@ohif/extension-cornerstone-dicom-seg": "3.8.0-beta.82", - "@ohif/extension-cornerstone-dynamic-volume": "3.8.0-beta.82", - "@ohif/extension-default": "3.8.0-beta.82", - "@ohif/extension-tmtv": "3.8.0-beta.82" + "@ohif/core": "3.9.0-beta.71", + "@ohif/extension-cornerstone": "3.9.0-beta.71", + "@ohif/extension-cornerstone-dicom-seg": "3.9.0-beta.71", + "@ohif/extension-cornerstone-dynamic-volume": "3.9.0-beta.71", + "@ohif/extension-default": "3.9.0-beta.71", + "@ohif/extension-tmtv": "3.9.0-beta.71" }, "dependencies": { "@babel/runtime": "^7.20.13" }, "devDependencies": { - "webpack": "^5.50.0", + "webpack": "5.89.0", "webpack-merge": "^5.7.3" } } diff --git a/modes/preclinical-4d/src/index.tsx b/modes/preclinical-4d/src/index.tsx index 213a5f618b..209e30fc03 100644 --- a/modes/preclinical-4d/src/index.tsx +++ b/modes/preclinical-4d/src/index.tsx @@ -37,7 +37,7 @@ function modeFactory({ modeConfiguration }) { id, routeName: 'dynamic-volume', displayName: '4D PT/CT', - onModeEnter: function ({ servicesManager, extensionManager, commandsManager }) { + onModeEnter: function ({ servicesManager, extensionManager, commandsManager }: withAppTypes) { const { measurementService, toolbarService, @@ -55,7 +55,7 @@ function modeFactory({ modeConfiguration }) { const { toolNames, Enums } = utilityModule.exports; measurementService.clearMeasurements(); - initToolGroups({ toolNames, Enums, toolGroupService, commandsManager }); + initToolGroups({ toolNames, Enums, toolGroupService, commandsManager, servicesManager }); toolbarService.addButtons([...toolbarButtons, ...segmentationButtons]); toolbarService.createButtonSection('secondary', ['ProgressDropdown']); @@ -86,12 +86,12 @@ function modeFactory({ modeConfiguration }) { } ); }, - onSetupRouteComplete: ({ servicesManager }) => { + onSetupRouteComplete: ({ servicesManager }: withAppTypes) => { // This needs to run after hanging protocol matching process because // it may change the protocol/stage based on workflow stage settings initWorkflowSteps({ servicesManager }); }, - onModeExit: ({ servicesManager }) => { + onModeExit: ({ servicesManager }: withAppTypes) => { const { toolGroupService, syncGroupService, diff --git a/modes/preclinical-4d/src/initToolGroups.tsx b/modes/preclinical-4d/src/initToolGroups.tsx index 9a64576188..e477c7feb2 100644 --- a/modes/preclinical-4d/src/initToolGroups.tsx +++ b/modes/preclinical-4d/src/initToolGroups.tsx @@ -5,7 +5,20 @@ const toolGroupIds = { CT: 'dynamic4D-ct', }; -function _initToolGroups(toolNames, Enums, toolGroupService, commandsManager) { +const colours = { + 'viewport-0': 'rgb(200, 0, 0)', + 'viewport-1': 'rgb(200, 200, 0)', + 'viewport-2': 'rgb(0, 200, 0)', +}; + +const colorsByOrientation = { + axial: 'rgb(200, 0, 0)', + sagittal: 'rgb(200, 200, 0)', + coronal: 'rgb(0, 200, 0)', +}; + +function _initToolGroups(toolNames, Enums, toolGroupService, commandsManager, servicesManager) { + const { cornerstoneViewportService } = servicesManager.services; const tools = { active: [ { @@ -94,12 +107,31 @@ function _initToolGroups(toolNames, Enums, toolGroupService, commandsManager) { { toolName: toolNames.Crosshairs, configuration: { - viewportIndicators: false, + viewportIndicators: true, + viewportIndicatorsConfig: { + circleRadius: 5, + xOffset: 0.95, + yOffset: 0.05, + }, disableOnPassive: true, autoPan: { enabled: false, panSize: 10, }, + getReferenceLineColor: viewportId => { + const viewportInfo = cornerstoneViewportService.getViewportInfo(viewportId); + const viewportOptions = viewportInfo?.viewportOptions; + if (viewportOptions) { + return ( + colours[viewportOptions.id] || + colorsByOrientation[viewportOptions.orientation] || + '#0c0' + ); + } else { + console.warn('missing viewport?', viewportId); + return '#0c0'; + } + }, }, }, ], @@ -123,8 +155,8 @@ function _initToolGroups(toolNames, Enums, toolGroupService, commandsManager) { toolGroupService.createToolGroupAndAddTools(toolGroupIds.default, tools); } -function initToolGroups({ toolNames, Enums, toolGroupService, commandsManager }) { - _initToolGroups(toolNames, Enums, toolGroupService, commandsManager); +function initToolGroups({ toolNames, Enums, toolGroupService, commandsManager, servicesManager }) { + _initToolGroups(toolNames, Enums, toolGroupService, commandsManager, servicesManager); } export { initToolGroups as default, toolGroupIds }; diff --git a/modes/preclinical-4d/src/initWorkflowSteps.ts b/modes/preclinical-4d/src/initWorkflowSteps.ts index 8b36fe48d9..47b423a63c 100644 --- a/modes/preclinical-4d/src/initWorkflowSteps.ts +++ b/modes/preclinical-4d/src/initWorkflowSteps.ts @@ -1,6 +1,6 @@ import getWorkflowSettings from './getWorkflowSettings'; -export default function initWorkflowSteps({ servicesManager }): void { +export default function initWorkflowSteps({ servicesManager }: withAppTypes): void { const { workflowStepsService } = servicesManager.services; const workflowSettings = getWorkflowSettings({ servicesManager }); diff --git a/modes/preclinical-4d/src/segmentationButtons.ts b/modes/preclinical-4d/src/segmentationButtons.ts index 330cdcf48b..4a4e1a89d9 100644 --- a/modes/preclinical-4d/src/segmentationButtons.ts +++ b/modes/preclinical-4d/src/segmentationButtons.ts @@ -1,16 +1,5 @@ import type { Button } from '@ohif/core/types'; -function _createSetToolActiveCommands(toolName) { - return [ - { - commandName: 'setToolActive', - commandOptions: { - toolName, - }, - }, - ]; -} - const toolbarButtons: Button[] = [ { id: 'BrushTools', @@ -26,10 +15,9 @@ const toolbarButtons: Button[] = [ name: 'evaluate.cornerstone.segmentation', toolNames: ['CircularBrush', 'SphereBrush'], }, - commands: _createSetToolActiveCommands('CircularBrush'), options: [ { - name: 'Radius (mm)', + name: 'Size (mm)', id: 'brush-radius', type: 'range', min: 0.5, @@ -62,7 +50,6 @@ const toolbarButtons: Button[] = [ name: 'evaluate.cornerstone.segmentation', toolNames: ['CircularEraser', 'SphereEraser'], }, - commands: _createSetToolActiveCommands('CircularEraser'), options: [ { name: 'Radius (mm)', @@ -98,7 +85,6 @@ const toolbarButtons: Button[] = [ name: 'evaluate.cornerstone.segmentation', toolNames: ['ThresholdCircularBrush', 'ThresholdSphereBrush'], }, - commands: _createSetToolActiveCommands('ThresholdCircularBrush'), options: [ { name: 'Radius (mm)', @@ -131,9 +117,9 @@ const toolbarButtons: Button[] = [ type: 'double-range', id: 'threshold-range', min: 0, - max: 10, - step: 1, - values: [2, 5], + max: 100, + step: 0.5, + value: [2, 50], commands: { commandName: 'setThresholdRange', commandOptions: { @@ -156,7 +142,6 @@ const toolbarButtons: Button[] = [ toolNames: ['CircleScissor', 'SphereScissor', 'RectangleScissor'], }, icon: 'icon-tool-shape', - commands: _createSetToolActiveCommands('CircleScissor'), options: [ { name: 'Shape', diff --git a/modes/segmentation/.webpack/webpack.prod.js b/modes/segmentation/.webpack/webpack.prod.js index 163392a699..95d7bfea57 100644 --- a/modes/segmentation/.webpack/webpack.prod.js +++ b/modes/segmentation/.webpack/webpack.prod.js @@ -51,6 +51,38 @@ const config = { extensions: ['.js', '.jsx', '.ts', '.tsx'], }, }, + { + test: /\.svg?$/, + oneOf: [ + { + use: [ + { + loader: '@svgr/webpack', + options: { + svgoConfig: { + plugins: [ + { + name: 'preset-default', + params: { + overrides: { + removeViewBox: false + }, + }, + }, + ] + }, + prettier: false, + svgo: true, + titleProp: true, + }, + }, + ], + issuer: { + and: [/\.(ts|tsx|js|jsx|md|mdx)$/], + }, + }, + ], + }, ], }, resolve: { diff --git a/modes/segmentation/CHANGELOG.md b/modes/segmentation/CHANGELOG.md index 9b12e7eaad..cc7ac47e62 100644 --- a/modes/segmentation/CHANGELOG.md +++ b/modes/segmentation/CHANGELOG.md @@ -3,6 +3,717 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.9.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.70...v3.9.0-beta.71) (2024-07-30) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.69...v3.9.0-beta.70) (2024-07-30) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.68...v3.9.0-beta.69) (2024-07-27) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.67...v3.9.0-beta.68) (2024-07-26) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.66...v3.9.0-beta.67) (2024-07-26) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.65...v3.9.0-beta.66) (2024-07-24) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.64...v3.9.0-beta.65) (2024-07-23) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.63...v3.9.0-beta.64) (2024-07-19) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.62...v3.9.0-beta.63) (2024-07-10) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.61...v3.9.0-beta.62) (2024-07-09) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.60...v3.9.0-beta.61) (2024-07-09) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.59...v3.9.0-beta.60) (2024-07-09) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.58...v3.9.0-beta.59) (2024-07-05) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.57...v3.9.0-beta.58) (2024-07-04) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.56...v3.9.0-beta.57) (2024-07-02) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.55...v3.9.0-beta.56) (2024-07-02) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.54...v3.9.0-beta.55) (2024-06-28) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.53...v3.9.0-beta.54) (2024-06-28) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.52...v3.9.0-beta.53) (2024-06-28) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.51...v3.9.0-beta.52) (2024-06-27) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.50...v3.9.0-beta.51) (2024-06-27) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.49...v3.9.0-beta.50) (2024-06-26) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.48...v3.9.0-beta.49) (2024-06-26) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.47...v3.9.0-beta.48) (2024-06-25) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.46...v3.9.0-beta.47) (2024-06-21) + + +### Bug Fixes + +* Allow the mode setup/creation to be async, and provide a few more values to extension/app config/mode setup. ([#4016](https://github.com/OHIF/Viewers/issues/4016)) ([88575c6](https://github.com/OHIF/Viewers/commit/88575c6c09fd778a31b2f91524163ce65d1639dd)) + + + + + +# [3.9.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.45...v3.9.0-beta.46) (2024-06-18) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.44...v3.9.0-beta.45) (2024-06-18) + + +### Bug Fixes + +* Re-enable hpScale module ([#4237](https://github.com/OHIF/Viewers/issues/4237)) ([2eab049](https://github.com/OHIF/Viewers/commit/2eab049d7993bb834f7736093941c175f16d61fc)) + + + + + +# [3.9.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.43...v3.9.0-beta.44) (2024-06-17) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.42...v3.9.0-beta.43) (2024-06-12) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.41...v3.9.0-beta.42) (2024-06-12) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.40...v3.9.0-beta.41) (2024-06-12) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.39...v3.9.0-beta.40) (2024-06-12) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.38...v3.9.0-beta.39) (2024-06-08) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.37...v3.9.0-beta.38) (2024-06-07) + + +### Bug Fixes + +* **window-level:** move window level region to more tools menu ([#4215](https://github.com/OHIF/Viewers/issues/4215)) ([33f4c18](https://github.com/OHIF/Viewers/commit/33f4c18f2687d30a250fe7183df3daae8394a984)) + + + + + +# [3.9.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.36...v3.9.0-beta.37) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.35...v3.9.0-beta.36) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.34...v3.9.0-beta.35) (2024-06-05) + + +### Bug Fixes + +* **seg:** maintain algorithm name and algorithm type when DICOM seg is exported or downloaded ([#4203](https://github.com/OHIF/Viewers/issues/4203)) ([a29e94d](https://github.com/OHIF/Viewers/commit/a29e94de803f79bbb3372d00ad8eb14b4224edc2)) + + + + + +# [3.9.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.33...v3.9.0-beta.34) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.32...v3.9.0-beta.33) (2024-06-05) + + +### Features + +* **window-level-region:** add window level region tool ([#4127](https://github.com/OHIF/Viewers/issues/4127)) ([ab1a18a](https://github.com/OHIF/Viewers/commit/ab1a18af5a5b0f9086c080ed81c8fda9bfaa975b)) + + + + + +# [3.9.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.31...v3.9.0-beta.32) (2024-05-31) + + +### Bug Fixes + +* **tmtv:** crosshairs should not have viewport indicators ([#4197](https://github.com/OHIF/Viewers/issues/4197)) ([f85da32](https://github.com/OHIF/Viewers/commit/f85da32f34389ef7cecae03c07e0af26468b52a6)) + + + + + +# [3.9.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.30...v3.9.0-beta.31) (2024-05-30) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.29...v3.9.0-beta.30) (2024-05-30) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.28...v3.9.0-beta.29) (2024-05-30) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.27...v3.9.0-beta.28) (2024-05-30) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.26...v3.9.0-beta.27) (2024-05-29) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.25...v3.9.0-beta.26) (2024-05-29) + + +### Features + +* **hp:** Add displayArea option for Hanging protocols and example with Mamo([#3808](https://github.com/OHIF/Viewers/issues/3808)) ([18ac08e](https://github.com/OHIF/Viewers/commit/18ac08ed860d119721c52e4ffc270332259100b6)) + + + + + +# [3.9.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.24...v3.9.0-beta.25) (2024-05-29) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.23...v3.9.0-beta.24) (2024-05-29) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.22...v3.9.0-beta.23) (2024-05-28) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.21...v3.9.0-beta.22) (2024-05-27) + + +### Features + +* **ui:** move to React 18 and base for using shadcn/ui ([#4174](https://github.com/OHIF/Viewers/issues/4174)) ([70f2c79](https://github.com/OHIF/Viewers/commit/70f2c797f42af603d7ea0eb8d23b4103aba66f77)) + + + + + +# [3.9.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.20...v3.9.0-beta.21) (2024-05-24) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.19...v3.9.0-beta.20) (2024-05-24) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.18...v3.9.0-beta.19) (2024-05-24) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.17...v3.9.0-beta.18) (2024-05-24) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.16...v3.9.0-beta.17) (2024-05-23) + + +### Bug Fixes + +* **crosshairs:** reset angle, position, and slabthickness for crosshairs when reset viewport tool is used ([#4113](https://github.com/OHIF/Viewers/issues/4113)) ([73d9e99](https://github.com/OHIF/Viewers/commit/73d9e99d5d6f38ab6c36f4471d54f18798feacb4)) + + + + + +# [3.9.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.15...v3.9.0-beta.16) (2024-05-23) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.14...v3.9.0-beta.15) (2024-05-22) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.13...v3.9.0-beta.14) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.12...v3.9.0-beta.13) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.11...v3.9.0-beta.12) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.10...v3.9.0-beta.11) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.9...v3.9.0-beta.10) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.8...v3.9.0-beta.9) (2024-05-17) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.7...v3.9.0-beta.8) (2024-05-16) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.6...v3.9.0-beta.7) (2024-05-15) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.5...v3.9.0-beta.6) (2024-05-15) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.4...v3.9.0-beta.5) (2024-05-14) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.3...v3.9.0-beta.4) (2024-05-14) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.2...v3.9.0-beta.3) (2024-05-08) + + +### Features + +* **typings:** Enhance typing support with withAppTypes and custom services throughout OHIF ([#4090](https://github.com/OHIF/Viewers/issues/4090)) ([374065b](https://github.com/OHIF/Viewers/commit/374065bc3bad9d212f9817a8d41546cc64cfabfb)) + + + + + +# [3.9.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.1...v3.9.0-beta.2) (2024-05-06) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.0...v3.9.0-beta.1) (2024-05-06) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.9.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.94...v3.9.0-beta.0) (2024-04-29) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.8.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0-beta.94) (2024-04-29) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29) + + +### Bug Fixes + +* **toolbox:** Preserve user-specified tool state and streamline command execution ([#4063](https://github.com/OHIF/Viewers/issues/4063)) ([f1a736d](https://github.com/OHIF/Viewers/commit/f1a736d1934733a434cb87b2c284907a3122403f)) + + + + + +# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19) + + +### Bug Fixes + +* **layouts:** and fix thumbnail in touch and update migration guide for 3.8 release ([#4052](https://github.com/OHIF/Viewers/issues/4052)) ([d250d04](https://github.com/OHIF/Viewers/commit/d250d04580883446fcb8d748b2a97c5c198922af)) + + + + + +# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + +# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18) + + +### Bug Fixes + +* **bugs:** and replace seriesInstanceUID and seriesInstanceUIDs URL with seriesInstanceUIDs ([#4049](https://github.com/OHIF/Viewers/issues/4049)) ([da7c1a5](https://github.com/OHIF/Viewers/commit/da7c1a5d8c54bfa1d3f97bbc500386bf76e7fd9d)) + + + + + +# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18) + +**Note:** Version bump only for package @ohif/mode-segmentation + + + + + # [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17) **Note:** Version bump only for package @ohif/mode-segmentation diff --git a/modes/segmentation/babel.config.js b/modes/segmentation/babel.config.js index a38ddda212..771573b602 100644 --- a/modes/segmentation/babel.config.js +++ b/modes/segmentation/babel.config.js @@ -1,5 +1,5 @@ module.exports = { - plugins: ['inline-react-svg', '@babel/plugin-proposal-class-properties'], + plugins: [ '@babel/plugin-proposal-class-properties'], env: { test: { presets: [ @@ -37,7 +37,7 @@ module.exports = { '@babel/preset-react', '@babel/preset-typescript', ], - plugins: ['react-hot-loader/babel'], + plugins: ['react-refresh/babel'], ignore: ['**/*.test.jsx', '**/*.test.js', '__snapshots__', '__tests__'], }, }, diff --git a/modes/segmentation/package.json b/modes/segmentation/package.json index 98ed80d958..d1f4fc2b2f 100644 --- a/modes/segmentation/package.json +++ b/modes/segmentation/package.json @@ -1,6 +1,6 @@ { "name": "@ohif/mode-segmentation", - "version": "3.8.0-beta.82", + "version": "3.9.0-beta.71", "description": "OHIF segmentation mode which enables labelmap segmentation read/edit/export", "author": "@ohif", "license": "MIT", @@ -35,42 +35,42 @@ "test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests" }, "peerDependencies": { - "@ohif/core": "3.8.0-beta.82", - "@ohif/extension-cornerstone": "3.8.0-beta.82", - "@ohif/extension-cornerstone-dicom-rt": "3.8.0-beta.82", - "@ohif/extension-cornerstone-dicom-seg": "3.8.0-beta.82", - "@ohif/extension-cornerstone-dicom-sr": "3.8.0-beta.82", - "@ohif/extension-default": "3.8.0-beta.82", - "@ohif/extension-dicom-pdf": "3.8.0-beta.82", - "@ohif/extension-dicom-video": "3.8.0-beta.82" + "@ohif/core": "3.9.0-beta.71", + "@ohif/extension-cornerstone": "3.9.0-beta.71", + "@ohif/extension-cornerstone-dicom-rt": "3.9.0-beta.71", + "@ohif/extension-cornerstone-dicom-seg": "3.9.0-beta.71", + "@ohif/extension-cornerstone-dicom-sr": "3.9.0-beta.71", + "@ohif/extension-default": "3.9.0-beta.71", + "@ohif/extension-dicom-pdf": "3.9.0-beta.71", + "@ohif/extension-dicom-video": "3.9.0-beta.71" }, "dependencies": { "@babel/runtime": "^7.20.13", "i18next": "^17.0.3" }, "devDependencies": { - "@babel/core": "^7.23.2", + "@babel/core": "7.24.7", "@babel/plugin-proposal-class-properties": "^7.16.7", "@babel/plugin-proposal-object-rest-spread": "^7.17.3", "@babel/plugin-proposal-private-methods": "^7.18.6", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-transform-arrow-functions": "^7.16.7", "@babel/plugin-transform-regenerator": "^7.16.7", - "@babel/plugin-transform-runtime": "^7.23.2", + "@babel/plugin-transform-runtime": "7.24.7", "@babel/plugin-transform-typescript": "^7.13.0", "@babel/preset-env": "7.23.2", "@babel/preset-react": "^7.16.7", "@babel/preset-typescript": "^7.13.0", + "@svgr/webpack": "^8.1.0", "babel-eslint": "^10.1.0", "babel-loader": "^8.0.0-beta.4", - "babel-plugin-inline-react-svg": "^2.0.1", "clean-webpack-plugin": "^4.0.0", "copy-webpack-plugin": "^10.2.0", "cross-env": "^7.0.3", "dotenv": "^14.1.0", - "eslint": "^5.0.1", + "eslint": "^8.39.0", "eslint-loader": "^2.0.0", - "webpack": "^5.50.0", + "webpack": "5.89.0", "webpack-cli": "^4.7.2", "webpack-merge": "^5.7.3" } diff --git a/modes/segmentation/src/index.tsx b/modes/segmentation/src/index.tsx index 85a55a8305..a37e617631 100644 --- a/modes/segmentation/src/index.tsx +++ b/modes/segmentation/src/index.tsx @@ -53,7 +53,7 @@ function modeFactory({ modeConfiguration }) { * Runs when the Mode Route is mounted to the DOM. Usually used to initialize * Services and other resources. */ - onModeEnter: ({ servicesManager, extensionManager, commandsManager }) => { + onModeEnter: ({ servicesManager, extensionManager, commandsManager }: withAppTypes) => { const { measurementService, toolbarService, toolGroupService } = servicesManager.services; measurementService.clearMeasurements(); @@ -76,7 +76,7 @@ function modeFactory({ modeConfiguration }) { ]); toolbarService.createButtonSection('segmentationToolbox', ['BrushTools', 'Shapes']); }, - onModeExit: ({ servicesManager }) => { + onModeExit: ({ servicesManager }: withAppTypes) => { const { toolGroupService, syncGroupService, @@ -156,7 +156,9 @@ function modeFactory({ modeConfiguration }) { /** List of extensions that are used by the mode */ extensions: extensionDependencies, /** HangingProtocol used by the mode */ - // hangingProtocol: [''], + // Commented out to just use the most applicable registered hanging protocol + // The example is used for a grid layout to specify that as a preferred layout + // hangingProtocol: ['@ohif/mnGrid'], /** SopClassHandlers used by the mode */ sopClassHandlers: [ohif.sopClassHandler, segmentation.sopClassHandler], /** hotkeys for mode */ diff --git a/modes/segmentation/src/initToolGroups.ts b/modes/segmentation/src/initToolGroups.ts index 8b2c28da94..babfe4a113 100644 --- a/modes/segmentation/src/initToolGroups.ts +++ b/modes/segmentation/src/initToolGroups.ts @@ -1,3 +1,15 @@ +const colours = { + 'viewport-0': 'rgb(200, 0, 0)', + 'viewport-1': 'rgb(200, 200, 0)', + 'viewport-2': 'rgb(0, 200, 0)', +}; + +const colorsByOrientation = { + axial: 'rgb(200, 0, 0)', + sagittal: 'rgb(200, 200, 0)', + coronal: 'rgb(0, 200, 0)', +}; + function createTools(utilityModule) { const { toolNames, Enums } = utilityModule.exports; return { @@ -55,10 +67,13 @@ function createTools(utilityModule) { parentTool: 'Brush', configuration: { activeStrategy: 'THRESHOLD_INSIDE_CIRCLE', - preview: { - enabled: true, - }, + // preview: { + // enabled: true, + // }, strategySpecificConfiguration: { + // to use the use the center segment index to determine + // if inside -> same segment, if outside -> eraser + // useCenterSegmentIndex: true, THRESHOLD: { isDynamic: true, dynamicRadius: 3, @@ -72,6 +87,7 @@ function createTools(utilityModule) { { toolName: toolNames.StackScroll }, { toolName: toolNames.Magnify }, { toolName: toolNames.SegmentationDisplay }, + { toolName: toolNames.WindowLevelRegion }, { toolName: toolNames.UltrasoundDirectional }, ], @@ -91,17 +107,38 @@ function initMPRToolGroup(extensionManager, toolGroupService, commandsManager) { const utilityModule = extensionManager.getModuleEntry( '@ohif/extension-cornerstone.utilityModule.tools' ); + const servicesManager = extensionManager._servicesManager; + const { cornerstoneViewportService } = servicesManager.services; const tools = createTools(utilityModule); tools.disabled.push( { toolName: utilityModule.exports.toolNames.Crosshairs, configuration: { - viewportIndicators: false, + viewportIndicators: true, + viewportIndicatorsConfig: { + circleRadius: 5, + xOffset: 0.95, + yOffset: 0.05, + }, disableOnPassive: true, autoPan: { enabled: false, panSize: 10, }, + getReferenceLineColor: viewportId => { + const viewportInfo = cornerstoneViewportService.getViewportInfo(viewportId); + const viewportOptions = viewportInfo?.viewportOptions; + if (viewportOptions) { + return ( + colours[viewportOptions.id] || + colorsByOrientation[viewportOptions.orientation] || + '#0c0' + ); + } else { + console.warn('missing viewport?', viewportId); + return '#0c0'; + } + }, }, }, { toolName: utilityModule.exports.toolNames.ReferenceLines } diff --git a/modes/segmentation/src/segmentationButtons.ts b/modes/segmentation/src/segmentationButtons.ts index cb096a9c68..448267f029 100644 --- a/modes/segmentation/src/segmentationButtons.ts +++ b/modes/segmentation/src/segmentationButtons.ts @@ -1,16 +1,5 @@ import type { Button } from '@ohif/core/types'; -function _createSetToolActiveCommands(toolName) { - return [ - { - commandName: 'setToolActive', - commandOptions: { - toolName, - }, - }, - ]; -} - const toolbarButtons: Button[] = [ { id: 'BrushTools', @@ -27,7 +16,6 @@ const toolbarButtons: Button[] = [ toolNames: ['CircularBrush', 'SphereBrush'], disabledText: 'Create new segmentation to enable this tool.', }, - commands: _createSetToolActiveCommands('CircularBrush'), options: [ { name: 'Radius (mm)', @@ -63,7 +51,6 @@ const toolbarButtons: Button[] = [ name: 'evaluate.cornerstone.segmentation', toolNames: ['CircularEraser', 'SphereEraser'], }, - commands: _createSetToolActiveCommands('CircularEraser'), options: [ { name: 'Radius (mm)', @@ -99,7 +86,6 @@ const toolbarButtons: Button[] = [ name: 'evaluate.cornerstone.segmentation', toolNames: ['ThresholdCircularBrush', 'ThresholdSphereBrush'], }, - commands: _createSetToolActiveCommands('ThresholdCircularBrush'), options: [ { name: 'Radius (mm)', @@ -112,21 +98,15 @@ const toolbarButtons: Button[] = [ commands: { commandName: 'setBrushSize', commandOptions: { - toolNames: ['ThresholdCircularBrush', 'ThresholdSphereBrush'], + toolNames: [ + 'ThresholdCircularBrush', + 'ThresholdSphereBrush', + 'ThresholdCircularBrushDynamic', + ], }, }, }, - { - name: 'Shape', - type: 'radio', - id: 'eraser-mode', - value: 'ThresholdCircularBrush', - values: [ - { value: 'ThresholdCircularBrush', label: 'Circle' }, - { value: 'ThresholdSphereBrush', label: 'Sphere' }, - ], - commands: 'setToolActiveToolbar', - }, + { name: 'Threshold', type: 'radio', @@ -136,18 +116,38 @@ const toolbarButtons: Button[] = [ { value: 'ThresholdDynamic', label: 'Dynamic' }, { value: 'ThresholdRange', label: 'Range' }, ], - commands: ({ value, commandsManager }) => { + commands: ({ value, commandsManager, options }) => { if (value === 'ThresholdDynamic') { commandsManager.run('setToolActive', { toolName: 'ThresholdCircularBrushDynamic', }); - } else { - commandsManager.run('setToolActive', { - toolName: 'ThresholdCircularBrush', - }); + + return; } + + // check the condition of the threshold-range option + const thresholdRangeOption = options.find( + option => option.id === 'threshold-shape' + ); + + commandsManager.run('setToolActiveToolbar', { + toolName: thresholdRangeOption.value, + }); }, }, + { + name: 'Shape', + type: 'radio', + id: 'threshold-shape', + value: 'ThresholdCircularBrush', + values: [ + { value: 'ThresholdCircularBrush', label: 'Circle' }, + { value: 'ThresholdSphereBrush', label: 'Sphere' }, + ], + condition: ({ options }) => + options.find(option => option.id === 'dynamic-mode').value === 'ThresholdRange', + commands: 'setToolActiveToolbar', + }, { name: 'ThresholdRange', type: 'double-range', @@ -155,7 +155,7 @@ const toolbarButtons: Button[] = [ min: -1000, max: 1000, step: 1, - values: [100, 600], + value: [100, 600], condition: ({ options }) => options.find(option => option.id === 'dynamic-mode').value === 'ThresholdRange', commands: { @@ -180,7 +180,6 @@ const toolbarButtons: Button[] = [ toolNames: ['CircleScissor', 'SphereScissor', 'RectangleScissor'], }, icon: 'icon-tool-shape', - commands: _createSetToolActiveCommands('CircleScissor'), options: [ { name: 'Shape', diff --git a/modes/segmentation/src/toolbarButtons.ts b/modes/segmentation/src/toolbarButtons.ts index 1d1b445be7..89b4092c66 100644 --- a/modes/segmentation/src/toolbarButtons.ts +++ b/modes/segmentation/src/toolbarButtons.ts @@ -1,5 +1,5 @@ import type { Button } from '@ohif/core/types'; -import { defaults, ToolbarService, ViewportGridService } from '@ohif/core'; +import { ToolbarService, ViewportGridService } from '@ohif/core'; const { createButton } = ToolbarService; @@ -207,8 +207,8 @@ const toolbarButtons: Button[] = [ createButton({ id: 'Magnify', icon: 'tool-magnify', - label: 'Magnify', - tooltip: 'Magnify', + label: 'Zoom-in', + tooltip: 'Zoom-in', commands: setToolActiveToolbar, evaluate: 'evaluate.cornerstoneTool', }), @@ -238,8 +238,8 @@ const toolbarButtons: Button[] = [ createButton({ id: 'AdvancedMagnify', icon: 'icon-tool-loupe', - label: 'Loupe', - tooltip: 'Loupe', + label: 'Magnify Probe', + tooltip: 'Magnify Probe', commands: 'toggleActiveDisabledToolbar', evaluate: 'evaluate.cornerstoneTool.toggle.ifStrictlyDisabled', }), @@ -251,6 +251,14 @@ const toolbarButtons: Button[] = [ commands: setToolActiveToolbar, evaluate: ['evaluate.cornerstoneTool', 'evaluate.isUS'], }), + createButton({ + id: 'WindowLevelRegion', + icon: 'icon-tool-window-region', + label: 'Window Level Region', + tooltip: 'Window Level Region', + commands: setToolActiveToolbar, + evaluate: 'evaluate.cornerstoneTool', + }), ], }, }, diff --git a/modes/tmtv/.webpack/webpack.dev.js b/modes/tmtv/.webpack/webpack.dev.js index 4bf848b6c5..1b8e34cfd1 100644 --- a/modes/tmtv/.webpack/webpack.dev.js +++ b/modes/tmtv/.webpack/webpack.dev.js @@ -4,7 +4,7 @@ const SRC_DIR = path.join(__dirname, '../src'); const DIST_DIR = path.join(__dirname, '../dist'); const ENTRY = { - app: `${SRC_DIR}/index.js`, + app: `${SRC_DIR}/index.ts`, }; module.exports = (env, argv) => { diff --git a/modes/tmtv/.webpack/webpack.prod.js b/modes/tmtv/.webpack/webpack.prod.js index 018db058d3..f2edb43fa6 100644 --- a/modes/tmtv/.webpack/webpack.prod.js +++ b/modes/tmtv/.webpack/webpack.prod.js @@ -11,7 +11,7 @@ const SRC_DIR = path.join(__dirname, '../src'); const DIST_DIR = path.join(__dirname, '../dist'); const ENTRY = { - app: `${SRC_DIR}/index.js`, + app: `${SRC_DIR}/index.ts`, }; module.exports = (env, argv) => { diff --git a/modes/tmtv/CHANGELOG.md b/modes/tmtv/CHANGELOG.md index 12a3fc9d64..f1de43963e 100644 --- a/modes/tmtv/CHANGELOG.md +++ b/modes/tmtv/CHANGELOG.md @@ -3,6 +3,702 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.9.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.70...v3.9.0-beta.71) (2024-07-30) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.69...v3.9.0-beta.70) (2024-07-30) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.68...v3.9.0-beta.69) (2024-07-27) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.67...v3.9.0-beta.68) (2024-07-26) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.66...v3.9.0-beta.67) (2024-07-26) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.65...v3.9.0-beta.66) (2024-07-24) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.64...v3.9.0-beta.65) (2024-07-23) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.63...v3.9.0-beta.64) (2024-07-19) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.62...v3.9.0-beta.63) (2024-07-10) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.61...v3.9.0-beta.62) (2024-07-09) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.60...v3.9.0-beta.61) (2024-07-09) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.59...v3.9.0-beta.60) (2024-07-09) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.58...v3.9.0-beta.59) (2024-07-05) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.57...v3.9.0-beta.58) (2024-07-04) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.56...v3.9.0-beta.57) (2024-07-02) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.55...v3.9.0-beta.56) (2024-07-02) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.54...v3.9.0-beta.55) (2024-06-28) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.53...v3.9.0-beta.54) (2024-06-28) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.52...v3.9.0-beta.53) (2024-06-28) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.51...v3.9.0-beta.52) (2024-06-27) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.50...v3.9.0-beta.51) (2024-06-27) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.49...v3.9.0-beta.50) (2024-06-26) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.48...v3.9.0-beta.49) (2024-06-26) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.47...v3.9.0-beta.48) (2024-06-25) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.46...v3.9.0-beta.47) (2024-06-21) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.45...v3.9.0-beta.46) (2024-06-18) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.44...v3.9.0-beta.45) (2024-06-18) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.43...v3.9.0-beta.44) (2024-06-17) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.42...v3.9.0-beta.43) (2024-06-12) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.41...v3.9.0-beta.42) (2024-06-12) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.40...v3.9.0-beta.41) (2024-06-12) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.39...v3.9.0-beta.40) (2024-06-12) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.38...v3.9.0-beta.39) (2024-06-08) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.37...v3.9.0-beta.38) (2024-06-07) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.36...v3.9.0-beta.37) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.35...v3.9.0-beta.36) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.34...v3.9.0-beta.35) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.33...v3.9.0-beta.34) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.32...v3.9.0-beta.33) (2024-06-05) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.31...v3.9.0-beta.32) (2024-05-31) + + +### Bug Fixes + +* **tmtv:** crosshairs should not have viewport indicators ([#4197](https://github.com/OHIF/Viewers/issues/4197)) ([f85da32](https://github.com/OHIF/Viewers/commit/f85da32f34389ef7cecae03c07e0af26468b52a6)) + + + + + +# [3.9.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.30...v3.9.0-beta.31) (2024-05-30) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.29...v3.9.0-beta.30) (2024-05-30) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.28...v3.9.0-beta.29) (2024-05-30) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.27...v3.9.0-beta.28) (2024-05-30) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.26...v3.9.0-beta.27) (2024-05-29) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.25...v3.9.0-beta.26) (2024-05-29) + + +### Features + +* **hp:** Add displayArea option for Hanging protocols and example with Mamo([#3808](https://github.com/OHIF/Viewers/issues/3808)) ([18ac08e](https://github.com/OHIF/Viewers/commit/18ac08ed860d119721c52e4ffc270332259100b6)) + + + + + +# [3.9.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.24...v3.9.0-beta.25) (2024-05-29) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.23...v3.9.0-beta.24) (2024-05-29) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.22...v3.9.0-beta.23) (2024-05-28) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.21...v3.9.0-beta.22) (2024-05-27) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.20...v3.9.0-beta.21) (2024-05-24) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.19...v3.9.0-beta.20) (2024-05-24) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.18...v3.9.0-beta.19) (2024-05-24) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.17...v3.9.0-beta.18) (2024-05-24) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.16...v3.9.0-beta.17) (2024-05-23) + + +### Bug Fixes + +* **crosshairs:** reset angle, position, and slabthickness for crosshairs when reset viewport tool is used ([#4113](https://github.com/OHIF/Viewers/issues/4113)) ([73d9e99](https://github.com/OHIF/Viewers/commit/73d9e99d5d6f38ab6c36f4471d54f18798feacb4)) + + + + + +# [3.9.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.15...v3.9.0-beta.16) (2024-05-23) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.14...v3.9.0-beta.15) (2024-05-22) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.13...v3.9.0-beta.14) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.12...v3.9.0-beta.13) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.11...v3.9.0-beta.12) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.10...v3.9.0-beta.11) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.9...v3.9.0-beta.10) (2024-05-21) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.8...v3.9.0-beta.9) (2024-05-17) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.7...v3.9.0-beta.8) (2024-05-16) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.6...v3.9.0-beta.7) (2024-05-15) + + +### Bug Fixes + +* **tmtv:** threshold was crashing the side panel ([#4119](https://github.com/OHIF/Viewers/issues/4119)) ([8d5c676](https://github.com/OHIF/Viewers/commit/8d5c676a5e1f3eda664071c8aece313de766bd59)) + + + + + +# [3.9.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.5...v3.9.0-beta.6) (2024-05-15) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.4...v3.9.0-beta.5) (2024-05-14) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.3...v3.9.0-beta.4) (2024-05-14) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.2...v3.9.0-beta.3) (2024-05-08) + + +### Features + +* **typings:** Enhance typing support with withAppTypes and custom services throughout OHIF ([#4090](https://github.com/OHIF/Viewers/issues/4090)) ([374065b](https://github.com/OHIF/Viewers/commit/374065bc3bad9d212f9817a8d41546cc64cfabfb)) + + + + + +# [3.9.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.1...v3.9.0-beta.2) (2024-05-06) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.0...v3.9.0-beta.1) (2024-05-06) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.9.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.94...v3.9.0-beta.0) (2024-04-29) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.8.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0-beta.94) (2024-04-29) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29) + + +### Bug Fixes + +* **toolbox:** Preserve user-specified tool state and streamline command execution ([#4063](https://github.com/OHIF/Viewers/issues/4063)) ([f1a736d](https://github.com/OHIF/Viewers/commit/f1a736d1934733a434cb87b2c284907a3122403f)) + + + + + +# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19) + + +### Features + +* **tmtv-mode:** Add Brush tools and move SUV peak calculation to web worker ([#4053](https://github.com/OHIF/Viewers/issues/4053)) ([8192e34](https://github.com/OHIF/Viewers/commit/8192e348eca993fec331d4963efe88f9a730eceb)) + + + + + +# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + +# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18) + + +### Bug Fixes + +* **bugs:** and replace seriesInstanceUID and seriesInstanceUIDs URL with seriesInstanceUIDs ([#4049](https://github.com/OHIF/Viewers/issues/4049)) ([da7c1a5](https://github.com/OHIF/Viewers/commit/da7c1a5d8c54bfa1d3f97bbc500386bf76e7fd9d)) + + + + + +# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18) + +**Note:** Version bump only for package @ohif/mode-tmtv + + + + + # [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17) **Note:** Version bump only for package @ohif/mode-tmtv diff --git a/modes/tmtv/package.json b/modes/tmtv/package.json index 16fe421eca..0ecbaab3fd 100644 --- a/modes/tmtv/package.json +++ b/modes/tmtv/package.json @@ -1,12 +1,12 @@ { "name": "@ohif/mode-tmtv", - "version": "3.8.0-beta.82", + "version": "3.9.0-beta.71", "description": "Total Metabolic Tumor Volume Workflow", "author": "OHIF", "license": "MIT", "repository": "OHIF/Viewers", "main": "dist/ohif-mode-tmtv.umd.js", - "module": "src/index.js", + "module": "src/index.ts", "engines": { "node": ">=14", "npm": ">=6", @@ -34,20 +34,20 @@ "test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests" }, "peerDependencies": { - "@ohif/core": "3.8.0-beta.82", - "@ohif/extension-cornerstone": "3.8.0-beta.82", - "@ohif/extension-cornerstone-dicom-sr": "3.8.0-beta.82", - "@ohif/extension-default": "3.8.0-beta.82", - "@ohif/extension-dicom-pdf": "3.8.0-beta.82", - "@ohif/extension-dicom-video": "3.8.0-beta.82", - "@ohif/extension-measurement-tracking": "3.8.0-beta.82" + "@ohif/core": "3.9.0-beta.71", + "@ohif/extension-cornerstone": "3.9.0-beta.71", + "@ohif/extension-cornerstone-dicom-sr": "3.9.0-beta.71", + "@ohif/extension-default": "3.9.0-beta.71", + "@ohif/extension-dicom-pdf": "3.9.0-beta.71", + "@ohif/extension-dicom-video": "3.9.0-beta.71", + "@ohif/extension-measurement-tracking": "3.9.0-beta.71" }, "dependencies": { "@babel/runtime": "^7.20.13", "i18next": "^17.0.3" }, "devDependencies": { - "webpack": "^5.50.0", + "webpack": "5.89.0", "webpack-merge": "^5.7.3" } } diff --git a/modes/tmtv/src/index.js b/modes/tmtv/src/index.ts similarity index 91% rename from modes/tmtv/src/index.js rename to modes/tmtv/src/index.ts index 7acca7c923..1ef04ca73c 100644 --- a/modes/tmtv/src/index.js +++ b/modes/tmtv/src/index.ts @@ -1,7 +1,7 @@ import { hotkeys, classes } from '@ohif/core'; import toolbarButtons from './toolbarButtons.js'; import { id } from './id.js'; -import initToolGroups, { toolGroupIds } from './initToolGroups.js'; +import initToolGroups from './initToolGroups.js'; import setCrosshairsConfiguration from './utils/setCrosshairsConfiguration.js'; import setFusionActiveVolume from './utils/setFusionActiveVolume.js'; import i18n from 'i18next'; @@ -35,7 +35,7 @@ const extensionDependencies = { '@ohif/extension-tmtv': '^3.0.0', }; -let unsubscriptions = []; +const unsubscriptions = []; function modeFactory({ modeConfiguration }) { return { // TODO: We're using this as a route segment @@ -46,14 +46,13 @@ function modeFactory({ modeConfiguration }) { /** * Lifecycle hooks */ - onModeEnter: ({ servicesManager, extensionManager, commandsManager }) => { + onModeEnter: ({ servicesManager, extensionManager, commandsManager }: withAppTypes) => { const { toolbarService, toolGroupService, customizationService, hangingProtocolService, displaySetService, - viewportGridService, } = servicesManager.services; const utilityModule = extensionManager.getModuleEntry( @@ -63,7 +62,7 @@ function modeFactory({ modeConfiguration }) { const { toolNames, Enums } = utilityModule.exports; // Init Default and SR ToolGroups - initToolGroups(toolNames, Enums, toolGroupService, commandsManager); + initToolGroups(toolNames, Enums, toolGroupService, commandsManager, null, servicesManager); const { unsubscribe } = toolGroupService.subscribe( toolGroupService.EVENTS.VIEWPORT_ADDED, @@ -97,9 +96,11 @@ function modeFactory({ modeConfiguration }) { 'WindowLevel', 'Crosshairs', 'Pan', - 'SyncToggle', ]); - toolbarService.createButtonSection('ROIThresholdToolbox', ['RectangleROIStartEndThreshold']); + toolbarService.createButtonSection('ROIThresholdToolbox', [ + 'RectangleROIStartEndThreshold', + 'BrushTools', + ]); customizationService.addModeCustomizations([ { @@ -112,19 +113,6 @@ function modeFactory({ modeConfiguration }) { }, ]); - // This is a hack and we need to find a better way to enable - // some tools that require the viewport to be ready - const { unsubscribe: unsub1 } = viewportGridService.subscribe( - viewportGridService.EVENTS.VIEWPORTS_READY, - () => { - commandsManager.run('setToolEnabled', { - toolName: 'OrientationMarker', - toolGroupId: 'mipToolGroup', - }); - unsub1(); - } - ); - // For the hanging protocol we need to decide on the window level // based on whether the SUV is corrected or not, hence we can't hard // code the window level in the hanging protocol but we add a custom @@ -156,7 +144,7 @@ function modeFactory({ modeConfiguration }) { } ); }, - onModeExit: ({ servicesManager }) => { + onModeExit: ({ servicesManager }: withAppTypes) => { const { toolGroupService, syncGroupService, diff --git a/modes/tmtv/src/initToolGroups.js b/modes/tmtv/src/initToolGroups.js index 965668ff4a..899bcc32d8 100644 --- a/modes/tmtv/src/initToolGroups.js +++ b/modes/tmtv/src/initToolGroups.js @@ -4,10 +4,16 @@ export const toolGroupIds = { Fusion: 'fusionToolGroup', MIP: 'mipToolGroup', default: 'default', - // MPR: 'mpr', }; -function _initToolGroups(toolNames, Enums, toolGroupService, commandsManager, modeLabelConfig) { +function _initToolGroups( + toolNames, + Enums, + toolGroupService, + commandsManager, + modeLabelConfig, + servicesManager +) { const tools = { active: [ { @@ -59,13 +65,73 @@ function _initToolGroups(toolNames, Enums, toolGroupService, commandsManager, mo { toolName: toolNames.Angle }, { toolName: toolNames.CobbAngle }, { toolName: toolNames.Magnify }, + { + toolName: 'CircularBrush', + parentTool: 'Brush', + configuration: { + activeStrategy: 'FILL_INSIDE_CIRCLE', + }, + }, + { + toolName: 'CircularEraser', + parentTool: 'Brush', + configuration: { + activeStrategy: 'ERASE_INSIDE_CIRCLE', + }, + }, + { + toolName: 'SphereBrush', + parentTool: 'Brush', + configuration: { + activeStrategy: 'FILL_INSIDE_SPHERE', + }, + }, + { + toolName: 'SphereEraser', + parentTool: 'Brush', + configuration: { + activeStrategy: 'ERASE_INSIDE_SPHERE', + }, + }, + { + toolName: 'ThresholdCircularBrush', + parentTool: 'Brush', + configuration: { + activeStrategy: 'THRESHOLD_INSIDE_CIRCLE', + }, + }, + { + toolName: 'ThresholdSphereBrush', + parentTool: 'Brush', + configuration: { + activeStrategy: 'THRESHOLD_INSIDE_SPHERE', + }, + }, + { + toolName: 'ThresholdCircularBrushDynamic', + parentTool: 'Brush', + configuration: { + activeStrategy: 'THRESHOLD_INSIDE_CIRCLE', + // preview: { + // enabled: true, + // }, + strategySpecificConfiguration: { + // to use the use the center segment index to determine + // if inside -> same segment, if outside -> eraser + // useCenterSegmentIndex: true, + THRESHOLD: { + isDynamic: true, + dynamicRadius: 3, + }, + }, + }, + }, ], enabled: [{ toolName: toolNames.SegmentationDisplay }], disabled: [ { toolName: toolNames.Crosshairs, configuration: { - viewportIndicators: false, disableOnPassive: true, autoPan: { enabled: false, @@ -118,8 +184,22 @@ function _initToolGroups(toolNames, Enums, toolGroupService, commandsManager, mo toolGroupService.createToolGroupAndAddTools(toolGroupIds.MIP, mipTools); } -function initToolGroups(toolNames, Enums, toolGroupService, commandsManager, modeLabelConfig) { - _initToolGroups(toolNames, Enums, toolGroupService, commandsManager, modeLabelConfig); +function initToolGroups( + toolNames, + Enums, + toolGroupService, + commandsManager, + modeLabelConfig, + servicesManager +) { + _initToolGroups( + toolNames, + Enums, + toolGroupService, + commandsManager, + modeLabelConfig, + servicesManager + ); } export default initToolGroups; diff --git a/modes/tmtv/src/toolbarButtons.js b/modes/tmtv/src/toolbarButtons.js index 042a54b596..26948697b1 100644 --- a/modes/tmtv/src/toolbarButtons.js +++ b/modes/tmtv/src/toolbarButtons.js @@ -1,8 +1,6 @@ -import { defaults, ToolbarService } from '@ohif/core'; +import { ToolbarService } from '@ohif/core'; import { toolGroupIds } from './initToolGroups'; -const { windowLevelPresets } = defaults; - const setToolActiveToolbar = { commandName: 'setToolActiveToolbar', commandOptions: { @@ -107,13 +105,180 @@ const toolbarButtons = [ icon: 'tool-create-threshold', label: 'Rectangle ROI Threshold', commands: setToolActiveToolbar, - evaluate: { - name: 'evaluate.cornerstoneTool', - disabledText: 'Select the PT Axial to enable this tool', - }, + evaluate: [ + 'evaluate.cornerstone.segmentation', + // need to put the disabled text last, since each evaluator will + // merge the result text into the final result + { + name: 'evaluate.cornerstoneTool', + disabledText: 'Select the PT Axial to enable this tool', + }, + ], options: 'tmtv.RectangleROIThresholdOptions', }, }, + { + id: 'BrushTools', + uiType: 'ohif.buttonGroup', + props: { + groupId: 'BrushTools', + items: [ + { + id: 'Brush', + icon: 'icon-tool-brush', + label: 'Brush', + evaluate: { + name: 'evaluate.cornerstone.segmentation', + toolNames: ['CircularBrush', 'SphereBrush'], + disabledText: 'Create new segmentation to enable this tool.', + }, + options: [ + { + name: 'Radius (mm)', + id: 'brush-radius', + type: 'range', + min: 0.5, + max: 99.5, + step: 0.5, + value: 25, + commands: { + commandName: 'setBrushSize', + commandOptions: { toolNames: ['CircularBrush', 'SphereBrush'] }, + }, + }, + { + name: 'Shape', + type: 'radio', + id: 'brush-mode', + value: 'CircularBrush', + values: [ + { value: 'CircularBrush', label: 'Circle' }, + { value: 'SphereBrush', label: 'Sphere' }, + ], + commands: 'setToolActiveToolbar', + }, + ], + }, + { + id: 'Eraser', + icon: 'icon-tool-eraser', + label: 'Eraser', + evaluate: { + name: 'evaluate.cornerstone.segmentation', + toolNames: ['CircularEraser', 'SphereEraser'], + }, + options: [ + { + name: 'Radius (mm)', + id: 'eraser-radius', + type: 'range', + min: 0.5, + max: 99.5, + step: 0.5, + value: 25, + commands: { + commandName: 'setBrushSize', + commandOptions: { toolNames: ['CircularEraser', 'SphereEraser'] }, + }, + }, + { + name: 'Shape', + type: 'radio', + id: 'eraser-mode', + value: 'CircularEraser', + values: [ + { value: 'CircularEraser', label: 'Circle' }, + { value: 'SphereEraser', label: 'Sphere' }, + ], + commands: 'setToolActiveToolbar', + }, + ], + }, + { + id: 'Threshold', + icon: 'icon-tool-threshold', + label: 'Threshold Tool', + evaluate: { + name: 'evaluate.cornerstone.segmentation', + toolNames: ['ThresholdCircularBrush', 'ThresholdSphereBrush'], + }, + options: [ + { + name: 'Radius (mm)', + id: 'threshold-radius', + type: 'range', + min: 0.5, + max: 99.5, + step: 0.5, + value: 25, + commands: { + commandName: 'setBrushSize', + commandOptions: { + toolNames: [ + 'ThresholdCircularBrush', + 'ThresholdSphereBrush', + 'ThresholdCircularBrushDynamic', + ], + }, + }, + }, + + { + name: 'Threshold', + type: 'radio', + id: 'dynamic-mode', + value: 'ThresholdRange', + values: [ + { value: 'ThresholdDynamic', label: 'Dynamic' }, + { value: 'ThresholdRange', label: 'Range' }, + ], + commands: ({ value, commandsManager }) => { + if (value === 'ThresholdDynamic') { + commandsManager.run('setToolActive', { + toolName: 'ThresholdCircularBrushDynamic', + }); + } else { + commandsManager.run('setToolActive', { + toolName: 'ThresholdCircularBrush', + }); + } + }, + }, + { + name: 'Shape', + type: 'radio', + id: 'eraser-mode', + value: 'ThresholdCircularBrush', + values: [ + { value: 'ThresholdCircularBrush', label: 'Circle' }, + { value: 'ThresholdSphereBrush', label: 'Sphere' }, + ], + condition: ({ options }) => + options.find(option => option.id === 'dynamic-mode').value === 'ThresholdRange', + commands: 'setToolActiveToolbar', + }, + { + name: 'ThresholdRange', + type: 'double-range', + id: 'threshold-range', + min: 0, + max: 50, + step: 0.5, + value: [2.5, 50], + condition: ({ options }) => + options.find(option => option.id === 'dynamic-mode').value === 'ThresholdRange', + commands: { + commandName: 'setThresholdRange', + commandOptions: { + toolNames: ['ThresholdCircularBrush', 'ThresholdSphereBrush'], + }, + }, + }, + ], + }, + ], + }, + }, ]; export default toolbarButtons; diff --git a/nx.json b/nx.json index 5ba23220da..ce4a8069e8 100644 --- a/nx.json +++ b/nx.json @@ -10,7 +10,6 @@ "test:unit:ci", "test", "test:e2e", - "test:e2e:ci", "test:e2e:local", "test:e2e:dist", "test:e2e:serve", @@ -27,31 +26,60 @@ }, "targetDefaults": { "test:unit": { - "dependsOn": ["^test:unit"] + "dependsOn": [ + "^test:unit" + ] }, "test:unit:ci": { - "dependsOn": ["^test:unit:ci"] + "dependsOn": [ + "^test:unit:ci" + ] }, "test": { - "dependsOn": ["^test"] + "dependsOn": [ + "^test" + ] }, "test:e2e": { - "dependsOn": ["^test:e2e"] + "dependsOn": [ + "^test:e2e" + ] }, - "test:e2e:ci": { - "dependsOn": ["^test:e2e:ci"] + "test:e2e:headed": { + "dependsOn": [ + "^test:e2e:headed" + ] }, "test:e2e:local": { - "dependsOn": ["^test:e2e:local"] + "dependsOn": [ + "^test:e2e:local" + ] }, "test:e2e:dist": { - "dependsOn": ["^test:e2e:dist"] + "dependsOn": [ + "^test:e2e:dist" + ] }, "test:e2e:serve": { - "dependsOn": ["^test:e2e:serve"] + "dependsOn": [ + "^test:e2e:serve" + ] }, "build": { - "outputs": ["{projectRoot}/platform/app/dist"] + "outputs": [ + "{projectRoot}/platform/app/dist" + ] } + }, + "$schema": "./node_modules/nx/schemas/nx-schema.json", + "namedInputs": { + "default": [ + "{projectRoot}/**/*", + "sharedGlobals" + ], + "sharedGlobals": [], + "production": [ + "default" + ] } } diff --git a/package.json b/package.json index 199db41f3f..cf5d6cd0a9 100644 --- a/package.json +++ b/package.json @@ -1,20 +1,22 @@ { "name": "ohif-monorepo-root", "private": true, + "packageManager": "yarn@1.22.22", "workspaces": { "packages": [ "platform/*", "extensions/*", - "modes/*" + "modes/*", + "addOns/externals/*" ], "nohoist": [ "**/html-minifier-terser" ] }, "engines": { - "node": ">=16", + "node": ">=18", "npm": ">=6", - "yarn": ">=1.16.0" + "yarn": ">=1.20.0" }, "scripts": { "cm": "npx git-cz", @@ -36,16 +38,19 @@ "dev:orthanc:no:cache": "lerna run dev:orthanc:no:cache --stream", "dev:dcm4chee": "lerna run dev:dcm4chee --stream", "dev:static": "lerna run dev:static --stream", - "orthanc:up": "docker-compose -f platform/app/.recipes/OpenResty-Orthanc/docker-compose.yml up", + "orthanc:up": "docker-compose -f platform/app/.recipes/Nginx-Orthanc/docker-compose.yml up", + "install:dev": "cp -f yarn.lock addOns/yarn.lock && cd addOns && yarn install --modules-folder ../node_modules", "preinstall": "node preinstall.js", "start": "yarn run dev", "test": "yarn run test:unit", - "test:data": "git submodule update --init -r", + "test:data": "git submodule update --init -f testdata", "test-watch": "jest --collectCoverage --watchAll", "test:unit": "jest --collectCoverage", "test:unit:ci": "lerna run test:unit:ci --parallel --stream", "test:e2e": "lerna run test:e2e --stream", - "test:e2e:ci": "lerna run test:e2e:ci --stream", + "test:e2e:ci": "npx playwright test", + "test:e2e:ui": "npx playwright test --ui", + "test:e2e:headed": "npx playwright test --headed", "test:e2e:dist": "lerna run test:e2e:dist --stream", "test:e2e:serve": "yarn test:data && lerna run test:e2e:serve --stream", "see-changed": "lerna changed", @@ -59,16 +64,16 @@ "link-list": "npm ls --depth=0 --link=true" }, "dependencies": { - "@babel/runtime": "^7.20.13", - "@kitware/vtk.js": "30.3.3", - "core-js": "^3.2.1" + "execa": "^8.0.1" }, - "peerDependencies": { - "react": "17.0.2", - "react-dom": "17.0.2" + "optionalDependencies": { + "@percy/cypress": "^3.1.1", + "@playwright/test": "^1.44.0", + "cypress": "13.7.2", + "cypress-file-upload": "^3.5.3" }, "devDependencies": { - "@babel/core": "^7.23.2", + "@babel/core": "7.24.7", "@babel/plugin-proposal-class-properties": "^7.16.7", "@babel/plugin-proposal-object-rest-spread": "^7.17.3", "@babel/plugin-proposal-private-methods": "^7.18.6", @@ -76,76 +81,13 @@ "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-transform-arrow-functions": "^7.16.7", "@babel/plugin-transform-regenerator": "^7.16.7", - "@babel/plugin-transform-runtime": "^7.23.2", + "@babel/plugin-transform-runtime": "7.24.7", "@babel/plugin-transform-typescript": "^7.13.0", - "@babel/preset-env": "^7.23.2", + "@babel/preset-env": "7.24.7", "@babel/preset-react": "^7.16.7", "@babel/preset-typescript": "^7.13.0", - "@types/jest": "^27.5.0", - "@typescript-eslint/eslint-plugin": "^6.3.0", - "@typescript-eslint/parser": "^6.3.0", - "autoprefixer": "^10.4.4", - "babel-eslint": "9.x", - "babel-loader": "^8.2.4", - "babel-plugin-inline-react-svg": "^2.0.2", - "babel-plugin-module-resolver": "^5.0.0", - "clean-webpack-plugin": "^3.0.0", - "copy-webpack-plugin": "^9.0.1", - "cross-env": "^5.2.0", - "css-loader": "^6.8.1", - "dotenv": "^8.1.0", - "eslint": "^7.32.0", - "eslint-config-prettier": "^7.2.0", - "eslint-config-react-app": "^6.0.0", - "eslint-plugin-cypress": "^2.12.1", - "eslint-plugin-flowtype": "^7.0.0", - "eslint-plugin-import": "^2.26.0", - "eslint-plugin-jsx-a11y": "^6.5.1", - "eslint-plugin-node": "^11.1.0", - "eslint-plugin-prettier": "^5.0.0", - "eslint-plugin-promise": "^5.2.0", - "eslint-plugin-react": "^7.29.4", - "eslint-plugin-react-hooks": "^4.4.0", - "eslint-plugin-tsdoc": "^0.2.11", - "eslint-webpack-plugin": "^2.5.3", - "execa": "^8.0.1", - "extract-css-chunks-webpack-plugin": "^4.5.4", - "html-webpack-plugin": "^5.3.2", - "husky": "^3.0.0", - "jest": "^29.5.0", - "jest-canvas-mock": "^2.1.0", - "jest-environment-jsdom": "^29.5.0", - "jest-junit": "^6.4.0", - "lerna": "^7.2.0", - "lint-staged": "^9.0.2", - "mini-css-extract-plugin": "^2.1.0", - "optimize-css-assets-webpack-plugin": "^6.0.1", - "postcss": "^8.3.5", - "postcss-import": "^14.0.2", - "postcss-loader": "^6.1.1", - "postcss-preset-env": "^7.4.3", - "prettier": "^3.0.3", - "prettier-plugin-tailwindcss": "^0.5.4", - "react-hot-loader": "^4.13.0", - "semver": "^7.5.1", - "serve": "^14.2.0", - "shader-loader": "^1.3.1", - "shx": "^0.3.3", - "source-map-loader": "^4.0.1", - "start-server-and-test": "^1.10.0", - "style-loader": "^1.0.0", - "stylus": "^0.59.0", - "stylus-loader": "^7.1.3", - "terser-webpack-plugin": "^5.1.4", - "typescript": "4.6.4", - "unused-webpack-plugin": "2.4.0", - "webpack": "^5.90.3", - "webpack-cli": "^4.7.2", - "webpack-dev-server": "4.7.3", - "webpack-hot-middleware": "^2.25.0", - "webpack-merge": "^5.7.3", - "workbox-webpack-plugin": "^6.1.5", - "worker-loader": "^3.0.8" + "prettier": "^3.3.2", + "prettier-plugin-tailwindcss": "^0.6.5" }, "husky": { "hooks": { @@ -161,11 +103,15 @@ "resolutions": { "**/@babel/runtime": "^7.20.13", "commander": "8.3.0", + "dcmjs": ">=0.33.0", + "dicomweb-client": ">=0.10.4", "nth-check": "^2.1.1", "trim-newlines": "^5.0.0", "glob-parent": "^6.0.2", "trim": "^1.0.0", "package-json": "^8.1.0", - "sharp": "^0.32.6" + "typescript": "4.6.4", + "sharp": "^0.32.6", + "ip": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz" } } diff --git a/platform/app/.gitignore b/platform/app/.gitignore index e985853ed8..82f6c1b363 100644 --- a/platform/app/.gitignore +++ b/platform/app/.gitignore @@ -1 +1,2 @@ .vercel +test-results diff --git a/platform/app/.recipes/Nginx-Dcm4chee-Keycloak/.gitignore b/platform/app/.recipes/Nginx-Dcm4chee-Keycloak/.gitignore new file mode 100644 index 0000000000..088f9a97f7 --- /dev/null +++ b/platform/app/.recipes/Nginx-Dcm4chee-Keycloak/.gitignore @@ -0,0 +1,6 @@ +logs/* +volumes/* +config/letsencrypt/* +config/certbot/* +!config/letsencrypt/.gitkeep +!config/certbot/.gitkeep diff --git a/platform/app/.recipes/Nginx-Dcm4chee-Keycloak/config/entrypoint.sh b/platform/app/.recipes/Nginx-Dcm4chee-Keycloak/config/entrypoint.sh new file mode 100644 index 0000000000..8648d7c7ca --- /dev/null +++ b/platform/app/.recipes/Nginx-Dcm4chee-Keycloak/config/entrypoint.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +# Start oauth2-proxy +oauth2-proxy --config=/etc/oauth2-proxy/oauth2-proxy.cfg & + +# Start nginx +nginx -g "daemon off;" diff --git a/platform/app/.recipes/Nginx-Dcm4chee-Keycloak/config/nginx.conf b/platform/app/.recipes/Nginx-Dcm4chee-Keycloak/config/nginx.conf new file mode 100644 index 0000000000..30b0089c45 --- /dev/null +++ b/platform/app/.recipes/Nginx-Dcm4chee-Keycloak/config/nginx.conf @@ -0,0 +1,240 @@ +worker_processes auto; +error_log /var/logs/nginx/error.log debug; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; + use epoll; + multi_accept on; +} + +http { + include '/etc/nginx/mime.types'; + default_type application/octet-stream; + + keepalive_timeout 65; + keepalive_requests 100000; + tcp_nopush on; + tcp_nodelay on; + + proxy_buffers 16 16k; + proxy_buffer_size 32k; + proxy_busy_buffers_size 64k; + proxy_max_temp_file_size 128k; + + + gzip on; + gzip_disable "msie6"; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml; + + server { + listen 80; + server_name YOUR_DOMAIN; + + client_max_body_size 0; + + location /.well-known/acme-challenge/ { + root /var/www/certbot; + } + + location / { + return 301 https://$host$request_uri; + } + } + + server { + listen 443 ssl; + server_name YOUR_DOMAIN; + ssl_certificate /etc/letsencrypt/live/YOUR_DOMAIN/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/YOUR_DOMAIN/privkey.pem; + root /var/www/html; + + gzip on; + gzip_types text/css application/javascript application/json image/svg+xml; + gzip_comp_level 9; + etag on; + + location /sw.js { + add_header Cache-Control "no-cache"; + proxy_cache_bypass $http_pragma; + proxy_cache_revalidate on; + expires off; + access_log off; + } + + + location /oauth2 { + expires -1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Auth-Request-Redirect $request_uri; + proxy_pass http://localhost:4180$uri$is_args$args; + } + + location /oauth2/callback { + proxy_pass http://localhost:4180; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location /oauth2/sign_out { + expires -1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Auth-Request-Redirect /oauth2/sign_in; + proxy_pass http://localhost:4180; + } + + + location /pacs/ { + auth_request /oauth2/auth; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + expires 0; + add_header Cache-Control private; + + add_header 'Access-Control-Allow-Origin' '*' always; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; + add_header 'Access-Control-Allow-Headers' 'Authorization, Origin, X-Requested-With, Content-Type, Accept' always; + + if ($request_method = OPTIONS) { + add_header 'Access-Control-Allow-Origin' '*'; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; + add_header 'Access-Control-Allow-Headers' 'Authorization, Origin, X-Requested-With, Content-Type, Accept'; + add_header 'Access-Control-Max-Age' 1728000; + add_header 'Content-Type' 'text/plain; charset=utf-8'; + add_header 'Content-Length' 0; + return 204; + } + + rewrite ^/pacs/(.*) /dcm4chee-arc/aets/DCM4CHEE/rs/$1 break; + proxy_pass http://arc:8080; + } + + location /pacs-admin { + return 301 /pacs-admin/; + } + + # Redirect /pacs-admin to /dcm4chee-arc/ui2/ + location = /pacs-admin { + return 301 $scheme://$host/dcm4chee-arc/ui2/; + } + + # Handle /pacs-admin/ requests + location /pacs-admin/ { + return 301 $scheme://$host/dcm4chee-arc/ui2/; + } + + # Proxy pass for /dcm4chee-arc/ui2/ + location /dcm4chee-arc/ui2/ { + error_page 401 = /oauth2/sign_in?rd=$scheme://$host$request_uri; + auth_request /oauth2/auth?allowed_groups=pacsadmin; + + auth_request_set $user $upstream_http_x_auth_request_user; + auth_request_set $token $upstream_http_x_auth_request_access_token; + auth_request_set $auth_cookie $upstream_http_set_cookie; + + proxy_set_header X-User $user; + proxy_set_header X-Access-Token $token; + add_header Set-Cookie $auth_cookie; + + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + expires 0; + add_header Cache-Control private; + + add_header 'Access-Control-Allow-Origin' '*' always; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; + add_header 'Access-Control-Allow-Headers' 'Authorization, Origin, X-Requested-With, Content-Type, Accept' always; + + if ($request_method = OPTIONS) { + add_header 'Access-Control-Allow-Origin' '*'; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; + add_header 'Access-Control-Allow-Headers' 'Authorization, Origin, X-Requested-With, Content-Type, Accept'; + add_header 'Access-Control-Max-Age' 1728000; + add_header 'Content-Type' 'text/plain; charset=utf-8'; + add_header 'Content-Length' 0; + return 204; + } + + proxy_pass http://arc:8080; + } + + # Proxy pass for other /dcm4chee-arc/ requests + location /dcm4chee-arc/ { + proxy_pass http://arc:8080; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + + location /pacs { + return 301 /pacs/; + } + + + location /ohif-viewer/ { + expires -1; + error_page 401 = /oauth2/sign_in?rd=$scheme://$host$request_uri; + auth_request /oauth2/auth; + + auth_request_set $user $upstream_http_x_auth_request_user; + auth_request_set $token $upstream_http_x_auth_request_access_token; + auth_request_set $auth_cookie $upstream_http_set_cookie; + + proxy_set_header X-User $user; + proxy_set_header X-Access-Token $token; + add_header Set-Cookie $auth_cookie; + + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Server $host; + proxy_set_header X-Forwarded-Proto $scheme; + + index index.html; + try_files $uri $uri/ /index.html; + } + + + location /ohif-viewer { + return 301 /ohif-viewer/; + } + + location = / { + return 301 /ohif-viewer/; + } + + location / { + add_header Cache-Control "no-store, no-cache, must-revalidate"; + add_header 'Cross-Origin-Opener-Policy' 'same-origin' always; + add_header 'Cross-Origin-Embedder-Policy' 'require-corp' always; + } + + location /keycloak/ { + proxy_pass http://keycloak:8080/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location /keycloak { + return 301 /keycloak/; + } + } +} diff --git a/platform/app/.recipes/Nginx-Dcm4chee-Keycloak/config/oauth2-proxy.cfg b/platform/app/.recipes/Nginx-Dcm4chee-Keycloak/config/oauth2-proxy.cfg new file mode 100644 index 0000000000..985525af91 --- /dev/null +++ b/platform/app/.recipes/Nginx-Dcm4chee-Keycloak/config/oauth2-proxy.cfg @@ -0,0 +1,22 @@ +http_address="0.0.0.0:4180" +cookie_secret="GENERATEACOOKIESECRET----------------------=" +email_domains=["*"] +cookie_secure="false" +cookie_expire="9m30s" +cookie_refresh="5m" +client_secret="2Xtlde7aozdkzzYHdIxQNfPDr0wNPTgg" +client_id="ohif_viewer" +redirect_url="http://YOUR_DOMAIN/oauth2/callback" + +ssl_insecure_skip_verify = true +insecure_oidc_allow_unverified_email = true +pass_access_token = true +provider="keycloak-oidc" +provider_display_name="Keycloak" +user_id_claim="oid" +oidc_email_claim="sub" +scope="openid" +pass_host_header=true +code_challenge_method="S256" +oidc_issuer_url="http://YOUR_DOMAIN/keycloak/realms/ohif" +insecure_oidc_skip_issuer_verification = true diff --git a/platform/app/.recipes/Nginx-Dcm4chee-Keycloak/config/ohif-keycloak-realm.json b/platform/app/.recipes/Nginx-Dcm4chee-Keycloak/config/ohif-keycloak-realm.json new file mode 100644 index 0000000000..3064ee70e4 --- /dev/null +++ b/platform/app/.recipes/Nginx-Dcm4chee-Keycloak/config/ohif-keycloak-realm.json @@ -0,0 +1,2315 @@ +{ + "id": "37c16268-9c83-41c3-b452-3fbc86e6966d", + "realm": "ohif", + "notBefore": 0, + "defaultSignatureAlgorithm": "RS256", + "revokeRefreshToken": false, + "refreshTokenMaxReuse": 0, + "accessTokenLifespan": 300, + "accessTokenLifespanForImplicitFlow": 900, + "ssoSessionIdleTimeout": 1800, + "ssoSessionMaxLifespan": 36000, + "ssoSessionIdleTimeoutRememberMe": 0, + "ssoSessionMaxLifespanRememberMe": 0, + "offlineSessionIdleTimeout": 2592000, + "offlineSessionMaxLifespanEnabled": false, + "offlineSessionMaxLifespan": 5184000, + "clientSessionIdleTimeout": 0, + "clientSessionMaxLifespan": 0, + "clientOfflineSessionIdleTimeout": 0, + "clientOfflineSessionMaxLifespan": 0, + "accessCodeLifespan": 60, + "accessCodeLifespanUserAction": 300, + "accessCodeLifespanLogin": 1800, + "actionTokenGeneratedByAdminLifespan": 43200, + "actionTokenGeneratedByUserLifespan": 300, + "oauth2DeviceCodeLifespan": 600, + "oauth2DevicePollingInterval": 5, + "enabled": true, + "sslRequired": "none", + "registrationAllowed": false, + "registrationEmailAsUsername": false, + "rememberMe": false, + "verifyEmail": false, + "loginWithEmailAllowed": true, + "duplicateEmailsAllowed": false, + "resetPasswordAllowed": false, + "editUsernameAllowed": false, + "bruteForceProtected": false, + "permanentLockout": false, + "maxTemporaryLockouts": 0, + "maxFailureWaitSeconds": 900, + "minimumQuickLoginWaitSeconds": 60, + "waitIncrementSeconds": 60, + "quickLoginCheckMilliSeconds": 1000, + "maxDeltaTimeSeconds": 43200, + "failureFactor": 30, + "roles": { + "realm": [ + { + "id": "b886fa27-974b-446f-adaa-a2c96342ce05", + "name": "uma_authorization", + "description": "${role_uma_authorization}", + "composite": false, + "clientRole": false, + "containerId": "37c16268-9c83-41c3-b452-3fbc86e6966d", + "attributes": {} + }, + { + "id": "d8bba2d8-ac65-46cb-a1b3-bbee4850333f", + "name": "offline_access", + "description": "${role_offline-access}", + "composite": false, + "clientRole": false, + "containerId": "37c16268-9c83-41c3-b452-3fbc86e6966d", + "attributes": {} + }, + { + "id": "4d80d451-18c2-4982-b2b7-f43aad1b54aa", + "name": "default-roles-ohif", + "description": "${role_default-roles}", + "composite": true, + "composites": { + "realm": [ + "offline_access", + "uma_authorization" + ], + "client": { + "account": [ + "manage-account", + "view-profile" + ] + } + }, + "clientRole": false, + "containerId": "37c16268-9c83-41c3-b452-3fbc86e6966d", + "attributes": {} + } + ], + "client": { + "realm-management": [ + { + "id": "0c749b40-bda4-463a-b1c2-edd014606c8c", + "name": "manage-identity-providers", + "description": "${role_manage-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "70605217-ff53-4895-8686-2f87bb81cecd", + "name": "view-realm", + "description": "${role_view-realm}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "1482af22-41e6-4850-b5a3-3d479edd334b", + "name": "view-users", + "description": "${role_view-users}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-users", + "query-groups" + ] + } + }, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "7b2b0fcd-3539-4322-bd12-379398ff9c63", + "name": "query-groups", + "description": "${role_query-groups}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "f5856ab0-17fe-49bb-8e04-27d1f37c53c7", + "name": "manage-realm", + "description": "${role_manage-realm}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "5cd89fbb-7860-4505-90b8-ad99b28a7ce2", + "name": "manage-users", + "description": "${role_manage-users}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "c53a6ea6-9c79-485f-9402-b2607df09f53", + "name": "view-authorization", + "description": "${role_view-authorization}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "696a4591-d966-446c-a1f6-9a8a8de41f41", + "name": "query-clients", + "description": "${role_query-clients}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "3b0c1a20-0692-4594-973f-bd7c0d42631b", + "name": "manage-authorization", + "description": "${role_manage-authorization}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "3279ff3a-ae5c-4d59-99a3-3b2791391745", + "name": "query-realms", + "description": "${role_query-realms}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "56767ac1-1098-41c9-8b94-b9efe47fa17a", + "name": "create-client", + "description": "${role_create-client}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "e231ed30-1c79-4786-80dc-c16d87866b03", + "name": "query-users", + "description": "${role_query-users}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "388304d0-befe-4498-99cd-c9821dfe5ff6", + "name": "realm-admin", + "description": "${role_realm-admin}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "manage-identity-providers", + "view-realm", + "view-users", + "query-groups", + "manage-realm", + "manage-users", + "view-authorization", + "query-clients", + "manage-authorization", + "query-realms", + "create-client", + "query-users", + "view-events", + "view-identity-providers", + "manage-clients", + "manage-events", + "view-clients", + "impersonation" + ] + } + }, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "901b8b02-4525-4ed9-b6c5-ee822a874236", + "name": "view-events", + "description": "${role_view-events}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "d9c612fa-421a-4463-8837-4bcc059649ea", + "name": "manage-clients", + "description": "${role_manage-clients}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "efbd010a-67a1-472c-b308-a91723ebe819", + "name": "manage-events", + "description": "${role_manage-events}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "60cbee1d-9fa4-47ee-8f86-f71ae22482c1", + "name": "view-identity-providers", + "description": "${role_view-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "84219236-4eaa-4ea7-a94c-52d6f8e1bb79", + "name": "view-clients", + "description": "${role_view-clients}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-clients" + ] + } + }, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "d46f77b0-ed82-4580-994f-8a6a8fc22480", + "name": "impersonation", + "description": "${role_impersonation}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + } + ], + "security-admin-console": [], + "ohif_viewer": [], + "admin-cli": [], + "account-console": [], + "broker": [ + { + "id": "3e2b2c4a-416e-463d-8907-b919d17a4592", + "name": "read-token", + "description": "${role_read-token}", + "composite": false, + "clientRole": true, + "containerId": "8d52074d-c27d-4917-8280-a33bcae47f59", + "attributes": {} + } + ], + "account": [ + { + "id": "1bd17278-c076-41df-9559-7f3524d5cd5e", + "name": "manage-account", + "description": "${role_manage-account}", + "composite": true, + "composites": { + "client": { + "account": [ + "manage-account-links" + ] + } + }, + "clientRole": true, + "containerId": "50a0e32a-f503-497b-b3c3-ff127cc56a56", + "attributes": {} + }, + { + "id": "302c47ca-5e53-4cbe-9670-4e10a281d2bf", + "name": "view-applications", + "description": "${role_view-applications}", + "composite": false, + "clientRole": true, + "containerId": "50a0e32a-f503-497b-b3c3-ff127cc56a56", + "attributes": {} + }, + { + "id": "a6bd8131-df31-4922-b7da-7011d7e967db", + "name": "view-profile", + "description": "${role_view-profile}", + "composite": false, + "clientRole": true, + "containerId": "50a0e32a-f503-497b-b3c3-ff127cc56a56", + "attributes": {} + }, + { + "id": "eed205fe-b606-4562-8b65-503e3d4d7d89", + "name": "manage-account-links", + "description": "${role_manage-account-links}", + "composite": false, + "clientRole": true, + "containerId": "50a0e32a-f503-497b-b3c3-ff127cc56a56", + "attributes": {} + }, + { + "id": "ea20e235-92da-4409-9a82-2dc4244bc342", + "name": "view-groups", + "description": "${role_view-groups}", + "composite": false, + "clientRole": true, + "containerId": "50a0e32a-f503-497b-b3c3-ff127cc56a56", + "attributes": {} + }, + { + "id": "ccca6524-fbc9-4712-a703-f4311b94e757", + "name": "manage-consent", + "description": "${role_manage-consent}", + "composite": true, + "composites": { + "client": { + "account": [ + "view-consent" + ] + } + }, + "clientRole": true, + "containerId": "50a0e32a-f503-497b-b3c3-ff127cc56a56", + "attributes": {} + }, + { + "id": "1b2fa98f-7ff0-4bf6-974c-c3e8b36d8dc3", + "name": "delete-account", + "description": "${role_delete-account}", + "composite": false, + "clientRole": true, + "containerId": "50a0e32a-f503-497b-b3c3-ff127cc56a56", + "attributes": {} + }, + { + "id": "dc213956-175c-4ef1-99e8-0033818761f4", + "name": "view-consent", + "description": "${role_view-consent}", + "composite": false, + "clientRole": true, + "containerId": "50a0e32a-f503-497b-b3c3-ff127cc56a56", + "attributes": {} + } + ] + } + }, + "groups": [ + { + "id": "3249b4f1-6572-4b59-a206-7e707d1e45f6", + "name": "pacsadmin", + "path": "/pacsadmin", + "subGroups": [], + "attributes": {}, + "realmRoles": [], + "clientRoles": {} + } + ], + "defaultRole": { + "id": "4d80d451-18c2-4982-b2b7-f43aad1b54aa", + "name": "default-roles-ohif", + "description": "${role_default-roles}", + "composite": true, + "clientRole": false, + "containerId": "37c16268-9c83-41c3-b452-3fbc86e6966d" + }, + "requiredCredentials": [ + "password" + ], + "otpPolicyType": "totp", + "otpPolicyAlgorithm": "HmacSHA1", + "otpPolicyInitialCounter": 0, + "otpPolicyDigits": 6, + "otpPolicyLookAheadWindow": 1, + "otpPolicyPeriod": 30, + "otpPolicyCodeReusable": false, + "otpSupportedApplications": [ + "totpAppFreeOTPName", + "totpAppGoogleName", + "totpAppMicrosoftAuthenticatorName" + ], + "localizationTexts": {}, + "webAuthnPolicyRpEntityName": "keycloak", + "webAuthnPolicySignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyRpId": "", + "webAuthnPolicyAttestationConveyancePreference": "not specified", + "webAuthnPolicyAuthenticatorAttachment": "not specified", + "webAuthnPolicyRequireResidentKey": "not specified", + "webAuthnPolicyUserVerificationRequirement": "not specified", + "webAuthnPolicyCreateTimeout": 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyAcceptableAaguids": [], + "webAuthnPolicyExtraOrigins": [], + "webAuthnPolicyPasswordlessRpEntityName": "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyPasswordlessRpId": "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey": "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified", + "webAuthnPolicyPasswordlessCreateTimeout": 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyPasswordlessAcceptableAaguids": [], + "webAuthnPolicyPasswordlessExtraOrigins": [], + "scopeMappings": [ + { + "clientScope": "offline_access", + "roles": [ + "offline_access" + ] + } + ], + "clientScopeMappings": { + "account": [ + { + "client": "account-console", + "roles": [ + "manage-account", + "view-groups" + ] + } + ] + }, + "clients": [ + { + "id": "50a0e32a-f503-497b-b3c3-ff127cc56a56", + "clientId": "account", + "name": "${client_account}", + "description": "", + "rootUrl": "${authAdminUrl}", + "adminUrl": "", + "baseUrl": "/realms/ohif/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/realms/ohif/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "oidc.ciba.grant.enabled": "false", + "backchannel.logout.session.required": "true", + "post.logout.redirect.uris": "+", + "display.on.consent.screen": "false", + "oauth2.device.authorization.grant.enabled": "false", + "backchannel.logout.revoke.offline.tokens": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "5c719a4e-2eed-4b9a-9536-edafb7763e6e", + "clientId": "account-console", + "name": "${client_account-console}", + "description": "", + "rootUrl": "${authAdminUrl}", + "adminUrl": "", + "baseUrl": "/realms/ohif/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/realms/ohif/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "oidc.ciba.grant.enabled": "false", + "backchannel.logout.session.required": "true", + "post.logout.redirect.uris": "+", + "display.on.consent.screen": "false", + "oauth2.device.authorization.grant.enabled": "false", + "pkce.code.challenge.method": "S256", + "backchannel.logout.revoke.offline.tokens": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "2a172f00-5ae2-400a-8aba-0c8f267844a3", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "5f86b71b-9a75-465a-9007-9cadd861a1c5", + "clientId": "admin-cli", + "name": "${client_admin-cli}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "8d52074d-c27d-4917-8280-a33bcae47f59", + "clientId": "broker", + "name": "${client_broker}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "ceddadb2-f4b6-4a1d-a0c8-efdd95fd2e9a", + "clientId": "ohif_viewer", + "name": "", + "description": "", + "rootUrl": "http://127.0.0.1", + "adminUrl": "http://127.0.0.1", + "baseUrl": "http://127.0.0.1", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "2Xtlde7aozdkzzYHdIxQNfPDr0wNPTgg", + "redirectUris": [ + "http://127.0.0.1/oauth2/callback" + ], + "webOrigins": [ + "http://127.0.0.1" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": true, + "protocol": "openid-connect", + "attributes": { + "oidc.ciba.grant.enabled": "false", + "client.secret.creation.time": "1718045868", + "backchannel.logout.session.required": "true", + "display.on.consent.screen": "false", + "oauth2.device.authorization.grant.enabled": "false", + "backchannel.logout.revoke.offline.tokens": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "id": "b405129c-ed1b-4c4e-b712-1f736be6440b", + "name": "Audience", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-mapper", + "consentRequired": false, + "config": { + "included.client.audience": "ohif_viewer", + "id.token.claim": "true", + "lightweight.claim": "false", + "access.token.claim": "true", + "introspection.token.claim": "true" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "groups", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "clientId": "realm-management", + "name": "${client_realm-management}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "ace68c1f-eae4-4d93-ab98-0005a071177d", + "clientId": "security-admin-console", + "name": "${client_security-admin-console}", + "rootUrl": "${authAdminUrl}", + "baseUrl": "/admin/ohif/console/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/admin/ohif/console/*" + ], + "webOrigins": [ + "+" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+", + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "fdee0223-2998-486a-b591-ae6712ae7831", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + } + ], + "clientScopes": [ + { + "id": "73b70709-cb2f-4d06-86af-0b04425970ee", + "name": "email", + "description": "OpenID Connect built-in scope: email", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${emailScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "0c8df10b-097f-4b13-85b8-3ec3b4d3ef03", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + }, + { + "id": "6cff88ad-73ed-4699-86f9-c7ac5e473a53", + "name": "email verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "emailVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email_verified", + "jsonType.label": "boolean" + } + } + ] + }, + { + "id": "4098872d-e896-4042-a715-be23f0a1437c", + "name": "offline_access", + "description": "OpenID Connect built-in scope: offline_access", + "protocol": "openid-connect", + "attributes": { + "consent.screen.text": "${offlineAccessScopeConsentText}", + "display.on.consent.screen": "true" + } + }, + { + "id": "06ba9538-581f-4c0b-a7ca-b56eaa8c1e59", + "name": "profile", + "description": "OpenID Connect built-in scope: profile", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${profileScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "d992a9b9-ec09-49fd-b052-65942ff5ba58", + "name": "updated at", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "updatedAt", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "updated_at", + "jsonType.label": "long" + } + }, + { + "id": "9b2089a4-ce6f-4dcb-abd8-67844a8e17b5", + "name": "profile", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "profile", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "profile", + "jsonType.label": "String" + } + }, + { + "id": "0e37cc54-2ff9-4976-9f66-f6f949652d40", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "introspection.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + }, + { + "id": "f2d87384-cc84-4d8a-bef7-379491ba1430", + "name": "gender", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "gender", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "gender", + "jsonType.label": "String" + } + }, + { + "id": "03c9b60a-32a9-4bd2-9173-ee7048f8face", + "name": "picture", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "picture", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "picture", + "jsonType.label": "String" + } + }, + { + "id": "6db8e846-d71d-4573-89be-cc249c93c4fd", + "name": "birthdate", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "birthdate", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "birthdate", + "jsonType.label": "String" + } + }, + { + "id": "aacde81e-9462-446f-abf9-25bb83d3c442", + "name": "website", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "website", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "website", + "jsonType.label": "String" + } + }, + { + "id": "44dc5e2c-de20-4e46-94ed-e5fbecee8021", + "name": "zoneinfo", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "zoneinfo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "zoneinfo", + "jsonType.label": "String" + } + }, + { + "id": "74ab1492-ecbb-4a52-a5dd-820d7bc1dec5", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + }, + { + "id": "69aab70e-94d5-45f0-ab8f-14c973492636", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "611957f1-cdfe-43b9-acc6-d2d37b5b6908", + "name": "nickname", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "nickname", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "nickname", + "jsonType.label": "String" + } + }, + { + "id": "90e9af6c-7a44-4b8b-bdea-020ccd7cf79b", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + }, + { + "id": "d1ceeaef-bebc-4be6-b5b7-85e361b91ce5", + "name": "middle name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "middleName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "middle_name", + "jsonType.label": "String" + } + }, + { + "id": "d74b3e90-c391-4fea-806d-98b24e598ade", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "077a40b6-ae18-440a-9858-57cb93483f4d", + "name": "web-origins", + "description": "OpenID Connect scope for add allowed web origins to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false", + "consent.screen.text": "" + }, + "protocolMappers": [ + { + "id": "f7a704cc-7466-41b4-ada4-3efe4dceb599", + "name": "allowed web origins", + "protocol": "openid-connect", + "protocolMapper": "oidc-allowed-origins-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "access.token.claim": "true" + } + } + ] + }, + { + "id": "16085075-08fa-4fe8-aa9e-c429b26df40e", + "name": "roles", + "description": "OpenID Connect scope for add user roles to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "true", + "consent.screen.text": "${rolesScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "1cb74178-9ba0-4225-8ede-a263f0cf0f9d", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "access.token.claim": "true" + } + }, + { + "id": "020299f1-b469-41fb-b80d-5cea4ceb4e7d", + "name": "realm roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "multivalued": "true", + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "realm_access.roles", + "jsonType.label": "String" + } + }, + { + "id": "6759edaf-7d37-44b0-ad7b-50a3383e9cd9", + "name": "client roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-client-role-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "multivalued": "true", + "userinfo.token.claim": "false", + "user.attribute": "foo", + "lightweight.claim": "false", + "id.token.claim": "false", + "access.token.claim": "true", + "claim.name": "resource_access.${client_id}. roles", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "905660b4-380a-4a8c-81a9-bd16b3b3ce3f", + "name": "microprofile-jwt", + "description": "Microprofile - JWT built-in scope", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "4e2f2bd8-602f-4ae1-a431-fa92bdedd386", + "name": "upn", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "upn", + "jsonType.label": "String" + } + }, + { + "id": "f1e69dc4-f19e-4c21-bbf9-609016339710", + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "multivalued": "true", + "user.attribute": "foo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "groups", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "24748647-8a70-422e-8532-f8d231a006db", + "name": "acr", + "description": "OpenID Connect scope for add acr (authentication context class reference) to the token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "fd884f9e-e345-4823-b463-beb39020ca23", + "name": "acr loa level", + "protocol": "openid-connect", + "protocolMapper": "oidc-acr-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "introspection.token.claim": "true", + "access.token.claim": "true" + } + } + ] + }, + { + "id": "db5c28fd-e142-40e1-926c-017d0d58c04a", + "name": "groups", + "description": "", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "true", + "gui.order": "", + "consent.screen.text": "" + }, + "protocolMappers": [ + { + "id": "1f5afdb5-1de2-40c7-8526-d1ad0585720b", + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-group-membership-mapper", + "consentRequired": false, + "config": { + "full.path": "false", + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "multivalued": "true", + "id.token.claim": "true", + "lightweight.claim": "false", + "access.token.claim": "true", + "claim.name": "groups" + } + } + ] + }, + { + "id": "c1678c18-641f-4eeb-af7e-c5327adee009", + "name": "role_list", + "description": "SAML role list", + "protocol": "saml", + "attributes": { + "consent.screen.text": "${samlRoleListScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "bec886da-1100-4af1-a83f-b322a23e9856", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + } + ] + }, + { + "id": "ead6084e-d9f1-4388-80c6-aead5b3ddfff", + "name": "address", + "description": "OpenID Connect built-in scope: address", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${addressScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "3a4ceb4e-e597-49e4-8d0c-d41a46a2ab38", + "name": "address", + "protocol": "openid-connect", + "protocolMapper": "oidc-address-mapper", + "consentRequired": false, + "config": { + "user.attribute.formatted": "formatted", + "user.attribute.country": "country", + "introspection.token.claim": "true", + "user.attribute.postal_code": "postal_code", + "userinfo.token.claim": "true", + "user.attribute.street": "street", + "id.token.claim": "true", + "user.attribute.region": "region", + "access.token.claim": "true", + "user.attribute.locality": "locality" + } + } + ] + }, + { + "id": "df3a89a6-3ed7-45ad-97e1-598b93a643e7", + "name": "phone", + "description": "OpenID Connect built-in scope: phone", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${phoneScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "9bbff1aa-ee20-4c33-b40f-d0076a2fe305", + "name": "phone number", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "phoneNumber", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number", + "jsonType.label": "String" + } + }, + { + "id": "726d1ea0-ee59-49fe-bd01-416b06276ae9", + "name": "phone number verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "phoneNumberVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number_verified", + "jsonType.label": "boolean" + } + } + ] + } + ], + "defaultDefaultClientScopes": [ + "role_list", + "profile", + "email", + "roles", + "web-origins", + "acr" + ], + "defaultOptionalClientScopes": [ + "offline_access", + "address", + "phone", + "microprofile-jwt" + ], + "browserSecurityHeaders": { + "contentSecurityPolicyReportOnly": "", + "xContentTypeOptions": "nosniff", + "referrerPolicy": "no-referrer", + "xRobotsTag": "none", + "xFrameOptions": "SAMEORIGIN", + "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection": "1; mode=block", + "strictTransportSecurity": "max-age=31536000; includeSubDomains" + }, + "smtpServer": {}, + "eventsEnabled": false, + "eventsListeners": [ + "jboss-logging" + ], + "enabledEventTypes": [], + "adminEventsEnabled": false, + "adminEventsDetailsEnabled": false, + "identityProviders": [], + "identityProviderMappers": [], + "components": { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ + { + "id": "e037fff2-9457-47c7-81c7-762fbe02d23c", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "cbd25133-ce87-483c-b2e3-a3c2947b23e9", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "saml-user-attribute-mapper", + "oidc-usermodel-property-mapper", + "oidc-usermodel-attribute-mapper", + "oidc-address-mapper", + "oidc-sha256-pairwise-sub-mapper", + "saml-role-list-mapper", + "saml-user-property-mapper", + "oidc-full-name-mapper" + ] + } + }, + { + "id": "2fa7da7b-1138-44f9-8236-7e31f5f72695", + "name": "Consent Required", + "providerId": "consent-required", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "d2e6c9ff-9c36-40cc-bc12-0055d5ea61c3", + "name": "Trusted Hosts", + "providerId": "trusted-hosts", + "subType": "anonymous", + "subComponents": {}, + "config": { + "host-sending-registration-request-must-match": [ + "true" + ], + "client-uris-must-match": [ + "true" + ] + } + }, + { + "id": "269704c3-de60-4233-a845-6efd83408eb0", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "saml-role-list-mapper", + "oidc-usermodel-attribute-mapper", + "oidc-full-name-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-usermodel-property-mapper", + "saml-user-attribute-mapper", + "saml-user-property-mapper", + "oidc-address-mapper" + ] + } + }, + { + "id": "28cb7c8a-2fd1-4a3d-8ab8-17e4e83c2648", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "3a77be15-e696-49aa-9dac-64a79d8e443f", + "name": "Full Scope Disabled", + "providerId": "scope", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "f662e962-d5bd-4bbe-bc43-bddc7f4faf57", + "name": "Max Clients Limit", + "providerId": "max-clients", + "subType": "anonymous", + "subComponents": {}, + "config": { + "max-clients": [ + "200" + ] + } + } + ], + "org.keycloak.keys.KeyProvider": [ + { + "id": "5a307075-97e6-4c78-8e05-10e21c097d53", + "name": "aes-generated", + "providerId": "aes-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + }, + { + "id": "78a25e8e-b46c-44c2-8fd4-4b09529890e7", + "name": "rsa-generated", + "providerId": "rsa-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + }, + { + "id": "bf0f6364-43f0-4b1c-bde2-7646ceb56a63", + "name": "hmac-generated-hs512", + "providerId": "hmac-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ], + "algorithm": [ + "HS512" + ] + } + }, + { + "id": "28485c9c-96bc-49c7-a9a2-8941c9067f7d", + "name": "rsa-enc-generated", + "providerId": "rsa-enc-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ], + "algorithm": [ + "RSA-OAEP" + ] + } + } + ] + }, + "internationalizationEnabled": false, + "supportedLocales": [], + "authenticationFlows": [ + { + "id": "bbb2d80e-a134-4933-afe9-7cb655d70791", + "alias": "Account verification options", + "description": "Method with which to verity the existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-email-verification", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Verify Existing Account by Re-authentication", + "userSetupAllowed": false + } + ] + }, + { + "id": "651f23c0-4ef1-4762-b186-fc2b985ead9d", + "alias": "Browser - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-otp-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "e8dd531a-b8b7-4416-984f-9226cfcc8800", + "alias": "Direct Grant - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "direct-grant-validate-otp", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "e4fc59c9-1048-45b5-9069-57d578d0f125", + "alias": "First broker login - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-otp-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "12ea6433-d1b6-4094-b3e2-1ef356b91d92", + "alias": "Handle Existing Account", + "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-confirm-link", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Account verification options", + "userSetupAllowed": false + } + ] + }, + { + "id": "5d6c3ca7-3581-4200-b592-9c714129044f", + "alias": "Reset - Conditional OTP", + "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-otp", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "b7712f6e-fbe8-4f15-936d-939e28efd279", + "alias": "User creation or linking", + "description": "Flow for the existing/non-existing user alternatives", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "create unique user config", + "authenticator": "idp-create-user-if-unique", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Handle Existing Account", + "userSetupAllowed": false + } + ] + }, + { + "id": "61a450b5-3007-4e98-a7b2-dba743ea54a7", + "alias": "Verify Existing Account by Re-authentication", + "description": "Reauthentication of existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-username-password-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "First broker login - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "d7566b94-731b-4e84-a2de-a1c8130af38b", + "alias": "browser", + "description": "browser based authentication", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-cookie", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-spnego", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "identity-provider-redirector", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 25, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 30, + "autheticatorFlow": true, + "flowAlias": "forms", + "userSetupAllowed": false + } + ] + }, + { + "id": "399c5ce6-4308-4524-89bc-4dee1afd6cbb", + "alias": "clients", + "description": "Base authentication for clients", + "providerId": "client-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "client-secret", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-jwt", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-secret-jwt", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 30, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-x509", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 40, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "c8e80f39-d8d7-4fa5-8944-33fcdd366721", + "alias": "direct grant", + "description": "OpenID Connect Resource Owner Grant", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "direct-grant-validate-username", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "direct-grant-validate-password", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 30, + "autheticatorFlow": true, + "flowAlias": "Direct Grant - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "79251c55-7de3-457e-99e3-92395f2b69a7", + "alias": "docker auth", + "description": "Used by Docker clients to authenticate against the IDP", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "docker-http-basic-authenticator", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "60a12c1d-d4ce-40c1-a83f-faba71145f0c", + "alias": "first broker login", + "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "review profile config", + "authenticator": "idp-review-profile", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "User creation or linking", + "userSetupAllowed": false + } + ] + }, + { + "id": "e36da2db-a596-4680-a5ca-16c4e5a1a9c1", + "alias": "forms", + "description": "Username, password, otp and other auth forms.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-username-password-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Browser - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "2b1b59ff-5417-48cd-8d7a-2ab5ecfedc9f", + "alias": "registration", + "description": "registration flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": true, + "flowAlias": "registration form", + "userSetupAllowed": false + } + ] + }, + { + "id": "3e4f2042-a809-490c-a1a6-9bb63b4b0e4a", + "alias": "registration form", + "description": "registration form", + "providerId": "form-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-user-creation", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-password-action", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 50, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-recaptcha-action", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 60, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-terms-and-conditions", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 70, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "0b59d69a-95b0-4c82-bd21-908c019a4974", + "alias": "reset credentials", + "description": "Reset credentials for a user if they forgot their password or something", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "reset-credentials-choose-user", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-credential-email", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-password", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 30, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 40, + "autheticatorFlow": true, + "flowAlias": "Reset - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "accf37f2-1a52-40b0-a92f-f5a931c57126", + "alias": "saml ecp", + "description": "SAML ECP Profile Authentication Flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + } + ], + "authenticatorConfig": [ + { + "id": "4eaad8bb-f86b-483d-99a4-4cba184ef573", + "alias": "create unique user config", + "config": { + "require.password.update.after.registration": "false" + } + }, + { + "id": "eb0a326f-17e0-49b7-b25c-575b0cd3888f", + "alias": "review profile config", + "config": { + "update.profile.on.first.login": "missing" + } + } + ], + "requiredActions": [ + { + "alias": "CONFIGURE_TOTP", + "name": "Configure OTP", + "providerId": "CONFIGURE_TOTP", + "enabled": true, + "defaultAction": false, + "priority": 10, + "config": {} + }, + { + "alias": "TERMS_AND_CONDITIONS", + "name": "Terms and Conditions", + "providerId": "TERMS_AND_CONDITIONS", + "enabled": false, + "defaultAction": false, + "priority": 20, + "config": {} + }, + { + "alias": "UPDATE_PASSWORD", + "name": "Update Password", + "providerId": "UPDATE_PASSWORD", + "enabled": true, + "defaultAction": false, + "priority": 30, + "config": {} + }, + { + "alias": "UPDATE_PROFILE", + "name": "Update Profile", + "providerId": "UPDATE_PROFILE", + "enabled": true, + "defaultAction": false, + "priority": 40, + "config": {} + }, + { + "alias": "VERIFY_EMAIL", + "name": "Verify Email", + "providerId": "VERIFY_EMAIL", + "enabled": true, + "defaultAction": false, + "priority": 50, + "config": {} + }, + { + "alias": "delete_account", + "name": "Delete Account", + "providerId": "delete_account", + "enabled": false, + "defaultAction": false, + "priority": 60, + "config": {} + }, + { + "alias": "webauthn-register", + "name": "Webauthn Register", + "providerId": "webauthn-register", + "enabled": true, + "defaultAction": false, + "priority": 70, + "config": {} + }, + { + "alias": "webauthn-register-passwordless", + "name": "Webauthn Register Passwordless", + "providerId": "webauthn-register-passwordless", + "enabled": true, + "defaultAction": false, + "priority": 80, + "config": {} + }, + { + "alias": "VERIFY_PROFILE", + "name": "Verify Profile", + "providerId": "VERIFY_PROFILE", + "enabled": true, + "defaultAction": false, + "priority": 90, + "config": {} + }, + { + "alias": "delete_credential", + "name": "Delete Credential", + "providerId": "delete_credential", + "enabled": true, + "defaultAction": false, + "priority": 100, + "config": {} + }, + { + "alias": "update_user_locale", + "name": "Update User Locale", + "providerId": "update_user_locale", + "enabled": true, + "defaultAction": false, + "priority": 1000, + "config": {} + } + ], + "browserFlow": "browser", + "registrationFlow": "registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "firstBrokerLoginFlow": "first broker login", + "attributes": { + "cibaBackchannelTokenDeliveryMode": "poll", + "cibaExpiresIn": "120", + "cibaAuthRequestedUserHint": "login_hint", + "oauth2DeviceCodeLifespan": "600", + "oauth2DevicePollingInterval": "5", + "parRequestUriLifespan": "60", + "cibaInterval": "5", + "realmReusableOtpCode": "false" + }, + "keycloakVersion": "24.0.5", + "userManagedAccessAllowed": false, + "clientProfiles": { + "profiles": [] + }, + "clientPolicies": { + "policies": [] + }, + "users": [ + { + "username": "viewer", + "enabled": true, + "emailVerified": true, + "firstName": "viewer", + "lastName": "viewer", + "email": "viewer@mail.com", + "credentials": [ + { + "type": "password", + "value": "viewer" + } + ] + }, + { + "username": "pacsadmin", + "enabled": true, + "emailVerified": true, + "firstName": "pacsadmin", + "lastName": "pacsadmin", + "email": "pacsadmin@mail.com", + "credentials": [ + { + "type": "password", + "value": "pacsadmin" + } + ], + "groups": ["pacsadmin"] + } + ] +} diff --git a/platform/app/.recipes/Nginx-Dcm4chee/docker-compose-dcm4che.env b/platform/app/.recipes/Nginx-Dcm4chee-Keycloak/docker-compose.env similarity index 100% rename from platform/app/.recipes/Nginx-Dcm4chee/docker-compose-dcm4che.env rename to platform/app/.recipes/Nginx-Dcm4chee-Keycloak/docker-compose.env diff --git a/platform/app/.recipes/Nginx-Dcm4chee-Keycloak/docker-compose.yml b/platform/app/.recipes/Nginx-Dcm4chee-Keycloak/docker-compose.yml new file mode 100644 index 0000000000..1c3aa0ec2e --- /dev/null +++ b/platform/app/.recipes/Nginx-Dcm4chee-Keycloak/docker-compose.yml @@ -0,0 +1,161 @@ +version: '3.8' + +services: + ldap: + image: dcm4che/slapd-dcm4chee:2.6.3-29.0 + logging: + driver: json-file + options: + max-size: "10m" + ports: + - "389:389" + env_file: docker-compose.env + volumes: + - ~/dcm4chee-arc/ldap:/var/lib/ldap + - ~/dcm4chee-arc/slapd.d:/etc/ldap/slapd.d + + db: + image: dcm4che/postgres-dcm4chee:14.5-29 + logging: + driver: json-file + options: + max-size: "10m" + ports: + - "5432:5432" + env_file: docker-compose.env + volumes: + - /etc/localtime:/etc/localtime:ro + - /etc/timezone:/etc/timezone:ro + - ~/dcm4chee-arc/db:/var/lib/postgresql/data + + arc: + image: dcm4che/dcm4chee-arc-psql:5.29.0 + logging: + driver: json-file + options: + max-size: "10m" + ports: + - "8080:8080" + - "8443:8443" + - "9990:9990" + - "9993:9993" + - "11112:11112" + - "2762:2762" + - "2575:2575" + - "12575:12575" + env_file: docker-compose.env + environment: + WILDFLY_CHOWN: /opt/wildfly/standalone /storage + WILDFLY_WAIT_FOR: ldap:389 db:5432 + depends_on: + - ldap + - db + volumes: + - /etc/localtime:/etc/localtime:ro + - /etc/timezone:/etc/timezone:ro + - ~/dcm4chee-arc/wildfly:/opt/wildfly/standalone + - ~/dcm4chee-arc/storage:/storage + + ohif_viewer: + build: + context: ./../../../../ + dockerfile: ./platform/app/.recipes/Nginx-Dcm4chee-Keycloak/dockerfile + image: webapp:latest + container_name: webapp + ports: + - '443:443' # SSL + - '80:80' # Web + depends_on: + keycloak: + condition: service_healthy + restart: on-failure + networks: + - default + extra_hosts: + - 'host.docker.internal:host-gateway' + environment: + - OAUTH2_PROXY_SKIP_PROVIDER_BUTTON=true + volumes: + - ./config/nginx.conf:/etc/nginx/nginx.conf + - ./config/oauth2-proxy.cfg:/etc/oauth2-proxy/oauth2-proxy.cfg + - ./config/letsencrypt:/etc/letsencrypt + - ./config/certbot:/var/www/certbot + + keycloak: + image: quay.io/keycloak/keycloak:24.0.5 + command: 'start-dev --import-realm' + hostname: keycloak + container_name: keycloak + volumes: + - ./config/ohif-keycloak-realm.json:/opt/keycloak/data/import/ohif-keycloak-realm.json + environment: + KC_DB_URL_HOST: postgres + KC_DB: postgres + KC_DB_URL: 'jdbc:postgresql://postgres:5432/keycloak' + KC_DB_SCHEMA: public + KC_DB_USERNAME: keycloak + KC_DB_PASSWORD: password + KC_HOSTNAME_ADMIN_URL: http://YOUR_DOMAIN/keycloak/ + KC_HOSTNAME_URL: http://YOUR_DOMAIN/keycloak/ + KC_HOSTNAME_STRICT_BACKCHANNEL: true + KC_HOSTNAME_STRICT_HTTPS: false + KC_HTTP_ENABLED: true + KEYCLOAK_ADMIN: admin + KEYCLOAK_ADMIN_PASSWORD: admin + KC_HEALTH_ENABLED: true + KC_METRICS_ENABLED: true + KC_PROXY: edge + KC_PROXY_HEADERS: xforwarded + KEYCLOAK_JDBC_PARAMS: connectTimeout=40000 + KC_LOG_LEVEL: INFO + KC_HOSTNAME_DEBUG: true + PROXY_ADDRESS_FORWARDING: true + ports: + - 8081:8080 + depends_on: + - postgres + restart: unless-stopped + networks: + - default + extra_hosts: + - 'host.docker.internal:host-gateway' + healthcheck: + test: + [ + "CMD-SHELL", + "exec 3<>/dev/tcp/YOUR_DOMAIN/8080;echo -e \"GET /health/ready HTTP/1.1\r\nhost: http://localhost\r\nConnection: close\r\n\r\n\" >&3;grep \"HTTP/1.1 200 OK\" <&3" + ] + interval: 1s + timeout: 5s + retries: 10 + start_period: 60s + + postgres: + image: postgres:15 + hostname: postgres + container_name: postgres + volumes: + - postgres_data:/var/lib/postgresql/data + environment: + POSTGRES_DB: keycloak + POSTGRES_USER: keycloak + POSTGRES_PASSWORD: password + restart: unless-stopped + networks: + - default + + certbot: + image: certbot/certbot + container_name: certbot + volumes: + - ./config/letsencrypt:/etc/letsencrypt + - ./config/certbot:/var/www/certbot + entrypoint: /bin/sh -c "trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;" + +volumes: + postgres_data: + driver: local + +networks: + default: + driver: bridge diff --git a/platform/app/.recipes/Nginx-Dcm4chee-Keycloak/dockerfile b/platform/app/.recipes/Nginx-Dcm4chee-Keycloak/dockerfile new file mode 100644 index 0000000000..bf610e8bd0 --- /dev/null +++ b/platform/app/.recipes/Nginx-Dcm4chee-Keycloak/dockerfile @@ -0,0 +1,50 @@ +# Stage 1: Build the application +FROM node:18.16.1-slim as builder + +# Setup the working directory +RUN mkdir /usr/src/app +WORKDIR /usr/src/app + +# Install dependencies +RUN apt-get update && apt-get install -y build-essential python3 + +# Copy the entire project +COPY ./ /usr/src/app/ + +# Install node dependencies +RUN yarn config set workspaces-experimental true +RUN yarn install + +# Set the environment for the build +ENV APP_CONFIG=config/docker-nginx-dcm4chee-keycloak.js + +# Build the application +RUN yarn run build + +# Stage 2: Setup the NGINX environment with OAuth2 Proxy +FROM nginx:alpine + +# Install dependencies for oauth2-proxy +RUN apk add --no-cache curl + +# Create necessary directories +RUN mkdir -p /var/logs/nginx /var/www/html /etc/oauth2-proxy + +# Download and install oauth2-proxy +RUN curl -L https://github.com/oauth2-proxy/oauth2-proxy/releases/download/v7.4.0/oauth2-proxy-v7.4.0.linux-amd64.tar.gz -o oauth2-proxy.tar.gz && \ + tar -xvzf oauth2-proxy.tar.gz && \ + mv oauth2-proxy-v7.4.0.linux-amd64/oauth2-proxy /usr/local/bin/ && \ + rm -rf oauth2-proxy-v7.4.0.linux-amd64 oauth2-proxy.tar.gz + +# Copy the built application +COPY --from=builder /usr/src/app/platform/app/dist /var/www/html + +# Copy the entrypoint script +COPY ./platform/app/.recipes/Nginx-Dcm4chee-Keycloak/config/entrypoint.sh /entrypoint.sh + +# Expose necessary ports +EXPOSE 80 443 4180 + +# Set the entrypoint script as the entrypoint +RUN chmod +x /entrypoint.sh +ENTRYPOINT ["/entrypoint.sh"] diff --git a/platform/app/.recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/ohif/account/.githold b/platform/app/.recipes/Nginx-Dcm4chee-Keycloak/etc/localtime similarity index 100% rename from platform/app/.recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/ohif/account/.githold rename to platform/app/.recipes/Nginx-Dcm4chee-Keycloak/etc/localtime diff --git a/platform/app/.recipes/Nginx-Dcm4chee-Keycloak/etc/timezone b/platform/app/.recipes/Nginx-Dcm4chee-Keycloak/etc/timezone new file mode 100644 index 0000000000..27f725e775 --- /dev/null +++ b/platform/app/.recipes/Nginx-Dcm4chee-Keycloak/etc/timezone @@ -0,0 +1 @@ +America/New_York \ No newline at end of file diff --git a/platform/app/.recipes/Nginx-Dcm4chee/config/nginx.conf b/platform/app/.recipes/Nginx-Dcm4chee/config/nginx.conf new file mode 100644 index 0000000000..8d9ca8f549 --- /dev/null +++ b/platform/app/.recipes/Nginx-Dcm4chee/config/nginx.conf @@ -0,0 +1,86 @@ +worker_processes auto; +error_log /var/logs/nginx/error.log debug; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; + use epoll; + multi_accept on; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/logs/nginx/access.log main; + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + types_hash_max_size 2048; + + gzip on; + gzip_disable "msie6"; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml; + + server { + listen 80 default_server; + listen [::]:80 default_server; + server_name _; + + client_max_body_size 0; + + + # Handle /pacs requests and rewrite them to the correct dcm4chee-arc UI path + # This allows accessing the dcm4chee-arc UI through the /pacs URL + location /pacs { + rewrite ^/pacs(.*)$ /dcm4chee-arc/ui2$1 break; + proxy_pass http://arc:8080; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_buffering off; + proxy_request_buffering off; + expires 0; + add_header Cache-Control private; + } + + # Proxy all dcm4chee-arc requests + # This block handles all API requests and general dcm4chee-arc paths + location /dcm4chee-arc/ { + proxy_pass http://arc:8080/dcm4chee-arc/; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_buffering off; + proxy_request_buffering off; + } + + + location /sw.js { + add_header Cache-Control "no-cache"; + proxy_cache_bypass $http_pragma; + proxy_cache_revalidate on; + expires off; + access_log off; + } + + location / { + root /var/www/html; + index index.html; + try_files $uri $uri/ /index.html; + add_header Cache-Control "no-store, no-cache, must-revalidate"; + add_header Cross-Origin-Opener-Policy 'same-origin' always; + add_header Cross-Origin-Embedder-Policy 'require-corp' always; + } + } +} diff --git a/platform/app/.recipes/Nginx-Dcm4chee/docker-compose.env b/platform/app/.recipes/Nginx-Dcm4chee/docker-compose.env new file mode 100644 index 0000000000..54961c3760 --- /dev/null +++ b/platform/app/.recipes/Nginx-Dcm4chee/docker-compose.env @@ -0,0 +1,4 @@ +STORAGE_DIR=/storage/fs1 +POSTGRES_DB=pacsdb +POSTGRES_USER=pacs +POSTGRES_PASSWORD=pacs diff --git a/platform/app/.recipes/Nginx-Dcm4chee/docker-compose.yml b/platform/app/.recipes/Nginx-Dcm4chee/docker-compose.yml index 40b6d8efe8..88aad58daa 100644 --- a/platform/app/.recipes/Nginx-Dcm4chee/docker-compose.yml +++ b/platform/app/.recipes/Nginx-Dcm4chee/docker-compose.yml @@ -1,50 +1,45 @@ -version: '3.5' - services: ldap: - image: dcm4che/slapd-dcm4chee:2.4.44-15.0 + image: dcm4che/slapd-dcm4chee:2.6.3-29.0 logging: driver: json-file options: - max-size: '10m' + max-size: "10m" ports: - - '389:389' - env_file: ./dcm4che/docker-compose-dcm4che.env + - "389:389" + env_file: docker-compose.env volumes: - - ./dcm4che/etc/localtime:/etc/localtime:ro - - ./dcm4che/etc/timezone:/etc/timezone:ro - - ./dcm4che/dcm4che-arc/ldap:/var/lib/ldap - - ./dcm4che/dcm4che-arc/slapd.d:/etc/ldap/slapd.d - networks: - - dcm4che_default + - ~/dcm4chee-arc/ldap:/var/lib/ldap + - ~/dcm4chee-arc/slapd.d:/etc/ldap/slapd.d db: - image: dcm4che/postgres-dcm4chee:11.1-15 + image: dcm4che/postgres-dcm4chee:14.5-29 logging: driver: json-file options: - max-size: '10m' + max-size: "10m" ports: - - '5432:5432' - env_file: ./dcm4che/docker-compose-dcm4che.env + - "5432:5432" + env_file: docker-compose.env volumes: - - ./dcm4che/etc/localtime:/etc/localtime:ro - - ./dcm4che/etc/timezone:/etc/timezone:ro - - ./dcm4che/dcm4che-arc/db:/var/lib/postgresql/data - networks: - - dcm4che_default + - /etc/localtime:/etc/localtime:ro + - /etc/timezone:/etc/timezone:ro + - ~/dcm4chee-arc/db:/var/lib/postgresql/data arc: - image: dcm4che/dcm4chee-arc-psql:5.15.0 + image: dcm4che/dcm4chee-arc-psql:5.29.0 logging: driver: json-file options: - max-size: '10m' + max-size: "10m" ports: - - '8080:8080' - - '8443:8443' - - '9990:9990' - - '11112:11112' - - '2575:2575' - env_file: ./dcm4che/docker-compose-dcm4che.env + - "8080:8080" + - "8443:8443" + - "9990:9990" + - "9993:9993" + - "11112:11112" + - "2762:2762" + - "2575:2575" + - "12575:12575" + env_file: docker-compose.env environment: WILDFLY_CHOWN: /opt/wildfly/standalone /storage WILDFLY_WAIT_FOR: ldap:389 db:5432 @@ -52,26 +47,27 @@ services: - ldap - db volumes: - - ./dcm4che/etc/localtime:/etc/localtime:ro - - ./dcm4che/etc/timezone:/etc/timezone:ro - - ./dcm4che/dcm4che-arc/wildfly:/opt/wildfly/standalone - - ./dcm4che/dcm4che-arc/storage:/storage - networks: - - dcm4che_default - viewer: - container_name: ohif-viewer + - /etc/localtime:/etc/localtime:ro + - /etc/timezone:/etc/timezone:ro + - ~/dcm4chee-arc/wildfly:/opt/wildfly/standalone + - ~/dcm4chee-arc/storage:/storage + ohif_viewer: build: - context: ../ - dockerfile: Dockerfile + # Project root + context: ./../../../../ + # Relative to context + dockerfile: ./platform/app/.recipes/Nginx-Dcm4chee/dockerfile + image: webapp:latest + container_name: ohif_dcm4chee + volumes: + # Nginx config + - ./config/nginx.conf:/etc/nginx/nginx.conf + # Logs + - ./logs/nginx:/var/logs/nginx + # Let's Encrypt + # - letsencrypt_certificates:/etc/letsencrypt + # - letsencrypt_challenges:/var/www/letsencrypt ports: - - '80:80' - # depends_on: - # - orthanc - environment: - - NODE_ENV=production - - APP_CONFIG=config/local_dcm4chee - restart: always - networks: - - dcm4che_default - -networks: dcm4che_default: + - '443:443' # SSL + - '80:80' # Web + restart: on-failure diff --git a/platform/app/.recipes/Nginx-Dcm4chee/dockerfile b/platform/app/.recipes/Nginx-Dcm4chee/dockerfile new file mode 100644 index 0000000000..d28e960560 --- /dev/null +++ b/platform/app/.recipes/Nginx-Dcm4chee/dockerfile @@ -0,0 +1,43 @@ +# Stage 1: Build the application +FROM node:18.16.1-slim as builder + +# Setup the working directory +RUN mkdir /usr/src/app +WORKDIR /usr/src/app + +# Install dependencies +# apt-get update is combined with apt-get install to avoid using outdated packages +RUN apt-get update && apt-get install -y build-essential python3 + +# Copy package.json and other dependency-related files first +# Assuming your package.json and yarn.lock or similar are located in the project root + +COPY ./ /usr/src/app/ + +# Install node dependencies +RUN yarn config set workspaces-experimental true +RUN yarn install + +# Copy the rest of the application code + +# set QUICK_BUILD to true to make the build faster for dev +ENV APP_CONFIG=config/docker-nginx-dcm4chee.js + +# Build the application +RUN yarn run build + +# # Stage 2: Bundle the built application into a Docker container which runs NGINX using Alpine Linux +FROM nginx:alpine + +# # Create directories for logs and html content if they don't already exist +RUN mkdir -p /var/log/nginx /var/www/html + + +# # Copy build output to serve static files +COPY --from=builder /usr/src/app/platform/app/dist /var/www/html + +# # Expose HTTP and HTTPS ports +EXPOSE 80 443 + +# # Start NGINX +CMD ["nginx", "-g", "daemon off;"] diff --git a/platform/app/.recipes/Nginx-Dcm4chee/nginx-proxy/conf/nginx.conf b/platform/app/.recipes/Nginx-Dcm4chee/nginx-proxy/conf/nginx.conf deleted file mode 100644 index de38c7f006..0000000000 --- a/platform/app/.recipes/Nginx-Dcm4chee/nginx-proxy/conf/nginx.conf +++ /dev/null @@ -1,49 +0,0 @@ -events { - worker_connections 4096; ## Default: 1024 -} - -http { - server { - listen 80 default_server; - server_name localhost; - - # - # Wide-open CORS config for nginx - # - location / { - if ($request_method = 'OPTIONS') { - add_header 'Access-Control-Allow-Origin' '*'; - add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; - # - # Custom headers and headers various browsers *should* be OK with but aren't - # - add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; - # - # Tell client that this pre-flight info is valid for 20 days - # - add_header 'Access-Control-Allow-Headers' 'Authorization'; - add_header 'Access-Control-Allow-Credentials' true; - add_header 'Access-Control-Max-Age' 1728000; - add_header 'Content-Length' 0; - return 204; - } - if ($request_method = 'POST') { - add_header 'Access-Control-Allow-Origin' '*'; - add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; - add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; - add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range'; - } - if ($request_method = 'GET') { - add_header 'Access-Control-Allow-Origin' '*'; - add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; - add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; - add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range'; - add_header 'Access-Control-Allow-Headers' 'Authorization'; - add_header 'Access-Control-Allow-Credentials' true; - } - - proxy_pass http://orthanc:8042; - } - - } -} \ No newline at end of file diff --git a/platform/app/.recipes/Nginx-Orthanc-Keycloak/.gitignore b/platform/app/.recipes/Nginx-Orthanc-Keycloak/.gitignore new file mode 100644 index 0000000000..088f9a97f7 --- /dev/null +++ b/platform/app/.recipes/Nginx-Orthanc-Keycloak/.gitignore @@ -0,0 +1,6 @@ +logs/* +volumes/* +config/letsencrypt/* +config/certbot/* +!config/letsencrypt/.gitkeep +!config/certbot/.gitkeep diff --git a/platform/app/.recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/ohif/admin/.githold b/platform/app/.recipes/Nginx-Orthanc-Keycloak/config/certbot/.gitkeep similarity index 100% rename from platform/app/.recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/ohif/admin/.githold rename to platform/app/.recipes/Nginx-Orthanc-Keycloak/config/certbot/.gitkeep diff --git a/platform/app/.recipes/Nginx-Orthanc-Keycloak/config/entrypoint.sh b/platform/app/.recipes/Nginx-Orthanc-Keycloak/config/entrypoint.sh new file mode 100644 index 0000000000..8648d7c7ca --- /dev/null +++ b/platform/app/.recipes/Nginx-Orthanc-Keycloak/config/entrypoint.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +# Start oauth2-proxy +oauth2-proxy --config=/etc/oauth2-proxy/oauth2-proxy.cfg & + +# Start nginx +nginx -g "daemon off;" diff --git a/platform/app/.recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/ohif/email/.githold b/platform/app/.recipes/Nginx-Orthanc-Keycloak/config/letsencrypt/.gitkeep similarity index 100% rename from platform/app/.recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/ohif/email/.githold rename to platform/app/.recipes/Nginx-Orthanc-Keycloak/config/letsencrypt/.gitkeep diff --git a/platform/app/.recipes/Nginx-Orthanc-Keycloak/config/nginx.conf b/platform/app/.recipes/Nginx-Orthanc-Keycloak/config/nginx.conf new file mode 100644 index 0000000000..1ad9f512dc --- /dev/null +++ b/platform/app/.recipes/Nginx-Orthanc-Keycloak/config/nginx.conf @@ -0,0 +1,210 @@ +worker_processes 2; +error_log /var/logs/nginx/mydomain.error.log; +pid /var/run/nginx.pid; +include /usr/share/nginx/modules/*.conf; + +events { + worker_connections 1024; + use epoll; + multi_accept on; +} + +http { + include '/etc/nginx/mime.types'; + default_type application/octet-stream; + + keepalive_timeout 65; + keepalive_requests 100000; + tcp_nopush on; + tcp_nodelay on; + + proxy_buffers 16 16k; + proxy_buffer_size 32k; + proxy_busy_buffers_size 64k; + proxy_max_temp_file_size 128k; + + server { + listen 80; + server_name YOUR_DOMAIN; + + location /.well-known/acme-challenge/ { + root /var/www/certbot; + } + + location / { + return 301 https://$host$request_uri; + } + } + + server { + listen 443 ssl; + server_name YOUR_DOMAIN; + + ssl_certificate /etc/letsencrypt/live/ohifviewer.duckdns.org/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/ohifviewer.duckdns.org/privkey.pem; + + root /var/www/html; + + gzip on; + gzip_types text/css application/javascript application/json image/svg+xml; + gzip_comp_level 9; + etag on; + + location /sw.js { + add_header Cache-Control "no-cache"; + proxy_cache_bypass $http_pragma; + proxy_cache_revalidate on; + expires off; + access_log off; + } + + location /oauth2 { + expires -1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Auth-Request-Redirect $request_uri; + proxy_pass http://localhost:4180$uri$is_args$args; + } + + location /oauth2/callback { + proxy_pass http://localhost:4180; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location /oauth2/sign_out { + expires -1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Auth-Request-Redirect /oauth2/sign_in; + proxy_pass http://localhost:4180; + } + + location /pacs-admin/ { + error_page 401 = /oauth2/sign_in?rd=$scheme://$host$request_uri; + auth_request /oauth2/auth?allowed_groups=pacsadmin; + + auth_request_set $user $upstream_http_x_auth_request_user; + auth_request_set $token $upstream_http_x_auth_request_access_token; + auth_request_set $auth_cookie $upstream_http_set_cookie; + + proxy_set_header X-User $user; + proxy_set_header X-Access-Token $token; + add_header Set-Cookie $auth_cookie; + + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + expires 0; + add_header Cache-Control private; + + add_header 'Access-Control-Allow-Origin' '*' always; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; + add_header 'Access-Control-Allow-Headers' 'Authorization, Origin, X-Requested-With, Content-Type, Accept' always; + + if ($request_method = OPTIONS) { + add_header 'Access-Control-Allow-Origin' '*'; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; + add_header 'Access-Control-Allow-Headers' 'Authorization, Origin, X-Requested-With, Content-Type, Accept'; + add_header 'Access-Control-Max-Age' 1728000; + add_header 'Content-Type' 'text/plain; charset=utf-8'; + add_header 'Content-Length' 0; + return 204; + } + + proxy_pass http://orthanc:8042/; + } + + location /pacs-admin { + return 301 /pacs-admin/; + } + + location /pacs/ { + auth_request /oauth2/auth; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + expires 0; + add_header Cache-Control private; + + add_header 'Access-Control-Allow-Origin' '*' always; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; + add_header 'Access-Control-Allow-Headers' 'Authorization, Origin, X-Requested-With, Content-Type, Accept' always; + + if ($request_method = OPTIONS) { + add_header 'Access-Control-Allow-Origin' '*'; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; + add_header 'Access-Control-Allow-Headers' 'Authorization, Origin, X-Requested-With, Content-Type, Accept'; + add_header 'Access-Control-Max-Age' 1728000; + add_header 'Content-Type' 'text/plain; charset=utf-8'; + add_header 'Content-Length' 0; + return 204; + } + + proxy_pass http://orthanc:8042/dicom-web/; + } + + location /pacs { + return 301 /pacs/; + } + + location /ohif-viewer/ { + expires -1; + error_page 401 = /oauth2/sign_in?rd=$scheme://$host$request_uri; + auth_request /oauth2/auth; + + auth_request_set $user $upstream_http_x_auth_request_user; + auth_request_set $token $upstream_http_x_auth_request_access_token; + auth_request_set $auth_cookie $upstream_http_set_cookie; + + proxy_set_header X-User $user; + proxy_set_header X-Access-Token $token; + add_header Set-Cookie $auth_cookie; + + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Server $host; + proxy_set_header X-Forwarded-Proto $scheme; + + index index.html; + try_files $uri $uri/ /index.html; + } + + location /ohif-viewer { + return 301 /ohif-viewer/; + } + + location = / { + return 301 /ohif-viewer/; + } + + location / { + add_header Cache-Control "no-store, no-cache, must-revalidate"; + add_header 'Cross-Origin-Opener-Policy' 'same-origin' always; + add_header 'Cross-Origin-Embedder-Policy' 'require-corp' always; + } + + location /keycloak/ { + proxy_pass http://keycloak:8080/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location /keycloak { + return 301 /keycloak/; + } + } +} diff --git a/platform/app/.recipes/Nginx-Orthanc-Keycloak/config/oauth2-proxy.cfg b/platform/app/.recipes/Nginx-Orthanc-Keycloak/config/oauth2-proxy.cfg new file mode 100644 index 0000000000..985525af91 --- /dev/null +++ b/platform/app/.recipes/Nginx-Orthanc-Keycloak/config/oauth2-proxy.cfg @@ -0,0 +1,22 @@ +http_address="0.0.0.0:4180" +cookie_secret="GENERATEACOOKIESECRET----------------------=" +email_domains=["*"] +cookie_secure="false" +cookie_expire="9m30s" +cookie_refresh="5m" +client_secret="2Xtlde7aozdkzzYHdIxQNfPDr0wNPTgg" +client_id="ohif_viewer" +redirect_url="http://YOUR_DOMAIN/oauth2/callback" + +ssl_insecure_skip_verify = true +insecure_oidc_allow_unverified_email = true +pass_access_token = true +provider="keycloak-oidc" +provider_display_name="Keycloak" +user_id_claim="oid" +oidc_email_claim="sub" +scope="openid" +pass_host_header=true +code_challenge_method="S256" +oidc_issuer_url="http://YOUR_DOMAIN/keycloak/realms/ohif" +insecure_oidc_skip_issuer_verification = true diff --git a/platform/app/.recipes/Nginx-Orthanc-Keycloak/config/ohif-keycloak-realm.json b/platform/app/.recipes/Nginx-Orthanc-Keycloak/config/ohif-keycloak-realm.json new file mode 100644 index 0000000000..3064ee70e4 --- /dev/null +++ b/platform/app/.recipes/Nginx-Orthanc-Keycloak/config/ohif-keycloak-realm.json @@ -0,0 +1,2315 @@ +{ + "id": "37c16268-9c83-41c3-b452-3fbc86e6966d", + "realm": "ohif", + "notBefore": 0, + "defaultSignatureAlgorithm": "RS256", + "revokeRefreshToken": false, + "refreshTokenMaxReuse": 0, + "accessTokenLifespan": 300, + "accessTokenLifespanForImplicitFlow": 900, + "ssoSessionIdleTimeout": 1800, + "ssoSessionMaxLifespan": 36000, + "ssoSessionIdleTimeoutRememberMe": 0, + "ssoSessionMaxLifespanRememberMe": 0, + "offlineSessionIdleTimeout": 2592000, + "offlineSessionMaxLifespanEnabled": false, + "offlineSessionMaxLifespan": 5184000, + "clientSessionIdleTimeout": 0, + "clientSessionMaxLifespan": 0, + "clientOfflineSessionIdleTimeout": 0, + "clientOfflineSessionMaxLifespan": 0, + "accessCodeLifespan": 60, + "accessCodeLifespanUserAction": 300, + "accessCodeLifespanLogin": 1800, + "actionTokenGeneratedByAdminLifespan": 43200, + "actionTokenGeneratedByUserLifespan": 300, + "oauth2DeviceCodeLifespan": 600, + "oauth2DevicePollingInterval": 5, + "enabled": true, + "sslRequired": "none", + "registrationAllowed": false, + "registrationEmailAsUsername": false, + "rememberMe": false, + "verifyEmail": false, + "loginWithEmailAllowed": true, + "duplicateEmailsAllowed": false, + "resetPasswordAllowed": false, + "editUsernameAllowed": false, + "bruteForceProtected": false, + "permanentLockout": false, + "maxTemporaryLockouts": 0, + "maxFailureWaitSeconds": 900, + "minimumQuickLoginWaitSeconds": 60, + "waitIncrementSeconds": 60, + "quickLoginCheckMilliSeconds": 1000, + "maxDeltaTimeSeconds": 43200, + "failureFactor": 30, + "roles": { + "realm": [ + { + "id": "b886fa27-974b-446f-adaa-a2c96342ce05", + "name": "uma_authorization", + "description": "${role_uma_authorization}", + "composite": false, + "clientRole": false, + "containerId": "37c16268-9c83-41c3-b452-3fbc86e6966d", + "attributes": {} + }, + { + "id": "d8bba2d8-ac65-46cb-a1b3-bbee4850333f", + "name": "offline_access", + "description": "${role_offline-access}", + "composite": false, + "clientRole": false, + "containerId": "37c16268-9c83-41c3-b452-3fbc86e6966d", + "attributes": {} + }, + { + "id": "4d80d451-18c2-4982-b2b7-f43aad1b54aa", + "name": "default-roles-ohif", + "description": "${role_default-roles}", + "composite": true, + "composites": { + "realm": [ + "offline_access", + "uma_authorization" + ], + "client": { + "account": [ + "manage-account", + "view-profile" + ] + } + }, + "clientRole": false, + "containerId": "37c16268-9c83-41c3-b452-3fbc86e6966d", + "attributes": {} + } + ], + "client": { + "realm-management": [ + { + "id": "0c749b40-bda4-463a-b1c2-edd014606c8c", + "name": "manage-identity-providers", + "description": "${role_manage-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "70605217-ff53-4895-8686-2f87bb81cecd", + "name": "view-realm", + "description": "${role_view-realm}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "1482af22-41e6-4850-b5a3-3d479edd334b", + "name": "view-users", + "description": "${role_view-users}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-users", + "query-groups" + ] + } + }, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "7b2b0fcd-3539-4322-bd12-379398ff9c63", + "name": "query-groups", + "description": "${role_query-groups}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "f5856ab0-17fe-49bb-8e04-27d1f37c53c7", + "name": "manage-realm", + "description": "${role_manage-realm}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "5cd89fbb-7860-4505-90b8-ad99b28a7ce2", + "name": "manage-users", + "description": "${role_manage-users}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "c53a6ea6-9c79-485f-9402-b2607df09f53", + "name": "view-authorization", + "description": "${role_view-authorization}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "696a4591-d966-446c-a1f6-9a8a8de41f41", + "name": "query-clients", + "description": "${role_query-clients}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "3b0c1a20-0692-4594-973f-bd7c0d42631b", + "name": "manage-authorization", + "description": "${role_manage-authorization}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "3279ff3a-ae5c-4d59-99a3-3b2791391745", + "name": "query-realms", + "description": "${role_query-realms}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "56767ac1-1098-41c9-8b94-b9efe47fa17a", + "name": "create-client", + "description": "${role_create-client}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "e231ed30-1c79-4786-80dc-c16d87866b03", + "name": "query-users", + "description": "${role_query-users}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "388304d0-befe-4498-99cd-c9821dfe5ff6", + "name": "realm-admin", + "description": "${role_realm-admin}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "manage-identity-providers", + "view-realm", + "view-users", + "query-groups", + "manage-realm", + "manage-users", + "view-authorization", + "query-clients", + "manage-authorization", + "query-realms", + "create-client", + "query-users", + "view-events", + "view-identity-providers", + "manage-clients", + "manage-events", + "view-clients", + "impersonation" + ] + } + }, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "901b8b02-4525-4ed9-b6c5-ee822a874236", + "name": "view-events", + "description": "${role_view-events}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "d9c612fa-421a-4463-8837-4bcc059649ea", + "name": "manage-clients", + "description": "${role_manage-clients}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "efbd010a-67a1-472c-b308-a91723ebe819", + "name": "manage-events", + "description": "${role_manage-events}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "60cbee1d-9fa4-47ee-8f86-f71ae22482c1", + "name": "view-identity-providers", + "description": "${role_view-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "84219236-4eaa-4ea7-a94c-52d6f8e1bb79", + "name": "view-clients", + "description": "${role_view-clients}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-clients" + ] + } + }, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + }, + { + "id": "d46f77b0-ed82-4580-994f-8a6a8fc22480", + "name": "impersonation", + "description": "${role_impersonation}", + "composite": false, + "clientRole": true, + "containerId": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "attributes": {} + } + ], + "security-admin-console": [], + "ohif_viewer": [], + "admin-cli": [], + "account-console": [], + "broker": [ + { + "id": "3e2b2c4a-416e-463d-8907-b919d17a4592", + "name": "read-token", + "description": "${role_read-token}", + "composite": false, + "clientRole": true, + "containerId": "8d52074d-c27d-4917-8280-a33bcae47f59", + "attributes": {} + } + ], + "account": [ + { + "id": "1bd17278-c076-41df-9559-7f3524d5cd5e", + "name": "manage-account", + "description": "${role_manage-account}", + "composite": true, + "composites": { + "client": { + "account": [ + "manage-account-links" + ] + } + }, + "clientRole": true, + "containerId": "50a0e32a-f503-497b-b3c3-ff127cc56a56", + "attributes": {} + }, + { + "id": "302c47ca-5e53-4cbe-9670-4e10a281d2bf", + "name": "view-applications", + "description": "${role_view-applications}", + "composite": false, + "clientRole": true, + "containerId": "50a0e32a-f503-497b-b3c3-ff127cc56a56", + "attributes": {} + }, + { + "id": "a6bd8131-df31-4922-b7da-7011d7e967db", + "name": "view-profile", + "description": "${role_view-profile}", + "composite": false, + "clientRole": true, + "containerId": "50a0e32a-f503-497b-b3c3-ff127cc56a56", + "attributes": {} + }, + { + "id": "eed205fe-b606-4562-8b65-503e3d4d7d89", + "name": "manage-account-links", + "description": "${role_manage-account-links}", + "composite": false, + "clientRole": true, + "containerId": "50a0e32a-f503-497b-b3c3-ff127cc56a56", + "attributes": {} + }, + { + "id": "ea20e235-92da-4409-9a82-2dc4244bc342", + "name": "view-groups", + "description": "${role_view-groups}", + "composite": false, + "clientRole": true, + "containerId": "50a0e32a-f503-497b-b3c3-ff127cc56a56", + "attributes": {} + }, + { + "id": "ccca6524-fbc9-4712-a703-f4311b94e757", + "name": "manage-consent", + "description": "${role_manage-consent}", + "composite": true, + "composites": { + "client": { + "account": [ + "view-consent" + ] + } + }, + "clientRole": true, + "containerId": "50a0e32a-f503-497b-b3c3-ff127cc56a56", + "attributes": {} + }, + { + "id": "1b2fa98f-7ff0-4bf6-974c-c3e8b36d8dc3", + "name": "delete-account", + "description": "${role_delete-account}", + "composite": false, + "clientRole": true, + "containerId": "50a0e32a-f503-497b-b3c3-ff127cc56a56", + "attributes": {} + }, + { + "id": "dc213956-175c-4ef1-99e8-0033818761f4", + "name": "view-consent", + "description": "${role_view-consent}", + "composite": false, + "clientRole": true, + "containerId": "50a0e32a-f503-497b-b3c3-ff127cc56a56", + "attributes": {} + } + ] + } + }, + "groups": [ + { + "id": "3249b4f1-6572-4b59-a206-7e707d1e45f6", + "name": "pacsadmin", + "path": "/pacsadmin", + "subGroups": [], + "attributes": {}, + "realmRoles": [], + "clientRoles": {} + } + ], + "defaultRole": { + "id": "4d80d451-18c2-4982-b2b7-f43aad1b54aa", + "name": "default-roles-ohif", + "description": "${role_default-roles}", + "composite": true, + "clientRole": false, + "containerId": "37c16268-9c83-41c3-b452-3fbc86e6966d" + }, + "requiredCredentials": [ + "password" + ], + "otpPolicyType": "totp", + "otpPolicyAlgorithm": "HmacSHA1", + "otpPolicyInitialCounter": 0, + "otpPolicyDigits": 6, + "otpPolicyLookAheadWindow": 1, + "otpPolicyPeriod": 30, + "otpPolicyCodeReusable": false, + "otpSupportedApplications": [ + "totpAppFreeOTPName", + "totpAppGoogleName", + "totpAppMicrosoftAuthenticatorName" + ], + "localizationTexts": {}, + "webAuthnPolicyRpEntityName": "keycloak", + "webAuthnPolicySignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyRpId": "", + "webAuthnPolicyAttestationConveyancePreference": "not specified", + "webAuthnPolicyAuthenticatorAttachment": "not specified", + "webAuthnPolicyRequireResidentKey": "not specified", + "webAuthnPolicyUserVerificationRequirement": "not specified", + "webAuthnPolicyCreateTimeout": 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyAcceptableAaguids": [], + "webAuthnPolicyExtraOrigins": [], + "webAuthnPolicyPasswordlessRpEntityName": "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyPasswordlessRpId": "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey": "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified", + "webAuthnPolicyPasswordlessCreateTimeout": 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyPasswordlessAcceptableAaguids": [], + "webAuthnPolicyPasswordlessExtraOrigins": [], + "scopeMappings": [ + { + "clientScope": "offline_access", + "roles": [ + "offline_access" + ] + } + ], + "clientScopeMappings": { + "account": [ + { + "client": "account-console", + "roles": [ + "manage-account", + "view-groups" + ] + } + ] + }, + "clients": [ + { + "id": "50a0e32a-f503-497b-b3c3-ff127cc56a56", + "clientId": "account", + "name": "${client_account}", + "description": "", + "rootUrl": "${authAdminUrl}", + "adminUrl": "", + "baseUrl": "/realms/ohif/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/realms/ohif/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "oidc.ciba.grant.enabled": "false", + "backchannel.logout.session.required": "true", + "post.logout.redirect.uris": "+", + "display.on.consent.screen": "false", + "oauth2.device.authorization.grant.enabled": "false", + "backchannel.logout.revoke.offline.tokens": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "5c719a4e-2eed-4b9a-9536-edafb7763e6e", + "clientId": "account-console", + "name": "${client_account-console}", + "description": "", + "rootUrl": "${authAdminUrl}", + "adminUrl": "", + "baseUrl": "/realms/ohif/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/realms/ohif/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "oidc.ciba.grant.enabled": "false", + "backchannel.logout.session.required": "true", + "post.logout.redirect.uris": "+", + "display.on.consent.screen": "false", + "oauth2.device.authorization.grant.enabled": "false", + "pkce.code.challenge.method": "S256", + "backchannel.logout.revoke.offline.tokens": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "2a172f00-5ae2-400a-8aba-0c8f267844a3", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "5f86b71b-9a75-465a-9007-9cadd861a1c5", + "clientId": "admin-cli", + "name": "${client_admin-cli}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "8d52074d-c27d-4917-8280-a33bcae47f59", + "clientId": "broker", + "name": "${client_broker}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "ceddadb2-f4b6-4a1d-a0c8-efdd95fd2e9a", + "clientId": "ohif_viewer", + "name": "", + "description": "", + "rootUrl": "http://127.0.0.1", + "adminUrl": "http://127.0.0.1", + "baseUrl": "http://127.0.0.1", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "2Xtlde7aozdkzzYHdIxQNfPDr0wNPTgg", + "redirectUris": [ + "http://127.0.0.1/oauth2/callback" + ], + "webOrigins": [ + "http://127.0.0.1" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": true, + "protocol": "openid-connect", + "attributes": { + "oidc.ciba.grant.enabled": "false", + "client.secret.creation.time": "1718045868", + "backchannel.logout.session.required": "true", + "display.on.consent.screen": "false", + "oauth2.device.authorization.grant.enabled": "false", + "backchannel.logout.revoke.offline.tokens": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "id": "b405129c-ed1b-4c4e-b712-1f736be6440b", + "name": "Audience", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-mapper", + "consentRequired": false, + "config": { + "included.client.audience": "ohif_viewer", + "id.token.claim": "true", + "lightweight.claim": "false", + "access.token.claim": "true", + "introspection.token.claim": "true" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "groups", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "fac6a1ed-5b50-4e83-b4a5-dff4f6499abc", + "clientId": "realm-management", + "name": "${client_realm-management}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "ace68c1f-eae4-4d93-ab98-0005a071177d", + "clientId": "security-admin-console", + "name": "${client_security-admin-console}", + "rootUrl": "${authAdminUrl}", + "baseUrl": "/admin/ohif/console/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/admin/ohif/console/*" + ], + "webOrigins": [ + "+" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+", + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "fdee0223-2998-486a-b591-ae6712ae7831", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + } + ], + "clientScopes": [ + { + "id": "73b70709-cb2f-4d06-86af-0b04425970ee", + "name": "email", + "description": "OpenID Connect built-in scope: email", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${emailScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "0c8df10b-097f-4b13-85b8-3ec3b4d3ef03", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + }, + { + "id": "6cff88ad-73ed-4699-86f9-c7ac5e473a53", + "name": "email verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "emailVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email_verified", + "jsonType.label": "boolean" + } + } + ] + }, + { + "id": "4098872d-e896-4042-a715-be23f0a1437c", + "name": "offline_access", + "description": "OpenID Connect built-in scope: offline_access", + "protocol": "openid-connect", + "attributes": { + "consent.screen.text": "${offlineAccessScopeConsentText}", + "display.on.consent.screen": "true" + } + }, + { + "id": "06ba9538-581f-4c0b-a7ca-b56eaa8c1e59", + "name": "profile", + "description": "OpenID Connect built-in scope: profile", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${profileScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "d992a9b9-ec09-49fd-b052-65942ff5ba58", + "name": "updated at", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "updatedAt", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "updated_at", + "jsonType.label": "long" + } + }, + { + "id": "9b2089a4-ce6f-4dcb-abd8-67844a8e17b5", + "name": "profile", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "profile", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "profile", + "jsonType.label": "String" + } + }, + { + "id": "0e37cc54-2ff9-4976-9f66-f6f949652d40", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "introspection.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + }, + { + "id": "f2d87384-cc84-4d8a-bef7-379491ba1430", + "name": "gender", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "gender", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "gender", + "jsonType.label": "String" + } + }, + { + "id": "03c9b60a-32a9-4bd2-9173-ee7048f8face", + "name": "picture", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "picture", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "picture", + "jsonType.label": "String" + } + }, + { + "id": "6db8e846-d71d-4573-89be-cc249c93c4fd", + "name": "birthdate", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "birthdate", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "birthdate", + "jsonType.label": "String" + } + }, + { + "id": "aacde81e-9462-446f-abf9-25bb83d3c442", + "name": "website", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "website", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "website", + "jsonType.label": "String" + } + }, + { + "id": "44dc5e2c-de20-4e46-94ed-e5fbecee8021", + "name": "zoneinfo", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "zoneinfo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "zoneinfo", + "jsonType.label": "String" + } + }, + { + "id": "74ab1492-ecbb-4a52-a5dd-820d7bc1dec5", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + }, + { + "id": "69aab70e-94d5-45f0-ab8f-14c973492636", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "611957f1-cdfe-43b9-acc6-d2d37b5b6908", + "name": "nickname", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "nickname", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "nickname", + "jsonType.label": "String" + } + }, + { + "id": "90e9af6c-7a44-4b8b-bdea-020ccd7cf79b", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + }, + { + "id": "d1ceeaef-bebc-4be6-b5b7-85e361b91ce5", + "name": "middle name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "middleName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "middle_name", + "jsonType.label": "String" + } + }, + { + "id": "d74b3e90-c391-4fea-806d-98b24e598ade", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "077a40b6-ae18-440a-9858-57cb93483f4d", + "name": "web-origins", + "description": "OpenID Connect scope for add allowed web origins to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false", + "consent.screen.text": "" + }, + "protocolMappers": [ + { + "id": "f7a704cc-7466-41b4-ada4-3efe4dceb599", + "name": "allowed web origins", + "protocol": "openid-connect", + "protocolMapper": "oidc-allowed-origins-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "access.token.claim": "true" + } + } + ] + }, + { + "id": "16085075-08fa-4fe8-aa9e-c429b26df40e", + "name": "roles", + "description": "OpenID Connect scope for add user roles to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "true", + "consent.screen.text": "${rolesScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "1cb74178-9ba0-4225-8ede-a263f0cf0f9d", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "access.token.claim": "true" + } + }, + { + "id": "020299f1-b469-41fb-b80d-5cea4ceb4e7d", + "name": "realm roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "multivalued": "true", + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "realm_access.roles", + "jsonType.label": "String" + } + }, + { + "id": "6759edaf-7d37-44b0-ad7b-50a3383e9cd9", + "name": "client roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-client-role-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "multivalued": "true", + "userinfo.token.claim": "false", + "user.attribute": "foo", + "lightweight.claim": "false", + "id.token.claim": "false", + "access.token.claim": "true", + "claim.name": "resource_access.${client_id}. roles", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "905660b4-380a-4a8c-81a9-bd16b3b3ce3f", + "name": "microprofile-jwt", + "description": "Microprofile - JWT built-in scope", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "4e2f2bd8-602f-4ae1-a431-fa92bdedd386", + "name": "upn", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "upn", + "jsonType.label": "String" + } + }, + { + "id": "f1e69dc4-f19e-4c21-bbf9-609016339710", + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "multivalued": "true", + "user.attribute": "foo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "groups", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "24748647-8a70-422e-8532-f8d231a006db", + "name": "acr", + "description": "OpenID Connect scope for add acr (authentication context class reference) to the token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "fd884f9e-e345-4823-b463-beb39020ca23", + "name": "acr loa level", + "protocol": "openid-connect", + "protocolMapper": "oidc-acr-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "introspection.token.claim": "true", + "access.token.claim": "true" + } + } + ] + }, + { + "id": "db5c28fd-e142-40e1-926c-017d0d58c04a", + "name": "groups", + "description": "", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "true", + "gui.order": "", + "consent.screen.text": "" + }, + "protocolMappers": [ + { + "id": "1f5afdb5-1de2-40c7-8526-d1ad0585720b", + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-group-membership-mapper", + "consentRequired": false, + "config": { + "full.path": "false", + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "multivalued": "true", + "id.token.claim": "true", + "lightweight.claim": "false", + "access.token.claim": "true", + "claim.name": "groups" + } + } + ] + }, + { + "id": "c1678c18-641f-4eeb-af7e-c5327adee009", + "name": "role_list", + "description": "SAML role list", + "protocol": "saml", + "attributes": { + "consent.screen.text": "${samlRoleListScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "bec886da-1100-4af1-a83f-b322a23e9856", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + } + ] + }, + { + "id": "ead6084e-d9f1-4388-80c6-aead5b3ddfff", + "name": "address", + "description": "OpenID Connect built-in scope: address", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${addressScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "3a4ceb4e-e597-49e4-8d0c-d41a46a2ab38", + "name": "address", + "protocol": "openid-connect", + "protocolMapper": "oidc-address-mapper", + "consentRequired": false, + "config": { + "user.attribute.formatted": "formatted", + "user.attribute.country": "country", + "introspection.token.claim": "true", + "user.attribute.postal_code": "postal_code", + "userinfo.token.claim": "true", + "user.attribute.street": "street", + "id.token.claim": "true", + "user.attribute.region": "region", + "access.token.claim": "true", + "user.attribute.locality": "locality" + } + } + ] + }, + { + "id": "df3a89a6-3ed7-45ad-97e1-598b93a643e7", + "name": "phone", + "description": "OpenID Connect built-in scope: phone", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${phoneScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "9bbff1aa-ee20-4c33-b40f-d0076a2fe305", + "name": "phone number", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "phoneNumber", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number", + "jsonType.label": "String" + } + }, + { + "id": "726d1ea0-ee59-49fe-bd01-416b06276ae9", + "name": "phone number verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "phoneNumberVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number_verified", + "jsonType.label": "boolean" + } + } + ] + } + ], + "defaultDefaultClientScopes": [ + "role_list", + "profile", + "email", + "roles", + "web-origins", + "acr" + ], + "defaultOptionalClientScopes": [ + "offline_access", + "address", + "phone", + "microprofile-jwt" + ], + "browserSecurityHeaders": { + "contentSecurityPolicyReportOnly": "", + "xContentTypeOptions": "nosniff", + "referrerPolicy": "no-referrer", + "xRobotsTag": "none", + "xFrameOptions": "SAMEORIGIN", + "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection": "1; mode=block", + "strictTransportSecurity": "max-age=31536000; includeSubDomains" + }, + "smtpServer": {}, + "eventsEnabled": false, + "eventsListeners": [ + "jboss-logging" + ], + "enabledEventTypes": [], + "adminEventsEnabled": false, + "adminEventsDetailsEnabled": false, + "identityProviders": [], + "identityProviderMappers": [], + "components": { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ + { + "id": "e037fff2-9457-47c7-81c7-762fbe02d23c", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "cbd25133-ce87-483c-b2e3-a3c2947b23e9", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "saml-user-attribute-mapper", + "oidc-usermodel-property-mapper", + "oidc-usermodel-attribute-mapper", + "oidc-address-mapper", + "oidc-sha256-pairwise-sub-mapper", + "saml-role-list-mapper", + "saml-user-property-mapper", + "oidc-full-name-mapper" + ] + } + }, + { + "id": "2fa7da7b-1138-44f9-8236-7e31f5f72695", + "name": "Consent Required", + "providerId": "consent-required", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "d2e6c9ff-9c36-40cc-bc12-0055d5ea61c3", + "name": "Trusted Hosts", + "providerId": "trusted-hosts", + "subType": "anonymous", + "subComponents": {}, + "config": { + "host-sending-registration-request-must-match": [ + "true" + ], + "client-uris-must-match": [ + "true" + ] + } + }, + { + "id": "269704c3-de60-4233-a845-6efd83408eb0", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "saml-role-list-mapper", + "oidc-usermodel-attribute-mapper", + "oidc-full-name-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-usermodel-property-mapper", + "saml-user-attribute-mapper", + "saml-user-property-mapper", + "oidc-address-mapper" + ] + } + }, + { + "id": "28cb7c8a-2fd1-4a3d-8ab8-17e4e83c2648", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "3a77be15-e696-49aa-9dac-64a79d8e443f", + "name": "Full Scope Disabled", + "providerId": "scope", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "f662e962-d5bd-4bbe-bc43-bddc7f4faf57", + "name": "Max Clients Limit", + "providerId": "max-clients", + "subType": "anonymous", + "subComponents": {}, + "config": { + "max-clients": [ + "200" + ] + } + } + ], + "org.keycloak.keys.KeyProvider": [ + { + "id": "5a307075-97e6-4c78-8e05-10e21c097d53", + "name": "aes-generated", + "providerId": "aes-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + }, + { + "id": "78a25e8e-b46c-44c2-8fd4-4b09529890e7", + "name": "rsa-generated", + "providerId": "rsa-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + }, + { + "id": "bf0f6364-43f0-4b1c-bde2-7646ceb56a63", + "name": "hmac-generated-hs512", + "providerId": "hmac-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ], + "algorithm": [ + "HS512" + ] + } + }, + { + "id": "28485c9c-96bc-49c7-a9a2-8941c9067f7d", + "name": "rsa-enc-generated", + "providerId": "rsa-enc-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ], + "algorithm": [ + "RSA-OAEP" + ] + } + } + ] + }, + "internationalizationEnabled": false, + "supportedLocales": [], + "authenticationFlows": [ + { + "id": "bbb2d80e-a134-4933-afe9-7cb655d70791", + "alias": "Account verification options", + "description": "Method with which to verity the existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-email-verification", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Verify Existing Account by Re-authentication", + "userSetupAllowed": false + } + ] + }, + { + "id": "651f23c0-4ef1-4762-b186-fc2b985ead9d", + "alias": "Browser - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-otp-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "e8dd531a-b8b7-4416-984f-9226cfcc8800", + "alias": "Direct Grant - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "direct-grant-validate-otp", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "e4fc59c9-1048-45b5-9069-57d578d0f125", + "alias": "First broker login - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-otp-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "12ea6433-d1b6-4094-b3e2-1ef356b91d92", + "alias": "Handle Existing Account", + "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-confirm-link", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Account verification options", + "userSetupAllowed": false + } + ] + }, + { + "id": "5d6c3ca7-3581-4200-b592-9c714129044f", + "alias": "Reset - Conditional OTP", + "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-otp", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "b7712f6e-fbe8-4f15-936d-939e28efd279", + "alias": "User creation or linking", + "description": "Flow for the existing/non-existing user alternatives", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "create unique user config", + "authenticator": "idp-create-user-if-unique", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Handle Existing Account", + "userSetupAllowed": false + } + ] + }, + { + "id": "61a450b5-3007-4e98-a7b2-dba743ea54a7", + "alias": "Verify Existing Account by Re-authentication", + "description": "Reauthentication of existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-username-password-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "First broker login - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "d7566b94-731b-4e84-a2de-a1c8130af38b", + "alias": "browser", + "description": "browser based authentication", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-cookie", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-spnego", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "identity-provider-redirector", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 25, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 30, + "autheticatorFlow": true, + "flowAlias": "forms", + "userSetupAllowed": false + } + ] + }, + { + "id": "399c5ce6-4308-4524-89bc-4dee1afd6cbb", + "alias": "clients", + "description": "Base authentication for clients", + "providerId": "client-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "client-secret", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-jwt", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-secret-jwt", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 30, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-x509", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 40, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "c8e80f39-d8d7-4fa5-8944-33fcdd366721", + "alias": "direct grant", + "description": "OpenID Connect Resource Owner Grant", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "direct-grant-validate-username", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "direct-grant-validate-password", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 30, + "autheticatorFlow": true, + "flowAlias": "Direct Grant - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "79251c55-7de3-457e-99e3-92395f2b69a7", + "alias": "docker auth", + "description": "Used by Docker clients to authenticate against the IDP", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "docker-http-basic-authenticator", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "60a12c1d-d4ce-40c1-a83f-faba71145f0c", + "alias": "first broker login", + "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "review profile config", + "authenticator": "idp-review-profile", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "User creation or linking", + "userSetupAllowed": false + } + ] + }, + { + "id": "e36da2db-a596-4680-a5ca-16c4e5a1a9c1", + "alias": "forms", + "description": "Username, password, otp and other auth forms.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-username-password-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Browser - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "2b1b59ff-5417-48cd-8d7a-2ab5ecfedc9f", + "alias": "registration", + "description": "registration flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": true, + "flowAlias": "registration form", + "userSetupAllowed": false + } + ] + }, + { + "id": "3e4f2042-a809-490c-a1a6-9bb63b4b0e4a", + "alias": "registration form", + "description": "registration form", + "providerId": "form-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-user-creation", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-password-action", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 50, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-recaptcha-action", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 60, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-terms-and-conditions", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 70, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "0b59d69a-95b0-4c82-bd21-908c019a4974", + "alias": "reset credentials", + "description": "Reset credentials for a user if they forgot their password or something", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "reset-credentials-choose-user", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-credential-email", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-password", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 30, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 40, + "autheticatorFlow": true, + "flowAlias": "Reset - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "accf37f2-1a52-40b0-a92f-f5a931c57126", + "alias": "saml ecp", + "description": "SAML ECP Profile Authentication Flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + } + ], + "authenticatorConfig": [ + { + "id": "4eaad8bb-f86b-483d-99a4-4cba184ef573", + "alias": "create unique user config", + "config": { + "require.password.update.after.registration": "false" + } + }, + { + "id": "eb0a326f-17e0-49b7-b25c-575b0cd3888f", + "alias": "review profile config", + "config": { + "update.profile.on.first.login": "missing" + } + } + ], + "requiredActions": [ + { + "alias": "CONFIGURE_TOTP", + "name": "Configure OTP", + "providerId": "CONFIGURE_TOTP", + "enabled": true, + "defaultAction": false, + "priority": 10, + "config": {} + }, + { + "alias": "TERMS_AND_CONDITIONS", + "name": "Terms and Conditions", + "providerId": "TERMS_AND_CONDITIONS", + "enabled": false, + "defaultAction": false, + "priority": 20, + "config": {} + }, + { + "alias": "UPDATE_PASSWORD", + "name": "Update Password", + "providerId": "UPDATE_PASSWORD", + "enabled": true, + "defaultAction": false, + "priority": 30, + "config": {} + }, + { + "alias": "UPDATE_PROFILE", + "name": "Update Profile", + "providerId": "UPDATE_PROFILE", + "enabled": true, + "defaultAction": false, + "priority": 40, + "config": {} + }, + { + "alias": "VERIFY_EMAIL", + "name": "Verify Email", + "providerId": "VERIFY_EMAIL", + "enabled": true, + "defaultAction": false, + "priority": 50, + "config": {} + }, + { + "alias": "delete_account", + "name": "Delete Account", + "providerId": "delete_account", + "enabled": false, + "defaultAction": false, + "priority": 60, + "config": {} + }, + { + "alias": "webauthn-register", + "name": "Webauthn Register", + "providerId": "webauthn-register", + "enabled": true, + "defaultAction": false, + "priority": 70, + "config": {} + }, + { + "alias": "webauthn-register-passwordless", + "name": "Webauthn Register Passwordless", + "providerId": "webauthn-register-passwordless", + "enabled": true, + "defaultAction": false, + "priority": 80, + "config": {} + }, + { + "alias": "VERIFY_PROFILE", + "name": "Verify Profile", + "providerId": "VERIFY_PROFILE", + "enabled": true, + "defaultAction": false, + "priority": 90, + "config": {} + }, + { + "alias": "delete_credential", + "name": "Delete Credential", + "providerId": "delete_credential", + "enabled": true, + "defaultAction": false, + "priority": 100, + "config": {} + }, + { + "alias": "update_user_locale", + "name": "Update User Locale", + "providerId": "update_user_locale", + "enabled": true, + "defaultAction": false, + "priority": 1000, + "config": {} + } + ], + "browserFlow": "browser", + "registrationFlow": "registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "firstBrokerLoginFlow": "first broker login", + "attributes": { + "cibaBackchannelTokenDeliveryMode": "poll", + "cibaExpiresIn": "120", + "cibaAuthRequestedUserHint": "login_hint", + "oauth2DeviceCodeLifespan": "600", + "oauth2DevicePollingInterval": "5", + "parRequestUriLifespan": "60", + "cibaInterval": "5", + "realmReusableOtpCode": "false" + }, + "keycloakVersion": "24.0.5", + "userManagedAccessAllowed": false, + "clientProfiles": { + "profiles": [] + }, + "clientPolicies": { + "policies": [] + }, + "users": [ + { + "username": "viewer", + "enabled": true, + "emailVerified": true, + "firstName": "viewer", + "lastName": "viewer", + "email": "viewer@mail.com", + "credentials": [ + { + "type": "password", + "value": "viewer" + } + ] + }, + { + "username": "pacsadmin", + "enabled": true, + "emailVerified": true, + "firstName": "pacsadmin", + "lastName": "pacsadmin", + "email": "pacsadmin@mail.com", + "credentials": [ + { + "type": "password", + "value": "pacsadmin" + } + ], + "groups": ["pacsadmin"] + } + ] +} diff --git a/platform/app/.recipes/OpenResty-Orthanc-Keycloak/config/orthanc.json b/platform/app/.recipes/Nginx-Orthanc-Keycloak/config/orthanc.json similarity index 100% rename from platform/app/.recipes/OpenResty-Orthanc-Keycloak/config/orthanc.json rename to platform/app/.recipes/Nginx-Orthanc-Keycloak/config/orthanc.json diff --git a/platform/app/.recipes/Nginx-Orthanc-Keycloak/docker-compose.yml b/platform/app/.recipes/Nginx-Orthanc-Keycloak/docker-compose.yml new file mode 100644 index 0000000000..1a44c3013c --- /dev/null +++ b/platform/app/.recipes/Nginx-Orthanc-Keycloak/docker-compose.yml @@ -0,0 +1,126 @@ +services: + ohif_viewer: + build: + context: ./../../../../ + dockerfile: ./platform/app/.recipes/Nginx-Orthanc-Keycloak/dockerfile + image: webapp:latest + container_name: webapp + ports: + - '443:443' # SSL + - '80:80' # Web + depends_on: + keycloak: + condition: service_healthy + restart: on-failure + networks: + - default + extra_hosts: + - 'host.docker.internal:host-gateway' + environment: + - OAUTH2_PROXY_SKIP_PROVIDER_BUTTON=true + volumes: + # - ../../app/dist /var/www/html + - ./config/nginx.conf:/etc/nginx/nginx.conf + - ./config/oauth2-proxy.cfg:/etc/oauth2-proxy/oauth2-proxy.cfg + + - ./config/letsencrypt:/etc/letsencrypt + - ./config/certbot:/var/www/certbot + + orthanc: + image: jodogne/orthanc-plugins + hostname: orthanc + container_name: orthanc + volumes: + - ./config/orthanc.json:/etc/orthanc/orthanc.json:ro + - ./volumes/orthanc-db/:/var/lib/orthanc/db/ + restart: unless-stopped + networks: + - default + + keycloak: + image: quay.io/keycloak/keycloak:24.0.5 + command: 'start-dev --import-realm' + hostname: keycloak + container_name: keycloak + volumes: + - ./config/ohif-keycloak-realm.json:/opt/keycloak/data/import/ohif-keycloak-realm.json + environment: + # Database + KC_DB_URL_HOST: postgres + KC_DB: postgres + KC_DB_URL: 'jdbc:postgresql://postgres:5432/keycloak' + KC_DB_SCHEMA: public + KC_DB_USERNAME: keycloak + KC_DB_PASSWORD: password + KC_HOSTNAME_ADMIN_URL: http://YOUR_DOMAIN/keycloak/ + KC_HOSTNAME_URL: http://YOUR_DOMAIN/keycloak/ + KC_HOSTNAME_STRICT_BACKCHANNEL: true + KC_HOSTNAME_STRICT_HTTPS: false + KC_HTTP_ENABLED: true + KEYCLOAK_ADMIN: admin + KEYCLOAK_ADMIN_PASSWORD: admin + KC_HEALTH_ENABLED: true + KC_METRICS_ENABLED: true + KC_PROXY: edge + KC_PROXY_HEADERS: xforwarded + KEYCLOAK_JDBC_PARAMS: connectTimeout=40000 + KC_LOG_LEVEL: INFO + KC_HOSTNAME_DEBUG: true + # added later + PROXY_ADDRESS_FORWARDING: true + ports: + - 8080:8080 + depends_on: + - postgres + restart: unless-stopped + networks: + - default + extra_hosts: + - 'host.docker.internal:host-gateway' + healthcheck: + test: [ + 'CMD-SHELL', + "exec 3<>/dev/tcp/YOUR_DOMAIN/8080;echo -e \"GET /health/ready HTTP/1.1\r + + host: http://localhost\r + + Connection: close\r + + \r + + \" >&3;grep \"HTTP/1.1 200 OK\" <&3", + ] + interval: 1s + timeout: 5s + retries: 10 + start_period: 60s + + postgres: + image: postgres:15 + hostname: postgres + container_name: postgres + volumes: + - postgres_data:/var/lib/postgresql/data + environment: + POSTGRES_DB: keycloak + POSTGRES_USER: keycloak + POSTGRES_PASSWORD: password + restart: unless-stopped + networks: + - default + + certbot: + image: certbot/certbot + container_name: certbot + volumes: + - ./config/letsencrypt:/etc/letsencrypt + - ./config/certbot:/var/www/certbot + entrypoint: + /bin/sh -c "trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;" +volumes: + postgres_data: + driver: local + +networks: + default: + driver: bridge diff --git a/platform/app/.recipes/Nginx-Orthanc-Keycloak/dockerfile b/platform/app/.recipes/Nginx-Orthanc-Keycloak/dockerfile new file mode 100644 index 0000000000..eba4237b44 --- /dev/null +++ b/platform/app/.recipes/Nginx-Orthanc-Keycloak/dockerfile @@ -0,0 +1,57 @@ +# Stage 1: Build the application +FROM node:18.16.1-slim as builder + +# Setup the working directory +RUN mkdir /usr/src/app +WORKDIR /usr/src/app + +# Install dependencies +# apt-get update is combined with apt-get install to avoid using outdated packages +RUN apt-get update && apt-get install -y build-essential python3 + +# Copy package.json and other dependency-related files first +# Assuming your package.json and yarn.lock or similar are located in the project root +# Todo: this probably can get improved by copying +# only the package json files and running yarn install before +# copying the rest of the files but having a monorepo setup +# makes this a bit more complicated, i wasn't able to get it working +COPY ./ /usr/src/app/ + +# Install node dependencies +RUN yarn config set workspaces-experimental true +RUN yarn install + +# Copy the rest of the application code + +# set QUICK_BUILD to true to make the build faster for dev +ENV APP_CONFIG=config/docker-nginx-orthanc-keycloak.js + +# Build the application +RUN yarn run build + +# Use nginx as the base image +FROM nginx:alpine + +# Install dependencies for oauth2-proxy +RUN apk add --no-cache curl + +# Create necessary directories +RUN mkdir -p /var/logs/nginx /var/www/html /etc/oauth2-proxy + +# Download and install oauth2-proxy +RUN curl -L https://github.com/oauth2-proxy/oauth2-proxy/releases/download/v7.4.0/oauth2-proxy-v7.4.0.linux-amd64.tar.gz -o oauth2-proxy.tar.gz && \ + tar -xvzf oauth2-proxy.tar.gz && \ + mv oauth2-proxy-v7.4.0.linux-amd64/oauth2-proxy /usr/local/bin/ && \ + rm -rf oauth2-proxy-v7.4.0.linux-amd64 oauth2-proxy.tar.gz + + +COPY --from=builder /usr/src/app/platform/app/dist /var/www/html + +# Copy the entrypoint script +COPY ./platform/app/.recipes/Nginx-Orthanc-Keycloak/config/entrypoint.sh /entrypoint.sh + +# Expose necessary ports +EXPOSE 80 443 4180 +# Set the entrypoint script as the entrypoint +RUN chmod +x entrypoint.sh +ENTRYPOINT ["/entrypoint.sh"] diff --git a/platform/app/.recipes/Nginx-Orthanc/.gitignore b/platform/app/.recipes/Nginx-Orthanc/.gitignore new file mode 100644 index 0000000000..12e4308df9 --- /dev/null +++ b/platform/app/.recipes/Nginx-Orthanc/.gitignore @@ -0,0 +1,2 @@ +logs/* +volumes/* diff --git a/platform/app/.recipes/Nginx-Orthanc/README.md b/platform/app/.recipes/Nginx-Orthanc/README.md new file mode 100644 index 0000000000..14e1a70b8e --- /dev/null +++ b/platform/app/.recipes/Nginx-Orthanc/README.md @@ -0,0 +1,26 @@ +# Docker compose files + +# Build + +Using docker compose you can build the image with the following command: + +```bash +docker-compose build +``` + +# Run + +To run the container use the following command: + +```bash +docker-compose up +``` + + +# Routes + +http://localhost/ -> OHIF +localhost/pacs -> Orthanc + + +See [here](../../../docs/docs/deployment/nginx--image-archive.md) for more information about this recipe. diff --git a/platform/app/.recipes/Nginx-Orthanc/config/nginx.conf b/platform/app/.recipes/Nginx-Orthanc/config/nginx.conf new file mode 100644 index 0000000000..57946cddfc --- /dev/null +++ b/platform/app/.recipes/Nginx-Orthanc/config/nginx.conf @@ -0,0 +1,86 @@ +worker_processes 2; +error_log /var/logs/nginx/mydomain.error.log; +pid /var/run/nginx.pid; +include /usr/share/nginx/modules/*.conf; # See /usr/share/doc/nginx/README.dynamic. + +events { + worker_connections 1024; ## Default: 1024 + use epoll; # http://nginx.org/en/docs/events.html + multi_accept on; # http://nginx.org/en/docs/ngx_core_module.html#multi_accept +} + +# Core Modules Docs: +# http://nginx.org/en/docs/http/ngx_http_core_module.html +http { + include '/etc/nginx/mime.types'; + default_type application/octet-stream; + + keepalive_timeout 65; + keepalive_requests 100000; + tcp_nopush on; + tcp_nodelay on; + + + + # Nginx `listener` block + server { + listen [::]:80 default_server; + listen 80; + + gzip on; + gzip_types text/css application/javascript application/json image/svg+xml; + gzip_comp_level 9; + etag on; + + + # Reverse Proxy for `orthanc` APIs (including DICOMWeb) + # + location /pacs/ { + + proxy_http_version 1.1; + + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + expires 0; + add_header Cache-Control private; + + # Add CORS headers + # Note: uncomment the following line to allow all domains to access the Orthanc APIs + # You should actually only allow the domains you trust to access the APIs + # add_header 'Access-Control-Allow-Origin' '*' always; + + proxy_pass http://orthanc:8042/; + + # By default, this endpoint is protected by CORS (cross-origin-resource-sharing) + # You can add headers to allow other domains to request this resource. + # See the "Updating CORS Settings" example below + } + + + # Do not cache sw.js, required for offline-first updates. + location /sw.js { + add_header Cache-Control "no-cache"; + proxy_cache_bypass $http_pragma; + proxy_cache_revalidate on; + expires off; + access_log off; + } + + + # Single Page App + # Try files, fallback to index.html + # + location / { + root /var/www/html; + index index.html; + try_files $uri $uri/ /index.html; + add_header Cache-Control "no-store, no-cache, must-revalidate"; + add_header 'Cross-Origin-Opener-Policy' 'same-origin' always; + add_header 'Cross-Origin-Embedder-Policy' 'require-corp' always; + } + + } +} diff --git a/platform/app/.recipes/OpenResty-Orthanc/config/orthanc.json b/platform/app/.recipes/Nginx-Orthanc/config/orthanc.json similarity index 100% rename from platform/app/.recipes/OpenResty-Orthanc/config/orthanc.json rename to platform/app/.recipes/Nginx-Orthanc/config/orthanc.json diff --git a/platform/app/.recipes/Nginx-Orthanc/docker-compose.yml b/platform/app/.recipes/Nginx-Orthanc/docker-compose.yml new file mode 100644 index 0000000000..c80c160259 --- /dev/null +++ b/platform/app/.recipes/Nginx-Orthanc/docker-compose.yml @@ -0,0 +1,46 @@ +# Reference: +# - https://docs.docker.com/compose/compose-file +# - https://eclipsesource.com/blogs/2018/01/11/authenticating-reverse-proxy-with-keycloak/ + +services: + # Exposed server that's handling incoming web requests + ohif_viewer: + build: + # Project root + context: ./../../../../ + # Relative to context + dockerfile: ./platform/app/.recipes/Nginx-Orthanc/dockerfile + image: webapp:latest + container_name: ohif_orthanc + volumes: + # Nginx config + - ./config/nginx.conf:/etc/nginx/nginx.conf + # Logs + - ./logs/nginx:/var/logs/nginx + # Let's Encrypt + # - letsencrypt_certificates:/etc/letsencrypt + # - letsencrypt_challenges:/var/www/letsencrypt + ports: + - '443:443' # SSL + - '80:80' # Web + depends_on: + # - keycloak + - orthanc + restart: on-failure + + # LINK: https://hub.docker.com/r/jodogne/orthanc-plugins/ + # TODO: Update to use Postgres + # https://github.com/mrts/docker-postgresql-multiple-databases + orthanc: + image: jodogne/orthanc-plugins + hostname: orthanc + container_name: orthancPACS + volumes: + # Config + - ./config/orthanc.json:/etc/orthanc/orthanc.json:ro + # Persist data + - ./volumes/orthanc-db/:/var/lib/orthanc/db/ + restart: unless-stopped + ports: + - '4242:4242' # Orthanc REST API + - '8042:8042' # Orthanc HTTP diff --git a/platform/app/.recipes/Nginx-Orthanc/dockerfile b/platform/app/.recipes/Nginx-Orthanc/dockerfile new file mode 100644 index 0000000000..ac7433ac6c --- /dev/null +++ b/platform/app/.recipes/Nginx-Orthanc/dockerfile @@ -0,0 +1,43 @@ +# Stage 1: Build the application +FROM node:18.16.1-slim as builder + +# Setup the working directory +RUN mkdir /usr/src/app +WORKDIR /usr/src/app + +# Install dependencies +# apt-get update is combined with apt-get install to avoid using outdated packages +RUN apt-get update && apt-get install -y build-essential python3 + +# Copy package.json and other dependency-related files first +# Assuming your package.json and yarn.lock or similar are located in the project root + +COPY ./ /usr/src/app/ + +# Install node dependencies +RUN yarn config set workspaces-experimental true +RUN yarn install + +# Copy the rest of the application code + +# set QUICK_BUILD to true to make the build faster for dev +ENV APP_CONFIG=config/docker-nginx-orthanc.js + +# Build the application +RUN yarn run build + +# # Stage 2: Bundle the built application into a Docker container which runs NGINX using Alpine Linux +FROM nginx:alpine + +# # Create directories for logs and html content if they don't already exist +RUN mkdir -p /var/log/nginx /var/www/html + + +# # Copy build output to serve static files +COPY --from=builder /usr/src/app/platform/app/dist /var/www/html + +# # Expose HTTP and HTTPS ports +EXPOSE 80 443 + +# # Start NGINX +CMD ["nginx", "-g", "daemon off;"] diff --git a/platform/app/.recipes/OpenResty-Orthanc-Keycloak/.env b/platform/app/.recipes/OpenResty-Orthanc-Keycloak/.env deleted file mode 100644 index 6989ff3fc7..0000000000 --- a/platform/app/.recipes/OpenResty-Orthanc-Keycloak/.env +++ /dev/null @@ -1,5 +0,0 @@ -# Docker ENV and ARG Variables -# ---------------------------- -# https://vsupalov.com/docker-arg-env-variable-guide/ -# -# diff --git a/platform/app/.recipes/OpenResty-Orthanc/.env b/platform/app/.recipes/OpenResty-Orthanc/.env deleted file mode 100644 index 6989ff3fc7..0000000000 --- a/platform/app/.recipes/OpenResty-Orthanc/.env +++ /dev/null @@ -1,5 +0,0 @@ -# Docker ENV and ARG Variables -# ---------------------------- -# https://vsupalov.com/docker-arg-env-variable-guide/ -# -# diff --git a/platform/app/.recipes/README.md b/platform/app/.recipes/README.md deleted file mode 100644 index 1f3f6f2000..0000000000 --- a/platform/app/.recipes/README.md +++ /dev/null @@ -1,53 +0,0 @@ -# Docker compose files - -This folder contains docker-compose files used to spin up OHIF-Viewer with -different options such as locally or with any PAS you desire to - -## Public Server - -#### build - -`$ docker-compose -f docker-compose-publicserver.yml build` - -#### run - -`$ docker-compose -f docker-compose-publicserver.yml up -d` - -then, access the application at [http://localhost](http://localhost) - -## Local Orthanc - -### Build - -`$ docker-compose -f docker-compose-orthanc.yml build` - -### Run - -Starts containers and leaves them running in the background. - -`$ docker-compose -f docker-compose-orthanc.yml up -d` - -then, access the application at [http://localhost](http://localhost) - -**remember that you have to access orthanc application and include your studies -there** - -## Local Dcm4chee - -#### build - -`$ docker-compose -f docker-compose-dcm4chee.yml build` - -#### run - -`$ docker-compose -f docker-compose-dcm4chee.yml up -d` - -then, access the application at [http://localhost](http://localhost) - -**remember that you have to access dcm4chee application and include your studies -there** You can use the following command to import your studies into dcm4che - -`$ docker run -v {YOUR_STUDY_FOLDER}:/tmp --rm --network=docker_dcm4che_default dcm4che/dcm4che-tools:5.14.0 storescu -cDCM4CHEE@arc:11112 /tmp` - -**make sure that your Docker network name is docker_dcm4chee_default or change -it to the right one** diff --git a/platform/app/.recipes/OpenResty-Orthanc-Keycloak/config/nginx.conf b/platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc-Keycloak/config/nginx.conf similarity index 100% rename from platform/app/.recipes/OpenResty-Orthanc-Keycloak/config/nginx.conf rename to platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc-Keycloak/config/nginx.conf diff --git a/platform/app/.recipes/OpenResty-Orthanc-Keycloak/config/ohif-keycloak-realm.json b/platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc-Keycloak/config/ohif-keycloak-realm.json similarity index 100% rename from platform/app/.recipes/OpenResty-Orthanc-Keycloak/config/ohif-keycloak-realm.json rename to platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc-Keycloak/config/ohif-keycloak-realm.json diff --git a/platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc-Keycloak/config/orthanc.json b/platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc-Keycloak/config/orthanc.json new file mode 100644 index 0000000000..2e10723c04 --- /dev/null +++ b/platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc-Keycloak/config/orthanc.json @@ -0,0 +1,89 @@ +{ + "Name": "Orthanc inside Docker", + "StorageDirectory": "/var/lib/orthanc/db", + "IndexDirectory": "/var/lib/orthanc/db", + "StorageCompression": false, + "MaximumStorageSize": 0, + "MaximumPatientCount": 0, + "LuaScripts": [], + "Plugins": ["/usr/share/orthanc/plugins", "/usr/local/share/orthanc/plugins"], + "ConcurrentJobs": 2, + "HttpServerEnabled": true, + "HttpPort": 8042, + "HttpDescribeErrors": true, + "HttpCompressionEnabled": true, + "DicomServerEnabled": true, + "DicomAet": "ORTHANC", + "DicomCheckCalledAet": false, + "DicomPort": 4242, + "DefaultEncoding": "Latin1", + "DeflatedTransferSyntaxAccepted": true, + "JpegTransferSyntaxAccepted": true, + "Jpeg2000TransferSyntaxAccepted": true, + "JpegLosslessTransferSyntaxAccepted": true, + "JpipTransferSyntaxAccepted": true, + "Mpeg2TransferSyntaxAccepted": true, + "RleTransferSyntaxAccepted": true, + "UnknownSopClassAccepted": false, + "DicomScpTimeout": 30, + + "RemoteAccessAllowed": true, + "SslEnabled": false, + "SslCertificate": "certificate.pem", + "AuthenticationEnabled": false, + "RegisteredUsers": { + "test": "test" + }, + "DicomModalities": {}, + "DicomModalitiesInDatabase": false, + "DicomAlwaysAllowEcho": true, + "DicomAlwaysAllowStore": true, + "DicomCheckModalityHost": false, + "DicomScuTimeout": 10, + "OrthancPeers": {}, + "OrthancPeersInDatabase": false, + "HttpProxy": "", + + "HttpVerbose": true, + + "HttpTimeout": 10, + "HttpsVerifyPeers": true, + "HttpsCACertificates": "", + "UserMetadata": {}, + "UserContentType": {}, + "StableAge": 60, + "StrictAetComparison": false, + "StoreMD5ForAttachments": true, + "LimitFindResults": 0, + "LimitFindInstances": 0, + "LimitJobs": 10, + "LogExportedResources": false, + "KeepAlive": true, + "TcpNoDelay": true, + "HttpThreadsCount": 50, + "StoreDicom": true, + "DicomAssociationCloseDelay": 5, + "QueryRetrieveSize": 10, + "CaseSensitivePN": false, + "LoadPrivateDictionary": true, + "Dictionary": {}, + "SynchronousCMove": true, + "JobsHistorySize": 10, + "SaveJobs": true, + "OverwriteInstances": false, + "MediaArchiveSize": 1, + "StorageAccessOnFind": "Always", + "MetricsEnabled": true, + + "DicomWeb": { + "Enable": true, + "Root": "/dicom-web/", + "EnableWado": true, + "WadoRoot": "/wado", + "Host": "127.0.0.1", + "Ssl": false, + "StowMaxInstances": 10, + "StowMaxSize": 10, + "QidoCaseSensitive": false + } +} diff --git a/platform/app/.recipes/OpenResty-Orthanc-Keycloak/docker-compose.yml b/platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc-Keycloak/docker-compose.yml similarity index 100% rename from platform/app/.recipes/OpenResty-Orthanc-Keycloak/docker-compose.yml rename to platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc-Keycloak/docker-compose.yml diff --git a/platform/app/.recipes/OpenResty-Orthanc-Keycloak/dockerfile b/platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc-Keycloak/dockerfile similarity index 100% rename from platform/app/.recipes/OpenResty-Orthanc-Keycloak/dockerfile rename to platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc-Keycloak/dockerfile diff --git a/platform/app/.recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/ohif/welcome/.githold b/platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/ohif/account/.githold similarity index 100% rename from platform/app/.recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/ohif/welcome/.githold rename to platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/ohif/account/.githold diff --git a/platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/ohif/admin/.githold b/platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/ohif/admin/.githold new file mode 100644 index 0000000000..e69de29bb2 diff --git a/platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/ohif/email/.githold b/platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/ohif/email/.githold new file mode 100644 index 0000000000..e69de29bb2 diff --git a/platform/app/.recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/ohif/login/resources/css/styles.css b/platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/ohif/login/resources/css/styles.css similarity index 100% rename from platform/app/.recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/ohif/login/resources/css/styles.css rename to platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/ohif/login/resources/css/styles.css diff --git a/platform/app/.recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/ohif/login/resources/img/background.jpg b/platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/ohif/login/resources/img/background.jpg similarity index 100% rename from platform/app/.recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/ohif/login/resources/img/background.jpg rename to platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/ohif/login/resources/img/background.jpg diff --git a/platform/app/.recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/ohif/login/theme.properties b/platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/ohif/login/theme.properties similarity index 100% rename from platform/app/.recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/ohif/login/theme.properties rename to platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/ohif/login/theme.properties diff --git a/platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/ohif/welcome/.githold b/platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/ohif/welcome/.githold new file mode 100644 index 0000000000..e69de29bb2 diff --git a/platform/app/.recipes/OpenResty-Orthanc-Keycloak/volumes/orthanc-db/.gitignore b/platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc-Keycloak/volumes/orthanc-db/.gitignore similarity index 100% rename from platform/app/.recipes/OpenResty-Orthanc-Keycloak/volumes/orthanc-db/.gitignore rename to platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc-Keycloak/volumes/orthanc-db/.gitignore diff --git a/platform/app/.recipes/OpenResty-Orthanc/config/nginx.conf b/platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc/config/nginx.conf similarity index 100% rename from platform/app/.recipes/OpenResty-Orthanc/config/nginx.conf rename to platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc/config/nginx.conf diff --git a/platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc/config/orthanc.json b/platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc/config/orthanc.json new file mode 100644 index 0000000000..2e10723c04 --- /dev/null +++ b/platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc/config/orthanc.json @@ -0,0 +1,89 @@ +{ + "Name": "Orthanc inside Docker", + "StorageDirectory": "/var/lib/orthanc/db", + "IndexDirectory": "/var/lib/orthanc/db", + "StorageCompression": false, + "MaximumStorageSize": 0, + "MaximumPatientCount": 0, + "LuaScripts": [], + "Plugins": ["/usr/share/orthanc/plugins", "/usr/local/share/orthanc/plugins"], + "ConcurrentJobs": 2, + "HttpServerEnabled": true, + "HttpPort": 8042, + "HttpDescribeErrors": true, + "HttpCompressionEnabled": true, + "DicomServerEnabled": true, + "DicomAet": "ORTHANC", + "DicomCheckCalledAet": false, + "DicomPort": 4242, + "DefaultEncoding": "Latin1", + "DeflatedTransferSyntaxAccepted": true, + "JpegTransferSyntaxAccepted": true, + "Jpeg2000TransferSyntaxAccepted": true, + "JpegLosslessTransferSyntaxAccepted": true, + "JpipTransferSyntaxAccepted": true, + "Mpeg2TransferSyntaxAccepted": true, + "RleTransferSyntaxAccepted": true, + "UnknownSopClassAccepted": false, + "DicomScpTimeout": 30, + + "RemoteAccessAllowed": true, + "SslEnabled": false, + "SslCertificate": "certificate.pem", + "AuthenticationEnabled": false, + "RegisteredUsers": { + "test": "test" + }, + "DicomModalities": {}, + "DicomModalitiesInDatabase": false, + "DicomAlwaysAllowEcho": true, + "DicomAlwaysAllowStore": true, + "DicomCheckModalityHost": false, + "DicomScuTimeout": 10, + "OrthancPeers": {}, + "OrthancPeersInDatabase": false, + "HttpProxy": "", + + "HttpVerbose": true, + + "HttpTimeout": 10, + "HttpsVerifyPeers": true, + "HttpsCACertificates": "", + "UserMetadata": {}, + "UserContentType": {}, + "StableAge": 60, + "StrictAetComparison": false, + "StoreMD5ForAttachments": true, + "LimitFindResults": 0, + "LimitFindInstances": 0, + "LimitJobs": 10, + "LogExportedResources": false, + "KeepAlive": true, + "TcpNoDelay": true, + "HttpThreadsCount": 50, + "StoreDicom": true, + "DicomAssociationCloseDelay": 5, + "QueryRetrieveSize": 10, + "CaseSensitivePN": false, + "LoadPrivateDictionary": true, + "Dictionary": {}, + "SynchronousCMove": true, + "JobsHistorySize": 10, + "SaveJobs": true, + "OverwriteInstances": false, + "MediaArchiveSize": 1, + "StorageAccessOnFind": "Always", + "MetricsEnabled": true, + + "DicomWeb": { + "Enable": true, + "Root": "/dicom-web/", + "EnableWado": true, + "WadoRoot": "/wado", + "Host": "127.0.0.1", + "Ssl": false, + "StowMaxInstances": 10, + "StowMaxSize": 10, + "QidoCaseSensitive": false + } +} diff --git a/platform/app/.recipes/OpenResty-Orthanc/docker-compose.yml b/platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc/docker-compose.yml similarity index 100% rename from platform/app/.recipes/OpenResty-Orthanc/docker-compose.yml rename to platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc/docker-compose.yml diff --git a/platform/app/.recipes/OpenResty-Orthanc/dockerfile b/platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc/dockerfile similarity index 100% rename from platform/app/.recipes/OpenResty-Orthanc/dockerfile rename to platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc/dockerfile diff --git a/platform/app/.recipes/OpenResty-Orthanc/volumes/orthanc-db/.gitignore b/platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc/volumes/orthanc-db/.gitignore similarity index 100% rename from platform/app/.recipes/OpenResty-Orthanc/volumes/orthanc-db/.gitignore rename to platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc/volumes/orthanc-db/.gitignore diff --git a/platform/app/.webpack/webpack.pwa.js b/platform/app/.webpack/webpack.pwa.js index c07fdfb366..69cc1e2606 100644 --- a/platform/app/.webpack/webpack.pwa.js +++ b/platform/app/.webpack/webpack.pwa.js @@ -20,6 +20,7 @@ const PUBLIC_URL = process.env.PUBLIC_URL || '/'; const APP_CONFIG = process.env.APP_CONFIG || 'config/default.js'; const PROXY_TARGET = process.env.PROXY_TARGET; const PROXY_DOMAIN = process.env.PROXY_DOMAIN; +const OHIF_PORT = Number(process.env.OHIF_PORT || 3000); const ENTRY_TARGET = process.env.ENTRY_TARGET || `${SRC_DIR}/index.js`; const Dotenv = require('dotenv-webpack'); const writePluginImportFile = require('./writePluginImportsFile.js'); @@ -101,13 +102,17 @@ module.exports = (env, argv) => { to: `${DIST_DIR}/app-config.js`, }, // Copy Dicom Microscopy Viewer build files - { - from: '../../../node_modules/dicom-microscopy-viewer/dist/dynamic-import', - to: DIST_DIR, - globOptions: { - ignore: ['**/*.min.js.map'], - }, - }, + // This is in pluginCOnfig.json now + // { + // from: '../../../node_modules/dicom-microscopy-viewer/dist/dynamic-import', + // to: DIST_DIR, + // globOptions: { + // ignore: ['**/*.min.js.map'], + // }, + // // The dicom-microscopy-viewer is optional, so if it doeesn't get + // // installed, it shouldn't cause issues. + // noErrorOnMissing: true, + // }, // Copy dicom-image-loader build files { from: '../../../node_modules/@cornerstonejs/dicom-image-loader/dist/dynamic-import', @@ -143,7 +148,7 @@ module.exports = (env, argv) => { // http2: true, // https: true, open: true, - port: 3000, + port: OHIF_PORT, client: { overlay: { errors: true, warnings: false }, }, diff --git a/platform/app/.webpack/writePluginImportsFile.js b/platform/app/.webpack/writePluginImportsFile.js index 47456d034f..c913e779ee 100644 --- a/platform/app/.webpack/writePluginImportsFile.js +++ b/platform/app/.webpack/writePluginImportsFile.js @@ -66,6 +66,18 @@ function getRuntimeLoadModesExtensions(modules) { ); modules.forEach(module => { const packageName = extractName(module); + if (!packageName) { + return; + } + if (module.importPath) { + dynamicLoad.push( + ` if( module==="${packageName}") {`, + ` const imported = await window.browserImportFunction('${module.importPath}');`, + ' return ' + (module.globalName ? `window["${module.globalName}"];` : `imported["${module.importName || 'default'}"];`), + ' }' + ); + return; + } dynamicLoad.push( ` if( module==="${packageName}") {`, ` const imported = await import("${packageName}");`, @@ -73,8 +85,9 @@ function getRuntimeLoadModesExtensions(modules) { ' }' ); }); + // TODO - handle more cases for import than just default dynamicLoad.push( - ' return (await import(/* webpackIgnore: true */ module)).default;', + ' return (await window.browserImportFunction(module)).default;', '}\n', '// Import a list of items (modules or string names)', '// @return a Promise evaluating to a list of modules', @@ -144,6 +157,7 @@ function writePluginImportsFile(SRC_DIR, DIST_DIR) { pluginImportsJsContent += getRuntimeLoadModesExtensions([ ...pluginConfig.extensions, ...pluginConfig.modes, + ...pluginConfig.public, ]); fs.writeFileSync(`${SRC_DIR}/pluginImports.js`, pluginImportsJsContent, { flag: 'w+' }, err => { diff --git a/platform/app/CHANGELOG.md b/platform/app/CHANGELOG.md index 144ebe68bf..1ad3eb0e53 100644 --- a/platform/app/CHANGELOG.md +++ b/platform/app/CHANGELOG.md @@ -3,6 +3,779 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.9.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.70...v3.9.0-beta.71) (2024-07-30) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.69...v3.9.0-beta.70) (2024-07-30) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.68...v3.9.0-beta.69) (2024-07-27) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.67...v3.9.0-beta.68) (2024-07-26) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.66...v3.9.0-beta.67) (2024-07-26) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.65...v3.9.0-beta.66) (2024-07-24) + + +### Features + +* **pmap:** added support for parametric map ([#4284](https://github.com/OHIF/Viewers/issues/4284)) ([fc0064f](https://github.com/OHIF/Viewers/commit/fc0064fd9d8cdc8fde81b81f0e71fd5d077ca22b)) + + + + + +# [3.9.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.64...v3.9.0-beta.65) (2024-07-23) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.63...v3.9.0-beta.64) (2024-07-19) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.62...v3.9.0-beta.63) (2024-07-10) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.61...v3.9.0-beta.62) (2024-07-09) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.60...v3.9.0-beta.61) (2024-07-09) + + +### Features + +* **auth:** Add Authorization Code Flow and new Keycloak recipes with new video tutorials ([#4234](https://github.com/OHIF/Viewers/issues/4234)) ([aefa6d9](https://github.com/OHIF/Viewers/commit/aefa6d94dff82d34fa8358933fb1d5dec3f8246d)) + + + + + +# [3.9.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.59...v3.9.0-beta.60) (2024-07-09) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.58...v3.9.0-beta.59) (2024-07-05) + + +### Bug Fixes + +* Cobb angle not working in basic-test mode and open contour ([#4280](https://github.com/OHIF/Viewers/issues/4280)) ([6fd3c7e](https://github.com/OHIF/Viewers/commit/6fd3c7e293fec851dd30e650c1347cc0bc7a99ee)) +* **image-orientation:** Prevent incorrect orientation marker display for single-slice US images ([#4275](https://github.com/OHIF/Viewers/issues/4275)) ([6d11048](https://github.com/OHIF/Viewers/commit/6d11048ca5ea66284948602613a63277083ec6a5)) +* webpack import bugs showing warnings on import ([#4265](https://github.com/OHIF/Viewers/issues/4265)) ([24c511f](https://github.com/OHIF/Viewers/commit/24c511f4bc04c4143bbd3d0d48029f41f7f36014)) + + + + + +# [3.9.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.57...v3.9.0-beta.58) (2024-07-04) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.56...v3.9.0-beta.57) (2024-07-02) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.55...v3.9.0-beta.56) (2024-07-02) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.54...v3.9.0-beta.55) (2024-06-28) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.53...v3.9.0-beta.54) (2024-06-28) + + +### Features + +* **studyPrefetcher:** Study Prefetcher ([#4206](https://github.com/OHIF/Viewers/issues/4206)) ([2048b19](https://github.com/OHIF/Viewers/commit/2048b19484c0b1fae73f993cfaa814f861bbd230)) + + + + + +# [3.9.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.52...v3.9.0-beta.53) (2024-06-28) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.51...v3.9.0-beta.52) (2024-06-27) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.50...v3.9.0-beta.51) (2024-06-27) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.49...v3.9.0-beta.50) (2024-06-26) + + +### Bug Fixes + +* **orthanc:** Correct bulkdata URL handling and add configuration example PDF ([#4262](https://github.com/OHIF/Viewers/issues/4262)) ([fdf883a](https://github.com/OHIF/Viewers/commit/fdf883ada880c0979acba8fdff9b542dc05b7706)) + + + + + +# [3.9.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.48...v3.9.0-beta.49) (2024-06-26) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.47...v3.9.0-beta.48) (2024-06-25) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.46...v3.9.0-beta.47) (2024-06-21) + + +### Bug Fixes + +* Allow the mode setup/creation to be async, and provide a few more values to extension/app config/mode setup. ([#4016](https://github.com/OHIF/Viewers/issues/4016)) ([88575c6](https://github.com/OHIF/Viewers/commit/88575c6c09fd778a31b2f91524163ce65d1639dd)) +* **code:** remove console log ([#4248](https://github.com/OHIF/Viewers/issues/4248)) ([f3bbfff](https://github.com/OHIF/Viewers/commit/f3bbfff09b66ee020daf503656a2b58e763634a3)) +* **CustomViewportOverlay:** pass accurate data to Custom Viewport Functions ([#4224](https://github.com/OHIF/Viewers/issues/4224)) ([aef00e9](https://github.com/OHIF/Viewers/commit/aef00e91d63e9bc2de289cc6f35975e36547fb20)) + + +### Features + +* customization service append and customize functionality should run once ([#4238](https://github.com/OHIF/Viewers/issues/4238)) ([e462fd3](https://github.com/OHIF/Viewers/commit/e462fd31f7944acfee34f08cfbc28cfd9de16169)) +* **sort:** custom series sort in study panel ([#4214](https://github.com/OHIF/Viewers/issues/4214)) ([a433d40](https://github.com/OHIF/Viewers/commit/a433d406e2cac13f644203996c682260b54e8865)) + + + + + +# [3.9.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.45...v3.9.0-beta.46) (2024-06-18) + + +### Bug Fixes + +* Use correct external URL for rendered responses with relative URI ([#4236](https://github.com/OHIF/Viewers/issues/4236)) ([d8f6991](https://github.com/OHIF/Viewers/commit/d8f6991dbe72465080cfc5de39c7ea225702f2e0)) + + + + + +# [3.9.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.44...v3.9.0-beta.45) (2024-06-18) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.43...v3.9.0-beta.44) (2024-06-17) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.42...v3.9.0-beta.43) (2024-06-12) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.41...v3.9.0-beta.42) (2024-06-12) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.40...v3.9.0-beta.41) (2024-06-12) + + +### Features + +* Add customization merge, append or replace functionality ([#3871](https://github.com/OHIF/Viewers/issues/3871)) ([55dcfa1](https://github.com/OHIF/Viewers/commit/55dcfa1f6994a7036e7e594efb23673382a41915)) + + + + + +# [3.9.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.39...v3.9.0-beta.40) (2024-06-12) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.38...v3.9.0-beta.39) (2024-06-08) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.37...v3.9.0-beta.38) (2024-06-07) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.36...v3.9.0-beta.37) (2024-06-05) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.35...v3.9.0-beta.36) (2024-06-05) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.34...v3.9.0-beta.35) (2024-06-05) + + +### Bug Fixes + +* **seg:** maintain algorithm name and algorithm type when DICOM seg is exported or downloaded ([#4203](https://github.com/OHIF/Viewers/issues/4203)) ([a29e94d](https://github.com/OHIF/Viewers/commit/a29e94de803f79bbb3372d00ad8eb14b4224edc2)) + + + + + +# [3.9.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.33...v3.9.0-beta.34) (2024-06-05) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.32...v3.9.0-beta.33) (2024-06-05) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.31...v3.9.0-beta.32) (2024-05-31) + + +### Bug Fixes + +* **tmtv:** crosshairs should not have viewport indicators ([#4197](https://github.com/OHIF/Viewers/issues/4197)) ([f85da32](https://github.com/OHIF/Viewers/commit/f85da32f34389ef7cecae03c07e0af26468b52a6)) + + + + + +# [3.9.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.30...v3.9.0-beta.31) (2024-05-30) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.29...v3.9.0-beta.30) (2024-05-30) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.28...v3.9.0-beta.29) (2024-05-30) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.27...v3.9.0-beta.28) (2024-05-30) + + +### Bug Fixes + +* **queryparam:** set all query params to lowercase by default ([#4190](https://github.com/OHIF/Viewers/issues/4190)) ([e073d19](https://github.com/OHIF/Viewers/commit/e073d195fdec7f8bdb67e5e3dae522a0fd121ad2)) + + + + + +# [3.9.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.26...v3.9.0-beta.27) (2024-05-29) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.25...v3.9.0-beta.26) (2024-05-29) + + +### Features + +* **hp:** Add displayArea option for Hanging protocols and example with Mamo([#3808](https://github.com/OHIF/Viewers/issues/3808)) ([18ac08e](https://github.com/OHIF/Viewers/commit/18ac08ed860d119721c52e4ffc270332259100b6)) + + + + + +# [3.9.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.24...v3.9.0-beta.25) (2024-05-29) + + +### Bug Fixes + +* **ultrasound:** Upgrade cornerstone3D version to resolve coloring issues ([#4181](https://github.com/OHIF/Viewers/issues/4181)) ([75a71db](https://github.com/OHIF/Viewers/commit/75a71db7f89840250ad1c2b35df5a35aceb8be7d)) + + + + + +# [3.9.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.23...v3.9.0-beta.24) (2024-05-29) + + +### Features + +* **measurements:** show untracked measurements in measurement panel under additional findings ([#4160](https://github.com/OHIF/Viewers/issues/4160)) ([18686c2](https://github.com/OHIF/Viewers/commit/18686c2caf13ede3e881303100bd4cc34b8b135f)) + + + + + +# [3.9.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.22...v3.9.0-beta.23) (2024-05-28) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.21...v3.9.0-beta.22) (2024-05-27) + + +### Features + +* **ui:** move to React 18 and base for using shadcn/ui ([#4174](https://github.com/OHIF/Viewers/issues/4174)) ([70f2c79](https://github.com/OHIF/Viewers/commit/70f2c797f42af603d7ea0eb8d23b4103aba66f77)) + + + + + +# [3.9.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.20...v3.9.0-beta.21) (2024-05-24) + + +### Features + +* **types:** typed app config ([#4171](https://github.com/OHIF/Viewers/issues/4171)) ([8960b89](https://github.com/OHIF/Viewers/commit/8960b89911a9342d93bf1a62bec97a696f101fd4)) + + + + + +# [3.9.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.19...v3.9.0-beta.20) (2024-05-24) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.18...v3.9.0-beta.19) (2024-05-24) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.17...v3.9.0-beta.18) (2024-05-24) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.16...v3.9.0-beta.17) (2024-05-23) + + +### Bug Fixes + +* **crosshairs:** reset angle, position, and slabthickness for crosshairs when reset viewport tool is used ([#4113](https://github.com/OHIF/Viewers/issues/4113)) ([73d9e99](https://github.com/OHIF/Viewers/commit/73d9e99d5d6f38ab6c36f4471d54f18798feacb4)) + + + + + +# [3.9.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.15...v3.9.0-beta.16) (2024-05-23) + + +### Bug Fixes + +* dicom json for orthanc by Update package versions for [@cornerstonejs](https://github.com/cornerstonejs) dependencies ([#4165](https://github.com/OHIF/Viewers/issues/4165)) ([34c7d72](https://github.com/OHIF/Viewers/commit/34c7d72142847486b98c9c52469940083eeaf87e)) + + + + + +# [3.9.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.14...v3.9.0-beta.15) (2024-05-22) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.13...v3.9.0-beta.14) (2024-05-21) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.12...v3.9.0-beta.13) (2024-05-21) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.11...v3.9.0-beta.12) (2024-05-21) + + +### Bug Fixes + +* **segmentation:** Address issue where segmentation creation failed on layout change ([#4153](https://github.com/OHIF/Viewers/issues/4153)) ([29944c8](https://github.com/OHIF/Viewers/commit/29944c8512c35718af03c03ef82bc43675ee1872)) + + + + + +# [3.9.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.10...v3.9.0-beta.11) (2024-05-21) + + +### Features + +* **test:** Playwright testing integration ([#4146](https://github.com/OHIF/Viewers/issues/4146)) ([fe1a706](https://github.com/OHIF/Viewers/commit/fe1a706446cc33670bf5fab8451e8281b487fcd6)) + + + + + +# [3.9.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.9...v3.9.0-beta.10) (2024-05-21) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.8...v3.9.0-beta.9) (2024-05-17) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.7...v3.9.0-beta.8) (2024-05-16) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.6...v3.9.0-beta.7) (2024-05-15) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.5...v3.9.0-beta.6) (2024-05-15) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.4...v3.9.0-beta.5) (2024-05-14) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.3...v3.9.0-beta.4) (2024-05-14) + + +### Bug Fixes + +* **auth:** bind handleUnauthenticated to correct context ([#4120](https://github.com/OHIF/Viewers/issues/4120)) ([8fa339f](https://github.com/OHIF/Viewers/commit/8fa339f296fd7e844f3879cfd81e47dbff315e66)) +* **DicomJSONDataSource:** Fix series filtering ([#4092](https://github.com/OHIF/Viewers/issues/4092)) ([2de102c](https://github.com/OHIF/Viewers/commit/2de102c73c795cfb48b49005b10aa788444a45b7)) + + + + + +# [3.9.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.2...v3.9.0-beta.3) (2024-05-08) + + +### Features + +* **typings:** Enhance typing support with withAppTypes and custom services throughout OHIF ([#4090](https://github.com/OHIF/Viewers/issues/4090)) ([374065b](https://github.com/OHIF/Viewers/commit/374065bc3bad9d212f9817a8d41546cc64cfabfb)) + + + + + +# [3.9.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.1...v3.9.0-beta.2) (2024-05-06) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.9.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.0...v3.9.0-beta.1) (2024-05-06) + + +### Bug Fixes + +* **rt:** enhanced RT support, utilize SVGs for rendering. ([#4074](https://github.com/OHIF/Viewers/issues/4074)) ([0156bc4](https://github.com/OHIF/Viewers/commit/0156bc426f1840ae0d090223e94a643726e856cb)) + + + + + +# [3.9.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.94...v3.9.0-beta.0) (2024-04-29) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.8.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0-beta.94) (2024-04-29) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29) + + +### Bug Fixes + +* **toolbox:** Preserve user-specified tool state and streamline command execution ([#4063](https://github.com/OHIF/Viewers/issues/4063)) ([f1a736d](https://github.com/OHIF/Viewers/commit/f1a736d1934733a434cb87b2c284907a3122403f)) + + + + + +# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28) + + +### Bug Fixes + +* **bugs:** fix patient header for doc, track ball rotate resize observer and add segmentation button not being enabled on viewport data change ([#4068](https://github.com/OHIF/Viewers/issues/4068)) ([c09311d](https://github.com/OHIF/Viewers/commit/c09311d3b7df05fcd00a9f36a7233e9d7e5589d0)) + + + + + +# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22) + + +### Bug Fixes + +* **viewport-webworker-segmentation:** Resolve issues with viewport detection, webworker termination, and segmentation panel layout change ([#4059](https://github.com/OHIF/Viewers/issues/4059)) ([52a0c59](https://github.com/OHIF/Viewers/commit/52a0c59294a4161fcca0a6708855549034849951)) + + + + + +# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19) + + +### Features + +* **tmtv-mode:** Add Brush tools and move SUV peak calculation to web worker ([#4053](https://github.com/OHIF/Viewers/issues/4053)) ([8192e34](https://github.com/OHIF/Viewers/commit/8192e348eca993fec331d4963efe88f9a730eceb)) + + + + + +# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19) + + +### Bug Fixes + +* **layouts:** and fix thumbnail in touch and update migration guide for 3.8 release ([#4052](https://github.com/OHIF/Viewers/issues/4052)) ([d250d04](https://github.com/OHIF/Viewers/commit/d250d04580883446fcb8d748b2a97c5c198922af)) + + + + + +# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18) + +**Note:** Version bump only for package @ohif/app + + + + + +# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18) + + +### Bug Fixes + +* **bugs:** and replace seriesInstanceUID and seriesInstanceUIDs URL with seriesInstanceUIDs ([#4049](https://github.com/OHIF/Viewers/issues/4049)) ([da7c1a5](https://github.com/OHIF/Viewers/commit/da7c1a5d8c54bfa1d3f97bbc500386bf76e7fd9d)) + + + + + +# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18) + + +### Bug Fixes + +* **bugs:** enhancements and bug fixes - final ([#4048](https://github.com/OHIF/Viewers/issues/4048)) ([170bb96](https://github.com/OHIF/Viewers/commit/170bb96983082c39b22b7352e0c54aacf3e73b02)) + + + + + # [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17) **Note:** Version bump only for package @ohif/app diff --git a/platform/app/cypress.config.ts b/platform/app/cypress.config.ts index c575e7c56c..648c42889d 100644 --- a/platform/app/cypress.config.ts +++ b/platform/app/cypress.config.ts @@ -28,6 +28,7 @@ export default defineConfig({ defaultCommandTimeout: 10000, requestTimeout: 10000, responseTimeout: 10000, + pageLoadTimeout: 10000, specPattern: 'cypress/integration/**/*.spec.[jt]s', projectId: '4oe38f', video: true, diff --git a/platform/app/cypress/integration/ImageConsistency.spec.js b/platform/app/cypress/integration/ImageConsistency.spec.js new file mode 100644 index 0000000000..52c27b5bfd --- /dev/null +++ b/platform/app/cypress/integration/ImageConsistency.spec.js @@ -0,0 +1,92 @@ +/** + * Add tests to ensure image consistency and quality + */ + +const testPixel = (dx, dy, expectedPixel) => { + cy.get('.cornerstone-canvas').then(v => { + const canvas = v[0]; + cy.log( + 'testPixel canvas', + dx, + dy, + expectedPixel, + canvas.width, + canvas.height, + canvas.style.width, + canvas.style.height + ); + const ctx = canvas.getContext('2d'); + cy.window() + .its('cornerstone') + .then(cornerstone => { + const { viewport } = cornerstone.getEnabledElements()[0]; + const imageData = viewport.getImageData(); + // cy.log("imageData", imageData); + const origin = viewport.worldToCanvas(imageData.origin); + const orX = origin[0] * devicePixelRatio; + const orY = origin[1] * devicePixelRatio; + const x = Math.round(orX + dx); + const y = Math.round(orY + dy); + cy.log('testPixel origin x,y point x,y', orX, orY, x, y); + // cy.log('world origin', imageData.origin); + // cy.log('focal', viewport.getCamera().focalPoint, + // viewport.worldToCanvas(viewport.getCamera().focalPoint)); + const pixelData = ctx.getImageData(x, y, 1, 1); + + expect(pixelData.data[0]).closeTo(expectedPixel, 1); + }); + }); +}; + +describe('CS3D Image Consistency and Quality', () => { + const setupStudySeries = (studyUID, seriesUID) => { + cy.checkStudyRouteInViewer( + studyUID, + `&seriesInstanceUID=${seriesUID}&hangingProtocolId=@ohif/hpScale` + ); + cy.initCornerstoneToolsAliases(); + + const skipMarkers = true; + cy.initCommonElementsAliases(skipMarkers); + }; + + it('TG18 Resolution Test Displayed 1:1', () => { + setupStudySeries( + '2.16.124.113543.6004.101.103.20021117.061159.1', + '2.16.124.113543.6004.101.103.20021117.061159.1.004' + ); + + cy.wait(2000); + testPixel(1018, 1028, 255); + // Horizontal and vertical delta from this should not be contaminated + // by values from center + testPixel(1019, 1028, 0); + testPixel(1018, 1029, 0); + testPixel(1017, 1028, 0); + testPixel(1018, 1027, 0); + }); + + // Missing test data - todo + it.skip('8 bit image displayable', () => { + setupStudySeries('1.3.46.670589.17.1.7.1.1.7', '1.3.46.670589.17.1.7.2.1.7'); + + cy.wait(1000); + + // Compare with dcm2jpg generated values or by manually computing WL values + testPixel(258, 257, 171); + testPixel(259, 257, 166); + }); + + it.skip('12 bit image displayable and zoom with pixel spacing', () => { + setupStudySeries( + '1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1', + '1.3.6.1.4.1.25403.345050719074.3824.20170125113608.5' + ); + + cy.wait(1000); + + // Compare with dcm2jpg generated values or by manually computing WL values + testPixel(258, 277, 120); + testPixel(259, 277, 122); + }); +}); diff --git a/platform/app/cypress/integration/customization/HangingProtocol.spec.js b/platform/app/cypress/integration/customization/HangingProtocol.spec.js index a30064acf2..743caecba1 100644 --- a/platform/app/cypress/integration/customization/HangingProtocol.spec.js +++ b/platform/app/cypress/integration/customization/HangingProtocol.spec.js @@ -25,6 +25,7 @@ describe('OHIF HP', () => { }); it('Should navigate to display set specified', () => { + Cypress.on('uncaught:exception', () => false); // This filters by series instance UID, meaning there will only be 1 thumbnail // It applies the initial SOP instance, navigating to that image cy.checkStudyRouteInViewer( diff --git a/platform/app/cypress/integration/measurement-tracking/visual-regression/PercyCheckOHIFCornerstoneHotkeys.spec.js b/platform/app/cypress/integration/measurement-tracking/visual-regression/PercyCheckOHIFCornerstoneHotkeys.spec.js deleted file mode 100644 index 0d59094379..0000000000 --- a/platform/app/cypress/integration/measurement-tracking/visual-regression/PercyCheckOHIFCornerstoneHotkeys.spec.js +++ /dev/null @@ -1,34 +0,0 @@ -/*describe('Visual Regression - OHIF Cornerstone Hotkeys', () => { - before(() => { - cy.checkStudyRouteInViewer( - '1.2.840.113619.2.5.1762583153.215519.978957063.78' - ); - cy.expectMinimumThumbnails(3); - }); - - beforeEach(() => { - cy.initCornerstoneToolsAliases(); - cy.initCommonElementsAliases(); - cy.resetViewport(); - }); - - it('checks if hotkey "I" can invert the image', () => { - // Hotkey I - cy.get('body').type('I'); - // Visual comparison - cy.screenshot('Hotkey I - Should Invert Image'); - cy.percyCanvasSnapshot('Hotkey I - Should Invert Image'); - }); - - it('checks if hotkey "SPACEBAR" can reset the image', () => { - // Press multiples hotkeys - cy.get('body').type('V+++I'); - - // Hotkey SPACEBAR - cy.get('body').type(' '); - - // Visual comparison to make sure the 'inverted' image was reset - cy.screenshot('Hotkey SPACEBAR - Should Reset Image'); - cy.percyCanvasSnapshot('Hotkey SPACEBAR - Should Reset Image'); - }); -});*/ diff --git a/platform/app/cypress/integration/measurement-tracking/visual-regression/PercyCheckOHIFCornerstoneToolbar.spec.js b/platform/app/cypress/integration/measurement-tracking/visual-regression/PercyCheckOHIFCornerstoneToolbar.spec.js deleted file mode 100644 index f7d8a69a74..0000000000 --- a/platform/app/cypress/integration/measurement-tracking/visual-regression/PercyCheckOHIFCornerstoneToolbar.spec.js +++ /dev/null @@ -1,85 +0,0 @@ -/*describe('Visual Regression - OHIF Cornerstone Toolbar', () => { - before(() => { - cy.checkStudyRouteInViewer( - '1.2.840.113619.2.5.1762583153.215519.978957063.78' - ); - cy.expectMinimumThumbnails(3); - }); - - beforeEach(() => { - cy.initCornerstoneToolsAliases(); - cy.initCommonElementsAliases(); - cy.resetViewport(); - }); - - it('checks if Pan tool will move the image inside the viewport', () => { - //Click on button and verify if icon is active on toolbar - cy.get('@panBtn') - .click() - .then($panBtn => { - cy.wrap($panBtn).should('have.class', 'active'); - }); - - cy.get('@viewport') - .trigger('mousedown', 'center', { which: 1 }) - .trigger('mousemove', 'bottom', { which: 1 }) - .trigger('mouseup', 'bottom'); - - // Visual comparison - cy.percyCanvasSnapshot('Pan tool moved the image inside the viewport'); - }); - - it('check if Invert tool will change the colors of the image in the viewport', () => { - // Click on More button - cy.get('@moreBtn').click(); - // Verify if overlay is displayed - cy.get('.tooltip-toolbar-overlay').should('be.visible'); - - // Click on Invert button - cy.get('[data-cy="invert"]').click(); - - // Visual comparison - cy.percyCanvasSnapshot('Invert tool - Should Invert Canvas'); - }); - - it('check if Rotate tool will change the image orientation in the viewport', () => { - //Click on More button - cy.get('@moreBtn').click(); - //Verify if overlay is displayed - cy.get('.tooltip-toolbar-overlay') - .should('be.visible') - .then(() => { - //Click on Rotate button - cy.get('[data-cy="rotate right"]').click({ force: true }); - }); - - // Visual comparison - cy.percyCanvasSnapshot('Rotate tool - Should Rotate Image to Right'); - }); - - it('check if Flip H tool will flip the image horizontally in the viewport', () => { - //Click on More button - cy.get('@moreBtn').click(); - //Verify if overlay is displayed - cy.get('.tooltip-toolbar-overlay').should('be.visible'); - - //Click on Flip H button - cy.get('[data-cy="flip h"]').click(); - - // Visual comparison - cy.percyCanvasSnapshot('Flip H tool - Should Flip Image on Y axis'); - }); - - it('check if Flip V tool will flip the image vertically in the viewport', () => { - //Click on More button - cy.get('@moreBtn').click(); - //Verify if overlay is displayed - cy.get('.tooltip-toolbar-overlay').should('be.visible'); - - //Click on Flip V button - cy.get('[data-cy="flip v"]').click(); - - // Visual comparison - cy.percyCanvasSnapshot('Flip V tool - Should Flip Image on X axis'); - }); -});*/ diff --git a/platform/app/cypress/integration/measurement-tracking/visual-regression/PercyCheckOHIFDownloadSnapshotFile.spec.js b/platform/app/cypress/integration/measurement-tracking/visual-regression/PercyCheckOHIFDownloadSnapshotFile.spec.js deleted file mode 100644 index 35c36433f7..0000000000 --- a/platform/app/cypress/integration/measurement-tracking/visual-regression/PercyCheckOHIFDownloadSnapshotFile.spec.js +++ /dev/null @@ -1,44 +0,0 @@ -/*describe('Visual Regression - OHIF Download Snapshot File', () => { - before(() => { - cy.checkStudyRouteInViewer( - '1.2.840.113619.2.5.1762583153.215519.978957063.78' - ); - cy.expectMinimumThumbnails(3); - }); - - beforeEach(() => { - cy.openDownloadImageModal(); - }); - - afterEach(() => { - // Close modal - cy.get('[data-cy="close-button"]') - .scrollIntoView() - .click(); - }); - - it('checks displayed information for Desktop experience', function() { - // Set Desktop resolution - cy.viewport(1750, 720); - // Visual comparison - cy.percyCanvasSnapshot('Download Image Modal - Desktop experience'); - }); - - it('checks if "Show Annotations" checkbox will display annotations', function() { - // Close modal that is initially opened - cy.get('[data-cy="close-button"]').click(); - - // Add measurements in the viewport - cy.addLengthMeasurement(); - cy.addAngleMeasurement(); - - // Open Modal - cy.openDownloadImageModal(); - // Select "Show Annotations" option - cy.get('[data-cy="show-annotations"]').check(); - // Check image preview - cy.get('[data-cy="image-preview"]').scrollIntoView(); - // Visual comparison - cy.percyCanvasSnapshot('Download Image Modal - Show Annotations checked'); - }); -});*/ diff --git a/platform/app/cypress/integration/measurement-tracking/visual-regression/PercyCheckOHIFStudyViewer.spec.js b/platform/app/cypress/integration/measurement-tracking/visual-regression/PercyCheckOHIFStudyViewer.spec.js deleted file mode 100644 index 58ba7422e4..0000000000 --- a/platform/app/cypress/integration/measurement-tracking/visual-regression/PercyCheckOHIFStudyViewer.spec.js +++ /dev/null @@ -1,36 +0,0 @@ -/*describe('Visual Regression - OHIF Study Viewer Page', function() { - before(() => { - cy.checkStudyRouteInViewer( - '1.2.840.113619.2.5.1762583153.215519.978957063.78' - ); - cy.expectMinimumThumbnails(3); - }); - - beforeEach(function() { - cy.initCommonElementsAliases(); - cy.resetViewport(); - }); - - it('checks if series thumbnails are being displayed', function() { - cy.percyCanvasSnapshot('Series Thumbnails - Should Display Thumbnails'); - }); - - it('opens About modal and verify the displayed information', function() { - cy.get('[data-cy="options-menu"]') - .first() - .click(); - cy.get('[data-cy="dd-item-menu"]') - .first() - .click(); - cy.get('[data-cy="about-modal"]') - .as('aboutOverlay') - .should('be.visible'); - - // Visual comparison - cy.percyCanvasSnapshot('About modal - Should display modal'); - - //close modal - cy.get('[data-cy="close-button"]').click(); - cy.get('@aboutOverlay').should('not.exist'); - }); -});*/ diff --git a/platform/app/cypress/integration/measurement-tracking/visual-regression/PercyCheckOHIFUserPreferences.spec.js b/platform/app/cypress/integration/measurement-tracking/visual-regression/PercyCheckOHIFUserPreferences.spec.js deleted file mode 100644 index b1d0122588..0000000000 --- a/platform/app/cypress/integration/measurement-tracking/visual-regression/PercyCheckOHIFUserPreferences.spec.js +++ /dev/null @@ -1,204 +0,0 @@ -/*describe('Visual Regression - OHIF User Preferences', () => { - context('Study List Page', function() { - before(() => { - cy.visit('/'); - }); - - beforeEach(() => { - // Open User Preferences modal - cy.openPreferences(); - }); - - afterEach(() => { - // Close User Preferences modal - cy.closePreferences(); - }); - - it('checks displayed information on User Preferences modal', function() { - // Go go hotkeys tab - cy.selectPreferencesTab('@userPreferencesHotkeysTab'); - cy.get('@restoreBtn').scrollIntoView(); - - // Visual comparison - cy.percyCanvasSnapshot( - 'User Preferences Modal - Hotkeys tab initial state in StudyList page' - ); - cy.get('[data-cy="close-button"]').click(); - }); - - it('checks translation by selecting Spanish language', function() { - cy.selectPreferencesTab('@userPreferencesGeneralTab'); - - // Language dropdown should be displayed - cy.get('#language-select').should('be.visible'); - - // Visual comparison - cy.percyCanvasSnapshot( - 'User Preferences Modal - General tab initial state in StudyList page' - ); - // Set language to Spanish and save - cy.setLanguage('Spanish'); - - // Options menu should be translated - cy.get('[data-cy="options-menu"]') - .should('have.text', 'Opciones') - .click(); - - // Visual comparison - cy.percyCanvasSnapshot( - 'User Preferences Modal - Spanish selected in StudyList page' - ); - - // Close Options menu - cy.get('[data-cy="options-menu"]').click(); - }); - }); - - context('Study Viewer Page', function() { - before(() => { - cy.openStudyInViewer('1.2.840.113619.2.5.1762583153.215519.978957063.78'); - cy.expectMinimumThumbnails(3); - }); - - beforeEach(() => { - cy.initCommonElementsAliases(); - cy.resetViewport(); - - cy.resetUserHotkeyPreferences(); - // Open User Preferences modal - cy.openPreferences(); - }); - - afterEach(() => { - // Close User Preferences modal - cy.closePreferences(); - }); - - it('checks displayed information on User Preferences modal', function() { - // Go go hotkeys tab - cy.selectPreferencesTab('@userPreferencesHotkeysTab'); - cy.get('@restoreBtn').scrollIntoView(); - - // Visual comparison - cy.percyCanvasSnapshot( - 'User Preferences Modal - Hotkeys tab initial state in StudyViewer page' - ); - cy.get('[data-cy="close-button"]').click(); //close User Preferences modal - }); - - it('checks if W/L Preferences table is being displayed in the Window Level tab', function() { - //Navigate to Window Level tab - cy.selectPreferencesTab('@userPreferencesWindowLevelTab'); - - // Visual comparison - cy.percyCanvasSnapshot( - 'User Preferences Modal - Window Level Presets Tab' - ); - }); - - it('checks translation by selecting Spanish language', function() { - cy.selectPreferencesTab('@userPreferencesGeneralTab'); - - // Visual comparison - cy.percyCanvasSnapshot( - 'User Preferences Modal - General tab initial state in StudyViewer page' - ); - // Set language to Spanish - cy.setLanguage('Spanish'); - - // Options menu should be translated - cy.get('[data-cy="options-menu"]') - .should('have.text', 'Opciones') - .click(); - - // Visual comparison - cy.percyCanvasSnapshot( - 'User Preferences Modal - Spanish selected in StudyViewer page' - ); - - // Close Options menu - cy.get('[data-cy="options-menu"]').click(); - }); - - it('checks if user can restore to default the language selection and application will be in English', function() { - cy.selectPreferencesTab('@userPreferencesGeneralTab'); - - // Set language to Spanish - cy.setLanguage('Spanish'); - - // Open User Preferences modal - cy.openPreferences(); - - // Go to general tab - cy.selectPreferencesTab('@userPreferencesGeneralTab'); - - cy.get('@restoreBtn') - .scrollIntoView() - .click(); - - cy.get('@saveBtn') - .scrollIntoView() - .click(); - - // Options menu should be in English - cy.get('[data-cy="options-menu"]') - .should('have.text', 'Options') - .click(); - - // Visual comparison - cy.percyCanvasSnapshot( - 'User Preferences Modal - English selected in StudyViewer page' - ); - - // Close Options menu - cy.get('[data-cy="options-menu"]').click(); - }); - - it('checks new hotkeys for "Next" and "Previous" Image on Viewport', function() { - // Go go hotkeys tab - cy.selectPreferencesTab('@userPreferencesHotkeysTab'); - - // Set new hotkey for 'Next Image Viewport' function - cy.setNewHotkeyShortcutOnUserPreferencesModal( - 'Next Viewport', - '{shift}{rightarrow}' - ); - - // Set new hotkey for 'Previous Image Viewport' function - cy.setNewHotkeyShortcutOnUserPreferencesModal( - 'Previous Viewport', - '{shift}{leftarrow}' - ); - - // Save new hotkeys - cy.get('@saveBtn') - .scrollIntoView() - .click(); - - // Set 3 viewports layout - cy.setLayout(3, 1); - cy.waitViewportImageLoading(); - - // Rotate Right and Invert colors on Viewport #1 - cy.get('body').type('RI'); - - //Move to Next Viewport - cy.get('body').type('{shift}{rightarrow}'); - // Rotate Left and Invert colors on Viewport #2 - cy.get('body').type('LI'); - - //Move to Previous Viewport - cy.get('body').type('{shift}{leftarrow}'); - // Reset viewport #1 with spacebar hotkey - cy.get('body').type(' '); - - // Visual comparison - cy.percyCanvasSnapshot( - 'Viewport Navigation - 2nd viewport inverted and rotated' - ); - // Set 1 viewport layout - cy.setLayout(1, 1); - }); - }); -}); -*/ diff --git a/platform/app/cypress/integration/study-list/OHIFStudyList.spec.js b/platform/app/cypress/integration/study-list/OHIFStudyList.spec.js index e59df25cff..c92216de2d 100644 --- a/platform/app/cypress/integration/study-list/OHIFStudyList.spec.js +++ b/platform/app/cypress/integration/study-list/OHIFStudyList.spec.js @@ -3,6 +3,7 @@ describe('OHIF Study List', function () { context('Desktop resolution', function () { beforeEach(function () { + Cypress.on('uncaught:exception', () => false); cy.window().then(win => win.sessionStorage.clear()); cy.openStudyList(); @@ -47,6 +48,8 @@ describe('OHIF Study List', function () { '[data-cy="mode-basic-test-1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1"]' ).click(); cy.get('[data-cy="return-to-work-list"]').click(); + cy.wait(2000); + cy.get('@searchResult2').should($list => { expect($list.length).to.be.eq(1); expect($list).to.contain('Juno'); @@ -72,6 +75,8 @@ describe('OHIF Study List', function () { '[data-cy="mode-basic-test-1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1"]' ).click(); cy.get('[data-cy="return-to-work-list"]').click(); + cy.wait(2000); + cy.get('@searchResult2').should($list => { expect($list.length).to.be.eq(1); expect($list).to.contain('0000003'); @@ -82,6 +87,7 @@ describe('OHIF Study List', function () { cy.get('@AccessionNumber').type('321'); //Wait result list to be displayed cy.waitStudyList(); + cy.wait(2000); cy.get('@searchResult2').should($list => { expect($list.length).to.be.eq(1); expect($list).to.contain('321'); @@ -92,11 +98,15 @@ describe('OHIF Study List', function () { cy.get('@AccessionNumber').type('0000155811'); //Wait result list to be displayed cy.waitStudyList(); + cy.wait(2000); + cy.get('[data-cy="studyRow-1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1"]').click(); cy.get( '[data-cy="mode-basic-test-1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1"]' ).click(); cy.get('[data-cy="return-to-work-list"]').click(); + cy.wait(2000); + cy.get('@searchResult2').should($list => { expect($list.length).to.be.eq(1); expect($list).to.contain('0000155811'); @@ -107,6 +117,8 @@ describe('OHIF Study List', function () { cy.get('@StudyDescription').type('PETCT'); //Wait result list to be displayed cy.waitStudyList(); + cy.wait(2000); + cy.get('@searchResult2').should($list => { expect($list.length).to.be.eq(1); expect($list).to.contain('PETCT'); @@ -117,13 +129,15 @@ describe('OHIF Study List', function () { cy.get('@StudyDescription').type('PETCT'); //Wait result list to be displayed cy.waitStudyList(); + cy.wait(2000); + cy.get('[data-cy="studyRow-1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1"]').click(); cy.get( '[data-cy="mode-basic-test-1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1"]' ).click(); cy.get('[data-cy="return-to-work-list"]').click(); + cy.wait(2000); - cy.wait(1000); cy.get('@searchResult2').should($list => { expect($list.length).to.be.eq(1); expect($list).to.contain('PETCT'); diff --git a/platform/app/cypress/integration/volume/MPR.spec.js b/platform/app/cypress/integration/volume/MPR.spec.js index 2ef026ec90..5677468ca3 100644 --- a/platform/app/cypress/integration/volume/MPR.spec.js +++ b/platform/app/cypress/integration/volume/MPR.spec.js @@ -12,7 +12,7 @@ describe('OHIF MPR', () => { it('should go MPR for reconstructible displaySets and come back', () => { cy.wait(250); - cy.get(':nth-child(3) > [data-cy="study-browser-thumbnail"]').dblclick(); + cy.get('[data-cy="study-browser-thumbnail"][data-series="4"]').dblclick(); cy.wait(250); cy.get('[data-cy="MPR"]').click(); @@ -27,7 +27,7 @@ describe('OHIF MPR', () => { it('should render correctly the MPR', () => { cy.wait(250); - cy.get(':nth-child(3) > [data-cy="study-browser-thumbnail"]').dblclick(); + cy.get('[data-cy="study-browser-thumbnail"][data-series="4"]').dblclick(); cy.wait(250); cy.get('[data-cy="MPR"]').click(); @@ -61,7 +61,7 @@ describe('OHIF MPR', () => { }); it('should correctly render Crosshairs for MPR', () => { - cy.get(':nth-child(3) > [data-cy="study-browser-thumbnail"]').dblclick(); + cy.get('[data-cy="study-browser-thumbnail"][data-series="4"]').dblclick(); cy.get('[data-cy="MPR"]').click(); cy.get('[data-cy="Crosshairs"]').click(); @@ -78,8 +78,8 @@ describe('OHIF MPR', () => { const fOR = Object.keys(fORMap)[0]; const fORAnnotation = fORMap[fOR]; - // it should have crosshairs as the only key - expect(Object.keys(fORAnnotation)).to.have.length(1); + // it should have crosshairs as the only key (references lines make this 2) + expect(Object.keys(fORAnnotation)).to.have.length(2); const crosshairs = fORAnnotation.Crosshairs; @@ -93,7 +93,7 @@ describe('OHIF MPR', () => { }); it('should activate window level when the active Crosshairs tool for MPR is clicked', () => { - cy.get(':nth-child(3) > [data-cy="study-browser-thumbnail"]').dblclick(); + cy.get('[data-cy="study-browser-thumbnail"][data-series="4"]').dblclick(); cy.get('[data-cy="MPR"]').click(); cy.get('[data-cy="Crosshairs"]').click(); diff --git a/platform/app/cypress/results/.gitignore b/platform/app/cypress/results/.gitignore index e69de29bb2..e3343cddfe 100644 --- a/platform/app/cypress/results/.gitignore +++ b/platform/app/cypress/results/.gitignore @@ -0,0 +1 @@ +test-output.xml diff --git a/platform/app/cypress/support/aliases.js b/platform/app/cypress/support/aliases.js index 5b28709ca6..1453c6f66b 100644 --- a/platform/app/cypress/support/aliases.js +++ b/platform/app/cypress/support/aliases.js @@ -15,7 +15,7 @@ export function initCornerstoneToolsAliases() { } //Creating aliases for Common page elements -export function initCommonElementsAliases() { +export function initCommonElementsAliases(skipMarkers) { cy.get('[data-cy="trackedMeasurements-btn"]').as('measurementsBtn'); cy.get('.cornerstone-viewport-element').as('viewport'); cy.get('[data-cy="seriesList-btn"]').as('seriesBtn'); @@ -33,8 +33,17 @@ export function initCommonElementsAliases() { cy.get('[data-cy="viewport-overlay-bottom-right"]').as('viewportInfoBottomRight'); cy.get('[data-cy="viewport-overlay-bottom-left"]').as('viewportInfoBottomLeft'); - cy.get('.left-mid.orientation-marker').as('viewportInfoMidLeft'); - cy.get('.top-mid.orientation-marker').as('viewportInfoMidTop'); + console.debug('🚀 ~ skipMarkers:', skipMarkers); + if (skipMarkers) { + return; + } + + try { + cy.get('.left-mid.orientation-marker')?.as('viewportInfoMidLeft'); + cy.get('.top-mid.orientation-marker')?.as('viewportInfoMidTop'); + } catch (error) { + console.log('Error: ', error); + } } //Creating aliases for Routes @@ -61,8 +70,8 @@ export function initStudyListAliasesOnDesktop() { // We can't use data attributes (e.g. data--cy) for these since // they are using third party libraries (i.e. react-dates, react-select) - cy.get('#date-range-studyDate-start-date').as('studyListStartDate'); - cy.get('#date-range-studyDate-end-date').as('studyListEndDate'); + cy.get('[data-cy="input-date-range-start"').as('studyListStartDate'); + cy.get('[data-cy="input-date-range-end"').as('studyListEndDate'); cy.get('#input-modalities').as('modalities'); } diff --git a/platform/app/cypress/support/commands.js b/platform/app/cypress/support/commands.js index 51f17643ba..f8bd42915d 100644 --- a/platform/app/cypress/support/commands.js +++ b/platform/app/cypress/support/commands.js @@ -6,36 +6,26 @@ import { initCommonElementsAliases, initRouteAliases, initStudyListAliasesOnDesktop, - initStudyListAliasesOnTablet, initPreferencesModalAliases, initPreferencesModalFooterBtnAliases, } from './aliases.js'; -// *********************************************** -// This example commands.js shows you how to -// create various custom commands and overwrite -// existing commands. -// -// For more comprehensive examples of custom -// commands please read more here: -// https://on.cypress.io/custom-commands -// *********************************************** -// -// -// -- This is a parent command -- -// Cypress.Commands.add("login", (email, password) => { ... }) -// -// -// -- This is a child command -- -// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) -// -// -// -- This is a dual command -- -// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) -// -// -// -- This is will overwrite an existing command -- -// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) +/** + * Command to select a layout preset. + * The layout preset is selected by clicking on the Layout button and then clicking on the desired preset. + * The preset name is the text that is displayed on the button. + * @param {string} presetName - The name of the layout preset that we would like to select + * @param {boolean} screenshot - If true, a screenshot will be taken when the layout tool is opened + */ +Cypress.Commands.add('selectLayoutPreset', (presetName, screenshot) => { + cy.get('[data-cy="Layout"]').click(); + if (screenshot) { + cy.percyCanvasSnapshot('Layout tool opened'); + } + cy.get('div').contains(presetName).should('be.visible').click(); + // fixed wait time for layout changes and rendering + cy.wait(3000); +}); /** * Command to search for a patient name and open his/her study. @@ -116,10 +106,10 @@ Cypress.Commands.add('isPageLoaded', (url = '/basic-test') => { Cypress.Commands.add('openStudyList', () => { cy.initRouteAliases(); - cy.visit('/'); + cy.visit('/', { timeout: 15000 }); // For some reason cypress 12.x does not like to stub the network request - // so we just wait herer for 1 second + // so we just wait here for 1 second // cy.wait('@getStudies'); cy.waitQueryList(); }); @@ -242,8 +232,8 @@ Cypress.Commands.add('initCornerstoneToolsAliases', () => { }); //Initialize aliases for Common page elements -Cypress.Commands.add('initCommonElementsAliases', () => { - initCommonElementsAliases(); +Cypress.Commands.add('initCommonElementsAliases', skipMarkers => { + initCommonElementsAliases(skipMarkers); }); //Initialize aliases for Routes @@ -288,6 +278,56 @@ Cypress.Commands.add( } ); +// Add brush stroke in the viewport +Cypress.Commands.add('addBrush', (viewport, firstClick = [85, 100], secondClick = [85, 300]) => { + cy.get(viewport) + .first() + .then(viewportElement => { + const [x1, y1] = firstClick; + const [x2, y2] = secondClick; + + const steps = 10; + const xStep = (x2 - x1) / steps; + const yStep = (y2 - y1) / steps; + + cy.wrap(viewportElement) + .trigger('mousedown', x1, y1, { buttons: 1 }) + .then(() => { + for (let i = 1; i <= steps; i++) { + let x = x1 + xStep * i; + let y = y1 + yStep * i; + cy.wrap(viewportElement).trigger('mousemove', x, y, { buttons: 1 }); + } + }) + .trigger('mouseup'); + }); +}); + +// Add erase stroke in the viewport +Cypress.Commands.add('addEraser', (viewport, firstClick = [85, 100], secondClick = [85, 300]) => { + cy.get(viewport) + .first() + .then(viewportElement => { + const [x1, y1] = firstClick; + const [x2, y2] = secondClick; + + const steps = 10; + const xStep = (x2 - x1) / steps; + const yStep = (y2 - y1) / steps; + + cy.wrap(viewportElement) + .trigger('mousedown', x1, y1, { buttons: 1 }) + .then(() => { + for (let i = 1; i <= steps; i++) { + let x = x1 + xStep * i; + let y = y1 + yStep * i; + cy.wrap(viewportElement).trigger('mousemove', x, y, { buttons: 1 }); + } + }) + .trigger('mouseup'); + }); +}); + //Add measurements in the viewport Cypress.Commands.add( 'addAngleMeasurement', diff --git a/platform/app/jest.config.js b/platform/app/jest.config.js index 63f2459e01..e7bd742732 100644 --- a/platform/app/jest.config.js +++ b/platform/app/jest.config.js @@ -3,7 +3,6 @@ const pkg = require('./package'); module.exports = { ...base, - name: pkg.name, displayName: pkg.name, setupFilesAfterEnv: ['/src/__tests__/globalSetup.js'], // rootDir: "../.." diff --git a/platform/app/package.json b/platform/app/package.json index aadfbb6c53..3cc0982e46 100644 --- a/platform/app/package.json +++ b/platform/app/package.json @@ -1,6 +1,6 @@ { "name": "@ohif/app", - "version": "3.8.0-beta.82", + "version": "3.9.0-beta.71", "productVersion": "3.4.0", "description": "OHIF Viewer", "author": "OHIF Contributors", @@ -24,19 +24,18 @@ "build:viewer:ci": "cross-env NODE_ENV=production PUBLIC_URL=/ APP_CONFIG=config/netlify.js QUICK_BUILD=false yarn run build", "build:viewer:qa": "cross-env NODE_ENV=production APP_CONFIG=config/google.js yarn run build", "build:viewer:demo": "cross-env NODE_ENV=production APP_CONFIG=config/demo.js HTML_TEMPLATE=rollbar.html QUICK_BUILD=false yarn run build", - "build": "node --max_old_space_size=4096 ./../../node_modules/webpack/bin/webpack.js --progress --config .webpack/webpack.pwa.js", + "build": "node --max_old_space_size=8096 ./../../node_modules/webpack/bin/webpack.js --progress --config .webpack/webpack.pwa.js", "clean": "shx rm -rf dist", "clean:deep": "yarn run clean && shx rm -rf node_modules", "dev": "cross-env NODE_ENV=development webpack serve --config .webpack/webpack.pwa.js", "dev:no:cache": "cross-env NODE_ENV=development webpack serve --no-cache --config .webpack/webpack.pwa.js", - "dev:orthanc": "cross-env NODE_ENV=development PROXY_TARGET=/dicom-web PROXY_DOMAIN=http://localhost:8042 APP_CONFIG=config/docker_nginx-orthanc.js webpack serve --config .webpack/webpack.pwa.js", - "dev:orthanc:no:cache": "cross-env NODE_ENV=development PROXY_TARGET=/dicom-web PROXY_DOMAIN=http://localhost:8042 APP_CONFIG=config/docker_nginx-orthanc.js webpack serve --no-cache --config .webpack/webpack.pwa.js", + "dev:orthanc": "cross-env NODE_ENV=development PROXY_TARGET=/dicom-web PROXY_DOMAIN=http://localhost:8042 APP_CONFIG=config/docker-nginx-orthanc.js webpack serve --config .webpack/webpack.pwa.js", + "dev:orthanc:no:cache": "cross-env NODE_ENV=development PROXY_TARGET=/dicom-web PROXY_DOMAIN=http://localhost:8042 APP_CONFIG=config/docker-nginx-orthanc.js webpack serve --no-cache --config .webpack/webpack.pwa.js", "dev:dcm4chee": "cross-env NODE_ENV=development APP_CONFIG=config/local_dcm4chee.js webpack serve --config .webpack/webpack.pwa.js", "dev:static": "cross-env NODE_ENV=development APP_CONFIG=config/local_static.js webpack serve --config .webpack/webpack.pwa.js", "dev:viewer": "yarn run dev", "start": "yarn run dev", "test:e2e": "cypress open", - "test:e2e:ci": "percy exec -- cypress run --config video=false --record --browser chrome --spec 'cypress/integration/visual-regression/**/*'", "test:e2e:local": "cypress run --config video=false --browser chrome --spec 'cypress/integration/common/**/*,cypress/integration/pwa/**/*'", "test:e2e:dist": "start-server-and-test test:e2e:serve http://localhost:3000 test:e2e:ci", "test:e2e:serve": "cross-env APP_CONFIG=config/e2e.js yarn start", @@ -56,61 +55,58 @@ "@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2", "@cornerstonejs/codec-openjpeg": "^1.2.2", "@cornerstonejs/codec-openjph": "^2.4.5", - "@cornerstonejs/dicom-image-loader": "^1.70.6", + "@cornerstonejs/dicom-image-loader": "^1.77.6", "@emotion/serialize": "^1.1.3", - "@ohif/core": "3.8.0-beta.82", - "@ohif/extension-cornerstone": "3.8.0-beta.82", - "@ohif/extension-cornerstone-dicom-rt": "3.8.0-beta.82", - "@ohif/extension-cornerstone-dicom-seg": "3.8.0-beta.82", - "@ohif/extension-cornerstone-dicom-sr": "3.8.0-beta.82", - "@ohif/extension-default": "3.8.0-beta.82", - "@ohif/extension-dicom-microscopy": "3.8.0-beta.82", - "@ohif/extension-dicom-pdf": "3.8.0-beta.82", - "@ohif/extension-dicom-video": "3.8.0-beta.82", - "@ohif/extension-test": "3.8.0-beta.82", - "@ohif/i18n": "3.8.0-beta.82", - "@ohif/mode-basic-dev-mode": "3.8.0-beta.82", - "@ohif/mode-longitudinal": "3.8.0-beta.82", - "@ohif/mode-microscopy": "3.8.0-beta.82", - "@ohif/mode-test": "3.8.0-beta.82", - "@ohif/ui": "3.8.0-beta.82", - "@types/react": "^17.0.38", + "@ohif/core": "3.9.0-beta.71", + "@ohif/extension-cornerstone": "3.9.0-beta.71", + "@ohif/extension-cornerstone-dicom-rt": "3.9.0-beta.71", + "@ohif/extension-cornerstone-dicom-seg": "3.9.0-beta.71", + "@ohif/extension-cornerstone-dicom-sr": "3.9.0-beta.71", + "@ohif/extension-default": "3.9.0-beta.71", + "@ohif/extension-dicom-microscopy": "3.9.0-beta.71", + "@ohif/extension-dicom-pdf": "3.9.0-beta.71", + "@ohif/extension-dicom-video": "3.9.0-beta.71", + "@ohif/extension-test": "3.9.0-beta.71", + "@ohif/i18n": "3.9.0-beta.71", + "@ohif/mode-basic-dev-mode": "3.9.0-beta.71", + "@ohif/mode-longitudinal": "3.9.0-beta.71", + "@ohif/mode-microscopy": "3.9.0-beta.71", + "@ohif/mode-test": "3.9.0-beta.71", + "@ohif/ui": "3.9.0-beta.71", + "@ohif/ui-next": "3.9.0-beta.71", + "@svgr/webpack": "^8.1.0", + "@types/react": "^18.3.3", "classnames": "^2.3.2", - "core-js": "^3.16.1", + "core-js": "*", "cornerstone-math": "^0.1.9", - "dcmjs": "^0.29.12", + "dcmjs": "*", "detect-gpu": "^4.0.16", "dicom-parser": "^1.8.9", "dotenv-webpack": "^1.7.0", + "file-loader": "^6.2.0", "hammerjs": "^2.0.8", "history": "^5.3.0", "i18next": "^17.0.3", "i18next-browser-languagedetector": "^3.0.1", "lodash.isequal": "4.5.0", "oidc-client": "1.11.5", + "oidc-client-ts": "^3.0.1", "prop-types": "^15.7.2", "query-string": "^6.12.1", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "react": "^18.3.1", + "react-dom": "^18.3.1", "react-dropzone": "^10.1.7", "react-i18next": "^12.2.2", - "react-resize-detector": "^9.1.0", - "react-router": "^6.8.1", - "react-router-dom": "^6.8.1" + "react-resize-detector": "^10.0.1", + "react-router": "^6.23.1", + "react-router-dom": "^6.8.1", + "url-loader": "^4.1.1" }, "devDependencies": { "@babel/plugin-proposal-private-methods": "^7.18.6", - "@percy/cypress": "^3.1.1", - "cypress": "13.7.2", - "cypress-file-upload": "^3.5.3", - "glob": "^8.0.3", + "@types/node": "^20.12.12", "identity-obj-proxy": "3.0.x", "lodash": "^4.17.21", - "tailwindcss": "3.2.4", - "terser-webpack-plugin": "^5.1.1", - "webpack": "^5.50.0", - "webpack-bundle-analyzer": "^4.4.2", - "webpack-cli": "^4.7.2", - "webpack-merge": "^5.7.3" + "tailwindcss": "3.2.4" } } diff --git a/platform/app/pluginConfig.json b/platform/app/pluginConfig.json index 3d022826a7..fefe449c93 100644 --- a/platform/app/pluginConfig.json +++ b/platform/app/pluginConfig.json @@ -22,6 +22,11 @@ "default": false, "version": "3.0.0" }, + { + "packageName": "@ohif/extension-cornerstone-dicom-pmap", + "default": false, + "version": "3.0.0" + }, { "packageName": "@ohif/extension-cornerstone-dynamic-volume", "default": false, @@ -96,6 +101,12 @@ "public": [ { "directory": "./platform/public" + }, + { + "packageName": "dicom-microscopy-viewer", + "importPath": "/dicom-microscopy-viewer/dicomMicroscopyViewer.min.js", + "globalName": "dicomMicroscopyViewer", + "directory": "./node_modules/dicom-microscopy-viewer/dist/dynamic-import" } ] } diff --git a/platform/app/public/config/aws.js b/platform/app/public/config/aws.js index f7dd9a0698..fdba3e035c 100644 --- a/platform/app/public/config/aws.js +++ b/platform/app/public/config/aws.js @@ -1,3 +1,5 @@ +/** @type {AppTypes.Config} */ + window.config = { routerBasename: '/', extensions: [], diff --git a/platform/app/public/config/customization.js b/platform/app/public/config/customization.js new file mode 100644 index 0000000000..39696c9b0d --- /dev/null +++ b/platform/app/public/config/customization.js @@ -0,0 +1,276 @@ +/** @type {AppTypes.Config} */ +window.config = { + routerBasename: '/', + extensions: [], + modes: ['@ohif/mode-test'], + showStudyList: true, + // below flag is for performance reasons, but it might not work for all servers + maxNumberOfWebWorkers: 3, + showWarningMessageForCrossOrigin: false, + showCPUFallbackMessage: false, + strictZSpacingForVolumeViewport: true, + // filterQueryParam: false, + + // Add some customizations to the default e2e datasource + customizationService: [ + '@ohif/extension-default.customizationModule.datasources', + '@ohif/extension-default.customizationModule.helloPage', + + { + id: '@ohif/cornerstoneOverlay', + // Append recursively, rather than replacing + merge: 'Append', + topRightItems: { + id: 'cornerstoneOverlayTopRight', + items: [ + { + id: 'PatientNameOverlay', + // Note below that here we are using the customization prototype of + // `ohif.overlayItem` which was registered to the customization module in + // `ohif/extension-default` extension. + customizationType: 'ohif.overlayItem', + // the following props are passed to the `ohif.overlayItem` prototype + // which is used to render the overlay item based on the label, color, + // conditions, etc. + attribute: 'PatientName', + label: 'PN:', + title: 'Patient Name', + color: 'yellow', + condition: ({ instance }) => instance?.PatientName, + contentF: ({ instance, formatters: { formatPN } }) => + formatPN(instance.PatientName) + + (instance.PatientSex ? ' (' + instance.PatientSex + ')' : ''), + }, + ], + }, + + topLeftItems: { + items: { + // Note the -10000 means -10000 + length of existing list, which is + // much before the start of hte list, so put the new value at the start. + '-10000': + { + id: 'Species', + customizationType: 'ohif.overlayItem', + label: 'Species:', + color: 'red', + background: 'green', + condition: ({ instance }) => + instance?.PatientSpeciesDescription, + contentF: ({ instance }) => + instance.PatientSpeciesDescription + + '/' + + instance.PatientBreedDescription, + }, + }, + }, + }, + ], + + defaultDataSourceName: 'e2e', + investigationalUseDialog: { + option: 'never', + }, + dataSources: [ + { + namespace: '@ohif/extension-default.dataSourcesModule.dicomweb', + sourceName: 'e2e', + configuration: { + friendlyName: 'StaticWado test data', + // The most important field to set for static WADO + staticWado: true, + name: 'StaticWADO', + wadoUriRoot: '/viewer-testdata', + qidoRoot: '/viewer-testdata', + wadoRoot: '/viewer-testdata', + qidoSupportsIncludeField: false, + imageRendering: 'wadors', + thumbnailRendering: 'wadors', + enableStudyLazyLoad: true, + supportsFuzzyMatching: false, + supportsWildcard: true, + singlepart: 'video,thumbnail,pdf', + omitQuotationForMultipartRequest: true, + bulkDataURI: { + enabled: true, + relativeResolution: 'studies', + }, + }, + }, + { + namespace: '@ohif/extension-default.dataSourcesModule.dicomweb', + sourceName: 'local5000', + configuration: { + friendlyName: 'Static WADO Local Data', + name: 'DCM4CHEE', + qidoRoot: 'http://localhost:5000/dicomweb', + wadoRoot: 'http://localhost:5000/dicomweb', + qidoSupportsIncludeField: false, + supportsReject: true, + supportsStow: true, + imageRendering: 'wadors', + thumbnailRendering: 'wadors', + enableStudyLazyLoad: true, + supportsFuzzyMatching: false, + supportsWildcard: true, + staticWado: true, + singlepart: 'video', + bulkDataURI: { + enabled: true, + relativeResolution: 'studies', + }, + }, + }, + { + namespace: '@ohif/extension-default.dataSourcesModule.dicomweb', + sourceName: 'docker', + configuration: { + friendlyName: 'Static WADO Docker Data', + name: 'DCM4CHEE', + qidoRoot: 'http://localhost:25080/dicomweb', + wadoRoot: 'http://localhost:25080/dicomweb', + qidoSupportsIncludeField: false, + supportsReject: true, + supportsStow: true, + imageRendering: 'wadors', + thumbnailRendering: 'wadors', + enableStudyLazyLoad: true, + supportsFuzzyMatching: false, + supportsWildcard: true, + staticWado: true, + singlepart: 'bulkdata,video,pdf', + bulkDataURI: { + enabled: true, + relativeResolution: 'studies', + }, + }, + }, + { + namespace: '@ohif/extension-default.dataSourcesModule.dicomweb', + sourceName: 'ohif', + configuration: { + friendlyName: 'AWS S3 Static wado server', + name: 'aws', + wadoUriRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb', + qidoRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb', + wadoRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb', + qidoSupportsIncludeField: false, + imageRendering: 'wadors', + thumbnailRendering: 'wadors', + enableStudyLazyLoad: true, + supportsFuzzyMatching: false, + supportsWildcard: true, + staticWado: true, + singlepart: 'video,pdf', + bulkDataURI: { + enabled: true, + relativeResolution: 'studies', + }, + }, + }, + + { + namespace: '@ohif/extension-default.dataSourcesModule.dicomweb', + sourceName: 'ohif2', + configuration: { + friendlyName: 'AWS S3 Static wado secondary server', + name: 'aws', + wadoUriRoot: 'https://d28o5kq0jsoob5.cloudfront.net/dicomweb', + qidoRoot: 'https://d28o5kq0jsoob5.cloudfront.net/dicomweb', + wadoRoot: 'https://d28o5kq0jsoob5.cloudfront.net/dicomweb', + qidoSupportsIncludeField: false, + supportsReject: false, + imageRendering: 'wadors', + thumbnailRendering: 'wadors', + enableStudyLazyLoad: true, + supportsFuzzyMatching: false, + supportsWildcard: true, + staticWado: true, + singlepart: 'bulkdata,video', + // whether the data source should use retrieveBulkData to grab metadata, + // and in case of relative path, what would it be relative to, options + // are in the series level or study level (some servers like series some study) + bulkDataURI: { + enabled: true, + relativeResolution: 'studies', + }, + omitQuotationForMultipartRequest: true, + }, + }, + { + namespace: '@ohif/extension-default.dataSourcesModule.dicomweb', + sourceName: 'ohif3', + configuration: { + friendlyName: 'AWS S3 Static wado secondary server', + name: 'aws', + wadoUriRoot: 'https://d3t6nz73ql33tx.cloudfront.net/dicomweb', + qidoRoot: 'https://d3t6nz73ql33tx.cloudfront.net/dicomweb', + wadoRoot: 'https://d3t6nz73ql33tx.cloudfront.net/dicomweb', + qidoSupportsIncludeField: false, + supportsReject: false, + imageRendering: 'wadors', + thumbnailRendering: 'wadors', + enableStudyLazyLoad: true, + supportsFuzzyMatching: false, + supportsWildcard: true, + staticWado: true, + singlepart: 'bulkdata,video', + // whether the data source should use retrieveBulkData to grab metadata, + // and in case of relative path, what would it be relative to, options + // are in the series level or study level (some servers like series some study) + bulkDataURI: { + enabled: true, + relativeResolution: 'studies', + }, + omitQuotationForMultipartRequest: true, + }, + }, + + { + friendlyName: 'StaticWado default data', + namespace: '@ohif/extension-default.dataSourcesModule.dicomweb', + sourceName: 'dicomweb', + configuration: { + name: 'DCM4CHEE', + wadoUriRoot: '/dicomweb', + qidoRoot: '/dicomweb', + wadoRoot: '/dicomweb', + qidoSupportsIncludeField: false, + supportsReject: false, + imageRendering: 'wadors', + thumbnailRendering: 'wadors', + enableStudyLazyLoad: true, + supportsFuzzyMatching: false, + supportsWildcard: true, + staticWado: true, + bulkDataURI: { + enabled: true, + relativeResolution: 'studies', + }, + }, + }, + { + namespace: '@ohif/extension-default.dataSourcesModule.dicomjson', + sourceName: 'dicomjson', + configuration: { + friendlyName: 'dicom json', + name: 'json', + }, + }, + { + namespace: '@ohif/extension-default.dataSourcesModule.dicomlocal', + sourceName: 'dicomlocal', + configuration: { + friendlyName: 'dicom local', + }, + }, + ], + httpErrorHandler: error => { + // This is 429 when rejected from the public idc sandbox too often. + console.warn(error.status); + + // Could use services manager here to bring up a dialog/modal if needed. + console.warn('test, navigate to https://ohif.org/'); + }, + hotkeys: [], +}; diff --git a/platform/app/public/config/default.js b/platform/app/public/config/default.js index 019fda669b..d9831f08a0 100644 --- a/platform/app/public/config/default.js +++ b/platform/app/public/config/default.js @@ -1,3 +1,5 @@ +/** @type {AppTypes.Config} */ + window.config = { routerBasename: '/', whiteLabeling: { @@ -27,6 +29,7 @@ window.config = { showWarningMessageForCrossOrigin: true, showCPUFallbackMessage: true, showLoadingIndicator: true, + experimentalStudyBrowserSort: false, strictZSpacingForVolumeViewport: true, groupEnabledModesFirst: true, maxNumRequests: { @@ -91,6 +94,7 @@ window.config = { }, }, }, + { friendlyName: 'Secondary GCP DICOMWeb Server', namespace: '@ohif/extension-default.dataSourcesModule.dicomweb', @@ -174,6 +178,60 @@ window.config = { omitQuotationForMultipartRequest: true, }, }, + { + namespace: '@ohif/extension-default.dataSourcesModule.dicomweb', + sourceName: 'ohif3', + configuration: { + friendlyName: 'AWS S3 Static wado secondary server', + name: 'aws', + wadoUriRoot: 'https://d3t6nz73ql33tx.cloudfront.net/dicomweb', + qidoRoot: 'https://d3t6nz73ql33tx.cloudfront.net/dicomweb', + wadoRoot: 'https://d3t6nz73ql33tx.cloudfront.net/dicomweb', + qidoSupportsIncludeField: false, + supportsReject: false, + imageRendering: 'wadors', + thumbnailRendering: 'wadors', + enableStudyLazyLoad: true, + supportsFuzzyMatching: false, + supportsWildcard: true, + staticWado: true, + singlepart: 'bulkdata,video', + // whether the data source should use retrieveBulkData to grab metadata, + // and in case of relative path, what would it be relative to, options + // are in the series level or study level (some servers like series some study) + bulkDataURI: { + enabled: true, + relativeResolution: 'studies', + }, + omitQuotationForMultipartRequest: true, + }, + }, + + { + namespace: '@ohif/extension-default.dataSourcesModule.dicomweb', + sourceName: 'local5000', + configuration: { + friendlyName: 'Static WADO Local Data', + name: 'DCM4CHEE', + qidoRoot: 'http://localhost:5000/dicomweb', + wadoRoot: 'http://localhost:5000/dicomweb', + qidoSupportsIncludeField: false, + supportsReject: true, + supportsStow: true, + imageRendering: 'wadors', + thumbnailRendering: 'wadors', + enableStudyLazyLoad: true, + supportsFuzzyMatching: false, + supportsWildcard: true, + staticWado: true, + singlepart: 'video', + bulkDataURI: { + enabled: true, + relativeResolution: 'studies', + }, + }, + }, + { namespace: '@ohif/extension-default.dataSourcesModule.dicomwebproxy', sourceName: 'dicomwebproxy', diff --git a/platform/app/public/config/default_16bit.js b/platform/app/public/config/default_16bit.js index 6ea7439990..4c11977ccc 100644 --- a/platform/app/public/config/default_16bit.js +++ b/platform/app/public/config/default_16bit.js @@ -1,3 +1,4 @@ +/** @type {AppTypes.Config} */ window.config = { routerBasename: '/', // whiteLabeling: {}, diff --git a/platform/app/public/config/demo.js b/platform/app/public/config/demo.js index 5dbd96ab15..d421506cd2 100644 --- a/platform/app/public/config/demo.js +++ b/platform/app/public/config/demo.js @@ -1,3 +1,4 @@ +/** @type {AppTypes.Config} */ window.config = { routerBasename: '/', modes: [], diff --git a/platform/app/public/config/docker_openresty-orthanc-keycloak.js b/platform/app/public/config/deprecated/docker_openresty-orthanc-keycloak.js similarity index 68% rename from platform/app/public/config/docker_openresty-orthanc-keycloak.js rename to platform/app/public/config/deprecated/docker_openresty-orthanc-keycloak.js index 5e9f7854f3..d93a853d14 100644 --- a/platform/app/public/config/docker_openresty-orthanc-keycloak.js +++ b/platform/app/public/config/deprecated/docker_openresty-orthanc-keycloak.js @@ -1,3 +1,4 @@ +/** @type {AppTypes.Config} */ window.config = { routerBasename: '/', showStudyList: true, @@ -35,19 +36,4 @@ window.config = { }, ], // This is an array, but we'll only use the first entry for now - oidc: [ - { - // ~ REQUIRED - // Authorization Server URL - authority: 'http://127.0.0.1/auth/realms/ohif', - client_id: 'ohif-viewer', - redirect_uri: 'http://127.0.0.1/callback', // `OHIFStandaloneViewer.js` - // "Authorization Code Flow" - // Resource: https://medium.com/@darutk/diagrams-of-all-the-openid-connect-flows-6968e3990660 - response_type: 'code', - scope: 'openid', // email profile openid - // ~ OPTIONAL - post_logout_redirect_uri: '/logout-redirect.html', - }, - ], }; diff --git a/platform/app/public/config/docker_openresty-orthanc.js b/platform/app/public/config/deprecated/docker_openresty-orthanc.js similarity index 97% rename from platform/app/public/config/docker_openresty-orthanc.js rename to platform/app/public/config/deprecated/docker_openresty-orthanc.js index 2500760bf2..1acdff5044 100644 --- a/platform/app/public/config/docker_openresty-orthanc.js +++ b/platform/app/public/config/deprecated/docker_openresty-orthanc.js @@ -1,3 +1,4 @@ +/** @type {AppTypes.Config} */ window.config = { routerBasename: '/', showStudyList: true, diff --git a/platform/app/public/config/dicomweb-server.js b/platform/app/public/config/dicomweb-server.js index a3522e587c..874e7507d4 100644 --- a/platform/app/public/config/dicomweb-server.js +++ b/platform/app/public/config/dicomweb-server.js @@ -1,3 +1,4 @@ +/** @type {AppTypes.Config} */ window.config = { routerBasename: '/', extensions: [], diff --git a/platform/app/public/config/dicomweb_relative.js b/platform/app/public/config/dicomweb_relative.js index bfa51c34ae..69752ea3a7 100644 --- a/platform/app/public/config/dicomweb_relative.js +++ b/platform/app/public/config/dicomweb_relative.js @@ -1,3 +1,4 @@ +/** @type {AppTypes.Config} */ window.config = { routerBasename: '/', extensions: [], diff --git a/platform/app/public/config/docker-nginx-dcm4chee-keycloak.js b/platform/app/public/config/docker-nginx-dcm4chee-keycloak.js new file mode 100644 index 0000000000..163703b7a3 --- /dev/null +++ b/platform/app/public/config/docker-nginx-dcm4chee-keycloak.js @@ -0,0 +1,35 @@ +/** @type {AppTypes.Config} */ +window.config = { + routerBasename: '/ohif-viewer/', + showStudyList: true, + customizationService: { + dicomUploadComponent: + '@ohif/extension-cornerstone.customizationModule.cornerstoneDicomUploadComponent', + }, + extensions: [], + modes: [], + // below flag is for performance reasons, but it might not work for all servers + showWarningMessageForCrossOrigin: true, + showCPUFallbackMessage: true, + showLoadingIndicator: true, + strictZSpacingForVolumeViewport: true, + defaultDataSourceName: 'dicomweb', + dataSources: [ + { + namespace: '@ohif/extension-default.dataSourcesModule.dicomweb', + sourceName: 'dicomweb', + configuration: { + friendlyName: 'Dcm4chee Server', + name: 'Dcm4chee', + wadoUriRoot: 'http://127.0.0.1/pacs', + qidoRoot: 'http://127.0.0.1/pacs', + wadoRoot: 'http://127.0.0.1/pacs', + qidoSupportsIncludeField: false, + imageRendering: 'wadors', + thumbnailRendering: 'wadors', + dicomUploadEnabled: true, + omitQuotationForMultipartRequest: true, + }, + }, + ], +}; diff --git a/platform/app/public/config/docker-nginx-dcm4chee.js b/platform/app/public/config/docker-nginx-dcm4chee.js new file mode 100644 index 0000000000..6d7e9fc473 --- /dev/null +++ b/platform/app/public/config/docker-nginx-dcm4chee.js @@ -0,0 +1,35 @@ +/** @type {AppTypes.Config} */ +window.config = { + routerBasename: '/', + showStudyList: true, + customizationService: { + dicomUploadComponent: + '@ohif/extension-cornerstone.customizationModule.cornerstoneDicomUploadComponent', + }, + extensions: [], + modes: [], + // below flag is for performance reasons, but it might not work for all servers + showWarningMessageForCrossOrigin: true, + showCPUFallbackMessage: true, + showLoadingIndicator: true, + strictZSpacingForVolumeViewport: true, + defaultDataSourceName: 'dicomweb', + dataSources: [ + { + namespace: '@ohif/extension-default.dataSourcesModule.dicomweb', + sourceName: 'dicomweb', + configuration: { + friendlyName: 'Dcm4chee Server', + name: 'Dcm4chee', + wadoUriRoot: '/dcm4chee-arc/aets/DCM4CHEE/wado', + qidoRoot: '/dcm4chee-arc/aets/DCM4CHEE/rs', + wadoRoot: '/dcm4chee-arc/aets/DCM4CHEE/rs', + qidoSupportsIncludeField: false, + imageRendering: 'wadors', + thumbnailRendering: 'wadors', + dicomUploadEnabled: true, + omitQuotationForMultipartRequest: true, + }, + }, + ], +}; diff --git a/platform/app/public/config/docker-nginx-orthanc-keycloak.js b/platform/app/public/config/docker-nginx-orthanc-keycloak.js new file mode 100644 index 0000000000..3a8b60a2c4 --- /dev/null +++ b/platform/app/public/config/docker-nginx-orthanc-keycloak.js @@ -0,0 +1,52 @@ +/** @type {AppTypes.Config} */ +window.config = { + routerBasename: '/ohif-viewer', + extensions: [], + modes: [], + customizationService: {}, + showStudyList: true, + maxNumberOfWebWorkers: 3, + showWarningMessageForCrossOrigin: true, + showCPUFallbackMessage: true, + showLoadingIndicator: true, + strictZSpacingForVolumeViewport: true, + groupEnabledModesFirst: true, + maxNumRequests: { + interaction: 100, + thumbnail: 75, + prefetch: 25, + }, + defaultDataSourceName: 'dicomweb', + dataSources: [ + { + namespace: '@ohif/extension-default.dataSourcesModule.dicomweb', + sourceName: 'dicomweb', + configuration: { + friendlyName: 'Local Orthanc', + name: 'Orthanc', + wadoUriRoot: 'http://127.0.0.1/pacs', + qidoRoot: 'http://127.0.0.1/pacs', + wadoRoot: 'http://127.0.0.1/pacs', + qidoSupportsIncludeField: false, + imageRendering: 'wadors', + thumbnailRendering: 'wadors', + enableStudyLazyLoad: true, + supportsFuzzyMatching: false, + supportsWildcard: true, + staticWado: true, + singlepart: 'bulkdata,video', + // whether the data source should use retrieveBulkData to grab metadata, + // and in case of relative path, what would it be relative to, options + // are in the series level or study level (some servers like series some study) + bulkDataURI: { + enabled: true, + }, + omitQuotationForMultipartRequest: true, + }, + }, + ], + httpErrorHandler: error => { + console.warn(error.status); + console.warn('test, navigate to https://ohif.org/'); + }, +}; diff --git a/platform/app/public/config/docker_nginx-orthanc.js b/platform/app/public/config/docker-nginx-orthanc.js similarity index 67% rename from platform/app/public/config/docker_nginx-orthanc.js rename to platform/app/public/config/docker-nginx-orthanc.js index 97316bc8ad..7a480ea89e 100644 --- a/platform/app/public/config/docker_nginx-orthanc.js +++ b/platform/app/public/config/docker-nginx-orthanc.js @@ -1,13 +1,25 @@ +/** @type {AppTypes.Config} */ window.config = { routerBasename: '/', showStudyList: true, + customizationService: { + dicomUploadComponent: + '@ohif/extension-cornerstone.customizationModule.cornerstoneDicomUploadComponent', + }, extensions: [], modes: [], // below flag is for performance reasons, but it might not work for all servers showWarningMessageForCrossOrigin: true, showCPUFallbackMessage: true, showLoadingIndicator: true, + experimentalStudyBrowserSort: false, strictZSpacingForVolumeViewport: true, + studyPrefetcher: { + enabled: true, + displaySetsCount: 2, + maxNumPrefetchRequests: 10, + order: 'closest', + }, defaultDataSourceName: 'dicomweb', dataSources: [ { @@ -17,11 +29,12 @@ window.config = { friendlyName: 'Orthanc Server', name: 'Orthanc', wadoUriRoot: '/wado', - qidoRoot: '/dicom-web', - wadoRoot: '/dicom-web', + qidoRoot: '/pacs/dicom-web', + wadoRoot: '/pacs/dicom-web', qidoSupportsIncludeField: false, imageRendering: 'wadors', thumbnailRendering: 'wadors', + dicomUploadEnabled: true, omitQuotationForMultipartRequest: true, }, }, @@ -41,4 +54,7 @@ window.config = { }, }, ], + httpErrorHandler: error => { + console.warn(`HTTP Error Handler (status: ${error.status})`, error); + }, }; diff --git a/platform/app/public/config/e2e.js b/platform/app/public/config/e2e.js index 90827b906c..ed7dcdc75c 100644 --- a/platform/app/public/config/e2e.js +++ b/platform/app/public/config/e2e.js @@ -1,3 +1,4 @@ +/** @type {AppTypes.Config} */ window.config = { routerBasename: '/', extensions: [], @@ -9,6 +10,13 @@ window.config = { showCPUFallbackMessage: false, strictZSpacingForVolumeViewport: true, // filterQueryParam: false, + + // Add some customizations to the default e2e datasource + customizationService: [ + '@ohif/extension-default.customizationModule.datasources', + '@ohif/extension-default.customizationModule.helloPage', + ], + defaultDataSourceName: 'e2e', investigationalUseDialog: { option: 'never', @@ -41,7 +49,7 @@ window.config = { }, { namespace: '@ohif/extension-default.dataSourcesModule.dicomweb', - sourceName: 'local', + sourceName: 'local5000', configuration: { friendlyName: 'Static WADO Local Data', name: 'DCM4CHEE', @@ -110,6 +118,64 @@ window.config = { }, }, }, + + { + namespace: '@ohif/extension-default.dataSourcesModule.dicomweb', + sourceName: 'ohif2', + configuration: { + friendlyName: 'AWS S3 Static wado secondary server', + name: 'aws', + wadoUriRoot: 'https://d28o5kq0jsoob5.cloudfront.net/dicomweb', + qidoRoot: 'https://d28o5kq0jsoob5.cloudfront.net/dicomweb', + wadoRoot: 'https://d28o5kq0jsoob5.cloudfront.net/dicomweb', + qidoSupportsIncludeField: false, + supportsReject: false, + imageRendering: 'wadors', + thumbnailRendering: 'wadors', + enableStudyLazyLoad: true, + supportsFuzzyMatching: false, + supportsWildcard: true, + staticWado: true, + singlepart: 'bulkdata,video', + // whether the data source should use retrieveBulkData to grab metadata, + // and in case of relative path, what would it be relative to, options + // are in the series level or study level (some servers like series some study) + bulkDataURI: { + enabled: true, + relativeResolution: 'studies', + }, + omitQuotationForMultipartRequest: true, + }, + }, + { + namespace: '@ohif/extension-default.dataSourcesModule.dicomweb', + sourceName: 'ohif3', + configuration: { + friendlyName: 'AWS S3 Static wado secondary server', + name: 'aws', + wadoUriRoot: 'https://d3t6nz73ql33tx.cloudfront.net/dicomweb', + qidoRoot: 'https://d3t6nz73ql33tx.cloudfront.net/dicomweb', + wadoRoot: 'https://d3t6nz73ql33tx.cloudfront.net/dicomweb', + qidoSupportsIncludeField: false, + supportsReject: false, + imageRendering: 'wadors', + thumbnailRendering: 'wadors', + enableStudyLazyLoad: true, + supportsFuzzyMatching: false, + supportsWildcard: true, + staticWado: true, + singlepart: 'bulkdata,video', + // whether the data source should use retrieveBulkData to grab metadata, + // and in case of relative path, what would it be relative to, options + // are in the series level or study level (some servers like series some study) + bulkDataURI: { + enabled: true, + relativeResolution: 'studies', + }, + omitQuotationForMultipartRequest: true, + }, + }, + { friendlyName: 'StaticWado default data', namespace: '@ohif/extension-default.dataSourcesModule.dicomweb', diff --git a/platform/app/public/config/google.js b/platform/app/public/config/google.js index b380a21a72..e416a9e811 100644 --- a/platform/app/public/config/google.js +++ b/platform/app/public/config/google.js @@ -1,3 +1,4 @@ +/** @type {AppTypes.Config} */ window.config = { routerBasename: '/', customizationService: { diff --git a/platform/app/public/config/idc.js b/platform/app/public/config/idc.js index 0089182ee9..5f08c83e5b 100644 --- a/platform/app/public/config/idc.js +++ b/platform/app/public/config/idc.js @@ -1,3 +1,4 @@ +/** @type {AppTypes.Config} */ window.config = { routerBasename: '/', enableGoogleCloudAdapter: true, diff --git a/platform/app/public/config/local_dcm4chee.js b/platform/app/public/config/local_dcm4chee.js index a521bfef06..5148bf4a4a 100644 --- a/platform/app/public/config/local_dcm4chee.js +++ b/platform/app/public/config/local_dcm4chee.js @@ -1,3 +1,4 @@ +/** @type {AppTypes.Config} */ window.config = { routerBasename: '/', customizationService: { diff --git a/platform/app/public/config/local_orthanc.js b/platform/app/public/config/local_orthanc.js index 9fd18992cd..9fa52fe6bc 100644 --- a/platform/app/public/config/local_orthanc.js +++ b/platform/app/public/config/local_orthanc.js @@ -1,3 +1,4 @@ +/** @type {AppTypes.Config} */ window.config = { routerBasename: '/', extensions: [], @@ -13,11 +14,11 @@ window.config = { showCPUFallbackMessage: true, strictZSpacingForVolumeViewport: true, // filterQueryParam: false, - defaultDataSourceName: 'dicomweb', + defaultDataSourceName: 'orthanc', dataSources: [ { namespace: '@ohif/extension-default.dataSourcesModule.dicomweb', - sourceName: 'dicomweb', + sourceName: 'orthanc', configuration: { friendlyName: 'local Orthanc DICOMWeb Server', name: 'DCM4CHEE', @@ -29,13 +30,23 @@ window.config = { imageRendering: 'wadors', thumbnailRendering: 'wadors', enableStudyLazyLoad: true, - useBulkDataURI: false, supportsFuzzyMatching: true, supportsWildcard: true, dicomUploadEnabled: true, omitQuotationForMultipartRequest: true, bulkDataURI: { enabled: true, + // This is an example config that can be used to fix the retrieve URL + // where it has the wrong prefix (eg a canned prefix). It is better to + // just use the correct prefix out of the box, but that is sometimes hard + // when URLs go through several systems. + // Example URLS are: + // "BulkDataURI" : "http://localhost/dicom-web/studies/1.2.276.0.7230010.3.1.2.2344313775.14992.1458058363.6979/series/1.2.276.0.7230010.3.1.3.1901948703.36080.1484835349.617/instances/1.2.276.0.7230010.3.1.4.1901948703.36080.1484835349.618/bulk/00420011", + // when running on http://localhost:3003 with no server running on localhost. This can be corrected to: + // /orthanc/dicom-web/studies/1.2.276.0.7230010.3.1.2.2344313775.14992.1458058363.6979/series/1.2.276.0.7230010.3.1.3.1901948703.36080.1484835349.617/instances/1.2.276.0.7230010.3.1.4.1901948703.36080.1484835349.618/bulk/00420011 + // which is a valid relative URL, and will result in using the http://localhost:3003/orthanc/.... path + // startsWith: 'http://localhost/', + // prefixWith: '/orthanc/', }, }, }, diff --git a/platform/app/public/config/local_static.js b/platform/app/public/config/local_static.js index 7bd03c87eb..2e2131c0b0 100644 --- a/platform/app/public/config/local_static.js +++ b/platform/app/public/config/local_static.js @@ -1,3 +1,4 @@ +/** @type {AppTypes.Config} */ window.config = { routerBasename: '/', customizationService: ['@ohif/extension-default.customizationModule.helloPage'], diff --git a/platform/app/public/config/multiple.js b/platform/app/public/config/multiple.js index 57684a9ef5..d02715d2e7 100644 --- a/platform/app/public/config/multiple.js +++ b/platform/app/public/config/multiple.js @@ -1,3 +1,4 @@ +/** @type {AppTypes.Config} */ window.config = { // Activate the new HP mode.... isNewHP: true, diff --git a/platform/app/public/config/netlify.js b/platform/app/public/config/netlify.js index e4907a839f..ce5ec9e3a8 100644 --- a/platform/app/public/config/netlify.js +++ b/platform/app/public/config/netlify.js @@ -1,3 +1,5 @@ +/** @type {AppTypes.Config} */ + window.config = { routerBasename: '/', extensions: [], @@ -7,14 +9,15 @@ window.config = { showWarningMessageForCrossOrigin: true, showCPUFallbackMessage: true, showLoadingIndicator: true, + experimentalStudyBrowserSort: false, strictZSpacingForVolumeViewport: true, groupEnabledModesFirst: true, // filterQueryParam: false, - defaultDataSourceName: 'dicomweb', + defaultDataSourceName: 'ohif', dataSources: [ { namespace: '@ohif/extension-default.dataSourcesModule.dicomweb', - sourceName: 'dicomweb', + sourceName: 'ohif', configuration: { friendlyName: 'AWS S3 Static wado server', name: 'aws', @@ -39,9 +42,10 @@ window.config = { omitQuotationForMultipartRequest: true, }, }, + { namespace: '@ohif/extension-default.dataSourcesModule.dicomweb', - sourceName: 'dicomweb2', + sourceName: 'ohif2', configuration: { friendlyName: 'AWS S3 Static wado secondary server', name: 'aws', @@ -67,6 +71,61 @@ window.config = { omitQuotationForMultipartRequest: true, }, }, + + { + namespace: '@ohif/extension-default.dataSourcesModule.dicomweb', + sourceName: 'ohif3', + configuration: { + friendlyName: 'AWS S3 Static wado secondary server', + name: 'aws', + wadoUriRoot: 'https://d3t6nz73ql33tx.cloudfront.net/dicomweb', + qidoRoot: 'https://d3t6nz73ql33tx.cloudfront.net/dicomweb', + wadoRoot: 'https://d3t6nz73ql33tx.cloudfront.net/dicomweb', + qidoSupportsIncludeField: false, + supportsReject: false, + imageRendering: 'wadors', + thumbnailRendering: 'wadors', + enableStudyLazyLoad: true, + supportsFuzzyMatching: false, + supportsWildcard: true, + staticWado: true, + singlepart: 'bulkdata,video', + // whether the data source should use retrieveBulkData to grab metadata, + // and in case of relative path, what would it be relative to, options + // are in the series level or study level (some servers like series some study) + bulkDataURI: { + enabled: true, + relativeResolution: 'studies', + }, + omitQuotationForMultipartRequest: true, + }, + }, + + { + namespace: '@ohif/extension-default.dataSourcesModule.dicomweb', + sourceName: 'local5000', + configuration: { + friendlyName: 'Static WADO Local Data', + name: 'DCM4CHEE', + qidoRoot: 'http://localhost:5000/dicomweb', + wadoRoot: 'http://localhost:5000/dicomweb', + qidoSupportsIncludeField: false, + supportsReject: true, + supportsStow: true, + imageRendering: 'wadors', + thumbnailRendering: 'wadors', + enableStudyLazyLoad: true, + supportsFuzzyMatching: false, + supportsWildcard: true, + staticWado: true, + singlepart: 'video', + bulkDataURI: { + enabled: true, + relativeResolution: 'studies', + }, + }, + }, + { namespace: '@ohif/extension-default.dataSourcesModule.dicomjson', sourceName: 'dicomjson', diff --git a/platform/app/public/html-templates/index.html b/platform/app/public/html-templates/index.html index dd61a8af9b..25e718e79b 100644 --- a/platform/app/public/html-templates/index.html +++ b/platform/app/public/html-templates/index.html @@ -183,10 +183,6 @@ href="<%= PUBLIC_URL %>assets/yandex-browser-manifest.json" /> - - - + - - diff --git a/platform/app/src/App.tsx b/platform/app/src/App.tsx index ec170ab40f..13b6fecc4e 100644 --- a/platform/app/src/App.tsx +++ b/platform/app/src/App.tsx @@ -1,4 +1,5 @@ // External + import React, { useEffect, useState } from 'react'; import PropTypes from 'prop-types'; import i18n from '@ohif/i18n'; @@ -6,7 +7,6 @@ import { I18nextProvider } from 'react-i18next'; import { BrowserRouter } from 'react-router-dom'; import Compose from './routes/Mode/Compose'; import { - ServicesManager, ExtensionManager, CommandsManager, HotkeysManager, @@ -24,6 +24,7 @@ import { UserAuthenticationProvider, ToolboxProvider, } from '@ohif/ui'; +import { ThemeWrapper as ThemeWrapperNext } from '@ohif/ui-next'; // Viewer Project // TODO: Should this influence study list? import { AppConfigProvider } from '@state'; @@ -33,11 +34,31 @@ import OpenIdConnectRoutes from './utils/OpenIdConnectRoutes'; let commandsManager: CommandsManager, extensionManager: ExtensionManager, - servicesManager: ServicesManager, + servicesManager: AppTypes.ServicesManager, serviceProvidersManager: ServiceProvidersManager, hotkeysManager: HotkeysManager; -function App({ config, defaultExtensions, defaultModes }) { +function App({ + config = { + /** + * Relative route from domain root that OHIF instance is installed at. + * For example: + * + * Hosted at: https://ohif.org/where-i-host-the/viewer/ + * Value: `/where-i-host-the/viewer/` + * */ + routerBaseName: '/', + /** + * + */ + showLoadingIndicator: true, + showStudyList: true, + oidc: [], + extensions: [], + }, + defaultExtensions = [], + defaultModes = [], +}) { const [init, setInit] = useState(null); useEffect(() => { const run = async () => { @@ -62,6 +83,13 @@ function App({ config, defaultExtensions, defaultModes }) { const appConfigState = init.appConfig; const { routerBasename, modes, dataSources, oidc, showStudyList } = appConfigState; + // get the maximum 3D texture size + const canvas = document.createElement('canvas'); + const gl = canvas.getContext('webgl2'); + + const max3DTextureSize = gl.getParameter(gl.MAX_3D_TEXTURE_SIZE); + appConfigState.max3DTextureSize = max3DTextureSize; + const { uiDialogService, uiModalService, @@ -77,11 +105,13 @@ function App({ config, defaultExtensions, defaultModes }) { [AppConfigProvider, { value: appConfigState }], [UserAuthenticationProvider, { service: userAuthenticationService }], [I18nextProvider, { i18n }], + [ThemeWrapperNext], [ThemeWrapper], [ToolboxProvider], [ViewportGridProvider, { service: viewportGridService }], [ViewportDialogProvider, { service: uiViewportDialogService }], [CineProvider, { service: cineService }], + // [NotificationProvider, { service: uiNotificationService }], [SnackbarProvider, { service: uiNotificationService }], [DialogProvider, { service: uiDialogService }], [ModalProvider, { service: uiModalService, modal: Modal }], @@ -147,27 +177,9 @@ App.propTypes = { /* Extensions that are "bundled" or "baked-in" to the application. * These would be provided at build time as part of they entry point. */ defaultExtensions: PropTypes.array, -}; - -App.defaultProps = { - config: { - /** - * Relative route from domain root that OHIF instance is installed at. - * For example: - * - * Hosted at: https://ohif.org/where-i-host-the/viewer/ - * Value: `/where-i-host-the/viewer/` - * */ - routerBaseName: '/', - /** - * - */ - showLoadingIndicator: true, - showStudyList: true, - oidc: [], - extensions: [], - }, - defaultExtensions: [], + /* Modes that are "bundled" or "baked-in" to the application. + * These would be provided at build time as part of they entry point. */ + defaultModes: PropTypes.array, }; export default App; diff --git a/platform/app/src/appInit.js b/platform/app/src/appInit.js index 4e26eee214..60f5ee4db2 100644 --- a/platform/app/src/appInit.js +++ b/platform/app/src/appInit.js @@ -20,10 +20,11 @@ import { CustomizationService, PanelService, WorkflowStepsService, + StudyPrefetcherService, // utils, } from '@ohif/core'; -import loadModules from './pluginImports'; +import loadModules, { loadModule as peerImport } from './pluginImports'; /** * @param {object|func} appConfigOrFunc - application configuration, or a function that returns application configuration @@ -41,9 +42,11 @@ async function appInit(appConfigOrFunc, defaultExtensions, defaultModes) { const appConfig = { ...(typeof appConfigOrFunc === 'function' - ? await appConfigOrFunc({ servicesManager }) + ? await appConfigOrFunc({ servicesManager, peerImport }) : appConfigOrFunc), }; + // Default the peer import function + appConfig.peerImport ||= peerImport; const extensionManager = new ExtensionManager({ commandsManager, @@ -71,6 +74,7 @@ async function appInit(appConfigOrFunc, defaultExtensions, defaultModes) { PanelService.REGISTRATION, WorkflowStepsService.REGISTRATION, StateSyncService.REGISTRATION, + [StudyPrefetcherService.REGISTRATION, appConfig.studyPrefetcher], ]); errorHandler.getHTTPErrorHandler = () => { @@ -113,7 +117,7 @@ async function appInit(appConfigOrFunc, defaultExtensions, defaultModes) { ? appConfig.modesConfiguration[id] : {}; - mode = mode.modeFactory({ modeConfiguration }); + mode = await mode.modeFactory({ modeConfiguration, loadModules }); } if (modesById.has(id)) { diff --git a/platform/app/src/components/ViewportGrid.tsx b/platform/app/src/components/ViewportGrid.tsx index ab0e09112d..807b2072da 100644 --- a/platform/app/src/components/ViewportGrid.tsx +++ b/platform/app/src/components/ViewportGrid.tsx @@ -1,26 +1,31 @@ import React, { useEffect, useCallback, useRef, useState } from 'react'; -import ReactResizeDetector from 'react-resize-detector'; +import { useResizeDetector } from 'react-resize-detector'; import PropTypes from 'prop-types'; -import { ServicesManager, Types, MeasurementService } from '@ohif/core'; +import { Types, MeasurementService } from '@ohif/core'; import { ViewportGrid, ViewportPane, useViewportGrid } from '@ohif/ui'; import EmptyViewport from './EmptyViewport'; import classNames from 'classnames'; import { useAppConfig } from '@state'; -function ViewerViewportGrid(props) { - const { servicesManager, viewportComponents, dataSource } = props; +function ViewerViewportGrid(props: withAppTypes) { + const { servicesManager, viewportComponents = [], dataSource } = props; const [viewportGrid, viewportGridService] = useViewportGrid(); const [appConfig] = useAppConfig(); const { layout, activeViewportId, viewports, isHangingProtocolLayout } = viewportGrid; const { numCols, numRows } = layout; - const elementRef = useRef(null); + const { ref: resizeRef } = useResizeDetector({ + refreshMode: 'debounce', + refreshRate: 7, + refreshOptions: { leading: true }, + onResize: () => { + viewportGridService.setViewportGridSizeChanged(); + }, + }); const layoutHash = useRef(null); - // TODO -> Need some way of selecting which displaySets hit the viewports. - const { displaySetService, measurementService, hangingProtocolService, uiNotificationService } = ( - servicesManager as ServicesManager - ).services; + const { displaySetService, measurementService, hangingProtocolService, uiNotificationService } = + servicesManager.services; const generateLayoutHash = () => `${numCols}-${numRows}`; @@ -103,20 +108,12 @@ function ViewerViewportGrid(props) { const _getUpdatedViewports = useCallback( (viewportId, displaySetInstanceUID) => { - if (!isHangingProtocolLayout) { - return [ - { - viewportId, - displaySetInstanceUIDs: [displaySetInstanceUID], - }, - ]; - } - let updatedViewports = []; try { updatedViewports = hangingProtocolService.getViewportsRequireUpdate( viewportId, - displaySetInstanceUID + displaySetInstanceUID, + isHangingProtocolLayout ); } catch (error) { console.warn(error); @@ -207,50 +204,6 @@ function ViewerViewportGrid(props) { }; }, [viewports]); - /** - const onDoubleClick = viewportId => { - // TODO -> Disabled for now. - // onNewImage on a cornerstone viewport is firing setDisplaySetsForViewport. - // Which it really really shouldn't. We need a larger fix for jump to - // measurements and all cornerstone "imageIndex" state to fix this. - if (cachedLayout) { - viewportGridService.set({ - numCols: cachedLayout.numCols, - numRows: cachedLayout.numRows, - activeViewportId: cachedLayout.activeViewportId, - viewports: cachedLayout.viewports, - cachedLayout: null, - }); - - return; - } - - const cachedViewports = viewports.map(viewport => { - return { - displaySetInstanceUID: viewport.displaySetInstanceUID, - }; - }); - - viewportGridService.set({ - numCols: 1, - numRows: 1, - activeViewportId: 0, - viewports: [ - { - displaySetInstanceUID: viewports[viewportId].displaySetInstanceUID, - imageIndex: undefined, - }, - ], - cachedLayout: { - numCols, - numRows, - viewports: cachedViewports, - activeViewportId: viewportId, - }, - }); - }; - */ - const onDropHandler = (viewportId, { displaySetInstanceUID }) => { const updatedViewports = _getUpdatedViewports(viewportId, displaySetInstanceUID); viewportGridService.setDisplaySetsForViewports(updatedViewports); @@ -372,21 +325,13 @@ function ViewerViewportGrid(props) { return (
- { - viewportGridService.setViewportGridSizeChanged(); - }} - targetRef={elementRef.current} - /> {getViewportPanes()}
@@ -395,11 +340,7 @@ function ViewerViewportGrid(props) { ViewerViewportGrid.propTypes = { viewportComponents: PropTypes.array.isRequired, - servicesManager: PropTypes.instanceOf(ServicesManager), -}; - -ViewerViewportGrid.defaultProps = { - viewportComponents: [], + servicesManager: PropTypes.instanceOf(Object).isRequired, }; function _getViewportComponent(displaySets, viewportComponents, uiNotificationService) { diff --git a/platform/app/src/index.js b/platform/app/src/index.js index 7b8d63324d..20b4cac7c4 100644 --- a/platform/app/src/index.js +++ b/platform/app/src/index.js @@ -2,9 +2,9 @@ * Entry point for development and production PWA builds. */ import 'regenerator-runtime/runtime'; +import { createRoot } from 'react-dom/client'; import App from './App'; import React from 'react'; -import ReactDOM from 'react-dom'; import { history } from './utils/history'; /** @@ -35,10 +35,10 @@ loadDynamicConfig(window.config).then(config_json => { defaultModes, }; - /** Create App */ - const app = React.createElement(App, appProps, null); - /** Render */ - ReactDOM.render(app, document.getElementById('root')); + const container = document.getElementById('root'); + + const root = createRoot(container); + root.render(React.createElement(App, appProps)); }); export { history }; diff --git a/platform/app/src/routes/CallbackPage.tsx b/platform/app/src/routes/CallbackPage.tsx index 74474552fb..bf938ecaae 100644 --- a/platform/app/src/routes/CallbackPage.tsx +++ b/platform/app/src/routes/CallbackPage.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useEffect } from 'react'; import PropTypes from 'prop-types'; function CallbackPage({ userManager, onRedirectSuccess }) { @@ -6,10 +6,12 @@ function CallbackPage({ userManager, onRedirectSuccess }) { throw new Error(error); }; - userManager - .signinRedirectCallback() - .then(user => onRedirectSuccess(user)) - .catch(error => onRedirectError(error)); + useEffect(() => { + userManager + .signinRedirectCallback() + .then(user => onRedirectSuccess(user)) + .catch(error => onRedirectError(error)); + }, [userManager, onRedirectSuccess]); return null; } diff --git a/platform/app/src/routes/DataSourceWrapper.tsx b/platform/app/src/routes/DataSourceWrapper.tsx index 0ae2b698ed..f391fe6fc4 100644 --- a/platform/app/src/routes/DataSourceWrapper.tsx +++ b/platform/app/src/routes/DataSourceWrapper.tsx @@ -27,7 +27,8 @@ const areLocationsTheSame = (location0, location1) => { * @param {object} props * @param {function} props.children - Layout Template React Component */ -function DataSourceWrapper(props) { +function DataSourceWrapper(props: withAppTypes) { + const { servicesManager } = props; const navigate = useNavigate(); const { children: LayoutTemplate, ...rest } = props; const params = useParams(); @@ -188,14 +189,29 @@ function DataSourceWrapper(props) { if (isDataInvalid) { getData().catch(e => { console.error(e); + + const { configurationAPI, friendlyName } = dataSource.getConfig(); // If there is a data source configuration API, then the Worklist will popup the dialog to attempt to configure it // and attempt to resolve this issue. - if (dataSource.getConfig().configurationAPI) { + if (configurationAPI) { return; } - // No data source configuration API, so navigate to the not found server page. - navigate('/notfoundserver', '_self'); + servicesManager.services.uiModalService.show({ + title: 'Data Source Connection Error', + containerDimensions: 'w-1/2', + content: () => { + return ( +
+

Error: {e.message}

+

+ Please ensure the following data source is configured correctly or is running: +

+
{friendlyName}
+
+ ); + }, + }); }); } } catch (ex) { @@ -234,29 +250,34 @@ export default DataSourceWrapper; */ function _getQueryFilterValues(query, queryLimit) { query = new URLSearchParams(query); + const newParams = new URLSearchParams(); + for (const [key, value] of query) { + newParams.set(key.toLowerCase(), value); + } + query = newParams; - const pageNumber = _tryParseInt(query.get('pageNumber'), 1); - const resultsPerPage = _tryParseInt(query.get('resultsPerPage'), 25); + const pageNumber = _tryParseInt(query.get('pagenumber'), 1); + const resultsPerPage = _tryParseInt(query.get('resultsperpage'), 25); const queryFilterValues = { // DCM patientId: query.get('mrn'), - patientName: query.get('patientName'), + patientName: query.get('patientname'), studyDescription: query.get('description'), modalitiesInStudy: query.get('modalities') && query.get('modalities').split(','), accessionNumber: query.get('accession'), // - startDate: query.get('startDate'), - endDate: query.get('endDate'), + startDate: query.get('startdate'), + endDate: query.get('enddate'), page: _tryParseInt(query.get('page'), undefined), pageNumber, resultsPerPage, // Rarely supported server-side - sortBy: query.get('sortBy'), - sortDirection: query.get('sortDirection'), + sortBy: query.get('sortby'), + sortDirection: query.get('sortdirection'), // Offset... offset: Math.floor((pageNumber * resultsPerPage) / queryLimit) * (queryLimit - 1), - config: query.get('configUrl'), + config: query.get('configurl'), }; // patientName: good diff --git a/platform/app/src/routes/Local/Local.tsx b/platform/app/src/routes/Local/Local.tsx index bea60c2683..1804cd7fe1 100644 --- a/platform/app/src/routes/Local/Local.tsx +++ b/platform/app/src/routes/Local/Local.tsx @@ -125,11 +125,12 @@ function Local({ modePath }: LocalProps) { >
- OHIF +
+ +
{dropInitiated ? (
diff --git a/platform/app/src/routes/Mode/Mode.tsx b/platform/app/src/routes/Mode/Mode.tsx index 023d1588b5..574520748e 100644 --- a/platform/app/src/routes/Mode/Mode.tsx +++ b/platform/app/src/routes/Mode/Mode.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useState, useRef } from 'react'; import { useParams, useLocation, useNavigate } from 'react-router'; import PropTypes from 'prop-types'; -import { ServicesManager, utils } from '@ohif/core'; +import { utils } from '@ohif/core'; import { DragAndDropProvider, ImageViewerProvider } from '@ohif/ui'; import { useSearchParams } from '@hooks'; import { useAppConfig } from '@state'; @@ -21,7 +21,7 @@ export default function ModeRoute({ servicesManager, commandsManager, hotkeysManager, -}) { +}: withAppTypes) { const [appConfig] = useAppConfig(); // Parse route params/querystring @@ -72,9 +72,8 @@ export default function ModeRoute({ locationRef.current = location; } - const { displaySetService, panelService, hangingProtocolService, userAuthenticationService } = ( - servicesManager as ServicesManager - ).services; + const { displaySetService, panelService, hangingProtocolService, userAuthenticationService } = + servicesManager.services; const { extensions, sopClassHandlers, hotkeys: hotkeyObj, hangingProtocol } = mode; @@ -252,18 +251,15 @@ export default function ModeRoute({ const filters = Array.from(query.keys()).reduce((acc: Record, val: string) => { const lowerVal = val.toLowerCase(); - if (lowerVal !== 'studyinstanceuids') { - // Not sure why the case matters here - it doesn't in the URL - if (lowerVal === 'seriesinstanceuid') { - const seriesUIDs = getSplitParam(lowerVal, query); - return { - ...acc, - seriesInstanceUID: seriesUIDs, - }; - } - - return { ...acc, [val]: getSplitParam(lowerVal, query) }; + // Not sure why the case matters here - it doesn't in the URL + if (lowerVal === 'seriesinstanceuids') { + const seriesUIDs = getSplitParam(lowerVal, query); + return { + ...acc, + seriesInstanceUID: seriesUIDs, + }; } + return { ...acc, [val]: getSplitParam(lowerVal, query) }; }, {}) ?? {}; let unsubs; @@ -322,9 +318,11 @@ export default function ModeRoute({ } // The unsubscriptions must occur before the extension onModeExit // in order to prevent exceptions during cleanup caused by spurious events - unsubscriptions.forEach(unsub => { - unsub(); - }); + if (unsubscriptions) { + unsubscriptions.forEach(unsub => { + unsub(); + }); + } // The extension manager must be called after the mode, this is // expected to cleanup the state to a standard setup. extensionManager.onModeExit(); diff --git a/platform/app/src/routes/Mode/defaultRouteInit.ts b/platform/app/src/routes/Mode/defaultRouteInit.ts index 975ac4d8bf..4a29201d1b 100644 --- a/platform/app/src/routes/Mode/defaultRouteInit.ts +++ b/platform/app/src/routes/Mode/defaultRouteInit.ts @@ -4,7 +4,7 @@ import isSeriesFilterUsed from '../../utils/isSeriesFilterUsed'; import { utils, Enums } from '@ohif/core'; -const { sortingCriteria } = utils; +const { sortingCriteria, getSplitParam } = utils; /** * Initialize the route. @@ -16,7 +16,7 @@ const { sortingCriteria } = utils; * @returns array of subscriptions to cancel */ export async function defaultRouteInit( - { servicesManager, studyInstanceUIDs, dataSource, filters, appConfig }, + { servicesManager, studyInstanceUIDs, dataSource, filters, appConfig }: withAppTypes, hangingProtocolId ) { const { displaySetService, hangingProtocolService, uiNotificationService, customizationService } = @@ -95,6 +95,18 @@ export async function defaultRouteInit( }); }); + // is displaysets from URL and has initialSOPInstanceUID or initialSeriesInstanceUID + // then we need to wait for all display sets to be retrieved before applying the hanging protocol + const params = new URLSearchParams(window.location.search); + + const initialSeriesInstanceUID = getSplitParam('initialseriesinstanceuid', params); + const initialSOPInstanceUID = getSplitParam('initialsopinstanceuid', params); + + let displaySetFromUrl = false; + if (initialSeriesInstanceUID || initialSOPInstanceUID) { + displaySetFromUrl = true; + } + await Promise.allSettled(allRetrieves).then(async promises => { log.timeEnd(Enums.TimingEnum.STUDY_TO_DISPLAY_SETS); log.time(Enums.TimingEnum.DISPLAY_SETS_TO_FIRST_IMAGE); @@ -109,7 +121,16 @@ export async function defaultRouteInit( promises.forEach(promise => { const retrieveSeriesMetadataPromise = promise.value; - if (Array.isArray(retrieveSeriesMetadataPromise)) { + if (!Array.isArray(retrieveSeriesMetadataPromise)) { + return; + } + + if (displaySetFromUrl) { + const requiredSeriesPromises = retrieveSeriesMetadataPromise.map(promise => + promise.start() + ); + allPromises.push(Promise.allSettled(requiredSeriesPromises)); + } else { const { requiredSeries, remaining } = hangingProtocolService.filterSeriesRequiredForRun( hangingProtocolId, retrieveSeriesMetadataPromise diff --git a/platform/app/src/routes/PrivateRoute.tsx b/platform/app/src/routes/PrivateRoute.tsx index 34bd3955b7..0e9f9279e4 100644 --- a/platform/app/src/routes/PrivateRoute.tsx +++ b/platform/app/src/routes/PrivateRoute.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import { useUserAuthentication } from '@ohif/ui'; export const PrivateRoute = ({ children, handleUnauthenticated }) => { diff --git a/platform/app/src/routes/WorkList/WorkList.tsx b/platform/app/src/routes/WorkList/WorkList.tsx index 225bf71c89..01c39509e4 100644 --- a/platform/app/src/routes/WorkList/WorkList.tsx +++ b/platform/app/src/routes/WorkList/WorkList.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect, useMemo } from 'react'; import classnames from 'classnames'; -import PropTypes from 'prop-types'; +import PropTypes, { object } from 'prop-types'; import { Link, useNavigate } from 'react-router-dom'; import moment from 'moment'; import qs from 'query-string'; @@ -10,12 +10,11 @@ import { useTranslation } from 'react-i18next'; import filtersMeta from './filtersMeta.js'; import { useAppConfig } from '@state'; import { useDebounce, useSearchParams } from '@hooks'; -import { utils, hotkeys, ServicesManager } from '@ohif/core'; +import { utils, hotkeys } from '@ohif/core'; import { Icon, StudyListExpandedRow, - LegacyButton, EmptyStudies, StudyListTable, StudyListPagination, @@ -57,7 +56,7 @@ function WorkList({ dataPath, onRefresh, servicesManager, -}) { +}: withAppTypes) { const { hotkeyDefinitions, hotkeyDefaults } = hotkeysManager; const { show, hide } = useModal(); const { t } = useTranslation(); @@ -271,6 +270,7 @@ function WorkList({ return { dataCY: `studyRow-${studyInstanceUid}`, + clickableCY: studyInstanceUid, row: [ { key: 'patientName', @@ -526,7 +526,7 @@ function WorkList({ customizationService.get('ohif.dataSourceConfigurationComponent') ?? {}; return ( -
+
-
+
100 ? 101 : numOfStudies} filtersMeta={filtersMeta} @@ -586,7 +586,7 @@ WorkList.propTypes = { getConfig: PropTypes.func, }).isRequired, isLoadingData: PropTypes.bool.isRequired, - servicesManager: PropTypes.instanceOf(ServicesManager), + servicesManager: PropTypes.object.isRequired, }; const defaultFilterValues = { @@ -618,6 +618,12 @@ function _tryParseInt(str, defaultValue) { } function _getQueryFilterValues(params) { + const newParams = new URLSearchParams(); + for (const [key, value] of params) { + newParams.set(key.toLowerCase(), value); + } + params = newParams; + const queryFilterValues = { patientName: params.get('patientname'), mrn: params.get('mrn'), diff --git a/platform/app/src/routes/buildModeRoutes.tsx b/platform/app/src/routes/buildModeRoutes.tsx index be46177b68..77dfde04e6 100644 --- a/platform/app/src/routes/buildModeRoutes.tsx +++ b/platform/app/src/routes/buildModeRoutes.tsx @@ -28,7 +28,7 @@ export default function buildModeRoutes({ servicesManager, commandsManager, hotkeysManager, -}) { +}: withAppTypes) { const routes = []; const dataSourceNames = []; @@ -81,7 +81,7 @@ export default function buildModeRoutes({ routes.push({ path, children, - private: true, // todo: all mode routes are private for now + private: true, }); }); diff --git a/platform/app/src/routes/index.tsx b/platform/app/src/routes/index.tsx index df2d52f740..32d33b6b7f 100644 --- a/platform/app/src/routes/index.tsx +++ b/platform/app/src/routes/index.tsx @@ -89,7 +89,7 @@ const createRoutes = ({ hotkeysManager, routerBasename, showStudyList, -}) => { +}: withAppTypes) => { const routes = buildModeRoutes({ modes, @@ -139,18 +139,20 @@ const createRoutes = ({ const { userAuthenticationService } = servicesManager.services; - // Note: PrivateRoutes in react-router-dom 6.x should be defined within - // a Route element + // All routes are private by default and then we let the user auth service + // to check if it is enabled or not + // Todo: I think we can remove the second public return below return ( {allRoutes.map((route, i) => { return route.private === true ? ( + userAuthenticationService.handleUnauthenticated()} + > } diff --git a/platform/app/src/utils/OpenIdConnectRoutes.tsx b/platform/app/src/utils/OpenIdConnectRoutes.tsx index 7c83efd2a0..de044161a8 100644 --- a/platform/app/src/utils/OpenIdConnectRoutes.tsx +++ b/platform/app/src/utils/OpenIdConnectRoutes.tsx @@ -3,7 +3,8 @@ import { useEffect } from 'react'; import { Route, Routes, useLocation, useNavigate } from 'react-router'; import CallbackPage from '../routes/CallbackPage'; import SignoutCallbackComponent from '../routes/SignoutCallbackComponent'; -import getUserManagerForOpenIdConnectClient from './getUserManagerForOpenIdConnectClient.js'; +import LegacyClient from './legacyOIDCClient'; +import NextClient from './nextOIDCClient'; function _isAbsoluteUrl(url) { return url.includes('http://') || url.includes('https://'); @@ -43,7 +44,9 @@ const initUserManager = (oidc, routerBasename) => { post_logout_redirect_uri: _makeAbsoluteIfNecessary(post_logout_redirect_uri, baseUri), }); - return getUserManagerForOpenIdConnectClient(openIdConnectConfiguration); + const client = firstOpenIdClient.useAuthorizationCodeFlow ? NextClient: LegacyClient + + return client(openIdConnectConfiguration); }; function LogoutComponent(props) { @@ -147,12 +150,18 @@ function OpenIdConnectRoutes({ oidc, routerBasename, userAuthenticationService } const location = useLocation(); const { pathname, search } = location; - const redirect_uri = new URL(userManager.settings._redirect_uri).pathname.replace( + const redirectURI = userManager.settings._redirect_uri ?? userManager.settings.redirect_uri; + const silentRedirectURI = + userManager.settings._silent_redirect_uri ?? userManager.settings.silent_redirect_uri; + const postLogoutRedirectURI = + userManager.settings._post_logout_redirect_uri ?? userManager.settings.post_logout_redirect_uri; + + const redirect_uri = new URL(redirectURI).pathname.replace( routerBasename !== '/' ? routerBasename : '', '' ); - const silent_refresh_uri = new URL(userManager.settings._silent_redirect_uri).pathname; //.replace(routerBasename,'') - const post_logout_redirect_uri = new URL(userManager.settings._post_logout_redirect_uri).pathname; //.replace(routerBasename,''); + const silent_refresh_uri = new URL(silentRedirectURI).pathname; //.replace(routerBasename,'') + const post_logout_redirect_uri = new URL(postLogoutRedirectURI).pathname; //.replace(routerBasename,''); // const pathnameRelative = pathname.replace(routerBasename,''); diff --git a/platform/app/src/utils/getUserManagerForOpenIdConnectClient.js b/platform/app/src/utils/legacyOIDCClient.ts similarity index 100% rename from platform/app/src/utils/getUserManagerForOpenIdConnectClient.js rename to platform/app/src/utils/legacyOIDCClient.ts diff --git a/platform/app/src/utils/nextOIDCClient.ts b/platform/app/src/utils/nextOIDCClient.ts new file mode 100644 index 0000000000..24213698e0 --- /dev/null +++ b/platform/app/src/utils/nextOIDCClient.ts @@ -0,0 +1,39 @@ +import { UserManager } from 'oidc-client-ts'; + +/** + * Creates a userManager from oidcSettings + * LINK: https://github.com/IdentityModel/oidc-client-js/wiki#configuration + * + * @param {Object} oidcSettings + * @param {string} oidcSettings.authServerUrl, + * @param {string} oidcSettings.clientId, + * @param {string} oidcSettings.authRedirectUri, + * @param {string} oidcSettings.postLogoutRedirectUri, + * @param {string} oidcSettings.responseType, + * @param {string} oidcSettings.extraQueryParams, + */ +export default function getUserManagerForOpenIdConnectClient(oidcSettings) { + if (!oidcSettings) { + return; + } + + if (!oidcSettings.authority || !oidcSettings.client_id || !oidcSettings.redirect_uri) { + console.error('Missing required oidc settings: authority, client_id, redirect_uri'); + return; + } + + const settings = { + ...oidcSettings, + // The next client always use the code flow with PKCE + response_type: 'code', + revokeTokensOnSignout: oidcSettings.revokeAccessTokenOnSignout ?? true, + filterProtocolClaims: true, + loadUserInfo: true, + // the followings are default values in the lib so no need to set them + // automaticSilentRenew: true, + }; + + const userManager = new UserManager(settings); + + return userManager; +} diff --git a/platform/app/tailwind.config.js b/platform/app/tailwind.config.js index bc354e5a1a..8c40c371f5 100644 --- a/platform/app/tailwind.config.js +++ b/platform/app/tailwind.config.js @@ -1,5 +1,4 @@ -// Todo: we probably should add external installed extensions/modes here as well. - +/** @type {import('tailwindcss').Config} */ module.exports = { // Note: in Tailwind 3.0, JIT will purge unused styles by default // but in development, it is often useful to disable this to see @@ -7,6 +6,7 @@ module.exports = { // ...(process.env.NODE_ENV === 'development' && { // safelist: [{ pattern: /.*/ }], // }), + presets: [require('../ui/tailwind.config.js'), require('../ui-next/tailwind.config.js')], content: [ './src/**/*.{jsx,js,ts,tsx, css}', '../../extensions/**/*.{jsx,js,ts,tsx, css}', @@ -14,256 +14,10 @@ module.exports = { '../../modes/**/*.{jsx,js,ts,tsx, css}', './node_modules/@ohif/ui/src/**/*.{js,jsx,ts,tsx, css}', '../../node_modules/@ohif/ui/src/**/*.{js,jsx,ts,tsx,css}', - '../../node_modules/@ohif/ui/src/**/*.{js,jsx,ts,tsx,css}', + '../../node_modules/@ohif/ui-next/src/**/*.{js,jsx,ts,tsx,css}', '../../node_modules/@ohif/extension-*/src/**/*.{js,jsx,css, ts,tsx}', ], theme: { - screens: { - sm: '640px', - md: '768px', - lg: '1024px', - xl: '1280px', - }, - colors: { - overlay: 'rgba(0, 0, 0, 0.8)', - transparent: 'transparent', - black: '#000', - white: '#fff', - initial: 'initial', - inherit: 'inherit', - - indigo: { - dark: '#0b1a42', - }, - aqua: { - pale: '#7bb2ce', - }, - - primary: { - light: '#5acce6', - main: '#0944b3', - dark: '#090c29', - active: '#348cfd', - }, - - inputfield: { - main: '#3a3f99', - disabled: '#2b166b', - focus: '#5acce6', - placeholder: '#39383f', - }, - - secondary: { - light: '#3a3f99', - main: '#2b166b', - dark: '#041c4a', - active: '#1f1f27', - }, - - common: { - bright: '#e1e1e1', - light: '#a19fad', - main: '#fff', - dark: '#726f7e', - active: '#2c3074', - }, - - customgreen: { - 100: '#05D97C', - 200: '#0FD97C', - }, - - customblue: { - 10: '#0A163F', - 20: '#0B1F54', - 30: '#09286e', - 40: '#0E307F', - 50: '#0F3A94', - 80: '#1454D4', - 100: '#c4fdff', - 200: '#38daff', - 300: '#1D204D', - 400: '#90A0C1', - }, - - customgray: { - 100: '#262943', - }, - - gray: { - 100: '#f7fafc', - 200: '#edf2f7', - 300: '#e2e8f0', - 400: '#cbd5e0', - 500: '#a0aec0', - 600: '#718096', - 700: '#4a5568', - 800: '#2d3748', - 900: '#1a202c', - }, - red: { - 100: '#fff5f5', - 200: '#fed7d7', - 300: '#feb2b2', - 400: '#fc8181', - 500: '#f56565', - 600: '#e53e3e', - 700: '#c53030', - 800: '#9b2c2c', - 900: '#742a2a', - }, - orange: { - 100: '#fffaf0', - 200: '#feebc8', - 300: '#fbd38d', - 400: '#f6ad55', - 500: '#ed8936', - 600: '#dd6b20', - 700: '#c05621', - 800: '#9c4221', - 900: '#7b341e', - }, - yellow: { - 100: '#fffff0', - 200: '#fefcbf', - 300: '#faf089', - 400: '#f6e05e', - 500: '#ecc94b', - 600: '#d69e2e', - 700: '#b7791f', - 800: '#975a16', - 900: '#744210', - }, - green: { - 100: '#f0fff4', - 200: '#c6f6d5', - 300: '#9ae6b4', - 400: '#68d391', - 500: '#48bb78', - 600: '#38a169', - 700: '#2f855a', - 800: '#276749', - 900: '#22543d', - }, - teal: { - 100: '#e6fffa', - 200: '#b2f5ea', - 300: '#81e6d9', - 400: '#4fd1c5', - 500: '#38b2ac', - 600: '#319795', - 700: '#2c7a7b', - 800: '#285e61', - 900: '#234e52', - }, - blue: { - 100: '#ebf8ff', - 200: '#bee3f8', - 300: '#90cdf4', - 400: '#63b3ed', - 500: '#4299e1', - 600: '#3182ce', - 700: '#2b6cb0', - 800: '#2c5282', - 900: '#2a4365', - }, - indigo: { - 100: '#ebf4ff', - 200: '#c3dafe', - 300: '#a3bffa', - 400: '#7f9cf5', - 500: '#667eea', - 600: '#5a67d8', - 700: '#4c51bf', - 800: '#434190', - 900: '#3c366b', - }, - purple: { - 100: '#faf5ff', - 200: '#e9d8fd', - 300: '#d6bcfa', - 400: '#b794f4', - 500: '#9f7aea', - 600: '#805ad5', - 700: '#6b46c1', - 800: '#553c9a', - 900: '#44337a', - }, - pink: { - 100: '#fff5f7', - 200: '#fed7e2', - 300: '#fbb6ce', - 400: '#f687b3', - 500: '#ed64a6', - 600: '#d53f8c', - 700: '#b83280', - 800: '#97266d', - 900: '#702459', - }, - }, - backgroundColor: theme => theme('colors'), - backgroundPosition: { - bottom: 'bottom', - center: 'center', - left: 'left', - 'left-bottom': 'left bottom', - 'left-top': 'left top', - right: 'right', - 'right-bottom': 'right bottom', - 'right-top': 'right top', - top: 'top', - }, - backgroundSize: { - auto: 'auto', - cover: 'cover', - contain: 'contain', - }, - borderColor: theme => ({ - ...theme('colors'), - DEFAULT: theme('colors.gray.300', 'currentColor'), - }), - boxShadow: { - xs: '0 0 0 1px rgba(0, 0, 0, 0.05)', - sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)', - DEFAULT: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)', - md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)', - lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)', - xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)', - '2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.25)', - inner: 'inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)', - outline: '0 0 0 3px rgba(66, 153, 225, 0.5)', - none: 'none', - }, - container: {}, - cursor: { - auto: 'auto', - default: 'default', - pointer: 'pointer', - wait: 'wait', - text: 'text', - move: 'move', - 'not-allowed': 'not-allowed', - }, - fill: { - current: 'currentColor', - }, - flex: { - 1: '1 1 0%', - 0.3: '0.3 0.3 0%', - 0.5: '0.5 0.5 0%', - auto: '1 1 auto', - initial: '0 1 auto', - none: 'none', - static: '0 0 auto', - }, - flexGrow: { - 0: '0', - DEFAULT: '1', - }, - flexShrink: { - 0: '0', - DEFAULT: '1', - }, fontFamily: { sans: [ 'Inter', @@ -296,500 +50,5 @@ module.exports = { '5xl': '3rem', '6xl': '4rem', }, - fontWeight: { - hairline: '100', - thin: '200', - light: '300', - normal: '300', - medium: '500', - semibold: '600', - bold: '700', - extrabold: '800', - black: '900', - }, - height: theme => ({ - auto: 'auto', - ...theme('spacing'), - full: '100%', - screen: '100vh', - inherit: 'inherit', - }), - inset: theme => ({ - ...theme('spacing'), - 0: '0', - auto: 'auto', - full: '100%', - viewport: '0.5rem', - '1/2': '50%', - 'viewport-scrollbar': '1.3rem', - }), - minHeight: theme => ({ - ...theme('spacing'), - 0: '0', - full: '100%', - screen: '100vh', - }), - letterSpacing: { - tighter: '-0.05em', - tight: '-0.025em', - normal: '0', - wide: '0.025em', - wider: '0.05em', - widest: '0.1em', - }, - lineHeight: { - none: '1', - tight: '1.25', - snug: '1.375', - normal: '1.5', - relaxed: '1.625', - loose: '2', - 3: '.75rem', - 4: '1rem', - 5: '1.25rem', - 6: '1.5rem', - 7: '1.75rem', - 8: '2rem', - 9: '2.25rem', - 10: '2.5rem', - }, - listStyleType: { - none: 'none', - disc: 'disc', - decimal: 'decimal', - }, - margin: (theme, { negative }) => ({ - auto: 'auto', - ...theme('spacing'), - ...negative(theme('spacing')), - }), - maxHeight: theme => ({ - full: '100%', - screen: '100vh', - ...theme('spacing'), - }), - maxWidth: (theme, { breakpoints }) => ({ - none: 'none', - xs: '20rem', - sm: '24rem', - md: '28rem', - lg: '32rem', - xl: '36rem', - '2xl': '42rem', - '3xl': '48rem', - '4xl': '56rem', - '5xl': '64rem', - '6xl': '72rem', - full: '100%', - ...breakpoints(theme('screens')), - ...theme('spacing'), - }), - minWidth: theme => ({ - ...theme('spacing'), - 0: '0', - xs: '2rem', - sm: '4rem', - md: '6rem', - lg: '8rem', - xl: '10rem', - full: '100%', - }), - objectPosition: { - bottom: 'bottom', - center: 'center', - left: 'left', - 'left-bottom': 'left bottom', - 'left-top': 'left top', - right: 'right', - 'right-bottom': 'right bottom', - 'right-top': 'right top', - top: 'top', - }, - opacity: { - 0: '0', - 5: '.5', - 10: '.10', - 15: '.15', - 20: '.20', - 25: '.25', - 30: '.30', - 35: '.35', - 40: '.40', - 45: '.45', - 50: '.50', - 55: '.55', - 60: '.60', - 65: '.65', - 70: '.70', - 75: '.75', - 80: '.80', - 85: '.85', - 90: '.90', - 95: '.95', - 100: '1', - }, - order: { - first: '-9999', - last: '9999', - none: '0', - 1: '1', - 2: '2', - 3: '3', - 4: '4', - 5: '5', - 6: '6', - 7: '7', - 8: '8', - 9: '9', - 10: '10', - 11: '11', - 12: '12', - }, - padding: theme => theme('spacing'), - placeholderColor: theme => theme('colors'), - stroke: theme => ({ - ...theme('colors'), - current: 'currentColor', - }), - strokeWidth: { - 0: '0', - 1: '1', - 2: '2', - }, - textColor: theme => theme('colors'), - width: theme => ({ - auto: 'auto', - ...theme('spacing'), - '1/2': '50%', - '1/3': '33.333333%', - '2/3': '66.666667%', - '1/4': '25%', - '2/4': '50%', - '3/4': '75%', - '1/5': '20%', - '2/5': '40%', - '3/5': '60%', - '4/5': '80%', - '1/6': '16.666667%', - '2/6': '33.333333%', - '3/6': '50%', - '4/6': '66.666667%', - '5/6': '83.333333%', - '1/12': '8.333333%', - '2/12': '16.666667%', - '3/12': '25%', - '4/12': '33.333333%', - '5/12': '41.666667%', - '6/12': '50%', - '7/12': '58.333333%', - '8/12': '66.666667%', - '9/12': '75%', - '10/12': '83.333333%', - '11/12': '91.666667%', - '1/24': '4.166666667%', - '2/24': '8.333333333%', - '3/24': '12.5%', - '4/24': '16.66666667%', - '5/24': '20.83333333%', - '6/24': '25%', - '7/24': '29.16666667%', - '8/24': '33.33333333%', - '9/24': '37.5%', - '10/24': '41.66666667%', - '11/24': '45.83333333%', - '12/24': '50%', - '13/24': '54.16666667%', - '14/24': '58.33333333%', - '15/24': '62.5%', - '16/24': '66.66666667%', - '17/24': '70.83333333%', - '18/24': '75%', - '19/24': '79.16666667%', - '20/24': '83.33333333%', - '21/24': '87.5%', - '22/24': '91.66666667%', - '23/24': '95.83333333%', - full: '100%', - screen: '100vw', - 'max-content': 'max-content', - }), - zIndex: { - auto: 'auto', - 0: '0', - 10: '10', - 20: '20', - 30: '30', - 40: '40', - 50: '50', - }, - gap: theme => theme('spacing'), - gridTemplateColumns: { - none: 'none', - 1: 'repeat(1, minmax(0, 1fr))', - 2: 'repeat(2, minmax(0, 1fr))', - 3: 'repeat(3, minmax(0, 1fr))', - 4: 'repeat(4, minmax(0, 1fr))', - 5: 'repeat(5, minmax(0, 1fr))', - 6: 'repeat(6, minmax(0, 1fr))', - 7: 'repeat(7, minmax(0, 1fr))', - 8: 'repeat(8, minmax(0, 1fr))', - 9: 'repeat(9, minmax(0, 1fr))', - 10: 'repeat(10, minmax(0, 1fr))', - 11: 'repeat(11, minmax(0, 1fr))', - 12: 'repeat(12, minmax(0, 1fr))', - }, - gridColumn: { - auto: 'auto', - 'span-1': 'span 1 / span 1', - 'span-2': 'span 2 / span 2', - 'span-3': 'span 3 / span 3', - 'span-4': 'span 4 / span 4', - 'span-5': 'span 5 / span 5', - 'span-6': 'span 6 / span 6', - 'span-7': 'span 7 / span 7', - 'span-8': 'span 8 / span 8', - 'span-9': 'span 9 / span 9', - 'span-10': 'span 10 / span 10', - 'span-11': 'span 11 / span 11', - 'span-12': 'span 12 / span 12', - }, - gridColumnStart: { - auto: 'auto', - 1: '1', - 2: '2', - 3: '3', - 4: '4', - 5: '5', - 6: '6', - 7: '7', - 8: '8', - 9: '9', - 10: '10', - 11: '11', - 12: '12', - 13: '13', - }, - gridColumnEnd: { - auto: 'auto', - 1: '1', - 2: '2', - 3: '3', - 4: '4', - 5: '5', - 6: '6', - 7: '7', - 8: '8', - 9: '9', - 10: '10', - 11: '11', - 12: '12', - 13: '13', - }, - gridTemplateRows: { - none: 'none', - 1: 'repeat(1, minmax(0, 1fr))', - 2: 'repeat(2, minmax(0, 1fr))', - 3: 'repeat(3, minmax(0, 1fr))', - 4: 'repeat(4, minmax(0, 1fr))', - 5: 'repeat(5, minmax(0, 1fr))', - 6: 'repeat(6, minmax(0, 1fr))', - }, - gridRow: { - auto: 'auto', - 'span-1': 'span 1 / span 1', - 'span-2': 'span 2 / span 2', - 'span-3': 'span 3 / span 3', - 'span-4': 'span 4 / span 4', - 'span-5': 'span 5 / span 5', - 'span-6': 'span 6 / span 6', - }, - gridRowStart: { - auto: 'auto', - 1: '1', - 2: '2', - 3: '3', - 4: '4', - 5: '5', - 6: '6', - 7: '7', - }, - gridRowEnd: { - auto: 'auto', - 1: '1', - 2: '2', - 3: '3', - 4: '4', - 5: '5', - 6: '6', - 7: '7', - }, - transformOrigin: { - center: 'center', - top: 'top', - 'top-right': 'top right', - right: 'right', - 'bottom-right': 'bottom right', - bottom: 'bottom', - 'bottom-left': 'bottom left', - left: 'left', - 'top-left': 'top left', - }, - scale: { - 0: '0', - 50: '.5', - 75: '.75', - 90: '.9', - 95: '.95', - 100: '1', - 105: '1.05', - 110: '1.1', - 125: '1.25', - 150: '1.5', - }, - rotate: { - '-180': '-180deg', - '-90': '-90deg', - '-45': '-45deg', - 0: '0', - 45: '45deg', - 90: '90deg', - 180: '180deg', - }, - translate: (theme, { negative }) => ({ - ...theme('spacing'), - ...negative(theme('spacing')), - '-full': '-100%', - '-1/2': '-50%', - '1/2': '50%', - full: '100%', - }), - skew: { - '-12': '-12deg', - '-6': '-6deg', - '-3': '-3deg', - 0: '0', - 3: '3deg', - 6: '6deg', - 12: '12deg', - }, - transitionProperty: { - none: 'none', - all: 'all', - height: 'height', - DEFAULT: - 'background-color, border-color, color, fill, stroke, opacity, box-shadow, transform', - colors: 'background-color, border-color, color, fill, stroke', - opacity: 'opacity', - shadow: 'box-shadow', - transform: 'transform', - }, - transitionTimingFunction: { - linear: 'linear', - in: 'cubic-bezier(0.4, 0, 1, 1)', - out: 'cubic-bezier(0, 0, 0.2, 1)', - 'in-out': 'cubic-bezier(0.4, 0, 0.2, 1)', - }, - transitionDuration: { - 75: '75ms', - 100: '100ms', - 150: '150ms', - 200: '200ms', - 300: '300ms', - 500: '500ms', - 700: '700ms', - 1000: '1000ms', - }, - }, - variants: { - accessibility: ['responsive', 'focus'], - alignContent: ['responsive'], - alignItems: ['responsive'], - alignSelf: ['responsive'], - appearance: ['responsive'], - backgroundAttachment: ['responsive'], - backgroundColor: ['responsive', 'hover', 'focus', 'active', 'group-focus', 'group-hover'], - backgroundPosition: ['responsive'], - backgroundRepeat: ['responsive'], - backgroundSize: ['responsive'], - borderCollapse: ['responsive'], - borderColor: ['responsive', 'hover', 'focus', 'active', 'group-focus', 'group-hover'], - borderRadius: ['responsive', 'focus', 'first', 'last'], - borderStyle: ['responsive', 'focus'], - borderWidth: ['responsive', 'focus', 'first', 'last'], - boxShadow: ['responsive', 'hover', 'focus'], - boxSizing: ['responsive'], - cursor: ['responsive'], - display: ['responsive'], - fill: ['responsive'], - flex: ['responsive'], - flexDirection: ['responsive'], - flexGrow: ['responsive'], - flexShrink: ['responsive'], - flexWrap: ['responsive'], - float: ['responsive'], - clear: ['responsive'], - fontFamily: ['responsive'], - fontSize: ['responsive'], - fontSmoothing: ['responsive'], - fontStyle: ['responsive'], - fontWeight: ['responsive', 'hover', 'focus'], - height: ['responsive'], - inset: ['responsive'], - justifyContent: ['responsive'], - letterSpacing: ['responsive'], - lineHeight: ['responsive'], - listStylePosition: ['responsive'], - listStyleType: ['responsive'], - margin: ['responsive'], - maxHeight: ['responsive'], - maxWidth: ['responsive'], - minHeight: ['responsive'], - minWidth: ['responsive'], - objectFit: ['responsive'], - objectPosition: ['responsive'], - opacity: ['responsive', 'hover', 'focus', 'active'], - order: ['responsive'], - outline: ['responsive', 'focus'], - overflow: ['responsive'], - padding: ['responsive', 'first'], - placeholderColor: ['responsive', 'focus'], - pointerEvents: ['responsive'], - position: ['responsive'], - resize: ['responsive'], - stroke: ['responsive'], - strokeWidth: ['responsive'], - tableLayout: ['responsive'], - textAlign: ['responsive'], - textColor: ['responsive', 'hover', 'focus', 'active', 'group-hover'], - textDecoration: ['responsive', 'hover', 'focus'], - textTransform: ['responsive'], - userSelect: ['responsive'], - verticalAlign: ['responsive'], - visibility: ['responsive'], - whitespace: ['responsive'], - width: ['responsive'], - wordBreak: ['responsive'], - zIndex: ['responsive'], - gap: ['responsive'], - gridAutoFlow: ['responsive'], - gridTemplateColumns: ['responsive'], - gridColumn: ['responsive'], - gridColumnStart: ['responsive'], - gridColumnEnd: ['responsive'], - gridTemplateRows: ['responsive'], - gridRow: ['responsive'], - gridRowStart: ['responsive'], - gridRowEnd: ['responsive'], - transform: ['responsive'], - transformOrigin: ['responsive'], - scale: ['responsive', 'hover', 'focus'], - rotate: ['responsive', 'hover', 'focus'], - translate: ['responsive', 'hover', 'focus'], - skew: ['responsive', 'hover', 'focus'], - transitionProperty: ['responsive'], - transitionTimingFunction: ['responsive'], - transitionDuration: ['responsive'], }, - corePlugins: {}, - plugins: [], }; diff --git a/platform/cli/CHANGELOG.md b/platform/cli/CHANGELOG.md index b0a5e2fc1d..5a0015c85f 100644 --- a/platform/cli/CHANGELOG.md +++ b/platform/cli/CHANGELOG.md @@ -3,6 +3,696 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.9.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.70...v3.9.0-beta.71) (2024-07-30) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.69...v3.9.0-beta.70) (2024-07-30) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.68...v3.9.0-beta.69) (2024-07-27) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.67...v3.9.0-beta.68) (2024-07-26) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.66...v3.9.0-beta.67) (2024-07-26) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.65...v3.9.0-beta.66) (2024-07-24) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.64...v3.9.0-beta.65) (2024-07-23) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.63...v3.9.0-beta.64) (2024-07-19) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.62...v3.9.0-beta.63) (2024-07-10) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.61...v3.9.0-beta.62) (2024-07-09) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.60...v3.9.0-beta.61) (2024-07-09) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.59...v3.9.0-beta.60) (2024-07-09) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.58...v3.9.0-beta.59) (2024-07-05) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.57...v3.9.0-beta.58) (2024-07-04) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.56...v3.9.0-beta.57) (2024-07-02) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.55...v3.9.0-beta.56) (2024-07-02) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.54...v3.9.0-beta.55) (2024-06-28) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.53...v3.9.0-beta.54) (2024-06-28) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.52...v3.9.0-beta.53) (2024-06-28) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.51...v3.9.0-beta.52) (2024-06-27) + + +### Bug Fixes + +* **cli:** missing js ([#4268](https://github.com/OHIF/Viewers/issues/4268)) ([f660f8e](https://github.com/OHIF/Viewers/commit/f660f8e970c0226b34a9de10e2c57429dcce6763)) + + + + + +# [3.9.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.50...v3.9.0-beta.51) (2024-06-27) + + +### Bug Fixes + +* **cli:** Fix the cli utilities which require full paths ([d09f8b5](https://github.com/OHIF/Viewers/commit/d09f8b5ba2dcc0c02beb405b8cfa79fbae5bdde8)), closes [#4267](https://github.com/OHIF/Viewers/issues/4267) + + + + + +# [3.9.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.49...v3.9.0-beta.50) (2024-06-26) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.48...v3.9.0-beta.49) (2024-06-26) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.47...v3.9.0-beta.48) (2024-06-25) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.46...v3.9.0-beta.47) (2024-06-21) + + +### Bug Fixes + +* Allow the mode setup/creation to be async, and provide a few more values to extension/app config/mode setup. ([#4016](https://github.com/OHIF/Viewers/issues/4016)) ([88575c6](https://github.com/OHIF/Viewers/commit/88575c6c09fd778a31b2f91524163ce65d1639dd)) + + + + + +# [3.9.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.45...v3.9.0-beta.46) (2024-06-18) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.44...v3.9.0-beta.45) (2024-06-18) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.43...v3.9.0-beta.44) (2024-06-17) + + +### Bug Fixes + +* **cli:** version txt had a new line which it should not ([#4233](https://github.com/OHIF/Viewers/issues/4233)) ([097ef76](https://github.com/OHIF/Viewers/commit/097ef7665559a672d73e1babfc42afccc3cdd41d)) + + + + + +# [3.9.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.42...v3.9.0-beta.43) (2024-06-12) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.41...v3.9.0-beta.42) (2024-06-12) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.40...v3.9.0-beta.41) (2024-06-12) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.39...v3.9.0-beta.40) (2024-06-12) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.38...v3.9.0-beta.39) (2024-06-08) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.37...v3.9.0-beta.38) (2024-06-07) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.36...v3.9.0-beta.37) (2024-06-05) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.35...v3.9.0-beta.36) (2024-06-05) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.34...v3.9.0-beta.35) (2024-06-05) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.33...v3.9.0-beta.34) (2024-06-05) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.32...v3.9.0-beta.33) (2024-06-05) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.31...v3.9.0-beta.32) (2024-05-31) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.30...v3.9.0-beta.31) (2024-05-30) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.29...v3.9.0-beta.30) (2024-05-30) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.28...v3.9.0-beta.29) (2024-05-30) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.27...v3.9.0-beta.28) (2024-05-30) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.26...v3.9.0-beta.27) (2024-05-29) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.25...v3.9.0-beta.26) (2024-05-29) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.24...v3.9.0-beta.25) (2024-05-29) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.23...v3.9.0-beta.24) (2024-05-29) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.22...v3.9.0-beta.23) (2024-05-28) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.21...v3.9.0-beta.22) (2024-05-27) + + +### Features + +* **ui:** move to React 18 and base for using shadcn/ui ([#4174](https://github.com/OHIF/Viewers/issues/4174)) ([70f2c79](https://github.com/OHIF/Viewers/commit/70f2c797f42af603d7ea0eb8d23b4103aba66f77)) + + + + + +# [3.9.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.20...v3.9.0-beta.21) (2024-05-24) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.19...v3.9.0-beta.20) (2024-05-24) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.18...v3.9.0-beta.19) (2024-05-24) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.17...v3.9.0-beta.18) (2024-05-24) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.16...v3.9.0-beta.17) (2024-05-23) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.15...v3.9.0-beta.16) (2024-05-23) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.14...v3.9.0-beta.15) (2024-05-22) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.13...v3.9.0-beta.14) (2024-05-21) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.12...v3.9.0-beta.13) (2024-05-21) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.11...v3.9.0-beta.12) (2024-05-21) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.10...v3.9.0-beta.11) (2024-05-21) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.9...v3.9.0-beta.10) (2024-05-21) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.8...v3.9.0-beta.9) (2024-05-17) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.7...v3.9.0-beta.8) (2024-05-16) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.6...v3.9.0-beta.7) (2024-05-15) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.5...v3.9.0-beta.6) (2024-05-15) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.4...v3.9.0-beta.5) (2024-05-14) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.3...v3.9.0-beta.4) (2024-05-14) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.2...v3.9.0-beta.3) (2024-05-08) + + +### Features + +* **typings:** Enhance typing support with withAppTypes and custom services throughout OHIF ([#4090](https://github.com/OHIF/Viewers/issues/4090)) ([374065b](https://github.com/OHIF/Viewers/commit/374065bc3bad9d212f9817a8d41546cc64cfabfb)) + + + + + +# [3.9.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.1...v3.9.0-beta.2) (2024-05-06) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.0...v3.9.0-beta.1) (2024-05-06) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.9.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.94...v3.9.0-beta.0) (2024-04-29) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.8.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0-beta.94) (2024-04-29) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18) + +**Note:** Version bump only for package @ohif/cli + + + + + +# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18) + +**Note:** Version bump only for package @ohif/cli + + + + + # [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17) **Note:** Version bump only for package @ohif/cli diff --git a/platform/cli/package.json b/platform/cli/package.json index bcf03ccb4a..768acbbeb6 100644 --- a/platform/cli/package.json +++ b/platform/cli/package.json @@ -1,6 +1,6 @@ { "name": "@ohif/cli", - "version": "3.8.0-beta.82", + "version": "3.9.0-beta.71", "description": "A CLI to bootstrap new OHIF extension or mode", "type": "module", "main": "src/index.js", @@ -20,10 +20,10 @@ "author": "OHIF Contributors", "license": "MIT", "dependencies": { - "@babel/core": "^7.23.2", - "axios": "^0.26.1", + "@babel/core": "7.24.7", + "axios": "^0.28.0", "chalk": "^5.0.0", - "execa": "^6.0.0", + "execa": "^8.0.1", "gitignore": "^0.7.0", "inquirer": "^8.2.0", "listr": "^0.14.3", diff --git a/platform/cli/src/commands/utils/editPackageJson.js b/platform/cli/src/commands/utils/editPackageJson.js index 4caa750745..e29da6a601 100644 --- a/platform/cli/src/commands/utils/editPackageJson.js +++ b/platform/cli/src/commands/utils/editPackageJson.js @@ -4,7 +4,7 @@ import path from 'path'; async function editPackageJson(options) { const { name, version, description, author, license, targetDir } = options; - const ohifVersion = fs.readFileSync('./version.txt', 'utf8'); + const ohifVersion = fs.readFileSync('./version.txt', 'utf8').trim(); // read package.json from targetDir const dependenciesPath = path.join(targetDir, 'dependencies.json'); diff --git a/platform/cli/templates/extension/.webpack/webpack.prod.js b/platform/cli/templates/extension/.webpack/webpack.prod.js index 070a723e38..3a78c48130 100644 --- a/platform/cli/templates/extension/.webpack/webpack.prod.js +++ b/platform/cli/templates/extension/.webpack/webpack.prod.js @@ -43,7 +43,40 @@ const config = { }, ], module: { + rules: [ + { + test: /\.svg?$/, + oneOf: [ + { + use: [ + { + loader: '@svgr/webpack', + options: { + svgoConfig: { + plugins: [ + { + name: 'preset-default', + params: { + overrides: { + removeViewBox: false + }, + }, + }, + ] + }, + prettier: false, + svgo: true, + titleProp: true, + }, + }, + ], + issuer: { + and: [/\.(ts|tsx|js|jsx|md|mdx)$/], + }, + }, + ], + }, { test: /(\.jsx|\.js|\.tsx|\.ts)$/, loader: 'babel-loader', diff --git a/platform/cli/templates/extension/babel.config.js b/platform/cli/templates/extension/babel.config.js index 371f77fcf4..4772105a8c 100644 --- a/platform/cli/templates/extension/babel.config.js +++ b/platform/cli/templates/extension/babel.config.js @@ -1,21 +1,5 @@ -// https://babeljs.io/docs/en/options#babelrcroots -const { extendDefaultPlugins } = require('svgo'); - module.exports = { plugins: [ - [ - 'inline-react-svg', - { - svgo: { - plugins: extendDefaultPlugins([ - { - name: 'removeViewBox', - active: false, - }, - ]), - }, - }, - ], ['@babel/plugin-proposal-class-properties', { loose: true }], '@babel/plugin-transform-typescript', ['@babel/plugin-proposal-private-property-in-object', { loose: true }], @@ -59,7 +43,7 @@ module.exports = { '@babel/preset-react', '@babel/preset-typescript', ], - plugins: ['react-hot-loader/babel'], + plugins: ['react-refresh/babel'], ignore: ['**/*.test.jsx', '**/*.test.js', '__snapshots__', '__tests__'], }, }, diff --git a/platform/cli/templates/extension/dependencies.json b/platform/cli/templates/extension/dependencies.json index 661ccf7d77..546fd56fec 100644 --- a/platform/cli/templates/extension/dependencies.json +++ b/platform/cli/templates/extension/dependencies.json @@ -1,6 +1,8 @@ { "repository": "OHIF/Viewers", - "keywords": ["ohif-extension"], + "keywords": [ + "ohif-extension" + ], "module": "src/index.tsx", "engines": { "node": ">=14", @@ -15,48 +17,48 @@ "start": "yarn run dev" }, "peerDependencies": { - "@ohif/core": "^3.0.0", - "@ohif/extension-default": "^3.0.0", - "@ohif/extension-cornerstone": "^3.0.0", + "@ohif/core": "^{LATEST_OHIF_VERSION}", + "@ohif/extension-default": "^{LATEST_OHIF_VERSION}", + "@ohif/extension-cornerstone": "^{LATEST_OHIF_VERSION}", "@ohif/i18n": "^1.0.0", "prop-types": "^15.6.2", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "react": "^18.3.1", + "react-dom": "^18.3.1", "react-i18next": "^12.2.2", "react-router": "^6.8.1", "react-router-dom": "^6.8.1", - "webpack": "^5.50.0", + "webpack": "5.89.0", "webpack-merge": "^5.7.3" }, "dependencies": { "@babel/runtime": "^7.20.13" }, "devDependencies": { - "@babel/core": "^7.23.2", + "@babel/core": "7.24.7", "@babel/plugin-proposal-class-properties": "^7.16.7", "@babel/plugin-proposal-object-rest-spread": "^7.17.3", "@babel/plugin-proposal-private-methods": "^7.18.6", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-transform-arrow-functions": "^7.16.7", "@babel/plugin-transform-regenerator": "^7.16.7", - "@babel/plugin-transform-runtime": "^7.23.2", + "@babel/plugin-transform-runtime": "7.24.7", "@babel/plugin-transform-typescript": "^7.13.0", - "@babel/preset-env": "^7.23.2", + "@babel/preset-env": "7.24.7", "@babel/preset-react": "^7.16.7", "@babel/preset-typescript": "^7.13.0", "@babel/plugin-proposal-private-property-in-object": "7.21.11", "babel-eslint": "9.x", "babel-loader": "^8.2.4", - "babel-plugin-inline-react-svg": "^2.0.2", + "@svgr/webpack": "^8.1.0", "babel-plugin-module-resolver": "^5.0.0", "clean-webpack-plugin": "^4.0.0", "copy-webpack-plugin": "^10.2.0", "cross-env": "^7.0.3", "dotenv": "^14.1.0", - "eslint": "^5.0.1", + "eslint": "^8.39.0", "eslint-loader": "^2.0.0", - "webpack": "^5.50.0", + "webpack": "5.89.0", "webpack-merge": "^5.7.3", - "webpack-cli": "^4.7.2" + "webpack-cli": "^5.0.2" } } diff --git a/platform/cli/templates/mode/.webpack/webpack.prod.js b/platform/cli/templates/mode/.webpack/webpack.prod.js index d0829f3c6a..9f742f9c9f 100644 --- a/platform/cli/templates/mode/.webpack/webpack.prod.js +++ b/platform/cli/templates/mode/.webpack/webpack.prod.js @@ -49,6 +49,38 @@ const config = { ], module: { rules: [ + { + test: /\.svg?$/, + oneOf: [ + { + use: [ + { + loader: '@svgr/webpack', + options: { + svgoConfig: { + plugins: [ + { + name: 'preset-default', + params: { + overrides: { + removeViewBox: false + }, + }, + }, + ] + }, + prettier: false, + svgo: true, + titleProp: true, + }, + }, + ], + issuer: { + and: [/\.(ts|tsx|js|jsx|md|mdx)$/], + }, + }, + ], + }, { test: /(\.jsx|\.js|\.tsx|\.ts)$/, loader: 'babel-loader', diff --git a/platform/cli/templates/mode/babel.config.js b/platform/cli/templates/mode/babel.config.js index a38ddda212..9705ae6f28 100644 --- a/platform/cli/templates/mode/babel.config.js +++ b/platform/cli/templates/mode/babel.config.js @@ -1,5 +1,5 @@ module.exports = { - plugins: ['inline-react-svg', '@babel/plugin-proposal-class-properties'], + plugins: ['@babel/plugin-proposal-class-properties'], env: { test: { presets: [ @@ -37,7 +37,7 @@ module.exports = { '@babel/preset-react', '@babel/preset-typescript', ], - plugins: ['react-hot-loader/babel'], + plugins: ['react-refresh/babel'], ignore: ['**/*.test.jsx', '**/*.test.js', '__snapshots__', '__tests__'], }, }, diff --git a/platform/cli/templates/mode/dependencies.json b/platform/cli/templates/mode/dependencies.json index e760085287..3ef164b803 100644 --- a/platform/cli/templates/mode/dependencies.json +++ b/platform/cli/templates/mode/dependencies.json @@ -1,6 +1,8 @@ { "repository": "OHIF/Viewers", - "keywords": ["ohif-mode"], + "keywords": [ + "ohif-mode" + ], "module": "src/index.tsx", "engines": { "node": ">=14", @@ -23,29 +25,29 @@ "@babel/runtime": "^7.20.13" }, "devDependencies": { - "@babel/core": "^7.23.2", + "@babel/core": "7.24.7", "@babel/plugin-proposal-class-properties": "^7.16.7", "@babel/plugin-proposal-object-rest-spread": "^7.17.3", "@babel/plugin-proposal-private-methods": "^7.18.6", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-transform-arrow-functions": "^7.16.7", "@babel/plugin-transform-regenerator": "^7.16.7", - "@babel/plugin-transform-runtime": "^7.23.2", + "@babel/plugin-transform-runtime": "7.24.7", "@babel/plugin-transform-typescript": "^7.13.0", - "@babel/preset-env": "^7.23.2", + "@babel/preset-env": "7.24.7", "@babel/preset-react": "^7.16.7", "@babel/preset-typescript": "^7.13.0", "babel-eslint": "^8.0.3", "babel-loader": "^8.0.0-beta.4", - "babel-plugin-inline-react-svg": "^2.0.1", + "@svgr/webpack": "^8.1.0", "clean-webpack-plugin": "^4.0.0", "copy-webpack-plugin": "^10.2.0", "cross-env": "^7.0.3", "dotenv": "^14.1.0", - "eslint": "^5.0.1", + "eslint": "^8.39.0", "eslint-loader": "^2.0.0", - "webpack": "^5.50.0", + "webpack": "5.89.0", "webpack-merge": "^5.7.3", - "webpack-cli": "^4.7.2" + "webpack-cli": "^5.0.2" } } diff --git a/platform/cli/templates/mode/src/index.tsx b/platform/cli/templates/mode/src/index.tsx index b607e921a9..5ef254dc9d 100644 --- a/platform/cli/templates/mode/src/index.tsx +++ b/platform/cli/templates/mode/src/index.tsx @@ -40,7 +40,7 @@ function modeFactory({ modeConfiguration }) { * Runs when the Mode Route is mounted to the DOM. Usually used to initialize * Services and other resources. */ - onModeEnter: ({ servicesManager, extensionManager, commandsManager }) => { + onModeEnter: ({ servicesManager, extensionManager, commandsManager }: withAppTypes) => { const { measurementService, toolbarService, toolGroupService } = servicesManager.services; measurementService.clearMeasurements(); @@ -60,7 +60,7 @@ function modeFactory({ modeConfiguration }) { 'MoreTools', ]); }, - onModeExit: ({ servicesManager }) => { + onModeExit: ({ servicesManager }: withAppTypes) => { const { toolGroupService, syncGroupService, diff --git a/platform/core/CHANGELOG.md b/platform/core/CHANGELOG.md index 63584dc085..128e16a22a 100644 --- a/platform/core/CHANGELOG.md +++ b/platform/core/CHANGELOG.md @@ -3,6 +3,769 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.9.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.70...v3.9.0-beta.71) (2024-07-30) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.69...v3.9.0-beta.70) (2024-07-30) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.68...v3.9.0-beta.69) (2024-07-27) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.67...v3.9.0-beta.68) (2024-07-26) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.66...v3.9.0-beta.67) (2024-07-26) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.65...v3.9.0-beta.66) (2024-07-24) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.64...v3.9.0-beta.65) (2024-07-23) + + +### Features + +* **SR:** text structured report (TEXT, CODE, NUM, PNAME, DATE, TIME and DATETIME) ([#4287](https://github.com/OHIF/Viewers/issues/4287)) ([246ebab](https://github.com/OHIF/Viewers/commit/246ebab6ebf5431a704a1861a5804045b9644ba4)) + + + + + +# [3.9.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.63...v3.9.0-beta.64) (2024-07-19) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.62...v3.9.0-beta.63) (2024-07-10) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.61...v3.9.0-beta.62) (2024-07-09) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.60...v3.9.0-beta.61) (2024-07-09) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.59...v3.9.0-beta.60) (2024-07-09) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.58...v3.9.0-beta.59) (2024-07-05) + + +### Bug Fixes + +* Cobb angle not working in basic-test mode and open contour ([#4280](https://github.com/OHIF/Viewers/issues/4280)) ([6fd3c7e](https://github.com/OHIF/Viewers/commit/6fd3c7e293fec851dd30e650c1347cc0bc7a99ee)) +* **image-orientation:** Prevent incorrect orientation marker display for single-slice US images ([#4275](https://github.com/OHIF/Viewers/issues/4275)) ([6d11048](https://github.com/OHIF/Viewers/commit/6d11048ca5ea66284948602613a63277083ec6a5)) +* webpack import bugs showing warnings on import ([#4265](https://github.com/OHIF/Viewers/issues/4265)) ([24c511f](https://github.com/OHIF/Viewers/commit/24c511f4bc04c4143bbd3d0d48029f41f7f36014)) + + +### Features + +* Add interleaved HTJ2K and volume progressive loading ([#4276](https://github.com/OHIF/Viewers/issues/4276)) ([a2084f3](https://github.com/OHIF/Viewers/commit/a2084f319b731d98b59485799fb80357094f8c38)) + + + + + +# [3.9.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.57...v3.9.0-beta.58) (2024-07-04) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.56...v3.9.0-beta.57) (2024-07-02) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.55...v3.9.0-beta.56) (2024-07-02) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.54...v3.9.0-beta.55) (2024-06-28) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.53...v3.9.0-beta.54) (2024-06-28) + + +### Features + +* **studyPrefetcher:** Study Prefetcher ([#4206](https://github.com/OHIF/Viewers/issues/4206)) ([2048b19](https://github.com/OHIF/Viewers/commit/2048b19484c0b1fae73f993cfaa814f861bbd230)) + + + + + +# [3.9.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.52...v3.9.0-beta.53) (2024-06-28) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.51...v3.9.0-beta.52) (2024-06-27) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.50...v3.9.0-beta.51) (2024-06-27) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.49...v3.9.0-beta.50) (2024-06-26) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.48...v3.9.0-beta.49) (2024-06-26) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.47...v3.9.0-beta.48) (2024-06-25) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.46...v3.9.0-beta.47) (2024-06-21) + + +### Bug Fixes + +* Allow the mode setup/creation to be async, and provide a few more values to extension/app config/mode setup. ([#4016](https://github.com/OHIF/Viewers/issues/4016)) ([88575c6](https://github.com/OHIF/Viewers/commit/88575c6c09fd778a31b2f91524163ce65d1639dd)) +* **code:** remove console log ([#4248](https://github.com/OHIF/Viewers/issues/4248)) ([f3bbfff](https://github.com/OHIF/Viewers/commit/f3bbfff09b66ee020daf503656a2b58e763634a3)) +* **CustomViewportOverlay:** pass accurate data to Custom Viewport Functions ([#4224](https://github.com/OHIF/Viewers/issues/4224)) ([aef00e9](https://github.com/OHIF/Viewers/commit/aef00e91d63e9bc2de289cc6f35975e36547fb20)) +* **studybrowser:** Differentiate recent and all in study panel based on a provided time period ([#4242](https://github.com/OHIF/Viewers/issues/4242)) ([6f93449](https://github.com/OHIF/Viewers/commit/6f9344914951c204feaff48aaeb43cd7d727623d)) + + +### Features + +* customization service append and customize functionality should run once ([#4238](https://github.com/OHIF/Viewers/issues/4238)) ([e462fd3](https://github.com/OHIF/Viewers/commit/e462fd31f7944acfee34f08cfbc28cfd9de16169)) +* **sort:** custom series sort in study panel ([#4214](https://github.com/OHIF/Viewers/issues/4214)) ([a433d40](https://github.com/OHIF/Viewers/commit/a433d406e2cac13f644203996c682260b54e8865)) + + + + + +# [3.9.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.45...v3.9.0-beta.46) (2024-06-18) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.44...v3.9.0-beta.45) (2024-06-18) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.43...v3.9.0-beta.44) (2024-06-17) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.42...v3.9.0-beta.43) (2024-06-12) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.41...v3.9.0-beta.42) (2024-06-12) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.40...v3.9.0-beta.41) (2024-06-12) + + +### Features + +* Add customization merge, append or replace functionality ([#3871](https://github.com/OHIF/Viewers/issues/3871)) ([55dcfa1](https://github.com/OHIF/Viewers/commit/55dcfa1f6994a7036e7e594efb23673382a41915)) + + + + + +# [3.9.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.39...v3.9.0-beta.40) (2024-06-12) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.38...v3.9.0-beta.39) (2024-06-08) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.37...v3.9.0-beta.38) (2024-06-07) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.36...v3.9.0-beta.37) (2024-06-05) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.35...v3.9.0-beta.36) (2024-06-05) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.34...v3.9.0-beta.35) (2024-06-05) + + +### Bug Fixes + +* **seg:** maintain algorithm name and algorithm type when DICOM seg is exported or downloaded ([#4203](https://github.com/OHIF/Viewers/issues/4203)) ([a29e94d](https://github.com/OHIF/Viewers/commit/a29e94de803f79bbb3372d00ad8eb14b4224edc2)) + + + + + +# [3.9.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.33...v3.9.0-beta.34) (2024-06-05) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.32...v3.9.0-beta.33) (2024-06-05) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.31...v3.9.0-beta.32) (2024-05-31) + + +### Bug Fixes + +* **tmtv:** crosshairs should not have viewport indicators ([#4197](https://github.com/OHIF/Viewers/issues/4197)) ([f85da32](https://github.com/OHIF/Viewers/commit/f85da32f34389ef7cecae03c07e0af26468b52a6)) + + + + + +# [3.9.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.30...v3.9.0-beta.31) (2024-05-30) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.29...v3.9.0-beta.30) (2024-05-30) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.28...v3.9.0-beta.29) (2024-05-30) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.27...v3.9.0-beta.28) (2024-05-30) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.26...v3.9.0-beta.27) (2024-05-29) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.25...v3.9.0-beta.26) (2024-05-29) + + +### Features + +* **hp:** Add displayArea option for Hanging protocols and example with Mamo([#3808](https://github.com/OHIF/Viewers/issues/3808)) ([18ac08e](https://github.com/OHIF/Viewers/commit/18ac08ed860d119721c52e4ffc270332259100b6)) + + + + + +# [3.9.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.24...v3.9.0-beta.25) (2024-05-29) + + +### Bug Fixes + +* **ultrasound:** Upgrade cornerstone3D version to resolve coloring issues ([#4181](https://github.com/OHIF/Viewers/issues/4181)) ([75a71db](https://github.com/OHIF/Viewers/commit/75a71db7f89840250ad1c2b35df5a35aceb8be7d)) + + + + + +# [3.9.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.23...v3.9.0-beta.24) (2024-05-29) + + +### Features + +* **measurements:** show untracked measurements in measurement panel under additional findings ([#4160](https://github.com/OHIF/Viewers/issues/4160)) ([18686c2](https://github.com/OHIF/Viewers/commit/18686c2caf13ede3e881303100bd4cc34b8b135f)) + + + + + +# [3.9.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.22...v3.9.0-beta.23) (2024-05-28) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.21...v3.9.0-beta.22) (2024-05-27) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.20...v3.9.0-beta.21) (2024-05-24) + + +### Features + +* **types:** typed app config ([#4171](https://github.com/OHIF/Viewers/issues/4171)) ([8960b89](https://github.com/OHIF/Viewers/commit/8960b89911a9342d93bf1a62bec97a696f101fd4)) + + + + + +# [3.9.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.19...v3.9.0-beta.20) (2024-05-24) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.18...v3.9.0-beta.19) (2024-05-24) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.17...v3.9.0-beta.18) (2024-05-24) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.16...v3.9.0-beta.17) (2024-05-23) + + +### Bug Fixes + +* **crosshairs:** reset angle, position, and slabthickness for crosshairs when reset viewport tool is used ([#4113](https://github.com/OHIF/Viewers/issues/4113)) ([73d9e99](https://github.com/OHIF/Viewers/commit/73d9e99d5d6f38ab6c36f4471d54f18798feacb4)) + + + + + +# [3.9.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.15...v3.9.0-beta.16) (2024-05-23) + + +### Bug Fixes + +* dicom json for orthanc by Update package versions for [@cornerstonejs](https://github.com/cornerstonejs) dependencies ([#4165](https://github.com/OHIF/Viewers/issues/4165)) ([34c7d72](https://github.com/OHIF/Viewers/commit/34c7d72142847486b98c9c52469940083eeaf87e)) + + + + + +# [3.9.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.14...v3.9.0-beta.15) (2024-05-22) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.13...v3.9.0-beta.14) (2024-05-21) + + +### Bug Fixes + +* **HangingProtocol:** fix hp when unsupported series load first ([#4145](https://github.com/OHIF/Viewers/issues/4145)) ([b124c91](https://github.com/OHIF/Viewers/commit/b124c91d8fa0def262d1fee8f105295b02864129)) + + + + + +# [3.9.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.12...v3.9.0-beta.13) (2024-05-21) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.11...v3.9.0-beta.12) (2024-05-21) + + +### Bug Fixes + +* **segmentation:** Address issue where segmentation creation failed on layout change ([#4153](https://github.com/OHIF/Viewers/issues/4153)) ([29944c8](https://github.com/OHIF/Viewers/commit/29944c8512c35718af03c03ef82bc43675ee1872)) + + + + + +# [3.9.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.10...v3.9.0-beta.11) (2024-05-21) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.9...v3.9.0-beta.10) (2024-05-21) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.8...v3.9.0-beta.9) (2024-05-17) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.7...v3.9.0-beta.8) (2024-05-16) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.6...v3.9.0-beta.7) (2024-05-15) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.5...v3.9.0-beta.6) (2024-05-15) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.4...v3.9.0-beta.5) (2024-05-14) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.3...v3.9.0-beta.4) (2024-05-14) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.2...v3.9.0-beta.3) (2024-05-08) + + +### Features + +* **typings:** Enhance typing support with withAppTypes and custom services throughout OHIF ([#4090](https://github.com/OHIF/Viewers/issues/4090)) ([374065b](https://github.com/OHIF/Viewers/commit/374065bc3bad9d212f9817a8d41546cc64cfabfb)) + + + + + +# [3.9.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.1...v3.9.0-beta.2) (2024-05-06) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.9.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.0...v3.9.0-beta.1) (2024-05-06) + + +### Bug Fixes + +* **rt:** enhanced RT support, utilize SVGs for rendering. ([#4074](https://github.com/OHIF/Viewers/issues/4074)) ([0156bc4](https://github.com/OHIF/Viewers/commit/0156bc426f1840ae0d090223e94a643726e856cb)) + + + + + +# [3.9.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.94...v3.9.0-beta.0) (2024-04-29) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.8.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0-beta.94) (2024-04-29) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29) + + +### Bug Fixes + +* **toolbox:** Preserve user-specified tool state and streamline command execution ([#4063](https://github.com/OHIF/Viewers/issues/4063)) ([f1a736d](https://github.com/OHIF/Viewers/commit/f1a736d1934733a434cb87b2c284907a3122403f)) + + + + + +# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28) + + +### Bug Fixes + +* **bugs:** fix patient header for doc, track ball rotate resize observer and add segmentation button not being enabled on viewport data change ([#4068](https://github.com/OHIF/Viewers/issues/4068)) ([c09311d](https://github.com/OHIF/Viewers/commit/c09311d3b7df05fcd00a9f36a7233e9d7e5589d0)) + + + + + +# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22) + + +### Bug Fixes + +* **viewport-webworker-segmentation:** Resolve issues with viewport detection, webworker termination, and segmentation panel layout change ([#4059](https://github.com/OHIF/Viewers/issues/4059)) ([52a0c59](https://github.com/OHIF/Viewers/commit/52a0c59294a4161fcca0a6708855549034849951)) + + + + + +# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22) + + +### Bug Fixes + +* **hp:** Fails to display any layouts in the layout selector if first layout has multiple stages ([#4058](https://github.com/OHIF/Viewers/issues/4058)) ([f0ed3fd](https://github.com/OHIF/Viewers/commit/f0ed3fd7b99b0e4e00b261ceb9888ba94726719c)) + + + + + +# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19) + + +### Features + +* **tmtv-mode:** Add Brush tools and move SUV peak calculation to web worker ([#4053](https://github.com/OHIF/Viewers/issues/4053)) ([8192e34](https://github.com/OHIF/Viewers/commit/8192e348eca993fec331d4963efe88f9a730eceb)) + + + + + +# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19) + + +### Bug Fixes + +* **layouts:** and fix thumbnail in touch and update migration guide for 3.8 release ([#4052](https://github.com/OHIF/Viewers/issues/4052)) ([d250d04](https://github.com/OHIF/Viewers/commit/d250d04580883446fcb8d748b2a97c5c198922af)) + + + + + +# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18) + +**Note:** Version bump only for package @ohif/core + + + + + +# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18) + + +### Bug Fixes + +* **bugs:** and replace seriesInstanceUID and seriesInstanceUIDs URL with seriesInstanceUIDs ([#4049](https://github.com/OHIF/Viewers/issues/4049)) ([da7c1a5](https://github.com/OHIF/Viewers/commit/da7c1a5d8c54bfa1d3f97bbc500386bf76e7fd9d)) + + + + + +# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18) + + +### Bug Fixes + +* **bugs:** enhancements and bug fixes - final ([#4048](https://github.com/OHIF/Viewers/issues/4048)) ([170bb96](https://github.com/OHIF/Viewers/commit/170bb96983082c39b22b7352e0c54aacf3e73b02)) + + + + + # [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17) **Note:** Version bump only for package @ohif/core diff --git a/platform/core/jest.config.js b/platform/core/jest.config.js index 2978b062ed..f57711b3f5 100644 --- a/platform/core/jest.config.js +++ b/platform/core/jest.config.js @@ -3,7 +3,6 @@ const pkg = require('./package'); module.exports = { ...base, - name: pkg.name, displayName: pkg.name, // rootDir: "../.." // testMatch: [ diff --git a/platform/core/package.json b/platform/core/package.json index 3ceaffb721..496b8c6a6f 100644 --- a/platform/core/package.json +++ b/platform/core/package.json @@ -1,6 +1,6 @@ { "name": "@ohif/core", - "version": "3.8.0-beta.82", + "version": "3.9.0-beta.71", "description": "Generic business logic for web-based medical imaging applications", "author": "OHIF Core Team", "license": "MIT", @@ -35,27 +35,28 @@ "peerDependencies": { "@cornerstonejs/codec-charls": "^1.2.3", "@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2", - "@cornerstonejs/codec-openjpeg": "^1.2.2", - "@cornerstonejs/codec-openjph": "^2.4.2", - "@cornerstonejs/dicom-image-loader": "^1.70.6", - "@ohif/ui": "3.8.0-beta.82", + "@cornerstonejs/codec-openjpeg": "^1.2.3", + "@cornerstonejs/codec-openjph": "^2.4.5", + "@cornerstonejs/dicom-image-loader": "^1.82.0", + "@ohif/ui": "3.9.0-beta.71", "cornerstone-math": "0.1.9", "dicom-parser": "^1.8.21" }, "dependencies": { "@babel/runtime": "^7.20.13", - "dcmjs": "^0.29.12", + "dcmjs": "*", "dicomweb-client": "^0.10.4", "gl-matrix": "^3.4.3", "isomorphic-base64": "^1.0.2", "lodash.clonedeep": "^4.5.0", - "lodash.merge": "^4.6.1", - "moment": "^2.24.0", + "lodash.merge": "^4.6.2", + "lodash.mergewith": "^4.6.2", + "moment": "*", "object-hash": "2.1.1", "query-string": "^6.14.0", "validate.js": "^0.12.0" }, "devDependencies": { - "webpack-merge": "5.7.3" + "webpack-merge": "*" } } diff --git a/platform/core/src/classes/CommandsManager.ts b/platform/core/src/classes/CommandsManager.ts index 820554ca2a..e6ef1e9123 100644 --- a/platform/core/src/classes/CommandsManager.ts +++ b/platform/core/src/classes/CommandsManager.ts @@ -204,7 +204,8 @@ export class CommandsManager { // Execute each command in the array let result: unknown; - commands.forEach(({ commandName, commandOptions, context }) => { + commands.forEach(command => { + const { commandName, commandOptions, context } = command; if (commandName) { result = this.runCommand( commandName, @@ -215,7 +216,11 @@ export class CommandsManager { context ); } else { - console.warn('No command name supplied in', toRun); + if (typeof command === 'function') { + result = command(); + } else { + console.warn('No command name supplied in', toRun); + } } }); diff --git a/platform/core/src/classes/HotkeysManager.ts b/platform/core/src/classes/HotkeysManager.ts index 8a01446b62..b7ca44308c 100644 --- a/platform/core/src/classes/HotkeysManager.ts +++ b/platform/core/src/classes/HotkeysManager.ts @@ -2,7 +2,6 @@ import objectHash from 'object-hash'; import { hotkeys } from '../utils'; import isequal from 'lodash.isequal'; import Hotkey from './Hotkey'; -import ServicesManager from '../services/ServicesManager'; /** * @@ -15,9 +14,9 @@ import ServicesManager from '../services/ServicesManager'; */ export class HotkeysManager { - private _servicesManager: ServicesManager; + private _servicesManager: AppTypes.ServicesManager; - constructor(commandsManager, servicesManager) { + constructor(commandsManager, servicesManager: AppTypes.ServicesManager) { this.hotkeyDefinitions = {}; this.hotkeyDefaults = []; this.isEnabled = true; diff --git a/platform/core/src/classes/MetadataProvider.ts b/platform/core/src/classes/MetadataProvider.ts index 30525a2bc7..a92fb5daa9 100644 --- a/platform/core/src/classes/MetadataProvider.ts +++ b/platform/core/src/classes/MetadataProvider.ts @@ -561,7 +561,9 @@ const WADO_IMAGE_LOADER = { columns: toNumber(instance.Columns), imageOrientationPatient: toNumber(ImageOrientationPatient), rowCosines: toNumber(rowCosines || [0, 1, 0]), + isDefaultValueSetForRowCosine: toNumber(rowCosines) ? false : true, columnCosines: toNumber(columnCosines || [0, 0, -1]), + isDefaultValueSetForColumnCosine: toNumber(columnCosines) ? false : true, imagePositionPatient: toNumber(instance.ImagePositionPatient || [0, 0, 0]), sliceThickness: toNumber(instance.SliceThickness), sliceLocation: toNumber(instance.SliceLocation), diff --git a/platform/core/src/extensions/ExtensionManager.ts b/platform/core/src/extensions/ExtensionManager.ts index d7997c9fc4..d01635538c 100644 --- a/platform/core/src/extensions/ExtensionManager.ts +++ b/platform/core/src/extensions/ExtensionManager.ts @@ -1,19 +1,19 @@ import MODULE_TYPES from './MODULE_TYPES'; import log from '../log'; -import { AppConfig } from '../types/AppConfig'; -import { PubSubService, ServiceProvidersManager, ServicesManager } from '../services'; +import { PubSubService, ServiceProvidersManager } from '../services'; import { HotkeysManager, CommandsManager } from '../classes'; -import { DataSourceDefinition } from '../types'; +import type { DataSourceDefinition } from '../types'; +import type AppTypes from '../types/AppTypes'; /** * This is the arguments given to create the extension. */ export interface ExtensionConstructor { - servicesManager: ServicesManager; + servicesManager: AppTypes.ServicesManager; serviceProvidersManager: ServiceProvidersManager; commandsManager: CommandsManager; hotkeysManager: HotkeysManager; - appConfig: AppConfig; + appConfig: AppTypes.Config; } /** @@ -28,9 +28,10 @@ export type ExtensionConfiguration = Record; */ export interface ExtensionParams extends ExtensionConstructor { extensionManager: ExtensionManager; - servicesManager: ServicesManager; + servicesManager: AppTypes.ServicesManager; serviceProvidersManager: ServiceProvidersManager; configuration?: ExtensionConfiguration; + peerImport: (moduleId: string) => Promise; } /** @@ -49,7 +50,7 @@ export interface Extension { getSopClassHandlerModule?: (p: ExtensionParams) => unknown; getToolbarModule?: (p: ExtensionParams) => unknown; getPanelModule?: (p: ExtensionParams) => unknown; - onModeEnter?: () => void; + onModeEnter?: (p: AppTypes) => void; onModeExit?: () => void; } @@ -72,7 +73,7 @@ export default class ExtensionManager extends PubSubService { public static readonly MODULE_TYPES = MODULE_TYPES; private _commandsManager: CommandsManager; - private _servicesManager: ServicesManager; + private _servicesManager: AppTypes.ServicesManager; private _hotkeysManager: HotkeysManager; private _serviceProvidersManager: ServiceProvidersManager; private modulesMap: Record; @@ -88,6 +89,7 @@ export default class ExtensionManager extends PubSubService { private dataSourceDefs: Record; private defaultDataSourceName: string; private activeDataSource: string; + private peerImport: (moduleId) => Promise; constructor({ commandsManager, @@ -116,6 +118,7 @@ export default class ExtensionManager extends PubSubService { this.dataSourceDefs = {}; this.defaultDataSourceName = appConfig.defaultDataSourceName; this.activeDataSource = appConfig.defaultDataSourceName; + this.peerImport = appConfig.peerImport; } public setActiveDataSource(dataSource: string): void { @@ -131,6 +134,16 @@ export default class ExtensionManager extends PubSubService { ); } + public getRegisteredExtensionIds() { + return [...this.registeredExtensionIds]; + } + + private getUniqueServicesList(servicesManager: AppTypes.ServicesManager) { + // Make sure only one service instance is returned because almost all services are + // registered with different keys (eg: StudyPrefetcherService and studyPrefetcherService) + return Array.from(new Set(Object.values(servicesManager.services))); + } + /** * Calls all the services and extension on mode enters. * The service onModeEnter is called first @@ -145,11 +158,12 @@ export default class ExtensionManager extends PubSubService { _hotkeysManager, _extensionLifeCycleHooks, } = this; + const services = this.getUniqueServicesList(_servicesManager); // The onModeEnter of the service must occur BEFORE the extension // onModeEnter in order to reset the state to a standard state // before the extension restores and cached data. - for (const service of Object.values(_servicesManager.services)) { + for (const service of services) { service?.onModeEnter?.(); } @@ -169,6 +183,7 @@ export default class ExtensionManager extends PubSubService { public onModeExit(): void { const { registeredExtensionIds, _servicesManager, _commandsManager, _extensionLifeCycleHooks } = this; + const services = this.getUniqueServicesList(_servicesManager); registeredExtensionIds.forEach(extensionId => { const onModeExit = _extensionLifeCycleHooks.onModeExit[extensionId]; @@ -183,7 +198,7 @@ export default class ExtensionManager extends PubSubService { // The service onModeExit calls must occur after the extension ones // so that extension ones can store/restore data. - for (const service of Object.values(_servicesManager.services)) { + for (const service of services) { try { service?.onModeExit?.(); } catch (e) { @@ -596,6 +611,10 @@ export default class ExtensionManager extends PubSubService { ); }); }; + + public get appConfig() { + return this._appConfig; + } } /** diff --git a/platform/core/src/hooks/useToolbar.tsx b/platform/core/src/hooks/useToolbar.tsx index 31eeb1d629..2dbd94fc8e 100644 --- a/platform/core/src/hooks/useToolbar.tsx +++ b/platform/core/src/hooks/useToolbar.tsx @@ -1,6 +1,6 @@ import { useCallback, useEffect, useState } from 'react'; -export function useToolbar({ servicesManager, buttonSection = 'primary' }) { +export function useToolbar({ servicesManager, buttonSection = 'primary' }: withAppTypes) { const { toolbarService, viewportGridService } = servicesManager.services; const { EVENTS } = toolbarService; diff --git a/platform/core/src/index.test.js b/platform/core/src/index.test.js index 7649a87026..66d4ac3796 100644 --- a/platform/core/src/index.test.js +++ b/platform/core/src/index.test.js @@ -1,7 +1,7 @@ import * as OHIF from './index'; describe('Top level exports', () => { - test.only('have not changed', () => { + test('have not changed', () => { const expectedExports = [ 'MODULE_TYPES', // @@ -47,6 +47,7 @@ describe('Top level exports', () => { 'PubSubService', 'PanelService', 'WorkflowStepsService', + 'StudyPrefetcherService', 'useToolbar', ].sort(); diff --git a/platform/core/src/index.ts b/platform/core/src/index.ts index d548e6e7b9..219b320988 100644 --- a/platform/core/src/index.ts +++ b/platform/core/src/index.ts @@ -13,7 +13,6 @@ import defaults from './defaults'; import * as Types from './types'; import * as Enums from './enums'; import { useToolbar } from './hooks/useToolbar'; - import { CineService, UIDialogService, @@ -34,6 +33,7 @@ import { StateSyncService, PanelService, WorkflowStepsService, + StudyPrefetcherService, } from './services'; import { DisplaySetMessage, DisplaySetMessageList } from './services/DisplaySetService'; @@ -86,6 +86,7 @@ const OHIF = { PanelService, useToolbar, WorkflowStepsService, + StudyPrefetcherService, }; export { @@ -131,6 +132,7 @@ export { Types, PanelService, WorkflowStepsService, + StudyPrefetcherService, useToolbar, }; diff --git a/platform/core/src/services/CustomizationService/CustomizationService.test.js b/platform/core/src/services/CustomizationService/CustomizationService.test.js index 763bd62e31..98c407fe9c 100644 --- a/platform/core/src/services/CustomizationService/CustomizationService.test.js +++ b/platform/core/src/services/CustomizationService/CustomizationService.test.js @@ -1,4 +1,4 @@ -import CustomizationService from './CustomizationService'; +import CustomizationService, { CustomizationType, MergeEnum } from './CustomizationService'; import log from '../../log'; jest.mock('../../log.js', () => ({ @@ -11,6 +11,8 @@ const extensionManager = { registeredExtensionIds: [], moduleEntries: {}, + getRegisteredExtensionIds: () => extensionManager.registeredExtensionIds, + getModuleEntry: function (id) { return this.moduleEntries[id]; }, @@ -49,6 +51,8 @@ describe('CustomizationService.ts', () => { configuration, commandsManager, }); + extensionManager.registeredExtensionIds = []; + extensionManager.moduleEntries = {}; }); describe('init', () => { @@ -101,7 +105,7 @@ describe('CustomizationService.ts', () => { configuration.testItem = testItem; customizationService.init(extensionManager); - const item = customizationService.getGlobalCustomization('testItem2', { + const item = customizationService.getCustomization('testItem2', { id: 'testItem2', customizationType: 'ohif.overlayItem', label: 'otherLabel', @@ -133,6 +137,7 @@ describe('CustomizationService.ts', () => { expect(customizationService.getGlobalCustomization('testItem')).toBeUndefined(); const item = customizationService.getModeCustomization('testItem'); + expect(item).not.toBeUndefined(); const props = { testAttribute: 'testAttrValue' }; const result = item.content(props); @@ -143,7 +148,7 @@ describe('CustomizationService.ts', () => { it('global customizations override modes', () => { extensionManager.registeredExtensionIds.push('@testExtension'); - extensionManager.moduleEntries['@testExtension.customizationModule.default'] = { + extensionManager.moduleEntries['@testExtension.customizationModule.global'] = { name: 'default', value: [ohifOverlayItem], }; @@ -160,5 +165,149 @@ describe('CustomizationService.ts', () => { expect(result.label).toBe(testItem.label); expect(result.value).toBe(props.testAttribute); }); + + it('mode customizations override default', () => { + extensionManager.registeredExtensionIds.push('@testExtension'); + extensionManager.moduleEntries['@testExtension.customizationModule.default'] = { + name: 'default', + value: [ohifOverlayItem, testItem], + }; + customizationService.init(extensionManager); + + // Add a mode customization that would otherwise fail below + customizationService.addModeCustomizations([{ ...testItem, label: 'other' }]); + + const item = customizationService.getCustomization('testItem'); + + const props = { testAttribute: 'testAttrValue' }; + const result = item.content(props); + expect(result.label).toBe('other'); + expect(result.value).toBe(props.testAttribute); + }); + }); + + describe('merge', () => { + it('appends to global configuration', () => { + customizationService.init(extensionManager); + + customizationService.setGlobalCustomization('appendSet', { + values: [{ id: 'one' }, { id: 'two' }], + }); + const appendSet = customizationService.getCustomization('appendSet'); + expect(appendSet.values.length).toBe(2); + + customizationService.setGlobalCustomization( + 'appendSet', + { + values: [{ id: 'three' }], + }, + MergeEnum.Append + ); + const appendSet2 = customizationService.getCustomization('appendSet'); + expect(appendSet2.values.length).toBe(3); + }); + + it('appends mode to default without touching default', () => { + customizationService.init(extensionManager); + + customizationService.setDefaultCustomization('appendSet', { + values: [{ id: 'one' }, { id: 'two' }], + }); + const appendSet = customizationService.get('appendSet'); + expect(appendSet.values.length).toBe(2); + + customizationService.setModeCustomization( + 'appendSet', + { + values: [{ id: 'three' }], + }, + MergeEnum.Append + ); + + expect(appendSet.values.length).toBe(2); + const appendSet2 = customizationService.getModeCustomization('appendSet'); + expect(appendSet2.values.length).toBe(3); + }); + + it('merges values by name/position', () => { + customizationService.init(extensionManager); + + customizationService.setDefaultCustomization('appendSet', { + values: [{ id: 'one', obj: { v: '5' }, list: [1, 2, 3] }, { id: 'two' }], + }); + const appendSet = customizationService.get('appendSet'); + expect(appendSet.values.length).toBe(2); + + customizationService.setModeCustomization( + 'appendSet', + { + values: [{ id: 'three', obj: { v: 2 }, list: [3, 2, 1, 4] }], + }, + MergeEnum.Merge, + ); + + const appendSet2 = customizationService.get('appendSet'); + const [value0] = appendSet2.values; + expect(value0.id).toBe('three'); + expect(value0.list).toEqual([3, 2, 1, 4]); + }); + + it('merges functions', () => { + customizationService.init(extensionManager); + + customizationService.setDefaultCustomization('appendSet', { + values: [{ f: () => 0, id: '0' }, { f: () => 5, id: '5' }], + }); + const appendSet = customizationService.get('appendSet'); + expect(appendSet.values.length).toBe(2); + + customizationService.setModeCustomization( + 'appendSet', + { + values: [{ f: () => 2, id: '2' }] + }, + MergeEnum.Merge, + ); + + const appendSet2 = customizationService.get('appendSet'); + const [value0, value1] = appendSet2.values; + expect(value0.f()).toBe(2); + expect(value1.f()).toBe(5); + }); + + it('merges list with object', () => { + customizationService.init(extensionManager); + + const destination = [ + 1, + { id: 'two', value: 2, list: [5, 6], }, + { id: 'three', value: 3 } + ]; + + const source = { + two: { value: 'updated2', list: { 0: 8 } }, + 1: { extraValue: 2, list: [7], }, + 1.0001: { id: 'inserted', value: 1.0001 }, + '-1': { + value: -3 + }, + }; + + customizationService.setDefaultCustomization('appendSet', { + values: destination, + }); + customizationService.setModeCustomization('appendSet', { + values: source, + }, MergeEnum.Append); + + const { values } = customizationService.getCustomization('appendSet'); + const [zero, one, two, three] = values; + expect(zero).toBe(1); + expect(one.value).toBe('updated2'); + expect(one.extraValue).toBe(2); + expect(one.list).toEqual([8, 6, 7]); + expect(two.id).toBe('inserted'); + expect(three.value).toBe(-3); + }); }); }); diff --git a/platform/core/src/services/CustomizationService/CustomizationService.ts b/platform/core/src/services/CustomizationService/CustomizationService.ts index 0d97a33076..4dd7d505a3 100644 --- a/platform/core/src/services/CustomizationService/CustomizationService.ts +++ b/platform/core/src/services/CustomizationService/CustomizationService.ts @@ -1,7 +1,9 @@ -import merge from 'lodash.merge'; +import { mergeWith, cloneDeepWith } from 'lodash'; + import { PubSubService } from '../_shared/pubSubServiceInterface'; -import { Customization, NestedStrings, Obj } from './types'; -import { CommandsManager } from '../../classes'; +import type { Customization, NestedStrings } from './types'; +import type { CommandsManager } from '../../classes'; +import type { ExtensionManager } from '../../extensions'; const EVENTS = { MODE_CUSTOMIZATION_MODIFIED: 'event::CustomizationService:modeModified', @@ -28,6 +30,27 @@ const flattenNestedStrings = ( return ret; }; +export enum MergeEnum { + /** + * Append values in the nested arrays + */ + Append = 'Append', + /** + * Merge values, replacing arrays + */ + Merge = 'Merge', + /** + * Replace the given value - this is the default + */ + Replace = 'Replace', +} + +export enum CustomizationType { + Global = 'Global', + Mode = 'Mode', + Default = 'Default', +} + /** * The CustomizationService allows for retrieving of custom components * and configuration for mode and global values. @@ -63,10 +86,34 @@ export default class CustomizationService extends PubSubService { }; commandsManager: CommandsManager; - extensionManager: Record; + extensionManager: ExtensionManager; + + /** + * mode customizations are changes to the default behaviour which are reset + * every time a new mode is entered. This allows the mode to define custom + * behaviour, and not interfere with other modes. + */ + private modeCustomizations = new Map(); + /** + * global customizations, are customizations which are set as a global default + * This allows changes across the board to be applied, essentially as a priority + * setting. + */ + private globalCustomizations = new Map(); + + /** + * Default customizations allow applying default values. The intent is that + * there is only one customization of that type, and it is registered at setup + * time. + */ + private defaultCustomizations = new Map(); + + /** + * Has the transformed/final customization value. This avoids needing to + * transform every time a customization is requested. + */ + private transformedCustomizations = new Map(); - modeCustomizations: Record = {}; - globalCustomizations: Record = {}; configuration: any; constructor({ configuration, commandsManager }) { @@ -77,83 +124,126 @@ export default class CustomizationService extends PubSubService { public init(extensionManager: ExtensionManager): void { this.extensionManager = extensionManager; + // Clear defaults as those are defined by the customization modules + this.defaultCustomizations.clear(); + // Clear modes because those are defined in onModeEnter functions. + this.modeCustomizations.clear(); this.initDefaults(); this.addReferences(this.configuration); } initDefaults(): void { - this.extensionManager.registeredExtensionIds.forEach(extensionId => { - const key = `${extensionId}.customizationModule.default`; - const defaultCustomizations = this.findExtensionValue(key); - if (!defaultCustomizations) { - return; + this.extensionManager.getRegisteredExtensionIds().forEach(extensionId => { + const keyDefault = `${extensionId}.customizationModule.default`; + const defaultCustomizations = this.findExtensionValue(keyDefault); + if (defaultCustomizations) { + const { value } = defaultCustomizations; + this.addReference(value, CustomizationType.Default); + } + const keyGlobal = `${extensionId}.customizationModule.global`; + const globalCustomizations = this.findExtensionValue(keyGlobal); + if (globalCustomizations) { + const { value } = globalCustomizations; + this.addReference(value, CustomizationType.Global); } - const { value } = defaultCustomizations; - this.addReference(value, true); }); } - findExtensionValue(value: string): Obj | void { + findExtensionValue(value: string) { const entry = this.extensionManager.getModuleEntry(value); - return entry; + return entry as { value: Customization }; } public onModeEnter(): void { super.reset(); - this.modeCustomizations = {}; + this.modeCustomizations.clear(); } - public getModeCustomizations(): Record { + public getModeCustomizations(): Map { return this.modeCustomizations; } - public setModeCustomization(customizationId: string, customization: Customization): void { - this.modeCustomizations[customizationId] = merge( - this.modeCustomizations[customizationId] || {}, - customization + public setModeCustomization( + customizationId: string, + customization: Customization, + merge = MergeEnum.Merge + ): void { + const defaultCustomization = this.defaultCustomizations.get(customizationId); + const modeCustomization = this.modeCustomizations.get(customizationId); + const globCustomization = this.globalCustomizations.get(customizationId); + const sourceCustomization = + modeCustomization || + (globCustomization && cloneDeepWith(globCustomization, cloneCustomizer)) || + defaultCustomization || + {}; + + // use the source merge type if not provided then fallback to merge + this.modeCustomizations.set( + customizationId, + this.mergeValue(sourceCustomization, customization, sourceCustomization.merge ?? merge) ); + this.transformedCustomizations.clear(); this._broadcastEvent(this.EVENTS.CUSTOMIZATION_MODIFIED, { buttons: this.modeCustomizations, - button: this.modeCustomizations[customizationId], + button: this.modeCustomizations.get(customizationId), }); } - /** This is the preferred getter for all customizations, - * getting mode customizations first and otherwise global customizations. + /** + * This is the preferred getter for all customizations, + * getting global (priority) customizations first, + * then mode customizations, and finally the default customization. * * @param customizationId - the customization id to look for - * @param defaultValue - is the default value to return. Note this value - * may have been extended with any customizationType extensions provided, - * so you cannot just use `|| defaultValue` + * @param defaultValue - is the default value to return. + * This value will be assigned as the default customization if there isn't + * currently a default customization, and thus, the first default provided + * will be used as the default - you cannot update this after or have it depend + * on changing values. + * Also, the value returned by the get customization has merges/updates applied, + * and is thus may be modified from the value provided, and may not be the original + * default provided. This allows applying the defaults for things like inheritance. * @return A customization to use if one is found, or the default customization, - * both enhanced with any customizationType inheritance (see transform) + * both enhanced with any customizationType inheritance (see transform) */ - public getCustomization( - customizationId: string, - defaultValue?: Customization - ): Customization | void { - return this.getModeCustomization(customizationId, defaultValue); + public getCustomization(customizationId: string, defaultValue?: Customization): Customization { + const transformed = this.transformedCustomizations.get(customizationId); + if (transformed) { + return transformed; + } + if (defaultValue && !this.defaultCustomizations.has(customizationId)) { + this.setDefaultCustomization(customizationId, defaultValue); + } + const customization = + this.globalCustomizations.get(customizationId) ?? + this.modeCustomizations.get(customizationId) ?? + this.defaultCustomizations.get(customizationId); + const newTransformed = this.transform(customization); + if (newTransformed !== undefined) { + this.transformedCustomizations.set(customizationId, newTransformed); + } + return newTransformed; } /** Mode customizations are changes to the behavior of the extensions * when running in a given mode. Reset clears mode customizations. - * Note that global customizations over-ride mode customizations. + * + * Note that global customizations over-ride mode customizations + * * @param defaultValue to return if no customization specified. */ - public getModeCustomization( - customizationId: string, - defaultValue?: Customization - ): Customization { - const customization = - this.globalCustomizations[customizationId] ?? - this.modeCustomizations[customizationId] ?? - defaultValue; - return this.transform(customization); - } + public getModeCustomization = this.getCustomization; + /** + * Returns true if there is a mode customization. Doesn't include defaults, but + * does return global overrides. + */ public hasModeCustomization(customizationId: string) { - return this.globalCustomizations[customizationId] || this.modeCustomizations[customizationId]; + return ( + this.globalCustomizations.has(customizationId) || this.modeCustomizations.has(customizationId) + ); } + /** * get is an alias for getModeCustomization, as it is the generic getter * which will return both mode and global customizations, and should be @@ -189,7 +279,7 @@ export default class CustomizationService extends PubSubService { if (!modeCustomizations) { return; } - this.addReferences(modeCustomizations, false); + this.addReferences(modeCustomizations, CustomizationType.Mode); this._broadcastModeCustomizationModified(); } @@ -206,16 +296,59 @@ export default class CustomizationService extends PubSubService { * Reset does NOT clear global customizations. */ getGlobalCustomization(id: string, defaultValue?: Customization): Customization | void { - return this.transform(this.globalCustomizations[id] ?? defaultValue); + return this.transform( + this.globalCustomizations.get(id) ?? this.defaultCustomizations.get(id) ?? defaultValue + ); + } + + /** + * Performs a merge, creating a new instance value - that is, not referencing + * the old one. This only works if you run once for the merge, so in general, + * the source value should be global, while the appends should be mode based. + * However, you can append to a global value too, as long as you ensure it + * only gets merged once. + */ + private mergeValue(oldValue, newValue, mergeType = MergeEnum.Replace) { + if (mergeType === MergeEnum.Replace) { + return newValue; + } + + const returnValue = mergeWith({}, oldValue, newValue, mergeType === MergeEnum.Append ? appendCustomizer : mergeCustomizer); + return returnValue; } - setGlobalCustomization(id: string, value: Customization): void { - this.globalCustomizations[id] = value; + public setGlobalCustomization(id: string, value: Customization, merge = MergeEnum.Replace): void { + const defaultCustomization = this.defaultCustomizations.get(id); + const globCustomization = this.globalCustomizations.get(id); + const sourceCustomization = + (globCustomization && cloneDeepWith(globCustomization, cloneCustomizer)) || + defaultCustomization || + {}; + this.globalCustomizations.set( + id, + this.mergeValue(sourceCustomization, value, value.merge ?? merge) + ); + this.transformedCustomizations.clear(); this._broadcastGlobalCustomizationModified(); } + public setDefaultCustomization( + id: string, + value: Customization, + merge = MergeEnum.Replace + ): void { + if (this.defaultCustomizations.has(id)) { + throw new Error(`Trying to update existing default for customization ${id}`); + } + this.transformedCustomizations.clear(); + this.defaultCustomizations.set( + id, + this.mergeValue(this.defaultCustomizations.get(id), value, merge) + ); + } + protected setConfigGlobalCustomization(configuration: AppConfigCustomization): void { - this.globalCustomizations = {}; + this.globalCustomizations.clear(); const keys = flattenNestedStrings(configuration.globalCustomizations); this.readCustomizationTypes(v => keys[v.name] && v.customization, this.globalCustomizations); @@ -235,7 +368,7 @@ export default class CustomizationService extends PubSubService { * A single reference is either an string to be loaded from a module, * or a customization itself. */ - addReference(value?: Obj | string, isGlobal = true, id?: string): void { + addReference(value?, type = CustomizationType.Global, id?: string, merge?: MergeEnum): void { if (!value) { return; } @@ -243,12 +376,16 @@ export default class CustomizationService extends PubSubService { const extensionValue = this.findExtensionValue(value); // The child of a reference is only a set of references when an array, // so call the addReference direct. It could be a secondary reference perhaps - this.addReference(extensionValue.value, isGlobal, extensionValue.name); + this.addReference(extensionValue.value, type, extensionValue.name, extensionValue.merge); } else if (Array.isArray(value)) { - this.addReferences(value, isGlobal); + this.addReferences(value, type); } else { const useId = value.id || id; - this[isGlobal ? 'setGlobalCustomization' : 'setModeCustomization'](useId as string, value); + const setName = + (type === CustomizationType.Global && 'setGlobalCustomization') || + (type === CustomizationType.Default && 'setDefaultCustomization') || + 'setModeCustomization'; + this[setName](useId as string, value, merge); } } @@ -257,19 +394,89 @@ export default class CustomizationService extends PubSubService { * or as an object whose key is the reference id, and the value is the string * or customization. */ - addReferences(references?: Obj | Obj[], isGlobal = true): void { + addReferences(references?, type = CustomizationType.Global): void { if (!references) { return; } if (Array.isArray(references)) { references.forEach(item => { - this.addReference(item, isGlobal); + this.addReference(item, type); }); } else { for (const key of Object.keys(references)) { const value = references[key]; - this.addReference(value, isGlobal, key); + this.addReference(value, type, key); } } } } + +/** + * Custom merging function, to handle merging arrays and copying functions + */ +function appendCustomizer(obj, src) { + if (Array.isArray(obj)) { + const srcArray = Array.isArray(src); + if (srcArray) { + return obj.concat(...src); + } + if (typeof src === 'object') { + const newList = obj.map(value => cloneDeepWith(value, cloneCustomizer)); + for (const [key, value] of Object.entries(src)) { + const { position, isMerge } = findPosition(key, value, newList); + if (isMerge) { + if (typeof obj[position] === 'object') { + newList[position] = mergeWith(Array.isArray(newList[position]) ? [] : {}, newList[position], value, appendCustomizer); + } else { + newList[position] = value; + } + } else { + newList.splice(position, 0, value); + } + } + return newList; + } + return obj.concat(src); + } + return cloneCustomizer(src); +} + +function mergeCustomizer(obj, src) { + return cloneCustomizer(src); +} + +function findPosition(key, value, newList) { + const numVal = Number(key); + const isNumeric = !isNaN(numVal); + const { length: len } = newList; + + if (isNumeric) { + if (newList[numVal < 0 ? numVal + len : numVal]) { + return { isMerge: true, position: (numVal + len) % len }; + } + const absPosition = Math.ceil(numVal < 0 ? len + numVal : numVal); + return { isMerge: false, position: Math.min(len, Math.max(absPosition, 0)) } + } + const findIndex = newList.findIndex(it => it.id === key); + if (findIndex !== -1) { + return { isMerge: true, position: findIndex }; + } + const { _priority: priority } = value; + if (priority !== undefined) { + if (newList[(priority + len) % len]) { + return { isMerge: true, position: (priority + len) % len }; + } + const absPosition = Math.ceil(priority < 0 ? len + priority : priority); + return { isMerge: false, position: Math.min(len, Math.max(absPosition, 0)) } + } + return { isMerge: false, position: len }; +} + +/** + * Custom cloning function to just copy function reference + */ +function cloneCustomizer(value) { + if (typeof value === 'function') { + return value; + } +} diff --git a/platform/core/src/services/DisplaySetService/DisplaySetService.ts b/platform/core/src/services/DisplaySetService/DisplaySetService.ts index 3db737c0cb..ac99224842 100644 --- a/platform/core/src/services/DisplaySetService/DisplaySetService.ts +++ b/platform/core/src/services/DisplaySetService/DisplaySetService.ts @@ -424,4 +424,24 @@ export default class DisplaySetService extends PubSubService { return result; } + + /** + * + * @param sortFn function to sort the display sets + * @param direction direction to sort the display sets + * @returns void + */ + public sortDisplaySets( + sortFn: (a: DisplaySet, b: DisplaySet) => number, + direction: string, + suppressEvent = false + ): void { + this.activeDisplaySets.sort(sortFn); + if (direction === 'descending') { + this.activeDisplaySets.reverse(); + } + if (!suppressEvent) { + this._broadcastEvent(EVENTS.DISPLAY_SETS_CHANGED, this.activeDisplaySets); + } + } } diff --git a/platform/core/src/services/HangingProtocolService/HangingProtocolService.ts b/platform/core/src/services/HangingProtocolService/HangingProtocolService.ts index 90c19c458c..f40b273244 100644 --- a/platform/core/src/services/HangingProtocolService/HangingProtocolService.ts +++ b/platform/core/src/services/HangingProtocolService/HangingProtocolService.ts @@ -6,7 +6,6 @@ import ProtocolEngine from './ProtocolEngine'; import { StudyMetadata } from '../../types/StudyMetadata'; import IDisplaySet from '../DisplaySetService/IDisplaySet'; import { CommandsManager } from '../../classes'; -import ServicesManager from '../ServicesManager'; import * as HangingProtocol from '../../types/HangingProtocol'; import { isDisplaySetFromUrl, sopInstanceLocation } from './custom-attribute/isDisplaySetFromUrl'; import numberOfDisplaySetsWithImages from './custom-attribute/numberOfDisplaySetsWithImages'; @@ -60,7 +59,7 @@ export default class HangingProtocolService extends PubSubService { stageIndex = 0; _commandsManager: CommandsManager; - _servicesManager: ServicesManager; + _servicesManager: AppTypes.ServicesManager; protocolEngine: ProtocolEngine; customViewportSettings = []; displaySets: IDisplaySet[] = []; @@ -136,7 +135,7 @@ export default class HangingProtocolService extends PubSubService { HangingProtocol.ViewportMatchDetails > = new Map(); - constructor(commandsManager: CommandsManager, servicesManager) { + constructor(commandsManager: CommandsManager, servicesManager: AppTypes.ServicesManager) { super(HangingProtocolService.EVENTS); this._commandsManager = commandsManager; this._servicesManager = servicesManager; @@ -601,24 +600,45 @@ export default class HangingProtocolService extends PubSubService { }; } - getViewportsRequireUpdate(viewportId, displaySetInstanceUID) { + /** + * This will return the viewports that need to be updated based on the + * hanging protocol layout and the displaySetInstanceUID that needs to be updated. + * + * This is useful, when for instance we drag and drop a displaySet into a viewport + * which is in MPR, and we need to update the other viewports that are showing the same + * layout. + * + * However, sometimes since we get out of sync with the hanging protocol layout, when + * the user use the custom grid layout, we should not update the other viewports, and that is + * when the isHangingProtocolLayout is set to false. + * + * @param viewportId - the id of the viewport that needs to be updated + * @param displaySetInstanceUID - the displaySetInstanceUID that needs to be updated + * @param isHangingProtocolLayout - whether the layout is a hanging protocol layout + * @returns + */ + getViewportsRequireUpdate(viewportId, displaySetInstanceUID, isHangingProtocolLayout = true) { + const newDisplaySetInstanceUID = displaySetInstanceUID; + const defaultReturn = [ + { + viewportId, + displaySetInstanceUIDs: [newDisplaySetInstanceUID], + }, + ]; + + if (!isHangingProtocolLayout) { + return defaultReturn; + } + const { displaySetService } = this._servicesManager.services; const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID); if (displaySet?.unsupported) { throw new Error('Unsupported displaySet'); } - const newDisplaySetInstanceUID = displaySetInstanceUID; const protocol = this.protocol; const protocolStage = protocol.stages[this.stageIndex]; const protocolViewports = protocolStage.viewports; - const defaultReturn = [ - { - viewportId, - displaySetInstanceUIDs: [newDisplaySetInstanceUID], - }, - ]; - if (!protocolViewports) { return defaultReturn; } @@ -1000,6 +1020,8 @@ export default class HangingProtocolService extends PubSubService { if (this.registeredImageLoadStrategies[imageLoadStrategy] instanceof Function) { this.activeImageLoadStrategyName = imageLoadStrategy; } + } else { + this.activeImageLoadStrategyName = null; } this._updateStageStatus(options); @@ -1084,9 +1106,9 @@ export default class HangingProtocolService extends PubSubService { options ): HangingProtocol.ViewportMatchDetails { if (this.protocol.id !== protocolId) { - throw new Error( - `Currently applied protocol ${this.protocol.id} is different from ${protocolId}` - ); + console.warn('setting protocol'); + this.protocol = this.getProtocolById(protocolId); + this.stageIndex = 0; } const protocol = this.protocol; const stage = protocol.stages[stageIdx]; @@ -1314,19 +1336,18 @@ export default class HangingProtocolService extends PubSubService { ); // Use the display set provided instead - // Todo: find out what is wrong here - // if (reuseDisplaySetUID) { - // if (viewportOptions.allowUnmatchedView !== true) { - // this.validateDisplaySetSelectMatch(viewportDisplaySet, id, reuseDisplaySetUID); - // } - // const displaySetInfo: HangingProtocol.DisplaySetInfo = { - // displaySetInstanceUID: reuseDisplaySetUID, - // displaySetOptions, - // }; - - // displaySetsInfo.push(displaySetInfo); - // return; - // } + if (reuseDisplaySetUID) { + if (viewportOptions.allowUnmatchedView !== true) { + this.validateDisplaySetSelectMatch(viewportDisplaySet, id, reuseDisplaySetUID); + } + const displaySetInfo: HangingProtocol.DisplaySetInfo = { + displaySetInstanceUID: reuseDisplaySetUID, + displaySetOptions, + }; + + displaySetsInfo.push(displaySetInfo); + return; + } // Use the display set index to allow getting the "next" match, eg // matching all display sets, and get the matchedDisplaySetsIndex'th item diff --git a/platform/core/src/services/HangingProtocolService/custom-attribute/isDisplaySetFromUrl.ts b/platform/core/src/services/HangingProtocolService/custom-attribute/isDisplaySetFromUrl.ts index 20ebb76fe4..0689e0c050 100644 --- a/platform/core/src/services/HangingProtocolService/custom-attribute/isDisplaySetFromUrl.ts +++ b/platform/core/src/services/HangingProtocolService/custom-attribute/isDisplaySetFromUrl.ts @@ -13,15 +13,16 @@ const isDisplaySetFromUrl = (displaySet): boolean => { if (!initialSeriesInstanceUID && !initialSOPInstanceUID) { return false; } - const isSeriesMatch = - !initialSeriesInstanceUID || - initialSeriesInstanceUID.some(seriesUID => displaySet.SeriesInstanceUID === seriesUID); - const isSopMatch = - !initialSOPInstanceUID || - displaySet.instances?.some?.(instance => - initialSOPInstanceUID.some(sopUID => sopUID === instance.SOPInstanceUID) - ); - return isSeriesMatch && isSopMatch; + + const isSeriesMatch = initialSeriesInstanceUID?.some( + seriesUID => displaySet.SeriesInstanceUID === seriesUID + ); + + const isSopMatch = initialSOPInstanceUID?.some(sopUID => + displaySet.instances?.some(instance => sopUID === instance.SOPInstanceUID) + ); + + return isSeriesMatch || isSopMatch; }; /** Returns the index location of the requested image, or the defaultValue in this. diff --git a/platform/core/src/services/MeasurementService/MeasurementService.ts b/platform/core/src/services/MeasurementService/MeasurementService.ts index 7f8c974898..35383f89a2 100644 --- a/platform/core/src/services/MeasurementService/MeasurementService.ts +++ b/platform/core/src/services/MeasurementService/MeasurementService.ts @@ -60,6 +60,7 @@ const MEASUREMENT_SCHEMA_KEYS = [ 'cachedStats', 'selected', 'textBox', + 'referencedImageId', ]; const EVENTS = { diff --git a/platform/core/src/services/PanelService/PanelService.tsx b/platform/core/src/services/PanelService/PanelService.tsx index 06795f4f20..0368b1a6ca 100644 --- a/platform/core/src/services/PanelService/PanelService.tsx +++ b/platform/core/src/services/PanelService/PanelService.tsx @@ -107,8 +107,8 @@ export default class PanelService extends PubSubService { // stack the content of the panels in one react component content = () => ( <> - {panelsData.map(({ content: PanelContent }) => ( - + {panelsData.map(({ content: PanelContent }, index) => ( + ))} ); diff --git a/platform/core/src/services/ServicesManager.ts b/platform/core/src/services/ServicesManager.ts index fb96db0f96..a73ff9a45f 100644 --- a/platform/core/src/services/ServicesManager.ts +++ b/platform/core/src/services/ServicesManager.ts @@ -1,10 +1,9 @@ import log from './../log.js'; -import Services from '../types/Services'; import CommandsManager from '../classes/CommandsManager'; import ExtensionManager from '../extensions/ExtensionManager'; export default class ServicesManager { - public services: Services = {}; + public services: AppTypes.Services = {}; public registeredServiceNames: string[] = []; private _commandsManager: CommandsManager; private _extensionManager: ExtensionManager; @@ -53,7 +52,7 @@ export default class ServicesManager { extensionManager: this._extensionManager, }); if (service.altName) { - console.log('Registering old name', service.altName); + // TODO - remove this registration this.services[service.altName] = this.services[service.name]; } } else { diff --git a/platform/core/src/services/StudyPrefetcherService/StudyPrefetcherService.ts b/platform/core/src/services/StudyPrefetcherService/StudyPrefetcherService.ts new file mode 100644 index 0000000000..3edf20525d --- /dev/null +++ b/platform/core/src/services/StudyPrefetcherService/StudyPrefetcherService.ts @@ -0,0 +1,686 @@ +import { PubSubService } from '../_shared/pubSubServiceInterface'; +import { ExtensionManager } from '../../extensions'; +import ServicesManager from '../ServicesManager'; +import ViewportGridService from '../ViewportGridService'; +import { DisplaySet } from '../../types'; + +const IMAGE_REQUEST_TYPE = 'prefetch'; + +export const EVENTS = { + SERVICE_STARTED: 'event::studyPrefetcherService:started', + SERVICE_STOPPED: 'event::studyPrefetcherService:stopped', + DISPLAYSET_LOAD_PROGRESS: 'event::studyPrefetcherService:displaySetLoadProgress', + DISPLAYSET_LOAD_COMPLETE: 'event::studyPrefetcherService:displaySetLoadComplete', +}; + +/** + * Order used for prefetching display set + */ +enum StudyPrefetchOrder { + closest = 'closest', + downward = 'downward', + upward = 'upward', +} + +/** + * Study Prefetcher configuration + */ +type StudyPrefetcherConfig = { + /* Enable/disable study prefetching service */ + enabled: boolean; + /* Number of displaysets to be prefetched */ + displaySetsCount: number; + /** + * Max number of concurrent prefetch requests + * High numbers may impact on the time to load a new dropped series because + * the browser will be busy with all prefetching requests. As soon as the + * prefetch requests get fulfilled the new ones from the new dropped series + * are sent to the server. + * + * TODO: abort all prefetch requests when a new series is loaded on a viewport. + * (need to add support for `AbortController` on Cornerstone) + * */ + maxNumPrefetchRequests: number; + /* Display sets prefetching order (closest, downward and upward) */ + order: StudyPrefetchOrder; +}; + +type DisplaySetLoadingState = { + displaySetInstanceUID: string; + numInstances: number; + pendingImageIds: Set; + loadedImageIds: Set; + failedImageIds: Set; + loadingProgress: number; +}; + +type ImageRequest = { + displaySetInstanceUID: string; + imageId: string; + aborted: boolean; +}; + +type PubSubServiceSubscription = { unsubscribe: () => any }; + +interface ICache { + isImageCached(imageId: string): boolean; +} + +interface IImageLoadPoolManager { + addRequest ( + requestFn: () => Promise, + type: string, + additionalDetails: Record, + priority?: number + ); + clearRequestStack(type: string): void; +} + +interface IImageLoader { + loadAndCacheImage(imageId: string, options: any): Promise; +} + +type EventSubscription = { + unsubscribe: () => void +}; + +interface IImageLoadEventsManager { + addEventListeners( + onImageLoaded: (evt: any) => void, + onImageLoadFailed: (evt: any) => void + ): EventSubscription[]; +} + +class StudyPrefetcherService extends PubSubService { + private _extensionManager: ExtensionManager; + private _servicesManager: ServicesManager; + private _subscriptions: PubSubServiceSubscription[]; + private _activeDisplaySetsInstanceUIDs: string[] = []; + private _pendingRequests: ImageRequest[] = []; + private _inflightRequests = new Map(); + private _isRunning = false; + private _displaySetLoadingStates = new Map(); + private _imageIdsToDisplaySetsMap = new Map>(); + private config: StudyPrefetcherConfig = { + /* Enable/disable study prefetching service */ + enabled: false, + /* Number of displaysets to be prefetched */ + displaySetsCount: 1, + /** + * Max number of concurrent prefetch requests + * High numbers may impact on the time to load a new dropped series because + * the browser will be busy with all prefetching requests. As soon as the + * prefetch requests get fulfilled the new ones from the new dropped series + * are sent to the server. + * + * TODO: abort all prefetch requests when a new series is loaded on a viewport. + * (need to add support for `AbortController` on Cornerstone) + * */ + maxNumPrefetchRequests: 10, + /* Display sets prefetching order (closest, downward and upward) */ + order: StudyPrefetchOrder.downward, + }; + + // Properties set by Cornerstone extension (initStudyPrefetcherService) + public requestType: string = IMAGE_REQUEST_TYPE; + public cache: ICache; + public imageLoadPoolManager: IImageLoadPoolManager; + public imageLoader: IImageLoader; + public imageLoadEventsManager: IImageLoadEventsManager; + + public static REGISTRATION = { + name: 'studyPrefetcherService', + altName: 'StudyPrefetcherService', + create: ({ configuration, servicesManager, extensionManager }): StudyPrefetcherService => { + return new StudyPrefetcherService({ + servicesManager, + extensionManager, + configuration, + }); + }, + }; + + constructor({ + servicesManager, + extensionManager, + configuration, + }: { + servicesManager: ServicesManager; + extensionManager: ExtensionManager; + configuration: StudyPrefetcherConfig; + }) { + super(EVENTS); + + this._servicesManager = servicesManager; + this._extensionManager = extensionManager; + this._subscriptions = []; + + Object.assign(this.config, configuration); + } + + public onModeEnter(): void { + this._addEventListeners(); + } + + /** + * The onModeExit returns the service to the initial state. + */ + public onModeExit(): void { + this._removeEventListeners(); + this._stopPrefetching(); + } + + private _addImageLoadingEventsListeners() { + const fnOnImageLoadCompleted = (imageId: string) => { + // `sendNextRequests` must be called after image loaded/failed events + // to make sure prefetch requests shall be sent as soon as the active + // displaySets (active viewport) are loaded. + // + // PS: active display sets are not loaded by this service and that is why + // the requests shall not be in the inflight queue. + if (!this._inflightRequests.get(imageId)) { + this._sendNextRequests(); + } + } + + const fnImageLoadedEventListener = (evt) => { + const { image } = evt.detail; + const { imageId } = image; + + this._moveImageIdToLoadedSet(imageId); + fnOnImageLoadCompleted(imageId); + } + + const fnImageLoadFailedEventListener = (evt) => { + const { imageId } = evt.detail; + + this._moveImageIdToFailedSet(imageId); + fnOnImageLoadCompleted(imageId); + } + + return this.imageLoadEventsManager.addEventListeners( + fnImageLoadedEventListener, + fnImageLoadFailedEventListener + ); + } + + private _addServicesListeners() { + const { displaySetService, viewportGridService } = this._servicesManager.services; + + // Restart the prefetcher after any change to the displaySets + // (eg: sorting the displaySets on StudyBrowser) + const displaySetsChangedSubscription = displaySetService.subscribe( + displaySetService.EVENTS.DISPLAY_SETS_CHANGED, + () => this._syncWithActiveViewport({ forceRestart: true }) + ); + + // Loads new datasets when making a new viewport active + const viewportGridActiveViewportIdSubscription = viewportGridService.subscribe( + ViewportGridService.EVENTS.ACTIVE_VIEWPORT_ID_CHANGED, + ({ viewportId }) => this._syncWithActiveViewport({ activeViewportId: viewportId }) + ); + + // Continue loading datasets after changing the layout (eg: from 1x1 to 2x1) + const viewportGridLayoutChangedSubscription = viewportGridService.subscribe( + ViewportGridService.EVENTS.LAYOUT_CHANGED, + () => this._syncWithActiveViewport() + ); + + // Loads new datasets after loading a new display set on a viewport + const viewportGridStateChangedSubscription = viewportGridService.subscribe( + ViewportGridService.EVENTS.GRID_STATE_CHANGED, + () => this._syncWithActiveViewport() + ); + + // Loads the first datasets right after opening the viewer + const viewportGridViewportreadySubscription = viewportGridService.subscribe( + ViewportGridService.EVENTS.VIEWPORTS_READY, + () => { + this._syncWithActiveViewport(); + this._startPrefetching(); + } + ); + + return [ + displaySetsChangedSubscription, + viewportGridActiveViewportIdSubscription, + viewportGridLayoutChangedSubscription, + viewportGridStateChangedSubscription, + viewportGridViewportreadySubscription + ]; + } + + private _addEventListeners() { + const imageLoadingEventsSubscriptions = this._addImageLoadingEventsListeners(); + const servicesSubscriptions = this._addServicesListeners(); + + this._subscriptions.push(...imageLoadingEventsSubscriptions); + this._subscriptions.push(...servicesSubscriptions); + } + + private _removeEventListeners() { + this._subscriptions.forEach(subscription => subscription.unsubscribe()); + this._subscriptions = []; + } + + private _syncWithActiveViewport( + { + activeViewportId, + forceRestart + }: + { + activeViewportId?: string, + forceRestart?: boolean + } = {}) { + const { viewportGridService } = this._servicesManager.services; + const viewportGridServiceState = viewportGridService.getState(); + const { viewports } = viewportGridServiceState; + + activeViewportId = activeViewportId ?? viewportGridServiceState.activeViewportId; + + // If may be null when the viewer is loaded + if (!activeViewportId) { + return; + } + + const activeViewport = viewports.get(activeViewportId); + const displaySetUpdated = this._setActiveDisplaySetsUIDs(activeViewport.displaySetInstanceUIDs); + + if (forceRestart || displaySetUpdated) { + this._restartPrefetching(); + } + } + + private _setActiveDisplaySetsUIDs(newActiveDisplaySetInstanceUIDs: string[]): boolean { + const sameDisplaySets = + newActiveDisplaySetInstanceUIDs.length === this._activeDisplaySetsInstanceUIDs.length && + newActiveDisplaySetInstanceUIDs.every(uid => + this._activeDisplaySetsInstanceUIDs.includes(uid) + ); + + if (sameDisplaySets) { + return false; + } + + this._activeDisplaySetsInstanceUIDs = [...newActiveDisplaySetInstanceUIDs]; + this._restartPrefetching(); + + return true; + } + + private _areActiveDisplaySetsLoaded() { + const { _activeDisplaySetsInstanceUIDs: displaySetsInstanceUIDs } = this; + + return displaySetsInstanceUIDs.length && displaySetsInstanceUIDs.every(displaySetsInstanceUID => + this._displaySetLoadingStates.get(displaySetsInstanceUID).loadingProgress >= 1); + } + + private _getClosestDisplaySets(displaySets: DisplaySet[], activeDisplaySetIndex: number) { + const sortedDisplaySets = []; + let previousIndex = activeDisplaySetIndex - 1; + let nextIndex = activeDisplaySetIndex + 1; + + while (previousIndex >= 0 || nextIndex < displaySets.length) { + if (previousIndex >= 0) { + sortedDisplaySets.push(displaySets[previousIndex]); + previousIndex--; + } + + if (nextIndex < displaySets.length) { + sortedDisplaySets.push(displaySets[nextIndex]); + nextIndex++; + } + } + + return sortedDisplaySets; + } + + private _getDownwardDisplaySets(displaySets: DisplaySet[], activeDisplaySetIndex: number) { + const sortedDisplaySets = []; + + for (let i = activeDisplaySetIndex + 1; i < displaySets.length; i++) { + sortedDisplaySets.push(displaySets[i]); + } + + return sortedDisplaySets; + } + + private _getUpwardDisplaySets(displaySets: DisplaySet[], activeDisplaySetIndex: number) { + const sortedDisplaySets = []; + + for (let i = activeDisplaySetIndex - 1; i >= 0 && i !== activeDisplaySetIndex; i--) { + sortedDisplaySets.push(displaySets[i]); + } + + return sortedDisplaySets; + } + + private _getSortedDisplaySetsToPrefetch(displaySets: DisplaySet[]): DisplaySet[] { + if (!this._activeDisplaySetsInstanceUIDs?.length) { + return []; + } + + const { displaySetsCount } = this.config; + const activeDisplaySetsInstanceUIDs = this._activeDisplaySetsInstanceUIDs; + const [activeDisplaySetUID] = activeDisplaySetsInstanceUIDs; + const activeDisplaySetIndex = displaySets.findIndex(ds => ds.displaySetInstanceUID === activeDisplaySetUID); + const getDisplaySetsFunctionsMap = { + [StudyPrefetchOrder.closest]: this._getClosestDisplaySets, + [StudyPrefetchOrder.downward]: this._getDownwardDisplaySets, + [StudyPrefetchOrder.upward]: this._getUpwardDisplaySets, + }; + const { order } = this.config; + const fnGetDisplaySets = getDisplaySetsFunctionsMap[order]; + + if (!fnGetDisplaySets) { + throw new Error(`Invalid order (${order})`); + } + + // Creates a `Set` to look for UIDs in O(1) instead of O(n) + const uidsSet = new Set(activeDisplaySetsInstanceUIDs); + + // Remove any active displaySet that may still be in the activeDisplaySetsInstanceUIDs. + // That may happen when activeDisplaySetsInstanceUIDs has more than one element. + return fnGetDisplaySets.call(this, displaySets, activeDisplaySetIndex).filter( + ds => !uidsSet.has(ds.displaySetInstanceUID) + ).slice(0, displaySetsCount); + } + + private _getDisplaySets() { + const { displaySetService } = this._servicesManager.services; + const displaySets = [...displaySetService.getActiveDisplaySets()]; + let displaySetsToPrefetch = this._getSortedDisplaySetsToPrefetch(displaySets); + + return { displaySets, displaySetsToPrefetch }; + } + + private _updateImageIdsDisplaySetMap( + displaySetInstanceUID: string, + imageIds: string[] + ): void { + for (const imageId of imageIds) { + let displaySetsInstanceUIDsMap = this._imageIdsToDisplaySetsMap.get(imageId); + + if (!displaySetsInstanceUIDsMap) { + displaySetsInstanceUIDsMap = new Set(); + this._imageIdsToDisplaySetsMap.set(imageId, displaySetsInstanceUIDsMap); + } + + displaySetsInstanceUIDsMap.add(displaySetInstanceUID); + } + } + + private _getImageIdsForDisplaySet(displaySet: DisplaySet): string[] { + const dataSource = this._extensionManager.getActiveDataSource()[0]; + + return dataSource.getImageIdsForDisplaySet(displaySet); + } + + private _updateDisplaySetLoadingProgress(displaySetLoadingState: DisplaySetLoadingState) { + const { numInstances, loadedImageIds, failedImageIds } = displaySetLoadingState; + const loadingProgress = (loadedImageIds.size + failedImageIds.size) / numInstances; + + displaySetLoadingState.loadingProgress = loadingProgress; + } + + private _addDisplaySetLoadingState(displaySet: DisplaySet): void { + const { displaySetInstanceUID } = displaySet; + const imageIds = this._getImageIdsForDisplaySet(displaySet); + let displaySetLoadingState = this._displaySetLoadingStates.get(displaySetInstanceUID); + + if (displaySetLoadingState) { + return; + } + + const pendingImageIds = new Set(imageIds); + const loadedImageIds = new Set(); + + // Needs to check which image is already loaded to update the progress properly + // because some images may already be loaded (thumbnails and viewports). + for (const imageId of imageIds) { + if (this.cache.isImageCached(imageId)) { + loadedImageIds.add(imageId); + } else { + pendingImageIds.add(imageId); + } + } + + displaySetLoadingState = { + displaySetInstanceUID, + numInstances: imageIds.length, + pendingImageIds, + loadedImageIds, + failedImageIds: new Set(), + loadingProgress: 0 + }; + + this._updateDisplaySetLoadingProgress(displaySetLoadingState); + this._displaySetLoadingStates.set(displaySetInstanceUID, displaySetLoadingState); + this._updateImageIdsDisplaySetMap(displaySetInstanceUID, imageIds) + + // Notify the UI that something is already loaded (eg: update StudyBrowser) + if (loadedImageIds.size) { + this._triggerDisplaySetEvents(displaySetInstanceUID); + } + } + + private _loadDisplaySets() { + const { displaySets, displaySetsToPrefetch } = this._getDisplaySets(); + + displaySets.forEach(displaySet => this._addDisplaySetLoadingState(displaySet)); + displaySetsToPrefetch.forEach(displaySet => this._enqueueDisplaySetImagesRequests(displaySet)); + } + + private _moveImageIdToLoadedSet(imageId: string): boolean { + const displaySetsInstanceUIDs = this._imageIdsToDisplaySetsMap.get(imageId); + + if (!displaySetsInstanceUIDs) { + return; + } + + for (const displaySetInstanceUID of Array.from(displaySetsInstanceUIDs.values())) { + const displaySetLoadingState = this._displaySetLoadingStates.get(displaySetInstanceUID); + const { pendingImageIds, loadedImageIds } = displaySetLoadingState; + + pendingImageIds.delete(imageId); + loadedImageIds.add(imageId); + + this._updateDisplaySetLoadingProgress(displaySetLoadingState); + this._triggerDisplaySetEvents(displaySetInstanceUID); + } + + return true; + } + + private _moveImageIdToFailedSet(imageId: string): boolean { + const displaySetsInstanceUIDs = this._imageIdsToDisplaySetsMap.get(imageId); + + if (!displaySetsInstanceUIDs) { + return; + } + + for (const displaySetInstanceUID of Array.from(displaySetsInstanceUIDs.values())) { + const displaySetLoadingState = this._displaySetLoadingStates.get(displaySetInstanceUID); + const { pendingImageIds, failedImageIds } = displaySetLoadingState; + + pendingImageIds.delete(imageId); + failedImageIds.add(imageId); + + this._updateDisplaySetLoadingProgress(displaySetLoadingState); + this._triggerDisplaySetEvents(displaySetInstanceUID); + } + + return true; + } + + private _triggerDisplaySetEvents(displaySetInstanceUID: string) { + const displaySetLoadingState = this._displaySetLoadingStates.get(displaySetInstanceUID); + const { loadingProgress, numInstances } = displaySetLoadingState; + + this._broadcastEvent(this.EVENTS.DISPLAYSET_LOAD_PROGRESS, { + displaySetInstanceUID, + numInstances, + loadingProgress, + }); + + if (loadingProgress >= 1) { + this._broadcastEvent(this.EVENTS.DISPLAYSET_LOAD_COMPLETE, { + displaySetInstanceUID, + }); + } + } + + private _onImagePrefetchSuccess(imageRequest: ImageRequest) { + if (imageRequest.aborted) { + return; + } + + const { imageId } = imageRequest; + + this._inflightRequests.delete(imageId); + this._moveImageIdToLoadedSet(imageId); + + // `sendNextRequests` must be called after removing the request from the inflight + // queue otherwise it shall not be able to send the request (maxNumPrefetchRequests) + this._sendNextRequests(); + } + + private _onImagePrefetchFailed(imageRequest, error) { + if (imageRequest.aborted) { + return; + } + + console.warn(`An error ocurred when trying to load "${imageRequest.imageId}"`, error); + + const { imageId } = imageRequest; + + this._inflightRequests.delete(imageId); + this._moveImageIdToFailedSet(imageId); + + // `sendNextRequests` must be called after removing the request from the inflight + // queue otherwise it shall not be able to send the request (maxNumPrefetchRequests) + this._sendNextRequests(); + } + + private async _sendNextRequests() { + // If the service has stopped with async requests in progress this method may + // get called again when each of those requests are fulfilled. + if (!this._isRunning) { + return; + } + + // Does not send any prefetch request until the active display sets are loaded + if (!this._areActiveDisplaySetsLoaded()) { + return; + } + + const { _pendingRequests: pendingRequests, _inflightRequests: inflightRequests } = this; + const { maxNumPrefetchRequests } = this.config; + + if (!pendingRequests.length || inflightRequests.size >= maxNumPrefetchRequests) { + return; + } + + const numImageRequests = Math.min( + pendingRequests.length, + maxNumPrefetchRequests - inflightRequests.size + ); + const imageRequests = this._pendingRequests.splice(0, numImageRequests); + + imageRequests.forEach(imageRequest => { + const { imageId } = imageRequest; + const options = { + priority: -5, + requestType: this.requestType, + additionalDetails: { imageId }, + preScale: { + enabled: true, + }, + }; + + this.imageLoadPoolManager.addRequest( + async () => + this.imageLoader.loadAndCacheImage(imageId, options).then( + _image => this._onImagePrefetchSuccess(imageRequest), + error => this._onImagePrefetchFailed(imageRequest, error) + ), + this.requestType, + { imageId } + ); + + inflightRequests.set(imageId, imageRequest); + }); + } + + private _enqueueDisplaySetImagesRequests(displaySet: DisplaySet) { + const { displaySetInstanceUID } = displaySet; + const imageIds = this._getImageIdsForDisplaySet(displaySet); + + imageIds.forEach(imageId => { + if (this.cache.isImageCached(imageId)) { + this._moveImageIdToLoadedSet(imageId); + return; + } + + this._pendingRequests.push({ + displaySetInstanceUID, + imageId, + aborted: false, + }); + }); + } + + /** + * Start prefetching the display sets based on the active viewport and app configuration. + */ + private _startPrefetching(): void { + if (this._isRunning) { + return; + } + + if (!this.config.enabled) { + console.log('StudyPrefetcher is not enabled'); + return; + } + + this._isRunning = true; + + this._loadDisplaySets(); + this._sendNextRequests(); + this._broadcastEvent(this.EVENTS.SERVICE_STARTED, {}); + } + + /** + * Stop prefetching the display sets. + * All internal variables are cleared but activeDisplaySetsInstanceUIDs otherwise restart would not work. + */ + private _stopPrefetching(): void { + if (!this._isRunning) { + return; + } + this._isRunning = false; + + // Mark all inflight requests as aborted before clearing the map. + this._inflightRequests.forEach(inflightRequest => (inflightRequest.aborted = true)); + + this._pendingRequests = []; + this._displaySetLoadingStates.clear(); + this._imageIdsToDisplaySetsMap.clear(); + this._inflightRequests.clear(); + this.imageLoadPoolManager.clearRequestStack(IMAGE_REQUEST_TYPE); + + this._broadcastEvent(this.EVENTS.SERVICE_STOPPED, {}); + } + + /** + * Restart prefetching in case it is already running. + */ + private _restartPrefetching(): void { + if (this._isRunning) { + this._stopPrefetching(); + this._startPrefetching(); + } + } +} + +export { StudyPrefetcherService as default, StudyPrefetcherService }; diff --git a/platform/core/src/services/StudyPrefetcherService/index.ts b/platform/core/src/services/StudyPrefetcherService/index.ts new file mode 100644 index 0000000000..51c22299cd --- /dev/null +++ b/platform/core/src/services/StudyPrefetcherService/index.ts @@ -0,0 +1,3 @@ +import { StudyPrefetcherService } from './StudyPrefetcherService'; + +export { StudyPrefetcherService as default, StudyPrefetcherService }; diff --git a/platform/core/src/services/ToolBarService/ToolbarService.ts b/platform/core/src/services/ToolBarService/ToolbarService.ts index b9dfea404b..7d80f843af 100644 --- a/platform/core/src/services/ToolBarService/ToolbarService.ts +++ b/platform/core/src/services/ToolBarService/ToolbarService.ts @@ -2,7 +2,6 @@ import { CommandsManager } from '../../classes'; import { ExtensionManager } from '../../extensions'; import { PubSubService } from '../_shared/pubSubServiceInterface'; import type { RunCommand } from '../../types/Command'; -import ServicesManager from '../ServicesManager'; import { Button, ButtonProps, EvaluateFunction, EvaluatePublic, NestedButtonProps } from './types'; const EVENTS = { @@ -52,14 +51,14 @@ export default class ToolbarService extends PubSubService { _commandsManager: CommandsManager; _extensionManager: ExtensionManager; - _servicesManager: ServicesManager; + _servicesManager: AppTypes.ServicesManager; _evaluateFunction: Record = {}; _serviceSubscriptions = []; constructor( commandsManager: CommandsManager, extensionManager: ExtensionManager, - servicesManager: ServicesManager + servicesManager: AppTypes.ServicesManager ) { super(EVENTS); this._commandsManager = commandsManager; @@ -156,7 +155,7 @@ export default class ToolbarService extends PubSubService { const itemId = interaction.itemId ?? interaction.id; interaction.itemId = itemId; - const commands = Array.isArray(interaction.commands) + let commands = Array.isArray(interaction.commands) ? interaction.commands : [interaction.commands]; @@ -170,6 +169,27 @@ export default class ToolbarService extends PubSubService { const commandOptions = { ...options, ...interaction }; + commands = commands.map(command => { + if (typeof command === 'function') { + return () => { + command({ + ...commandOptions, + commandsManager: this._commandsManager, + servicesManager: this._servicesManager, + }); + }; + } + + return command; + }); + + // if still no commands, return + commands = commands.filter(Boolean); + + if (!commands.length) { + return; + } + // Loop through commands and run them with the combined options this._commandsManager.run(commands, commandOptions); @@ -377,6 +397,26 @@ export default class ToolbarService extends PubSubService { ); } + /** + * Retrieves the tool name for a given button. + * @param button - The button object. + * @returns The tool name associated with the button. + */ + getToolNameForButton(button) { + const { props } = button; + + const commands = props?.commands || button.commands; + const commandsArray = Array.isArray(commands) ? commands : [commands]; + const firstCommand = commandsArray[0]; + + if (firstCommand?.commandOptions) { + return firstCommand.commandOptions.toolName ?? props?.id ?? button.id; + } + + // use id as a fallback for toolName + return props?.id ?? button.id; + } + /** * * @param {*} btn @@ -438,7 +478,11 @@ export default class ToolbarService extends PubSubService { } if (Array.isArray(evaluate)) { - const evaluators = evaluate.map(evaluatorName => { + const evaluators = evaluate.map(evaluator => { + const isObject = typeof evaluator === 'object'; + + const evaluatorName = isObject ? evaluator.name : evaluator; + const evaluateFunction = this._evaluateFunction[evaluatorName]; if (!evaluateFunction) { @@ -447,6 +491,10 @@ export default class ToolbarService extends PubSubService { ); } + if (isObject) { + return args => evaluateFunction({ ...args, ...evaluator }); + } + return evaluateFunction; }); diff --git a/platform/core/src/services/UIDialogService/UIDialogService.ts b/platform/core/src/services/UIDialogService/UIDialogService.ts new file mode 100644 index 0000000000..079a1943ae --- /dev/null +++ b/platform/core/src/services/UIDialogService/UIDialogService.ts @@ -0,0 +1,80 @@ +import { PubSubService } from '../_shared/pubSubServiceInterface'; + +class UIDialogService extends PubSubService { + public static readonly EVENTS = {}; + + public static REGISTRATION = { + name: 'uiDialogService', + altName: 'UIDialogService', + create: ({ configuration = {} }) => { + return new UIDialogService(); + }, + }; + + serviceImplementation = { + _dismiss: () => console.warn('dismiss() NOT IMPLEMENTED'), + _dismissAll: () => console.warn('dismissAll() NOT IMPLEMENTED'), + _create: () => console.warn('create() NOT IMPLEMENTED'), + }; + + constructor() { + super(UIDialogService.EVENTS); + this.serviceImplementation = { + ...this.serviceImplementation, + }; + } + + public create({ + id, + content, + contentProps, + onStart, + onDrag, + onStop, + centralize = false, + preservePosition = true, + isDraggable = true, + showOverlay = false, + defaultPosition, + }) { + return this.serviceImplementation._create({ + id, + content, + contentProps, + onStart, + onDrag, + onStop, + centralize, + preservePosition, + isDraggable, + showOverlay, + defaultPosition, + }); + } + + public dismiss({ id }) { + return this.serviceImplementation._dismiss({ id }); + } + + public dismissAll() { + return this.serviceImplementation._dismissAll(); + } + + public setServiceImplementation({ + dismiss: dismissImplementation, + dismissAll: dismissAllImplementation, + create: createImplementation, + }) { + if (dismissImplementation) { + this.serviceImplementation._dismiss = dismissImplementation; + } + if (dismissAllImplementation) { + this.serviceImplementation._dismissAll = dismissAllImplementation; + } + if (createImplementation) { + this.serviceImplementation._create = createImplementation; + } + } +} + +export default UIDialogService; diff --git a/platform/core/src/services/UIDialogService/index.js b/platform/core/src/services/UIDialogService/index.js deleted file mode 100644 index dfa38c63cb..0000000000 --- a/platform/core/src/services/UIDialogService/index.js +++ /dev/null @@ -1,131 +0,0 @@ -/** - * A UI Element Position - * - * @typedef {Object} ElementPosition - * @property {number} top - - * @property {number} left - - * @property {number} right - - * @property {number} bottom - - */ - -/** - * UI Dialog - * - * @typedef {Object} DialogProps - * @property {string} id The dialog id. - * @property {ReactElement|HTMLElement} content The dialog content. - * @property {Object} contentProps The dialog content props. - * @property {boolean} [isDraggable=true] Controls if dialog content is draggable or not. - * @property {boolean} [showOverlay=false] Controls dialog overlay. - * @property {boolean} [centralize=false] Center the dialog on the screen. - * @property {boolean} [preservePosition=true] Use last position instead of default. - * @property {ElementPosition} defaultPosition Specifies the `x` and `y` that the dragged item should start at. - * @property {Function} onStart Called when dragging starts. If `false` is returned any handler, the action will cancel. - * @property {Function} onStop Called when dragging stops. - * @property {Function} onDrag Called while dragging. - */ - -const name = 'uiDialogService'; - -const publicAPI = { - name, - dismiss: _dismiss, - dismissAll: _dismissAll, - create: _create, - setServiceImplementation, -}; - -const serviceImplementation = { - _dismiss: () => console.warn('dismiss() NOT IMPLEMENTED'), - _dismissAll: () => console.warn('dismissAll() NOT IMPLEMENTED'), - _create: () => console.warn('create() NOT IMPLEMENTED'), -}; - -/** - * Show a new UI dialog; - * - * @param {DialogProps} props { id, content, contentProps, onStart, onDrag, onStop, centralize, isDraggable, showOverlay, preservePosition, defaultPosition } - */ -function _create({ - id, - content, - contentProps, - onStart, - onDrag, - onStop, - centralize = false, - preservePosition = true, - isDraggable = true, - showOverlay = false, - onClickOutside, - defaultPosition, -}) { - return serviceImplementation._create({ - id, - content, - contentProps, - onStart, - onDrag, - onStop, - centralize, - preservePosition, - isDraggable, - onClickOutside, - showOverlay, - defaultPosition, - }); -} - -/** - * Destroys all dialogs, if any - * - * @returns void - */ -function _dismissAll() { - return serviceImplementation._dismissAll(); -} - -/** - * Destroy the dialog, if currently created - * - * @returns void - */ -function _dismiss({ id }) { - return serviceImplementation._dismiss({ id }); -} - -/** - * - * - * @param {*} { - * dismiss: dismissImplementation, - * dismissAll: dismissAllImplementation, - * create: createImplementation, - * } - */ -function setServiceImplementation({ - dismiss: dismissImplementation, - dismissAll: dismissAllImplementation, - create: createImplementation, -}) { - if (dismissImplementation) { - serviceImplementation._dismiss = dismissImplementation; - } - if (dismissAllImplementation) { - serviceImplementation._dismissAll = dismissAllImplementation; - } - if (createImplementation) { - serviceImplementation._create = createImplementation; - } -} - -// TODO - export type here -export default { - REGISTRATION: { - name, - altName: 'UIDialogService', - create: ({ configuration = {} }) => { - return publicAPI; - }, - }, -}; diff --git a/platform/core/src/services/UIDialogService/index.ts b/platform/core/src/services/UIDialogService/index.ts new file mode 100644 index 0000000000..3d787a5b05 --- /dev/null +++ b/platform/core/src/services/UIDialogService/index.ts @@ -0,0 +1,3 @@ +import UIDialogService from './UIDialogService'; + +export default UIDialogService; diff --git a/platform/core/src/services/UIViewportDialogService/UIViewportDialogService.ts b/platform/core/src/services/UIViewportDialogService/UIViewportDialogService.ts new file mode 100644 index 0000000000..37b64188fa --- /dev/null +++ b/platform/core/src/services/UIViewportDialogService/UIViewportDialogService.ts @@ -0,0 +1,52 @@ +import { PubSubService } from '../_shared/pubSubServiceInterface'; + +class UIViewportDialogService extends PubSubService { + public static readonly EVENTS = {}; + public static REGISTRATION = { + name: 'uiViewportDialogService', + altName: 'UIViewportDialogService', + create: ({ configuration = {} }) => { + return new UIViewportDialogService(); + }, + }; + + serviceImplementation = { + _hide: () => console.warn('hide() NOT IMPLEMENTED'), + _show: () => console.warn('show() NOT IMPLEMENTED'), + }; + + constructor() { + super(UIViewportDialogService.EVENTS); + this.serviceImplementation = { + ...this.serviceImplementation, + }; + } + + public show({ viewportId, id, type, message, actions, onSubmit, onOutsideClick, onKeyPress }) { + return this.serviceImplementation._show({ + viewportId, + id, + type, + message, + actions, + onSubmit, + onOutsideClick, + onKeyPress, + }); + } + + public hide() { + return this.serviceImplementation._hide(); + } + + public setServiceImplementation({ hide: hideImplementation, show: showImplementation }) { + if (hideImplementation) { + this.serviceImplementation._hide = hideImplementation; + } + if (showImplementation) { + this.serviceImplementation._show = showImplementation; + } + } +} + +export default UIViewportDialogService; diff --git a/platform/core/src/services/UIViewportDialogService/index.js b/platform/core/src/services/UIViewportDialogService/index.js deleted file mode 100644 index 20e962a584..0000000000 --- a/platform/core/src/services/UIViewportDialogService/index.js +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Viewport Dialog - * - * @typedef {Object} ViewportDialogProps - * @property {ReactElement|HTMLElement} [content=null] Modal content. - * @property {Object} [contentProps=null] Modal content props. - * @property {boolean} [viewportId=false] Modal is dismissible via the esc key. - */ - -const name = 'uiViewportDialogService'; - -const publicAPI = { - name, - hide: _hide, - show: _show, - setServiceImplementation, -}; - -const serviceImplementation = { - _hide: () => console.warn('hide() NOT IMPLEMENTED'), - _show: () => console.warn('show() NOT IMPLEMENTED'), -}; - -/** - * Show a new UI viewport dialog on the specified viewportId; - * - * @param {ViewportDialogProps} props { content, contentProps, viewportId } - */ -function _show({ viewportId, id, type, message, actions, onSubmit, onOutsideClick, onKeyPress }) { - return serviceImplementation._show({ - viewportId, - id, - type, - message, - actions, - onSubmit, - onOutsideClick, - onKeyPress, - }); -} - -/** - * Hides/dismisses the viewport dialog, if currently shown - */ -function _hide() { - return serviceImplementation._hide(); -} - -/** - * - * - * @param {*} { - * hide: hideImplementation, - * show: showImplementation, - * viewportId, - * } - */ -function setServiceImplementation({ hide: hideImplementation, show: showImplementation }) { - if (hideImplementation) { - serviceImplementation._hide = hideImplementation; - } - if (showImplementation) { - serviceImplementation._show = showImplementation; - } -} - -export default { - REGISTRATION: { - name, - altName: 'UIViewportDialogService', - create: ({ configuration = {} }) => { - return publicAPI; - }, - }, -}; diff --git a/platform/core/src/services/UIViewportDialogService/index.ts b/platform/core/src/services/UIViewportDialogService/index.ts new file mode 100644 index 0000000000..a968569ecc --- /dev/null +++ b/platform/core/src/services/UIViewportDialogService/index.ts @@ -0,0 +1,3 @@ +import UIViewportDialogService from './UIViewportDialogService'; + +export default UIViewportDialogService; diff --git a/platform/core/src/services/UserAuthenticationService/UserAuthenticationService.js b/platform/core/src/services/UserAuthenticationService/UserAuthenticationService.js deleted file mode 100644 index 5c1ec921b6..0000000000 --- a/platform/core/src/services/UserAuthenticationService/UserAuthenticationService.js +++ /dev/null @@ -1,94 +0,0 @@ -const name = 'userAuthenticationService'; - -const publicAPI = { - name, - getState: _getState, - setUser: _setUser, - getUser: _getUser, - getAuthorizationHeader: _getAuthorizationHeader, - handleUnauthenticated: _handleUnauthenticated, - setServiceImplementation, - reset: _reset, - set: _set, -}; - -const serviceImplementation = { - _getState: () => console.warn('getState() NOT IMPLEMENTED'), - _setUser: () => console.warn('_setUser() NOT IMPLEMENTED'), - _getUser: () => console.warn('_setUser() NOT IMPLEMENTED'), - _getAuthorizationHeader: () => {}, // TODO: have enabled/disabled state? - //console.warn('_getAuthorizationHeader() NOT IMPLEMENTED'), - _handleUnauthenticated: () => console.warn('_handleUnauthenticated() NOT IMPLEMENTED'), - _reset: () => console.warn('reset() NOT IMPLEMENTED'), - _set: () => console.warn('set() NOT IMPLEMENTED'), -}; - -function _getState() { - return serviceImplementation._getState(); -} - -function _setUser(user) { - return serviceImplementation._setUser(user); -} - -function _getUser() { - return serviceImplementation._getUser(); -} - -function _getAuthorizationHeader() { - return serviceImplementation._getAuthorizationHeader(); -} - -function _handleUnauthenticated() { - return serviceImplementation._handleUnauthenticated(); -} - -function _set(state) { - return serviceImplementation._set(state); -} - -function _reset() { - return serviceImplementation._reset({}); -} - -function setServiceImplementation({ - getState: getStateImplementation, - setUser: setUserImplementation, - getUser: getUserImplementation, - getAuthorizationHeader: getAuthorizationHeaderImplementation, - handleUnauthenticated: handleUnauthenticatedImplementation, - reset: resetImplementation, - set: setImplementation, -}) { - if (getStateImplementation) { - serviceImplementation._getState = getStateImplementation; - } - if (setUserImplementation) { - serviceImplementation._setUser = setUserImplementation; - } - if (getUserImplementation) { - serviceImplementation._getUser = getUserImplementation; - } - if (getAuthorizationHeaderImplementation) { - serviceImplementation._getAuthorizationHeader = getAuthorizationHeaderImplementation; - } - if (handleUnauthenticatedImplementation) { - serviceImplementation._handleUnauthenticated = handleUnauthenticatedImplementation; - } - if (resetImplementation) { - serviceImplementation._reset = resetImplementation; - } - if (setImplementation) { - serviceImplementation._set = setImplementation; - } -} - -export default { - REGISTRATION: { - name, - altName: 'UserAuthenticationService', - create: ({ configuration = {} }) => { - return publicAPI; - }, - }, -}; diff --git a/platform/core/src/services/UserAuthenticationService/UserAuthenticationService.ts b/platform/core/src/services/UserAuthenticationService/UserAuthenticationService.ts new file mode 100644 index 0000000000..6ae3c8e920 --- /dev/null +++ b/platform/core/src/services/UserAuthenticationService/UserAuthenticationService.ts @@ -0,0 +1,92 @@ +import { PubSubService } from '../_shared/pubSubServiceInterface'; + +class UserAuthenticationService extends PubSubService { + public static readonly EVENTS = {}; + + public static REGISTRATION = { + name: 'userAuthenticationService', + altName: 'UserAuthenticationService', + create: ({ configuration = {} }) => { + return new UserAuthenticationService(); + }, + }; + + serviceImplementation = { + _getState: () => console.warn('getState() NOT IMPLEMENTED'), + _setUser: () => console.warn('_setUser() NOT IMPLEMENTED'), + _getUser: () => console.warn('_getUser() NOT IMPLEMENTED'), + _getAuthorizationHeader: () => {}, // TODO: Implement this method + _handleUnauthenticated: () => console.warn('_handleUnauthenticated() NOT IMPLEMENTED'), + _reset: () => console.warn('reset() NOT IMPLEMENTED'), + _set: () => console.warn('set() NOT IMPLEMENTED'), + }; + + constructor() { + super(UserAuthenticationService.EVENTS); + this.serviceImplementation = { + ...this.serviceImplementation, + }; + } + + public getState() { + return this.serviceImplementation._getState(); + } + + public setUser(user) { + return this.serviceImplementation._setUser(user); + } + + public getUser() { + return this.serviceImplementation._getUser(); + } + + public getAuthorizationHeader() { + return this.serviceImplementation._getAuthorizationHeader(); + } + + public handleUnauthenticated() { + return this.serviceImplementation._handleUnauthenticated(); + } + + public reset() { + return this.serviceImplementation._reset(); + } + + public set(state) { + return this.serviceImplementation._set(state); + } + + public setServiceImplementation({ + getState: getStateImplementation, + setUser: setUserImplementation, + getUser: getUserImplementation, + getAuthorizationHeader: getAuthorizationHeaderImplementation, + handleUnauthenticated: handleUnauthenticatedImplementation, + reset: resetImplementation, + set: setImplementation, + }) { + if (getStateImplementation) { + this.serviceImplementation._getState = getStateImplementation; + } + if (setUserImplementation) { + this.serviceImplementation._setUser = setUserImplementation; + } + if (getUserImplementation) { + this.serviceImplementation._getUser = getUserImplementation; + } + if (getAuthorizationHeaderImplementation) { + this.serviceImplementation._getAuthorizationHeader = getAuthorizationHeaderImplementation; + } + if (handleUnauthenticatedImplementation) { + this.serviceImplementation._handleUnauthenticated = handleUnauthenticatedImplementation; + } + if (resetImplementation) { + this.serviceImplementation._reset = resetImplementation; + } + if (setImplementation) { + this.serviceImplementation._set = setImplementation; + } + } +} + +export default UserAuthenticationService; diff --git a/platform/core/src/services/UserAuthenticationService/index.js b/platform/core/src/services/UserAuthenticationService/index.ts similarity index 100% rename from platform/core/src/services/UserAuthenticationService/index.js rename to platform/core/src/services/UserAuthenticationService/index.ts diff --git a/platform/core/src/services/ViewportGridService/ViewportGridService.ts b/platform/core/src/services/ViewportGridService/ViewportGridService.ts index 60309eb097..4f31ba0513 100644 --- a/platform/core/src/services/ViewportGridService/ViewportGridService.ts +++ b/platform/core/src/services/ViewportGridService/ViewportGridService.ts @@ -105,8 +105,8 @@ class ViewportGridService extends PubSubService { this.setDisplaySetsForViewports([props]); } - public setDisplaySetsForViewports(props) { - this.serviceImplementation._setDisplaySetsForViewports(props); + public async setDisplaySetsForViewports(props) { + await this.serviceImplementation._setDisplaySetsForViewports(props); const state = this.getState(); const viewports = []; diff --git a/platform/core/src/services/WorkflowStepsService/WorkflowStepsService.ts b/platform/core/src/services/WorkflowStepsService/WorkflowStepsService.ts index 8a5d337821..5165e55a11 100644 --- a/platform/core/src/services/WorkflowStepsService/WorkflowStepsService.ts +++ b/platform/core/src/services/WorkflowStepsService/WorkflowStepsService.ts @@ -1,6 +1,5 @@ import { CommandsManager } from '../../classes'; import { ExtensionManager } from '../../extensions'; -import { ServicesManager } from '../../services'; import { PubSubService } from '../_shared/pubSubServiceInterface'; export const EVENTS = { @@ -82,7 +81,7 @@ export type WorkflowStep = { class WorkflowStepsService extends PubSubService { private _extensionManager: ExtensionManager; - private _servicesManager: ServicesManager; + private _servicesManager: AppTypes.ServicesManager; private _commandsManager: CommandsManager; private _workflowSteps: WorkflowStep[]; private _activeWorkflowStep: WorkflowStep; @@ -90,7 +89,7 @@ class WorkflowStepsService extends PubSubService { constructor( extensionManager: ExtensionManager, commandsManager: CommandsManager, - servicesManager: ServicesManager + servicesManager: AppTypes.ServicesManager ) { super(EVENTS); this._workflowSteps = []; diff --git a/platform/core/src/services/index.ts b/platform/core/src/services/index.ts index f8d972057c..68666a18af 100644 --- a/platform/core/src/services/index.ts +++ b/platform/core/src/services/index.ts @@ -17,6 +17,7 @@ import CustomizationService from './CustomizationService'; import StateSyncService from './StateSyncService'; import PanelService from './PanelService'; import WorkflowStepsService from './WorkflowStepsService'; +import StudyPrefetcherService from './StudyPrefetcherService'; import type Services from '../types/Services'; @@ -42,4 +43,5 @@ export { UserAuthenticationService, PanelService, WorkflowStepsService, + StudyPrefetcherService, }; diff --git a/platform/core/src/types/AppConfig.ts b/platform/core/src/types/AppConfig.ts deleted file mode 100644 index 3c75694cba..0000000000 --- a/platform/core/src/types/AppConfig.ts +++ /dev/null @@ -1,7 +0,0 @@ -import Hotkey from '../classes/Hotkey'; - -export interface AppConfig { - extensions?: string[]; - defaultDataSourceName?: string; - hotkeys?: Record | Hotkey[]; -} diff --git a/platform/core/src/types/AppTypes.ts b/platform/core/src/types/AppTypes.ts new file mode 100644 index 0000000000..e14bce529b --- /dev/null +++ b/platform/core/src/types/AppTypes.ts @@ -0,0 +1,147 @@ +/* eslint-disable @typescript-eslint/no-namespace */ +import HangingProtocolServiceType from '../services/HangingProtocolService'; +import CustomizationServiceType from '../services/CustomizationService'; +import MeasurementServiceType from '../services/MeasurementService'; +import ViewportGridServiceType from '../services/ViewportGridService'; +import ToolbarServiceType from '../services/ToolBarService'; +import DisplaySetServiceType from '../services/DisplaySetService'; +import StateSyncServiceType from '../services/StateSyncService'; +import UINotificationServiceType from '../services/UINotificationService'; +import UIModalServiceType from '../services/UIModalService'; +import WorkflowStepsServiceType from '../services/WorkflowStepsService'; +import CineServiceType from '../services/CineService'; +import UserAuthenticationServiceType from '../services/UserAuthenticationService'; +import PanelServiceType from '../services/PanelService'; +import UIDialogServiceType from '../services/UIDialogService'; +import UIViewportDialogServiceType from '../services/UIViewportDialogService'; +import StudyPrefetcherServiceType from '../services/StudyPrefetcherService'; + +import ServicesManagerType from '../services/ServicesManager'; +import CommandsManagerType from '../classes/CommandsManager'; +import ExtensionManagerType from '../extensions/ExtensionManager'; + +import Hotkey from '../classes/Hotkey'; + +declare global { + namespace AppTypes { + export type ServicesManager = ServicesManagerType; + export type CommandsManager = CommandsManagerType; + export type ExtensionManager = ExtensionManagerType; + export type HangingProtocolService = HangingProtocolServiceType; + export type CustomizationService = CustomizationServiceType; + export type MeasurementService = MeasurementServiceType; + export type DisplaySetService = DisplaySetServiceType; + export type ToolbarService = ToolbarServiceType; + export type ViewportGridService = ViewportGridServiceType; + export type UIModalService = UIModalServiceType; + export type UINotificationService = UINotificationServiceType; + export type StateSyncService = StateSyncServiceType; + export type WorkflowStepsService = WorkflowStepsServiceType; + export type CineService = CineServiceType; + export type UserAuthenticationService = UserAuthenticationServiceType; + export type UIDialogService = UIDialogServiceType; + export type UIViewportDialogService = UIViewportDialogServiceType; + export type PanelService = PanelServiceType; + export type StudyPrefetcherService = StudyPrefetcherServiceType; + + export interface Managers { + servicesManager?: ServicesManager; + commandsManager?: CommandsManager; + extensionManager?: ExtensionManager; + } + + export interface Services { + hangingProtocolService?: HangingProtocolServiceType; + customizationService?: CustomizationServiceType; + measurementService?: MeasurementServiceType; + displaySetService?: DisplaySetServiceType; + toolbarService?: ToolbarServiceType; + viewportGridService?: ViewportGridServiceType; + uiModalService?: UIModalServiceType; + uiNotificationService?: UINotificationServiceType; + stateSyncService?: StateSyncServiceType; + workflowStepsService?: WorkflowStepsServiceType; + cineService?: CineServiceType; + userAuthenticationService?: UserAuthenticationServiceType; + uiDialogService?: UIDialogServiceType; + uiViewportDialogService?: UIViewportDialogServiceType; + panelService?: PanelServiceType; + studyPrefetcherService?: StudyPrefetcherServiceType; + } + export interface Config { + routerBasename?: string; + customizationService?: any; + extensions?: string[]; + modes?: string[]; + experimentalStudyBrowserSort?: boolean; + defaultDataSourceName?: string; + hotkeys?: Record | Hotkey[]; + useSharedArrayBuffer?: 'AUTO' | 'FALSE' | 'TRUE'; + preferSizeOverAccuracy?: boolean; + useNorm16Texture?: boolean; + useCPURendering?: boolean; + strictZSpacingForVolumeViewport?: boolean; + useCursors?: boolean; + maxCacheSize?: number; + max3DTextureSize?: number; + showWarningMessageForCrossOrigin?: boolean; + showCPUFallbackMessage?: boolean; + maxNumRequests?: { + interaction?: number; + prefetch?: number; + thumbnail?: number; + }; + disableEditing?: boolean; + maxNumberOfWebWorkers?: number; + acceptHeader?: string[]; + investigationalUseDialog?: { + option: 'always' | 'never' | 'configure'; + days?: number; + }; + groupEnabledModesFirst?: boolean; + disableConfirmationPrompts?: boolean; + showPatientInfo?: 'visible' | 'visibleCollapsed' | 'disabled' | 'visibleReadOnly'; + requestTransferSyntaxUID?: string; + omitQuotationForMultipartRequest?: boolean; + modesConfiguration?: { + [key: string]: object; + }; + showLoadingIndicator?: boolean; + supportsWildcard?: boolean; + allowMultiSelectExport?: boolean; + activateViewportBeforeInteraction?: boolean; + autoPlayCine?: boolean; + showStudyList?: boolean; + whiteLabeling?: any; + httpErrorHandler?: any; + addWindowLevelActionMenu?: boolean; + dangerouslyUseDynamicConfig?: { + enabled: boolean; + regex: RegExp; + }; + onConfiguration?: (dicomWebConfig: any, options: any) => any; + dataSources?: any; + oidc?: any; + peerImport?: (moduleId: string) => Promise; + studyPrefetcher: { + enabled: boolean; + displaySetsCount: number; + maxNumPrefetchRequests: number; + order: 'closest' | 'downward' | 'upward'; + } + } + + export interface Test { + services?: Services; + commandsManager?: CommandsManager; + extensionManager?: ExtensionManager; + config?: Config; + } + } + + export type withAppTypes = T & + AppTypes.Services & + AppTypes.Managers & { + [key: string]: any; + }; +} diff --git a/platform/core/src/types/HangingProtocol.ts b/platform/core/src/types/HangingProtocol.ts index 5fabe5417c..16b846fb22 100644 --- a/platform/core/src/types/HangingProtocol.ts +++ b/platform/core/src/types/HangingProtocol.ts @@ -24,6 +24,18 @@ export type DisplaySetAndViewportOptions = { displaySetOptions: DisplaySetOptions; }; +export type DisplayArea = { + type?: 'SCALE' | 'FIT'; + scale?: number; + interpolationType?: any; + imageArea?: [number, number]; // areaX, areaY + imageCanvasPoint?: { + imagePoint: [number, number]; // imageX, imageY + canvasPoint?: [number, number]; // canvasX, canvasY + }; + storeAsInitialCamera?: boolean; +}; + export type SetProtocolOptions = { /** Used to provide a mapping of what keys are provided for which viewport. * For example, a Chest XRay might use have the display set selector id of @@ -155,6 +167,7 @@ export type ViewportOptions = { id?: string; orientation?: CustomOption; viewportId?: string; + displayArea?: DisplayArea; initialImageOptions?: CustomOption; syncGroups?: CustomOption[]; customViewportProps?: Record; @@ -322,7 +335,7 @@ export type Protocol = { * to the GUI when this is used, and it can be expensive to apply. * Alternatives include using the custom attributes where possible. */ -export type ProtocolGenerator = ({ servicesManager: any, commandsManager: any }) => { +export type ProtocolGenerator = ({ servicesManager, commandsManager }: withAppTypes) => { protocol: Protocol; }; diff --git a/platform/core/src/types/Services.ts b/platform/core/src/types/Services.ts index 9cedd0ad3d..119a2da876 100644 --- a/platform/core/src/types/Services.ts +++ b/platform/core/src/types/Services.ts @@ -9,12 +9,18 @@ import { UINotificationService, UIModalService, WorkflowStepsService, + CineService, + UserAuthenticationService, + PanelService, + UIDialogService, + UIViewportDialogService, } from '../services'; /** * The interface for the services object */ -export default interface Services { + +interface Services { hangingProtocolService?: HangingProtocolService; customizationService?: CustomizationService; measurementService?: MeasurementService; @@ -25,15 +31,11 @@ export default interface Services { uiNotificationService?: UINotificationService; stateSyncService?: StateSyncService; workflowStepsService: WorkflowStepsService; - cineService?: unknown; - userAuthenticationService?: unknown; - cornerstoneViewportService?: unknown; - uiDialogService?: unknown; - toolGroupService?: unknown; - uiViewportDialogService?: unknown; - syncGroupService?: unknown; - cornerstoneCacheService?: unknown; - segmentationService?: unknown; - panelService?: unknown; - colorbarService?: unknown; + cineService?: CineService; + userAuthenticationService?: UserAuthenticationService; + uiDialogService?: UIDialogService; + uiViewportDialogService?: UIViewportDialogService; + panelService?: PanelService; } + +export default Services; diff --git a/platform/core/src/types/index.ts b/platform/core/src/types/index.ts index 15c428e3db..e01e64f710 100644 --- a/platform/core/src/types/index.ts +++ b/platform/core/src/types/index.ts @@ -7,11 +7,10 @@ import type { BaseDataSourceConfigurationAPI, BaseDataSourceConfigurationAPIItem, } from './DataSourceConfigurationAPI'; -import type { PresentationIds } from '../services/ViewportGridService'; +export type * from '../services/ViewportGridService'; export type * from '../services/CustomizationService/types'; // Separate out some generic types -export type * from './AppConfig'; export type * from './Consumer'; export type * from './Command'; export type * from './DisplaySet'; @@ -32,5 +31,4 @@ export { DataSourceDefinition, BaseDataSourceConfigurationAPI, BaseDataSourceConfigurationAPIItem, - PresentationIds, }; diff --git a/platform/core/src/utils/createStudyBrowserTabs.ts b/platform/core/src/utils/createStudyBrowserTabs.ts new file mode 100644 index 0000000000..0d55149e34 --- /dev/null +++ b/platform/core/src/utils/createStudyBrowserTabs.ts @@ -0,0 +1,76 @@ +/** + * + * @param {string[]} primaryStudyInstanceUIDs + * @param {object[]} studyDisplayList + * @param {string} studyDisplayList.studyInstanceUid + * @param {string} studyDisplayList.date + * @param {string} studyDisplayList.description + * @param {string} studyDisplayList.modalities + * @param {number} studyDisplayList.numInstances + * @param {object[]} displaySets + * @param {number} recentTimeframe - The number of milliseconds to consider a study recent + * @returns tabs - The prop object expected by the StudyBrowser component + */ + +export function createStudyBrowserTabs(primaryStudyInstanceUIDs, studyDisplayList, displaySets, recentTimeframeMS = 31536000000) { + const primaryStudies = []; + const allStudies = []; + + studyDisplayList.forEach(study => { + const displaySetsForStudy = displaySets.filter( + ds => ds.StudyInstanceUID === study.studyInstanceUid + ); + const tabStudy = Object.assign({}, study, { + displaySets: displaySetsForStudy, + }); + + if (primaryStudyInstanceUIDs.includes(study.studyInstanceUid)) { + primaryStudies.push(tabStudy); + } + allStudies.push(tabStudy); + }); + + const primaryStudiesTimestamps = primaryStudies + .filter(study => study.date) + .map(study => new Date(study.date).getTime()); + + const recentStudies = + primaryStudiesTimestamps.length > 0 + ? allStudies.filter(study => { + const oldestPrimaryTimeStamp = Math.min(...primaryStudiesTimestamps); + + if (!study.date) { + return false; + } + const studyTimeStamp = new Date(study.date).getTime(); + return oldestPrimaryTimeStamp - studyTimeStamp < recentTimeframeMS; + }) + : []; + + // Newest first + const _byDate = (a, b) => { + const dateA = Date.parse(a); + const dateB = Date.parse(b); + + return dateB - dateA; + }; + const tabs = [ + { + name: 'primary', + label: 'Primary', + studies: primaryStudies.sort((studyA, studyB) => _byDate(studyA.date, studyB.date)), + }, + { + name: 'recent', + label: 'Recent', + studies: recentStudies.sort((studyA, studyB) => _byDate(studyA.date, studyB.date)), + }, + { + name: 'all', + label: 'All', + studies: allStudies.sort((studyA, studyB) => _byDate(studyA.date, studyB.date)), + }, + ]; + + return tabs; +} diff --git a/platform/core/src/utils/formatTime.ts b/platform/core/src/utils/formatTime.ts new file mode 100644 index 0000000000..5d46ee047d --- /dev/null +++ b/platform/core/src/utils/formatTime.ts @@ -0,0 +1,12 @@ +import moment from 'moment'; + +/** + * Format time in HHmmss.SSS format (24h time) into HH:mm:ss + * + * @param time - Time to be formatted + * @param format - Desired time format + * @returns Formatted time + */ +export default function formatTime(time: string, format = 'HH:mm:ss') { + return moment(time, 'HH:mm:ss').format(format); +} diff --git a/platform/core/src/utils/index.test.js b/platform/core/src/utils/index.test.js index 30d8f70ef5..f72714b474 100644 --- a/platform/core/src/utils/index.test.js +++ b/platform/core/src/utils/index.test.js @@ -1,4 +1,4 @@ -import * as utils from './index.js'; +import * as utils from './index'; describe('Top level exports', () => { test('should export the modules ', () => { @@ -22,7 +22,9 @@ describe('Top level exports', () => { 'imageIdToURI', 'roundNumber', 'b64toBlob', + 'createStudyBrowserTabs', 'formatDate', + 'formatTime', 'formatPN', 'generateAcceptHeader', 'isEqualWithin', diff --git a/platform/core/src/utils/index.js b/platform/core/src/utils/index.ts similarity index 94% rename from platform/core/src/utils/index.js rename to platform/core/src/utils/index.ts index d7862618e0..63518961cd 100644 --- a/platform/core/src/utils/index.js +++ b/platform/core/src/utils/index.ts @@ -13,6 +13,7 @@ import hotkeys from './hotkeys'; import Queue from './Queue'; import isDicomUid from './isDicomUid'; import formatDate from './formatDate'; +import formatTime from './formatTime'; import formatPN from './formatPN'; import generateAcceptHeader from './generateAcceptHeader'; import resolveObjectPath from './resolveObjectPath'; @@ -37,6 +38,7 @@ import { } from './sortStudy'; import { subscribeToNextViewportGridChange } from './subscribeToNextViewportGridChange'; import { splitComma, getSplitParam } from './splitComma'; +import { createStudyBrowserTabs } from './createStudyBrowserTabs'; // Commented out unused functionality. // Need to implement new mechanism for derived displaySets using the displaySetManager. @@ -55,6 +57,7 @@ const utils = { seriesSortCriteria, writeScript, formatDate, + formatTime, formatPN, b64toBlob, urlUtil, @@ -80,6 +83,7 @@ const utils = { splitComma, getSplitParam, generateAcceptHeader, + createStudyBrowserTabs, }; export { @@ -112,6 +116,7 @@ export { splitComma, getSplitParam, generateAcceptHeader, + createStudyBrowserTabs, }; export default utils; diff --git a/platform/core/src/utils/isDisplaySetReconstructable.js b/platform/core/src/utils/isDisplaySetReconstructable.js index c32b565b0d..00decb83a7 100644 --- a/platform/core/src/utils/isDisplaySetReconstructable.js +++ b/platform/core/src/utils/isDisplaySetReconstructable.js @@ -10,7 +10,7 @@ const iopTolerance = 0.01; * * @param {Object[]} instances An array of `OHIFInstanceMetadata` objects. */ -export default function isDisplaySetReconstructable(instances) { +export default function isDisplaySetReconstructable(instances, appConfig) { if (!instances.length) { return { value: false }; } @@ -18,6 +18,14 @@ export default function isDisplaySetReconstructable(instances) { const isMultiframe = firstInstance.NumberOfFrames > 1; + if (appConfig) { + const rows = toNumber(firstInstance.Rows); + const columns = toNumber(firstInstance.Columns); + + if (rows > appConfig.max3DTextureSize || columns > appConfig.max3DTextureSize) { + return { value: false }; + } + } // We used to check is reconstructable modalities here, but the logic is removed // in favor of the calculation by metadata (orientation and positions) diff --git a/platform/core/src/utils/isLowPriorityModality.js b/platform/core/src/utils/isLowPriorityModality.js deleted file mode 100644 index 54024d5a05..0000000000 --- a/platform/core/src/utils/isLowPriorityModality.js +++ /dev/null @@ -1,5 +0,0 @@ -const LOW_PRIORITY_MODALITIES = Object.freeze(['SEG', 'KO', 'PR', 'SR', 'RTSTRUCT']); - -export default function isLowPriorityModality(Modality) { - return LOW_PRIORITY_MODALITIES.includes(Modality); -} diff --git a/platform/core/src/utils/isLowPriorityModality.ts b/platform/core/src/utils/isLowPriorityModality.ts index 54024d5a05..cfcee34e40 100644 --- a/platform/core/src/utils/isLowPriorityModality.ts +++ b/platform/core/src/utils/isLowPriorityModality.ts @@ -1,4 +1,4 @@ -const LOW_PRIORITY_MODALITIES = Object.freeze(['SEG', 'KO', 'PR', 'SR', 'RTSTRUCT']); +const LOW_PRIORITY_MODALITIES = Object.freeze(['SEG', 'KO', 'PR', 'SR', 'RTSTRUCT', 'RTDOSE', 'RTPLAN', 'RTRECORD', 'REG']); export default function isLowPriorityModality(Modality) { return LOW_PRIORITY_MODALITIES.includes(Modality); diff --git a/platform/core/src/utils/metadataProvider/getPixelSpacingInformation.js b/platform/core/src/utils/metadataProvider/getPixelSpacingInformation.js index 9e8425a158..0941136c58 100644 --- a/platform/core/src/utils/metadataProvider/getPixelSpacingInformation.js +++ b/platform/core/src/utils/metadataProvider/getPixelSpacingInformation.js @@ -28,7 +28,6 @@ export default function getPixelSpacingInformation(instance) { PixelSpacingCalibrationType, PixelSpacingCalibrationDescription, EstimatedRadiographicMagnificationFactor, - SequenceOfUltrasoundRegions, } = instance; const isProjection = projectionRadiographSOPClassUIDs.includes(SOPClassUID); @@ -90,21 +89,6 @@ export default function getPixelSpacingInformation(instance) { PixelSpacing: CorrectedImagerPixelSpacing, isProjection, }; - } else if (SequenceOfUltrasoundRegions && typeof SequenceOfUltrasoundRegions === 'object') { - const { PhysicalDeltaX, PhysicalDeltaY } = SequenceOfUltrasoundRegions; - const USPixelSpacing = [PhysicalDeltaX * 10, PhysicalDeltaY * 10]; - - return { - PixelSpacing: USPixelSpacing, - }; - } else if ( - SequenceOfUltrasoundRegions && - Array.isArray(SequenceOfUltrasoundRegions) && - SequenceOfUltrasoundRegions.length > 1 - ) { - log.warn( - 'Sequence of Ultrasound Regions > one entry. This is not yet implemented, all measurements will be shown in pixels.' - ); } else if (isProjection === false && !ImagerPixelSpacing) { // If only Pixel Spacing is present, and this is not a projection radiograph, // we can stop here diff --git a/platform/docs/CHANGELOG.md b/platform/docs/CHANGELOG.md index fd164bdd73..4552598efd 100644 --- a/platform/docs/CHANGELOG.md +++ b/platform/docs/CHANGELOG.md @@ -3,6 +3,735 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.9.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.70...v3.9.0-beta.71) (2024-07-30) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.69...v3.9.0-beta.70) (2024-07-30) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.68...v3.9.0-beta.69) (2024-07-27) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.67...v3.9.0-beta.68) (2024-07-26) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.66...v3.9.0-beta.67) (2024-07-26) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.65...v3.9.0-beta.66) (2024-07-24) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.64...v3.9.0-beta.65) (2024-07-23) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.63...v3.9.0-beta.64) (2024-07-19) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.62...v3.9.0-beta.63) (2024-07-10) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.61...v3.9.0-beta.62) (2024-07-09) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.60...v3.9.0-beta.61) (2024-07-09) + + +### Features + +* **auth:** Add Authorization Code Flow and new Keycloak recipes with new video tutorials ([#4234](https://github.com/OHIF/Viewers/issues/4234)) ([aefa6d9](https://github.com/OHIF/Viewers/commit/aefa6d94dff82d34fa8358933fb1d5dec3f8246d)) + + + + + +# [3.9.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.59...v3.9.0-beta.60) (2024-07-09) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.58...v3.9.0-beta.59) (2024-07-05) + + +### Bug Fixes + +* webpack import bugs showing warnings on import ([#4265](https://github.com/OHIF/Viewers/issues/4265)) ([24c511f](https://github.com/OHIF/Viewers/commit/24c511f4bc04c4143bbd3d0d48029f41f7f36014)) + + +### Features + +* Add interleaved HTJ2K and volume progressive loading ([#4276](https://github.com/OHIF/Viewers/issues/4276)) ([a2084f3](https://github.com/OHIF/Viewers/commit/a2084f319b731d98b59485799fb80357094f8c38)) + + + + + +# [3.9.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.57...v3.9.0-beta.58) (2024-07-04) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.56...v3.9.0-beta.57) (2024-07-02) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.55...v3.9.0-beta.56) (2024-07-02) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.54...v3.9.0-beta.55) (2024-06-28) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.53...v3.9.0-beta.54) (2024-06-28) + + +### Features + +* **studyPrefetcher:** Study Prefetcher ([#4206](https://github.com/OHIF/Viewers/issues/4206)) ([2048b19](https://github.com/OHIF/Viewers/commit/2048b19484c0b1fae73f993cfaa814f861bbd230)) + + + + + +# [3.9.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.52...v3.9.0-beta.53) (2024-06-28) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.51...v3.9.0-beta.52) (2024-06-27) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.50...v3.9.0-beta.51) (2024-06-27) + + +### Bug Fixes + +* **cli:** Fix the cli utilities which require full paths ([d09f8b5](https://github.com/OHIF/Viewers/commit/d09f8b5ba2dcc0c02beb405b8cfa79fbae5bdde8)), closes [#4267](https://github.com/OHIF/Viewers/issues/4267) + + + + + +# [3.9.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.49...v3.9.0-beta.50) (2024-06-26) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.48...v3.9.0-beta.49) (2024-06-26) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.47...v3.9.0-beta.48) (2024-06-25) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.46...v3.9.0-beta.47) (2024-06-21) + + +### Bug Fixes + +* Allow the mode setup/creation to be async, and provide a few more values to extension/app config/mode setup. ([#4016](https://github.com/OHIF/Viewers/issues/4016)) ([88575c6](https://github.com/OHIF/Viewers/commit/88575c6c09fd778a31b2f91524163ce65d1639dd)) +* **CustomViewportOverlay:** pass accurate data to Custom Viewport Functions ([#4224](https://github.com/OHIF/Viewers/issues/4224)) ([aef00e9](https://github.com/OHIF/Viewers/commit/aef00e91d63e9bc2de289cc6f35975e36547fb20)) + + +### Features + +* customization service append and customize functionality should run once ([#4238](https://github.com/OHIF/Viewers/issues/4238)) ([e462fd3](https://github.com/OHIF/Viewers/commit/e462fd31f7944acfee34f08cfbc28cfd9de16169)) +* **sort:** custom series sort in study panel ([#4214](https://github.com/OHIF/Viewers/issues/4214)) ([a433d40](https://github.com/OHIF/Viewers/commit/a433d406e2cac13f644203996c682260b54e8865)) + + + + + +# [3.9.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.45...v3.9.0-beta.46) (2024-06-18) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.44...v3.9.0-beta.45) (2024-06-18) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.43...v3.9.0-beta.44) (2024-06-17) + + +### Bug Fixes + +* **cli:** version txt had a new line which it should not ([#4233](https://github.com/OHIF/Viewers/issues/4233)) ([097ef76](https://github.com/OHIF/Viewers/commit/097ef7665559a672d73e1babfc42afccc3cdd41d)) + + + + + +# [3.9.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.42...v3.9.0-beta.43) (2024-06-12) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.41...v3.9.0-beta.42) (2024-06-12) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.40...v3.9.0-beta.41) (2024-06-12) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.39...v3.9.0-beta.40) (2024-06-12) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.38...v3.9.0-beta.39) (2024-06-08) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.37...v3.9.0-beta.38) (2024-06-07) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.36...v3.9.0-beta.37) (2024-06-05) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.35...v3.9.0-beta.36) (2024-06-05) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.34...v3.9.0-beta.35) (2024-06-05) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.33...v3.9.0-beta.34) (2024-06-05) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.32...v3.9.0-beta.33) (2024-06-05) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.31...v3.9.0-beta.32) (2024-05-31) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.30...v3.9.0-beta.31) (2024-05-30) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.29...v3.9.0-beta.30) (2024-05-30) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.28...v3.9.0-beta.29) (2024-05-30) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.27...v3.9.0-beta.28) (2024-05-30) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.26...v3.9.0-beta.27) (2024-05-29) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.25...v3.9.0-beta.26) (2024-05-29) + + +### Features + +* **hp:** Add displayArea option for Hanging protocols and example with Mamo([#3808](https://github.com/OHIF/Viewers/issues/3808)) ([18ac08e](https://github.com/OHIF/Viewers/commit/18ac08ed860d119721c52e4ffc270332259100b6)) + + + + + +# [3.9.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.24...v3.9.0-beta.25) (2024-05-29) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.23...v3.9.0-beta.24) (2024-05-29) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.22...v3.9.0-beta.23) (2024-05-28) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.21...v3.9.0-beta.22) (2024-05-27) + + +### Features + +* **ui:** move to React 18 and base for using shadcn/ui ([#4174](https://github.com/OHIF/Viewers/issues/4174)) ([70f2c79](https://github.com/OHIF/Viewers/commit/70f2c797f42af603d7ea0eb8d23b4103aba66f77)) + + + + + +# [3.9.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.20...v3.9.0-beta.21) (2024-05-24) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.19...v3.9.0-beta.20) (2024-05-24) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.18...v3.9.0-beta.19) (2024-05-24) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.17...v3.9.0-beta.18) (2024-05-24) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.16...v3.9.0-beta.17) (2024-05-23) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.15...v3.9.0-beta.16) (2024-05-23) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.14...v3.9.0-beta.15) (2024-05-22) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.13...v3.9.0-beta.14) (2024-05-21) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.12...v3.9.0-beta.13) (2024-05-21) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.11...v3.9.0-beta.12) (2024-05-21) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.10...v3.9.0-beta.11) (2024-05-21) + + +### Features + +* **test:** Playwright testing integration ([#4146](https://github.com/OHIF/Viewers/issues/4146)) ([fe1a706](https://github.com/OHIF/Viewers/commit/fe1a706446cc33670bf5fab8451e8281b487fcd6)) + + + + + +# [3.9.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.9...v3.9.0-beta.10) (2024-05-21) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.8...v3.9.0-beta.9) (2024-05-17) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.7...v3.9.0-beta.8) (2024-05-16) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.6...v3.9.0-beta.7) (2024-05-15) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.5...v3.9.0-beta.6) (2024-05-15) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.4...v3.9.0-beta.5) (2024-05-14) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.3...v3.9.0-beta.4) (2024-05-14) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.2...v3.9.0-beta.3) (2024-05-08) + + +### Features + +* **typings:** Enhance typing support with withAppTypes and custom services throughout OHIF ([#4090](https://github.com/OHIF/Viewers/issues/4090)) ([374065b](https://github.com/OHIF/Viewers/commit/374065bc3bad9d212f9817a8d41546cc64cfabfb)) + + + + + +# [3.9.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.1...v3.9.0-beta.2) (2024-05-06) + + +### Bug Fixes + +* **bugs:** enhancements and bugs in several areas ([#4086](https://github.com/OHIF/Viewers/issues/4086)) ([730f434](https://github.com/OHIF/Viewers/commit/730f4349100f21b4489a21707dbb2dca9dbfbba2)) + + + + + +# [3.9.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.0...v3.9.0-beta.1) (2024-05-06) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.9.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.94...v3.9.0-beta.0) (2024-04-29) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.8.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0-beta.94) (2024-04-29) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29) + + +### Bug Fixes + +* **toolbox:** Preserve user-specified tool state and streamline command execution ([#4063](https://github.com/OHIF/Viewers/issues/4063)) ([f1a736d](https://github.com/OHIF/Viewers/commit/f1a736d1934733a434cb87b2c284907a3122403f)) + + + + + +# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19) + + +### Features + +* **tmtv-mode:** Add Brush tools and move SUV peak calculation to web worker ([#4053](https://github.com/OHIF/Viewers/issues/4053)) ([8192e34](https://github.com/OHIF/Viewers/commit/8192e348eca993fec331d4963efe88f9a730eceb)) + + + + + +# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19) + + +### Bug Fixes + +* **layouts:** and fix thumbnail in touch and update migration guide for 3.8 release ([#4052](https://github.com/OHIF/Viewers/issues/4052)) ([d250d04](https://github.com/OHIF/Viewers/commit/d250d04580883446fcb8d748b2a97c5c198922af)) + + + + + +# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18) + +**Note:** Version bump only for package ohif-docs + + + + + +# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18) + + +### Bug Fixes + +* **bugs:** and replace seriesInstanceUID and seriesInstanceUIDs URL with seriesInstanceUIDs ([#4049](https://github.com/OHIF/Viewers/issues/4049)) ([da7c1a5](https://github.com/OHIF/Viewers/commit/da7c1a5d8c54bfa1d3f97bbc500386bf76e7fd9d)) + + + + + +# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18) + +**Note:** Version bump only for package ohif-docs + + + + + # [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17) **Note:** Version bump only for package ohif-docs diff --git a/platform/docs/docs/README.md b/platform/docs/docs/README.md index 3f6446dd13..9b5a6f7d5d 100644 --- a/platform/docs/docs/README.md +++ b/platform/docs/docs/README.md @@ -38,11 +38,15 @@ Key features: | | | | | :-: | :--- | :--- | -| Measurement tracking | Measurement Tracking | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5) | -| Segmentations | Labelmap Segmentations | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.12.2.1107.5.2.32.35162.30000015050317233592200000046) | -| Hanging Protocols | Fusion and Custom Hanging protocols | [Demo](https://viewer.ohif.org/tmtv?StudyInstanceUIDs=1.3.6.1.4.1.14519.5.2.1.7009.2403.334240657131972136850343327463) | -| Microscopy | Slide Microscopy | [Demo](https://viewer.ohif.org/microscopy?StudyInstanceUIDs=2.25.275741864483510678566144889372061815320) | -| Volume Rendering | Volume Rendering | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5&hangingprotocolId=mprAnd3DVolumeViewport) | +| Measurement tracking | Measurement Tracking | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5) | +| Segmentations | Labelmap Segmentations | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.12.2.1107.5.2.32.35162.30000015050317233592200000046) | +| Hanging Protocols | Fusion and Custom Hanging protocols | [Demo](https://viewer.ohif.org/tmtv?StudyInstanceUIDs=1.3.6.1.4.1.14519.5.2.1.7009.2403.334240657131972136850343327463) | +| Volume Rendering | Volume Rendering | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5&hangingprotocolId=mprAnd3DVolumeViewport) | +| PDF | PDF | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=2.25.317377619501274872606137091638706705333) | +| RTSTRUCT | RT STRUCT | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.6.1.4.1.5962.99.1.2968617883.1314880426.1493322302363.3.0) | +| 4D | 4D | [Demo](https://viewer.ohif.org/dynamic-volume?StudyInstanceUIDs=2.25.232704420736447710317909004159492840763) | +| VIDEO | Video | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=2.25.96975534054447904995905761963464388233) | +| microscopy | Slide Microscopy | [Demo](https://viewer.ohif.org/microscopy?StudyInstanceUIDs=2.25.141277760791347900862109212450152067508) | diff --git a/platform/docs/docs/assets/img/customizable-overlay.jpeg b/platform/docs/docs/assets/img/customizable-overlay.jpeg new file mode 100644 index 0000000000..e166f24406 Binary files /dev/null and b/platform/docs/docs/assets/img/customizable-overlay.jpeg differ diff --git a/platform/docs/docs/assets/img/customizable-overlay.png b/platform/docs/docs/assets/img/customizable-overlay.png deleted file mode 100644 index 05ca4d275b..0000000000 Binary files a/platform/docs/docs/assets/img/customizable-overlay.png and /dev/null differ diff --git a/platform/docs/docs/assets/img/dcm4chee-upload.gif b/platform/docs/docs/assets/img/dcm4chee-upload.gif new file mode 100644 index 0000000000..e0e94f1030 Binary files /dev/null and b/platform/docs/docs/assets/img/dcm4chee-upload.gif differ diff --git a/platform/docs/docs/assets/img/demo-4d.webp b/platform/docs/docs/assets/img/demo-4d.webp new file mode 100644 index 0000000000..0d00c2cfde Binary files /dev/null and b/platform/docs/docs/assets/img/demo-4d.webp differ diff --git a/platform/docs/docs/assets/img/demo-measurements.jpg b/platform/docs/docs/assets/img/demo-measurements.jpg deleted file mode 100644 index f26d6a579c..0000000000 Binary files a/platform/docs/docs/assets/img/demo-measurements.jpg and /dev/null differ diff --git a/platform/docs/docs/assets/img/demo-measurements.webp b/platform/docs/docs/assets/img/demo-measurements.webp new file mode 100644 index 0000000000..d6aaf88dec Binary files /dev/null and b/platform/docs/docs/assets/img/demo-measurements.webp differ diff --git a/platform/docs/docs/assets/img/demo-microscopy.png b/platform/docs/docs/assets/img/demo-microscopy.png deleted file mode 100644 index ad54801261..0000000000 Binary files a/platform/docs/docs/assets/img/demo-microscopy.png and /dev/null differ diff --git a/platform/docs/docs/assets/img/demo-pdf.webp b/platform/docs/docs/assets/img/demo-pdf.webp new file mode 100644 index 0000000000..3119a12b55 Binary files /dev/null and b/platform/docs/docs/assets/img/demo-pdf.webp differ diff --git a/platform/docs/docs/assets/img/demo-ptct.png b/platform/docs/docs/assets/img/demo-ptct.png deleted file mode 100644 index 83472f0766..0000000000 Binary files a/platform/docs/docs/assets/img/demo-ptct.png and /dev/null differ diff --git a/platform/docs/docs/assets/img/demo-ptct.webp b/platform/docs/docs/assets/img/demo-ptct.webp new file mode 100644 index 0000000000..ec0a528e16 Binary files /dev/null and b/platform/docs/docs/assets/img/demo-ptct.webp differ diff --git a/platform/docs/docs/assets/img/demo-rtstruct.webp b/platform/docs/docs/assets/img/demo-rtstruct.webp new file mode 100644 index 0000000000..7a985ff39a Binary files /dev/null and b/platform/docs/docs/assets/img/demo-rtstruct.webp differ diff --git a/platform/docs/docs/assets/img/demo-segmentation.png b/platform/docs/docs/assets/img/demo-segmentation.png deleted file mode 100644 index 3482a15c51..0000000000 Binary files a/platform/docs/docs/assets/img/demo-segmentation.png and /dev/null differ diff --git a/platform/docs/docs/assets/img/demo-segmentation.webp b/platform/docs/docs/assets/img/demo-segmentation.webp new file mode 100644 index 0000000000..2f798c326d Binary files /dev/null and b/platform/docs/docs/assets/img/demo-segmentation.webp differ diff --git a/platform/docs/docs/assets/img/demo-video.webp b/platform/docs/docs/assets/img/demo-video.webp new file mode 100644 index 0000000000..f3b3cdbbe8 Binary files /dev/null and b/platform/docs/docs/assets/img/demo-video.webp differ diff --git a/platform/docs/docs/assets/img/demo-volume-rendering.webp b/platform/docs/docs/assets/img/demo-volume-rendering.webp new file mode 100644 index 0000000000..c74915fcd0 Binary files /dev/null and b/platform/docs/docs/assets/img/demo-volume-rendering.webp differ diff --git a/platform/docs/docs/assets/img/github-readme-branches-Jun2024.png b/platform/docs/docs/assets/img/github-readme-branches-Jun2024.png new file mode 100644 index 0000000000..4129cc43be Binary files /dev/null and b/platform/docs/docs/assets/img/github-readme-branches-Jun2024.png differ diff --git a/platform/docs/docs/assets/img/github-readme-branches.png b/platform/docs/docs/assets/img/github-readme-branches.png deleted file mode 100644 index 271001a473..0000000000 Binary files a/platform/docs/docs/assets/img/github-readme-branches.png and /dev/null differ diff --git a/platform/docs/docs/assets/img/large-pt-ct.jpeg b/platform/docs/docs/assets/img/large-pt-ct.jpeg new file mode 100644 index 0000000000..9999e247e7 Binary files /dev/null and b/platform/docs/docs/assets/img/large-pt-ct.jpeg differ diff --git a/platform/docs/docs/assets/img/large-pt-ct.png b/platform/docs/docs/assets/img/large-pt-ct.png deleted file mode 100644 index 16c16bcbae..0000000000 Binary files a/platform/docs/docs/assets/img/large-pt-ct.png and /dev/null differ diff --git a/platform/docs/docs/assets/img/microscopy.webp b/platform/docs/docs/assets/img/microscopy.webp new file mode 100644 index 0000000000..e348e38229 Binary files /dev/null and b/platform/docs/docs/assets/img/microscopy.webp differ diff --git a/platform/docs/docs/assets/img/nginx-image-archive.png b/platform/docs/docs/assets/img/nginx-image-archive.png index bd75479652..f1ac06119f 100644 Binary files a/platform/docs/docs/assets/img/nginx-image-archive.png and b/platform/docs/docs/assets/img/nginx-image-archive.png differ diff --git a/platform/docs/docs/assets/img/ohif-pacs-keycloak.png b/platform/docs/docs/assets/img/ohif-pacs-keycloak.png new file mode 100644 index 0000000000..e95d2af355 Binary files /dev/null and b/platform/docs/docs/assets/img/ohif-pacs-keycloak.png differ diff --git a/platform/docs/docs/configuration/configurationFiles.md b/platform/docs/docs/configuration/configurationFiles.md index 1c945f4cbf..db24e8da95 100644 --- a/platform/docs/docs/configuration/configurationFiles.md +++ b/platform/docs/docs/configuration/configurationFiles.md @@ -124,6 +124,8 @@ Here are a list of some options available: - `acceptHeader` : accept header to request specific dicom transfer syntax ex : [ 'multipart/related; type=image/jls; q=1', 'multipart/related; type=application/octet-stream; q=0.1' ] - `investigationalUseDialog`: This should contain an object with `option` value, it can be either `always` which always shows the dialog once per session, `never` which never shows the dialog, or `configure` which shows the dialog once and won't show it again until a set number of days defined by the user, if it's set to configure, you are required to add an additional property `days` which is the number of days to wait before showing the dialog again. - `groupEnabledModesFirst`: boolean, if set to true, all valid modes for the study get grouped together first, then the rest of the modes. If false, all modes are shown in the order they are defined in the configuration. +- `experimentalStudyBrowserSort`: boolean, if set to true, you will get the experimental StudyBrowserSort component in the UI, which displays a list of sort functions that the displaySets can be sorted by, the sort reflects in all part of the app including the thumbnail/study panel. These sort functions are defined in the customizationModule and can be expanded by users. +- `disableConfirmationPrompts`: boolean, if set to true, it skips confirmation prompts for measurement tracking and hydration. - `showPatientInfo`: string, if set to 'visible', the patient info header will be shown and its initial state is expanded. If set to 'visibleCollapsed', the patient info header will be shown but it's initial state is collapsed. If set to 'disabled', the patient info header will never be shown, and if set to 'visibleReadOnly', the patient info header will be shown and always expanded. - `requestTransferSyntaxUID` : Request a specific Transfer syntax from dicom web server ex: 1.2.840.10008.1.2.4.80 (applied only if acceptHeader is not set) - `omitQuotationForMultipartRequest`: Some servers (e.g., .NET) require the `multipart/related` request to be sent without quotation marks. Defaults to `false`. If your server doesn't require this, then setting this flag to `true` might improve performance (by removing the need for preflight requests). Also note that @@ -224,7 +226,6 @@ Example usage:
supportsFuzzyMatching: false, supportsWildcard: false, singlepart: 'bulkdata,video,pdf', - useBulkDataURI: false, onConfiguration: (dicomWebConfig, options) => { const { params } = options; const { project, location, dataset, dicomStore } = params; @@ -256,6 +257,35 @@ This will result in two panels, one with `dicomSeg.panel` and `tracked.measureme ::: +### Study Prefetcher + +You can enable the study prefetcher so that OHIF loads the next/previous series/display sets +based on the proximity to the current series/display set. This can be useful to improve the user experience + + +```js + studyPrefetcher: { + /* Enable/disable study prefetching service (default: false) */ + enabled: true, + /* Number of displaysets to be prefetched (default: 2)*/ + displaySetCount: 2, + /** + * Max number of concurrent prefetch requests (default: 10) + * High numbers may impact on the time to load a new dropped series because + * the browser will be busy with all prefetching requests. As soon as the + * prefetch requests get fulfilled the new ones from the new dropped series + * are sent to the server. + * + * TODO: abort all prefetch requests when a new series is loaded on a viewport. + * (need to add support for `AbortController` on Cornerstone) + * */ + maxNumPrefetchRequests: 10, + /* Display sets loading order (closest (deafult), downward or upward) */ + order: 'closest', + }, + +``` + ### More on Accept Header Configuration In the previous section we showed that you can modify the `acceptHeader` configuration to request specific dicom transfer syntax. By default @@ -292,6 +322,7 @@ alternative data source (or even specify different default hotkeys). | `APP_CONFIG` | Which [configuration file][config-file] to copy to output as `app-config.js` | `config/default.js` | | `PROXY_TARGET` | When developing, proxy requests that match this pattern to `PROXY_DOMAIN` | `undefined` | | `PROXY_DOMAIN` | When developing, proxy requests from `PROXY_TARGET` to `PROXY_DOMAIN` | `undefined` | +| `OHIF_PORT` | The port to run the webpack server on for PWA builds. | `3000` | You can also create a new config file and specify its path relative to the build output's root by setting the `APP_CONFIG` environment variable. You can set the diff --git a/platform/docs/docs/configuration/dataSources/dicom-json.md b/platform/docs/docs/configuration/dataSources/dicom-json.md index c2b95a874b..84e7be228f 100644 --- a/platform/docs/docs/configuration/dataSources/dicom-json.md +++ b/platform/docs/docs/configuration/dataSources/dicom-json.md @@ -38,7 +38,7 @@ You could run it like this: node .scripts/dicom-json-generator.js '/path/to/study/folder' 'url/to/dicom/server/folder' 'json/output/file.json' ``` -Some modalities require additional metadata to be added to the JSON file. You can read more about the minimum amount of metadata required for the viewer to work [here](../../faq.md#what-are-the-list-of-required-metadata-for-the-ohif-viewer-to-work). We will handle this in the script. For example, the script will add the CodeSequences for SR in order to display the measurements in the viewer. +Some modalities require additional metadata to be added to the JSON file. You can read more about the minimum amount of metadata required for the viewer to work [here](../../faq/technical#what-are-the-list-of-required-metadata-for-the-ohif-viewer-to-work). We will handle this in the script. For example, the script will add the CodeSequences for SR in order to display the measurements in the viewer. ::: diff --git a/platform/docs/docs/configuration/dataSources/dicom-web.md b/platform/docs/docs/configuration/dataSources/dicom-web.md index 5548d3c39d..8e2d492501 100644 --- a/platform/docs/docs/configuration/dataSources/dicom-web.md +++ b/platform/docs/docs/configuration/dataSources/dicom-web.md @@ -65,11 +65,9 @@ yarn run orthanc:up _Upload your first Study:_ 1. Navigate to - [Orthanc's web interface](http://localhost:8042/app/explorer.html) at - `http://localhost:8042/app/explorer.html` in a web browser. -2. In the top right corner, click "Upload" -3. Click "Select files to upload..." and select one or more DICOM files -4. Click "Start the upload" + [Orthanc's web interface](http://localhost:8042/ui/app/index.html#/) at + `http://localhost:8042/ui/app/index.html#/` in a web browser. +2. In the left you can see the upload button where you can drag and drop your DICOM files #### Orthanc: Learn More @@ -104,13 +102,13 @@ is running the `dev:orthanc` script in our project's `package.json` (inside `platform/app`). That script is: ```js -cross-env NODE_ENV=development PROXY_TARGET=/dicom-web PROXY_DOMAIN=http://localhost:8042 APP_CONFIG=config/docker_nginx-orthanc.js webpack-dev-server --config .webpack/webpack.pwa.js -w +cross-env NODE_ENV=development PROXY_TARGET=/dicom-web PROXY_DOMAIN=http://localhost:8042 APP_CONFIG=config/docker-nginx-orthanc.js webpack-dev-server --config .webpack/webpack.pwa.js -w ``` - `cross-env` sets three environment variables - PROXY_TARGET: `/dicom-web` - PROXY_DOMAIN: `http://localhost:8042` - - APP_CONFIG: `config/docker_nginx-orthanc.js` + - APP_CONFIG: `config/docker-nginx-orthanc.js` - `webpack-dev-server` runs using the `.webpack/webpack.pwa.js` configuration file. It will watch for changes and update as we develop. @@ -169,6 +167,16 @@ then consider switching to using [DICOMweb instead](https://book.orthanc-server. ![toolbarModule-layout](../../assets/img/uploader.gif) +Don't forget to add the customization to the config as well + +```js +customizationService: { + dicomUploadComponent: + '@ohif/extension-cornerstone.customizationModule.cornerstoneDicomUploadComponent', +}, +``` + + #### `singlepart` A comma delimited string specifying which payloads the data source responds with as single part. Those not listed are considered multipart. Values that can be included here are `pdf`, `video`, `bulkdata`, `thumbnail` and `image`. @@ -180,6 +188,15 @@ To learn more about how you can configure the OHIF Viewer, check out our ### DICOM Upload See the [`dicomUploadEnabled`](#dicomuploadenabled) data source configuration option. +Don't forget to add the customization to the config as well + +```js +customizationService: { + dicomUploadComponent: + '@ohif/extension-cornerstone.customizationModule.cornerstoneDicomUploadComponent', +}, +``` + ### DICOM PDF See the [`singlepart`](#singlepart) data source configuration option. diff --git a/platform/docs/docs/configuration/url.md b/platform/docs/docs/configuration/url.md index c81464e2fb..cac7e5ad4d 100644 --- a/platform/docs/docs/configuration/url.md +++ b/platform/docs/docs/configuration/url.md @@ -120,47 +120,74 @@ values. ::: -### SeriesInstanceUID, SeriesInstanceUIDs and initialSeriesInstanceUID +### SeriesInstanceUIDs Sometimes you need to only retrieve a specific series in a study, you can do that by providing series level QIDO query parameters in the URL such as -SeriesInstanceUID or SeriesNumber. This does NOT work with instance or study +SeriesInstanceUIDs. This does NOT work with instance or study level parameters. For example: ```js -http://localhost:3000/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1&SeriesInstanceUID=1.3.6.1.4.1.25403.345050719074.3824.20170125113545.4 +http://localhost:3000/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5&SeriesInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095449.8 ``` This will only open the viewer with one series (one displaySet) loaded, and no queries made for any other series. Sometimes you need to only retrieve a subset of series in a study, you can do -that by providing study level wado query parameters in the URL such as -SeriesInstanceUIDs. For example: +that by providing more than one series, separated by commas. For example: ```js -http://localhost:3000/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1&SeriesInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125113545.4,1.3.6.1.4.1.25403.345050719074.3824.20170125113545.5 +http://localhost:3000/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5&SeriesInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095449.8,1.3.6.1.4.1.25403.345050719074.3824.20170125095506.10 ``` This will only open the viewer with two series (two displaySets) loaded, and no queries made for any other series. -Alternatively, sometimes you want to just open the study on a specified series -and/or display a particular sop instance, which you can accomplish using: -`initialSeriesInstanceUID` and/or `initialSOPInstanceUID` -to select the series to open on, but allowing other -series to be present in the study browser panel. This is the same behaviour -as in OHIF 2.0, albeit on different URL parameters. For example: +### initialSeriesInstanceUID + +Alternatively, sometimes you want to just open the study on a specified series, but allowing other +series to be present too. This is the same behavior can be +achieved by using the `initialSeriesInstanceUID` parameter. For example: ```js -http://localhost:3000/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1&initialSeriesInstanceUID=1.3.6.1.4.1.25403.345050719074.3824.20170125113545.4 +http://localhost:3000/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5&initialSeriesInstanceUID=1.3.6.1.4.1.25403.345050719074.3824.20170125095449.8 ``` +This will open all the series in the study, but the viewer will start with the +series specified by the `initialSeriesInstanceUID` parameter. + + Note that you can combine these, if you want to load a specific set of series plus show an initial one as the first one selected, for example: ```js -http://localhost:3000/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1&SeriesInstanceUID=1.3.6.1.4.1.25403.345050719074.3824.20170125113545.4&initialSopInstanceUID=1.3.6.1.4.1.25403.345050719074.3824.20170125113546.1 +http://localhost:3000/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5&SeriesInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095449.8,1.3.6.1.4.1.25403.345050719074.3824.20170125095506.10&initialSeriesInstanceUID=1.3.6.1.4.1.25403.345050719074.3824.20170125095506.10 +``` + +### initialSopInstanceUID + +You can also specify the initial SOP Instance to be displayed by using the +`initialSopInstanceUID` parameter. For example: + +```js +http://localhost:3000/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5&SeriesInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095449.8&initialSopInstanceUID=1.3.6.1.4.1.25403.345050719074.3824.20170125095501.9 +``` + +This will open the study with the filtered series, and navigate to the slice 101 +which happens to be the SOP Instance specified by the `initialSopInstanceUID` + +Note: again you can mix and match + +```js +http://localhost:3000/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5&SeriesInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095449.8,1.3.6.1.4.1.25403.345050719074.3824.20170125095506.10&initialSeriesInstanceUID=1.3.6.1.4.1.25403.345050719074.3824.20170125095506.10&initialSopInstanceUID=1.3.6.1.4.1.25403.345050719074.3824.20170125095510.8 +``` + +You can even load the whole study and only specify the initial SOP Instance to be displayed. Although +it will take more time to match, but it works as expected. + +```js +http://localhost:3000/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5&initialSopInstanceUID=1.3.6.1.4.1.25403.345050719074.3824.20170125095510.8 ``` ### hangingProtocolId @@ -169,6 +196,11 @@ You can select the initial hanging protocol to apply by using the hangingProtocolId parameter. The selected parameter must be available in a hangingProtocolModule registration, but does not have to be active. +For instance for loading a specific study in mpr mode from start you can use: + +```js +http://localhost:3000/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5&hangingProtocolId=@ohif/mnGrid +``` ### token diff --git a/platform/docs/docs/conformance.md b/platform/docs/docs/conformance.md index 62c9c40f8a..d0ca8ba009 100644 --- a/platform/docs/docs/conformance.md +++ b/platform/docs/docs/conformance.md @@ -1,5 +1,5 @@ --- -sidebar_position: 10 +sidebar_position: 12 sidebar_label: DICOM Conformance Statement (NEW) title: DICOM Conformance Statement --- diff --git a/platform/docs/docs/deployment/authorization.md b/platform/docs/docs/deployment/authorization.md index b80a7c9625..b3589b1a97 100644 --- a/platform/docs/docs/deployment/authorization.md +++ b/platform/docs/docs/deployment/authorization.md @@ -1,32 +1,29 @@ --- sidebar_position: 6 -sidebar_label: Authorization +sidebar_label: Auth --- -# Authorization +# Authorization and Authentication The OHIF Viewer can be configured to work with authorization servers that support one or more of the OpenID-Connect authorization flows. The Viewer finds it's OpenID-Connect settings on the oidc configuration key. You can set these values in your configuration files. For instance you can take a look at our `google.js` configuration file. ```js oidc: [ - { - // ~ REQUIRED - // Authorization Server URL - authority: 'https://accounts.google.com', - client_id: - '723928408739-k9k9r3i44j32rhu69vlnibipmmk9i57p.apps.googleusercontent.com', - redirect_uri: '/callback', - response_type: 'id_token token', - scope: - 'email profile openid https://www.googleapis.com/auth/cloudplatformprojects.readonly https://www.googleapis.com/auth/cloud-healthcare', // email profile openid - // ~ OPTIONAL - post_logout_redirect_uri: '/logout-redirect.html', - revoke_uri: 'https://accounts.google.com/o/oauth2/revoke?token=', - automaticSilentRenew: true, - revokeAccessTokenOnSignout: true, - }, - ], + { + // ~ REQUIRED + authority: 'https://accounts.google.com', + client_id: '723928408739-k9k9r3i44j32rhu69vlnibipmmk9i57p.apps.googleusercontent.com', + redirect_uri: '/callback', + response_type: 'id_token token', + scope: 'email profile openid https://www.googleapis.com/auth/cloudplatformprojects.readonly https://www.googleapis.com/auth/cloud-healthcare', // email profile openid + // ~ OPTIONAL + post_logout_redirect_uri: '/logout-redirect.html', + revoke_uri: 'https://accounts.google.com/o/oauth2/revoke?token=', + automaticSilentRenew: true, + revokeAccessTokenOnSignout: true, + }, +], ``` You need to provide the following information: @@ -53,8 +50,7 @@ const userAuthenticationService = servicesManager.services.userAuthenticationSer Then the userAuthenticationService will inject the token as Authorization header in the requests that are sent to the server (both metadata and pixelData). - -## Token based authentication +## Token based authentication in URL Sometimes (although not recommended), some servers like to send the token in the query string. In this case, the viewer will automatically grab the token from the query string and add it to the userAuthenticationService and remove it from the query string (to prevent it from being logged in the console @@ -65,3 +61,35 @@ and example would be ```js http://localhost:3000/viewer?StudyInstanceUIDs=1.2.3.4.5.6.6.7&token=e123125jsdfahsdf ``` + + + +## Implicit Flow vs Authorization Code Flow + +The Viewer supports both the Implicit Flow and the Authorization Code Flow. The Implicit Flow is the default currently, as it is easier to set up and use. However, you can opt for better security by using the Authorization Code Flow. To do so, add `useAuthorizationCodeFlow` to the configuration and change the `response_type` from `id_token token` to `code`. + +Read more about Implicit Flow vs Authorization Code Flow [here](https://documentation.openiddict.com/guides/choosing-the-right-flow.html#:~:text=The%20implicit%20flow%20is%20similar,when%20using%20response_mode%3Dform_post%20) and [here](https://medium.com/@alysachan830/the-basics-of-oauth-2-0-authorization-code-implicit-flow-state-and-pkce-ed95d3478e1c) + +```js +oidc: [ + { + authority: 'https://accounts.google.com', + client_id: '723928408739-k9k9r3i44j32rhu69vlnibipmmk9i57p.apps.googleusercontent.com', + redirect_uri: '/callback', + scope: 'email profile openid', + post_logout_redirect_uri: '/logout-redirect.html', + revoke_uri: 'https://accounts.google.com/o/oauth2/revoke?token=', + revokeAccessTokenOnSignout: true, + automaticSilentRenew: true, + // CHANGE THESE ***************************** + response_type: 'code', + useAuthorizationCodeFlow: true, + }, +], +``` + +In fact, since browsers are blocking third-party cookies, the Implicit Flow will cease functioning in the future (not specific to OHIF). Read more [here](https://support.okta.com/help/s/article/FAQ-How-Blocking-Third-Party-Cookies-Can-Potentially-Impact-Your-Okta-Environment?language=en_US). It is recommended to use the Authorization Code Flow and begin migrating to it. + +:::note +For the Authorization Code Flow, when authenticating against Google, you must add the `client_secret` to the configuration as well. Unfortunately, this seems to occur only with Google. +::: diff --git a/platform/docs/docs/deployment/google-cloud-healthcare.md b/platform/docs/docs/deployment/google-cloud-healthcare.md index 73b3785542..54df8bb029 100644 --- a/platform/docs/docs/deployment/google-cloud-healthcare.md +++ b/platform/docs/docs/deployment/google-cloud-healthcare.md @@ -1,5 +1,5 @@ --- -sidebar_position: 10 +sidebar_position: 9 --- # Google Cloud Healthcare diff --git a/platform/docs/docs/deployment/nginx--image-archive.md b/platform/docs/docs/deployment/nginx--image-archive.md index 8d86587980..b1a2fd34b8 100644 --- a/platform/docs/docs/deployment/nginx--image-archive.md +++ b/platform/docs/docs/deployment/nginx--image-archive.md @@ -1,11 +1,9 @@ --- -sidebar_position: 9 +sidebar_position: 10 --- # Nginx + Image Archive -> DISCLAIMER! We make no claims or guarantees of this approach's security. If in -> doubt, enlist the help of an expert and conduct proper audits. At a certain point, you may want others to have access to your instance of the OHIF Viewer and its medical imaging data. This post covers one of many potential @@ -16,19 +14,14 @@ Do not use this recipe to host sensitive medical data on the open web. Depending on your company's policies, this may be an appropriate setup on an internal network when protected with a server's basic authentication. -## Overview -Our two biggest hurdles when hosting our image archive and web client are: - -- Risks related to exposing our PACS to the network -- Cross-Origin Resource Sharing (CORS) requests ### Handling Web Requests We mitigate our first issue by allowing [Nginx][nginx] to handle incoming web requests. Nginx is open source software for web serving, reverse proxying, caching, and more. It's designed for maximum performance and stability -- -allowing us to more reliably serve content than Orthanc's built-in server can. +allowing us to more reliably serve content. More specifically, we accomplish this by using a [`reverse proxy`](https://en.wikipedia.org/wiki/Reverse_proxy) to retrieve @@ -38,35 +31,16 @@ resources from our image archive (Orthanc), and when accessing its web admin. > of a client from one or more servers. These resources are then returned to the > client, appearing as if they originated from the proxy server itself. -### CORS Issues - -Cross-Origin Resource Sharing (CORS) is a mechanism that uses HTTP headers to -tell a browser which web applications have permission to access selected -resources from a server at a different origin (domain, protocol, port). IE. By -default, a Web App located at `http://my-website.com` can't access resources -hosted at `http://not-my-website.com` - -We can solve this one of two ways: - -1. Have our Image Archive located at the same domain as our Web App -2. Add appropriate `Access-Control-Allow-*` HTTP headers -**This solution uses the first approach.** - -You can read more about CORS in this Medium article: [Understanding -CORS][understanding-cors] - -### Diagram This setup allows us to create a setup similar to the one pictured below: ![nginX](../assets/img/nginx-image-archive.png) - -- All web requests are routed through `nginx` on our `OpenResty` image -- `/pacs` is a reverse proxy for `orthanc`'s `DICOM Web` endpoints -- `/pacs-admin` is a reverse proxy for `orthanc`'s Web Admin +- All web requests are routed through `nginx` image +- `/pacs/dicom-web` is a reverse proxy for `orthanc`'s `DICOM Web` endpoints, which handles DICOM requests +- `/pacs` is a reverse proxy for `orthanc`'s Web Admin, which is the UI for managing studies - All static resources for OHIF Viewer are served up by `nginx` when a matching route for that resource is requested @@ -83,36 +57,40 @@ in command prompt or terminal_ ### Setup -- Navigate to `app` folder inside `platform` -- then: `cd .recipes/OpenResty-Orthanc` +- `cd platform/app/.recipes/Nginx-Orthanc` - run: `docker-compose up --build` -- Navigate to `127.0.0.1` for the viewer -- Navigate to `127.0.0.1/pacs-admin` for uploading studies via the UI, or send studies via DIMSE C-STORE to `ORTHANC@127.0.0.1:4242` (hint: you can use utilites like dcm4che's `storescu` to send studies in bulk via the command line) +- Navigate to `127.0.0.1` for the viewer (at first there is no study) +- Navigate to `127.0.0.1/pacs` for uploading studies via the UI, or send studies via DIMSE C-STORE to `ORTHANC@127.0.0.1:4242` (hint: you can use utilizes like dcm4che's `storescu` to send studies in bulk via the command line) +:::note +For subsequent runs, use `docker-compose up -d` to start the services without rebuilding the images. However, ensure you rebuild the images if you make changes to the Dockerfile. If you modify the configurations in the `nginx.conf` or `orthanc.json` files, you can restart the services by running `docker-compose up`, as these files are mounted as volumes. +``` +Inside docker compose file you see the following volumes mounted: -You can see the overview of the mentioned steps: +volumes: + # Nginx config + - ./config/nginx.conf:/etc/nginx/nginx.conf + # Logs + - ./logs/nginx:/var/logs/nginx +``` +::: +You can see the overview of the mentioned steps: -
- -
- ### Troubleshooting @@ -154,10 +132,10 @@ configuration we use is set to a specific file when we build the viewer, and determined by the env variable: `APP_CONFIG`. You can see where we set its value in the `dockerfile` for this solution: -`ENV APP_CONFIG=config/docker_openresty-orthanc.js` +`ENV APP_CONFIG=config/docker-nginx-orthanc.js` You can find the configuration we're using here: -`/public/config/docker_openresty-orthanc.js` +`/public/config/docker-nginx-orthanc.js` To rebuild the `webapp` image created by our `dockerfile` after updating the Viewer's configuration, you can run: @@ -167,78 +145,49 @@ Viewer's configuration, you can run: #### Other -All other files are found in: `/docker/OpenResty-Orthanc/` +All other files are found in: `/docker/Nginx-Orthanc/` | Service | Configuration | Docs | | ----------------- | --------------------------------- | ------------------------------------------- | | OHIF Viewer | [dockerfile][dockerfile] | You're reading them now! | -| OpenResty (Nginx) | [`/nginx.conf`][config-nginx] | [lua-resty-openidc][lua-resty-openidc-docs] | +| Nginx | [`/nginx.conf`][config-nginx] | | | Orthanc | [`/orthanc.json`][config-orthanc] | [Here][orthanc-docs] | ## Next Steps -### Deploying to Production - -While these configuration and docker-compose files model an environment suitable -for production, they are not easy to deploy "as is". You can either: - -- Manually recreate this environment and deploy built application files **OR** -- Deploy to a cloud kubernetes provider like - [Digital Ocean](https://www.digitalocean.com/products/kubernetes/) **OR** - - [See a full list of cloud providers here](https://landscape.cncf.io/category=cloud&format=card-mode&grouping=category) -- Find and follow your preferred provider's guide on setting up - [swarms and stacks](https://docs.docker.com/get-started/) +### OHIF + Dcm4chee -### Adding SSL +You can follow the similar steps above to run OHIF Viewer with Dcm4chee PACS. -Adding SSL registration and renewal for your domain with Let's Encrypt that -terminates at Nginx is an incredibly important step toward securing your data. -Here are some resources, specific to this setup, that may be helpful: +The recipe for this setup can be found at `platform/app/.recipes/Nginx-Dcm4chee`. -- [lua-resty-auto-ssl](https://github.com/GUI/lua-resty-auto-ssl) -- [Let's Encrypt + Nginx](https://www.nginx.com/blog/using-free-ssltls-certificates-from-lets-encrypt-with-nginx/) -While we terminate SSL at Nginx, it may be worth using self-signed certificates -for communication between services. +The routes are as follows: +- `127.0.0.1` for the OHIF viewer +- `127.0.0.1/pacs` for the Dcm4chee UI -- [SSL Termination for TCP Upstream Servers](https://docs.nginx.com/nginx/admin-guide/security-controls/terminating-ssl-tcp/) +:::info +For uploading studies, you can see the following gif for the steps: -### Use PostgresSQL w/ Orthanc +![alt text](../assets/img/dcm4chee-upload.gif) -Orthanc can handle a large amount of data and requests, but if you find that -requests start to slow as you add more and more studies, you may want to -configure your Orthanc instance to use PostgresSQL. Instructions on how to do -that can be found in the -[`Orthanc Server Book`](http://book.orthanc-server.com/users/docker.html), under -"PostgreSQL and Orthanc inside Docker" - -### Improving This Guide +::: -Here are some improvements this guide would benefit from, and that we would be -more than happy to accept Pull Requests for: +### Deploying to Production -- SSL Support -- Complete configuration with `.env` file (or something similar) -- Any security issues -- One-click deploy to a cloud provider +While you can deploy this solution to production, there is one main caveat: every user can access the app and the patient portal without any authentication. In the next step, we will add authentication with Keycloak to secure the app. -## Resources -### Misc. Helpful Commands -_Check if `nginx.conf` is valid:_ -```bash -docker run --rm -t -a stdout --name my-openresty -v $PWD/config/:/usr/local/openresty/nginx/conf/:ro openresty/openresty:alpine-fat openresty -c /usr/local/openresty/nginx/conf/nginx.conf -t -``` +### Improving This Guide -_Interact w/ running container:_ +Here are some improvements this guide would benefit from, and that we would be +more than happy to accept Pull Requests for: -`docker exec -it CONTAINER_NAME bash` +- Add Docker caching for faster builds -_List running containers:_ -`docker ps` ### Referenced Articles @@ -246,8 +195,6 @@ For more documentation on the software we've chosen to use, you may find the following resources helpful: - [Orthanc for Docker](http://book.orthanc-server.com/users/docker.html) -- [OpenResty Guide](http://www.staticshin.com/programming/definitely-an-open-resty-guide/) -- [Lua Ngx API](https://openresty-reference.readthedocs.io/en/latest/Lua_Nginx_API/) For a different take on this setup, check out the repositories our community members put together: diff --git a/platform/docs/docs/deployment/user-account-control.md b/platform/docs/docs/deployment/user-account-control.md index 5447ce282c..87f0235bea 100644 --- a/platform/docs/docs/deployment/user-account-control.md +++ b/platform/docs/docs/deployment/user-account-control.md @@ -3,8 +3,10 @@ sidebar_position: 11 --- # User Account Control -> DISCLAIMER! We make no claims or guarantees of this approach's security. If in -> doubt, enlist the help of an expert and conduct proper audits. + +:::danger +DISCLAIMER: We make no claims or guarantees regarding the security of this approach. If you have any doubts, please consult an expert and conduct thorough audits. +::: Making a viewer and its medical imaging data accessible on the open web can provide a lot of benefits, but requires additional security to make sure @@ -18,7 +20,7 @@ sensitive data. ## Overview This guide builds on top of our -[Nginx + Image Archive guide](/deployment/recipes/nginx--image-archive.md), +[Nginx + Image Archive guide](./nginx--image-archive.md), wherein we used a [`reverse proxy`](https://en.wikipedia.org/wiki/Reverse_proxy) to retrieve resources from our image archive (Orthanc). @@ -35,20 +37,43 @@ applications and services with little to no code. We improve upon our This setup allows us to create a setup similar to the one pictured below: -![userControlFlow](../assets/img/user-access-control-request-flow.png) +![userControlFlow](../assets/img/ohif-pacs-keycloak.png) + + + +**Nginx:** + +- Acts as a reverse proxy server that handles incoming requests to the domain (mydomain.com:80) and forwards them to the appropriate backend services. +- It also ensures that all requests go through the OAuth2 Proxy for authentication. + + +**OAuth2 Proxy:** + +- Serves as an intermediary that authenticates users via OAuth2. +- Works in conjunction with Keycloak to manage user sessions and authentication tokens. +- Once the user is authenticated, it allows access to specific routes (/ohif-viewer, /pacs, /pacs-admin). + +**Keycloak:** + +- An open-source identity and access management solution. +- Manages user identities, including authentication and authorization. +- Communicates with the OAuth2 Proxy to validate user credentials and provide tokens for authenticated sessions. + +**OHIF Viewer:** + +- Hosted under the route /ohif-viewer, which serves the static assets of the OHIF Viewer. +**Orthanc/DCM4chee:** +- PACS (Picture Archiving and Communication System) for managing medical imaging data. +Exposes two routes: +- /pacs: Accesses the DICOM web services. +- /pacs-admin: Provides administrative and explorer interfaces. -- All web requests are routed through `nginx` on our `OpenResty` image -- `/pacs` is a reverse proxy for `orthanc`'s `DICOM Web` endpoints - - Requires valid `Authorization: Bearer ` header -- `/pacs-admin` is a reverse proxy for `orthanc`'s Web Admin -- `/auth` is a reverse proxy for `keycloak` -- All static resources for OHIF Viewer are unprotected and accessible. We have - application logic that will redirect unauthenticated users to the appropriate - `keycloak` login screen. -## Getting Started + +## Getting Started - Orthanc + ### Requirements @@ -59,46 +84,336 @@ This setup allows us to create a setup similar to the one pictured below: _Not sure if you have `docker` installed already? Try running `docker --version` in command prompt or terminal_ -### Setup +### Setup 1 - Trying Locally + +Navigate to the Orthanc Keycloak configuration directory: + +`cd platform\app\.recipes\Nginx-Orthanc-Keycloak` + +Due to the increased complexity of this setup, we've introduced a magic word `YOUR_DOMAIN`. Replace this word with your project IP address to follow along more easily. + +Since we are running this locally, we will use `127.0.0.1` as our IP address. + +In the `docker-compose.yml` file, replace `YOUR_DOMAIN` with `127.0.0.1`. + +In the Keycloak service: + + +Before: + +``` +KC_HOSTNAME_ADMIN_URL: http://YOUR_DOMAIN/keycloak/ +KC_HOSTNAME_URL: http://YOUR_DOMAIN/keycloak/ +``` + + +After + +``` +KC_HOSTNAME_ADMIN_URL: http://127.0.0.1/keycloak/ +KC_HOSTNAME_URL: http://127.0.0.1/keycloak/ +``` + +In the Keycloak healthcheck, replace `YOUR_DOMAIN` with `localhost`. + +In the Nginx config, change: + +``` +server_name YOUR_DOMAIN; +``` + +to: + +``` +server_name 127.0.0.1; +``` + +Since we're not using SSL, remove the following lines from the Nginx config file and create one server instead of two: + +Before (two servers one for http and one for https): + +``` +server { + listen 80; + server_name YOUR_DOMAIN; + + location /.well-known/acme-challenge/ { + root /var/www/certbot; + } + + location / { + return 301 https://$host$request_uri; + } +} + +server { + listen 443 ssl; + server_name YOUR_DOMAIN; + + ssl_certificate /etc/letsencrypt/live/ohifviewer.duckdns.org/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/ohifviewer.duckdns.org/privkey.pem; + + root /var/www/html; +``` + +After (merging both servers into one only http server): + +``` +server { + listen 80; + server_name 127.0.0.1; + + location /.well-known/acme-challenge/ { + root /var/www/certbot; + } + + root /var/www/html; +``` + +In OAuth2-proxy configuration at `oauth2-proxy.cfg` + +Before: + +``` +redirect_url="http://YOUR_DOMAIN/oauth2/callback" +oidc_issuer_url="http://YOUR_DOMAIN/keycloak/realms/ohif" +``` + +After: + +``` +redirect_url="http://127.0.0.1/oauth2/callback" +oidc_issuer_url="http://127.0.0.1/keycloak/realms/ohif" +``` + +Finally, in the docker-nginx-orthanc-keycloak config file that lives in `platform/app/public/config/docker-nginx-orthanc-keycloak.js`, replace `YOUR_DOMAIN` with + +Before: + +``` +wadoUriRoot: 'http://YOUR_DOMAIN/pacs', +qidoRoot: 'http://YOUR_DOMAIN/pacs', +wadoRoot: 'http://YOUR_DOMAIN/pacs', +``` + +After: + +``` +wadoUriRoot: 'http://127.0.0.1/pacs', +qidoRoot: 'http://127.0.0.1/pacs', +wadoRoot: 'http://127.0.0.1/pacs', +``` + +:::note +This is the config that is used inside the dockerfile to build the viewer, look at dockerfile + +`ENV APP_CONFIG=config/docker-nginx-orthanc-keycloak.js` +::: + +Run the following command to start the services: + +``` +docker-compose up --build +``` + + +You can watch the following video, which will guide you through the process of setting up Orthanc with keycloak and OHIF locally. + +We have set up two predefined users in Keycloak: + +- `user: admin password: admin` - Has access to keycloak portal for managing users and clients +- `user: viewer password: viewer` - Has access to the OHIF Viewer but not the pacs-admin +- `user: pacsadmin password: pacsadmin` - Has access to both the pacs-admin for uploading and the OHIF Viewer + +You can navigate to: + +- `http://127.0.0.1` - This will redirect you to `http://127.0.0.1/ohif-viewer`, prompting you to log in with Keycloak using either user +- `http://127.0.0.1/pacs-admin` - Only the `pacsadmin` user can access this route, while the `viewer` user cannot +- + +
+ +
+ + +### Step 2 - Trying via a Server + +Now that you have successfully set up Orthanc with Keycloak and OHIF locally, you can deploy it to a server. While you can rent a server from any provider, this tutorial will demonstrate the process using Linode as an example. -_Spin Things Up_ +You can watch the following video, which will guide you through the process. -- Navigate to `platform\app\.recipes\OpenResty-Orthanc-Keycloak` in your shell -- Run `docker-compose up` +Some notes: -_Create Your First User_ +- Since this is a remote machine we need to clone the repo +- Typically a Linux machine, you need to download and install Docker on it +- Use the Visual Studio Code Remote SSH extension to connect to the server +- Use docker extension in Visual Studio Code to manage the containers +- The public IP address of the server now becomes the YOUR_DOMAIN and is used in the configuration files. -- Navigate to: `http://127.0.0.1/auth/admin` -- Sign in with: `admin`/`password` -- From the top left dropdown, select the `Ohif` realm -- From the left sidebar, under `Manage`, select `Users` -- Click `Add User` - - Username: `test` - - Email Verified: `ON` - - Click `Save` -- Click the `Credentials` Tab - - New Password: `test` - - Password Confirmation: `test` - - Temporary: `OFF` - - Click: `Reset Password` -- From the top right dropdown, select `Admin`, then `Sign Out` +Still we have not set up SSL, so we will use HTTP instead of HTTPS. -_Sign In_ +We should use the same one server configuration as we did locally for Nginx (but with the new server IP address) -- Navigate to `http://127.0.0.1/` -- Username: `test`, Password: `test` -- Click `Log In` +:::info +Don't forget to change the `docker-ngix-orthanc-keycloak.js` file to use the new server IP address. +::: -_Upload Your First Study_ +After you run `docker compose up --build` you can navigate to the server IP address and see the viewer will not work... -- Navigate to `http://127.0.0.1/pacs-admin` -- If you're not already logged in, use `test`/`test` -- From the top right, select "Upload" -- Click "Select files to upload..." (DICOM) -- Click "Start the upload" -- Navigate back to `http://127.0.0.1/` to view your studies in the Study List +We have encountered some strange issues with the Keycloak service not allowing non-HTTPS connections (around 10:00). To resolve this, we need to modify the Keycloak configuration to permit HTTPS. This requires accessing the container and making the necessary changes. -### Troubleshooting +After accessing the container shell + +``` +cd /opt/keycloak/bin + +./kcadm.sh config credentials --server http://localhost:8080 --realm master --user admin +./kcadm.sh update realms/master -s sslRequired=NONE +``` + +After we need to change some configurations in the Keycloak UI to enable the connection in the server + +Navigate to + +``` +http://IP_ADDRESS/keycloak +``` + +which will redirect you to the Keycloak login page + +0. login with the admin user `admin` and password `admin` +1. From the top left drop down menu, select `ohif` realm +2. Go to `Clients` and select `ohif_viewer` +3. In the `Access Settings` change all instances of `http://127.0.0.1` to `http://IP_ADDRESS` + 1. Root URL: `http://IP_ADDRESS` + 2. Home URL: `http://IP_ADDRESS` + 3. Valid Redirect URIs: `http://IP_ADDRESS/oauth2/callback` + 4. Valid post logout URIs: `*` + 5. Web Origins: `http://IP_ADDRESS` + 6. Admin URL: `http://IP_ADDRESS` + +Now if you navigate to the IP address it should work !! + + +
+ +
+ +### Step 3 - Adding SSL and Deploying to Production + +Now we'll add an SSL certificate to our server to enable HTTPS. We'll use Let's Encrypt to generate the SSL certificate. + +Let's Encrypt requires a domain name, so we'll use a free domain name service like DuckDNS (duckdns.org). Follow these steps: + +1. Visit https://www.duckdns.org/ and create an account. +2. Create a free domain name and point it to your server's IP address. + +You can watch a video guide for this process if needed. + +Replace `YOUR_DOMAIN` with your new domain name in the `docker-compose.yml` file and all other config files, as we did previously. + +Next, we'll add HTTPS support. Add the following lines to the Nginx config file: + +(Note: We'll have both HTTP and HTTPS servers, and the server IP will use HTTPS) +``` +server { + listen 80; + server_name https://IP_ADDRESS; + + location /.well-known/acme-challenge/ { + root /var/www/certbot; + } + + location / { + return 301 https://$host$request_uri; + } +} + +server { + listen 443 ssl; + server_name https://IP_ADDRESS; + + ssl_certificate /etc/letsencrypt/live/ohifviewer.duckdns.org/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/ohifviewer.duckdns.org/privkey.pem; + + root /var/www/html; +``` + +Don't forget to replace `YOUR_DOMAIN` with the new domain name in the `docker-nginx-orthanc-keycloak.js` file. + +:::info +Remember to include `https://` when adding the domain name to the configurations. +::: + +Now, we need to add a certificate. Let's assume we have the domain name `hospital.duckdns.org` and the email we registered with DuckDNS is `your_email@example.com`. + +``` + docker run -it --rm --name certbot \ + -v ./config/letsencrypt:/etc/letsencrypt \ + -v ./config/certbot:/var/www/certbot \ + -p 80:80 \ + certbot/certbot certonly \ + --standalone \ + --preferred-challenges http \ + --email your_email@example.com \ + --agree-tos \ + --no-eff-email \ + -d hospital.duckdns.org +``` + +:::note +Replace "hospital.duckdns.org" with your domain name and update the email address accordingly. +::: + +:::warning +DuckDNS is suitable for testing and demonstration purposes only. For production environments, use a proper domain name and SSL certificate to ensure security. +::: + +If you follow these steps, you'll encounter the error `invalid parameter: redirect_uri` when attempting to log in to Keycloak. This occurs because the redirect URL isn't set up correctly in the Keycloak client configuration. To resolve this, we need to log in and adjust these settings. + +Navigate to: + +``` +http://IP_ADDRESS/keycloak +``` + +Log in using the admin credentials: +- Username: `admin` +- Password: `admin` + +Replace all IP addresses with the new domain name, using HTTPS. + +
+ +
+ + + + + + +## Getting Started - DCM4CHEE + + + + +You can follow the same steps as above to set up DCM4CHEE. The only difference is that you need to navigate to the correct directory. `platform\app\.recipes\Nginx-Dcm4chee-Keycloak` + +You can watch the following video, which will guide you through the process of setting up DCM4CHEE. + + +
+ +
+ + + +## Troubleshooting + + +_invalid parameter: redirect_uri_ + +This means the redirect URL isn't set up correctly in the Keycloak client configuration. To resolve this, log in to Keycloak and adjust the settings in the correct client (ohif_viewer) and correct realm (ohif). _Exit code 137_ @@ -116,14 +431,6 @@ Stop running all containers: - Win: `docker ps -a -q | ForEach { docker stop $_ }` - Linux: `docker stop $(docker ps -a -q)` -### Configuration - -After verifying that everything runs with default configuration values, you will -likely want to update: - -- The domain: `http://127.0.0.1` -- Set secure, non-default passwords -- Regenerate Keycloak Client Secrets #### OHIF Viewer @@ -132,10 +439,10 @@ configuration we use is set to a specific file when we build the viewer, and determined by the env variable: `APP_CONFIG`. You can see where we set its value in the `dockerfile` for this solution: -`ENV APP_CONFIG=config/docker_openresty-orthanc-keycloak.js` +`ENV APP_CONFIG=config/docker-nginx-orthanc-keycloak.js` You can find the configuration we're using here: -`/public/config/docker_openresty-orthanc-keycloak.js` +`/public/config/docker-nginx-orthanc-keycloak.js` To rebuild the `webapp` image created by our `dockerfile` after updating the Viewer's configuration, you can run: @@ -143,25 +450,15 @@ Viewer's configuration, you can run: - `docker-compose build` OR - `docker-compose up --build` -#### Other - -All other files are found in: `/docker/OpenResty-Orthanc-Keycloak/` -| Service | Configuration | Docs | -| ----------------- | ------------------------------------------------ | ------------------------------------------- | -| OHIF Viewer | [dockerfile][dockerfile] / [config.js][config] | You're reading them now! | -| OpenResty (Nginx) | [`/nginx.conf`][config-nginx] | [lua-resty-openidc][lua-resty-openidc-docs] | -| Orthanc | [`/orthanc.json`][config-orthanc] | [Here][orthanc-docs] | -| Keycloak | [`/ohif-keycloak-realm.json`][config-keycloak]\* | | -\* These are the seed values for Keycloak. They can be manually updated at -`http://127.0.0.1/auth/admin` +## Next Steps -#### Keycloak Themeing +### Keycloak Theming The `Login` screen for the `ohif-viewer` client is using a Custom Keycloak theme. You can find the source files for it in -`/docker/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes/`. You can see how +`platform/app/.recipes/deprecated-recipes/OpenResty-Orthanc-Keycloak/volumes/keycloak-themes`. You can see how we add it to Keycloak in the `docker-compose` file, and you can read up on how to leverage custom themes in [Keycloak's own docs](https://www.keycloak.org/docs/latest/server_development/index.html#_themes). @@ -170,77 +467,12 @@ to leverage custom themes in | ---------------------------------------------------------------------- | ---------------------------------------------------------------- | | ![Keycloak Default Theme](../assets/img/keycloak-default-theme.png) | ![Keycloak OHIF Theme](../assets/img/keycloak-ohif-theme.png) | -## Next Steps - -### Deploying to Production - -While these configuration and docker-compose files model an environment suitable -for production, they are not easy to deploy "as is". You can either: - -- Manually recreate this environment and deploy built application files **OR** -- Deploy to a cloud kubernetes provider like - [Digital Ocean](https://www.digitalocean.com/products/kubernetes/) **OR** - - [See a full list of cloud providers here](https://landscape.cncf.io/category=cloud&format=card-mode&grouping=category) -- Find and follow your preferred provider's guide on setting up - [swarms and stacks](https://docs.docker.com/get-started/) - -### Adding SSL - -Adding SSL registration and renewal for your domain with Let's Encrypt that -terminates at Nginx is an incredibly important step toward securing your data. -Here are some resources, specific to this setup, that may be helpful: - -- [lua-resty-auto-ssl](https://github.com/GUI/lua-resty-auto-ssl) -- [Let's Encrypt + Nginx](https://www.nginx.com/blog/using-free-ssltls-certificates-from-lets-encrypt-with-nginx/) - -While we terminate SSL at Nginx, it may be worth using self signed certificates -for communication between services. - -- [SSL Termination for TCP Upstream Servers](https://docs.nginx.com/nginx/admin-guide/security-controls/terminating-ssl-tcp/) - -### Use PostgresSQL w/ Orthanc -Orthanc can handle a large amount of data and requests, but if you find that -requests start to slow as you add more and more studies, you may want to -configure your Orthanc instance to use PostgresSQL. Instructions on how to do -that can be found in the -[`Orthanc Server Book`](http://book.orthanc-server.com/users/docker.html), under -"PostgreSQL and Orthanc inside Docker" -### Improving This Guide -Here are some improvements this guide would benefit from, and that we would be -more than happy to accept Pull Requests for: - -- SSL Support -- Complete configuration with `.env` file (or something similar) -- Keycloak Theme improvements -- Any security issues -- One-click deploy to a cloud provider ## Resources -### Misc. Helpful Commands - -_Check if `nginx.conf` is valid:_ - -```bash -docker run --rm -t -a stdout --name my-openresty -v $PWD/config/:/usr/local/openresty/nginx/conf/:ro openresty/openresty:alpine-fat openresty -c /usr/local/openresty/nginx/conf/nginx.conf -t -``` - -_Interact w/ running container:_ - -`docker exec -it CONTAINER_NAME bash` - -_List running containers:_ - -`docker ps` - -_Clear Keycloak DB so you can re-seed values:_ - -- `docker volume prune` OR -- `docker volume ls` and `docker volume rm VOLUME_NAME VOLUME_NAME` - ### Referenced Articles The inspiration for our setup was driven largely by these articles: diff --git a/platform/docs/docs/development/architecture.md b/platform/docs/docs/development/architecture.md index 4ac0561946..f8755c68ab 100644 --- a/platform/docs/docs/development/architecture.md +++ b/platform/docs/docs/development/architecture.md @@ -162,7 +162,7 @@ logic you desire. As the components are presentational, you may swap out the viewer. The UI library is here to make development easier and quicker, but it is not mandatory for extension components to use. -[Check out our component library!](https://react.ohif.org/) +[Check out our component library!](https://ui.ohif.org/) ## Overview of the architecture diff --git a/platform/docs/docs/development/getting-started.md b/platform/docs/docs/development/getting-started.md index cafb0f538a..32214b66fa 100644 --- a/platform/docs/docs/development/getting-started.md +++ b/platform/docs/docs/development/getting-started.md @@ -40,6 +40,7 @@ aren't as concerned with syncing updates, then follow these steps: ## Developing + ### Branches #### `master` branch - The latest dev (beta) release @@ -50,19 +51,17 @@ This is typically where the latest development happens. Code that is in the mast Each package is tagged with beta version numbers, and published to npm such as `@ohif/ui@3.6.0-beta.1` -### `release` branch - The latest stable release - -This branch represents the latest stable version of the project that is considered ready for production. The code in this branch should be fully tested and vetted for release. Once the code in the master branch reaches a state where it's stable and ready to be released to users, -we do a comprehensive code review and QA testing. Once the code is approved, -we merge it into the release branch and tag a new release. +### `release/*` branches - The latest stable releases +Once the `master` branch code reaches a stable, release-ready state, we conduct a comprehensive code review and QA testing. Upon approval, we create a new release branch from `master`. These branches represent the latest stable version considered ready for production. -Each package is tagged with version numbers, and published to npm such as `@ohif/ui@3.5.0` +For example, `release/3.5` is the branch for version 3.5.0, and `release/3.6` is for version 3.6.0. After each release, we wait a few days to ensure no critical bugs. If any are found, we fix them in the release branch and create a new release with a minor version bump, e.g., 3.5.1 in the `release/3.5` branch. -Note: `master` is always ahead of `release` branch. We publish both docker builds for beta and stable releases. +Each package is tagged with version numbers and published to npm, such as `@ohif/ui@3.5.0`. Note that `master` is always ahead of the `release` branch. We publish docker builds for both beta and stable releases. Here is a schematic representation of our development workflow: -![Alt text](../../docs/assets/img/github-readme-branches.png) +![alt text](../assets/img/github-readme-branches-Jun2024.png) + ### Requirements diff --git a/platform/docs/docs/development/playwright-testing.md b/platform/docs/docs/development/playwright-testing.md new file mode 100644 index 0000000000..679872399b --- /dev/null +++ b/platform/docs/docs/development/playwright-testing.md @@ -0,0 +1,159 @@ +--- +sidebar_position: 11 +sidebar_label: Playwright Testing +--- + +# Writing PlayWright Tests + +Our Playwright tests are written using the Playwright test framework. We use these tests to test our OHIF Viewer and ensure that it is working as expected. + +In this guide, we will show you how to write Playwright tests for the OHIF Viewer. + +## Using a specific study and mode + +If you would like to use a specific study, you can use the `studyInstanceUID` property to reference the study you would like to visit. for example, if you would like to use the study with StudyInstanceUID `2.16.840.1.114362.1.11972228.22789312658.616067305.306.2` and the mode `Basic Viewer`, you can use the following code snippet: + +```ts +import { test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths } from './utils/index.js'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '2.16.840.1.114362.1.11972228.22789312658.616067305.306.2'; + const mode = 'Basic Viewer'; + await visitStudy(page, studyInstanceUID, mode); +}); + +test.describe('Some Test', async () => { + test('should do something.', async ({ page }) => { + // Your test code here... + }); +}); + +``` + +## Screenshots + +A good way to check your tests is working as expected is to capture screenshots at different stages of the test. You can use our `checkForScreenshot` function located in `tests/utils/checkForScreenshot.ts` to capture screenshots. You should also plan your screenshots in advance, screenshots need to be defined in the `tests/utils/screenshotPaths.ts` file. For example, if you would to capture a screenshot after a measurement is added, you can define a screenshot path like this: + +```ts +const screenShotPaths = { + your_test_name: { + measurementAdded: 'measurementAdded.png', + measurementRemoved: 'measurementRemoved.png', + }, +}; +``` + +It's okay if the screenshot doesn't exist yet, this will be dealt with in the next step. Once you have defined your screenshot path, you can use the `checkForScreenshot` function in your test to capture the screenshot. For example, if you would like to capture a screenshot of the page after a measurement is added, you can use the following code snippet: + +```ts +import { test } from '@playwright/test'; +import { + visitStudy, + checkForScreenshot, + screenshotPath, +} from './utils/index.js'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '2.16.840.1.114362.1.11972228.22789312658.616067305.306.2'; + const mode = 'Basic Viewer'; + await visitStudy(page, studyInstanceUID, mode); +}); + +test.describe('Some test', async () => { + test('should do something', async ({ page }) => { + // Your test code here to add a measurement + await checkForScreenshot( + page, + page, + screenshotPath.your_test_name.measurementAdded + ); + }); +}); +``` + +The test will automatically fail the first time you run it, it will however generate the screenshot for you, you will notice 3 new entries in the `tests/screenshots` folder, under `chromium/your-test.spec.js/measurementAdded.png`, `firefox/your-test.spec.js/measurementAdded.png` and `webkit/your-test.spec.js/measurementAdded.png` folders. You can now run the test again and it will use those screenshots to compare against the current state of the example. Please verify that the ground truth screenshots are correct before committing them or testing against them. + +## Simulating mouse drags + +If you would like to simulate a mouse drag, you can use the `simulateDrag` function located in `tests/utils/simulateDrag.ts`. You can use this function to simulate a mouse drag on an element. For example, if you would like to simulate a mouse drag on the `cornerstone-canvas` element, you can use the following code snippet: + +```ts +import { + visitStudy, + checkForScreenshot, + screenShotPaths, + simulateDrag, +} from './utils/index.js'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '2.16.840.1.114362.1.11972228.22789312658.616067305.306.2'; + const mode = 'Basic Viewer'; + await visitStudy(page, studyInstanceUID, mode); +}); + +test.describe('Some Test', async () => { + test('should do something..', async ({ + page, + }) => { + const locator = page.locator('.cornerstone-canvas'); + await simulateDrag(page, locator); + }); +}); +``` + +Our simulate drag utility can simulate a drag on any element, and avoid going out of bounds. It will calculuate the bounding box of the element and ensure that the drag stays within the bounds of the element. This should be good enough for most tools, and better than providing custom x, and y coordinates which can be error prone and make the code difficult to maintain. + +## Running the tests + +After you have wrote your tests, you can run them by using the following command: + +```bash +yarn test:e2e:ci +``` + +If you want to use headed mode, you can use the following command: + +```bash +yarn test:e2e:headed +``` + +You will see the test results in your terminal, if you want an indepth report, you can use the following command: + +```bash +yarn playwright show-report tests/playwright-report +``` + +## Serving the viewer manually for development + +By default, when you run the tests, it will call the `yarn start` command to serve the viewer first, then run the tests, if you would like to serve the viewer manually, you can use the same command. The viewer will be available at `http://localhost:3000`. This could speed up your development process since playwright will skip this step and use the existing server on port 3000. + +## Accessing services, managers, configs and cornerstone in your tests + +If you would like to access the cornerstone3D, services, or command managers in your tests, you can use the `page.evaluate` function to access them. For example, if you would like to access the `services` so you can show a UI notifcation using the uiNotifcationService, you can use the following code snippet: + +```ts + await page.evaluate(({ services }: AppTypes.Test) => { + const { uiNotificationService } = services; + uiNotificationService.show({ + title: 'Test', + message: 'This is a test', + type: 'info', + }); + }, await page.evaluateHandle('window')); + ``` + +## Playwright VSCode Extension and Recording Tests + +If you are using VSCode, you can use the Playwright extension to help you write your tests. The extension provides a test runner and many great features such as picking a locator using your mouse, recording a new test, and more. You can install the extension by searching for `Playwright` in the extensions tab in VSCode or by visiting the [Playwright extension page](https://marketplace.visualstudio.com/items?itemName=ms-playwright.playwright). + +
+ +
+ + +
+ +
diff --git a/platform/docs/docs/development/types.md b/platform/docs/docs/development/types.md new file mode 100644 index 0000000000..a6af5df12a --- /dev/null +++ b/platform/docs/docs/development/types.md @@ -0,0 +1,85 @@ +--- +sidebar_position: 10 +sidebar_label: Global Types +--- + +# Extending App Types and Services in Your Application + +This documentation provides an overview and examples on how to use and extend `withAppTypes`, integrate custom properties, and add services in the global namespace of the application. This helps in enhancing the application's modularity and extensibility. + +## Overview of `withAppTypes` + +The `withAppTypes` function is a TypeScript utility that extends the base properties of components or modules with the application's core service and manager types. It allows for a more flexible and type-safe way to pass around core functionality and custom properties. + +### Using `withAppTypes` + +`withAppTypes` can be enhanced using generics to include custom properties. This is particularly useful for passing additional data or configurations specific to your component or service. + +### Extending with Custom Properties + +You can extend `withAppTypes` to include custom properties by defining an interface for the props you need. For example: + +```typescript +interface ColorbarProps { + viewportId: string; + displaySets: Array; + colorbarProperties: ColorbarProperties; +} + +export function Colorbar({ + viewportId, + displaySets, + commandsManager, // injected type + servicesManager, // injected type + colorbarProperties, +}: withAppTypes): ReactElement { + // Component logic here +} +``` + +In this example, `ColorbarProps` is a custom interface that extends the application types through `withAppTypes`. + +## Typing the custom extensions's new services + +Extensions can define additional services that integrate seamlessly into the application's global service architecture, and will be available on the ServicesManager for use across the application. + +### Adding the extension's services Types + +Declare your service in the global namespace and use it across your application as demonstrated below: + +`extensions/my-extension/src/types/whatever.ts` + +```typescript +declare global { + namespace AppTypes { + // only add if you need direct access to the service ex. AppTypes.MicroscopyService + export type MicroscopyService = MicroscopyServiceType; + // add to the global Services interface, and to withAppTypes + export interface Services { + microscopyService?: MicroscopyServiceType; + } + } +} +``` + +Doing the above adds the `microscopyService` to the global Services interface, which ServicesManager uses by default `public services: AppTypes.Services = {};` to type services, and is also used by withAppTypes to inject services into components. +You will also get access to the seperate services via `AppTypes.YourServiceName` in your application. + + +```typescript +export function CustomComponent({ + servicesManager, +}: withAppTypes): ReactElement { + const { microscopyService } = servicesManager.services; + microscopyService.someMethod(); // auto completation available + +} +``` + +```typescript +export function CustomComponent2( + microscopyService: AppTypes.MicroscopyService, +): ReactElement { + microscopyService.someMethod(); // auto completation available +} +``` diff --git a/platform/docs/docs/faq/_category_.json b/platform/docs/docs/faq/_category_.json new file mode 100644 index 0000000000..d83af03281 --- /dev/null +++ b/platform/docs/docs/faq/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "FAQ", + "position": 13 +} diff --git a/platform/docs/docs/faq/faq-measure-1.png b/platform/docs/docs/faq/faq-measure-1.png new file mode 100644 index 0000000000..86d92ddd93 Binary files /dev/null and b/platform/docs/docs/faq/faq-measure-1.png differ diff --git a/platform/docs/docs/faq/faq-measure-2.png b/platform/docs/docs/faq/faq-measure-2.png new file mode 100644 index 0000000000..3feef696a6 Binary files /dev/null and b/platform/docs/docs/faq/faq-measure-2.png differ diff --git a/platform/docs/docs/faq/faq-measure-4.png b/platform/docs/docs/faq/faq-measure-4.png new file mode 100644 index 0000000000..4198eda5ac Binary files /dev/null and b/platform/docs/docs/faq/faq-measure-4.png differ diff --git a/platform/docs/docs/faq/faq-measure-5.png b/platform/docs/docs/faq/faq-measure-5.png new file mode 100644 index 0000000000..1dcdc42534 Binary files /dev/null and b/platform/docs/docs/faq/faq-measure-5.png differ diff --git a/platform/docs/docs/faq/faq-measure3.png b/platform/docs/docs/faq/faq-measure3.png new file mode 100644 index 0000000000..3231771c0c Binary files /dev/null and b/platform/docs/docs/faq/faq-measure3.png differ diff --git a/platform/docs/docs/faq/general.md b/platform/docs/docs/faq/general.md new file mode 100644 index 0000000000..e2975a49bd --- /dev/null +++ b/platform/docs/docs/faq/general.md @@ -0,0 +1,82 @@ +--- +id: general +--- + + + +# General FAQ + + +## How do I report a bug? + +Navigate to our [GitHub Repository][new-issue], and submit a new bug report. +Follow the steps outlined in the [Bug Report Template][bug-report-template]. + +## How can I request a new feature? + +At the moment we are in the process of defining our roadmap and will do our best +to communicate this to the community. If your requested feature is on the +roadmap, then it will most likely be built at some point. If it is not, you are +welcome to build it yourself and [contribute it](../development/contributing.md). +If you have resources and would like to fund the development of a feature, +please [contact us](https://ohif.org/get-support). + + +## Who should I contact about Academic Collaborations? + +[Gordon J. Harris](https://www.dfhcc.harvard.edu/insider/member-detail/member/gordon-j-harris-phd/) +at Massachusetts General Hospital is the primary contact for any academic +collaborators. We are always happy to hear about new groups interested in using +the OHIF framework, and may be able to provide development support if the +proposed collaboration has an impact on cancer research. + +## Does OHIF offer support? + +yes, you can contact us for more information [here](https://ohif.org/get-support) + + +## Does The OHIF Viewer have [510(k) Clearance][501k-clearance] from the U.S. F.D.A or [CE Marking][ce-marking] from the European Commission? + +**NO.** The OHIF Viewer is **NOT** F.D.A. cleared or CE Marked. It is the users' +responsibility to ensure compliance with applicable rules and regulations. The +[License](https://github.com/OHIF/Viewers/blob/master/LICENSE) for the OHIF +Platform does not prevent your company or group from seeking F.D.A. clearance +for a product built using the platform. + +If you have gone this route (or are going there), please let us know because we +would be interested to hear about your experience. + +## Is there a DICOM Conformance Statement for the OHIF Viewer? + +Yes, check it here [DICOM Conformance Statement](https://docs.google.com/document/d/1hbDlUApX4svX33gAUGxGfD7fXXZNaBsX0hSePbc-hNA/edit?usp=sharing) + +## Is The OHIF Viewer [HIPAA][hipaa-def] Compliant? + +**NO.** The OHIF Viewer **DOES NOT** fulfill all of the criteria to become HIPAA +Compliant. It is the users' responsibility to ensure compliance with applicable +rules and regulations. + +## Could you provide me with a particular study from the OHIF Viewer Demo? + +You can check out the studies that we have put in this [Dropbox link](https://www.dropbox.com/scl/fo/66xidsx13pn0zf3b9cbfq/ADaCgn7aT29WMlnTdT_WRXM?rlkey=rratvx6g4kfxnswjdbupewjye&dl=0) + + + + + + +[general]: ../faq.md#general +[technical]: ../faq.md#technical +[report-bug]: ../faq.md#how-do-i-report-a-bug +[new-feature]: ../faq.md#how-can-i-request-a-new-feature +[commercial-support]: ../faq.md#does-ohif-offer-commercial-support +[academic]: ../faq.md#who-should-i-contact-about-academic-collaborations +[fda-clearance]: ../faq.md#does-the-ohif-viewer-have-510k-clearance-from-the-us-fda-or-ce-marking-from-the-european-commission +[hipaa]: ../faq.md#is-the-ohif-viewer-hipaa-compliant +[501k-clearance]: https://www.fda.gov/MedicalDevices/DeviceRegulationandGuidance/HowtoMarketYourDevice/PremarketSubmissions/PremarketNotification510k/ +[ce-marking]: https://ec.europa.eu/growth/single-market/ce-marking_en +[hipaa-def]: https://en.wikipedia.org/wiki/Health_Insurance_Portability_and_Accountability_Act +[new-issue]: https://github.com/OHIF/Viewers/issues/new/choose +[bug-report-template]: https://github.com/OHIF/Viewers/issues/new?assignees=&labels=Bug+Report+%3Abug%3A&template=---bug-report.md&title= diff --git a/platform/docs/docs/faq/index.md b/platform/docs/docs/faq/index.md new file mode 100644 index 0000000000..e5e50578c4 --- /dev/null +++ b/platform/docs/docs/faq/index.md @@ -0,0 +1,92 @@ +--- +id: index +--- + + +- [General FAQ](../faq.md#general-faq) + - [How do I report a bug?](../faq.md#how-do-i-report-a-bug) + - [How can I request a new feature?](../faq.md#how-can-i-request-a-new-feature) + - [Who should I contact about Academic Collaborations?](../faq.md#who-should-i-contact-about-academic-collaborations) + - [Does OHIF offer support?](../faq.md#does-ohif-offer-support) + - [Does The OHIF Viewer have 510(k) Clearance from the U.S. F.D.A or CE Marking from the European Commission?](../faq.md#does-the-ohif-viewer-have-510k-clearance-from-the-us-fda-or-ce-marking-from-the-european-commission) + - [Is there a DICOM Conformance Statement for the OHIF Viewer?](../faq.md#is-there-a-dicom-conformance-statement-for-the-ohif-viewer) + - [Is The OHIF Viewer HIPAA Compliant?](../faq.md#is-the-ohif-viewer-hipaa-compliant) + - [Could you provide me with a particular study from the OHIF Viewer Demo?](../faq.md#could-you-provide-me-with-a-particular-study-from-the-ohif-viewer-demo) + + +# General FAQ + + +## How do I report a bug? + +Navigate to our [GitHub Repository][new-issue], and submit a new bug report. +Follow the steps outlined in the [Bug Report Template][bug-report-template]. + +## How can I request a new feature? + +At the moment we are in the process of defining our roadmap and will do our best +to communicate this to the community. If your requested feature is on the +roadmap, then it will most likely be built at some point. If it is not, you are +welcome to build it yourself and [contribute it](../development/contributing.md). +If you have resources and would like to fund the development of a feature, +please [contact us](https://ohif.org/get-support). + + +## Who should I contact about Academic Collaborations? + +[Gordon J. Harris](https://www.dfhcc.harvard.edu/insider/member-detail/member/gordon-j-harris-phd/) +at Massachusetts General Hospital is the primary contact for any academic +collaborators. We are always happy to hear about new groups interested in using +the OHIF framework, and may be able to provide development support if the +proposed collaboration has an impact on cancer research. + +## Does OHIF offer support? + +yes, you can contact us for more information [here](https://ohif.org/get-support) + + +## Does The OHIF Viewer have [510(k) Clearance][501k-clearance] from the U.S. F.D.A or [CE Marking][ce-marking] from the European Commission? + +**NO.** The OHIF Viewer is **NOT** F.D.A. cleared or CE Marked. It is the users' +responsibility to ensure compliance with applicable rules and regulations. The +[License](https://github.com/OHIF/Viewers/blob/master/LICENSE) for the OHIF +Platform does not prevent your company or group from seeking F.D.A. clearance +for a product built using the platform. + +If you have gone this route (or are going there), please let us know because we +would be interested to hear about your experience. + +## Is there a DICOM Conformance Statement for the OHIF Viewer? + +Yes, check it here [DICOM Conformance Statement](https://docs.google.com/document/d/1hbDlUApX4svX33gAUGxGfD7fXXZNaBsX0hSePbc-hNA/edit?usp=sharing) + +## Is The OHIF Viewer [HIPAA][hipaa-def] Compliant? + +**NO.** The OHIF Viewer **DOES NOT** fulfill all of the criteria to become HIPAA +Compliant. It is the users' responsibility to ensure compliance with applicable +rules and regulations. + +## Could you provide me with a particular study from the OHIF Viewer Demo? + +You can check out the studies that we have put in this [Dropbox link](https://www.dropbox.com/scl/fo/66xidsx13pn0zf3b9cbfq/ADaCgn7aT29WMlnTdT_WRXM?rlkey=rratvx6g4kfxnswjdbupewjye&dl=0) + + + + + + +[general]: ../faq.md#general +[technical]: ../faq.md#technical +[report-bug]: ../faq.md#how-do-i-report-a-bug +[new-feature]: ../faq.md#how-can-i-request-a-new-feature +[commercial-support]: ../faq.md#does-ohif-offer-commercial-support +[academic]: ../faq.md#who-should-i-contact-about-academic-collaborations +[fda-clearance]: ../faq.md#does-the-ohif-viewer-have-510k-clearance-from-the-us-fda-or-ce-marking-from-the-european-commission +[hipaa]: ../faq.md#is-the-ohif-viewer-hipaa-compliant +[501k-clearance]: https://www.fda.gov/MedicalDevices/DeviceRegulationandGuidance/HowtoMarketYourDevice/PremarketSubmissions/PremarketNotification510k/ +[ce-marking]: https://ec.europa.eu/growth/single-market/ce-marking_en +[hipaa-def]: https://en.wikipedia.org/wiki/Health_Insurance_Portability_and_Accountability_Act +[new-issue]: https://github.com/OHIF/Viewers/issues/new/choose +[bug-report-template]: https://github.com/OHIF/Viewers/issues/new?assignees=&labels=Bug+Report+%3Abug%3A&template=---bug-report.md&title= diff --git a/platform/docs/docs/faq/study-sorting.png b/platform/docs/docs/faq/study-sorting.png new file mode 100644 index 0000000000..46d2be1ec4 Binary files /dev/null and b/platform/docs/docs/faq/study-sorting.png differ diff --git a/platform/docs/docs/faq.md b/platform/docs/docs/faq/technical.md similarity index 50% rename from platform/docs/docs/faq.md rename to platform/docs/docs/faq/technical.md index 5064899db7..33a50df51f 100644 --- a/platform/docs/docs/faq.md +++ b/platform/docs/docs/faq/technical.md @@ -1,92 +1,9 @@ ---- -sidebar_position: 8 -sidebar_label: FAQ ---- - - -- [General FAQ](#general-faq) - - [How do I report a bug?](#how-do-i-report-a-bug) - - [How can I request a new feature?](#how-can-i-request-a-new-feature) - - [Who should I contact about Academic Collaborations?](#who-should-i-contact-about-academic-collaborations) - - [Does OHIF offer support?](#does-ohif-offer-support) - - [Does The OHIF Viewer have 510(k) Clearance from the U.S. F.D.A or CE Marking from the European Commission?](#does-the-ohif-viewer-have-510k-clearance-from-the-us-fda-or-ce-marking-from-the-european-commission) - - [Is there a DICOM Conformance Statement for the OHIF Viewer?](#is-there-a-dicom-conformance-statement-for-the-ohif-viewer) - - [Is The OHIF Viewer HIPAA Compliant?](#is-the-ohif-viewer-hipaa-compliant) - - [Could you provide me with a particular study from the OHIF Viewer Demo?](#could-you-provide-me-with-a-particular-study-from-the-ohif-viewer-demo) -- [Technical FAQ](#technical-faq) - - [Why do I keep seeing a Cross Origin Isolation warning](#why-do-i-keep-seeing-a-cross-origin-isolation-warning) - - [What if my setup does not support the Shared Array Buffers API?](#what-if-my-setup-does-not-support-the-shared-array-buffers-api) - - [Viewer opens but does not show any thumbnails](#viewer-opens-but-does-not-show-any-thumbnails) - - [What are the list of required metadata for the OHIF Viewer to work?](#what-are-the-list-of-required-metadata-for-the-ohif-viewer-to-work) - - [Mandatory](#mandatory) - - [Optional](#optional) - - [How do I handle large volumes for MPR and Volume Rendering](#how-do-i-handle-large-volumes-for-mpr-and-volume-rendering) - - [`useNorm16Texture`](#usenorm16texture) - - [`preferSizeOverAccuracy`](#prefersizeoveraccuracy) - - -# General FAQ - - -## How do I report a bug? - -Navigate to our [GitHub Repository][new-issue], and submit a new bug report. -Follow the steps outlined in the [Bug Report Template][bug-report-template]. - -## How can I request a new feature? - -At the moment we are in the process of defining our roadmap and will do our best -to communicate this to the community. If your requested feature is on the -roadmap, then it will most likely be built at some point. If it is not, you are -welcome to build it yourself and [contribute it](development/contributing.md). -If you have resources and would like to fund the development of a feature, -please [contact us](https://ohif.org/get-support). - - -## Who should I contact about Academic Collaborations? - -[Gordon J. Harris](https://www.dfhcc.harvard.edu/insider/member-detail/member/gordon-j-harris-phd/) -at Massachusetts General Hospital is the primary contact for any academic -collaborators. We are always happy to hear about new groups interested in using -the OHIF framework, and may be able to provide development support if the -proposed collaboration has an impact on cancer research. - -## Does OHIF offer support? - -yes, you can contact us for more information [here](https://ohif.org/get-support) - - -## Does The OHIF Viewer have [510(k) Clearance][501k-clearance] from the U.S. F.D.A or [CE Marking][ce-marking] from the European Commission? - -**NO.** The OHIF Viewer is **NOT** F.D.A. cleared or CE Marked. It is the users' -responsibility to ensure compliance with applicable rules and regulations. The -[License](https://github.com/OHIF/Viewers/blob/master/LICENSE) for the OHIF -Platform does not prevent your company or group from seeking F.D.A. clearance -for a product built using the platform. - -If you have gone this route (or are going there), please let us know because we -would be interested to hear about your experience. - -## Is there a DICOM Conformance Statement for the OHIF Viewer? - -Yes, check it here [DICOM Conformance Statement](https://docs.google.com/document/d/1hbDlUApX4svX33gAUGxGfD7fXXZNaBsX0hSePbc-hNA/edit?usp=sharing) - -## Is The OHIF Viewer [HIPAA][hipaa-def] Compliant? - -**NO.** The OHIF Viewer **DOES NOT** fulfill all of the criteria to become HIPAA -Compliant. It is the users' responsibility to ensure compliance with applicable -rules and regulations. - -## Could you provide me with a particular study from the OHIF Viewer Demo? - -You can check out the studies that we have put in this [Dropbox link](https://www.dropbox.com/scl/fo/66xidsx13pn0zf3b9cbfq/ADaCgn7aT29WMlnTdT_WRXM?rlkey=rratvx6g4kfxnswjdbupewjye&dl=0) - # Technical FAQ ## Why do I keep seeing a Cross Origin Isolation warning -If you encounter a warning while running OHIF indicating that your application is not cross-origin isolated, it implies that volume rendering, such as MPR, will not function properly since they depend on Shared Array Buffers. To resolve this issue, we recommend referring to our comprehensive guide on Cross Origin Isolation available at [our dedicated cors page](./deployment/cors.md). +If you encounter a warning while running OHIF indicating that your application is not cross-origin isolated, it implies that volume rendering, such as MPR, will not function properly since they depend on Shared Array Buffers. To resolve this issue, we recommend referring to our comprehensive guide on Cross Origin Isolation available at [our dedicated cors page](../deployment/cors.md). ## What if my setup does not support the Shared Array Buffers API? You can simply disable that by adding the `useSharedArrayBuffer: 'FALSE'` (notice the string FALSE), and the volumes will only use a regular @@ -101,7 +18,7 @@ One For instance for the following filtering in the worklist tab we send this request -![](assets/img/filtering-worklist.png) +![](../assets/img/filtering-worklist.png) `https://d33do7qe4w26qo.cloudfront.net/dicomweb/studies?PatientName=*Head*&limit=101&offset=0&fuzzymatching=false&includefield=00081030%2C00080060` @@ -223,25 +140,25 @@ WebGL officially supports only 8-bit and 32-bit data types. For most images, 8 b Through [EXT_texture_norm16](https://registry.khronos.org/webgl/extensions/EXT_texture_norm16/) , WebGL can support 16 bit data type which is ideal for most images. You can look into the [webgl report](https://webglreport.com/?v=2) to check if you have that extension enabled. -![](assets/img/webgl-report-norm16.png) +![](../assets/img/webgl-report-norm16.png) -This is a flag that you can set in your [configuration file](./configuration/configurationFiles.md) to force usage of 16 bit data type for the volume rendering and MPR. This will reduce the memory usage by half. +This is a flag that you can set in your [configuration file](../configuration/configurationFiles.md) to force usage of 16 bit data type for the volume rendering and MPR. This will reduce the memory usage by half. For instance for a large pt/ct study -![](assets/img/large-pt-ct.png) +![](../assets/img/large-pt-ct.jpeg) Before (without the flag) the app shows 399 MB of memory usage -![](assets/img/memory-profiling-regular.png) +![](../assets/img/memory-profiling-regular.png) After (with flag, running locally) the app shows 249 MB of memory usage -![](assets/img/webgl-int16.png) +![](../assets/img/webgl-int16.png) :::note Using the 16 bit texture (if supported) will not have any effect in the rendering what so ever, and pixelData @@ -264,7 +181,7 @@ to be still some issues with it. You can read and track bugs below. ### `preferSizeOverAccuracy` -This is another flag that you can set in your [configuration file](./configuration/configurationFiles.md) to force the usage of the `half_float` data type for volume rendering and MPR. The main reason to choose this option over `useNorm16Texture` is its broader support across hardware and browsers. However, it is less accurate than the 16-bit data type and may lead to some rendering artifacts. +This is another flag that you can set in your [configuration file](../configuration/configurationFiles.md) to force the usage of the `half_float` data type for volume rendering and MPR. The main reason to choose this option over `useNorm16Texture` is its broader support across hardware and browsers. However, it is less accurate than the 16-bit data type and may lead to some rendering artifacts. ```js Integers between 0 and 2048 can be exactly represented (and also between −2048 and 0) @@ -279,24 +196,154 @@ As you see in the ranges above 2048 there will be inaccuracies in the rendering. Memory snapshot after enabling `preferSizeOverAccuracy` for the same study as above -![](assets/img/preferSizeOverAccuracy.png) +![](../assets/img/preferSizeOverAccuracy.png) + + +## How to dynamically load a measurement + +You can dynamically load a measurement by using a combination of `MeasurementService` and `CornerstoneTools` Annotation API. Here, we will demonstrate this with an example of loading a `Rectangle` measurement. + +![alt text](faq-measure-1.png) + +So if we look at the terminal and get the measurement service we can see there is one measurement + +![alt text](faq-measure-2.png) + +However, this is the `mapped` cornerstone measurement inside OHIF, and it has additional information such as `geReport` and `source`, which are internal details of OHIF Viewers that you don't need to worry about. + +we can call the `cornerstoneTools` api to grab the raw annotation data with the `uid` + +`cornerstoneTools.annotation.state.getAnnotation("ea45a45c-0731-47d4-9438-d2a53ffea4ff")` + +![alt text](faq-measure3.png) + + + + +:::note +Note: There is a `pointsInShape` attribute inside the data that stores the points within the annotation for some tools like `Rectangle` and `EllipticalRoi`. However, you can remove that attribute as well. +::: + +For the sake of this example, I have extracted those keys and uploaded them to our server for fetching. +` +https://ohif-assets.s3.us-east-2.amazonaws.com/ohif-faq/rectangle-roi.json +` +Now, let's discuss how to load this measurement dynamically and programmatically. +There are numerous places in OHIF where you can add annotations, but we always recommend having your own extensions and modes to maintain full control over your custom API. - -[general]: #general -[technical]: #technical -[report-bug]: #how-do-i-report-a-bug -[new-feature]: #how-can-i-request-a-new-feature -[commercial-support]: #does-ohif-offer-commercial-support -[academic]: #who-should-i-contact-about-academic-collaborations -[fda-clearance]: #does-the-ohif-viewer-have-510k-clearance-from-the-us-fda-or-ce-marking-from-the-european-commission -[hipaa]: #is-the-ohif-viewer-hipaa-compliant -[501k-clearance]: https://www.fda.gov/MedicalDevices/DeviceRegulationandGuidance/HowtoMarketYourDevice/PremarketSubmissions/PremarketNotification510k/ -[ce-marking]: https://ec.europa.eu/growth/single-market/ce-marking_en -[hipaa-def]: https://en.wikipedia.org/wiki/Health_Insurance_Portability_and_Accountability_Act -[new-issue]: https://github.com/OHIF/Viewers/issues/new/choose -[bug-report-template]: https://github.com/OHIF/Viewers/issues/new?assignees=&labels=Bug+Report+%3Abug%3A&template=---bug-report.md&title= +For this example, I will add the logic in the `longitudinal` mode. However, as mentioned, you can create your own extension and mode, and either use `onModeEnter` or other lifecycle hooks to add annotations. Learn more about lifecycle hooks [here](../platform/extensions/lifecycle.md). + + +Of course, you need to load the appropriate measurement for each study. However, for simplicity's sake, I will hardcode the URL in this example. + +```js +import * as cs3dTools from '@cornerstonejs/tools'; + +onModeEnter: function ({ servicesManager, extensionManager, commandsManager }: withAppTypes) { + // rest of logic + + const annotationResponse = await fetch( + 'https://ohif-assets.s3.us-east-2.amazonaws.com/ohif-faq/rectangle-roi.json' + ); + + const annotationData = await annotationResponse.json(); + + cs3dTools.annotation.state.addAnnotation(annotationData); +}, +``` + +As you can see, we use the CornerstoneTools API to add the annotation. Since OHIF has mappers set up for CornerstoneTools (`extensions/cornerstone/src/utils/measurementServiceMappings/measurementServiceMappingsFactory.ts`), it will automatically map the annotation to the OHIF measurement service. + +If you refresh the viewer, you'll see the measurement loaded on the image. + +![alt text](faq-measure-4.png) + +But if you notice it does not appear on the right panel, the reason is that the right panel is the tracking measurement panel. You can switch to a non-tracking measurement by changing + +`rightPanels: [dicomSeg.panel, tracked.measurements],` + +to + +`rightPanels: [dicomSeg.panel, '@ohif/extension-default.panelModule.measure'],` + +which then it will look like + +![alt text](faq-measure-5.png) + + + +## How do I sort the series in the study panel by a specific value + +You need to enable the experimental StudyBrowserSort component by setting the `experimentalStudyBrowserSort` to true in your config file. This will add a dropdown in the study panel to sort the series by a specific value. This component is experimental +since we are re-deigning the study panel and it might change in the future, but the functionality will remain the same. + +```js +{ + experimentalStudyBrowserSort: true, +} +``` +The component will appear in the study panel and will allow you to sort the series by a specific value. It comes with 3 default sorting functions, Series Number, Series Image Count, and Series Date. + +You can sort the series in the study panel by a specific value by adding a custom sorting function in the customizationModule, you can use the existing customizationModule in `extensions/default/src/getCustomizationModule.tsx` or create your own in your extension. + +The value to be used for the entry is `studyBrowser.sortFunctions` and should be under the `default` key. + +### Example + +```js +export default function getCustomizationModule({ servicesManager, extensionManager }) { + return [ + { + name: 'default', + value: [ + + { + id: 'studyBrowser.sortFunctions', + values: [ + { + label: 'Series Number', + sortFunction: (a, b) => { + return a?.SeriesNumber - b?.SeriesNumber; + }, + }, + // Add more sort functions as needed + ], + }, + ], + }, + ]; +} +``` + +### Explanation +This function will be retrieved by the StudyBrowserSort component and will be used to sort all displaySets, it will reflect in all parts of the app since it works at the displaySetService level, which means the thumbnails in the study panel will also be sorted by the desired value. +You can define multiple functions and pick which sort to use via the dropdown in the StudyBrowserSort component that appears in the study panel. + + +## How can i change the sorting of the thumbnail / study panel / study browser +We are currently redesigning the study panel and the study browser. During this process, you can enable our undesigned component via the `experimentalStudyBrowserSort` flag. This will look like: + +![alt text](study-sorting.png) + +You can also add your own sorting functions by utilizing the `customizationService` and adding the `studyBrowser.sortFunctions` key, as shown below: + +``` +customizationService.addModeCustomizations([ + { + id: 'studyBrowser.sortFunctions', + values: [{ + label: 'Series Images', + sortFunction: (a, b) => { + return a?.numImageFrames - b?.numImageFrames; + }, + }], + }, +]); +``` + +:::note +Notice the arrays and objects, the values are arrays +::: diff --git a/platform/docs/docs/migration-guide/from-3p7-to-3p8.md b/platform/docs/docs/migration-guide/from-3p7-to-3p8.md index 48ea73890a..b07d8ffe0e 100644 --- a/platform/docs/docs/migration-guide/from-3p7-to-3p8.md +++ b/platform/docs/docs/migration-guide/from-3p7-to-3p8.md @@ -1,5 +1,5 @@ --- -sidebar_position: 1 +sidebar_position: 2 sidebar_label: 3.7 -> 3.8 --- @@ -132,6 +132,81 @@ Additional Resources - For more information on the new toolbar module and its usage, refer to the [Toolbar documentation](../platform/extensions/modules/toolbar.md). - Consult the updated button definitions in `modes/longitudinal/src/toolbarButtons.ts` for examples of the new object-based button definition format and the usage of evaluators. +### Tool listeners + +Some tools can be configured to listen to events to trigger, for example + +```ts +createButton({ + id: 'ReferenceLines', + icon: 'tool-referenceLines', + label: 'Reference Lines', + tooltip: 'Show Reference Lines', + commands: 'toggleEnabledDisabledToolbar', + listeners: { + [ViewportGridService.EVENTS.ACTIVE_VIEWPORT_ID_CHANGED]: + ReferenceLinesListeners, + [ViewportGridService.EVENTS.VIEWPORTS_READY]: + ReferenceLinesListeners, + }, + evaluate: 'evaluate.cornerstoneTool.toggle', + }), +``` + +If you have a custom viewport component, and you are overriding the ```onElementEnabled``` handler, than ensure to call ```viewportGridService.setViewportIsReady(viewportId, true)``` in your own handler so that eventually the ```VIEWPORTS_READY``` event fires as expected, if you are not modifying the handler, then an existing handler that is automatically passed down via the props will call that for you, it is passed down from ```ViewportGrid.tsx``` + +```ts + 1 ? viewportLabel : ''} + viewportId={viewportId} + dataSource={dataSource} + viewportOptions={viewportOptions} + displaySetOptions={displaySetOptions} + needsRerendering={displaySetsNeedsRerendering} + isHangingProtocolLayout={isHangingProtocolLayout} + onElementEnabled={() => { + viewportGridService.setViewportIsReady(viewportId, true); + }} +/> + +``` + +## Toolbar Service + +toolbarService.init is not a function. + +**Action Needed** +remove the call to toolbarService.init() from your codebase. + + + ## leftPanelDefaultClosed and rightPanelDefaultClosed Now they are renamed to `leftPanelClosed` and `rightPanelClosed` respectively. + + +## StudyInstanceUID in the URL param + +Previously there were two params that you could choose: seriesInstanceUID and seriesInstanceUIDs, they have been replaced with seriesInstanceUIDs so even if you would like to filter one series use ``seriesInstanceUIDs` + + +## UI + +### Header +Header in @ohif/ui now needs servicesManager and appConfig as input. + + +### Panels +Left and right panel lists are no longer injected into the LayoutTemplate, and have been moved to a PanelService where you have to fetch them from. + +If you're using the main layout, you're fine. However, if you have a custom layout, you'll need to update it. To get the panels, see the + +`extensions/default/src/ViewerLayout/index.tsx` + + + + +## Refactoring + +- TimingEnum (and I guess all enums exported from OHIF core have now moved from Types to Enums export). diff --git a/platform/docs/docs/migration-guide/from-3p8-to-3p9-beta.md b/platform/docs/docs/migration-guide/from-3p8-to-3p9-beta.md new file mode 100644 index 0000000000..af8fca41fc --- /dev/null +++ b/platform/docs/docs/migration-guide/from-3p8-to-3p9-beta.md @@ -0,0 +1,269 @@ +--- +sidebar_position: 1 +sidebar_label: 3.8 -> 3.9-beta +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + +# Migration Guide + + +## React 18 Migration Guide +As we upgrade to React 18, we're making some exciting changes to improve performance and developer experience. This guide will help you navigate the key updates and ensure your custom extensions and modes are compatible with the new version. +What's Changing? + + + +```md +- React 17 +- Using `defaultProps` +- `babel-inline-svg` for SVG imports +``` + + + + +```md +- React 18 +- Default parameters for props +- `svgr` for SVG imports +``` + + + + + +### Run newer yarn version +You must be running a newer yarn version for react 18. +It isn't clear the exact yarn required. + +### Update React version: +In your custom extensions and modes, change the version of react and react-dom to ^18.3.1. + +### Replace defaultProps with default parameters: + + + + +```jsx +const MyComponent = ({ prop1, prop2 }) => { + return
{prop1} {prop2}
+} + +MyComponent.defaultProps = { + prop1: 'default value', + prop2: 'default value' +} +``` + +
+ + +```jsx +const MyComponent = ({ prop1 = 'default value', prop2 = 'default value' }) => { + return
{prop1} {prop2}
+} +``` +
+
+ +### Update SVG imports: + + + + +```javascript +import arrowDown from './../../assets/icons/arrow-down.svg'; +``` + + + + +```javascript +import { ReactComponent as arrowDown } from './../../assets/icons/arrow-down.svg'; +``` + + + + + +
+ +--- + +
+ +## Renaming + +The panel in the default extension is renamed from `measure` to `measurements` to be more consistent with the rest of the extensions. + +**Action Needed** + +Update any references to the `measure` panel to `measurements` in your code. + +Find and replace + + + + @ohif/extension-default.panelModule.measure + + + @ohif/extension-default.panelModule.measurements + + + + +
+ +--- + +
+ +## RTStructure Set has transitioned from VTK actors to SVG. + +We have transitioned from VTK-based rendering to SVG-based rendering for RTStructure Set contours. This change should not require any modifications to your codebase. We anticipate improved stability and speed in our contour rendering. + +As a result of this update, viewports rendering RTStructure Sets will no longer convert to volume viewports. Instead, they will remain as stack viewports. + + +Read more in Pull Requests: +- https://github.com/OHIF/Viewers/pull/4074 +- https://github.com/OHIF/Viewers/pull/4157 + +
+ +--- + +
+ +## Crosshairs + +They now have new colors in their associated viewports in the MPR view. However, you can turn this feature off. + +To disable it, remove the configuration from the `initToolGroups` in your mode. + +``` +{ + configuration: { + viewportIndicators: true, + viewportIndicatorsConfig: { + circleRadius: 5, + xOffset: 0.95, + yOffset: 0.05, + }, + } +} +``` + +
+ +--- + +
+ +## External Libraries +Some libraries are loaded via dynamic import. You can provide a global function +`browserImport` the allows loading of dynamic imports without affecting the +webpack build. This import looks like: + +``` + +``` + +and belongs in the root html file for your application. +You then need to remove `dependencies` on the external import, and add a reference +to the external import in your `pluginConfig.json` file. + +### Example plugin config for `dicom-microscopy-viewer` +The example below imports the `dicom-microscopy-viewer` for use as an external +dependency. The example is part of the default `pluginConfig.json` file. + +``` + "public": [ + { + "directory": "./platform/public" + }, + { + "packageName": "dicom-microscopy-viewer", + "importPath": "/dicom-microscopy-viewer/dicomMicroscopyViewer.min.js", + "globalName": "dicomMicroscopyViewer", + "directory": "./node_modules/dicom-microscopy-viewer/dist/dynamic-import" + } + ] +``` + +This defines two directory modules, whose contents are copied unchanged to the +output build directory. It then defines the `dicom-microscopy-viewer` using +the `packageName` element as being a module which is imported dynamically. +Then, the import path passed into the browserImportFunction above is +specified, and then how to access the import itself, via the `window.dicomMicroscopyViewer` +global name reference. + +### Referencing External Imports +The appConfig either defines or has a default peerImport function which can be +used to load references to the modules defined in the pluginConfig file. See +the example in `init.tsx` for the cornerstone extension for how this is passed +into CS3D for loading the whole slide imaging library. + +### Usage of Dynamic Imports + + +## BulkDataURI Configuration + +We've updated the configuration for BulkDataURI to provide more flexibility and control. This guide will help you migrate from the old configuration to the new one. + +### What's Changing? + + + + +```javascript +useBulkDataURI: false, +``` + + + + +```javascript +bulkDataURI: { + enabled: true, + // Additional configuration options +}, +``` + + + + + +Additional Notes: +- The new configuration allows for more granular control over BulkDataURI behavior. +- You can now add custom URL prefixing logic using the startsWith and prefixWith properties. +- This change enables easier correction of retrieval URLs, especially in scenarios where URLs pass through multiple systems. + + +
+ +--- + +
+ +## Polyfill.io + +We have removed the Polyfill.io script from the Viewer. If you require polyfills, you can add them to your project manually. This change primarily affects Internet Explorer, which Microsoft has already [ended support for](https://learn.microsoft.com/en-us/lifecycle/faq/internet-explorer-microsoft-edge#is-internet-explorer-11-the-last-version-of-internet-explorer-). + + +
+ +--- + +
+ +## Dynamic Modules + +TBD diff --git a/platform/docs/docs/migration-guide/from-v2.md b/platform/docs/docs/migration-guide/from-v2.md index 81f70806f5..285ba3551e 100644 --- a/platform/docs/docs/migration-guide/from-v2.md +++ b/platform/docs/docs/migration-guide/from-v2.md @@ -1,5 +1,5 @@ --- -sidebar_position: 2 +sidebar_position: 3 sidebar_label: 2.x -> 3.5 --- @@ -102,7 +102,7 @@ There are various configurations available to customize the viewer. Each configu OHIF v3 has a new configuration structure. The main difference is that the `servers` is renamed to `dataSources` and the configuration is now asynchronous. Datasources are more abstract and far more capable than servers. Read more about dataSources [here](../platform/extensions/modules/data-source.md). -- `StudyPrefetcher` is not currently supported in OHIF v3. +- `StudyPrefetcher` is only available in OHIF v3.9 beta and will be available in the next stable 3.9 release. - The `servers` object has been replaced with a `dataSources` array containing objects representing different data sources. - The cornerstoneExtensionConfig property has been removed, you should use `customizationService` instead (you can read more [here](../platform/services/ui/customization-service.md)) - The maxConcurrentMetadataRequests property has been removed in favor of `maxNumRequests` diff --git a/platform/docs/docs/migration-guide/index.md b/platform/docs/docs/migration-guide/index.md new file mode 100644 index 0000000000..85d2af849c --- /dev/null +++ b/platform/docs/docs/migration-guide/index.md @@ -0,0 +1,13 @@ +--- +id: index +--- + + +import DocCardList from '@theme/DocCardList'; +import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; + +# Migration Guides + +Based on the version you are migrating from, you can find the migration guide for the latest version of the platform. + + diff --git a/platform/docs/docs/platform/browser-support.md b/platform/docs/docs/platform/browser-support.md index 20ca7e8c27..fa31439c38 100644 --- a/platform/docs/docs/platform/browser-support.md +++ b/platform/docs/docs/platform/browser-support.md @@ -37,9 +37,7 @@ language feature yet. Our earlier transpilation will rectify _syntax_ discrepancies, but unimplemented features require a "temporary" implementation. That's where polyfills step in. -You can utilize a service like [polyfill.io](https://polyfill.io/v3/) to -auto-detect and apply polyfills as needed, or you can update the PWA build to -include polyfill's in your bundle by incorporating [core-js][core-js] +We previously used polyfill io, but due to a security vulnerability in the library, it's necessary to switch to alternative services. Target Syntax + ['@babel/preset-env', { modules: false }], + '@babel/preset-react', + '@babel/preset-typescript', + ], + ignore: ['**/*.test.jsx', '**/*.test.js', '__snapshots__', '__tests__'], + }, + development: { + presets: [ + // WebPack handles ES6 --> Target Syntax + ['@babel/preset-env', { modules: false }], + '@babel/preset-react', + '@babel/preset-typescript', + ], + plugins: ['react-refresh/babel'], + ignore: ['**/*.test.jsx', '**/*.test.js', '__snapshots__', '__tests__'], + }, + }, +}; diff --git a/platform/ui-next/components.json b/platform/ui-next/components.json new file mode 100644 index 0000000000..e66d5c81ea --- /dev/null +++ b/platform/ui-next/components.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": false, + "tsx": true, + "tailwind": { + "config": "tailwind.config.js", + "css": "src/tailwind.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "src/components", + "utils": "src/lib/utils" + } +} diff --git a/platform/ui-next/package.json b/platform/ui-next/package.json new file mode 100644 index 0000000000..17e8b97d99 --- /dev/null +++ b/platform/ui-next/package.json @@ -0,0 +1,52 @@ +{ + "name": "@ohif/ui-next", + "version": "3.9.0-beta.71", + "description": "Next version of OHIF Viewers UI, more customizable using shadcn/ui", + "main": "dist/ohif-ui-next.umd.js", + "module": "src/index.ts", + "publishConfig": { + "access": "public" + }, + "files": [ + "dist", + "README.md" + ], + "scripts": { + "clean": "rm -rf node_modules/.cache/storybook && shx rm -rf dist", + "clean:deep": "yarn run clean && shx rm -rf node_modules", + "start": "yarn run build --watch", + "dev": "cross-env NODE_ENV=development webpack serve --config .webpack/webpack.playground.js", + "test": "echo \"Error: no test specified\" && exit 1", + "build": "cross-env NODE_ENV=production webpack --config .webpack/webpack.prod.js", + "build:package": "yarn run build" + }, + "exports": { + "./tailwind.config": "./tailwind.config.ts", + "./lib/*": "./src/lib/*.ts", + "./components/*": "./src/components/*.tsx", + ".": "./src/index.ts" + }, + "dependencies": { + "@radix-ui/react-dialog": "^1.0.5", + "@radix-ui/react-icons": "^1.3.0", + "@radix-ui/react-popover": "^1.0.7", + "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-tooltip": "^1.1.2", + "class-variance-authority": "^0.7.0", + "clsx": "*", + "cmdk": "^1.0.0", + "date-fns": "^3.6.0", + "framer-motion": "6.2.4", + "lucide-react": "^0.379.0", + "next-themes": "^0.3.0", + "react": "^18.3.1", + "react-day-picker": "^8.10.1", + "sonner": "^1.4.41", + "tailwind-merge": "^2.3.0", + "tailwindcss": "3.2.4", + "tailwindcss-animate": "^1.0.7" + }, + "keywords": [], + "author": "OHIF", + "license": "MIT" +} diff --git a/platform/ui-next/src/_pages/README.md b/platform/ui-next/src/_pages/README.md new file mode 100644 index 0000000000..78d70551f5 --- /dev/null +++ b/platform/ui-next/src/_pages/README.md @@ -0,0 +1 @@ +This is our playground for designing and developing the next generation of the platform's UI. You probably don't need to be here. diff --git a/platform/ui-next/src/_pages/colors.tsx b/platform/ui-next/src/_pages/colors.tsx new file mode 100644 index 0000000000..4f3fdc62e4 --- /dev/null +++ b/platform/ui-next/src/_pages/colors.tsx @@ -0,0 +1,134 @@ +import React from 'react'; +import { createRoot } from 'react-dom/client'; +import '../tailwind.css'; + +function Colors() { + return ( +
+

Primary color

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +

New colors

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +

Core colors

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +

Borders

+
+
+
+
+
+
+
+
+
+
+
+
+ ); +} + +const container = document.getElementById('root'); +const root = createRoot(container); +root.render(React.createElement(Colors)); diff --git a/platform/ui-next/src/_pages/index.tsx b/platform/ui-next/src/_pages/index.tsx new file mode 100644 index 0000000000..27b8e74e21 --- /dev/null +++ b/platform/ui-next/src/_pages/index.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import { createRoot } from 'react-dom/client'; + +import '../tailwind.css'; + +const App: React.FC = () => ( +
+); + +const container = document.getElementById('root'); +const root = createRoot(container); +root.render(React.createElement(App)); diff --git a/platform/ui-next/src/_pages/playground.tsx b/platform/ui-next/src/_pages/playground.tsx new file mode 100644 index 0000000000..25d56efbda --- /dev/null +++ b/platform/ui-next/src/_pages/playground.tsx @@ -0,0 +1,185 @@ +import React from 'react'; +import { createRoot } from 'react-dom/client'; +import '../tailwind.css'; + +import { Button } from '../components/Button'; +// import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from '../components/Tooltip'; + +// import type { Metadata } from 'next'; +// import Script from 'next/script'; +// import BackgroundColorSelector from '@/components/backgroundcolor'; +// import { useState, useEffect } from 'react'; +// import { Inter } from 'next/font/google'; +// import { ThemeProvider } from '@/components/themeprovider'; +// import { Button2 } from '@/components/ui/button2'; +// import { Switch } from '@/components/ui/switch'; +// import { Slider } from '@/components/ui/slider'; +// import { ScrollArea } from '@/components/ui/scroll-area'; +// import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; +// import { Separator } from '@/components/ui/separator'; +// import { Toggle } from '@/components/ui/toggle'; +// import { Checkbox } from '@/components/ui/checkbox'; +// import { +// Select, +// SelectContent, +// SelectItem, +// SelectTrigger, +// SelectValue, +// } from '@/components/ui/select'; +// import { Input } from '@/components/ui/input'; +// import { Label } from '@/components/ui/label'; +// import icons from '../../components/icons'; +// import SegRow from '@/components/segrow'; + +export default function Playground() { + return ( +
+ {/* */} + +

Button default

+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +

Button small

+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +

Button large

+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +

Color swatches

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ); +} + +const container = document.getElementById('root'); +const root = createRoot(container); +root.render(React.createElement(Playground)); diff --git a/platform/ui-next/src/_pages/viewer.tsx b/platform/ui-next/src/_pages/viewer.tsx new file mode 100644 index 0000000000..b9bf9d096e --- /dev/null +++ b/platform/ui-next/src/_pages/viewer.tsx @@ -0,0 +1,17 @@ +import React from 'react'; +import { createRoot } from 'react-dom/client'; +import '../tailwind.css'; + +// component imports + +function Viewer() { + return ( +
+
Viewer
+
+ ); +} + +const container = document.getElementById('root'); +const root = createRoot(container); +root.render(React.createElement(Viewer)); diff --git a/platform/ui-next/src/components/Button/Button.tsx b/platform/ui-next/src/components/Button/Button.tsx new file mode 100644 index 0000000000..eff08ac540 --- /dev/null +++ b/platform/ui-next/src/components/Button/Button.tsx @@ -0,0 +1,54 @@ +import * as React from 'react'; +import { Slot } from '@radix-ui/react-slot'; +import { cva, type VariantProps } from 'class-variance-authority'; + +import { cn } from '../../lib/utils'; + +const buttonVariants = cva( + 'inline-flex items-center justify-center whitespace-nowrap rounded text-base font-medium leading-tight transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50', + { + variants: { + variant: { + default: 'bg-primary/60 text-primary-foreground hover:bg-primary/100', + destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90', + outline: + 'border border-input bg-background hover:bg-primary/25 hover:text-accent-foreground', + secondary: 'bg-primary/40 text-secondary-foreground hover:bg-primary/60', + ghost: 'text-primary hover:bg-primary/25', + link: 'text-primary underline-offset-4 hover:underline', + }, + size: { + default: 'h-7 px-2 py-2', + sm: 'h-6 rounded px-2', + lg: 'h-9 rounded px-2', + icon: 'h-6 w-6', + }, + }, + defaultVariants: { + variant: 'default', + size: 'default', + }, + } +); + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean; +} + +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : 'button'; + return ( + + ); + } +); +Button.displayName = 'Button'; + +export { Button, buttonVariants }; diff --git a/platform/ui-next/src/components/Button/index.ts b/platform/ui-next/src/components/Button/index.ts new file mode 100644 index 0000000000..2e2ea29174 --- /dev/null +++ b/platform/ui-next/src/components/Button/index.ts @@ -0,0 +1 @@ +export { Button, buttonVariants } from './Button'; diff --git a/platform/ui-next/src/components/Calendar/Calendar.tsx b/platform/ui-next/src/components/Calendar/Calendar.tsx new file mode 100644 index 0000000000..72ce7501a2 --- /dev/null +++ b/platform/ui-next/src/components/Calendar/Calendar.tsx @@ -0,0 +1,61 @@ +import * as React from 'react'; +import { ChevronLeft, ChevronRight } from 'lucide-react'; +import { DayPicker } from 'react-day-picker'; + +import { cn } from '../../lib/utils'; + +import { buttonVariants } from '../Button'; + +export type CalendarProps = React.ComponentProps; + +function Calendar({ className, classNames, showOutsideDays = true, ...props }: CalendarProps) { + return ( + undefined, + labelYearDropdown: () => undefined, + }} + classNames={{ + months: 'flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0', + month: 'space-y-4', + caption: 'flex justify-between items-center px-2', + + caption_dropdowns: 'flex space-x-2 text-black', + caption_label: 'hidden', + nav: 'space-x-1 flex items-center', + table: 'w-full border-collapse space-y-1', + head_row: 'flex', + head_cell: 'text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]', + row: 'flex w-full mt-2', + cell: 'h-9 w-9 text-center text-sm p-0 relative [&:has([aria-selected].day-range-end)]:rounded-r-md [&:has([aria-selected].day-outside)]:bg-accent/50 [&:has([aria-selected])]:bg-accent first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20', + day: cn( + buttonVariants({ variant: 'ghost' }), + 'h-9 w-9 p-0 font-normal aria-selected:opacity-100' + ), + day_range_end: 'day-range-end', + day_selected: + 'bg-primary/60 text-primary-foreground hover:bg-primary/80 hover:text-primary-foreground focus:bg-primary/80 focus:text-primary-foreground', + day_today: 'bg-accent text-accent-foreground', + day_outside: + 'day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30', + day_disabled: 'text-muted-foreground opacity-50', + day_range_middle: 'aria-selected:bg-accent aria-selected:text-accent-foreground', + day_hidden: 'invisible', + ...classNames, + }} + components={{ + IconLeft: ({ ...props }) => , + IconRight: ({ ...props }) => , + }} + {...props} + /> + ); +} +Calendar.displayName = 'Calendar'; + +export { Calendar }; diff --git a/platform/ui-next/src/components/Calendar/index.tsx b/platform/ui-next/src/components/Calendar/index.tsx new file mode 100644 index 0000000000..110b553c2b --- /dev/null +++ b/platform/ui-next/src/components/Calendar/index.tsx @@ -0,0 +1,3 @@ +import { Calendar } from './Calendar'; + +export default Calendar; diff --git a/platform/ui-next/src/components/Combobox/Combobox.tsx b/platform/ui-next/src/components/Combobox/Combobox.tsx new file mode 100644 index 0000000000..173b58e533 --- /dev/null +++ b/platform/ui-next/src/components/Combobox/Combobox.tsx @@ -0,0 +1,66 @@ +import * as React from 'react'; +import { Check, ChevronsUpDown } from 'lucide-react'; + +import { cn } from '../../lib/utils'; +import { Button } from '../Button/Button'; +import { + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, +} from '../Command/Command'; +import { Popover, PopoverContent, PopoverTrigger } from '../Popover/Popover'; + +export function Combobox({ data = [], placeholder = 'Select item...' }) { + const [open, setOpen] = React.useState(false); + const [value, setValue] = React.useState(''); + + return ( + + + + + + + + No {placeholder.toLowerCase()} found. + + + {data.map(item => ( + { + setValue(currentValue === value ? '' : currentValue); + setOpen(false); + }} + > + + {item.label} + + ))} + + + + + + ); +} diff --git a/platform/ui-next/src/components/Combobox/index.ts b/platform/ui-next/src/components/Combobox/index.ts new file mode 100644 index 0000000000..83249c99dd --- /dev/null +++ b/platform/ui-next/src/components/Combobox/index.ts @@ -0,0 +1,3 @@ +import { Combobox } from './Combobox'; + +export default Combobox; diff --git a/platform/ui-next/src/components/Command/Command.tsx b/platform/ui-next/src/components/Command/Command.tsx new file mode 100644 index 0000000000..5e4a14cafa --- /dev/null +++ b/platform/ui-next/src/components/Command/Command.tsx @@ -0,0 +1,150 @@ +import * as React from 'react'; +import { type DialogProps } from '@radix-ui/react-dialog'; +import { MagnifyingGlassIcon } from '@radix-ui/react-icons'; +import { Command as CommandPrimitive } from 'cmdk'; + +import { cn } from '../../lib/utils'; +import { Dialog, DialogContent } from '../Dialog/Dialog'; + +const Command = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +Command.displayName = CommandPrimitive.displayName; + +interface CommandDialogProps extends DialogProps {} + +const CommandDialog = ({ children, ...props }: CommandDialogProps) => { + return ( + + + + {children} + + + + ); +}; + +const CommandInput = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( +
+ + +
+)); + +CommandInput.displayName = CommandPrimitive.Input.displayName; + +const CommandList = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); + +CommandList.displayName = CommandPrimitive.List.displayName; + +const CommandEmpty = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>((props, ref) => ( + +)); + +CommandEmpty.displayName = CommandPrimitive.Empty.displayName; + +const CommandGroup = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); + +CommandGroup.displayName = CommandPrimitive.Group.displayName; + +const CommandSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +CommandSeparator.displayName = CommandPrimitive.Separator.displayName; + +const CommandItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); + +CommandItem.displayName = CommandPrimitive.Item.displayName; + +const CommandShortcut = ({ className, ...props }: React.HTMLAttributes) => { + return ( + + ); +}; +CommandShortcut.displayName = 'CommandShortcut'; + +export { + Command, + CommandDialog, + CommandInput, + CommandList, + CommandEmpty, + CommandGroup, + CommandItem, + CommandShortcut, + CommandSeparator, +}; diff --git a/platform/ui-next/src/components/Command/index.ts b/platform/ui-next/src/components/Command/index.ts new file mode 100644 index 0000000000..2f7ec14d2e --- /dev/null +++ b/platform/ui-next/src/components/Command/index.ts @@ -0,0 +1,3 @@ +import * as CommandComponents from './Command'; + +export default CommandComponents; diff --git a/platform/ui-next/src/components/DateRange/DateRange.tsx b/platform/ui-next/src/components/DateRange/DateRange.tsx new file mode 100644 index 0000000000..5c2fdecf11 --- /dev/null +++ b/platform/ui-next/src/components/DateRange/DateRange.tsx @@ -0,0 +1,153 @@ +import * as React from 'react'; +import { format, parse, isValid } from 'date-fns'; +import { Calendar as CalendarIcon } from 'lucide-react'; +import { cn } from '../../lib/utils'; +import Calendar from '../Calendar'; +import Popover from '../Popover'; + +export type DatePickerWithRangeProps = { + id: string; + /** YYYYMMDD (19921022) */ + startDate: string; + /** YYYYMMDD (19921022) */ + endDate: string; + /** Callback that received { startDate: string(YYYYMMDD), endDate: string(YYYYMMDD)} */ + onChange: (value: { startDate: string; endDate: string }) => void; +}; + +export function DatePickerWithRange({ + className, + id, + startDate, + endDate, + onChange, + ...props +}: React.HTMLAttributes & DatePickerWithRangeProps) { + const [start, setStart] = React.useState( + startDate ? format(parse(startDate, 'yyyyMMdd', new Date()), 'yyyy-MM-dd') : '' + ); + const [end, setEnd] = React.useState( + endDate ? format(parse(endDate, 'yyyyMMdd', new Date()), 'yyyy-MM-dd') : '' + ); + const [openEnd, setOpenEnd] = React.useState(false); + + const handleStartSelect = (selectedDate: Date | undefined) => { + if (selectedDate) { + const formattedDate = format(selectedDate, 'yyyy-MM-dd'); + setStart(formattedDate); + setOpenEnd(true); + onChange({ + startDate: format(selectedDate, 'yyyyMMdd'), + endDate: end.replace(/-/g, ''), + }); + } + }; + + const handleEndSelect = (selectedDate: Date | undefined) => { + if (selectedDate) { + const formattedDate = format(selectedDate, 'yyyy-MM-dd'); + setEnd(formattedDate); + setOpenEnd(false); + onChange({ + startDate: start.replace(/-/g, ''), + endDate: format(selectedDate, 'yyyyMMdd'), + }); + } + }; + + const handleInputChange = (e: React.ChangeEvent, type: 'start' | 'end') => { + const value = e.target.value; + const date = parse(value, 'yyyy-MM-dd', new Date()); + if (type === 'start') { + setStart(value); + if (isValid(date)) { + handleStartSelect(date); + } + } else { + setEnd(value); + if (isValid(date)) { + handleEndSelect(date); + } + } + }; + + React.useEffect(() => { + setStart(startDate ? format(parse(startDate, 'yyyyMMdd', new Date()), 'yyyy-MM-dd') : ''); + setEnd(endDate ? format(parse(endDate, 'yyyyMMdd', new Date()), 'yyyy-MM-dd') : ''); + }, [startDate, endDate]); + + return ( +
+ + +
+ + handleInputChange(e, 'start')} + className={cn( + 'border-inputfield-main focus:border-inputfield-focus h-[32px] w-full justify-start rounded border bg-black py-[6.5px] pl-[6.5px] pr-[6.5px] text-left text-sm font-normal hover:bg-black hover:text-white', + !start && 'text-muted-foreground' + )} + data-cy="input-date-range-start" + /> +
+
+ + + +
+ + + +
+ + handleInputChange(e, 'end')} + className={cn( + 'border-inputfield-main focus:border-inputfield-focus h-full w-full justify-start rounded border bg-black py-[6.5px] pl-[6.5px] pr-[6.5px] text-left text-sm font-normal hover:bg-black hover:text-white', + !end && 'text-muted-foreground' + )} + data-cy="input-date-range-end" + /> +
+
+ + + +
+
+ ); +} diff --git a/platform/ui-next/src/components/DateRange/index.ts b/platform/ui-next/src/components/DateRange/index.ts new file mode 100644 index 0000000000..dd77e0cb03 --- /dev/null +++ b/platform/ui-next/src/components/DateRange/index.ts @@ -0,0 +1,3 @@ +import { DatePickerWithRange } from "./DateRange"; + +export default DatePickerWithRange; diff --git a/platform/ui-next/src/components/Dialog/Dialog.tsx b/platform/ui-next/src/components/Dialog/Dialog.tsx new file mode 100644 index 0000000000..0b67911aa1 --- /dev/null +++ b/platform/ui-next/src/components/Dialog/Dialog.tsx @@ -0,0 +1,105 @@ +import * as React from 'react'; +import * as DialogPrimitive from '@radix-ui/react-dialog'; +import { Cross2Icon } from '@radix-ui/react-icons'; + +import { cn } from '../../lib/utils'; + +const Dialog = DialogPrimitive.Root; + +const DialogTrigger = DialogPrimitive.Trigger; + +const DialogPortal = DialogPrimitive.Portal; + +const DialogClose = DialogPrimitive.Close; + +const DialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName; + +const DialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + {children} + + + Close + + + +)); +DialogContent.displayName = DialogPrimitive.Content.displayName; + +const DialogHeader = ({ className, ...props }: React.HTMLAttributes) => ( +
+); +DialogHeader.displayName = 'DialogHeader'; + +const DialogFooter = ({ className, ...props }: React.HTMLAttributes) => ( +
+); +DialogFooter.displayName = 'DialogFooter'; + +const DialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogTitle.displayName = DialogPrimitive.Title.displayName; + +const DialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogDescription.displayName = DialogPrimitive.Description.displayName; + +export { + Dialog, + DialogPortal, + DialogOverlay, + DialogTrigger, + DialogClose, + DialogContent, + DialogHeader, + DialogFooter, + DialogTitle, + DialogDescription, +}; diff --git a/platform/ui-next/src/components/Dialog/index.ts b/platform/ui-next/src/components/Dialog/index.ts new file mode 100644 index 0000000000..92f1d6d428 --- /dev/null +++ b/platform/ui-next/src/components/Dialog/index.ts @@ -0,0 +1,3 @@ +import * as DialogComponents from './Dialog'; + +export default DialogComponents; diff --git a/platform/ui-next/src/components/Popover/Popover.tsx b/platform/ui-next/src/components/Popover/Popover.tsx new file mode 100644 index 0000000000..bdd335d792 --- /dev/null +++ b/platform/ui-next/src/components/Popover/Popover.tsx @@ -0,0 +1,31 @@ +import * as React from 'react'; +import * as PopoverPrimitive from '@radix-ui/react-popover'; + +import { cn } from '../../lib/utils'; + +const Popover = PopoverPrimitive.Root; + +const PopoverTrigger = PopoverPrimitive.Trigger; + +const PopoverAnchor = PopoverPrimitive.Anchor; + +const PopoverContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => ( + + + +)); +PopoverContent.displayName = PopoverPrimitive.Content.displayName; + +export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor }; diff --git a/platform/ui-next/src/components/Popover/index.ts b/platform/ui-next/src/components/Popover/index.ts new file mode 100644 index 0000000000..56fdcd0c04 --- /dev/null +++ b/platform/ui-next/src/components/Popover/index.ts @@ -0,0 +1,3 @@ +import * as Popover from './Popover'; + +export default Popover; diff --git a/platform/ui-next/src/components/ThemeWrapper/ThemeWrapper.tsx b/platform/ui-next/src/components/ThemeWrapper/ThemeWrapper.tsx new file mode 100644 index 0000000000..561fcaacc1 --- /dev/null +++ b/platform/ui-next/src/components/ThemeWrapper/ThemeWrapper.tsx @@ -0,0 +1,4 @@ +import React from 'react'; +import '../../tailwind.css'; + +export const ThemeWrapper = ({ children }) => {children}; diff --git a/platform/ui-next/src/components/ThemeWrapper/index.ts b/platform/ui-next/src/components/ThemeWrapper/index.ts new file mode 100644 index 0000000000..69f5248ba7 --- /dev/null +++ b/platform/ui-next/src/components/ThemeWrapper/index.ts @@ -0,0 +1 @@ +export { ThemeWrapper } from './ThemeWrapper'; diff --git a/platform/ui-next/src/components/Tooltip/Tooltip.tsx b/platform/ui-next/src/components/Tooltip/Tooltip.tsx new file mode 100644 index 0000000000..8f3cb69b26 --- /dev/null +++ b/platform/ui-next/src/components/Tooltip/Tooltip.tsx @@ -0,0 +1,28 @@ +import * as React from 'react'; +import * as TooltipPrimitive from '@radix-ui/react-tooltip'; + +import { cn } from '../../lib/utils'; + +const TooltipProvider = TooltipPrimitive.Provider; + +const Tooltip = TooltipPrimitive.Root; + +const TooltipTrigger = TooltipPrimitive.Trigger; + +const TooltipContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + +)); +TooltipContent.displayName = TooltipPrimitive.Content.displayName; + +export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }; diff --git a/platform/ui-next/src/components/Tooltip/index.ts b/platform/ui-next/src/components/Tooltip/index.ts new file mode 100644 index 0000000000..a775f002b0 --- /dev/null +++ b/platform/ui-next/src/components/Tooltip/index.ts @@ -0,0 +1,3 @@ +import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from './Tooltip'; + +export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger }; diff --git a/platform/ui-next/src/components/index.ts b/platform/ui-next/src/components/index.ts new file mode 100644 index 0000000000..e0c1cbe767 --- /dev/null +++ b/platform/ui-next/src/components/index.ts @@ -0,0 +1,10 @@ +import { Button, buttonVariants } from './Button'; +import { ThemeWrapper } from './ThemeWrapper'; +import Command from './Command'; +import Dialog from './Dialog'; +import Combobox from './Combobox'; +import Popover from './Popover'; +import Calendar from './Calendar'; +import DatePickerWithRange from './DateRange'; + +export { Button, buttonVariants, ThemeWrapper, Command, Dialog, Combobox, Popover, Calendar, DatePickerWithRange}; diff --git a/platform/ui-next/src/contextProviders/NotificationProvider.tsx b/platform/ui-next/src/contextProviders/NotificationProvider.tsx new file mode 100644 index 0000000000..6cabfa317a --- /dev/null +++ b/platform/ui-next/src/contextProviders/NotificationProvider.tsx @@ -0,0 +1,85 @@ +import React, { useState, createContext, useContext, useCallback, useEffect } from 'react'; +import PropTypes from 'prop-types'; +import { Toaster, toast } from 'sonner'; + +const NotificationContext = createContext(null); + +export const useNotification = () => useContext(NotificationContext); + +const NotificationProvider = ({ children, service }) => { + const DEFAULT_OPTIONS = { + title: '', + message: '', + duration: 5000, + position: 'bottom-right', // Aligning to Sonner's positioning system + type: 'info', // info, success, error + }; + + const [notificationItems, setNotificationItems] = useState([]); + + const show = useCallback(options => { + const { title, message, duration, position, type } = { ...DEFAULT_OPTIONS, ...options }; + const id = toast[type](message, { + duration, + position, + render: () => ( +
+ {title} +

{message}

+
+ ), + }); + + setNotificationItems(state => [...state, { id, ...options }]); + }, []); + + const hide = useCallback(id => { + toast.dismiss(id); + setNotificationItems(state => state.filter(item => item.id !== id)); + }, []); + + const hideAll = useCallback(() => { + toast.dismiss(); + setNotificationItems([]); + }, []); + + useEffect(() => { + window.notification = { show, hide, hideAll }; + }, [show, hide, hideAll]); + + /** + * Sets the implementation of a notification service that can be used by extensions. + * + * @returns void + */ + useEffect(() => { + if (service) { + service.setServiceImplementation({ hide, show }); + } + }, [service, hide, show]); + + return ( + + + {children} + + ); +}; + +NotificationProvider.propTypes = { + children: PropTypes.node.isRequired, +}; + +export const withNotification = Component => { + return function WrappedComponent(props) { + const notificationContext = useNotification(); + return ( + + ); + }; +}; + +export default NotificationProvider; diff --git a/platform/ui-next/src/contextProviders/index.ts b/platform/ui-next/src/contextProviders/index.ts new file mode 100644 index 0000000000..57d3d90ecd --- /dev/null +++ b/platform/ui-next/src/contextProviders/index.ts @@ -0,0 +1,3 @@ +import NotificationProvider, { useNotification } from './NotificationProvider'; + +export { useNotification, NotificationProvider }; diff --git a/platform/ui-next/src/index.ts b/platform/ui-next/src/index.ts new file mode 100644 index 0000000000..63fbdcf76e --- /dev/null +++ b/platform/ui-next/src/index.ts @@ -0,0 +1,28 @@ +import { + Button, + buttonVariants, + ThemeWrapper, + Dialog, + Command, + Popover, + Combobox, + Calendar, + DatePickerWithRange, +} from './components'; +import { useNotification, NotificationProvider } from './contextProviders'; + +export { + // components + Button, + Dialog, + Command, + Popover, + Combobox, + buttonVariants, + ThemeWrapper, + Calendar, + DatePickerWithRange, + // contextProviders + NotificationProvider, + useNotification, +}; diff --git a/platform/ui-next/src/lib/utils.ts b/platform/ui-next/src/lib/utils.ts new file mode 100644 index 0000000000..9ad0df4269 --- /dev/null +++ b/platform/ui-next/src/lib/utils.ts @@ -0,0 +1,6 @@ +import { type ClassValue, clsx } from 'clsx'; +import { twMerge } from 'tailwind-merge'; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} diff --git a/platform/ui-next/src/tailwind.css b/platform/ui-next/src/tailwind.css new file mode 100644 index 0000000000..ebb4afb43e --- /dev/null +++ b/platform/ui-next/src/tailwind.css @@ -0,0 +1,197 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* OHIF Theme */ + +@layer base { + :root { + --highlight: 191 74% 63%; + --background: 236 62% 5%; + --foreground: 0 0% 98%; + --card: 236 62% 5%; + --card-foreground: 0 0% 98%; + --popover: 236 62% 5%; + --popover-foreground: 0 0% 98%; + --primary: 214 98% 60%; + --primary-foreground: 0 0% 98%; + --secondary: 214 66% 48%; + --secondary-foreground: 0 0% 98%; + --muted: 234 64% 10%; + --muted-foreground: 200 46 65%; + --accent: 214 67% 12%; + --accent-foreground: 0 0% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 0% 98%; + --border: 0 0% 14.9%; + --input: 236 45% 21%; + --ring: 214 98% 60%; + --chart-1: 220 70% 50%; + --chart-2: 160 60% 45%; + --chart-3: 30 80% 55%; + --chart-4: 280 65% 60%; + --chart-5: 340 75% 55%; + --radius: 0.5rem; + } + + .dark { + --background: 0 0% 3.9%; + --foreground: 0 0% 98%; + --card: 0 0% 3.9%; + --card-foreground: 0 0% 98%; + --popover: 0 0% 3.9%; + --popover-foreground: 0 0% 98%; + --primary: 214 98% 60%; + --primary-foreground: 0 0% 98%; + --secondary: 0 0% 14.9%; + --secondary-foreground: 0 0% 98%; + --muted: 0 0% 14.9%; + --muted-foreground: 0 0% 63.9%; + --accent: 0 0% 14.9%; + --accent-foreground: 0 0% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 0% 98%; + --border: 0 0% 14.9%; + --input: 236 45% 21%; + --ring: 214 98% 60%; + --chart-1: 220 70% 50%; + --chart-2: 160 60% 45%; + --chart-3: 30 80% 55%; + --chart-4: 280 65% 60%; + --chart-5: 340 75% 55%; + } +} + +/* ORIGINAL THEME for comparison and testing + +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 240 10% 3.9%; + --card: 0 0% 100%; + --card-foreground: 240 10% 3.9%; + --popover: 0 0% 100%; + --popover-foreground: 240 10% 3.9%; + --primary: 240 5.9% 10%; + --primary-foreground: 0 0% 98%; + --secondary: 240 4.8% 95.9%; + --secondary-foreground: 240 5.9% 10%; + --muted: 240 4.8% 95.9%; + --muted-foreground: 240 3.8% 46.1%; + --accent: 240 4.8% 95.9%; + --accent-foreground: 240 5.9% 10%; + --destructive: 0 72.22% 50.59%; + --destructive-foreground: 0 0% 98%; + --border: 240 5.9% 90%; + --input: 240 5.9% 90%; + --ring: 240 5% 64.9%; + --radius: 0.5rem; + + --chart-1: 12 76% 61%; + --chart-2: 173 58% 39%; + --chart-3: 197 37% 24%; + --chart-4: 43 74% 66%; + --chart-5: 27 87% 67%; + } + + + .dark { + --background: 240 10% 3.9%; + --foreground: 0 0% 98%; + --card: 240 10% 3.9%; + --card-foreground: 0 0% 98%; + --popover: 240 10% 3.9%; + --popover-foreground: 0 0% 98%; + --primary: 0 0% 98%; + --primary-foreground: 240 5.9% 10%; + --secondary: 240 3.7% 15.9%; + --secondary-foreground: 0 0% 98%; + --muted: 240 3.7% 15.9%; + --muted-foreground: 240 5% 64.9%; + --accent: 240 3.7% 15.9%; + --accent-foreground: 0 0% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 85.7% 97.3%; + --border: 240 3.7% 15.9%; + --input: 240 3.7% 15.9%; + --ring: 240 4.9% 83.9%; + + --chart-1: 220 70% 50%; + --chart-2: 160 60% 45%; + --chart-3: 30 80% 55%; + --chart-4: 280 65% 60%; + --chart-5: 340 75% 55%; + } +} + +*/ + +/* Theme Copy Example + +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 224 71.4% 4.1%; + --card: 0 0% 100%; + --card-foreground: 224 71.4% 4.1%; + --popover: 0 0% 100%; + --popover-foreground: 224 71.4% 4.1%; + --primary: 262.1 83.3% 57.8%; + --primary-foreground: 210 20% 98%; + --secondary: 220 14.3% 95.9%; + --secondary-foreground: 220.9 39.3% 11%; + --muted: 220 14.3% 95.9%; + --muted-foreground: 220 8.9% 46.1%; + --accent: 220 14.3% 95.9%; + --accent-foreground: 220.9 39.3% 11%; + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 210 20% 98%; + --border: 220 13% 91%; + --input: 220 13% 91%; + --ring: 262.1 83.3% 57.8%; + --radius: 0.5rem; + --chart-1: ; + --chart-2: ; + --chart-3: ; + --chart-4: ; + --chart-5: ; + } + + .dark { + --background: 224 71.4% 4.1%; + --foreground: 210 20% 98%; + --card: 224 71.4% 4.1%; + --card-foreground: 210 20% 98%; + --popover: 224 71.4% 4.1%; + --popover-foreground: 210 20% 98%; + --primary: 263.4 70% 50.4%; + --primary-foreground: 210 20% 98%; + --secondary: 215 27.9% 16.9%; + --secondary-foreground: 210 20% 98%; + --muted: 215 27.9% 16.9%; + --muted-foreground: 217.9 10.6% 64.9%; + --accent: 215 27.9% 16.9%; + --accent-foreground: 210 20% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 210 20% 98%; + --border: 215 27.9% 16.9%; + --input: 215 27.9% 16.9%; + --ring: 263.4 70% 50.4%; + --chart-1: ; + --chart-2: ; + --chart-3: ; + --chart-4: ; + --chart-5: ; + } +} + +*/ + + +/* Additional CSS edits to components */ + +/* Tooltip */ + +.TooltipContent[data-side='bottom'] { + animation-name: slideDown; +} diff --git a/platform/ui-next/tailwind.config.js b/platform/ui-next/tailwind.config.js new file mode 100644 index 0000000000..d82d4fbcfa --- /dev/null +++ b/platform/ui-next/tailwind.config.js @@ -0,0 +1,71 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + presets: [require('../ui/tailwind.config.js')], + content: [ + './pages/**/*.{ts,tsx}', + './components/**/*.{ts,tsx}', + './app/**/*.{ts,tsx}', + './src/**/*.{ts,tsx}', + ], + prefix: '', + theme: { + extend: { + colors: { + highlight: 'hsl(var(--highlight))', + border: 'hsl(var(--border))', + input: 'hsl(var(--input))', + ring: 'hsl(var(--ring))', + background: 'hsl(var(--background))', + foreground: 'hsl(var(--foreground))', + primary: { + DEFAULT: 'hsl(var(--primary))', + foreground: 'hsl(var(--primary-foreground))', + }, + secondary: { + DEFAULT: 'hsl(var(--secondary))', + foreground: 'hsl(var(--secondary-foreground))', + }, + destructive: { + DEFAULT: 'hsl(var(--destructive))', + foreground: 'hsl(var(--destructive-foreground))', + }, + muted: { + DEFAULT: 'hsl(var(--muted))', + foreground: 'hsl(var(--muted-foreground))', + }, + accent: { + DEFAULT: 'hsl(var(--accent))', + foreground: 'hsl(var(--accent-foreground))', + }, + popover: { + DEFAULT: 'hsl(var(--popover))', + foreground: 'hsl(var(--popover-foreground))', + }, + card: { + DEFAULT: 'hsl(var(--card))', + foreground: 'hsl(var(--card-foreground))', + }, + }, + borderRadius: { + lg: 'var(--radius)', + md: 'calc(var(--radius) - 2px)', + sm: 'calc(var(--radius) - 4px)', + }, + keyframes: { + 'accordion-down': { + from: { height: '0' }, + to: { height: 'var(--radix-accordion-content-height)' }, + }, + 'accordion-up': { + from: { height: 'var(--radix-accordion-content-height)' }, + to: { height: '0' }, + }, + }, + animation: { + 'accordion-down': 'accordion-down 0.2s ease-out', + 'accordion-up': 'accordion-up 0.2s ease-out', + }, + }, + }, + plugins: [require('tailwindcss-animate')], +}; diff --git a/platform/ui-next/tsconfig.json b/platform/ui-next/tsconfig.json new file mode 100644 index 0000000000..e63e92ef48 --- /dev/null +++ b/platform/ui-next/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@ui/*": ["./src/*"] + } + }, + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/platform/ui/CHANGELOG.md b/platform/ui/CHANGELOG.md index 58d5e2bbc7..365cc70c9d 100644 --- a/platform/ui/CHANGELOG.md +++ b/platform/ui/CHANGELOG.md @@ -3,6 +3,750 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.9.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.70...v3.9.0-beta.71) (2024-07-30) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.69...v3.9.0-beta.70) (2024-07-30) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.68...v3.9.0-beta.69) (2024-07-27) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.67...v3.9.0-beta.68) (2024-07-26) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.66...v3.9.0-beta.67) (2024-07-26) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.65...v3.9.0-beta.66) (2024-07-24) + + +### Features + +* **pmap:** added support for parametric map ([#4284](https://github.com/OHIF/Viewers/issues/4284)) ([fc0064f](https://github.com/OHIF/Viewers/commit/fc0064fd9d8cdc8fde81b81f0e71fd5d077ca22b)) + + + + + +# [3.9.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.64...v3.9.0-beta.65) (2024-07-23) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.63...v3.9.0-beta.64) (2024-07-19) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.62...v3.9.0-beta.63) (2024-07-10) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.61...v3.9.0-beta.62) (2024-07-09) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.60...v3.9.0-beta.61) (2024-07-09) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.59...v3.9.0-beta.60) (2024-07-09) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.58...v3.9.0-beta.59) (2024-07-05) + + +### Bug Fixes + +* Cobb angle not working in basic-test mode and open contour ([#4280](https://github.com/OHIF/Viewers/issues/4280)) ([6fd3c7e](https://github.com/OHIF/Viewers/commit/6fd3c7e293fec851dd30e650c1347cc0bc7a99ee)) + + + + + +# [3.9.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.57...v3.9.0-beta.58) (2024-07-04) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.56...v3.9.0-beta.57) (2024-07-02) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.55...v3.9.0-beta.56) (2024-07-02) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.54...v3.9.0-beta.55) (2024-06-28) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.53...v3.9.0-beta.54) (2024-06-28) + + +### Features + +* **studyPrefetcher:** Study Prefetcher ([#4206](https://github.com/OHIF/Viewers/issues/4206)) ([2048b19](https://github.com/OHIF/Viewers/commit/2048b19484c0b1fae73f993cfaa814f861bbd230)) + + + + + +# [3.9.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.52...v3.9.0-beta.53) (2024-06-28) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.51...v3.9.0-beta.52) (2024-06-27) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.50...v3.9.0-beta.51) (2024-06-27) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.49...v3.9.0-beta.50) (2024-06-26) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.48...v3.9.0-beta.49) (2024-06-26) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.47...v3.9.0-beta.48) (2024-06-25) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.46...v3.9.0-beta.47) (2024-06-21) + + +### Bug Fixes + +* Allow the mode setup/creation to be async, and provide a few more values to extension/app config/mode setup. ([#4016](https://github.com/OHIF/Viewers/issues/4016)) ([88575c6](https://github.com/OHIF/Viewers/commit/88575c6c09fd778a31b2f91524163ce65d1639dd)) + + +### Features + +* customization service append and customize functionality should run once ([#4238](https://github.com/OHIF/Viewers/issues/4238)) ([e462fd3](https://github.com/OHIF/Viewers/commit/e462fd31f7944acfee34f08cfbc28cfd9de16169)) +* **sort:** custom series sort in study panel ([#4214](https://github.com/OHIF/Viewers/issues/4214)) ([a433d40](https://github.com/OHIF/Viewers/commit/a433d406e2cac13f644203996c682260b54e8865)) + + + + + +# [3.9.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.45...v3.9.0-beta.46) (2024-06-18) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.44...v3.9.0-beta.45) (2024-06-18) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.43...v3.9.0-beta.44) (2024-06-17) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.42...v3.9.0-beta.43) (2024-06-12) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.41...v3.9.0-beta.42) (2024-06-12) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.40...v3.9.0-beta.41) (2024-06-12) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.39...v3.9.0-beta.40) (2024-06-12) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.38...v3.9.0-beta.39) (2024-06-08) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.37...v3.9.0-beta.38) (2024-06-07) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.36...v3.9.0-beta.37) (2024-06-05) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.35...v3.9.0-beta.36) (2024-06-05) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.34...v3.9.0-beta.35) (2024-06-05) + + +### Bug Fixes + +* **seg:** maintain algorithm name and algorithm type when DICOM seg is exported or downloaded ([#4203](https://github.com/OHIF/Viewers/issues/4203)) ([a29e94d](https://github.com/OHIF/Viewers/commit/a29e94de803f79bbb3372d00ad8eb14b4224edc2)) + + + + + +# [3.9.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.33...v3.9.0-beta.34) (2024-06-05) + + +### Bug Fixes + +* **hydration:** Maintain the same slice that the user was on pre hydration in post hydration for SR and SEG. ([#4200](https://github.com/OHIF/Viewers/issues/4200)) ([430330f](https://github.com/OHIF/Viewers/commit/430330f7e384d503cb6fc695a7a9642ddfaac313)) + + + + + +# [3.9.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.32...v3.9.0-beta.33) (2024-06-05) + + +### Features + +* **window-level-region:** add window level region tool ([#4127](https://github.com/OHIF/Viewers/issues/4127)) ([ab1a18a](https://github.com/OHIF/Viewers/commit/ab1a18af5a5b0f9086c080ed81c8fda9bfaa975b)) + + + + + +# [3.9.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.31...v3.9.0-beta.32) (2024-05-31) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.30...v3.9.0-beta.31) (2024-05-30) + + +### Bug Fixes + +* **seg:** should be able to navigate outside toolbox and come back later ([#4196](https://github.com/OHIF/Viewers/issues/4196)) ([93e7609](https://github.com/OHIF/Viewers/commit/93e760937f6587ba7481fcf3484ba9004ba49a62)) + + + + + +# [3.9.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.29...v3.9.0-beta.30) (2024-05-30) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.28...v3.9.0-beta.29) (2024-05-30) + + +### Bug Fixes + +* **tmtv:** side panel crashing when activeToolOptions is not an array ([#4189](https://github.com/OHIF/Viewers/issues/4189)) ([19b5b1c](https://github.com/OHIF/Viewers/commit/19b5b1c15cb29ddf1cfd9b608815199bc838f8b2)) + + + + + +# [3.9.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.27...v3.9.0-beta.28) (2024-05-30) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.26...v3.9.0-beta.27) (2024-05-29) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.25...v3.9.0-beta.26) (2024-05-29) + + +### Features + +* **hp:** Add displayArea option for Hanging protocols and example with Mamo([#3808](https://github.com/OHIF/Viewers/issues/3808)) ([18ac08e](https://github.com/OHIF/Viewers/commit/18ac08ed860d119721c52e4ffc270332259100b6)) + + + + + +# [3.9.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.24...v3.9.0-beta.25) (2024-05-29) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.23...v3.9.0-beta.24) (2024-05-29) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.22...v3.9.0-beta.23) (2024-05-28) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.21...v3.9.0-beta.22) (2024-05-27) + + +### Features + +* **ui:** move to React 18 and base for using shadcn/ui ([#4174](https://github.com/OHIF/Viewers/issues/4174)) ([70f2c79](https://github.com/OHIF/Viewers/commit/70f2c797f42af603d7ea0eb8d23b4103aba66f77)) + + + + + +# [3.9.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.20...v3.9.0-beta.21) (2024-05-24) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.19...v3.9.0-beta.20) (2024-05-24) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.18...v3.9.0-beta.19) (2024-05-24) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.17...v3.9.0-beta.18) (2024-05-24) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.16...v3.9.0-beta.17) (2024-05-23) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.15...v3.9.0-beta.16) (2024-05-23) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.14...v3.9.0-beta.15) (2024-05-22) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.13...v3.9.0-beta.14) (2024-05-21) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.12...v3.9.0-beta.13) (2024-05-21) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.11...v3.9.0-beta.12) (2024-05-21) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.10...v3.9.0-beta.11) (2024-05-21) + + +### Features + +* **test:** Playwright testing integration ([#4146](https://github.com/OHIF/Viewers/issues/4146)) ([fe1a706](https://github.com/OHIF/Viewers/commit/fe1a706446cc33670bf5fab8451e8281b487fcd6)) + + + + + +# [3.9.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.9...v3.9.0-beta.10) (2024-05-21) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.8...v3.9.0-beta.9) (2024-05-17) + + +### Bug Fixes + +* **select:** utilize react portals for select component ([#4144](https://github.com/OHIF/Viewers/issues/4144)) ([dce1e7d](https://github.com/OHIF/Viewers/commit/dce1e7d423cb64ec0d4be7362ecbfd52db47ef36)) + + + + + +# [3.9.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.7...v3.9.0-beta.8) (2024-05-16) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.6...v3.9.0-beta.7) (2024-05-15) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.5...v3.9.0-beta.6) (2024-05-15) + + +### Bug Fixes + +* 🐛 Overflow scroll list menu based on screen hight ([#4123](https://github.com/OHIF/Viewers/issues/4123)) ([6bba2e7](https://github.com/OHIF/Viewers/commit/6bba2e70f80d8eacc57c0e765013d9c10adf5413)) + + + + + +# [3.9.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.4...v3.9.0-beta.5) (2024-05-14) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.3...v3.9.0-beta.4) (2024-05-14) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.2...v3.9.0-beta.3) (2024-05-08) + + +### Features + +* **typings:** Enhance typing support with withAppTypes and custom services throughout OHIF ([#4090](https://github.com/OHIF/Viewers/issues/4090)) ([374065b](https://github.com/OHIF/Viewers/commit/374065bc3bad9d212f9817a8d41546cc64cfabfb)) + + + + + +# [3.9.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.1...v3.9.0-beta.2) (2024-05-06) + + +### Bug Fixes + +* **bugs:** enhancements and bugs in several areas ([#4086](https://github.com/OHIF/Viewers/issues/4086)) ([730f434](https://github.com/OHIF/Viewers/commit/730f4349100f21b4489a21707dbb2dca9dbfbba2)) + + + + + +# [3.9.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.9.0-beta.0...v3.9.0-beta.1) (2024-05-06) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.9.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.94...v3.9.0-beta.0) (2024-04-29) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.8.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.93...v3.8.0-beta.94) (2024-04-29) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.8.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.92...v3.8.0-beta.93) (2024-04-29) + + +### Bug Fixes + +* **toolbox:** Preserve user-specified tool state and streamline command execution ([#4063](https://github.com/OHIF/Viewers/issues/4063)) ([f1a736d](https://github.com/OHIF/Viewers/commit/f1a736d1934733a434cb87b2c284907a3122403f)) + + + + + +# [3.8.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.91...v3.8.0-beta.92) (2024-04-28) + + +### Bug Fixes + +* **bugs:** fix patient header for doc, track ball rotate resize observer and add segmentation button not being enabled on viewport data change ([#4068](https://github.com/OHIF/Viewers/issues/4068)) ([c09311d](https://github.com/OHIF/Viewers/commit/c09311d3b7df05fcd00a9f36a7233e9d7e5589d0)) + + + + + +# [3.8.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.90...v3.8.0-beta.91) (2024-04-25) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.8.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.89...v3.8.0-beta.90) (2024-04-22) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.8.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.88...v3.8.0-beta.89) (2024-04-22) + + +### Bug Fixes + +* **viewport-webworker-segmentation:** Resolve issues with viewport detection, webworker termination, and segmentation panel layout change ([#4059](https://github.com/OHIF/Viewers/issues/4059)) ([52a0c59](https://github.com/OHIF/Viewers/commit/52a0c59294a4161fcca0a6708855549034849951)) + + + + + +# [3.8.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.87...v3.8.0-beta.88) (2024-04-22) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.8.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.86...v3.8.0-beta.87) (2024-04-19) + + +### Features + +* **tmtv-mode:** Add Brush tools and move SUV peak calculation to web worker ([#4053](https://github.com/OHIF/Viewers/issues/4053)) ([8192e34](https://github.com/OHIF/Viewers/commit/8192e348eca993fec331d4963efe88f9a730eceb)) + + + + + +# [3.8.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.85...v3.8.0-beta.86) (2024-04-19) + + +### Bug Fixes + +* **layouts:** and fix thumbnail in touch and update migration guide for 3.8 release ([#4052](https://github.com/OHIF/Viewers/issues/4052)) ([d250d04](https://github.com/OHIF/Viewers/commit/d250d04580883446fcb8d748b2a97c5c198922af)) + + + + + +# [3.8.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.84...v3.8.0-beta.85) (2024-04-18) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.8.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.83...v3.8.0-beta.84) (2024-04-18) + +**Note:** Version bump only for package @ohif/ui + + + + + +# [3.8.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.82...v3.8.0-beta.83) (2024-04-18) + + +### Bug Fixes + +* **bugs:** enhancements and bug fixes - final ([#4048](https://github.com/OHIF/Viewers/issues/4048)) ([170bb96](https://github.com/OHIF/Viewers/commit/170bb96983082c39b22b7352e0c54aacf3e73b02)) + + + + + # [3.8.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.81...v3.8.0-beta.82) (2024-04-17) diff --git a/platform/ui/assets/images/action-new-dialog.svg b/platform/ui/assets/images/action-new-dialog.svg new file mode 100644 index 0000000000..89331dc6b5 --- /dev/null +++ b/platform/ui/assets/images/action-new-dialog.svg @@ -0,0 +1,14 @@ + + + action-new-dialog + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/arrow-down.svg b/platform/ui/assets/images/arrow-down.svg new file mode 100644 index 0000000000..5064d51e42 --- /dev/null +++ b/platform/ui/assets/images/arrow-down.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/platform/ui/assets/images/arrow-left-small.svg b/platform/ui/assets/images/arrow-left-small.svg new file mode 100644 index 0000000000..4a86c50e23 --- /dev/null +++ b/platform/ui/assets/images/arrow-left-small.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/ui/assets/images/arrow-left.svg b/platform/ui/assets/images/arrow-left.svg new file mode 100644 index 0000000000..307f8ffdf4 --- /dev/null +++ b/platform/ui/assets/images/arrow-left.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/ui/assets/images/arrow-right-small.svg b/platform/ui/assets/images/arrow-right-small.svg new file mode 100644 index 0000000000..6d72336f60 --- /dev/null +++ b/platform/ui/assets/images/arrow-right-small.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/ui/assets/images/arrow-right.svg b/platform/ui/assets/images/arrow-right.svg new file mode 100644 index 0000000000..307f8ffdf4 --- /dev/null +++ b/platform/ui/assets/images/arrow-right.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/ui/assets/images/calendar.svg b/platform/ui/assets/images/calendar.svg new file mode 100644 index 0000000000..af83a587fc --- /dev/null +++ b/platform/ui/assets/images/calendar.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/platform/ui/assets/images/cancel.svg b/platform/ui/assets/images/cancel.svg new file mode 100644 index 0000000000..dbf6c1df11 --- /dev/null +++ b/platform/ui/assets/images/cancel.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/platform/ui/assets/images/checkbox-active.svg b/platform/ui/assets/images/checkbox-active.svg new file mode 100644 index 0000000000..a56c13f5c7 --- /dev/null +++ b/platform/ui/assets/images/checkbox-active.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/platform/ui/assets/images/checkbox-checked.svg b/platform/ui/assets/images/checkbox-checked.svg new file mode 100644 index 0000000000..e9aeb91451 --- /dev/null +++ b/platform/ui/assets/images/checkbox-checked.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/platform/ui/assets/images/checkbox-default.svg b/platform/ui/assets/images/checkbox-default.svg new file mode 100644 index 0000000000..3fd0791532 --- /dev/null +++ b/platform/ui/assets/images/checkbox-default.svg @@ -0,0 +1,3 @@ + + + diff --git a/platform/ui/assets/images/checkbox-unchecked.svg b/platform/ui/assets/images/checkbox-unchecked.svg new file mode 100644 index 0000000000..99779d52e5 --- /dev/null +++ b/platform/ui/assets/images/checkbox-unchecked.svg @@ -0,0 +1,3 @@ + + + diff --git a/platform/ui/assets/images/chevron-down.svg b/platform/ui/assets/images/chevron-down.svg new file mode 100644 index 0000000000..01aea1b304 --- /dev/null +++ b/platform/ui/assets/images/chevron-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/platform/ui/assets/images/chevron-left.svg b/platform/ui/assets/images/chevron-left.svg new file mode 100644 index 0000000000..e9951716ba --- /dev/null +++ b/platform/ui/assets/images/chevron-left.svg @@ -0,0 +1,3 @@ + + + diff --git a/platform/ui/assets/images/chevron-menu.svg b/platform/ui/assets/images/chevron-menu.svg new file mode 100644 index 0000000000..7e0d9054df --- /dev/null +++ b/platform/ui/assets/images/chevron-menu.svg @@ -0,0 +1,12 @@ + + + chevron-menu + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/chevron-next.svg b/platform/ui/assets/images/chevron-next.svg new file mode 100644 index 0000000000..197f3f2d42 --- /dev/null +++ b/platform/ui/assets/images/chevron-next.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/ui/assets/images/chevron-prev.svg b/platform/ui/assets/images/chevron-prev.svg new file mode 100644 index 0000000000..dcd01a2b8c --- /dev/null +++ b/platform/ui/assets/images/chevron-prev.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/ui/assets/images/chevron-right.svg b/platform/ui/assets/images/chevron-right.svg new file mode 100644 index 0000000000..355ccbff15 --- /dev/null +++ b/platform/ui/assets/images/chevron-right.svg @@ -0,0 +1,3 @@ + + + diff --git a/platform/ui/assets/images/circled-checkmark.svg b/platform/ui/assets/images/circled-checkmark.svg new file mode 100644 index 0000000000..a45ac3e51c --- /dev/null +++ b/platform/ui/assets/images/circled-checkmark.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/ui/assets/images/clipboard.svg b/platform/ui/assets/images/clipboard.svg new file mode 100644 index 0000000000..850511a0b8 --- /dev/null +++ b/platform/ui/assets/images/clipboard.svg @@ -0,0 +1 @@ + diff --git a/platform/ui/assets/images/closeIcon.svg b/platform/ui/assets/images/closeIcon.svg new file mode 100644 index 0000000000..4760717a4b --- /dev/null +++ b/platform/ui/assets/images/closeIcon.svg @@ -0,0 +1,3 @@ + + + diff --git a/platform/ui/assets/images/content-next.svg b/platform/ui/assets/images/content-next.svg new file mode 100644 index 0000000000..45f0b39856 --- /dev/null +++ b/platform/ui/assets/images/content-next.svg @@ -0,0 +1,9 @@ + + + chevron-next + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/content-prev.svg b/platform/ui/assets/images/content-prev.svg new file mode 100644 index 0000000000..a01164b6ba --- /dev/null +++ b/platform/ui/assets/images/content-prev.svg @@ -0,0 +1,9 @@ + + + chevron-prev + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/database.svg b/platform/ui/assets/images/database.svg new file mode 100644 index 0000000000..79fd60ef69 --- /dev/null +++ b/platform/ui/assets/images/database.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/platform/ui/assets/images/dotted-circle.svg b/platform/ui/assets/images/dotted-circle.svg new file mode 100644 index 0000000000..9fcbdcf5a3 --- /dev/null +++ b/platform/ui/assets/images/dotted-circle.svg @@ -0,0 +1,3 @@ + + + diff --git a/platform/ui/assets/images/edit-patient.svg b/platform/ui/assets/images/edit-patient.svg new file mode 100644 index 0000000000..cd37992127 --- /dev/null +++ b/platform/ui/assets/images/edit-patient.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/platform/ui/assets/images/exclamation.svg b/platform/ui/assets/images/exclamation.svg new file mode 100644 index 0000000000..5b6ae388b2 --- /dev/null +++ b/platform/ui/assets/images/exclamation.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/platform/ui/assets/images/external-link.svg b/platform/ui/assets/images/external-link.svg new file mode 100644 index 0000000000..e2407a154d --- /dev/null +++ b/platform/ui/assets/images/external-link.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/platform/ui/assets/images/eye-hidden.svg b/platform/ui/assets/images/eye-hidden.svg new file mode 100644 index 0000000000..df364aeb69 --- /dev/null +++ b/platform/ui/assets/images/eye-hidden.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/platform/ui/assets/images/eye-visible.svg b/platform/ui/assets/images/eye-visible.svg new file mode 100644 index 0000000000..91e3efb805 --- /dev/null +++ b/platform/ui/assets/images/eye-visible.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/ui/assets/images/focus-frame-target.svg b/platform/ui/assets/images/focus-frame-target.svg new file mode 100644 index 0000000000..1139d858c6 --- /dev/null +++ b/platform/ui/assets/images/focus-frame-target.svg @@ -0,0 +1,13 @@ + + + focus-frame-target + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/group-layers.svg b/platform/ui/assets/images/group-layers.svg new file mode 100644 index 0000000000..f4b0592151 --- /dev/null +++ b/platform/ui/assets/images/group-layers.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/ui/assets/images/icon-add.svg b/platform/ui/assets/images/icon-add.svg new file mode 100644 index 0000000000..cc62a07ad4 --- /dev/null +++ b/platform/ui/assets/images/icon-add.svg @@ -0,0 +1,15 @@ + + + icon-add + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/icon-alert-small.svg b/platform/ui/assets/images/icon-alert-small.svg new file mode 100644 index 0000000000..51151d7092 --- /dev/null +++ b/platform/ui/assets/images/icon-alert-small.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/platform/ui/assets/images/icon-chevron-patient.svg b/platform/ui/assets/images/icon-chevron-patient.svg new file mode 100644 index 0000000000..b96478759b --- /dev/null +++ b/platform/ui/assets/images/icon-chevron-patient.svg @@ -0,0 +1,12 @@ + + + icon-chevron-patient + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/icon-clear-field.svg b/platform/ui/assets/images/icon-clear-field.svg new file mode 100644 index 0000000000..faf0195004 --- /dev/null +++ b/platform/ui/assets/images/icon-clear-field.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/platform/ui/assets/images/icon-close.svg b/platform/ui/assets/images/icon-close.svg new file mode 100644 index 0000000000..75066f4d00 --- /dev/null +++ b/platform/ui/assets/images/icon-close.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/platform/ui/assets/images/icon-color-lut.svg b/platform/ui/assets/images/icon-color-lut.svg new file mode 100644 index 0000000000..a339125e7f --- /dev/null +++ b/platform/ui/assets/images/icon-color-lut.svg @@ -0,0 +1,23 @@ + + + icon-color-lut + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/icon-delete.svg b/platform/ui/assets/images/icon-delete.svg new file mode 100644 index 0000000000..c55f7a27f0 --- /dev/null +++ b/platform/ui/assets/images/icon-delete.svg @@ -0,0 +1,17 @@ + + + icon-delete + + + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/icon-disclosure-close.svg b/platform/ui/assets/images/icon-disclosure-close.svg new file mode 100644 index 0000000000..dd6078c55c --- /dev/null +++ b/platform/ui/assets/images/icon-disclosure-close.svg @@ -0,0 +1,12 @@ + + + icon-disclosure-close + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/icon-disclosure-open.svg b/platform/ui/assets/images/icon-disclosure-open.svg new file mode 100644 index 0000000000..7dae7c9ec4 --- /dev/null +++ b/platform/ui/assets/images/icon-disclosure-open.svg @@ -0,0 +1,12 @@ + + + icon-disclosure-open + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/icon-display-settings.svg b/platform/ui/assets/images/icon-display-settings.svg new file mode 100644 index 0000000000..90adb8b5cc --- /dev/null +++ b/platform/ui/assets/images/icon-display-settings.svg @@ -0,0 +1,21 @@ + + + icon-display-settings + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/icon-more-menu.svg b/platform/ui/assets/images/icon-more-menu.svg new file mode 100644 index 0000000000..32f655b0d2 --- /dev/null +++ b/platform/ui/assets/images/icon-more-menu.svg @@ -0,0 +1,17 @@ + + + icon-more-menu + + + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/icon-mpr-alt.svg b/platform/ui/assets/images/icon-mpr-alt.svg new file mode 100644 index 0000000000..74c7550b45 --- /dev/null +++ b/platform/ui/assets/images/icon-mpr-alt.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/platform/ui/assets/images/icon-multiple-patients.svg b/platform/ui/assets/images/icon-multiple-patients.svg new file mode 100644 index 0000000000..276662f9a9 --- /dev/null +++ b/platform/ui/assets/images/icon-multiple-patients.svg @@ -0,0 +1,21 @@ + + + icon-multiple-patients + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/icon-next-inactive.svg b/platform/ui/assets/images/icon-next-inactive.svg new file mode 100644 index 0000000000..9071554487 --- /dev/null +++ b/platform/ui/assets/images/icon-next-inactive.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/ui/assets/images/icon-next.svg b/platform/ui/assets/images/icon-next.svg new file mode 100644 index 0000000000..0a475ea0b1 --- /dev/null +++ b/platform/ui/assets/images/icon-next.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/ui/assets/images/icon-patient.svg b/platform/ui/assets/images/icon-patient.svg new file mode 100644 index 0000000000..0ddc8f7e65 --- /dev/null +++ b/platform/ui/assets/images/icon-patient.svg @@ -0,0 +1,13 @@ + + + icon-patient + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/icon-pause.svg b/platform/ui/assets/images/icon-pause.svg new file mode 100644 index 0000000000..00f45ac298 --- /dev/null +++ b/platform/ui/assets/images/icon-pause.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/ui/assets/images/icon-play.svg b/platform/ui/assets/images/icon-play.svg new file mode 100644 index 0000000000..226ae614d2 --- /dev/null +++ b/platform/ui/assets/images/icon-play.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/ui/assets/images/icon-prev-inactive.svg b/platform/ui/assets/images/icon-prev-inactive.svg new file mode 100644 index 0000000000..2d0df2da12 --- /dev/null +++ b/platform/ui/assets/images/icon-prev-inactive.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/ui/assets/images/icon-prev.svg b/platform/ui/assets/images/icon-prev.svg new file mode 100644 index 0000000000..bd77818049 --- /dev/null +++ b/platform/ui/assets/images/icon-prev.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/ui/assets/images/icon-rename.svg b/platform/ui/assets/images/icon-rename.svg new file mode 100644 index 0000000000..6ccfa0432e --- /dev/null +++ b/platform/ui/assets/images/icon-rename.svg @@ -0,0 +1,15 @@ + + + icon-rename + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/icon-search.svg b/platform/ui/assets/images/icon-search.svg new file mode 100644 index 0000000000..2a960ddd32 --- /dev/null +++ b/platform/ui/assets/images/icon-search.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/platform/ui/assets/images/icon-settings.svg b/platform/ui/assets/images/icon-settings.svg new file mode 100644 index 0000000000..381dae6f2e --- /dev/null +++ b/platform/ui/assets/images/icon-settings.svg @@ -0,0 +1,13 @@ + + + icon-settings + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/icon-status-alert.svg b/platform/ui/assets/images/icon-status-alert.svg new file mode 100644 index 0000000000..615d4a2fdb --- /dev/null +++ b/platform/ui/assets/images/icon-status-alert.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/platform/ui/assets/images/icon-tool-scissor.svg b/platform/ui/assets/images/icon-tool-scissor.svg new file mode 100644 index 0000000000..8559d25154 --- /dev/null +++ b/platform/ui/assets/images/icon-tool-scissor.svg @@ -0,0 +1,17 @@ + + + icon-tool-scissor + + + + + + + + + + + + + + diff --git a/platform/ui/assets/images/icon-toolbar-back.svg b/platform/ui/assets/images/icon-toolbar-back.svg new file mode 100644 index 0000000000..8ee453b2c1 --- /dev/null +++ b/platform/ui/assets/images/icon-toolbar-back.svg @@ -0,0 +1,12 @@ + + + icon-toolbar-back + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/icon-transferring.svg b/platform/ui/assets/images/icon-transferring.svg new file mode 100644 index 0000000000..86379e138e --- /dev/null +++ b/platform/ui/assets/images/icon-transferring.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/ui/assets/images/icon-upload.svg b/platform/ui/assets/images/icon-upload.svg new file mode 100644 index 0000000000..cdd1366fa3 --- /dev/null +++ b/platform/ui/assets/images/icon-upload.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/ui/assets/images/icons-alert-outline.svg b/platform/ui/assets/images/icons-alert-outline.svg new file mode 100644 index 0000000000..747b65c78e --- /dev/null +++ b/platform/ui/assets/images/icons-alert-outline.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/platform/ui/assets/images/illustration-investigational-use.svg b/platform/ui/assets/images/illustration-investigational-use.svg new file mode 100644 index 0000000000..5ca03db687 --- /dev/null +++ b/platform/ui/assets/images/illustration-investigational-use.svg @@ -0,0 +1,20 @@ + + + illustration-investigational-use + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/info-action.svg b/platform/ui/assets/images/info-action.svg new file mode 100644 index 0000000000..305a6c385a --- /dev/null +++ b/platform/ui/assets/images/info-action.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/platform/ui/assets/images/info-link.svg b/platform/ui/assets/images/info-link.svg new file mode 100644 index 0000000000..743fdbb6b6 --- /dev/null +++ b/platform/ui/assets/images/info-link.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/platform/ui/assets/images/info.svg b/platform/ui/assets/images/info.svg new file mode 100644 index 0000000000..8874e2a8dd --- /dev/null +++ b/platform/ui/assets/images/info.svg @@ -0,0 +1,3 @@ + + + diff --git a/platform/ui/assets/images/launch-arrow.svg b/platform/ui/assets/images/launch-arrow.svg new file mode 100644 index 0000000000..0f55172d87 --- /dev/null +++ b/platform/ui/assets/images/launch-arrow.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/platform/ui/assets/images/launch-info.svg b/platform/ui/assets/images/launch-info.svg new file mode 100644 index 0000000000..6e999dc357 --- /dev/null +++ b/platform/ui/assets/images/launch-info.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/platform/ui/assets/images/layout-advanced-3d-four-up.svg b/platform/ui/assets/images/layout-advanced-3d-four-up.svg new file mode 100644 index 0000000000..f9f445ee13 --- /dev/null +++ b/platform/ui/assets/images/layout-advanced-3d-four-up.svg @@ -0,0 +1,13 @@ + + + layout-advanced-3d-four-up + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/layout-advanced-3d-main.svg b/platform/ui/assets/images/layout-advanced-3d-main.svg new file mode 100644 index 0000000000..15b5d31cca --- /dev/null +++ b/platform/ui/assets/images/layout-advanced-3d-main.svg @@ -0,0 +1,12 @@ + + + layout-advanced-3d-main + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/layout-advanced-3d-only.svg b/platform/ui/assets/images/layout-advanced-3d-only.svg new file mode 100644 index 0000000000..8ee7a74315 --- /dev/null +++ b/platform/ui/assets/images/layout-advanced-3d-only.svg @@ -0,0 +1,9 @@ + + + layout-advanced-3d-only + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/layout-advanced-3d-primary.svg b/platform/ui/assets/images/layout-advanced-3d-primary.svg new file mode 100644 index 0000000000..e77ecc9d65 --- /dev/null +++ b/platform/ui/assets/images/layout-advanced-3d-primary.svg @@ -0,0 +1,12 @@ + + + layout-advanced-3d-primary + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/layout-advanced-axial-primary.svg b/platform/ui/assets/images/layout-advanced-axial-primary.svg new file mode 100644 index 0000000000..79a34077a9 --- /dev/null +++ b/platform/ui/assets/images/layout-advanced-axial-primary.svg @@ -0,0 +1,11 @@ + + + layout-advanced-axial-primary + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/layout-advanced-mpr.svg b/platform/ui/assets/images/layout-advanced-mpr.svg new file mode 100644 index 0000000000..d23b2fbf45 --- /dev/null +++ b/platform/ui/assets/images/layout-advanced-mpr.svg @@ -0,0 +1,11 @@ + + + layout-advanced-mpr + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/layout-common-1x1.svg b/platform/ui/assets/images/layout-common-1x1.svg new file mode 100644 index 0000000000..537c7a86cf --- /dev/null +++ b/platform/ui/assets/images/layout-common-1x1.svg @@ -0,0 +1,9 @@ + + + layout-common-1x1 + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/layout-common-1x2.svg b/platform/ui/assets/images/layout-common-1x2.svg new file mode 100644 index 0000000000..db5aca3627 --- /dev/null +++ b/platform/ui/assets/images/layout-common-1x2.svg @@ -0,0 +1,10 @@ + + + layout-common-1x2 + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/layout-common-2x2.svg b/platform/ui/assets/images/layout-common-2x2.svg new file mode 100644 index 0000000000..8dfe00701f --- /dev/null +++ b/platform/ui/assets/images/layout-common-2x2.svg @@ -0,0 +1,11 @@ + + + layout-common-2x2 + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/layout-common-2x3.svg b/platform/ui/assets/images/layout-common-2x3.svg new file mode 100644 index 0000000000..3cb298eec5 --- /dev/null +++ b/platform/ui/assets/images/layout-common-2x3.svg @@ -0,0 +1,12 @@ + + + layout-common-2x3 + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/list-bullets.svg b/platform/ui/assets/images/list-bullets.svg new file mode 100644 index 0000000000..25949de56d --- /dev/null +++ b/platform/ui/assets/images/list-bullets.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/platform/ui/assets/images/loading-ohif-mark.svg b/platform/ui/assets/images/loading-ohif-mark.svg new file mode 100644 index 0000000000..181e275eb1 --- /dev/null +++ b/platform/ui/assets/images/loading-ohif-mark.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/platform/ui/assets/images/lock.svg b/platform/ui/assets/images/lock.svg new file mode 100644 index 0000000000..e3eaf48b68 --- /dev/null +++ b/platform/ui/assets/images/lock.svg @@ -0,0 +1 @@ + diff --git a/platform/ui/assets/images/logo-ohif-small.svg b/platform/ui/assets/images/logo-ohif-small.svg new file mode 100644 index 0000000000..6a8f669f66 --- /dev/null +++ b/platform/ui/assets/images/logo-ohif-small.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/platform/ui/assets/images/magnifier.svg b/platform/ui/assets/images/magnifier.svg new file mode 100644 index 0000000000..7d199db880 --- /dev/null +++ b/platform/ui/assets/images/magnifier.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/platform/ui/assets/images/navigation-panel-right-hide.svg b/platform/ui/assets/images/navigation-panel-right-hide.svg new file mode 100644 index 0000000000..7394397813 --- /dev/null +++ b/platform/ui/assets/images/navigation-panel-right-hide.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/platform/ui/assets/images/navigation-panel-right-reveal.svg b/platform/ui/assets/images/navigation-panel-right-reveal.svg new file mode 100644 index 0000000000..5d5f03544c --- /dev/null +++ b/platform/ui/assets/images/navigation-panel-right-reveal.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/platform/ui/assets/images/next-arrow.svg b/platform/ui/assets/images/next-arrow.svg new file mode 100644 index 0000000000..027a17de37 --- /dev/null +++ b/platform/ui/assets/images/next-arrow.svg @@ -0,0 +1,12 @@ + + + arrow-right + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/notifications-error.svg b/platform/ui/assets/images/notifications-error.svg new file mode 100644 index 0000000000..615d4a2fdb --- /dev/null +++ b/platform/ui/assets/images/notifications-error.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/platform/ui/assets/images/notifications-info.svg b/platform/ui/assets/images/notifications-info.svg new file mode 100644 index 0000000000..c3dd49c07a --- /dev/null +++ b/platform/ui/assets/images/notifications-info.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/platform/ui/assets/images/notifications-success.svg b/platform/ui/assets/images/notifications-success.svg new file mode 100644 index 0000000000..38096d3d79 --- /dev/null +++ b/platform/ui/assets/images/notifications-success.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/ui/assets/images/notifications-warning.svg b/platform/ui/assets/images/notifications-warning.svg new file mode 100644 index 0000000000..a3f435647b --- /dev/null +++ b/platform/ui/assets/images/notifications-warning.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/platform/ui/assets/images/notificationwarning-diamond.svg b/platform/ui/assets/images/notificationwarning-diamond.svg new file mode 100644 index 0000000000..3ab48f2b90 --- /dev/null +++ b/platform/ui/assets/images/notificationwarning-diamond.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/platform/ui/assets/images/ohif-logo-color-darkbg.svg b/platform/ui/assets/images/ohif-logo-color-darkbg.svg new file mode 100644 index 0000000000..5458381274 --- /dev/null +++ b/platform/ui/assets/images/ohif-logo-color-darkbg.svg @@ -0,0 +1,20 @@ + + + ohif-logo-color-darkbg + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/ohif-logo.svg b/platform/ui/assets/images/ohif-logo.svg new file mode 100644 index 0000000000..3692116b41 --- /dev/null +++ b/platform/ui/assets/images/ohif-logo.svg @@ -0,0 +1,18 @@ + + + toolbar-branding-open-health-imaging-foundation + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/old-play.svg b/platform/ui/assets/images/old-play.svg new file mode 100644 index 0000000000..b947e19343 --- /dev/null +++ b/platform/ui/assets/images/old-play.svg @@ -0,0 +1,9 @@ + + Play + + diff --git a/platform/ui/assets/images/old-stop.svg b/platform/ui/assets/images/old-stop.svg new file mode 100644 index 0000000000..264d09a2f8 --- /dev/null +++ b/platform/ui/assets/images/old-stop.svg @@ -0,0 +1,9 @@ + + Stop + + diff --git a/platform/ui/assets/images/old-trash.svg b/platform/ui/assets/images/old-trash.svg new file mode 100644 index 0000000000..f3033a083c --- /dev/null +++ b/platform/ui/assets/images/old-trash.svg @@ -0,0 +1,9 @@ + + Trash + + diff --git a/platform/ui/assets/images/panel-group-more.svg b/platform/ui/assets/images/panel-group-more.svg new file mode 100644 index 0000000000..a8b496e524 --- /dev/null +++ b/platform/ui/assets/images/panel-group-more.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/ui/assets/images/panel-group-open-close.svg b/platform/ui/assets/images/panel-group-open-close.svg new file mode 100644 index 0000000000..5bed02f11a --- /dev/null +++ b/platform/ui/assets/images/panel-group-open-close.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/ui/assets/images/pencil.svg b/platform/ui/assets/images/pencil.svg new file mode 100644 index 0000000000..1b643bfecb --- /dev/null +++ b/platform/ui/assets/images/pencil.svg @@ -0,0 +1,4 @@ + + + diff --git a/platform/ui/assets/images/power-off.svg b/platform/ui/assets/images/power-off.svg new file mode 100644 index 0000000000..3dd5dcf20d --- /dev/null +++ b/platform/ui/assets/images/power-off.svg @@ -0,0 +1,11 @@ + + Power Off + + diff --git a/platform/ui/assets/images/prev-arrow.svg b/platform/ui/assets/images/prev-arrow.svg new file mode 100644 index 0000000000..455afb6bfb --- /dev/null +++ b/platform/ui/assets/images/prev-arrow.svg @@ -0,0 +1,12 @@ + + + arrow-left + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/profile.svg b/platform/ui/assets/images/profile.svg new file mode 100644 index 0000000000..6d07ec81ea --- /dev/null +++ b/platform/ui/assets/images/profile.svg @@ -0,0 +1 @@ + diff --git a/platform/ui/assets/images/push-left.svg b/platform/ui/assets/images/push-left.svg new file mode 100644 index 0000000000..3569a0a406 --- /dev/null +++ b/platform/ui/assets/images/push-left.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/platform/ui/assets/images/push-right.svg b/platform/ui/assets/images/push-right.svg new file mode 100644 index 0000000000..af673fe3a3 --- /dev/null +++ b/platform/ui/assets/images/push-right.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/platform/ui/assets/images/row-add.svg b/platform/ui/assets/images/row-add.svg new file mode 100644 index 0000000000..490ede8bd1 --- /dev/null +++ b/platform/ui/assets/images/row-add.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/platform/ui/assets/images/row-edit.svg b/platform/ui/assets/images/row-edit.svg new file mode 100644 index 0000000000..5195a9628a --- /dev/null +++ b/platform/ui/assets/images/row-edit.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/platform/ui/assets/images/row-hidden.svg b/platform/ui/assets/images/row-hidden.svg new file mode 100644 index 0000000000..fdb63b0788 --- /dev/null +++ b/platform/ui/assets/images/row-hidden.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/platform/ui/assets/images/row-lock.svg b/platform/ui/assets/images/row-lock.svg new file mode 100644 index 0000000000..2cc3780e79 --- /dev/null +++ b/platform/ui/assets/images/row-lock.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/platform/ui/assets/images/row-shown.svg b/platform/ui/assets/images/row-shown.svg new file mode 100644 index 0000000000..de7cef9d62 --- /dev/null +++ b/platform/ui/assets/images/row-shown.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/platform/ui/assets/images/row-unlock.svg b/platform/ui/assets/images/row-unlock.svg new file mode 100644 index 0000000000..ed05e36747 --- /dev/null +++ b/platform/ui/assets/images/row-unlock.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/platform/ui/assets/images/settings.svg b/platform/ui/assets/images/settings.svg new file mode 100644 index 0000000000..a59f13eeb4 --- /dev/null +++ b/platform/ui/assets/images/settings.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/ui/assets/images/side-panel-close-left.svg b/platform/ui/assets/images/side-panel-close-left.svg new file mode 100644 index 0000000000..ef901e0a83 --- /dev/null +++ b/platform/ui/assets/images/side-panel-close-left.svg @@ -0,0 +1,14 @@ + + + icon-panel-close-left + + + + + + + + + + + diff --git a/platform/ui/assets/images/side-panel-close-right.svg b/platform/ui/assets/images/side-panel-close-right.svg new file mode 100644 index 0000000000..d455e2abc2 --- /dev/null +++ b/platform/ui/assets/images/side-panel-close-right.svg @@ -0,0 +1,14 @@ + + + icon-panel-close-right + + + + + + + + + + + diff --git a/platform/ui/assets/images/sorting-active-down.svg b/platform/ui/assets/images/sorting-active-down.svg new file mode 100644 index 0000000000..78ed531021 --- /dev/null +++ b/platform/ui/assets/images/sorting-active-down.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/ui/assets/images/sorting-active-up.svg b/platform/ui/assets/images/sorting-active-up.svg new file mode 100644 index 0000000000..f322f393b5 --- /dev/null +++ b/platform/ui/assets/images/sorting-active-up.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/ui/assets/images/sorting.svg b/platform/ui/assets/images/sorting.svg new file mode 100644 index 0000000000..cdd422f34a --- /dev/null +++ b/platform/ui/assets/images/sorting.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/ui/assets/images/status-alert-warning.svg b/platform/ui/assets/images/status-alert-warning.svg new file mode 100644 index 0000000000..6339753510 --- /dev/null +++ b/platform/ui/assets/images/status-alert-warning.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/platform/ui/assets/images/status-alert.svg b/platform/ui/assets/images/status-alert.svg new file mode 100644 index 0000000000..3a88223e96 --- /dev/null +++ b/platform/ui/assets/images/status-alert.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/platform/ui/assets/images/status-locked.svg b/platform/ui/assets/images/status-locked.svg new file mode 100644 index 0000000000..344ffe329e --- /dev/null +++ b/platform/ui/assets/images/status-locked.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/platform/ui/assets/images/status-tracked.svg b/platform/ui/assets/images/status-tracked.svg new file mode 100644 index 0000000000..549063a496 --- /dev/null +++ b/platform/ui/assets/images/status-tracked.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/platform/ui/assets/images/status-untracked.svg b/platform/ui/assets/images/status-untracked.svg new file mode 100644 index 0000000000..a4186231a1 --- /dev/null +++ b/platform/ui/assets/images/status-untracked.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/ui/assets/images/tab-4d.svg b/platform/ui/assets/images/tab-4d.svg new file mode 100644 index 0000000000..e8eb101c21 --- /dev/null +++ b/platform/ui/assets/images/tab-4d.svg @@ -0,0 +1,13 @@ + + + tab-4d + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tab-linear.svg b/platform/ui/assets/images/tab-linear.svg new file mode 100644 index 0000000000..b03c552963 --- /dev/null +++ b/platform/ui/assets/images/tab-linear.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/platform/ui/assets/images/tab-patient-info.svg b/platform/ui/assets/images/tab-patient-info.svg new file mode 100644 index 0000000000..f74a7d079e --- /dev/null +++ b/platform/ui/assets/images/tab-patient-info.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/platform/ui/assets/images/tab-roi-threshold.svg b/platform/ui/assets/images/tab-roi-threshold.svg new file mode 100644 index 0000000000..2680ceab54 --- /dev/null +++ b/platform/ui/assets/images/tab-roi-threshold.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/platform/ui/assets/images/tab-segmentation.svg b/platform/ui/assets/images/tab-segmentation.svg new file mode 100644 index 0000000000..0a7a3377a2 --- /dev/null +++ b/platform/ui/assets/images/tab-segmentation.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/platform/ui/assets/images/tab-studies.svg b/platform/ui/assets/images/tab-studies.svg new file mode 100644 index 0000000000..7e3e1ce3e3 --- /dev/null +++ b/platform/ui/assets/images/tab-studies.svg @@ -0,0 +1,13 @@ + + + tab-studies + + + + + + + + + + diff --git a/platform/ui/assets/images/tool-3d-rotate.svg b/platform/ui/assets/images/tool-3d-rotate.svg new file mode 100644 index 0000000000..20d190cad1 --- /dev/null +++ b/platform/ui/assets/images/tool-3d-rotate.svg @@ -0,0 +1,20 @@ + + + tool-3d-rotate + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-angle.svg b/platform/ui/assets/images/tool-angle.svg new file mode 100644 index 0000000000..064a1502f8 --- /dev/null +++ b/platform/ui/assets/images/tool-angle.svg @@ -0,0 +1,12 @@ + + + tool-angle + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-annotate.svg b/platform/ui/assets/images/tool-annotate.svg new file mode 100644 index 0000000000..b10a8ad529 --- /dev/null +++ b/platform/ui/assets/images/tool-annotate.svg @@ -0,0 +1,11 @@ + + + tool-annotate + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-bidirectional.svg b/platform/ui/assets/images/tool-bidirectional.svg new file mode 100644 index 0000000000..4f77aa51b8 --- /dev/null +++ b/platform/ui/assets/images/tool-bidirectional.svg @@ -0,0 +1,21 @@ + + + tool-bidirectional + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-calibrate.svg b/platform/ui/assets/images/tool-calibrate.svg new file mode 100644 index 0000000000..7fd8966db6 --- /dev/null +++ b/platform/ui/assets/images/tool-calibrate.svg @@ -0,0 +1,19 @@ + + + tool-calibrate + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-capture.svg b/platform/ui/assets/images/tool-capture.svg new file mode 100644 index 0000000000..391cb892e3 --- /dev/null +++ b/platform/ui/assets/images/tool-capture.svg @@ -0,0 +1,10 @@ + + + tool- + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-cine.svg b/platform/ui/assets/images/tool-cine.svg new file mode 100644 index 0000000000..e3da518d30 --- /dev/null +++ b/platform/ui/assets/images/tool-cine.svg @@ -0,0 +1,9 @@ + + + tool-cine + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-circle.svg b/platform/ui/assets/images/tool-circle.svg new file mode 100644 index 0000000000..011ec55073 --- /dev/null +++ b/platform/ui/assets/images/tool-circle.svg @@ -0,0 +1,8 @@ + + + tool-circle + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-cobb-angle.svg b/platform/ui/assets/images/tool-cobb-angle.svg new file mode 100644 index 0000000000..debb0397b2 --- /dev/null +++ b/platform/ui/assets/images/tool-cobb-angle.svg @@ -0,0 +1,14 @@ + + + tool-cobb-angle + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-create-threshold.svg b/platform/ui/assets/images/tool-create-threshold.svg new file mode 100644 index 0000000000..2385f80739 --- /dev/null +++ b/platform/ui/assets/images/tool-create-threshold.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/platform/ui/assets/images/tool-crosshair.svg b/platform/ui/assets/images/tool-crosshair.svg new file mode 100644 index 0000000000..ebbd617f25 --- /dev/null +++ b/platform/ui/assets/images/tool-crosshair.svg @@ -0,0 +1,14 @@ + + + tool-crosshair + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-dicom-tag-browser.svg b/platform/ui/assets/images/tool-dicom-tag-browser.svg new file mode 100644 index 0000000000..f87608015b --- /dev/null +++ b/platform/ui/assets/images/tool-dicom-tag-browser.svg @@ -0,0 +1,15 @@ + + + tool-dicom-tag-browser + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-flip-horizontal.svg b/platform/ui/assets/images/tool-flip-horizontal.svg new file mode 100644 index 0000000000..f3ab15fe54 --- /dev/null +++ b/platform/ui/assets/images/tool-flip-horizontal.svg @@ -0,0 +1,10 @@ + + + tool-flip-horizontal + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-freehand-polygon.svg b/platform/ui/assets/images/tool-freehand-polygon.svg new file mode 100644 index 0000000000..bfc1b0dcd5 --- /dev/null +++ b/platform/ui/assets/images/tool-freehand-polygon.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/platform/ui/assets/images/tool-freehand-roi.svg b/platform/ui/assets/images/tool-freehand-roi.svg new file mode 100644 index 0000000000..42160326ed --- /dev/null +++ b/platform/ui/assets/images/tool-freehand-roi.svg @@ -0,0 +1,12 @@ + + + tool-freehand-roi + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-freehand.svg b/platform/ui/assets/images/tool-freehand.svg new file mode 100644 index 0000000000..2159f91505 --- /dev/null +++ b/platform/ui/assets/images/tool-freehand.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/platform/ui/assets/images/tool-fusion-color.svg b/platform/ui/assets/images/tool-fusion-color.svg new file mode 100644 index 0000000000..a09783d8c1 --- /dev/null +++ b/platform/ui/assets/images/tool-fusion-color.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/platform/ui/assets/images/tool-invert.svg b/platform/ui/assets/images/tool-invert.svg new file mode 100644 index 0000000000..9b5047ca29 --- /dev/null +++ b/platform/ui/assets/images/tool-invert.svg @@ -0,0 +1,10 @@ + + + tool-invert + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-layout-default.svg b/platform/ui/assets/images/tool-layout-default.svg new file mode 100644 index 0000000000..2ebbcabc6f --- /dev/null +++ b/platform/ui/assets/images/tool-layout-default.svg @@ -0,0 +1,22 @@ + + + tool-layout + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-length.svg b/platform/ui/assets/images/tool-length.svg new file mode 100644 index 0000000000..5ede3069da --- /dev/null +++ b/platform/ui/assets/images/tool-length.svg @@ -0,0 +1,16 @@ + + + tool-length + + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-magnetic-roi.svg b/platform/ui/assets/images/tool-magnetic-roi.svg new file mode 100644 index 0000000000..fbcb25bce2 --- /dev/null +++ b/platform/ui/assets/images/tool-magnetic-roi.svg @@ -0,0 +1,17 @@ + + + tool-livewire + + + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-magnify.svg b/platform/ui/assets/images/tool-magnify.svg new file mode 100644 index 0000000000..cb3ad1e612 --- /dev/null +++ b/platform/ui/assets/images/tool-magnify.svg @@ -0,0 +1,7 @@ + + + tool-magnify-area + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-measure-elipse.svg b/platform/ui/assets/images/tool-measure-elipse.svg new file mode 100644 index 0000000000..5198db687a --- /dev/null +++ b/platform/ui/assets/images/tool-measure-elipse.svg @@ -0,0 +1,12 @@ + + + tool-measure-elipse + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-more-menu.svg b/platform/ui/assets/images/tool-more-menu.svg new file mode 100644 index 0000000000..4ae8ca6944 --- /dev/null +++ b/platform/ui/assets/images/tool-more-menu.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/ui/assets/images/tool-move.svg b/platform/ui/assets/images/tool-move.svg new file mode 100644 index 0000000000..411e95194e --- /dev/null +++ b/platform/ui/assets/images/tool-move.svg @@ -0,0 +1,13 @@ + + + tool-move + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-polygon.svg b/platform/ui/assets/images/tool-polygon.svg new file mode 100644 index 0000000000..ff2f9e0299 --- /dev/null +++ b/platform/ui/assets/images/tool-polygon.svg @@ -0,0 +1,3 @@ + + + diff --git a/platform/ui/assets/images/tool-quick-magnify.svg b/platform/ui/assets/images/tool-quick-magnify.svg new file mode 100644 index 0000000000..7a4766a7e7 --- /dev/null +++ b/platform/ui/assets/images/tool-quick-magnify.svg @@ -0,0 +1,11 @@ + + + tool-zoom-in + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-rectangle.svg b/platform/ui/assets/images/tool-rectangle.svg new file mode 100644 index 0000000000..d534c8ad5c --- /dev/null +++ b/platform/ui/assets/images/tool-rectangle.svg @@ -0,0 +1,12 @@ + + + tool-rectangle + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-reference-lines.svg b/platform/ui/assets/images/tool-reference-lines.svg new file mode 100644 index 0000000000..6329d81cbc --- /dev/null +++ b/platform/ui/assets/images/tool-reference-lines.svg @@ -0,0 +1,13 @@ + + + tool-reference-lines + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-reset.svg b/platform/ui/assets/images/tool-reset.svg new file mode 100644 index 0000000000..5c6d49fe4c --- /dev/null +++ b/platform/ui/assets/images/tool-reset.svg @@ -0,0 +1,9 @@ + + + tool-reset + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-rotate-right.svg b/platform/ui/assets/images/tool-rotate-right.svg new file mode 100644 index 0000000000..7ee9942197 --- /dev/null +++ b/platform/ui/assets/images/tool-rotate-right.svg @@ -0,0 +1,12 @@ + + + tool-rotate-right + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-seg-brush.svg b/platform/ui/assets/images/tool-seg-brush.svg new file mode 100644 index 0000000000..2258260d96 --- /dev/null +++ b/platform/ui/assets/images/tool-seg-brush.svg @@ -0,0 +1,9 @@ + + + tool-seg-brush + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-seg-eraser.svg b/platform/ui/assets/images/tool-seg-eraser.svg new file mode 100644 index 0000000000..a1f78fed4e --- /dev/null +++ b/platform/ui/assets/images/tool-seg-eraser.svg @@ -0,0 +1,10 @@ + + + tool-seg-eraser + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-seg-shape.svg b/platform/ui/assets/images/tool-seg-shape.svg new file mode 100644 index 0000000000..290d156e6c --- /dev/null +++ b/platform/ui/assets/images/tool-seg-shape.svg @@ -0,0 +1,9 @@ + + + tool-seg-shape + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-seg-threshold.svg b/platform/ui/assets/images/tool-seg-threshold.svg new file mode 100644 index 0000000000..4870fa5a49 --- /dev/null +++ b/platform/ui/assets/images/tool-seg-threshold.svg @@ -0,0 +1,17 @@ + + + tool-seg-threshold + + + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-spline-roi.svg b/platform/ui/assets/images/tool-spline-roi.svg new file mode 100644 index 0000000000..9266c536c3 --- /dev/null +++ b/platform/ui/assets/images/tool-spline-roi.svg @@ -0,0 +1,14 @@ + + + tool-spline-roi + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-stack-image-sync.svg b/platform/ui/assets/images/tool-stack-image-sync.svg new file mode 100644 index 0000000000..d09d4861b8 --- /dev/null +++ b/platform/ui/assets/images/tool-stack-image-sync.svg @@ -0,0 +1,10 @@ + + + tool-stack-image-sync + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-stack-scroll.svg b/platform/ui/assets/images/tool-stack-scroll.svg new file mode 100644 index 0000000000..795da7701d --- /dev/null +++ b/platform/ui/assets/images/tool-stack-scroll.svg @@ -0,0 +1,10 @@ + + + tool-stack-scroll + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-toggle-dicom-overlay.svg b/platform/ui/assets/images/tool-toggle-dicom-overlay.svg new file mode 100644 index 0000000000..6cd55e57a4 --- /dev/null +++ b/platform/ui/assets/images/tool-toggle-dicom-overlay.svg @@ -0,0 +1,9 @@ + + + tool-toggle-dicom-overlay + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-ultrasound-bidirectional.svg b/platform/ui/assets/images/tool-ultrasound-bidirectional.svg new file mode 100644 index 0000000000..8ec735b1aa --- /dev/null +++ b/platform/ui/assets/images/tool-ultrasound-bidirectional.svg @@ -0,0 +1,15 @@ + + + tool-ultrasound-bidirectional + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-window-level.svg b/platform/ui/assets/images/tool-window-level.svg new file mode 100644 index 0000000000..fd63f1b6ea --- /dev/null +++ b/platform/ui/assets/images/tool-window-level.svg @@ -0,0 +1,9 @@ + + + tool-window-level + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-window-region.svg b/platform/ui/assets/images/tool-window-region.svg new file mode 100644 index 0000000000..29230e82cc --- /dev/null +++ b/platform/ui/assets/images/tool-window-region.svg @@ -0,0 +1,12 @@ + + + tool-window-region + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tool-zoom.svg b/platform/ui/assets/images/tool-zoom.svg new file mode 100644 index 0000000000..c6fbfebc60 --- /dev/null +++ b/platform/ui/assets/images/tool-zoom.svg @@ -0,0 +1,9 @@ + + + tool-zoom + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/tracked.svg b/platform/ui/assets/images/tracked.svg new file mode 100644 index 0000000000..a45ac3e51c --- /dev/null +++ b/platform/ui/assets/images/tracked.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/ui/assets/images/ui-arrow-down.svg b/platform/ui/assets/images/ui-arrow-down.svg new file mode 100644 index 0000000000..de013233ef --- /dev/null +++ b/platform/ui/assets/images/ui-arrow-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/platform/ui/assets/images/ui-arrow-left.svg b/platform/ui/assets/images/ui-arrow-left.svg new file mode 100644 index 0000000000..43bd4ace4f --- /dev/null +++ b/platform/ui/assets/images/ui-arrow-left.svg @@ -0,0 +1,3 @@ + + + diff --git a/platform/ui/assets/images/ui-arrow-right.svg b/platform/ui/assets/images/ui-arrow-right.svg new file mode 100644 index 0000000000..756a9e2cd7 --- /dev/null +++ b/platform/ui/assets/images/ui-arrow-right.svg @@ -0,0 +1,3 @@ + + + diff --git a/platform/ui/assets/images/ui-arrow-up.svg b/platform/ui/assets/images/ui-arrow-up.svg new file mode 100644 index 0000000000..9a6aa6014d --- /dev/null +++ b/platform/ui/assets/images/ui-arrow-up.svg @@ -0,0 +1,3 @@ + + + diff --git a/platform/ui/assets/images/unlink.svg b/platform/ui/assets/images/unlink.svg new file mode 100644 index 0000000000..ed9526b7f4 --- /dev/null +++ b/platform/ui/assets/images/unlink.svg @@ -0,0 +1,9 @@ + + Unlink + + diff --git a/platform/ui/assets/images/viewport-status-tracked.svg b/platform/ui/assets/images/viewport-status-tracked.svg new file mode 100644 index 0000000000..68185761a8 --- /dev/null +++ b/platform/ui/assets/images/viewport-status-tracked.svg @@ -0,0 +1,13 @@ + + + viewport-status-tracfked + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/assets/images/viewport-window-level.svg b/platform/ui/assets/images/viewport-window-level.svg new file mode 100644 index 0000000000..ce0a562b2f --- /dev/null +++ b/platform/ui/assets/images/viewport-window-level.svg @@ -0,0 +1,17 @@ + + + viewport-window-level + + + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/jest.config.js b/platform/ui/jest.config.js index 2978b062ed..f57711b3f5 100644 --- a/platform/ui/jest.config.js +++ b/platform/ui/jest.config.js @@ -3,7 +3,6 @@ const pkg = require('./package'); module.exports = { ...base, - name: pkg.name, displayName: pkg.name, // rootDir: "../.." // testMatch: [ diff --git a/platform/ui/package.json b/platform/ui/package.json index c0d98aed9e..c897e2e72f 100644 --- a/platform/ui/package.json +++ b/platform/ui/package.json @@ -1,6 +1,6 @@ { "name": "@ohif/ui", - "version": "3.8.0-beta.82", + "version": "3.9.0-beta.71", "description": "A set of React components for Medical Imaging Viewers", "author": "OHIF Contributors", "license": "MIT", @@ -29,11 +29,11 @@ "build-storybook": "storybook build" }, "peerDependencies": { - "react": "17.0.2", - "react-dom": "17.0.2" + "react": "^18.3.1", + "react-dom": "^18.3.1" }, "dependencies": { - "@testing-library/react-hooks": "^3.2.1", + "@testing-library/react": "^13.1.0", "browser-detect": "^0.2.28", "classnames": "^2.3.2", "d3-array": "3", @@ -44,26 +44,26 @@ "d3-shape": "3", "d3-zoom": "3", "lodash.debounce": "4.0.8", - "moment": "2.29.4", + "moment": "*", "mousetrap": "^1.6.5", - "react": "^17.0.2", + "react": "^18.3.1", "react-dates": "^21.8.0", "react-dnd": "14.0.2", "react-dnd-html5-backend": "14.0.0", - "react-dom": "^17.0.2", - "react-draggable": "4.4.3", + "react-dom": "^18.3.1", + "react-draggable": "^4.4.6", "react-error-boundary": "^3.1.3", "react-modal": "3.11.2", "react-outside-click-handler": "^1.3.0", "react-select": "5.7.4", - "react-test-renderer": "^16.12.0", + "react-test-renderer": "^18.3.1", "react-window": "^1.8.9", "react-with-direction": "^1.3.1", "swiper": "^8.4.2", - "webpack": "^5.81.0" + "webpack": "5.89.0" }, "devDependencies": { - "@babel/core": "^7.23.2", + "@babel/core": "7.24.7", "@storybook/addon-actions": "^7.6.10", "@storybook/addon-docs": "^7.6.10", "@storybook/addon-essentials": "^7.6.10", diff --git a/platform/ui/src/assets/icons/database.svg b/platform/ui/src/assets/icons/database.svg new file mode 100644 index 0000000000..79fd60ef69 --- /dev/null +++ b/platform/ui/src/assets/icons/database.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/platform/ui/src/assets/icons/ohif-logo-color-darkbg.svg b/platform/ui/src/assets/icons/ohif-logo-color-darkbg.svg new file mode 100644 index 0000000000..5458381274 --- /dev/null +++ b/platform/ui/src/assets/icons/ohif-logo-color-darkbg.svg @@ -0,0 +1,20 @@ + + + ohif-logo-color-darkbg + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/tab-4d.svg b/platform/ui/src/assets/icons/tab-4d.svg new file mode 100644 index 0000000000..e8eb101c21 --- /dev/null +++ b/platform/ui/src/assets/icons/tab-4d.svg @@ -0,0 +1,13 @@ + + + tab-4d + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/tool-cobb-angle.svg b/platform/ui/src/assets/icons/tool-cobb-angle.svg new file mode 100644 index 0000000000..debb0397b2 --- /dev/null +++ b/platform/ui/src/assets/icons/tool-cobb-angle.svg @@ -0,0 +1,14 @@ + + + tool-cobb-angle + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/tool-window-region.svg b/platform/ui/src/assets/icons/tool-window-region.svg new file mode 100644 index 0000000000..29230e82cc --- /dev/null +++ b/platform/ui/src/assets/icons/tool-window-region.svg @@ -0,0 +1,12 @@ + + + tool-window-region + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/src/components/ActionButtons/ActionButtons.tsx b/platform/ui/src/components/ActionButtons/ActionButtons.tsx index ae58b985b8..0e7bd33b5e 100644 --- a/platform/ui/src/components/ActionButtons/ActionButtons.tsx +++ b/platform/ui/src/components/ActionButtons/ActionButtons.tsx @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import { Button, ButtonEnums } from '../../components'; -function ActionButtons({ actions, disabled, t }) { +function ActionButtons({ actions, disabled = false, t }) { return ( {actions.map((action, index) => ( @@ -33,8 +33,4 @@ ActionButtons.propTypes = { disabled: PropTypes.bool, }; -ActionButtons.defaultProps = { - disabled: false, -}; - export default ActionButtons; diff --git a/platform/ui/src/components/AdvancedToolbox/ToolSettings.tsx b/platform/ui/src/components/AdvancedToolbox/ToolSettings.tsx index 26b20b89de..0d5d339b5c 100644 --- a/platform/ui/src/components/AdvancedToolbox/ToolSettings.tsx +++ b/platform/ui/src/components/AdvancedToolbox/ToolSettings.tsx @@ -86,6 +86,7 @@ const renderRadioSetting = option => { {option.name}
value === option.value) || 0} > {renderButtons(option)} @@ -102,7 +103,7 @@ const renderDoubleRangeSetting = option => { key={option.id} > {}, dataCY, startIconTooltip = null, endIconTooltip = null, @@ -121,14 +121,6 @@ const Button = ({ ); }; -Button.defaultProps = { - disabled: false, - children: '', - onClick: () => {}, - type: defaults.type, - size: defaults.size, -}; - Button.propTypes = { /** What is inside the button, can be text or react component */ children: PropTypes.node, diff --git a/platform/ui/src/components/CinePlayer/CinePlayer.tsx b/platform/ui/src/components/CinePlayer/CinePlayer.tsx index a628754ccd..1a4024e9df 100644 --- a/platform/ui/src/components/CinePlayer/CinePlayer.tsx +++ b/platform/ui/src/components/CinePlayer/CinePlayer.tsx @@ -31,15 +31,15 @@ const fpsButtonClassNames = const CinePlayer: React.FC = ({ className, - isPlaying, - minFrameRate, - maxFrameRate, - stepFrameRate, - frameRate: defaultFrameRate, + isPlaying = false, + minFrameRate = 1, + maxFrameRate = 90, + stepFrameRate = 1, + frameRate: defaultFrameRate = 24, + onFrameRateChange = () => {}, + onPlayPauseChange = () => {}, + onClose = () => {}, dynamicInfo = {}, - onFrameRateChange, - onPlayPauseChange, - onClose, updateDynamicInfo, }) => { const isDynamic = !!dynamicInfo?.numTimePoints; @@ -163,21 +163,6 @@ const CinePlayer: React.FC = ({ ); }; -const noop = () => {}; - -CinePlayer.defaultProps = { - isPlaying: false, - minFrameRate: 1, - maxFrameRate: 90, - stepFrameRate: 1, - frameRate: 24, - onPlayPauseChange: noop, - onFrameRateChange: noop, - onClose: noop, - isDynamic: false, - dynamicInfo: {}, -}; - CinePlayer.propTypes = { /** Minimum value for range slider */ minFrameRate: PropTypes.number, diff --git a/platform/ui/src/components/DateRange/DateRange.tsx b/platform/ui/src/components/DateRange/DateRange.tsx index b93016731d..bfca06ac30 100644 --- a/platform/ui/src/components/DateRange/DateRange.tsx +++ b/platform/ui/src/components/DateRange/DateRange.tsx @@ -29,7 +29,7 @@ const renderYearsOptions = () => { }; const DateRange = props => { - const { id, onChange, startDate, endDate } = props; + const { id = '', onChange, startDate = null, endDate = null } = props; const [focusedInput, setFocusedInput] = useState(null); const renderYearsOptionsCallback = useCallback(renderYearsOptions, []); const { t } = useTranslation('DatePicker'); @@ -165,12 +165,6 @@ const DateRange = props => { ); }; -DateRange.defaultProps = { - id: '', - startDate: null, - endDate: null, -}; - DateRange.propTypes = { id: PropTypes.string, /** YYYYMMDD (19921022) */ diff --git a/platform/ui/src/components/Dialog/Dialog.tsx b/platform/ui/src/components/Dialog/Dialog.tsx index 8de63a1a2c..faa2bd504b 100644 --- a/platform/ui/src/components/Dialog/Dialog.tsx +++ b/platform/ui/src/components/Dialog/Dialog.tsx @@ -15,10 +15,10 @@ const Dialog = ({ actions, onShow, onSubmit, - header: HeaderComponent, - body: BodyComponent, - footer: FooterComponent, - value: defaultValue, + header: HeaderComponent = Header, + body: BodyComponent = Body, + footer: FooterComponent = Footer, + value: defaultValue = {}, }) => { const [value, setValue] = useState(defaultValue); @@ -78,13 +78,7 @@ Dialog.propTypes = { type: PropTypes.oneOf(['primary', 'secondary', 'cancel']).isRequired, }) ).isRequired, -}; - -Dialog.defaultProps = { - header: Header, - footer: Footer, - body: Body, - value: {}, + onShow: PropTypes.func, }; export default Dialog; diff --git a/platform/ui/src/components/Dialog/Footer.tsx b/platform/ui/src/components/Dialog/Footer.tsx index e67a144849..c369df95b3 100644 --- a/platform/ui/src/components/Dialog/Footer.tsx +++ b/platform/ui/src/components/Dialog/Footer.tsx @@ -4,7 +4,7 @@ import PropTypes from 'prop-types'; import Button, { ButtonEnums } from '../Button'; -const Footer = ({ actions, className, onSubmit, value }) => { +const Footer = ({ actions = [], className, onSubmit = () => {}, value }) => { const flex = 'flex items-center justify-end'; const padding = 'pt-[20px]'; @@ -47,9 +47,4 @@ Footer.propTypes = { ).isRequired, }; -Footer.defaultProps = { - onSubmit: noop, - actions: [], -}; - export default Footer; diff --git a/platform/ui/src/components/Dialog/Header.tsx b/platform/ui/src/components/Dialog/Header.tsx index d3bfb906ea..24831c92a9 100644 --- a/platform/ui/src/components/Dialog/Header.tsx +++ b/platform/ui/src/components/Dialog/Header.tsx @@ -20,7 +20,7 @@ CloseButton.propTypes = { onClick: PropTypes.func, }; -const Header = ({ title, noCloseButton, onClose }) => { +const Header = ({ title, noCloseButton = false, onClose }) => { const theme = 'bg-primary-dark'; const flex = 'flex items-center justify-between'; const padding = 'pb-[20px]'; @@ -46,8 +46,4 @@ Header.propTypes = { onClose: PropTypes.func, }; -Header.defaultProps = { - noCloseButton: false, -}; - export default Header; diff --git a/platform/ui/src/components/Dropdown/Dropdown.tsx b/platform/ui/src/components/Dropdown/Dropdown.tsx index 2e9a441445..c183ddc934 100644 --- a/platform/ui/src/components/Dropdown/Dropdown.tsx +++ b/platform/ui/src/components/Dropdown/Dropdown.tsx @@ -11,15 +11,15 @@ const borderStyle = 'border-b last:border-b-0 border-secondary-main'; const Dropdown = ({ id, children, - showDropdownIcon, + showDropdownIcon = true, list, itemsClassName, titleClassName, - showBorders, + showBorders = true, alignment, // By default the max characters per line is the longest title // if you wish to override this, you can pass in a number - maxCharactersPerLine, + maxCharactersPerLine = 20, }) => { const [open, setOpen] = useState(false); const elementRef = useRef(null); @@ -199,11 +199,6 @@ const Dropdown = ({
); }; -Dropdown.defaultProps = { - showDropdownIcon: true, - maxCharactersPerLine: 20, - showBorders: true, -}; Dropdown.propTypes = { id: PropTypes.string, diff --git a/platform/ui/src/components/EmptyStudies/EmptyStudies.tsx b/platform/ui/src/components/EmptyStudies/EmptyStudies.tsx index 091d98e443..5ea1ea24b4 100644 --- a/platform/ui/src/components/EmptyStudies/EmptyStudies.tsx +++ b/platform/ui/src/components/EmptyStudies/EmptyStudies.tsx @@ -7,7 +7,7 @@ import Icon from '../Icon'; import Typography from '../Typography'; // TODO: Add loading spinner to OHIF + use it here. -const EmptyStudies = ({ className }) => { +const EmptyStudies = ({ className = '' }) => { const { t } = useTranslation('StudyList'); return (
@@ -25,10 +25,6 @@ const EmptyStudies = ({ className }) => { ); }; -EmptyStudies.defaultProps = { - className: '', -}; - EmptyStudies.propTypes = { className: PropTypes.string, }; diff --git a/platform/ui/src/components/ErrorBoundary/ErrorBoundary.tsx b/platform/ui/src/components/ErrorBoundary/ErrorBoundary.tsx index df87cce97c..6fccb97b9f 100644 --- a/platform/ui/src/components/ErrorBoundary/ErrorBoundary.tsx +++ b/platform/ui/src/components/ErrorBoundary/ErrorBoundary.tsx @@ -10,7 +10,7 @@ import IconButton from '../IconButton'; const isProduction = process.env.NODE_ENV === 'production'; -const DefaultFallback = ({ error, context, resetErrorBoundary, fallbackRoute }) => { +const DefaultFallback = ({ error, context, resetErrorBoundary = () => {}, fallbackRoute }) => { const { t } = useTranslation('ErrorBoundary'); const [showDetails, setShowDetails] = useState(false); const title = `${t('Something went wrong')}${!isProduction && ` ${t('in')} ${context}`}.`; @@ -57,25 +57,19 @@ const DefaultFallback = ({ error, context, resetErrorBoundary, fallbackRoute }) ); }; -const noop = () => {}; - DefaultFallback.propTypes = { error: PropTypes.object.isRequired, resetErrorBoundary: PropTypes.func, componentStack: PropTypes.string, }; -DefaultFallback.defaultProps = { - resetErrorBoundary: noop, -}; - const ErrorBoundary = ({ - context, - onReset, - onError, - fallbackComponent: FallbackComponent, + context = 'OHIF', + onReset = () => {}, + onError = () => {}, + fallbackComponent: FallbackComponent = DefaultFallback, children, - fallbackRoute, + fallbackRoute = null, isPage, }) => { const [isOpen, setIsOpen] = useState(true); @@ -132,12 +126,4 @@ ErrorBoundary.propTypes = { fallbackRoute: PropTypes.string, }; -ErrorBoundary.defaultProps = { - context: 'OHIF', - onReset: noop, - onError: noop, - fallbackComponent: DefaultFallback, - fallbackRoute: null, -}; - export default ErrorBoundary; diff --git a/platform/ui/src/components/ExpandableToolbarButton/ExpandableToolbarButton.tsx b/platform/ui/src/components/ExpandableToolbarButton/ExpandableToolbarButton.tsx index ece6256287..320b70074f 100644 --- a/platform/ui/src/components/ExpandableToolbarButton/ExpandableToolbarButton.tsx +++ b/platform/ui/src/components/ExpandableToolbarButton/ExpandableToolbarButton.tsx @@ -8,14 +8,14 @@ import Icon from '../Icon'; import './ExpandableToolbarButton.css'; const ExpandableToolbarButton = ({ - type, - id, - isActive, - onClick, - icon, + type = 'primary', + id = '', + isActive = false, + onClick = () => {}, + icon = 'clipboard', className, - content: Content, - contentProps, + content: Content = null, + contentProps = {}, }) => { const classes = { type: { @@ -71,15 +71,6 @@ const ExpandableToolbarButton = ({ const noop = () => {}; -ExpandableToolbarButton.defaultProps = { - id: '', - icon: 'clipboard', - isActive: false, - type: 'primary', - content: null, - onClick: noop, -}; - ExpandableToolbarButton.propTypes = { /* Influences background/hover styling */ type: PropTypes.oneOf(['primary', 'secondary']), diff --git a/platform/ui/src/components/Header/Header.tsx b/platform/ui/src/components/Header/Header.tsx index c75dfa9231..7472d652ce 100644 --- a/platform/ui/src/components/Header/Header.tsx +++ b/platform/ui/src/components/Header/Header.tsx @@ -14,16 +14,16 @@ import { PatientInfoVisibility } from '../../types/PatientInfoVisibility'; function Header({ children, menuOptions, - isReturnEnabled, + isReturnEnabled = true, onClickReturnButton, - isSticky, + isSticky = false, WhiteLabeling, showPatientInfo = PatientInfoVisibility.VISIBLE_COLLAPSED, servicesManager, Secondary, appConfig, ...props -}): ReactNode { +}: withAppTypes): ReactNode { const { t } = useTranslation('Header'); // TODO: this should be passed in as a prop instead and the react-router-dom @@ -113,9 +113,4 @@ Header.propTypes = { servicesManager: PropTypes.object, }; -Header.defaultProps = { - isReturnEnabled: true, - isSticky: false, -}; - export default Header; diff --git a/platform/ui/src/components/HeaderPatientInfo/HeaderPatientInfo.tsx b/platform/ui/src/components/HeaderPatientInfo/HeaderPatientInfo.tsx index 8c545d8989..7e7de4d238 100644 --- a/platform/ui/src/components/HeaderPatientInfo/HeaderPatientInfo.tsx +++ b/platform/ui/src/components/HeaderPatientInfo/HeaderPatientInfo.tsx @@ -13,7 +13,7 @@ const formatWithEllipsis = (str, maxLength) => { return str; }; -function usePatientInfo(servicesManager) { +function usePatientInfo(servicesManager: AppTypes.ServicesManager) { const { displaySetService } = servicesManager.services; const [patientInfo, setPatientInfo] = useState({ @@ -47,12 +47,12 @@ function usePatientInfo(servicesManager) { return; } setPatientInfo({ - PatientID: instance.PatientID || '', - PatientName: instance.PatientName ? formatPN(instance.PatientName.Alphabetic) : '', - PatientSex: instance.PatientSex || '', - PatientDOB: formatDate(instance.PatientBirthDate) || '', + PatientID: instance.PatientID || null, + PatientName: instance.PatientName ? formatPN(instance.PatientName.Alphabetic) : null, + PatientSex: instance.PatientSex || null, + PatientDOB: formatDate(instance.PatientBirthDate) || null, }); - checkMixedPatients(instance.PatientID || ''); + checkMixedPatients(instance.PatientID || null); }; useEffect(() => { @@ -70,7 +70,7 @@ function usePatientInfo(servicesManager) { return { patientInfo, isMixedPatients }; } -function HeaderPatientInfo({ servicesManager, appConfig }) { +function HeaderPatientInfo({ servicesManager, appConfig }: withAppTypes) { const initialExpandedState = appConfig.showPatientInfo === PatientInfoVisibility.VISIBLE || appConfig.showPatientInfo === PatientInfoVisibility.VISIBLE_READONLY; diff --git a/platform/ui/src/components/HotkeyField/HotkeyField.tsx b/platform/ui/src/components/HotkeyField/HotkeyField.tsx index 81e0b8824b..4283dcf328 100644 --- a/platform/ui/src/components/HotkeyField/HotkeyField.tsx +++ b/platform/ui/src/components/HotkeyField/HotkeyField.tsx @@ -15,7 +15,7 @@ import { getKeys, formatKeysForInput } from './utils'; * @param {string} props.className input classes * @param {Array[]} props.modifierKeys */ -const HotkeyField = ({ disabled, keys, onChange, className, modifierKeys, hotkeys }) => { +const HotkeyField = ({ disabled = false, keys, onChange, className, modifierKeys, hotkeys }) => { const inputValue = formatKeysForInput(keys); const onInputKeyDown = event => { @@ -58,8 +58,4 @@ HotkeyField.propTypes = { }).isRequired, }; -HotkeyField.defaultProps = { - disabled: false, -}; - export default HotkeyField; diff --git a/platform/ui/src/components/HotkeysPreferences/HotkeysPreferences.tsx b/platform/ui/src/components/HotkeysPreferences/HotkeysPreferences.tsx index 2b9b1eb02d..7758546e76 100644 --- a/platform/ui/src/components/HotkeysPreferences/HotkeysPreferences.tsx +++ b/platform/ui/src/components/HotkeysPreferences/HotkeysPreferences.tsx @@ -11,10 +11,10 @@ import { MODIFIER_KEYS } from './hotkeysConfig'; import { validate, splitHotkeyDefinitionsAndCreateTuples } from './utils'; const HotkeysPreferences = ({ - disabled, + disabled = false, hotkeyDefinitions, errors: controlledErrors, - onChange, + onChange = () => {}, hotkeysModule, }) => { const { t } = useTranslation('UserPreferencesModal'); @@ -127,8 +127,6 @@ const HotkeysPreferences = ({ ); }; -const noop = () => {}; - HotkeysPreferences.propTypes = { onChange: PropTypes.func, disabled: PropTypes.bool, @@ -142,9 +140,4 @@ HotkeysPreferences.propTypes = { }).isRequired, }; -HotkeysPreferences.defaultProps = { - onChange: noop, - disabled: false, -}; - export default HotkeysPreferences; diff --git a/platform/ui/src/components/Icon/getIcon.js b/platform/ui/src/components/Icon/getIcon.js index 494b8ce3bf..1413d25287 100644 --- a/platform/ui/src/components/Icon/getIcon.js +++ b/platform/ui/src/components/Icon/getIcon.js @@ -1,178 +1,182 @@ import React from 'react'; -// Icons -import arrowDown from './../../assets/icons/arrow-down.svg'; -import arrowLeft from './../../assets/icons/arrow-left.svg'; -import arrowRight from './../../assets/icons/arrow-right.svg'; -import arrowLeftSmall from './../../assets/icons/arrow-left-small.svg'; -import arrowRightSmall from './../../assets/icons/arrow-right-small.svg'; -import calendar from './../../assets/icons/calendar.svg'; -import cancel from './../../assets/icons/cancel.svg'; -import clipboard from './../../assets/icons/clipboard.svg'; -import close from './../../assets/icons/closeIcon.svg'; -import dottedCircle from './../../assets/icons/dotted-circle.svg'; -import circledCheckmark from './../../assets/icons/circled-checkmark.svg'; -import chevronDown from './../../assets/icons/chevron-down.svg'; -import chevronLeft from './../../assets/icons/chevron-left.svg'; -import chevronMenu from './../../assets/icons/chevron-menu.svg'; -import chevronNext from './../../assets/icons/chevron-next.svg'; -import chevronPrev from './../../assets/icons/chevron-prev.svg'; -import chevronRight from './../../assets/icons/chevron-right.svg'; -import contentNext from './../../assets/icons/content-next.svg'; -import contentPrev from './../../assets/icons/content-prev.svg'; -import eyeVisible from './../../assets/icons/eye-visible.svg'; -import eyeHidden from './../../assets/icons/eye-hidden.svg'; -import exclamation from './../../assets/icons/exclamation.svg'; -import externalLink from './../../assets/icons/external-link.svg'; -import groupLayers from './../../assets/icons/group-layers.svg'; -import info from './../../assets/icons/info.svg'; -import infoAction from './../../assets/icons/info-action.svg'; -import infoLink from './../../assets/icons/info-link.svg'; -import launchArrow from './../../assets/icons/launch-arrow.svg'; -import launchInfo from './../../assets/icons/launch-info.svg'; -import link from './../../assets/icons/tool-stack-image-sync.svg'; -import listBullets from './../../assets/icons/list-bullets.svg'; -import lock from './../../assets/icons/lock.svg'; -import logoOhifSmall from './../../assets/icons/logo-ohif-small.svg'; -import magnifier from './../../assets/icons/magnifier.svg'; -import notificationwarningDiamond from './../../assets/icons/notificationwarning-diamond.svg'; -import pencil from './../../assets/icons/pencil.svg'; -import powerOff from './../../assets/icons/power-off.svg'; -import profile from './../../assets/icons/profile.svg'; -import pushLeft from './../../assets/icons/push-left.svg'; -import pushRight from './../../assets/icons/push-right.svg'; -import settings from './../../assets/icons/settings.svg'; -import sidePanelCloseLeft from './../../assets/icons/side-panel-close-left.svg'; -import sidePanelCloseRight from './../../assets/icons/side-panel-close-right.svg'; -import sorting from './../../assets/icons/sorting.svg'; -import sortingActiveDown from './../../assets/icons/sorting-active-down.svg'; -import sortingActiveUp from './../../assets/icons/sorting-active-up.svg'; -import statusAlertWarning from './../../assets/icons/status-alert-warning.svg'; -import statusAlert from './../../assets/icons/status-alert.svg'; -import statusLocked from './../../assets/icons/status-locked.svg'; -import statusTracked from './../../assets/icons/status-tracked.svg'; -import statusUntracked from './../../assets/icons/status-untracked.svg'; -import tracked from './../../assets/icons/tracked.svg'; -import unlink from './../../assets/icons/unlink.svg'; -import checkboxChecked from './../../assets/icons/checkbox-checked.svg'; -import checkboxUnchecked from './../../assets/icons/checkbox-unchecked.svg'; -import iconAlertOutline from './../../assets/icons/icons-alert-outline.svg'; -import iconAlertSmall from './../../assets/icons/icon-alert-small.svg'; -import iconClose from './../../assets/icons/icon-close.svg'; -import iconClearField from './../../assets/icons/icon-clear-field.svg'; -import iconNextInactive from './../../assets/icons/icon-next-inactive.svg'; -import iconNext from './../../assets/icons/icon-next.svg'; -import iconPlay from './../../assets/icons/icon-play.svg'; -import iconPause from './../../assets/icons/icon-pause.svg'; -import iconPrevInactive from './../../assets/icons/icon-prev-inactive.svg'; -import iconPrev from './../../assets/icons/icon-prev.svg'; -import iconSearch from './../../assets/icons/icon-search.svg'; -import iconStatusAlert from './../../assets/icons/icon-status-alert.svg'; -import iconTransferring from './../../assets/icons/icon-transferring.svg'; -import iconUpload from './../../assets/icons/icon-upload.svg'; -import navigationPanelRightHide from './../../assets/icons/navigation-panel-right-hide.svg'; -import navigationPanelRightReveal from './../../assets/icons/navigation-panel-right-reveal.svg'; -import tabLinear from './../../assets/icons/tab-linear.svg'; -import tabPatientInfo from './../../assets/icons/tab-patient-info.svg'; -import tabROIThreshold from './../../assets/icons/tab-roi-threshold.svg'; -import tabSegmentation from './../../assets/icons/tab-segmentation.svg'; -import tabStudies from './../../assets/icons/tab-studies.svg'; -import uiArrowDown from './../../assets/icons/ui-arrow-down.svg'; -import uiArrowUp from './../../assets/icons/ui-arrow-up.svg'; -import uiArrowLeft from './../../assets/icons/ui-arrow-left.svg'; -import uiArrowRight from './../../assets/icons/ui-arrow-right.svg'; -import loadingOHIFMark from './../../assets/icons/loading-ohif-mark.svg'; -import notificationsInfo from './../../assets/icons/notifications-info.svg'; -import notificationsWarning from './../../assets/icons/notifications-warning.svg'; -import notificationsError from './../../assets/icons/notifications-error.svg'; -import notificationsSuccess from './../../assets/icons/notifications-success.svg'; -import nextArrow from './../../assets/icons/next-arrow.svg'; -import prevArrow from './../../assets/icons/prev-arrow.svg'; -import viewportStatusTracked from './../../assets/icons/viewport-status-tracked.svg'; +import { ReactComponent as arrowDown } from './../../assets/icons/arrow-down.svg'; +import { ReactComponent as arrowLeft } from './../../assets/icons/arrow-left.svg'; +import { ReactComponent as arrowRight } from './../../assets/icons/arrow-right.svg'; +import { ReactComponent as arrowLeftSmall } from './../../assets/icons/arrow-left-small.svg'; +import { ReactComponent as arrowRightSmall } from './../../assets/icons/arrow-right-small.svg'; +import { ReactComponent as calendar } from './../../assets/icons/calendar.svg'; +import { ReactComponent as cancel } from './../../assets/icons/cancel.svg'; +import { ReactComponent as clipboard } from './../../assets/icons/clipboard.svg'; +import { ReactComponent as close } from './../../assets/icons/closeIcon.svg'; +import { ReactComponent as database } from './../../assets/icons/database.svg'; +import { ReactComponent as dottedCircle } from './../../assets/icons/dotted-circle.svg'; +import { ReactComponent as circledCheckmark } from './../../assets/icons/circled-checkmark.svg'; +import { ReactComponent as chevronDown } from './../../assets/icons/chevron-down.svg'; +import { ReactComponent as chevronLeft } from './../../assets/icons/chevron-left.svg'; +import { ReactComponent as chevronMenu } from './../../assets/icons/chevron-menu.svg'; +import { ReactComponent as chevronNext } from './../../assets/icons/chevron-next.svg'; +import { ReactComponent as chevronPrev } from './../../assets/icons/chevron-prev.svg'; +import { ReactComponent as chevronRight } from './../../assets/icons/chevron-right.svg'; +import { ReactComponent as contentNext } from './../../assets/icons/content-next.svg'; +import { ReactComponent as contentPrev } from './../../assets/icons/content-prev.svg'; +import { ReactComponent as eyeVisible } from './../../assets/icons/eye-visible.svg'; +import { ReactComponent as eyeHidden } from './../../assets/icons/eye-hidden.svg'; +import { ReactComponent as exclamation } from './../../assets/icons/exclamation.svg'; +import { ReactComponent as externalLink } from './../../assets/icons/external-link.svg'; +import { ReactComponent as groupLayers } from './../../assets/icons/group-layers.svg'; +import { ReactComponent as info } from './../../assets/icons/info.svg'; +import { ReactComponent as infoAction } from './../../assets/icons/info-action.svg'; +import { ReactComponent as infoLink } from './../../assets/icons/info-link.svg'; +import { ReactComponent as launchArrow } from './../../assets/icons/launch-arrow.svg'; +import { ReactComponent as launchInfo } from './../../assets/icons/launch-info.svg'; +import { ReactComponent as link } from './../../assets/icons/tool-stack-image-sync.svg'; +import { ReactComponent as listBullets } from './../../assets/icons/list-bullets.svg'; +import { ReactComponent as lock } from './../../assets/icons/lock.svg'; +import { ReactComponent as logoOhifSmall } from './../../assets/icons/logo-ohif-small.svg'; +import { ReactComponent as logoDarkBackGround } from './../../assets/icons/ohif-logo-color-darkbg.svg'; +import { ReactComponent as magnifier } from './../../assets/icons/magnifier.svg'; +import { ReactComponent as notificationwarningDiamond } from './../../assets/icons/notificationwarning-diamond.svg'; +import { ReactComponent as pencil } from './../../assets/icons/pencil.svg'; +import { ReactComponent as powerOff } from './../../assets/icons/power-off.svg'; +import { ReactComponent as profile } from './../../assets/icons/profile.svg'; +import { ReactComponent as pushLeft } from './../../assets/icons/push-left.svg'; +import { ReactComponent as pushRight } from './../../assets/icons/push-right.svg'; +import { ReactComponent as settings } from './../../assets/icons/settings.svg'; +import { ReactComponent as sidePanelCloseLeft } from './../../assets/icons/side-panel-close-left.svg'; +import { ReactComponent as sidePanelCloseRight } from './../../assets/icons/side-panel-close-right.svg'; +import { ReactComponent as sorting } from './../../assets/icons/sorting.svg'; +import { ReactComponent as sortingActiveDown } from './../../assets/icons/sorting-active-down.svg'; +import { ReactComponent as sortingActiveUp } from './../../assets/icons/sorting-active-up.svg'; +import { ReactComponent as statusAlertWarning } from './../../assets/icons/status-alert-warning.svg'; +import { ReactComponent as statusAlert } from './../../assets/icons/status-alert.svg'; +import { ReactComponent as statusLocked } from './../../assets/icons/status-locked.svg'; +import { ReactComponent as statusTracked } from './../../assets/icons/status-tracked.svg'; +import { ReactComponent as statusUntracked } from './../../assets/icons/status-untracked.svg'; +import { ReactComponent as tracked } from './../../assets/icons/tracked.svg'; +import { ReactComponent as unlink } from './../../assets/icons/unlink.svg'; +import { ReactComponent as checkboxChecked } from './../../assets/icons/checkbox-checked.svg'; +import { ReactComponent as checkboxUnchecked } from './../../assets/icons/checkbox-unchecked.svg'; +import { ReactComponent as iconAlertOutline } from './../../assets/icons/icons-alert-outline.svg'; +import { ReactComponent as iconAlertSmall } from './../../assets/icons/icon-alert-small.svg'; +import { ReactComponent as iconClose } from './../../assets/icons/icon-close.svg'; +import { ReactComponent as iconClearField } from './../../assets/icons/icon-clear-field.svg'; +import { ReactComponent as iconNextInactive } from './../../assets/icons/icon-next-inactive.svg'; +import { ReactComponent as iconNext } from './../../assets/icons/icon-next.svg'; +import { ReactComponent as iconPlay } from './../../assets/icons/icon-play.svg'; +import { ReactComponent as iconPause } from './../../assets/icons/icon-pause.svg'; +import { ReactComponent as iconPrevInactive } from './../../assets/icons/icon-prev-inactive.svg'; +import { ReactComponent as iconPrev } from './../../assets/icons/icon-prev.svg'; +import { ReactComponent as iconSearch } from './../../assets/icons/icon-search.svg'; +import { ReactComponent as iconStatusAlert } from './../../assets/icons/icon-status-alert.svg'; +import { ReactComponent as iconTransferring } from './../../assets/icons/icon-transferring.svg'; +import { ReactComponent as iconUpload } from './../../assets/icons/icon-upload.svg'; +import { ReactComponent as navigationPanelRightHide } from './../../assets/icons/navigation-panel-right-hide.svg'; +import { ReactComponent as navigationPanelRightReveal } from './../../assets/icons/navigation-panel-right-reveal.svg'; +import { ReactComponent as tabLinear } from './../../assets/icons/tab-linear.svg'; +import { ReactComponent as tabPatientInfo } from './../../assets/icons/tab-patient-info.svg'; +import { ReactComponent as tabROIThreshold } from './../../assets/icons/tab-roi-threshold.svg'; +import { ReactComponent as tabSegmentation } from './../../assets/icons/tab-segmentation.svg'; +import { ReactComponent as tabStudies } from './../../assets/icons/tab-studies.svg'; +import { ReactComponent as uiArrowDown } from './../../assets/icons/ui-arrow-down.svg'; +import { ReactComponent as uiArrowUp } from './../../assets/icons/ui-arrow-up.svg'; +import { ReactComponent as uiArrowLeft } from './../../assets/icons/ui-arrow-left.svg'; +import { ReactComponent as uiArrowRight } from './../../assets/icons/ui-arrow-right.svg'; +import { ReactComponent as loadingOHIFMark } from './../../assets/icons/loading-ohif-mark.svg'; +import { ReactComponent as notificationsInfo } from './../../assets/icons/notifications-info.svg'; +import { ReactComponent as notificationsWarning } from './../../assets/icons/notifications-warning.svg'; +import { ReactComponent as notificationsError } from './../../assets/icons/notifications-error.svg'; +import { ReactComponent as notificationsSuccess } from './../../assets/icons/notifications-success.svg'; +import { ReactComponent as nextArrow } from './../../assets/icons/next-arrow.svg'; +import { ReactComponent as prevArrow } from './../../assets/icons/prev-arrow.svg'; +import { ReactComponent as viewportStatusTracked } from './../../assets/icons/viewport-status-tracked.svg'; +import { ReactComponent as toggleDicomOverlay } from './../../assets/icons/tool-toggle-dicom-overlay.svg'; +import { ReactComponent as toolZoom } from './../../assets/icons/tool-zoom.svg'; +import { ReactComponent as toolCapture } from './../../assets/icons/tool-capture.svg'; +import { ReactComponent as toolLayout } from './../../assets/icons/tool-layout-default.svg'; +import { ReactComponent as toolMore } from './../../assets/icons/tool-more-menu.svg'; +import { ReactComponent as toolMove } from './../../assets/icons/tool-move.svg'; +import { ReactComponent as toolWindow } from './../../assets/icons/tool-window-level.svg'; +import { ReactComponent as toolAnnotate } from './../../assets/icons/tool-annotate.svg'; +import { ReactComponent as toolBidirectional } from './../../assets/icons/tool-bidirectional.svg'; +import { ReactComponent as toolElipse } from './../../assets/icons/tool-measure-elipse.svg'; +import { ReactComponent as toolCircle } from './../../assets/icons/tool-circle.svg'; +import { ReactComponent as toolLength } from './../../assets/icons/tool-length.svg'; +import { ReactComponent as toolStackScroll } from './../../assets/icons/tool-stack-scroll.svg'; +import { ReactComponent as toolMagnify } from './../../assets/icons/tool-quick-magnify.svg'; +import { ReactComponent as toolFlipHorizontal } from './../../assets/icons/tool-flip-horizontal.svg'; +import { ReactComponent as toolInvert } from './../../assets/icons/tool-invert.svg'; +import { ReactComponent as toolRotateRight } from './../../assets/icons/tool-rotate-right.svg'; +import { ReactComponent as toolCine } from './../../assets/icons/tool-cine.svg'; +import { ReactComponent as toolCrosshair } from './../../assets/icons/tool-crosshair.svg'; +import { ReactComponent as toolProbe } from './../../assets/icons/focus-frame-target.svg'; +import { ReactComponent as toolAngle } from './../../assets/icons/tool-angle.svg'; +import { ReactComponent as toolReset } from './../../assets/icons/tool-reset.svg'; +import { ReactComponent as toolRectangle } from './../../assets/icons/tool-rectangle.svg'; +import { ReactComponent as toolFusionColor } from './../../assets/icons/tool-fusion-color.svg'; +import { ReactComponent as toolCreateThreshold } from './../../assets/icons/tool-create-threshold.svg'; +import { ReactComponent as toolCalibration } from './../../assets/icons/tool-calibrate.svg'; +import { ReactComponent as toolFreehand } from './../../assets/icons/tool-freehand.svg'; +import { ReactComponent as toolFreehandPolygon } from './../../assets/icons/tool-freehand-polygon.svg'; +import { ReactComponent as toolPolygon } from './../../assets/icons/tool-polygon.svg'; +import { ReactComponent as editPatient } from './../../assets/icons/edit-patient.svg'; +import { ReactComponent as panelGroupMore } from './../../assets/icons/panel-group-more.svg'; +import { ReactComponent as panelGroupOpenClose } from './../../assets/icons/panel-group-open-close.svg'; +import { ReactComponent as rowAdd } from './../../assets/icons/row-add.svg'; +import { ReactComponent as rowEdit } from './../../assets/icons/row-edit.svg'; +import { ReactComponent as rowHidden } from './../../assets/icons/row-hidden.svg'; +import { ReactComponent as rowShown } from './../../assets/icons/row-shown.svg'; +import { ReactComponent as rowLock } from './../../assets/icons/row-lock.svg'; +import { ReactComponent as rowUnlock } from './../../assets/icons/row-unlock.svg'; +import { ReactComponent as iconMPR } from './../../assets/icons/icon-mpr-alt.svg'; +import { ReactComponent as checkboxDefault } from './../../assets/icons/checkbox-default.svg'; +import { ReactComponent as checkboxActive } from './../../assets/icons/checkbox-active.svg'; +import { ReactComponent as referenceLines } from './../../assets/icons/tool-reference-lines.svg'; +import { ReactComponent as chevronDownNew } from './../../assets/icons/icon-disclosure-close.svg'; +import { ReactComponent as chevronLeftNew } from './../../assets/icons/icon-disclosure-open.svg'; +import { ReactComponent as settingsBars } from './../../assets/icons/icon-display-settings.svg'; +import { ReactComponent as iconAdd } from './../../assets/icons/icon-add.svg'; +import { ReactComponent as iconRename } from './../../assets/icons/icon-rename.svg'; +import { ReactComponent as iconDelete } from './../../assets/icons/icon-delete.svg'; +import { ReactComponent as iconMoreMenu } from './../../assets/icons/icon-more-menu.svg'; +import { ReactComponent as iconToolBrush } from './../../assets/icons/tool-seg-brush.svg'; +import { ReactComponent as iconToolEraser } from './../../assets/icons/tool-seg-eraser.svg'; +import { ReactComponent as iconToolScissor } from './../../assets/icons/icon-tool-scissor.svg'; +import { ReactComponent as iconToolShape } from './../../assets/icons/tool-seg-shape.svg'; +import { ReactComponent as iconToolThreshold } from './../../assets/icons/tool-seg-threshold.svg'; +import { ReactComponent as viewportWindowLevel } from './../../assets/icons/viewport-window-level.svg'; +import { ReactComponent as dicomTagBrowser } from './../../assets/icons/tool-dicom-tag-browser.svg'; +import { ReactComponent as iconToolFreehandRoi } from './../../assets/icons/tool-freehand-roi.svg'; +import { ReactComponent as iconToolLivewire } from './../../assets/icons/tool-magnetic-roi.svg'; +import { ReactComponent as iconToolSplineRoi } from './../../assets/icons/tool-spline-roi.svg'; +import { ReactComponent as iconToolUltrasoundBidirectional } from './../../assets/icons/tool-ultrasound-bidirectional.svg'; +import { ReactComponent as iconToolLoupe } from './../../assets/icons/tool-magnify.svg'; +import { ReactComponent as oldTrash } from './../../assets/icons/old-trash.svg'; +import { ReactComponent as oldPlay } from './../../assets/icons/old-play.svg'; +import { ReactComponent as oldStop } from './../../assets/icons/old-stop.svg'; +import { ReactComponent as iconColorLUT } from './../../assets/icons/icon-color-lut.svg'; +import { ReactComponent as iconChevronPatient } from './../../assets/icons/icon-chevron-patient.svg'; +import { ReactComponent as iconPatient } from './../../assets/icons/icon-patient.svg'; +import { ReactComponent as iconSettings } from './../../assets/icons/icon-settings.svg'; +import { ReactComponent as iconToolbarBack } from './../../assets/icons/icon-toolbar-back.svg'; +import { ReactComponent as iconMultiplePatients } from './../../assets/icons/icon-multiple-patients.svg'; +import { ReactComponent as layoutAdvanced3DFourUp } from './../../assets/icons/layout-advanced-3d-four-up.svg'; +import { ReactComponent as layoutAdvanced3DMain } from './../../assets/icons/layout-advanced-3d-main.svg'; +import { ReactComponent as layoutAdvanced3DOnly } from './../../assets/icons/layout-advanced-3d-only.svg'; +import { ReactComponent as layoutAdvanced3DPrimary } from './../../assets/icons/layout-advanced-3d-primary.svg'; +import { ReactComponent as layoutAdvancedAxialPrimary } from './../../assets/icons/layout-advanced-axial-primary.svg'; +import { ReactComponent as layoutAdvancedMPR } from './../../assets/icons/layout-advanced-mpr.svg'; +import { ReactComponent as layoutCommon1x1 } from './../../assets/icons/layout-common-1x1.svg'; +import { ReactComponent as layoutCommon1x2 } from './../../assets/icons/layout-common-1x2.svg'; +import { ReactComponent as layoutCommon2x2 } from './../../assets/icons/layout-common-2x2.svg'; +import { ReactComponent as layoutCommon2x3 } from './../../assets/icons/layout-common-2x3.svg'; +import { ReactComponent as iconToolRotate } from './../../assets/icons/tool-3d-rotate.svg'; +import { ReactComponent as tab4D } from './../../assets/icons/tab-4d.svg'; +import { ReactComponent as investigationalUse } from './../../assets/icons/illustration-investigational-use.svg'; +import { ReactComponent as actionNewDialog } from './../../assets/icons/action-new-dialog.svg'; +import { ReactComponent as iconToolCobbAngle } from './../../assets/icons/tool-cobb-angle.svg'; +import { ReactComponent as iconToolWindowRegion } from './../../assets/icons/tool-window-region.svg'; -/** Tools */ -import toggleDicomOverlay from './../../assets/icons/tool-toggle-dicom-overlay.svg'; -import toolZoom from './../../assets/icons/tool-zoom.svg'; -import toolCapture from './../../assets/icons/tool-capture.svg'; -import toolLayout from './../../assets/icons/tool-layout-default.svg'; -import toolMore from './../../assets/icons/tool-more-menu.svg'; -import toolMove from './../../assets/icons/tool-move.svg'; -import toolWindow from './../../assets/icons/tool-window-level.svg'; -import toolAnnotate from './../../assets/icons/tool-annotate.svg'; -import toolBidirectional from './../../assets/icons/tool-bidirectional.svg'; -import toolElipse from './../../assets/icons/tool-measure-elipse.svg'; -import toolCircle from './../../assets/icons/tool-circle.svg'; -import toolLength from './../../assets/icons/tool-length.svg'; -import toolStackScroll from './../../assets/icons/tool-stack-scroll.svg'; -import toolMagnify from './../../assets/icons/tool-quick-magnify.svg'; -import toolFlipHorizontal from './../../assets/icons/tool-flip-horizontal.svg'; -import toolInvert from './../../assets/icons/tool-invert.svg'; -import toolRotateRight from './../../assets/icons/tool-rotate-right.svg'; -import toolCine from './../../assets/icons/tool-cine.svg'; -import toolCrosshair from './../../assets/icons/tool-crosshair.svg'; -import toolProbe from './../../assets/icons/focus-frame-target.svg'; -import toolAngle from './../../assets/icons/tool-angle.svg'; -import toolReset from './../../assets/icons/tool-reset.svg'; -import toolRectangle from './../../assets/icons/tool-rectangle.svg'; -import toolFusionColor from './../../assets/icons/tool-fusion-color.svg'; -import toolCreateThreshold from './../../assets/icons/tool-create-threshold.svg'; -import toolCalibration from './../../assets/icons/tool-calibrate.svg'; -import toolFreehand from './../../assets/icons/tool-freehand.svg'; -import toolFreehandPolygon from './../../assets/icons/tool-freehand-polygon.svg'; -import toolPolygon from './../../assets/icons/tool-polygon.svg'; -import toolBrush from './../../assets/icons/tool-brush.svg'; -import toolEraser from './../../assets/icons/tool-eraser.svg'; -import toolScissorRect from './../../assets/icons/tool-scissor-rect.svg'; -import toolScissorCircle from './../../assets/icons/tool-scissor-circle.svg'; -import toolPaintFill from './../../assets/icons/tool-paint-fill.svg'; -import editPatient from './../../assets/icons/edit-patient.svg'; -import panelGroupMore from './../../assets/icons/panel-group-more.svg'; -import panelGroupOpenClose from './../../assets/icons/panel-group-open-close.svg'; -import rowAdd from './../../assets/icons/row-add.svg'; -import rowEdit from './../../assets/icons/row-edit.svg'; -import rowHidden from './../../assets/icons/row-hidden.svg'; -import rowShown from './../../assets/icons/row-shown.svg'; -import rowLock from './../../assets/icons/row-lock.svg'; -import rowUnlock from './../../assets/icons/row-unlock.svg'; -import iconMPR from './../../assets/icons/icon-mpr-alt.svg'; -import checkboxDefault from './../../assets/icons/checkbox-default.svg'; -import checkboxActive from './../../assets/icons/checkbox-active.svg'; -import referenceLines from './../../assets/icons/tool-reference-lines.svg'; -import chevronDownNew from './../../assets/icons/icon-disclosure-close.svg'; -import chevronLeftNew from './../../assets/icons/icon-disclosure-open.svg'; -import settingsBars from './../../assets/icons/icon-display-settings.svg'; -import iconAdd from './../../assets/icons/icon-add.svg'; -import iconRename from './../../assets/icons/icon-rename.svg'; -import iconDelete from './../../assets/icons/icon-delete.svg'; -import iconMoreMenu from './../../assets/icons/icon-more-menu.svg'; -import iconToolBrush from './../../assets/icons/tool-seg-brush.svg'; -import iconToolEraser from './../../assets/icons/tool-seg-eraser.svg'; -import iconToolScissor from './../../assets/icons/icon-tool-scissor.svg'; -import iconToolShape from './../../assets/icons/tool-seg-shape.svg'; -import iconToolThreshold from './../../assets/icons/tool-seg-threshold.svg'; -import viewportWindowLevel from './../../assets/icons/viewport-window-level.svg'; -import dicomTagBrowser from './../../assets/icons/tool-dicom-tag-browser.svg'; -import iconToolFreehandRoi from './../../assets/icons/tool-freehand-roi.svg'; -import iconToolLivewire from './../../assets/icons/tool-magnetic-roi.svg'; -import iconToolSplineRoi from './../../assets/icons/tool-spline-roi.svg'; -import iconToolUltrasoundBidirectional from './../../assets/icons/tool-ultrasound-bidirectional.svg'; -import iconToolLoupe from './../../assets/icons/tool-magnify.svg'; -/** Old OHIF */ -import oldTrash from './../../assets/icons/old-trash.svg'; -import oldPlay from './../../assets/icons/old-play.svg'; -import oldStop from './../../assets/icons/old-stop.svg'; - -/** ColorLut */ -import iconColorLUT from './../../assets/icons/icon-color-lut.svg'; - -/** New Patient Info Toolbar */ -import iconChevronPatient from './../../assets/icons/icon-chevron-patient.svg'; -import iconPatient from './../../assets/icons/icon-patient.svg'; -import iconSettings from './../../assets/icons/icon-settings.svg'; -import iconToolbarBack from './../../assets/icons/icon-toolbar-back.svg'; -import iconMultiplePatients from './../../assets/icons/icon-multiple-patients.svg'; - -/** Volume Rendering */ import CTAAA from './../../assets/icons/CT-AAA.png'; import CTAAA2 from './../../assets/icons/CT-AAA2.png'; import CTAir from './../../assets/icons/CT-Air.png'; @@ -200,24 +204,6 @@ import MRDefault from './../../assets/icons/MR-Default.png'; import MRMIP from './../../assets/icons/MR-MIP.png'; import MRT2Brain from './../../assets/icons/MR-T2-Brain.png'; import VolumeRendering from './../../assets/icons/VolumeRendering.png'; -import actionNewDialog from './../../assets/icons/action-new-dialog.svg'; - -/** LAYOUT */ - -import layoutAdvanced3DFourUp from './../../assets/icons/layout-advanced-3d-four-up.svg'; -import layoutAdvanced3DMain from './../../assets/icons/layout-advanced-3d-main.svg'; -import layoutAdvanced3DOnly from './../../assets/icons/layout-advanced-3d-only.svg'; -import layoutAdvanced3DPrimary from './../../assets/icons/layout-advanced-3d-primary.svg'; -import layoutAdvancedAxialPrimary from './../../assets/icons/layout-advanced-axial-primary.svg'; -import layoutAdvancedMPR from './../../assets/icons/layout-advanced-mpr.svg'; -import layoutCommon1x1 from './../../assets/icons/layout-common-1x1.svg'; -import layoutCommon1x2 from './../../assets/icons/layout-common-1x2.svg'; -import layoutCommon2x2 from './../../assets/icons/layout-common-2x2.svg'; -import layoutCommon2x3 from './../../assets/icons/layout-common-2x3.svg'; -import iconToolRotate from './../../assets/icons/tool-3d-rotate.svg'; - -/** New investigational use */ -import investigationalUse from './../../assets/icons/illustration-investigational-use.svg'; const ICONS = { 'arrow-down': arrowDown, @@ -229,6 +215,7 @@ const ICONS = { cancel: cancel, clipboard: clipboard, close: close, + database: database, 'dotted-circle': dottedCircle, 'circled-checkmark': circledCheckmark, 'chevron-down': chevronDown, @@ -261,6 +248,7 @@ const ICONS = { 'list-bullets': listBullets, lock: lock, 'logo-ohif-small': logoOhifSmall, + 'logo-dark-background': logoDarkBackGround, magnifier: magnifier, exclamation: exclamation, 'notificationwarning-diamond': notificationwarningDiamond, @@ -374,6 +362,8 @@ const ICONS = { 'icon-tool-spline-roi': iconToolSplineRoi, 'icon-tool-ultrasound-bidirectional': iconToolUltrasoundBidirectional, 'icon-tool-loupe': iconToolLoupe, + 'icon-tool-cobb-angle': iconToolCobbAngle, + 'icon-tool-window-region': iconToolWindowRegion, /** Old OHIF */ 'old-trash': oldTrash, 'old-play': oldPlay, @@ -426,6 +416,7 @@ const ICONS = { 'layout-common-1x2': layoutCommon1x2, 'layout-common-2x2': layoutCommon2x2, 'layout-common-2x3': layoutCommon2x3, + 'tab-4d': tab4D, /** New investigational use */ 'illustration-investigational-use': investigationalUse, diff --git a/platform/ui/src/components/IconButton/IconButton.tsx b/platform/ui/src/components/IconButton/IconButton.tsx index fff9d168f7..e6d74594b1 100644 --- a/platform/ui/src/components/IconButton/IconButton.tsx +++ b/platform/ui/src/components/IconButton/IconButton.tsx @@ -74,14 +74,14 @@ const fullWidthClasses = { const IconButton = ({ children, - variant, - color, - size, - rounded, - disabled, - type, - fullWidth, - onClick, + variant = 'contained', + color = 'default', + size = 'medium', + rounded = 'medium', + disabled = false, + type = 'button', + fullWidth = false, + onClick = () => {}, className, id, ...rest @@ -122,17 +122,6 @@ const IconButton = ({ ); }; -IconButton.defaultProps = { - onClick: () => {}, - color: 'default', - disabled: false, - fullWidth: false, - rounded: 'medium', - size: 'medium', - type: 'button', - variant: 'contained', -}; - IconButton.propTypes = { children: PropTypes.node.isRequired, size: PropTypes.oneOf(['small', 'medium', 'large', 'initial', 'toolbar', 'toolbox']), diff --git a/platform/ui/src/components/ImageScrollbar/ImageScrollbar.tsx b/platform/ui/src/components/ImageScrollbar/ImageScrollbar.tsx index 1128680a1c..cfa5fcac4a 100644 --- a/platform/ui/src/components/ImageScrollbar/ImageScrollbar.tsx +++ b/platform/ui/src/components/ImageScrollbar/ImageScrollbar.tsx @@ -20,10 +20,12 @@ class ImageScrollbar extends PureComponent { width: `${this.props.height}`, }; + const { onContextMenu = e => e.preventDefault() } = this.props; + return (
e.preventDefault(), -}; - export default ImageScrollbar; diff --git a/platform/ui/src/components/InputDateRange/InputDateRange.tsx b/platform/ui/src/components/InputDateRange/InputDateRange.tsx index 88dafbb1a2..88638b496d 100644 --- a/platform/ui/src/components/InputDateRange/InputDateRange.tsx +++ b/platform/ui/src/components/InputDateRange/InputDateRange.tsx @@ -1,7 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; -import DateRange from '../DateRange'; +import { DatePickerWithRange } from '@ohif/ui-next'; import InputLabelWrapper from '../InputLabelWrapper'; const InputDateRange = ({ @@ -9,8 +9,8 @@ const InputDateRange = ({ label, isSortable, sortDirection, - onLabelClick, - value, + onLabelClick = () => {}, + value = {}, onChange, }) => { const { startDate, endDate } = value; @@ -26,9 +26,11 @@ const InputDateRange = ({ isSortable={isSortable} sortDirection={sortDirection} onLabelClick={onClickHandler} + className="xl:min-w-[284px]" > -
- + {}; - -InputDateRange.defaultProps = { - value: {}, - onLabelClick: noop, -}; - InputDateRange.propTypes = { id: PropTypes.string, label: PropTypes.string.isRequired, diff --git a/platform/ui/src/components/InputDoubleRange/InputDoubleRange.tsx b/platform/ui/src/components/InputDoubleRange/InputDoubleRange.tsx index d5ea681657..19367d0bcf 100644 --- a/platform/ui/src/components/InputDoubleRange/InputDoubleRange.tsx +++ b/platform/ui/src/components/InputDoubleRange/InputDoubleRange.tsx @@ -25,20 +25,20 @@ type InputDoubleRangeProps = { const InputDoubleRange: React.FC = ({ values, onChange, - minValue, - maxValue, - step, - unit, - containerClassName, - inputClassName, - labelClassName, - labelVariant, - showLabel, - labelPosition, - trackColor, - allowNumberEdit, + minValue = 0, + maxValue = 100, + step = 1, + unit = '', + containerClassName = '', + inputClassName = '', + labelClassName = '', + labelVariant = 'body1', + showLabel = false, + labelPosition = 'left', + trackColor = 'primary', + allowNumberEdit = false, allowOutOfRange = false, - showAdjustmentArrows, + showAdjustmentArrows = false, }) => { // Set initial thumb positions as percentages const initialPercentageStart = Math.round(((values[0] - minValue) / (maxValue - minValue)) * 100); @@ -235,20 +235,4 @@ const InputDoubleRange: React.FC = ({ ); }; -InputDoubleRange.defaultProps = { - minValue: 0, - maxValue: 100, - step: 1, - unit: '', - containerClassName: '', - inputClassName: '', - labelClassName: '', - labelVariant: 'body1', - showLabel: false, - labelPosition: 'left', - trackColor: 'primary', - allowNumberEdit: false, - showAdjustmentArrows: false, -}; - export default InputDoubleRange; diff --git a/platform/ui/src/components/InputLabelWrapper/InputLabelWrapper.tsx b/platform/ui/src/components/InputLabelWrapper/InputLabelWrapper.tsx index 904b06904e..fcd2177822 100644 --- a/platform/ui/src/components/InputLabelWrapper/InputLabelWrapper.tsx +++ b/platform/ui/src/components/InputLabelWrapper/InputLabelWrapper.tsx @@ -17,7 +17,7 @@ const InputLabelWrapper = ({ isSortable, sortDirection, onLabelClick, - className, + className = '', children, }) => { const onClickHandler = e => { @@ -53,10 +53,6 @@ const InputLabelWrapper = ({ ); }; -InputLabelWrapper.defaultProps = { - className: '', -}; - InputLabelWrapper.propTypes = { label: PropTypes.string.isRequired, isSortable: PropTypes.bool.isRequired, diff --git a/platform/ui/src/components/InputMultiSelect/InputMultiSelect.tsx b/platform/ui/src/components/InputMultiSelect/InputMultiSelect.tsx index 6a0c397456..9197833d0d 100644 --- a/platform/ui/src/components/InputMultiSelect/InputMultiSelect.tsx +++ b/platform/ui/src/components/InputMultiSelect/InputMultiSelect.tsx @@ -10,9 +10,9 @@ const InputMultiSelect = ({ isSortable, sortDirection, onLabelClick, - value, - placeholder, - options, + value = [], + placeholder = '', + options = [], onChange, }) => { return ( @@ -30,7 +30,7 @@ const InputMultiSelect = ({ value={value} isMulti={true} isClearable={false} - isSearchable={false} + isSearchable={true} closeMenuOnSelect={false} hideSelectedOptions={false} onChange={(selectedOptions, action) => { @@ -50,12 +50,6 @@ const InputMultiSelect = ({ ); }; -InputMultiSelect.defaultProps = { - value: [], - placeholder: '', - options: [], -}; - InputMultiSelect.propTypes = { id: PropTypes.string, label: PropTypes.string.isRequired, diff --git a/platform/ui/src/components/InputText/InputText.tsx b/platform/ui/src/components/InputText/InputText.tsx index 532b6282b6..290e2a0fff 100644 --- a/platform/ui/src/components/InputText/InputText.tsx +++ b/platform/ui/src/components/InputText/InputText.tsx @@ -4,7 +4,15 @@ import PropTypes from 'prop-types'; import Input from '../Input'; import InputLabelWrapper from '../InputLabelWrapper'; -const InputText = ({ id, label, isSortable, sortDirection, onLabelClick, value, onChange }) => { +const InputText = ({ + id, + label, + isSortable = false, + sortDirection = 'none', + onLabelClick = () => {}, + value = '', + onChange, +}) => { return ( {}, - sortDirection: 'none', -}; - InputText.propTypes = { id: PropTypes.string, label: PropTypes.string.isRequired, diff --git a/platform/ui/src/components/InvestigationalUseDialog/InvestigationalUseDialog.tsx b/platform/ui/src/components/InvestigationalUseDialog/InvestigationalUseDialog.tsx index 024dac07ba..3f29de6873 100644 --- a/platform/ui/src/components/InvestigationalUseDialog/InvestigationalUseDialog.tsx +++ b/platform/ui/src/components/InvestigationalUseDialog/InvestigationalUseDialog.tsx @@ -9,7 +9,11 @@ export enum showDialogOption { ShowOnceAndConfigure = 'configure', } -const InvestigationalUseDialog = ({ dialogConfiguration }) => { +const InvestigationalUseDialog = ({ + dialogConfiguration = { + option: showDialogOption.AlwaysShowDialog, + }, +}) => { const { option, days } = dialogConfiguration; const [isHidden, setIsHidden] = useState(true); @@ -84,6 +88,7 @@ const InvestigationalUseDialog = ({ dialogConfiguration }) => { type={ButtonEnums.type.primary} onClick={handleConfirmAndHide} className="bg-primary-main" + dataCY="confirm-and-hide-button" > Confirm and Hide @@ -96,13 +101,7 @@ InvestigationalUseDialog.propTypes = { dialogConfiguration: PropTypes.shape({ option: PropTypes.oneOf(Object.values(showDialogOption)).isRequired, days: PropTypes.number, - }).isRequired, -}; - -InvestigationalUseDialog.defaultProps = { - dialogConfiguration: { - option: showDialogOption.AlwaysShowDialog, - }, + }), }; export default InvestigationalUseDialog; diff --git a/platform/ui/src/components/LayoutPreset/LayoutPreset.tsx b/platform/ui/src/components/LayoutPreset/LayoutPreset.tsx index 9113cc0ea3..d8d0a7272e 100644 --- a/platform/ui/src/components/LayoutPreset/LayoutPreset.tsx +++ b/platform/ui/src/components/LayoutPreset/LayoutPreset.tsx @@ -4,7 +4,7 @@ import classNames from 'classnames'; import Icon from '../Icon/Icon'; function LayoutPreset({ - onSelection, + onSelection = () => {}, title, icon, commandOptions, @@ -27,10 +27,6 @@ function LayoutPreset({ ); } -LayoutPreset.defaultProps = { - onSelection: () => {}, -}; - LayoutPreset.propTypes = { onSelection: PropTypes.func.isRequired, title: PropTypes.string, diff --git a/platform/ui/src/components/LayoutSelector/LayoutSelector.tsx b/platform/ui/src/components/LayoutSelector/LayoutSelector.tsx index 2271069edf..de8512abcc 100644 --- a/platform/ui/src/components/LayoutSelector/LayoutSelector.tsx +++ b/platform/ui/src/components/LayoutSelector/LayoutSelector.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react'; import PropTypes from 'prop-types'; -function LayoutSelector({ onSelection, rows, columns }) { +function LayoutSelector({ onSelection = () => {}, rows = 3, columns = 4 }) { const [hoveredIndex, setHoveredIndex] = useState(); const hoverX = hoveredIndex % columns; const hoverY = Math.floor(hoveredIndex / columns); @@ -48,12 +48,6 @@ function LayoutSelector({ onSelection, rows, columns }) { ); } -LayoutSelector.defaultProps = { - onSelection: () => {}, - columns: 4, - rows: 3, -}; - LayoutSelector.propTypes = { onSelection: PropTypes.func.isRequired, columns: PropTypes.number.isRequired, diff --git a/platform/ui/src/components/LegacyButton/LegacyButton.tsx b/platform/ui/src/components/LegacyButton/LegacyButton.tsx index dea53f9271..0ec63cae4f 100644 --- a/platform/ui/src/components/LegacyButton/LegacyButton.tsx +++ b/platform/ui/src/components/LegacyButton/LegacyButton.tsx @@ -137,7 +137,7 @@ const fullWidthClasses = { }; const LegacyButton = ({ - children, + children = '', variant = defaults.variant, color = defaults.color, border = defaults.border, @@ -151,7 +151,7 @@ const LegacyButton = ({ endIcon: endIconProp, name, className, - onClick, + onClick = () => {}, /** TODO: All possible props should be explicitly defined -- avoid spreading props */ ...rest }) => { @@ -206,13 +206,6 @@ const LegacyButton = ({ ); }; -LegacyButton.defaultProps = { - color: defaults.color, - disabled: false, - children: '', - onClick: () => {}, -}; - LegacyButton.propTypes = { /** What is inside the button, can be text or react component */ children: PropTypes.node, diff --git a/platform/ui/src/components/LegacyCinePlayer/LegacyCinePlayer.tsx b/platform/ui/src/components/LegacyCinePlayer/LegacyCinePlayer.tsx index fff5154f12..9824b30f9b 100644 --- a/platform/ui/src/components/LegacyCinePlayer/LegacyCinePlayer.tsx +++ b/platform/ui/src/components/LegacyCinePlayer/LegacyCinePlayer.tsx @@ -8,14 +8,14 @@ import Icon from '../Icon'; import './LegacyCinePlayerCustomInputRange.css'; const LegacyCinePlayer = ({ - isPlaying, - minFrameRate, - maxFrameRate, - stepFrameRate, - frameRate: defaultFrameRate, - onFrameRateChange, - onPlayPauseChange, - onClose, + isPlaying = false, + minFrameRate = 1, + maxFrameRate = 90, + stepFrameRate = 1, + frameRate: defaultFrameRate = 24, + onFrameRateChange = () => {}, + onPlayPauseChange = () => {}, + onClose = () => {}, }) => { const [frameRate, setFrameRate] = useState(defaultFrameRate); const debouncedSetFrameRate = debounce(onFrameRateChange, 300); @@ -74,17 +74,6 @@ const LegacyCinePlayer = ({ const noop = () => {}; -LegacyCinePlayer.defaultProps = { - isPlaying: false, - minFrameRate: 1, - maxFrameRate: 90, - stepFrameRate: 1, - frameRate: 24, - onPlayPauseChange: noop, - onFrameRateChange: noop, - onClose: noop, -}; - LegacyCinePlayer.propTypes = { /** Minimum value for range slider */ minFrameRate: PropTypes.number.isRequired, diff --git a/platform/ui/src/components/LegacySidePanel/LegacySidePanel.tsx b/platform/ui/src/components/LegacySidePanel/LegacySidePanel.tsx index ceb9c491f2..466b59a2bc 100644 --- a/platform/ui/src/components/LegacySidePanel/LegacySidePanel.tsx +++ b/platform/ui/src/components/LegacySidePanel/LegacySidePanel.tsx @@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next'; import SwiperCore, { A11y, Controller, Navigation, Pagination, Scrollbar } from 'swiper'; import { Swiper, SwiperSlide } from 'swiper/react'; -import { PanelService, ServicesManager, Types } from '@ohif/core'; +import { Types } from '@ohif/core'; import LegacyButton from '../LegacyButton'; import Icon from '../Icon'; @@ -71,8 +71,8 @@ const LegacySidePanel = ({ className, activeTabIndex: activeTabIndexProp, tabs, -}) => { - const panelService: PanelService = servicesManager?.services?.panelService; +}: withAppTypes) => { + const panelService = servicesManager?.services?.panelService; const { t } = useTranslation('LegacySidePanel'); @@ -283,12 +283,8 @@ const LegacySidePanel = ({ ); }; -LegacySidePanel.defaultProps = { - defaultComponentOpen: null, -}; - LegacySidePanel.propTypes = { - servicesManager: PropTypes.instanceOf(ServicesManager), + servicesManager: PropTypes.object.isRequired, side: PropTypes.oneOf(['left', 'right']).isRequired, className: PropTypes.string, activeTabIndex: PropTypes.number, diff --git a/platform/ui/src/components/LegacySplitButton/LegacySplitButton.tsx b/platform/ui/src/components/LegacySplitButton/LegacySplitButton.tsx index 856d26dcbd..4dae06b43d 100644 --- a/platform/ui/src/components/LegacySplitButton/LegacySplitButton.tsx +++ b/platform/ui/src/components/LegacySplitButton/LegacySplitButton.tsx @@ -72,10 +72,10 @@ const LegacySplitButton = ({ primary, secondary, items, - renderer, + renderer = null, onInteraction, - Component, - isActive, + Component = null, + isActive = false, }) => { const { t } = useTranslation('Buttons'); const [state, setState] = useState({ isHovering: false, isExpanded: false }); @@ -149,7 +149,6 @@ const LegacySplitButton = ({ }; LegacySplitButton.propTypes = { - isToggle: PropTypes.bool, groupId: PropTypes.string.isRequired, primary: PropTypes.object.isRequired, secondary: PropTypes.object.isRequired, @@ -160,11 +159,4 @@ LegacySplitButton.propTypes = { Component: PropTypes.elementType, }; -LegacySplitButton.defaultProps = { - isToggle: false, - renderer: null, - isActive: false, - Component: null, -}; - export default LegacySplitButton; diff --git a/platform/ui/src/components/LegacyViewportActionBar/LegacyViewportActionBar.tsx b/platform/ui/src/components/LegacyViewportActionBar/LegacyViewportActionBar.tsx index 4f7d40dd0b..00857662fd 100644 --- a/platform/ui/src/components/LegacyViewportActionBar/LegacyViewportActionBar.tsx +++ b/platform/ui/src/components/LegacyViewportActionBar/LegacyViewportActionBar.tsx @@ -11,11 +11,11 @@ import LegacyCinePlayer from '../LegacyCinePlayer'; const LegacyViewportActionBar = ({ studyData, - showNavArrows, - showStatus, - showCine, - cineProps, - showPatientInfo: patientInfoVisibility, + showNavArrows = true, + showStatus = true, + showCine = false, + cineProps = {}, + showPatientInfo: patientInfoVisibility = false, onArrowsClick, onDoubleClick, getStatusComponent, @@ -166,14 +166,8 @@ LegacyViewportActionBar.propTypes = { }), }).isRequired, getStatusComponent: PropTypes.func.isRequired, -}; - -LegacyViewportActionBar.defaultProps = { - cineProps: {}, - showCine: false, - showStatus: true, - showNavArrows: true, - showPatientInfo: false, + onDoubleClick: PropTypes.func.isRequired, + showStatus: PropTypes.bool, }; export default LegacyViewportActionBar; diff --git a/platform/ui/src/components/LineChart/LineChart.tsx b/platform/ui/src/components/LineChart/LineChart.tsx index 472fa7a5bd..08fe3cfe0a 100644 --- a/platform/ui/src/components/LineChart/LineChart.tsx +++ b/platform/ui/src/components/LineChart/LineChart.tsx @@ -10,11 +10,11 @@ const LineChart = ({ height: heightProp, axis, series, - showAxisLabels, - showAxisGrid, - showLegend, - legendWidth, - transparentChartBackground, + showAxisLabels = true, + showAxisGrid = true, + showLegend = false, + legendWidth = 120, + transparentChartBackground = false, containerClassName, chartContainerClassName, }: { @@ -105,14 +105,6 @@ const LineChart = ({ ); }; -LineChart.defaultProps = { - showAxisLabels: true, - showAxisGrid: true, - showLegend: false, - legendWidth: 120, - transparentChartBackground: false, -}; - LineChart.propTypes = { title: PropTypes.string, width: PropTypes.number, diff --git a/platform/ui/src/components/ListMenu/ListMenu.tsx b/platform/ui/src/components/ListMenu/ListMenu.tsx index 170c626e22..56b896cb4c 100644 --- a/platform/ui/src/components/ListMenu/ListMenu.tsx +++ b/platform/ui/src/components/ListMenu/ListMenu.tsx @@ -5,7 +5,7 @@ import PropTypes from 'prop-types'; const flex = 'flex flex-row justify-between items-center'; const theme = 'bg-indigo-dark text-white'; -const ListMenu = ({ items = [], renderer, onClick }) => { +const ListMenu = ({ items = [], renderer, onClick = () => {} }) => { const [selectedIndex, setSelectedIndex] = useState(null); const ListItem = ({ item, index, isSelected }) => { @@ -30,7 +30,10 @@ const ListMenu = ({ items = [], renderer, onClick }) => { }; return ( -
+
{items.map((item, index) => { return ( { ); }; -const noop = () => {}; - ListMenu.propTypes = { items: PropTypes.array.isRequired, renderer: PropTypes.func.isRequired, onClick: PropTypes.func, }; -ListMenu.defaultProps = { - onClick: noop, -}; - export default ListMenu; diff --git a/platform/ui/src/components/MeasurementTable/MeasurementItem.tsx b/platform/ui/src/components/MeasurementTable/MeasurementItem.tsx index 6126db1b7f..70c20d6a9f 100644 --- a/platform/ui/src/components/MeasurementTable/MeasurementItem.tsx +++ b/platform/ui/src/components/MeasurementTable/MeasurementItem.tsx @@ -9,7 +9,7 @@ const MeasurementItem = ({ index, label, displayText, - isActive, + isActive = false, onClick, onEdit, onDelete, @@ -110,8 +110,4 @@ MeasurementItem.propTypes = { onDelete: PropTypes.func, }; -MeasurementItem.defaultProps = { - isActive: false, -}; - export default MeasurementItem; diff --git a/platform/ui/src/components/MeasurementTable/MeasurementTable.tsx b/platform/ui/src/components/MeasurementTable/MeasurementTable.tsx index 86fbdae286..226c41f0d1 100644 --- a/platform/ui/src/components/MeasurementTable/MeasurementTable.tsx +++ b/platform/ui/src/components/MeasurementTable/MeasurementTable.tsx @@ -1,12 +1,17 @@ import React from 'react'; -import { ServicesManager } from '@ohif/core'; import PropTypes from 'prop-types'; import { useTranslation } from 'react-i18next'; import MeasurementItem from './MeasurementItem'; -const MeasurementTable = ({ data, title, onClick, onEdit, onDelete, servicesManager }) => { - servicesManager = servicesManager as ServicesManager; +const MeasurementTable = ({ + data = [], + title, + onClick = () => {}, + onEdit = () => {}, + onDelete, + servicesManager, +}: withAppTypes) => { const { customizationService, measurementService } = servicesManager.services; const { t } = useTranslation('MeasurementTable'); const amount = data.length; @@ -66,12 +71,6 @@ const MeasurementTable = ({ data, title, onClick, onEdit, onDelete, servicesMana ); }; -MeasurementTable.defaultProps = { - data: [], - onClick: () => {}, - onEdit: () => {}, -}; - MeasurementTable.propTypes = { title: PropTypes.string.isRequired, data: PropTypes.arrayOf( diff --git a/platform/ui/src/components/Modal/Modal.tsx b/platform/ui/src/components/Modal/Modal.tsx index 1a717dc103..8730b5604a 100644 --- a/platform/ui/src/components/Modal/Modal.tsx +++ b/platform/ui/src/components/Modal/Modal.tsx @@ -15,12 +15,12 @@ if (typeof document !== 'undefined') { const Modal = ({ closeButton, - shouldCloseOnEsc, + shouldCloseOnEsc = true, isOpen, title, onClose, children, - shouldCloseOnOverlayClick, + shouldCloseOnOverlayClick = true, movable = false, containerDimensions = null, contentDimensions = null, @@ -99,14 +99,6 @@ const Modal = ({ ); }; -Modal.defaultProps = { - shouldCloseOnEsc: true, - shouldCloseOnOverlayClick: true, - movable: false, - containerDimensions: null, - contentDimensions: null, -}; - Modal.propTypes = { closeButton: PropTypes.bool, shouldCloseOnEsc: PropTypes.bool, diff --git a/platform/ui/src/components/Notification/Notification.tsx b/platform/ui/src/components/Notification/Notification.tsx index 5d1c82f5b5..816a06e304 100644 --- a/platform/ui/src/components/Notification/Notification.tsx +++ b/platform/ui/src/components/Notification/Notification.tsx @@ -5,7 +5,15 @@ import PropTypes from 'prop-types'; import Button, { ButtonEnums } from '../Button'; import Icon from '../Icon'; -const Notification = ({ id, type, message, actions, onSubmit, onOutsideClick, onKeyPress }) => { +const Notification = ({ + id, + type = 'info', + message, + actions, + onSubmit, + onOutsideClick = () => {}, + onKeyPress, +}) => { const notificationRef = useRef(null); useEffect(() => { @@ -99,11 +107,6 @@ const Notification = ({ id, type, message, actions, onSubmit, onOutsideClick, on ); }; -Notification.defaultProps = { - type: 'info', - onOutsideClick: () => {}, -}; - Notification.propTypes = { type: PropTypes.oneOf(['error', 'warning', 'info', 'success']), message: PropTypes.string.isRequired, diff --git a/platform/ui/src/components/PanelSection/PanelSection.tsx b/platform/ui/src/components/PanelSection/PanelSection.tsx index 6dd79fefdc..06aea7f4ec 100644 --- a/platform/ui/src/components/PanelSection/PanelSection.tsx +++ b/platform/ui/src/components/PanelSection/PanelSection.tsx @@ -49,8 +49,6 @@ const PanelSection = ({ title, children, actionIcons = [], childrenClassName }) ); }; -PanelSection.defaultProps = {}; - PanelSection.propTypes = { title: PropTypes.string, children: PropTypes.node, diff --git a/platform/ui/src/components/SegmentationGroupTable/SegmentationDropDownRow.tsx b/platform/ui/src/components/SegmentationGroupTable/SegmentationDropDownRow.tsx index ff909483a1..20d001408d 100644 --- a/platform/ui/src/components/SegmentationGroupTable/SegmentationDropDownRow.tsx +++ b/platform/ui/src/components/SegmentationGroupTable/SegmentationDropDownRow.tsx @@ -7,7 +7,7 @@ function SegmentationDropDownRow({ segmentations = [], activeSegmentation, onActiveSegmentationChange, - disableEditing, + disableEditing = false, onToggleSegmentationVisibility, onSegmentationEdit, onSegmentationDownload, @@ -180,9 +180,4 @@ SegmentationDropDownRow.propTypes = { onSegmentationAdd: PropTypes.func, }; -SegmentationDropDownRow.defaultProps = { - segmentations: [], - disableEditing: false, -}; - export default SegmentationDropDownRow; diff --git a/platform/ui/src/components/SegmentationGroupTable/SegmentationGroupSegment.tsx b/platform/ui/src/components/SegmentationGroupTable/SegmentationGroupSegment.tsx index 11773a8b7f..e197fa02f7 100644 --- a/platform/ui/src/components/SegmentationGroupTable/SegmentationGroupSegment.tsx +++ b/platform/ui/src/components/SegmentationGroupTable/SegmentationGroupSegment.tsx @@ -8,7 +8,7 @@ const SegmentItem = ({ segmentIndex, segmentationId, label, - isActive, + isActive = false, isVisible, color, showDelete, @@ -28,9 +28,12 @@ const SegmentItem = ({ return (
{ e.stopPropagation(); onClick(segmentationId, segmentIndex); @@ -151,11 +154,11 @@ const SegmentItem = ({
{Array.isArray(displayText) ? ( -
+
{displayText.map(text => (
{text}
@@ -163,7 +166,7 @@ const SegmentItem = ({
) : ( displayText && ( -
+
{displayText}
) @@ -233,8 +236,4 @@ SegmentItem.propTypes = { displayText: PropTypes.string, }; -SegmentItem.defaultProps = { - isActive: false, -}; - export default SegmentItem; diff --git a/platform/ui/src/components/SegmentationGroupTable/SegmentationGroupTable.tsx b/platform/ui/src/components/SegmentationGroupTable/SegmentationGroupTable.tsx index 73262d69f1..e92c05bcff 100644 --- a/platform/ui/src/components/SegmentationGroupTable/SegmentationGroupTable.tsx +++ b/platform/ui/src/components/SegmentationGroupTable/SegmentationGroupTable.tsx @@ -9,39 +9,34 @@ import SegmentationGroupSegment from './SegmentationGroupSegment'; import { useTranslation } from 'react-i18next'; const SegmentationGroupTable = ({ - segmentations, - // segmentation initial config + segmentations = [], segmentationConfig, - // UI show/hide - disableEditing, - showAddSegmentation, - showAddSegment, - showDeleteSegment, - // segmentation/segment handlers - onSegmentationAdd, - onSegmentationEdit, - onSegmentationClick, - onSegmentationDelete, - onSegmentationDownload, - onSegmentationDownloadRTSS, - storeSegmentation, - // segment handlers - onSegmentClick, - onSegmentAdd, - onSegmentDelete, - onSegmentEdit, - onToggleSegmentationVisibility, - onToggleSegmentVisibility, - onToggleSegmentLock, - onSegmentColorClick, - // segmentation config handlers - setFillAlpha, - setFillAlphaInactive, - setOutlineWidthActive, - setOutlineOpacityActive, - setRenderFill, - setRenderInactiveSegmentations, - setRenderOutline, + disableEditing = false, + showAddSegmentation = true, + showAddSegment = true, + showDeleteSegment = true, + onSegmentationAdd = () => {}, + onSegmentationEdit = () => {}, + onSegmentationClick = () => {}, + onSegmentationDelete = () => {}, + onSegmentationDownload = () => {}, + onSegmentationDownloadRTSS = () => {}, + storeSegmentation = () => {}, + onSegmentClick = () => {}, + onSegmentAdd = () => {}, + onSegmentDelete = () => {}, + onSegmentEdit = () => {}, + onToggleSegmentationVisibility = () => {}, + onToggleSegmentVisibility = () => {}, + onToggleSegmentLock = () => {}, + onSegmentColorClick = () => {}, + setFillAlpha = () => {}, + setFillAlphaInactive = () => {}, + setOutlineWidthActive = () => {}, + setOutlineOpacityActive = () => {}, + setRenderFill = () => {}, + setRenderInactiveSegmentations = () => {}, + setRenderOutline = () => {}, addSegmentationClassName, }) => { const [isConfigOpen, setIsConfigOpen] = useState(false); @@ -216,33 +211,4 @@ SegmentationGroupTable.propTypes = { setRenderOutline: PropTypes.func.isRequired, }; -SegmentationGroupTable.defaultProps = { - segmentations: [], - disableEditing: false, - showAddSegmentation: true, - showAddSegment: true, - showDeleteSegment: true, - onSegmentationAdd: () => {}, - onSegmentationEdit: () => {}, - onSegmentationClick: () => {}, - onSegmentationDelete: () => {}, - onSegmentationDownload: () => {}, - onSemgnetationDownloadRTSS: () => {}, - storeSegmentation: () => {}, - onSegmentClick: () => {}, - onSegmentAdd: () => {}, - onSegmentDelete: () => {}, - onSegmentEdit: () => {}, - onToggleSegmentationVisibility: () => {}, - onToggleSegmentVisibility: () => {}, - onToggleSegmentLock: () => {}, - onSegmentColorClick: () => {}, - setFillAlpha: () => {}, - setFillAlphaInactive: () => {}, - setOutlineWidthActive: () => {}, - setOutlineOpacityActive: () => {}, - setRenderFill: () => {}, - setRenderInactiveSegmentations: () => {}, - setRenderOutline: () => {}, -}; export default SegmentationGroupTable; diff --git a/platform/ui/src/components/SegmentationGroupTable/SegmentationGroupTableExpanded.tsx b/platform/ui/src/components/SegmentationGroupTable/SegmentationGroupTableExpanded.tsx index e2ae334bb7..543285f730 100644 --- a/platform/ui/src/components/SegmentationGroupTable/SegmentationGroupTableExpanded.tsx +++ b/platform/ui/src/components/SegmentationGroupTable/SegmentationGroupTableExpanded.tsx @@ -7,39 +7,34 @@ import { useTranslation } from 'react-i18next'; import SegmentationItem from './SegmentationItem'; const SegmentationGroupTableExpanded = ({ - segmentations, - // segmentation initial config + segmentations = [], segmentationConfig, - // UI show/hide - disableEditing, - showAddSegmentation, - showAddSegment, - showDeleteSegment, - // segmentation/segment handlers - onSegmentationAdd, - onSegmentationEdit, - onSegmentationClick, - onSegmentationDelete, - onSegmentationDownload, - onSegmentationDownloadRTSS, - storeSegmentation, - // segment handlers - onSegmentClick, - onSegmentAdd, - onSegmentDelete, - onSegmentEdit, - onToggleSegmentationVisibility, - onToggleSegmentVisibility, - onToggleSegmentLock, - onSegmentColorClick, - // segmentation config handlers - setFillAlpha, - setFillAlphaInactive, - setOutlineWidthActive, - setOutlineOpacityActive, - setRenderFill, - setRenderInactiveSegmentations, - setRenderOutline, + disableEditing = false, + showAddSegmentation = true, + showAddSegment = true, + showDeleteSegment = true, + onSegmentationAdd = () => {}, + onSegmentationEdit = () => {}, + onSegmentationClick = () => {}, + onSegmentationDelete = () => {}, + onSegmentationDownload = () => {}, + onSegmentationDownloadRTSS = () => {}, + storeSegmentation = () => {}, + onSegmentClick = () => {}, + onSegmentAdd = () => {}, + onSegmentDelete = () => {}, + onSegmentEdit = () => {}, + onToggleSegmentationVisibility = () => {}, + onToggleSegmentVisibility = () => {}, + onToggleSegmentLock = () => {}, + onSegmentColorClick = () => {}, + setFillAlpha = () => {}, + setFillAlphaInactive = () => {}, + setOutlineWidthActive = () => {}, + setOutlineOpacityActive = () => {}, + setRenderFill = () => {}, + setRenderInactiveSegmentations = () => {}, + setRenderOutline = () => {}, }) => { const [isConfigOpen, setIsConfigOpen] = useState(false); const [activeSegmentationId, setActiveSegmentationId] = useState(null); @@ -179,33 +174,4 @@ SegmentationGroupTableExpanded.propTypes = { setRenderOutline: PropTypes.func.isRequired, }; -SegmentationGroupTableExpanded.defaultProps = { - segmentations: [], - disableEditing: false, - showAddSegmentation: true, - showAddSegment: true, - showDeleteSegment: true, - onSegmentationAdd: () => {}, - onSegmentationEdit: () => {}, - onSegmentationClick: () => {}, - onSegmentationDelete: () => {}, - onSegmentationDownload: () => {}, - onSemgnetationDownloadRTSS: () => {}, - storeSegmentation: () => {}, - onSegmentClick: () => {}, - onSegmentAdd: () => {}, - onSegmentDelete: () => {}, - onSegmentEdit: () => {}, - onToggleSegmentationVisibility: () => {}, - onToggleSegmentVisibility: () => {}, - onToggleSegmentLock: () => {}, - onSegmentColorClick: () => {}, - setFillAlpha: () => {}, - setFillAlphaInactive: () => {}, - setOutlineWidthActive: () => {}, - setOutlineOpacityActive: () => {}, - setRenderFill: () => {}, - setRenderInactiveSegmentations: () => {}, - setRenderOutline: () => {}, -}; export default SegmentationGroupTableExpanded; diff --git a/platform/ui/src/components/SegmentationGroupTable/SegmentationItem.tsx b/platform/ui/src/components/SegmentationGroupTable/SegmentationItem.tsx index 8741c338f5..866ab64b34 100644 --- a/platform/ui/src/components/SegmentationGroupTable/SegmentationItem.tsx +++ b/platform/ui/src/components/SegmentationGroupTable/SegmentationItem.tsx @@ -8,8 +8,8 @@ import SegmentationGroupSegment from './SegmentationGroupSegment'; import { Tooltip } from '../../components'; function SegmentationItem({ - segmentation, - disableEditing, + segmentation = {}, + disableEditing = false, onSegmentationEdit, onSegmentationDownload, onSegmentationDownloadRTSS, @@ -203,9 +203,4 @@ SegmentationItem.propTypes = { activeSegmentationId: PropTypes.string, }; -SegmentationItem.defaultProps = { - segmentation: null, - disableEditing: false, -}; - export default SegmentationItem; diff --git a/platform/ui/src/components/SegmentationTable/SegmentationItem.tsx b/platform/ui/src/components/SegmentationTable/SegmentationItem.tsx index a7f3e966d7..83c91428ff 100644 --- a/platform/ui/src/components/SegmentationTable/SegmentationItem.tsx +++ b/platform/ui/src/components/SegmentationTable/SegmentationItem.tsx @@ -8,8 +8,8 @@ const SegmentationItem = ({ id, index, label, - displayText, - isActive, + displayText = [], + isActive = false, isVisible, onClick, onEdit, @@ -138,9 +138,4 @@ SegmentationItem.propTypes = { toggleVisibility: PropTypes.func, }; -SegmentationItem.defaultProps = { - isActive: false, - displayText: [], -}; - export default SegmentationItem; diff --git a/platform/ui/src/components/SegmentationTable/SegmentationTable.tsx b/platform/ui/src/components/SegmentationTable/SegmentationTable.tsx index 1d683baf4c..97aa985d6c 100644 --- a/platform/ui/src/components/SegmentationTable/SegmentationTable.tsx +++ b/platform/ui/src/components/SegmentationTable/SegmentationTable.tsx @@ -5,14 +5,14 @@ import SegmentationItem from './SegmentationItem'; import Icon from '../Icon'; const SegmentationTable = ({ - title, - segmentations, - activeSegmentationId, - onClick, - onEdit, - onDelete, - onToggleVisibility, - onToggleVisibilityAll, + title = '', + segmentations = [], + activeSegmentationId = '', + onClick = () => {}, + onEdit = () => {}, + onDelete = () => {}, + onToggleVisibility = () => {}, + onToggleVisibilityAll = () => {}, }) => { const [hiddenSegmentationIds, setHiddenSegmentationIds] = useState([]); const amount = segmentations.length; @@ -112,14 +112,4 @@ SegmentationTable.propTypes = { onToggleVisibilityAll: PropTypes.func.isRequired, }; -SegmentationTable.defaultProps = { - title: '', - segmentations: [], - activeSegmentationId: '', - onClick: () => {}, - onEdit: () => {}, - onToggleVisibility: () => {}, - onToggleVisibilityAll: () => {}, -}; - export default SegmentationTable; diff --git a/platform/ui/src/components/Select/Select.css b/platform/ui/src/components/Select/Select.css index b1e9eb3486..03b1bd3458 100644 --- a/platform/ui/src/components/Select/Select.css +++ b/platform/ui/src/components/Select/Select.css @@ -6,6 +6,21 @@ @apply border-gray-500; } +.customSelect__control { + height: 32px; +} + +.customSelect__value-container { + padding-top: 0px !important; + padding-bottom: 0px !important; +} + +.customSelect__input { + @apply text-white !important; + font-size: 0.75rem !important; + line-height: 1.25 !important; +} + .customSelect__wrapper .customSelect__control:focus, .customSelect__wrapper .customSelect__control--menu-is-open { @apply border-gray-500 outline-none; @@ -27,16 +42,16 @@ padding: 4px; } -.customSelect__wrapper .customSelect__option { - color: #d6d6d6; - font-size: 14px; - display: flex; - align-items: center; - @apply flex flex-row items-center; + .customSelect__option { + color: #d6d6d6 !important; + font-size: 14px !important; + display: flex !important; + align-items: center !important; + @apply flex flex-row items-center !important; } -.customSelect__wrapper .customSelect__option--is-selected { - @apply bg-transparent; +.customSelect__option--is-selected { + @apply bg-transparent !important; } .customSelect__wrapper .customSelect__single-value { @@ -55,26 +70,26 @@ @apply inline-block truncate px-3 py-2; } -.ohif-select .customSelect__menu { +.customSelect__menu-portal .customSelect__menu { background-color: transparent !important; border-radius: 6px; } -.ohif-select .customSelect__menu-list { +.customSelect__menu-portal .customSelect__menu-list { overflow-x: hidden !important; margin: 4px; padding-top: 0px !important; } -.ohif-select .customSelect__menu-list::-webkit-scrollbar { +.customSelect__menu-portal .customSelect__menu-list::-webkit-scrollbar { width: 6px; border-radius: 10px; } -.ohif-select .customSelect__placeholder { +.customSelect__menu-portal .customSelect__placeholder { @apply text-aqua-pale pl-1.5; } -.ohif-select .customSelect__menu-list::-webkit-scrollbar-thumb { +.customSelect__menu-portal .customSelect__menu-list::-webkit-scrollbar-thumb { background-color: #0944b3; border-radius: 10px; } @@ -83,11 +98,11 @@ background-color: #0944b391 !important; } -.ohif-select .customSelect__option:hover { +.customSelect__menu-portal .customSelect__option:hover { background-color: #0944b391; } -.ohif-select .customSelect__menu { +.customSelect__menu-portal .customSelect__menu { border: 2px solid #0944b3; border-radius: 6px; background-color: #151515 !important; diff --git a/platform/ui/src/components/Select/Select.tsx b/platform/ui/src/components/Select/Select.tsx index a24a00c699..474edc23e7 100644 --- a/platform/ui/src/components/Select/Select.tsx +++ b/platform/ui/src/components/Select/Select.tsx @@ -42,20 +42,20 @@ const Option = props => { const Select = ({ id, - className, - closeMenuOnSelect, - hideSelectedOptions, - isClearable, - isDisabled, - isMulti, - isSearchable, + className = '', + closeMenuOnSelect = true, + hideSelectedOptions = false, + isClearable = true, + isDisabled = false, + isMulti = false, + isSearchable = true, onChange, options, placeholder, - noIcons, - menuPlacement, - components, - value, + noIcons = false, + menuPlacement = 'auto', + components = {}, + value = [], }) => { const _noIconComponents = { DropdownIndicator: () => null, @@ -94,6 +94,11 @@ const Select = ({ components={_components} placeholder={placeholder} options={options} + blurInputOnSelect={true} + menuPortalTarget={document.body} + styles={{ + menuPortal: base => ({ ...base, zIndex: 9999 }), + }} value={value && Array.isArray(value) ? selectedOptions : value} onChange={(selectedOptions, { action }) => { const newSelection = !selectedOptions.length @@ -105,20 +110,6 @@ const Select = ({ ); }; -Select.defaultProps = { - className: '', - closeMenuOnSelect: true, - hideSelectedOptions: false, - isClearable: true, - components: {}, - isDisabled: false, - isMulti: false, - isSearchable: true, - noIcons: false, - menuPlacement: 'auto', - value: [], -}; - Select.propTypes = { className: PropTypes.string, closeMenuOnSelect: PropTypes.bool, diff --git a/platform/ui/src/components/SidePanel/SidePanel.tsx b/platform/ui/src/components/SidePanel/SidePanel.tsx index bdfef63c4f..c606cfdd1a 100644 --- a/platform/ui/src/components/SidePanel/SidePanel.tsx +++ b/platform/ui/src/components/SidePanel/SidePanel.tsx @@ -161,7 +161,7 @@ const createBaseStyle = (expandedWidth: number) => { const SidePanel = ({ side, className, - activeTabIndex: activeTabIndexProp, + activeTabIndex: activeTabIndexProp = null, tabs, onOpen, expandedWidth = 248, @@ -400,11 +400,6 @@ const SidePanel = ({ ); }; -SidePanel.defaultProps = { - defaultComponentOpen: null, - activeTabIndex: null, // the default is to close the side panel -}; - SidePanel.propTypes = { side: PropTypes.oneOf(['left', 'right']).isRequired, className: PropTypes.string, diff --git a/platform/ui/src/components/SplitButton/SplitButton.tsx b/platform/ui/src/components/SplitButton/SplitButton.tsx index 6fb7ec5b9c..fd44f40416 100644 --- a/platform/ui/src/components/SplitButton/SplitButton.tsx +++ b/platform/ui/src/components/SplitButton/SplitButton.tsx @@ -91,9 +91,9 @@ const SplitButton = ({ primary, secondary, items, - renderer, + renderer = null, onInteraction, - Component, + Component = Icon, }) => { const { t } = useTranslation('Buttons'); const [state, setState] = useState({ isHovering: false, isExpanded: false }); @@ -172,7 +172,6 @@ const SplitButton = ({ }; SplitButton.propTypes = { - isToggle: PropTypes.bool, groupId: PropTypes.string.isRequired, primary: PropTypes.object.isRequired, secondary: PropTypes.object.isRequired, @@ -184,11 +183,4 @@ SplitButton.propTypes = { interactionType: PropTypes.oneOf(['action', 'tool', 'toggle']), }; -SplitButton.defaultProps = { - isToggle: false, - renderer: null, - isActive: false, - Component: null, -}; - export default SplitButton; diff --git a/platform/ui/src/components/StudyBrowser/StudyBrowser.tsx b/platform/ui/src/components/StudyBrowser/StudyBrowser.tsx index c212de7ffd..91fd6b0e4a 100644 --- a/platform/ui/src/components/StudyBrowser/StudyBrowser.tsx +++ b/platform/ui/src/components/StudyBrowser/StudyBrowser.tsx @@ -7,6 +7,7 @@ import LegacyButtonGroup from '../LegacyButtonGroup'; import LegacyButton from '../LegacyButton'; import ThumbnailList from '../ThumbnailList'; import { StringNumber } from '../../types'; +import StudyBrowserSort from '../StudyBrowserSort'; const getTrackedSeries = displaySets => { let trackedSeries = 0; @@ -19,18 +20,20 @@ const getTrackedSeries = displaySets => { return trackedSeries; }; +const noop = () => {}; + const StudyBrowser = ({ tabs, activeTabName, expandedStudyInstanceUIDs, - onClickTab, - onClickStudy, - onClickThumbnail, - onDoubleClickThumbnail, - onClickUntrack, + onClickTab = noop, + onClickStudy = noop, + onClickThumbnail = noop, + onDoubleClickThumbnail = noop, + onClickUntrack = noop, activeDisplaySetInstanceUIDs, servicesManager, -}) => { +}: withAppTypes) => { const { t } = useTranslation('StudyBrowser'); const { customizationService } = servicesManager?.services || {}; @@ -71,7 +74,7 @@ const StudyBrowser = ({ return (
{/* TODO Revisit design of LegacyButtonGroup later - for now use LegacyButton for its children.*/} @@ -109,6 +112,9 @@ const StudyBrowser = ({ ); })} + {window.config.experimentalStudyBrowserSort && ( + + )}
{getTabContent()} @@ -168,14 +174,4 @@ StudyBrowser.propTypes = { ), }; -const noop = () => {}; - -StudyBrowser.defaultProps = { - onClickTab: noop, - onClickStudy: noop, - onClickThumbnail: noop, - onDoubleClickThumbnail: noop, - onClickUntrack: noop, -}; - export default StudyBrowser; diff --git a/platform/ui/src/components/StudyBrowserSort/StudyBrowserSort.tsx b/platform/ui/src/components/StudyBrowserSort/StudyBrowserSort.tsx new file mode 100644 index 0000000000..a9bfdd81dd --- /dev/null +++ b/platform/ui/src/components/StudyBrowserSort/StudyBrowserSort.tsx @@ -0,0 +1,73 @@ +import React, { useEffect, useState } from 'react'; +import Icon from '../Icon'; + +export default function StudyBrowserSort({ servicesManager }: withAppTypes) { + const { customizationService, displaySetService } = servicesManager.services; + const { values: sortFunctions } = customizationService.get('studyBrowser.sortFunctions'); + + const [selectedSort, setSelectedSort] = useState(sortFunctions[0]); + const [sortDirection, setSortDirection] = useState('ascending'); + + const handleSortChange = event => { + const selectedSortFunction = sortFunctions.find(sort => sort.label === event.target.value); + setSelectedSort(selectedSortFunction); + }; + + const toggleSortDirection = e => { + e.stopPropagation(); + setSortDirection(prevDirection => (prevDirection === 'ascending' ? 'descending' : 'ascending')); + }; + + useEffect(() => { + displaySetService.sortDisplaySets(selectedSort.sortFunction, sortDirection); + }, [displaySetService, selectedSort, sortDirection]); + + useEffect(() => { + const SubscriptionDisplaySetsChanged = displaySetService.subscribe( + displaySetService.EVENTS.DISPLAY_SETS_CHANGED, + () => { + displaySetService.sortDisplaySets(selectedSort.sortFunction, sortDirection, true); + } + ); + const SubscriptionDisplaySetMetaDataInvalidated = displaySetService.subscribe( + displaySetService.EVENTS.DISPLAY_SET_SERIES_METADATA_INVALIDATED, + () => { + displaySetService.sortDisplaySets(selectedSort.sortFunction, sortDirection, true); + } + ); + + return () => { + SubscriptionDisplaySetsChanged.unsubscribe(); + SubscriptionDisplaySetMetaDataInvalidated.unsubscribe(); + }; + }, [displaySetService, selectedSort, sortDirection]); + + return ( +
+ + +
+ ); +} diff --git a/platform/ui/src/components/StudyBrowserSort/index.js b/platform/ui/src/components/StudyBrowserSort/index.js new file mode 100644 index 0000000000..1f9a4601eb --- /dev/null +++ b/platform/ui/src/components/StudyBrowserSort/index.js @@ -0,0 +1,3 @@ +import StudyBrowserSort from './StudyBrowserSort'; + +export default StudyBrowserSort; diff --git a/platform/ui/src/components/StudyListTable/StudyListTableRow.tsx b/platform/ui/src/components/StudyListTable/StudyListTableRow.tsx index 4a3fa6f931..45e75910c8 100644 --- a/platform/ui/src/components/StudyListTable/StudyListTableRow.tsx +++ b/platform/ui/src/components/StudyListTable/StudyListTableRow.tsx @@ -7,7 +7,7 @@ import Icon from '../Icon'; const StudyListTableRow = props => { const { tableData } = props; - const { row, expandedContent, onClickRow, isExpanded, dataCY } = tableData; + const { row, expandedContent, onClickRow, isExpanded, dataCY, clickableCY } = tableData; return ( <> { { 'bg-secondary-dark': isExpanded } )} onClick={onClickRow} + data-cy={clickableCY} > {row.map((cell, index) => { const { content, title, gridCol } = cell; @@ -108,6 +109,7 @@ StudyListTableRow.propTypes = { onClickRow: PropTypes.func.isRequired, isExpanded: PropTypes.bool.isRequired, dataCY: PropTypes.string, + clickableCY: PropTypes.string, }), }; diff --git a/platform/ui/src/components/Svg/getSvg.tsx b/platform/ui/src/components/Svg/getSvg.tsx index 22ebc3b842..8a1975176e 100644 --- a/platform/ui/src/components/Svg/getSvg.tsx +++ b/platform/ui/src/components/Svg/getSvg.tsx @@ -1,6 +1,6 @@ import React from 'react'; // Svgs -import logoOhif from './../../assets/svgs/ohif-logo.svg'; +import { ReactComponent as logoOhif } from './../../assets/svgs/ohif-logo.svg'; const SVGS = { 'logo-ohif': logoOhif, diff --git a/platform/ui/src/components/Table/Table.tsx b/platform/ui/src/components/Table/Table.tsx index ab699f708c..ecb6bc64e3 100644 --- a/platform/ui/src/components/Table/Table.tsx +++ b/platform/ui/src/components/Table/Table.tsx @@ -2,7 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; -const Table = ({ children, className, fullWidth, style }) => { +const Table = ({ children, className = '', fullWidth = true, style = {} }) => { const classes = { base: 'text-lg text-white', fullWidth: { @@ -21,12 +21,6 @@ const Table = ({ children, className, fullWidth, style }) => { ); }; -Table.defaultProps = { - className: '', - fullWidth: true, - style: {}, -}; - Table.propTypes = { fullWidth: PropTypes.bool, children: PropTypes.node.isRequired, diff --git a/platform/ui/src/components/TableBody/TableBody.tsx b/platform/ui/src/components/TableBody/TableBody.tsx index 95f4fdf134..e22b27abde 100644 --- a/platform/ui/src/components/TableBody/TableBody.tsx +++ b/platform/ui/src/components/TableBody/TableBody.tsx @@ -2,7 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; -const TableBody = ({ children, className, style }) => { +const TableBody = ({ children, className = '', style = {} }) => { return (
{ ); }; -TableBody.defaultProps = { - className: '', - style: {}, -}; - TableBody.propTypes = { children: function (props, propName, componentName) { const elements = React.Children.toArray(props.children); diff --git a/platform/ui/src/components/TableCell/TableCell.tsx b/platform/ui/src/components/TableCell/TableCell.tsx index a107eea466..9a5b588815 100644 --- a/platform/ui/src/components/TableCell/TableCell.tsx +++ b/platform/ui/src/components/TableCell/TableCell.tsx @@ -4,14 +4,14 @@ import classnames from 'classnames'; const TableCell = ({ children, - className, - colSpan, + className = '', + colSpan = 1, // ignored because we don't want to expose this prop // eslint-disable-next-line react/prop-types cellsNum, - isTableHead, - align, - style, + isTableHead = false, + align = 'left', + style = {}, }) => { const classes = { align: { @@ -42,14 +42,6 @@ const TableCell = ({ ); }; -TableCell.defaultProps = { - align: 'left', - className: '', - colSpan: 1, - isTableHead: false, - style: {}, -}; - TableCell.propTypes = { align: PropTypes.oneOf(['left', 'center', 'right', 'justify']), children: PropTypes.node.isRequired, diff --git a/platform/ui/src/components/TableHead/TableHead.tsx b/platform/ui/src/components/TableHead/TableHead.tsx index b23cbf0a8c..526c355aff 100644 --- a/platform/ui/src/components/TableHead/TableHead.tsx +++ b/platform/ui/src/components/TableHead/TableHead.tsx @@ -2,7 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; -const TableHead = ({ children, className, style }) => { +const TableHead = ({ children, className = '', style = {} }) => { return (
{ ); }; -TableHead.defaultProps = { - className: '', - style: {}, -}; - TableHead.propTypes = { children: function (props, propName, componentName) { const elements = React.Children.toArray(props.children); diff --git a/platform/ui/src/components/TableRow/TableRow.tsx b/platform/ui/src/components/TableRow/TableRow.tsx index e786b05506..ea66854a80 100644 --- a/platform/ui/src/components/TableRow/TableRow.tsx +++ b/platform/ui/src/components/TableRow/TableRow.tsx @@ -2,7 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; -const TableRow = ({ children, className, isTableHead, style }) => { +const TableRow = ({ children, className = '', isTableHead = false, style = {} }) => { const childrens = React.Children.map(children, child => { const isValidReactElement = React.isValidElement(child); @@ -21,12 +21,6 @@ const TableRow = ({ children, className, isTableHead, style }) => { ); }; -TableRow.defaultProps = { - isTableHead: false, - className: '', - style: {}, -}; - TableRow.propTypes = { isTableHead: PropTypes.bool, children: function (props, propName, componentName) { diff --git a/platform/ui/src/components/Thumbnail/Thumbnail.tsx b/platform/ui/src/components/Thumbnail/Thumbnail.tsx index 578f4a73fe..b904a91e62 100644 --- a/platform/ui/src/components/Thumbnail/Thumbnail.tsx +++ b/platform/ui/src/components/Thumbnail/Thumbnail.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import { useDrag } from 'react-dnd'; @@ -17,9 +17,10 @@ const Thumbnail = ({ description, seriesNumber, numInstances, + loadingProgress, countIcon, messages, - dragData, + dragData = {}, isActive, onClick, onDoubleClick, @@ -35,6 +36,19 @@ const Thumbnail = ({ }, }); + const [lastTap, setLastTap] = useState(0); + + const handleTouchEnd = e => { + const currentTime = new Date().getTime(); + const tapLength = currentTime - lastTap; + if (tapLength < 300 && tapLength > 0) { + onDoubleClick(e); + } else { + onClick(e); + } + setLastTap(currentTime); + }; + return (
@@ -56,9 +72,6 @@ const Thumbnail = ({ ? 'border-primary-light border-2' : 'border-secondary-light border hover:border-blue-300' )} - style={{ - margin: isActive ? '0' : '1px', - }} > {imageSrc ? ( {` ${numInstances}`}
+
+ {loadingProgress && loadingProgress < 1 && <>{Math.round(loadingProgress * 100)}%} + {loadingProgress && loadingProgress === 1 && ( + + )} +
{ + const currentTime = new Date().getTime(); + const tapLength = currentTime - lastTap; + if (tapLength < 300 && tapLength > 0) { + onDoubleClick(e); + } else { + onClick(e); + } + setLastTap(currentTime); + }; + return (
{ const currentButtonIdsStr = JSON.stringify( @@ -33,11 +40,24 @@ function Toolbox({ servicesManager, buttonSectionId, commandsManager, title, ... }) ); - if (prevButtonIdsRef.current === currentButtonIdsStr) { + const currentToolBoxStateStr = JSON.stringify( + Object.keys(toolboxState.toolOptions).map(tool => { + const options = toolboxState.toolOptions[tool]; + if (Array.isArray(options)) { + return options?.map(option => `${option.id}-${option.value}`); + } + }) + ); + + if ( + prevButtonIdsRef.current === currentButtonIdsStr && + prevToolboxStateRef.current === currentToolBoxStateStr + ) { return; } prevButtonIdsRef.current = currentButtonIdsStr; + prevToolboxStateRef.current = currentToolBoxStateStr; const initializeOptionsWithEnhancements = toolbarButtons.reduce( (accumulator, toolbarButton) => { @@ -51,11 +71,15 @@ function Toolbox({ servicesManager, buttonSectionId, commandsManager, title, ... return option; } + const value = + toolboxState.toolOptions?.[parentId]?.find(prop => prop.id === option.id)?.value ?? + option.value; + + const updatedOptions = toolboxState.toolOptions?.[parentId]; + return { ...option, - value: - toolboxState.toolOptions?.[parentId]?.find(prop => prop.id === option.id)?.value ?? - option.value, + value, commands: value => { api.handleToolOptionChange(parentId, option.id, value); @@ -72,10 +96,15 @@ function Toolbox({ servicesManager, buttonSectionId, commandsManager, title, ... } else if (isObject) { commandsManager.run({ ...command, - commandOptions: { ...command.commandOptions, ...option, value }, + commandOptions: { + ...command.commandOptions, + ...option, + value, + options: updatedOptions, + }, }); } else if (isFunction) { - command({ value, commandsManager, servicesManager }); + command({ value, commandsManager, servicesManager, options: updatedOptions }); } }); }, @@ -101,7 +130,7 @@ function Toolbox({ servicesManager, buttonSectionId, commandsManager, title, ... ); api.initializeToolOptions(initializeOptionsWithEnhancements); - }, [toolbarButtons, api]); + }, [toolbarButtons, api, toolboxState, commandsManager, servicesManager]); const handleToolOptionChange = (toolName, optionName, newValue) => { api.handleToolOptionChange(toolName, optionName, newValue); @@ -118,7 +147,7 @@ function Toolbox({ servicesManager, buttonSectionId, commandsManager, title, ... {...props} title={title} toolbarButtons={toolbarButtons} - activeToolOptions={toolboxState.toolOptions?.[toolboxState.activeTool]} + toolboxState={toolboxState} handleToolSelect={id => api.handleToolSelect(id)} handleToolOptionChange={handleToolOptionChange} onInteraction={onInteraction} diff --git a/platform/ui/src/components/Toolbox/ToolboxUI.tsx b/platform/ui/src/components/Toolbox/ToolboxUI.tsx index 6a102a1951..4b1dec6efc 100644 --- a/platform/ui/src/components/Toolbox/ToolboxUI.tsx +++ b/platform/ui/src/components/Toolbox/ToolboxUI.tsx @@ -1,23 +1,55 @@ -import React from 'react'; -import { PanelSection, ToolSettings, Tooltip } from '../../components'; +import React, { useEffect, useRef } from 'react'; +import { PanelSection, ToolSettings } from '../../components'; import classnames from 'classnames'; const ItemsPerRow = 4; +function usePrevious(value) { + const ref = useRef(); + useEffect(() => { + ref.current = value; + }); + return ref.current; +} + /** * Just refactoring from the toolbox component to make it more readable */ -function ToolboxUI(props) { +function ToolboxUI(props: withAppTypes) { const { toolbarButtons, handleToolSelect, - activeToolOptions, + toolboxState, numRows, servicesManager, title, useCollapsedPanel = true, } = props; + const { activeTool, toolOptions, selectedEvent } = toolboxState; + const activeToolOptions = toolOptions?.[activeTool]; + + const prevToolOptions = usePrevious(activeToolOptions); + + useEffect(() => { + if (!activeToolOptions || Array.isArray(activeToolOptions) === false) { + return; + } + + activeToolOptions.forEach((option, index) => { + const prevOption = prevToolOptions ? prevToolOptions[index] : undefined; + if (!prevOption || option.value !== prevOption.value || selectedEvent) { + const isOptionValid = option.condition + ? option.condition({ options: activeToolOptions }) + : true; + if (isOptionValid) { + const { commands } = option; + commands(option.value); + } + } + }); + }, [activeToolOptions, selectedEvent]); + const render = () => { return ( <> @@ -34,7 +66,8 @@ function ToolboxUI(props) { const toolClasses = `ml-1 ${isLastRow ? '' : 'mb-2'}`; const onInteraction = ({ itemId, id, commands }) => { - handleToolSelect(itemId || id); + const idToUse = itemId || id; + handleToolSelect(idToUse); props.onInteraction({ itemId, commands, diff --git a/platform/ui/src/components/Tooltip/PortalTooltip.tsx b/platform/ui/src/components/Tooltip/PortalTooltip.tsx index cf20549721..225bf2c360 100644 --- a/platform/ui/src/components/Tooltip/PortalTooltip.tsx +++ b/platform/ui/src/components/Tooltip/PortalTooltip.tsx @@ -39,8 +39,8 @@ export default class PortalTooltip extends React.Component { if (!portalNodes[this.props.group]) { this.createPortal(); } - let { parent, ...other } = props; - let parentEl = typeof parent === 'string' ? document.querySelector(parent) : parent; + const { parent, ...other } = props; + const parentEl = typeof parent === 'string' ? document.querySelector(parent) : parent; ReactDOM.render( { const [isActive, setIsActive] = useState(false); @@ -78,6 +78,13 @@ const Tooltip = ({ handleMouseOutDebounced(); }; + useEffect(() => { + return () => { + handleMouseOverDebounced.cancel(); + handleMouseOutDebounced.cancel(); + }; + }, [handleMouseOverDebounced, handleMouseOutDebounced]); + useEffect(() => { if (!isOpen && onHide) { onHide(); @@ -182,14 +189,6 @@ const Tooltip = ({ ); }; -Tooltip.defaultProps = { - tight: false, - isSticky: false, - position: 'bottom', - isDisabled: false, - showHideDelay: 300, -}; - Tooltip.propTypes = { isDisabled: PropTypes.bool, content: PropTypes.oneOfType([PropTypes.node, PropTypes.func]), diff --git a/platform/ui/src/components/TooltipClipboard/TooltipClipboard.tsx b/platform/ui/src/components/TooltipClipboard/TooltipClipboard.tsx index c48755363e..aea55941ae 100644 --- a/platform/ui/src/components/TooltipClipboard/TooltipClipboard.tsx +++ b/platform/ui/src/components/TooltipClipboard/TooltipClipboard.tsx @@ -9,7 +9,7 @@ const DELAY_TO_SHOW = 1000; const DELAY_TO_HIDE = 10; // it needs at least a little delay to prevent tooltip to suddenly hide const DELAY_TO_HIDE_AFTER_COPYING = 1000; -const TooltipClipboard = ({ children, text }) => { +const TooltipClipboard = ({ children, text = '' }) => { const { t } = useTranslation('TooltipClipboard'); const [isActive, setIsActive] = useState(false); @@ -158,10 +158,6 @@ const TooltipClipboard = ({ children, text }) => { ); }; -TooltipClipboard.defaultProps = { - text: '', -}; - TooltipClipboard.propTypes = { text: PropTypes.string, children: PropTypes.node.isRequired, diff --git a/platform/ui/src/components/UserPreferences/UserPreferences.tsx b/platform/ui/src/components/UserPreferences/UserPreferences.tsx index 923838f4fe..5e61210c8e 100644 --- a/platform/ui/src/components/UserPreferences/UserPreferences.tsx +++ b/platform/ui/src/components/UserPreferences/UserPreferences.tsx @@ -12,12 +12,12 @@ const UserPreferences = ({ availableLanguages, defaultLanguage, currentLanguage, - disabled, + disabled = false, hotkeyDefinitions, hotkeyDefaults, - onCancel, - onSubmit, - onReset, + onCancel = () => {}, + onSubmit = () => {}, + onReset = () => {}, hotkeysModule, }) => { const { t } = useTranslation('UserPreferencesModal'); @@ -140,12 +140,6 @@ UserPreferences.propTypes = { disabled: PropTypes.bool, hotkeyDefaults: PropTypes.object.isRequired, hotkeyDefinitions: PropTypes.object.isRequired, - languageOptions: PropTypes.arrayOf( - PropTypes.shape({ - label: PropTypes.string.isRequired, - value: PropTypes.any.isRequired, - }) - ), onCancel: PropTypes.func, onSubmit: PropTypes.func, onReset: PropTypes.func, @@ -158,15 +152,4 @@ UserPreferences.propTypes = { }).isRequired, }; -UserPreferences.defaultProps = { - languageOptions: [ - { value: 'ONE', label: 'ONE' }, - { value: 'TWO', label: 'TWO' }, - ], - onCancel: noop, - onSubmit: noop, - onReset: noop, - disabled: false, -}; - export default UserPreferences; diff --git a/platform/ui/src/components/ViewportPane/ViewportPane.tsx b/platform/ui/src/components/ViewportPane/ViewportPane.tsx index ada09c871d..33fd2174b4 100644 --- a/platform/ui/src/components/ViewportPane/ViewportPane.tsx +++ b/platform/ui/src/components/ViewportPane/ViewportPane.tsx @@ -13,7 +13,7 @@ function ViewportPane({ isActive, onDrop, onDoubleClick, - onInteraction, + onInteraction = () => {}, acceptDropsFor, }) { let dropElement = null; @@ -108,10 +108,4 @@ ViewportPane.propTypes = { onDoubleClick: PropTypes.func, }; -const noop = () => {}; - -ViewportPane.defaultProps = { - onInteraction: noop, -}; - export default ViewportPane; diff --git a/platform/ui/src/components/WindowLevel/WindowLevel.tsx b/platform/ui/src/components/WindowLevel/WindowLevel.tsx index 7fd1c390f8..53a7258e57 100644 --- a/platform/ui/src/components/WindowLevel/WindowLevel.tsx +++ b/platform/ui/src/components/WindowLevel/WindowLevel.tsx @@ -12,7 +12,6 @@ import { histogramPropType, colormapPropType, } from './types'; -import PanelSection from '../PanelSection'; const convertVOItoVOIRange = voi => { return { @@ -22,21 +21,19 @@ const convertVOItoVOIRange = voi => { }; const WindowLevel = ({ - title, - step, + step = 1, histogram, voi: voiProp, - opacity: opacityProp, - showOpacitySlider, + opacity: opacityProp = 1, + showOpacitySlider = false, colormap, - style, - fillColor, - lineColor, + style = 'polygon', + fillColor = '#3f3f3f', + lineColor = '#707070', containerClassName, onVOIChange, onOpacityChange, }: { - title: string; step: number; histogram: Histogram; voi: VOI; @@ -105,7 +102,6 @@ const WindowLevel = ({ return (
- {/* {title} */}
{range.min} @@ -161,17 +157,7 @@ const WindowLevel = ({ ); }; -WindowLevel.defaultProps = { - step: 1, - opacity: 1, - showOpacitySlider: false, - style: 'polygon', - fillColor: '#3f3f3f', - lineColor: '#707070', -}; - WindowLevel.propTypes = { - title: PropTypes.string, step: PropTypes.number, histogram: histogramPropType.isRequired, voi: voiPropType, diff --git a/platform/ui/src/components/WindowLevel/WindowLevelHistogram.tsx b/platform/ui/src/components/WindowLevel/WindowLevelHistogram.tsx index 987263a96d..9e116d3583 100644 --- a/platform/ui/src/components/WindowLevel/WindowLevelHistogram.tsx +++ b/platform/ui/src/components/WindowLevel/WindowLevelHistogram.tsx @@ -154,10 +154,10 @@ const WindowLevelHistogram = ({ range, voiRange, histogram, - colormap, - style, - fillColor, - lineColor, + colormap = DEFAULT_COLORMAP, + style = 'polygon', + fillColor = '#3f3f3f', + lineColor = '#707070', }: { range: Range; voiRange: VOIRange; @@ -216,13 +216,6 @@ const WindowLevelHistogram = ({ ); }; -WindowLevelHistogram.defaultProps = { - colormap: DEFAULT_COLORMAP, - style: 'polygon', - fillColor: '#3f3f3f', - lineColor: '#707070', -}; - WindowLevelHistogram.propTypes = { range: rangePropType.isRequired, voiRange: voiRangePropType.isRequired, diff --git a/platform/ui/src/components/index.js b/platform/ui/src/components/index.js index f3e62c8472..52020efd55 100644 --- a/platform/ui/src/components/index.js +++ b/platform/ui/src/components/index.js @@ -95,6 +95,7 @@ import InvestigationalUseDialog from './InvestigationalUseDialog'; import MeasurementItem from './MeasurementTable/MeasurementItem'; import LayoutPreset from './LayoutPreset'; import ActionButtons from './ActionButtons'; +import StudyBrowserSort from './StudyBrowserSort'; export { ActionButtons, @@ -198,4 +199,5 @@ export { ToolSettings, Toolbox, InvestigationalUseDialog, + StudyBrowserSort, }; diff --git a/platform/ui/src/contextProviders/DialogProvider.tsx b/platform/ui/src/contextProviders/DialogProvider.tsx index b1cef23fe7..9e0667ae70 100644 --- a/platform/ui/src/contextProviders/DialogProvider.tsx +++ b/platform/ui/src/contextProviders/DialogProvider.tsx @@ -17,7 +17,7 @@ const DialogContext = createContext(null); export const useDialog = () => useContext(DialogContext); -const DialogProvider = ({ children, service }) => { +const DialogProvider = ({ children, service = null }) => { const [isDragging, setIsDragging] = useState(false); const [dialogs, setDialogs] = useState([]); const [lastDialogId, setLastDialogId] = useState(null); @@ -300,10 +300,6 @@ export const withDialog = Component => { }; }; -DialogProvider.defaultProps = { - service: null, -}; - DialogProvider.propTypes = { children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node, PropTypes.func]) .isRequired, diff --git a/platform/ui/src/contextProviders/ModalComponent.tsx b/platform/ui/src/contextProviders/ModalComponent.tsx index ad7e56d330..3de9dce3e2 100644 --- a/platform/ui/src/contextProviders/ModalComponent.tsx +++ b/platform/ui/src/contextProviders/ModalComponent.tsx @@ -2,27 +2,17 @@ import PropTypes from 'prop-types'; import React from 'react'; export const ModalComponent = ({ - content, - contentProps, - shouldCloseOnEsc, - isOpen, - closeButton, - title, - customClassName, + content = null, + contentProps = null, + shouldCloseOnEsc = true, + isOpen = true, + closeButton = true, + title = null, + customClassName = '', }) => { return <>; }; -ModalComponent.defaultProps = { - content: null, - contentProps: null, - shouldCloseOnEsc: true, - isOpen: true, - closeButton: true, - title: null, - customClassName: '', -}; - ModalComponent.propTypes = { content: PropTypes.node, contentProps: PropTypes.object, diff --git a/platform/ui/src/contextProviders/ModalProvider.tsx b/platform/ui/src/contextProviders/ModalProvider.tsx index edda2eccc9..19f31982d6 100644 --- a/platform/ui/src/contextProviders/ModalProvider.tsx +++ b/platform/ui/src/contextProviders/ModalProvider.tsx @@ -21,7 +21,7 @@ export const useModal = () => useContext(ModalContext); * @property {string} [customClassName=null] The custom class to style the modal. */ -const ModalProvider = ({ children, modal: Modal, service }) => { +const ModalProvider = ({ children, modal: Modal, service = null }) => { const DEFAULT_OPTIONS = { content: null, contentProps: null, @@ -125,10 +125,6 @@ export const withModal = Component => { }; }; -ModalProvider.defaultProps = { - service: null, -}; - ModalProvider.propTypes = { children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired, modal: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node, PropTypes.func]) diff --git a/platform/ui/src/contextProviders/SnackbarProvider.tsx b/platform/ui/src/contextProviders/SnackbarProvider.tsx index edc6b43a0e..05ef35042b 100644 --- a/platform/ui/src/contextProviders/SnackbarProvider.tsx +++ b/platform/ui/src/contextProviders/SnackbarProvider.tsx @@ -8,7 +8,7 @@ const SnackbarContext = createContext(null); export const useSnackbar = () => useContext(SnackbarContext); -const SnackbarProvider = ({ children, service }) => { +const SnackbarProvider = ({ children, service = null }) => { const DEFAULT_OPTIONS = { title: '', message: '', @@ -104,10 +104,6 @@ const SnackbarProvider = ({ children, service }) => { ); }; -SnackbarProvider.defaultProps = { - service: null, -}; - SnackbarProvider.propTypes = { children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node, PropTypes.func]) .isRequired, diff --git a/platform/ui/src/contextProviders/Toolbox/ToolboxContext.tsx b/platform/ui/src/contextProviders/Toolbox/ToolboxContext.tsx index 1a61e3fe9c..23c87f80f1 100644 --- a/platform/ui/src/contextProviders/Toolbox/ToolboxContext.tsx +++ b/platform/ui/src/contextProviders/Toolbox/ToolboxContext.tsx @@ -6,7 +6,7 @@ export const toolboxReducer = (state, action) => { const { toolbarSectionId } = action.payload; if (!state[toolbarSectionId]) { - state[toolbarSectionId] = { activeTool: null, toolOptions: {} }; + state[toolbarSectionId] = { activeTool: null, toolOptions: {}, selectedEvent: false }; } switch (action.type) { @@ -16,6 +16,7 @@ export const toolboxReducer = (state, action) => { [toolbarSectionId]: { ...state[toolbarSectionId], activeTool: action.payload.activeTool, + selectedEvent: true, }, }; case 'UPDATE_TOOL_OPTION': @@ -24,6 +25,7 @@ export const toolboxReducer = (state, action) => { ...state, [toolbarSectionId]: { ...state[toolbarSectionId], + selectedEvent: false, toolOptions: { ...state[toolbarSectionId].toolOptions, [toolName]: state[toolbarSectionId].toolOptions[toolName].map(option => @@ -36,6 +38,7 @@ export const toolboxReducer = (state, action) => { // Initialize tool options for each toolbarSectionId return { ...state, + selectedEvent: false, [action.toolbarSectionId]: { ...state[action.toolbarSectionId], toolOptions: action.payload, diff --git a/platform/ui/src/contextProviders/ViewportGridProvider.tsx b/platform/ui/src/contextProviders/ViewportGridProvider.tsx index 72fc67fb43..9f1ae81553 100644 --- a/platform/ui/src/contextProviders/ViewportGridProvider.tsx +++ b/platform/ui/src/contextProviders/ViewportGridProvider.tsx @@ -160,6 +160,14 @@ export function ViewportGridProvider({ children, service }) { const previousViewport = viewports.get(viewportId); + // remove options that were meant for one time usage + if (previousViewport?.viewportOptions?.initialImageOptions) { + const { useOnce } = previousViewport.viewportOptions.initialImageOptions; + if (useOnce) { + previousViewport.viewportOptions.initialImageOptions = null; + } + } + // Use the newly provide viewportOptions and display set options // when provided, and otherwise fall back to the previous ones. // That allows for easy updates of just the display set. @@ -182,8 +190,10 @@ export function ViewportGridProvider({ children, service }) { // if it is not part of the hanging protocol layout, we should remove the toolGroupId // and viewportType from the viewportOptions so that it doesn't - // inherit the hanging protocol layout options - if (!state.isHangingProtocolLayout) { + // inherit the hanging protocol layout options, only when + // the viewport options is not provided (e.g., when drag and drop) + // otherwise, programmatically set options should be preserved + if (!updatedViewport.viewportOptions && !state.isHangingProtocolLayout) { viewportOptions = { viewportId: viewportOptions.viewportId, }; @@ -224,7 +234,6 @@ export function ViewportGridProvider({ children, service }) { // If empty viewportOptions, we use numRow and numCols to calculate number of viewports const hasOptions = layoutOptions?.length; const viewports = new Map(); - // Options is a temporary state store which can be used by the // findOrCreate to store state about already found viewports. Typically, // it will be used to store the display set UID's which are already @@ -237,7 +246,21 @@ export function ViewportGridProvider({ children, service }) { for (let col = 0; col < numCols; col++) { const position = col + row * numCols; const layoutOption = layoutOptions[position]; - const positionId = layoutOption?.positionId || `${col}-${row}`; + + let xPos, yPos, w, h; + if (layoutOptions && layoutOptions[position]) { + ({ x: xPos, y: yPos, width: w, height: h } = layoutOptions[position]); + } else { + w = 1 / numCols; + h = 1 / numRows; + xPos = col * w; + yPos = row * h; + } + + const colIndex = Math.round(xPos * numCols); + const rowIndex = Math.round(yPos * numRows); + + const positionId = layoutOption?.positionId || `${colIndex}-${rowIndex}`; if (hasOptions && position >= layoutOptions.length) { continue; @@ -264,16 +287,6 @@ export function ViewportGridProvider({ children, service }) { // and it is part of the read only state viewports.set(viewport.viewportId, viewport); - let xPos, yPos, w, h; - if (layoutOptions && layoutOptions[position]) { - ({ x: xPos, y: yPos, width: w, height: h } = layoutOptions[position]); - } else { - w = 1 / numCols; - h = 1 / numRows; - xPos = col * w; - yPos = row * h; - } - Object.assign(viewport, { width: w, height: h, diff --git a/platform/ui/src/hooks/useSessionStorage.test.js b/platform/ui/src/hooks/useSessionStorage.test.js index bd3645db24..2da1992c0c 100644 --- a/platform/ui/src/hooks/useSessionStorage.test.js +++ b/platform/ui/src/hooks/useSessionStorage.test.js @@ -1,4 +1,5 @@ -import { renderHook, act } from '@testing-library/react-hooks'; +import { act } from 'react'; +import { renderHook } from '@testing-library/react'; import useSessionStorage from './useSessionStorage'; const SESSION_STORAGE_KEY = 'test'; diff --git a/platform/ui/src/index.js b/platform/ui/src/index.js index 214b4584a8..b240a6e4b5 100644 --- a/platform/ui/src/index.js +++ b/platform/ui/src/index.js @@ -132,6 +132,7 @@ export { Toolbox, InvestigationalUseDialog, LayoutPreset, + StudyBrowserSort, } from './components'; export { useSessionStorage } from './hooks'; diff --git a/platform/ui/tailwind.config.js b/platform/ui/tailwind.config.js index fed8ac10a9..29e859d8f0 100644 --- a/platform/ui/tailwind.config.js +++ b/platform/ui/tailwind.config.js @@ -34,7 +34,6 @@ module.exports = { dark: '#090c29', active: '#348cfd', }, - inputfield: { main: '#3a3f99', disabled: '#2b166b', @@ -49,6 +48,10 @@ module.exports = { active: '#1f1f27', }, + indigo: { + dark: '#0b1a42', + }, + common: { bright: '#e1e1e1', light: '#a19fad', diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000000..4245ce7623 --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,44 @@ +import { defineConfig, devices } from '@playwright/test'; + +export default defineConfig({ + testDir: './tests', + fullyParallel: true, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 2 : 0, + workers: process.env.CI ? 1 : undefined, + snapshotPathTemplate: './tests/screenshots{/projectName}/{testFilePath}/{arg}{ext}', + outputDir: './tests/test-results', + reporter: [[process.env.CI ? 'blob' : 'html', { outputFolder: './tests/playwright-report' }]], + timeout: 720 * 1000, + use: { + baseURL: 'http://localhost:3000', + trace: 'on-first-retry', + video: 'on', + testIdAttribute: 'data-cy', + }, + + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'], deviceScaleFactor: 1 }, + }, + // TODO: Fix firefox tests + // { + // name: 'firefox', + // use: { ...devices['Desktop Firefox'], deviceScaleFactor: 1 }, + // }, + // This is commented out until SharedArrayBuffer is enabled in WebKit + // See: https://github.com/microsoft/playwright/issues/14043 + + //{ + // name: 'webkit', + // use: { ...devices['Desktop Safari'], deviceScaleFactor: 1 }, + //}, + ], + webServer: { + command: 'yarn test:e2e:serve', + url: 'http://localhost:3000', + reuseExistingServer: !process.env.CI, + timeout: 240 * 1000, + }, +}); diff --git a/testdata b/testdata index c9892af83d..bd743ed76b 160000 --- a/testdata +++ b/testdata @@ -1 +1 @@ -Subproject commit c9892af83d5dc4b06fac6ff1ca77246467571ec0 +Subproject commit bd743ed76b403e6d476e1af0bbfe7479d96b563d diff --git a/tests/3DFourUp.spec.ts b/tests/3DFourUp.spec.ts new file mode 100644 index 0000000000..e196856d9c --- /dev/null +++ b/tests/3DFourUp.spec.ts @@ -0,0 +1,26 @@ +import { test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths, reduce3DViewportSize } from './utils'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '1.3.6.1.4.1.14519.5.2.1.1706.8374.643249677828306008300337414785'; + const mode = 'Basic Viewer'; + await visitStudy(page, studyInstanceUID, mode, 2000); +}); + +test.describe('3D four up Test', async () => { + test('should render 3D four up correctly.', async ({ page }) => { + await page.getByTestId('Layout').click(); + await page + .locator('div') + .filter({ hasText: /^3D four up$/ }) + .first() + .click(); + await reduce3DViewportSize(page); + await checkForScreenshot( + page, + page, + screenShotPaths.threeDFourUp.threeDFourUpDisplayedCorrectly, + 200 + ); + }); +}); diff --git a/tests/3DMain.spec.ts b/tests/3DMain.spec.ts new file mode 100644 index 0000000000..f0ce18f34a --- /dev/null +++ b/tests/3DMain.spec.ts @@ -0,0 +1,26 @@ +import { test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths, reduce3DViewportSize } from './utils'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '1.3.6.1.4.1.14519.5.2.1.1706.8374.643249677828306008300337414785'; + const mode = 'Basic Viewer'; + await visitStudy(page, studyInstanceUID, mode, 2000); +}); + +test.describe('3D main Test', async () => { + test('should render 3D main correctly.', async ({ page }) => { + await page.getByTestId('Layout').click(); + await page + .locator('div') + .filter({ hasText: /^3D main$/ }) + .first() + .click(); + await reduce3DViewportSize(page); + await checkForScreenshot( + page, + page, + screenShotPaths.threeDMain.threeDMainDisplayedCorrectly, + 200 + ); + }); +}); diff --git a/tests/3DOnly.spec.ts b/tests/3DOnly.spec.ts new file mode 100644 index 0000000000..28489d0247 --- /dev/null +++ b/tests/3DOnly.spec.ts @@ -0,0 +1,26 @@ +import { test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths, reduce3DViewportSize } from './utils'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '1.3.6.1.4.1.14519.5.2.1.1706.8374.643249677828306008300337414785'; + const mode = 'Basic Viewer'; + await visitStudy(page, studyInstanceUID, mode, 2000); +}); + +test.describe('3D only Test', async () => { + test('should render 3D only correctly.', async ({ page }) => { + await page.getByTestId('Layout').click(); + await page + .locator('div') + .filter({ hasText: /^3D only$/ }) + .first() + .click(); + await reduce3DViewportSize(page); + await checkForScreenshot( + page, + page, + screenShotPaths.threeDOnly.threeDOnlyDisplayedCorrectly, + 200 + ); + }); +}); diff --git a/tests/3DPrimary.spec.ts b/tests/3DPrimary.spec.ts new file mode 100644 index 0000000000..f384815884 --- /dev/null +++ b/tests/3DPrimary.spec.ts @@ -0,0 +1,27 @@ +import { test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths, reduce3DViewportSize } from './utils'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '1.3.6.1.4.1.14519.5.2.1.1706.8374.643249677828306008300337414785'; + const mode = 'Basic Viewer'; + await visitStudy(page, studyInstanceUID, mode, 2000); +}); + +test.describe('3D primary Test', async () => { + test('should render 3D primary correctly.', async ({ page }) => { + await page.getByTestId('Layout').click(); + await page + .locator('div') + .filter({ hasText: /^3D primary$/ }) + .first() + .click(); + + await reduce3DViewportSize(page); + await checkForScreenshot( + page, + page, + screenShotPaths.threeDPrimary.threeDPrimaryDisplayedCorrectly, + 200 + ); + }); +}); diff --git a/tests/Angle.spec.ts b/tests/Angle.spec.ts new file mode 100644 index 0000000000..88ef1c4591 --- /dev/null +++ b/tests/Angle.spec.ts @@ -0,0 +1,33 @@ +import { test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths, simulateClicksOnElement } from './utils'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; + const mode = 'Basic Viewer'; + await visitStudy(page, studyInstanceUID, mode, 2000); +}); + +test('should display the angle tool', async ({ page }) => { + await page.getByTestId('MoreTools-split-button-secondary').click(); + await page.getByTestId('Angle').click(); + const locator = page.getByTestId('viewport-pane').locator('canvas'); + await simulateClicksOnElement({ + locator, + points: [ + { + x: 550, + y: 200, + }, + { + x: 450, + y: 250, + }, + { + x: 550, + y: 300, + }, + ], + }); + await page.getByTestId('prompt-begin-tracking-yes-btn').click(); + await checkForScreenshot(page, page, screenShotPaths.angle.angleDisplayedCorrectly); +}); diff --git a/tests/AxialPrimary.spec.ts b/tests/AxialPrimary.spec.ts new file mode 100644 index 0000000000..8826ed031e --- /dev/null +++ b/tests/AxialPrimary.spec.ts @@ -0,0 +1,25 @@ +import { test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '1.3.6.1.4.1.14519.5.2.1.1706.8374.643249677828306008300337414785'; + const mode = 'Basic Viewer'; + await visitStudy(page, studyInstanceUID, mode, 2000); +}); + +test.describe('Axial Primary Test', async () => { + test('should render Axial Primary correctly.', async ({ page }) => { + await page.getByTestId('Layout').click(); + await page + .locator('div') + .filter({ hasText: /^Axial Primary$/ }) + .first() + .click(); + await checkForScreenshot( + page, + page, + screenShotPaths.axialPrimary.axialPrimaryDisplayedCorrectly, + 200 + ); + }); +}); diff --git a/tests/Bidirectional.spec.ts b/tests/Bidirectional.spec.ts new file mode 100644 index 0000000000..68268480a6 --- /dev/null +++ b/tests/Bidirectional.spec.ts @@ -0,0 +1,34 @@ +import { test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths, simulateClicksOnElement } from './utils'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; + const mode = 'Basic Viewer'; + await visitStudy(page, studyInstanceUID, mode, 2000); +}); + +test('should display the bidirectional tool', async ({ page }) => { + await page.getByTestId('MeasurementTools-split-button-secondary').click(); + await page.getByTestId('Bidirectional').click(); + const locator = page.getByTestId('viewport-pane').locator('canvas'); + + await simulateClicksOnElement({ + locator, + points: [ + { + x: 405, + y: 277, + }, + { + x: 515, + y: 339, + }, + ], + }); + await page.getByTestId('prompt-begin-tracking-yes-btn').click(); + await checkForScreenshot( + page, + page, + screenShotPaths.bidirectional.bidirectionalDisplayedCorrectly + ); +}); diff --git a/tests/Circle.spec.ts b/tests/Circle.spec.ts new file mode 100644 index 0000000000..c3505f5e01 --- /dev/null +++ b/tests/Circle.spec.ts @@ -0,0 +1,29 @@ +import { test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths, simulateClicksOnElement } from './utils'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; + const mode = 'Basic Viewer'; + await visitStudy(page, studyInstanceUID, mode, 2000); +}); + +test('should display the circle tool', async ({ page }) => { + await page.getByTestId('MeasurementTools-split-button-secondary').click(); + await page.getByTestId('CircleROI').click(); + const locator = page.getByTestId('viewport-pane').locator('canvas'); + await simulateClicksOnElement({ + locator, + points: [ + { + x: 480, + y: 205, + }, + { + x: 488, + y: 247, + }, + ], + }); + await page.getByTestId('prompt-begin-tracking-yes-btn').click(); + await checkForScreenshot(page, page, screenShotPaths.circle.circleDisplayedCorrectly); +}); diff --git a/tests/CobbAngle.spec.ts b/tests/CobbAngle.spec.ts new file mode 100644 index 0000000000..d142535c29 --- /dev/null +++ b/tests/CobbAngle.spec.ts @@ -0,0 +1,37 @@ +import { test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths, simulateClicksOnElement } from './utils'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; + const mode = 'Basic Viewer'; + await visitStudy(page, studyInstanceUID, mode, 2000); +}); + +test('should display the cobb angle tool', async ({ page }) => { + await page.getByTestId('MoreTools-split-button-secondary').click(); + await page.getByTestId('CobbAngle').click(); + const locator = page.getByTestId('viewport-pane').locator('canvas'); + await simulateClicksOnElement({ + locator, + points: [ + { + x: 515, + y: 212, + }, + { + x: 616, + y: 207, + }, + { + x: 527, + y: 293, + }, + { + x: 625, + y: 291, + }, + ], + }); + await page.getByTestId('prompt-begin-tracking-yes-btn').click(); + await checkForScreenshot(page, page, screenShotPaths.cobbangle.cobbangleDisplayedCorrectly); +}); diff --git a/tests/Crosshairs.spec.ts b/tests/Crosshairs.spec.ts new file mode 100644 index 0000000000..c711177bc9 --- /dev/null +++ b/tests/Crosshairs.spec.ts @@ -0,0 +1,104 @@ +import { Page, test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths, initilizeMousePositionTracker, getMousePosition } from './utils/index.js'; + + +const rotateCrosshairs = async (page: Page, id: string, lineNumber: number) => { + const locator = await page.locator(id).locator('line').nth(lineNumber); + await locator.click({ force: true }); + await locator.hover({ force: true }); + const circleLocator = await page.locator(id).locator('circle').nth(1); + await circleLocator.hover({ force: true }); + await page.mouse.down(); + const position = await getMousePosition(page); + await page.mouse.move(position.x, position.y + 100); + await page.mouse.up(); +} + +const increaseSlabThickness = async (page: Page, id: string, lineNumber: number, axis: string) => { + const locator = await page.locator(id).locator('line').nth(lineNumber) + await locator.click({ force: true }); + await locator.hover({ force: true }); + const circleLocator = await page.locator(id).locator('rect').first(); + await circleLocator.hover({ force: true }); + await page.mouse.down(); + const position = await getMousePosition(page); + switch (axis) { + case 'x': + await page.mouse.move(position.x + 100, position.y); + break; + case 'y': + await page.mouse.move(position.x, position.y + 100); + break; + } + await page.mouse.up(); +} + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '1.3.6.1.4.1.14519.5.2.1.1706.8374.643249677828306008300337414785'; + const mode = 'Basic Viewer'; + await visitStudy(page, studyInstanceUID, mode, 2000); + await initilizeMousePositionTracker(page); +}); + +test.describe('Crosshairs Test', async () => { + test('should render the crosshairs correctly.', async ({ page }) => { + await page.getByTestId('Layout').click(); + await page.locator('div').filter({ hasText: /^MPR$/ }).first().click(); + await page.getByTestId('Crosshairs').click(); + + await checkForScreenshot(page, page, screenShotPaths.crosshairs.crosshairsRendered); + }); + + test('should allow the user to rotate the crosshairs', async ({ page }) => { + await page.getByTestId('Layout').click(); + await page.locator('div').filter({ hasText: /^MPR$/ }).first().click(); + await page.getByTestId('Crosshairs').click(); + + await rotateCrosshairs(page, '#svg-layer-mpr-axial', 3); + await rotateCrosshairs(page, '#svg-layer-mpr-sagittal', 0); + await rotateCrosshairs(page, '#svg-layer-mpr-coronal', 0); + + await checkForScreenshot(page, page, screenShotPaths.crosshairs.crosshairsRotated); + }); + + test('should allow the user to adjust the slab thickness', async ({ page }) => { + await page.getByTestId('Layout').click(); + await page.locator('div').filter({ hasText: /^MPR$/ }).first().click(); + await page.getByTestId('Crosshairs').click(); + + await increaseSlabThickness(page, '#svg-layer-mpr-axial', 0, 'x'); + await increaseSlabThickness(page, '#svg-layer-mpr-sagittal', 2, 'x'); + await increaseSlabThickness(page, '#svg-layer-mpr-coronal', 0, 'y'); + + await checkForScreenshot(page, page, screenShotPaths.crosshairs.crosshairsSlabThickness); + }); + + test('should reset the crosshairs to the initial position when reset is clicked', async ({ page }) => { + await page.getByTestId('Layout').click(); + await page.locator('div').filter({ hasText: /^MPR$/ }).first().click(); + await page.getByTestId('Crosshairs').click(); + + await rotateCrosshairs(page, '#svg-layer-mpr-axial', 3); + await rotateCrosshairs(page, '#svg-layer-mpr-sagittal', 0); + await rotateCrosshairs(page, '#svg-layer-mpr-coronal', 0); + + await page.getByTestId('MoreTools-split-button-primary').click(); + + await checkForScreenshot(page, page, screenShotPaths.crosshairs.crosshairsResetToolbar); + }); + + test('should reset the crosshairs when a new displayset is loaded', async ({ page }) => { + await page.getByTestId('Layout').click(); + await page.locator('div').filter({ hasText: /^MPR$/ }).first().click(); + await page.getByTestId('Crosshairs').click(); + + await rotateCrosshairs(page, '#svg-layer-mpr-axial', 0); + await rotateCrosshairs(page, '#svg-layer-mpr-sagittal', 0); + await rotateCrosshairs(page, '#svg-layer-mpr-coronal', 3); + + await page.getByTestId('study-browser-thumbnail').nth(1).dblclick(); + + await checkForScreenshot(page, page, screenShotPaths.crosshairs.crosshairsNewDisplayset); + }); + +}); diff --git a/tests/DicomTagBrowser.spec.ts b/tests/DicomTagBrowser.spec.ts new file mode 100644 index 0000000000..1e4136c421 --- /dev/null +++ b/tests/DicomTagBrowser.spec.ts @@ -0,0 +1,18 @@ +import { test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; + const mode = 'Basic Viewer'; + await visitStudy(page, studyInstanceUID, mode, 2000); +}); + +test('should display the dicom tag browser', async ({ page }) => { + await page.getByTestId('MoreTools-split-button-secondary').click(); + await page.getByTestId('TagBrowser').click(); + await checkForScreenshot( + page, + page, + screenShotPaths.dicomTagBrowser.dicomTagBrowserDisplayedCorrectly + ); +}); diff --git a/tests/Ellipse.spec.ts b/tests/Ellipse.spec.ts new file mode 100644 index 0000000000..3dca6cdd35 --- /dev/null +++ b/tests/Ellipse.spec.ts @@ -0,0 +1,29 @@ +import { test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths, simulateClicksOnElement } from './utils'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; + const mode = 'Basic Viewer'; + await visitStudy(page, studyInstanceUID, mode, 2000); +}); + +test('should display the ellipse tool', async ({ page }) => { + await page.getByTestId('MeasurementTools-split-button-secondary').click(); + await page.getByTestId('EllipticalROI').click(); + const locator = page.getByTestId('viewport-pane').locator('canvas'); + await simulateClicksOnElement({ + locator, + points: [ + { + x: 446, + y: 245, + }, + { + x: 508, + y: 281, + }, + ], + }); + await page.getByTestId('prompt-begin-tracking-yes-btn').click(); + await checkForScreenshot(page, page, screenShotPaths.ellipse.ellipseDisplayedCorrectly); +}); diff --git a/tests/FlipHorizontal.spec.ts b/tests/FlipHorizontal.spec.ts new file mode 100644 index 0000000000..7477a050c9 --- /dev/null +++ b/tests/FlipHorizontal.spec.ts @@ -0,0 +1,18 @@ +import { test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '2.16.840.1.114362.1.11972228.22789312658.616067305.306.2'; + const mode = 'Basic Viewer'; + await visitStudy(page, studyInstanceUID, mode, 2000); +}); + +test('should flip the image horizontally', async ({ page }) => { + await page.getByTestId('MoreTools-split-button-secondary').click(); + await page.getByTestId('flipHorizontal').click(); + await checkForScreenshot( + page, + page, + screenShotPaths.flipHorizontal.flipHorizontalDisplayedCorrectly + ); +}); diff --git a/tests/Invert.spec.ts b/tests/Invert.spec.ts new file mode 100644 index 0000000000..bbff4657c7 --- /dev/null +++ b/tests/Invert.spec.ts @@ -0,0 +1,14 @@ +import { test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; + const mode = 'Basic Viewer'; + await visitStudy(page, studyInstanceUID, mode, 2000); +}); + +test('should invert the image', async ({ page }) => { + await page.getByTestId('MoreTools-split-button-secondary').click(); + await page.getByTestId('invert').click(); + await checkForScreenshot(page, page, screenShotPaths.invert.invertDisplayedCorrectly); +}); diff --git a/tests/Length.spec.ts b/tests/Length.spec.ts new file mode 100644 index 0000000000..8b6c51f301 --- /dev/null +++ b/tests/Length.spec.ts @@ -0,0 +1,28 @@ +import { test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths, simulateClicksOnElement } from './utils'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; + const mode = 'Basic Viewer'; + await visitStudy(page, studyInstanceUID, mode, 2000); +}); + +test('should display the length tool', async ({ page }) => { + await page.getByTestId('MeasurementTools-split-button-primary').click(); + const locator = page.getByTestId('viewport-pane').locator('canvas'); + await simulateClicksOnElement({ + locator, + points: [ + { + x: 364, + y: 234, + }, + { + x: 544, + y: 232, + }, + ], + }); + await page.getByTestId('prompt-begin-tracking-yes-btn').click(); + await checkForScreenshot(page, page, screenShotPaths.length.lengthDisplayedCorrectly); +}); diff --git a/tests/Livewire.spec.ts b/tests/Livewire.spec.ts new file mode 100644 index 0000000000..dae68b4498 --- /dev/null +++ b/tests/Livewire.spec.ts @@ -0,0 +1,45 @@ +import { test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths, simulateClicksOnElement } from './utils'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; + const mode = 'Basic Viewer'; + await visitStudy(page, studyInstanceUID, mode, 2000); +}); + +test('should display the livewire tool', async ({ page }) => { + await page.getByTestId('MeasurementTools-split-button-secondary').click(); + await page.getByTestId('LivewireContour').click(); + const locator = page.getByTestId('viewport-pane').locator('canvas'); + await simulateClicksOnElement({ + locator, + points: [ + { + x: 380, + y: 459, + }, + { + x: 420, + y: 396, + }, + { + x: 523, + y: 392, + }, + { + x: 581, + y: 447, + }, + { + x: 482, + y: 493, + }, + { + x: 383, + y: 461, + }, + ], + }); + await page.getByTestId('prompt-begin-tracking-yes-btn').click(); + await checkForScreenshot(page, page, screenShotPaths.livewire.livewireDisplayedCorrectly); +}); diff --git a/tests/MPR.spec.ts b/tests/MPR.spec.ts new file mode 100644 index 0000000000..66c711ada7 --- /dev/null +++ b/tests/MPR.spec.ts @@ -0,0 +1,16 @@ +import { test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths } from './utils/index.js'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '1.3.6.1.4.1.14519.5.2.1.1706.8374.643249677828306008300337414785'; + const mode = 'Basic Viewer'; + await visitStudy(page, studyInstanceUID, mode, 2000); +}); + +test.describe('MPR Test', async () => { + test('should render MPR correctly.', async ({ page }) => { + await page.getByTestId('Layout').click(); + await page.locator('div').filter({ hasText: /^MPR$/ }).first().click(); + await checkForScreenshot(page, page, screenShotPaths.mpr.mprDisplayedCorrectly); + }); +}); diff --git a/tests/Probe.spec.ts b/tests/Probe.spec.ts new file mode 100644 index 0000000000..1a4fac22fe --- /dev/null +++ b/tests/Probe.spec.ts @@ -0,0 +1,25 @@ +import { test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths, simulateClicksOnElement } from './utils'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; + const mode = 'Basic Viewer'; + await visitStudy(page, studyInstanceUID, mode, 2000); +}); + +test('should display the probe tool', async ({ page }) => { + await page.getByTestId('MoreTools-split-button-secondary').click(); + await page.getByTestId('Probe').click(); + const locator = page.getByTestId('viewport-pane').locator('canvas'); + await simulateClicksOnElement({ + locator, + points: [ + { + x: 550, + y: 200, + }, + ], + }); + await page.getByTestId('prompt-begin-tracking-yes-btn').click(); + await checkForScreenshot(page, page, screenShotPaths.probe.probeDisplayedCorrectly); +}); diff --git a/tests/RTHydration.spec.ts b/tests/RTHydration.spec.ts new file mode 100644 index 0000000000..b3638e28d5 --- /dev/null +++ b/tests/RTHydration.spec.ts @@ -0,0 +1,18 @@ +import { test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '1.2.840.113619.2.290.3.3767434740.226.1600859119.501'; + const mode = 'Basic Viewer'; + await visitStudy(page, studyInstanceUID, mode, 2000); +}); + +test('should hydrate RT reports correctly', async ({ page }) => { + await page.getByTestId('side-panel-header-right').click(); + await page.getByTestId('study-browser-thumbnail-no-image').dblclick(); + await checkForScreenshot(page, page, screenShotPaths.rtHydration.rtPreHydration); + await page.getByTestId('yes-hydrate-btn').click(); + await checkForScreenshot(page, page, screenShotPaths.rtHydration.rtPostHydration); + await page.getByText('Small Sphere').click(); + await checkForScreenshot(page, page, screenShotPaths.rtHydration.rtJumpToStructure); +}); diff --git a/tests/Rectangle.spec.ts b/tests/Rectangle.spec.ts new file mode 100644 index 0000000000..904e27a352 --- /dev/null +++ b/tests/Rectangle.spec.ts @@ -0,0 +1,29 @@ +import { test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths, simulateClicksOnElement } from './utils'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; + const mode = 'Basic Viewer'; + await visitStudy(page, studyInstanceUID, mode, 2000); +}); + +test('should display the rectangle tool', async ({ page }) => { + await page.getByTestId('MeasurementTools-split-button-secondary').click(); + await page.getByTestId('RectangleROI').click(); + const locator = page.getByTestId('viewport-pane').locator('canvas'); + await simulateClicksOnElement({ + locator, + points: [ + { + x: 476, + y: 159, + }, + { + x: 591, + y: 217, + }, + ], + }); + await page.getByTestId('prompt-begin-tracking-yes-btn').click(); + await checkForScreenshot(page, page, screenShotPaths.rectangle.rectangleDisplayedCorrectly); +}); diff --git a/tests/Reset.spec.ts b/tests/Reset.spec.ts new file mode 100644 index 0000000000..b4ca11963c --- /dev/null +++ b/tests/Reset.spec.ts @@ -0,0 +1,18 @@ +import { test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '2.16.840.1.114362.1.11972228.22789312658.616067305.306.2'; + const mode = 'Basic Viewer'; + await visitStudy(page, studyInstanceUID, mode, 2000); +}); + +test('should reset the image to its original state', async ({ page }) => { + await page.getByTestId('MoreTools-split-button-secondary').click(); + await page.getByTestId('rotate-right').click(); + await page.getByTestId('MoreTools-split-button-secondary').click(); + await page.getByTestId('invert').click(); + await page.getByTestId('MoreTools-split-button-secondary').click(); + await page.getByTestId('Reset').click(); + await checkForScreenshot(page, page, screenShotPaths.reset.resetDisplayedCorrectly); +}); diff --git a/tests/RotateRight.spec.ts b/tests/RotateRight.spec.ts new file mode 100644 index 0000000000..2f6971a239 --- /dev/null +++ b/tests/RotateRight.spec.ts @@ -0,0 +1,14 @@ +import { test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; + const mode = 'Basic Viewer'; + await visitStudy(page, studyInstanceUID, mode, 2000); +}); + +test('should rotate the image to the right', async ({ page }) => { + await page.getByTestId('MoreTools-split-button-secondary').click(); + await page.getByTestId('rotate-right').click(); + await checkForScreenshot(page, page, screenShotPaths.rotateRight.rotateRightDisplayedCorrectly); +}); diff --git a/tests/SEGHydration.spec.ts b/tests/SEGHydration.spec.ts new file mode 100644 index 0000000000..2077d99fc2 --- /dev/null +++ b/tests/SEGHydration.spec.ts @@ -0,0 +1,18 @@ +import { test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '1.3.6.1.4.1.14519.5.2.1.256467663913010332776401703474716742458'; + const mode = 'Basic Viewer'; + await visitStudy(page, studyInstanceUID, mode, 2000); +}); + +test('should hydrate SEG reports correctly', async ({ page }) => { + await page.getByTestId('side-panel-header-right').click(); + await page.getByTestId('study-browser-thumbnail-no-image').dblclick(); + await checkForScreenshot(page, page, screenShotPaths.segHydration.segPreHydration); + await page.getByTestId('yes-hydrate-btn').click(); + await checkForScreenshot(page, page, screenShotPaths.segHydration.segPostHydration); + await page.getByText('Esophagus').click(); + await checkForScreenshot(page, page, screenShotPaths.segHydration.segJumpToSegment); +}); diff --git a/tests/SRHydration.spec.ts b/tests/SRHydration.spec.ts new file mode 100644 index 0000000000..844f1908de --- /dev/null +++ b/tests/SRHydration.spec.ts @@ -0,0 +1,19 @@ +import { test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '1.3.6.1.4.1.14519.5.2.1.7695.4007.324475281161490036195179843543'; + const mode = 'Basic Viewer'; + await visitStudy(page, studyInstanceUID, mode, 2000); +}); + +test('should hydrate SR reports correctly', async ({ page }) => { + await page.getByTestId('side-panel-header-right').click(); + await page.getByTestId('trackedMeasurements-btn').click(); + await page.getByTestId('study-browser-thumbnail-no-image').dblclick(); + await checkForScreenshot(page, page, screenShotPaths.srHydration.srPreHydration); + await page.getByTestId('yes-hydrate-btn').click(); + await checkForScreenshot(page, page, screenShotPaths.srHydration.srPostHydration); + await page.getByTestId('measurement-item').first().click(); + await checkForScreenshot(page, page, screenShotPaths.srHydration.srJumpToMeasurement); +}); diff --git a/tests/Spline.spec.ts b/tests/Spline.spec.ts new file mode 100644 index 0000000000..acd4adf6a2 --- /dev/null +++ b/tests/Spline.spec.ts @@ -0,0 +1,45 @@ +import { test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths, simulateClicksOnElement } from './utils'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; + const mode = 'Basic Viewer'; + await visitStudy(page, studyInstanceUID, mode, 2000); +}); + +test('should display the spline tool', async ({ page }) => { + await page.getByTestId('MeasurementTools-split-button-secondary').click(); + await page.getByTestId('SplineROI').click(); + const locator = page.getByTestId('viewport-pane').locator('canvas'); + await simulateClicksOnElement({ + locator, + points: [ + { + x: 380, + y: 459, + }, + { + x: 420, + y: 396, + }, + { + x: 523, + y: 392, + }, + { + x: 581, + y: 447, + }, + { + x: 482, + y: 493, + }, + { + x: 383, + y: 461, + }, + ], + }); + await page.getByTestId('prompt-begin-tracking-yes-btn').click(); + await checkForScreenshot(page, page, screenShotPaths.spline.splineDisplayedCorrectly); +}); diff --git a/tests/screenshots/chromium/3DFourUp.spec.ts/threeDFourUpDisplayedCorrectly.png b/tests/screenshots/chromium/3DFourUp.spec.ts/threeDFourUpDisplayedCorrectly.png new file mode 100644 index 0000000000..ddf13a29e7 Binary files /dev/null and b/tests/screenshots/chromium/3DFourUp.spec.ts/threeDFourUpDisplayedCorrectly.png differ diff --git a/tests/screenshots/chromium/3DMain.spec.ts/threeDMainDisplayedCorrectly.png b/tests/screenshots/chromium/3DMain.spec.ts/threeDMainDisplayedCorrectly.png new file mode 100644 index 0000000000..10f72b0fa7 Binary files /dev/null and b/tests/screenshots/chromium/3DMain.spec.ts/threeDMainDisplayedCorrectly.png differ diff --git a/tests/screenshots/chromium/3DOnly.spec.ts/threeDOnlyDisplayedCorrectly.png b/tests/screenshots/chromium/3DOnly.spec.ts/threeDOnlyDisplayedCorrectly.png new file mode 100644 index 0000000000..60dc715509 Binary files /dev/null and b/tests/screenshots/chromium/3DOnly.spec.ts/threeDOnlyDisplayedCorrectly.png differ diff --git a/tests/screenshots/chromium/3DPrimary.spec.ts/threeDPrimaryDisplayedCorrectly.png b/tests/screenshots/chromium/3DPrimary.spec.ts/threeDPrimaryDisplayedCorrectly.png new file mode 100644 index 0000000000..8d1fb1df39 Binary files /dev/null and b/tests/screenshots/chromium/3DPrimary.spec.ts/threeDPrimaryDisplayedCorrectly.png differ diff --git a/tests/screenshots/chromium/Angle.spec.ts/angleDisplayedCorrectly.png b/tests/screenshots/chromium/Angle.spec.ts/angleDisplayedCorrectly.png new file mode 100644 index 0000000000..4e279090ce Binary files /dev/null and b/tests/screenshots/chromium/Angle.spec.ts/angleDisplayedCorrectly.png differ diff --git a/tests/screenshots/chromium/AxialPrimary.spec.ts/axialPrimaryDisplayedCorrectly.png b/tests/screenshots/chromium/AxialPrimary.spec.ts/axialPrimaryDisplayedCorrectly.png new file mode 100644 index 0000000000..babca6641a Binary files /dev/null and b/tests/screenshots/chromium/AxialPrimary.spec.ts/axialPrimaryDisplayedCorrectly.png differ diff --git a/tests/screenshots/chromium/Bidirectional.spec.ts/bidirectionalDisplayedCorrectly.png b/tests/screenshots/chromium/Bidirectional.spec.ts/bidirectionalDisplayedCorrectly.png new file mode 100644 index 0000000000..6a0e8742c7 Binary files /dev/null and b/tests/screenshots/chromium/Bidirectional.spec.ts/bidirectionalDisplayedCorrectly.png differ diff --git a/tests/screenshots/chromium/Circle.spec.ts/circleDisplayedCorrectly.png b/tests/screenshots/chromium/Circle.spec.ts/circleDisplayedCorrectly.png new file mode 100644 index 0000000000..a19d65fa60 Binary files /dev/null and b/tests/screenshots/chromium/Circle.spec.ts/circleDisplayedCorrectly.png differ diff --git a/tests/screenshots/chromium/CobbAngle.spec.ts/cobbangleDisplayedCorrectly.png b/tests/screenshots/chromium/CobbAngle.spec.ts/cobbangleDisplayedCorrectly.png new file mode 100644 index 0000000000..1e457ea099 Binary files /dev/null and b/tests/screenshots/chromium/CobbAngle.spec.ts/cobbangleDisplayedCorrectly.png differ diff --git a/tests/screenshots/chromium/Crosshairs.spec.ts/crosshairsNewDisplayset.png b/tests/screenshots/chromium/Crosshairs.spec.ts/crosshairsNewDisplayset.png new file mode 100644 index 0000000000..aaf27b71d1 Binary files /dev/null and b/tests/screenshots/chromium/Crosshairs.spec.ts/crosshairsNewDisplayset.png differ diff --git a/tests/screenshots/chromium/Crosshairs.spec.ts/crosshairsRendered.png b/tests/screenshots/chromium/Crosshairs.spec.ts/crosshairsRendered.png new file mode 100644 index 0000000000..dd73614bd3 Binary files /dev/null and b/tests/screenshots/chromium/Crosshairs.spec.ts/crosshairsRendered.png differ diff --git a/tests/screenshots/chromium/Crosshairs.spec.ts/crosshairsResetToolbar.png b/tests/screenshots/chromium/Crosshairs.spec.ts/crosshairsResetToolbar.png new file mode 100644 index 0000000000..09ed89bb2b Binary files /dev/null and b/tests/screenshots/chromium/Crosshairs.spec.ts/crosshairsResetToolbar.png differ diff --git a/tests/screenshots/chromium/Crosshairs.spec.ts/crosshairsRotated.png b/tests/screenshots/chromium/Crosshairs.spec.ts/crosshairsRotated.png new file mode 100644 index 0000000000..8952348f2a Binary files /dev/null and b/tests/screenshots/chromium/Crosshairs.spec.ts/crosshairsRotated.png differ diff --git a/tests/screenshots/chromium/Crosshairs.spec.ts/crosshairsSlabThickness.png b/tests/screenshots/chromium/Crosshairs.spec.ts/crosshairsSlabThickness.png new file mode 100644 index 0000000000..85cf7fa729 Binary files /dev/null and b/tests/screenshots/chromium/Crosshairs.spec.ts/crosshairsSlabThickness.png differ diff --git a/tests/screenshots/chromium/DicomTagBrowser.spec.ts/dicomTagBrowserDisplayedCorrectly.png b/tests/screenshots/chromium/DicomTagBrowser.spec.ts/dicomTagBrowserDisplayedCorrectly.png new file mode 100644 index 0000000000..708ee6464c Binary files /dev/null and b/tests/screenshots/chromium/DicomTagBrowser.spec.ts/dicomTagBrowserDisplayedCorrectly.png differ diff --git a/tests/screenshots/chromium/Ellipse.spec.ts/ellipseDisplayedCorrectly.png b/tests/screenshots/chromium/Ellipse.spec.ts/ellipseDisplayedCorrectly.png new file mode 100644 index 0000000000..a1bc4b7c44 Binary files /dev/null and b/tests/screenshots/chromium/Ellipse.spec.ts/ellipseDisplayedCorrectly.png differ diff --git a/tests/screenshots/chromium/FlipHorizontal.spec.ts/flipHorizontalDisplayedCorrectly.png b/tests/screenshots/chromium/FlipHorizontal.spec.ts/flipHorizontalDisplayedCorrectly.png new file mode 100644 index 0000000000..09826fd5e9 Binary files /dev/null and b/tests/screenshots/chromium/FlipHorizontal.spec.ts/flipHorizontalDisplayedCorrectly.png differ diff --git a/tests/screenshots/chromium/Invert.spec.ts/invertDisplayedCorrectly.png b/tests/screenshots/chromium/Invert.spec.ts/invertDisplayedCorrectly.png new file mode 100644 index 0000000000..a4b0ca6645 Binary files /dev/null and b/tests/screenshots/chromium/Invert.spec.ts/invertDisplayedCorrectly.png differ diff --git a/tests/screenshots/chromium/Length.spec.ts/lengthDisplayedCorrectly.png b/tests/screenshots/chromium/Length.spec.ts/lengthDisplayedCorrectly.png new file mode 100644 index 0000000000..76c7e9ead0 Binary files /dev/null and b/tests/screenshots/chromium/Length.spec.ts/lengthDisplayedCorrectly.png differ diff --git a/tests/screenshots/chromium/Livewire.spec.ts/livewireDisplayedCorrectly.png b/tests/screenshots/chromium/Livewire.spec.ts/livewireDisplayedCorrectly.png new file mode 100644 index 0000000000..9308f5c727 Binary files /dev/null and b/tests/screenshots/chromium/Livewire.spec.ts/livewireDisplayedCorrectly.png differ diff --git a/tests/screenshots/chromium/MPR.spec.ts/mprDisplayedCorrectly.png b/tests/screenshots/chromium/MPR.spec.ts/mprDisplayedCorrectly.png new file mode 100644 index 0000000000..01a5cd4e21 Binary files /dev/null and b/tests/screenshots/chromium/MPR.spec.ts/mprDisplayedCorrectly.png differ diff --git a/tests/screenshots/chromium/Probe.spec.ts/probeDisplayedCorrectly.png b/tests/screenshots/chromium/Probe.spec.ts/probeDisplayedCorrectly.png new file mode 100644 index 0000000000..eff69051a7 Binary files /dev/null and b/tests/screenshots/chromium/Probe.spec.ts/probeDisplayedCorrectly.png differ diff --git a/tests/screenshots/chromium/RTHydration.spec.ts/rtJumpToStructure.png b/tests/screenshots/chromium/RTHydration.spec.ts/rtJumpToStructure.png new file mode 100644 index 0000000000..6b2feb1df5 Binary files /dev/null and b/tests/screenshots/chromium/RTHydration.spec.ts/rtJumpToStructure.png differ diff --git a/tests/screenshots/chromium/RTHydration.spec.ts/rtPostHydration.png b/tests/screenshots/chromium/RTHydration.spec.ts/rtPostHydration.png new file mode 100644 index 0000000000..df604fa899 Binary files /dev/null and b/tests/screenshots/chromium/RTHydration.spec.ts/rtPostHydration.png differ diff --git a/tests/screenshots/chromium/RTHydration.spec.ts/rtPreHydration.png b/tests/screenshots/chromium/RTHydration.spec.ts/rtPreHydration.png new file mode 100644 index 0000000000..cf72ffed15 Binary files /dev/null and b/tests/screenshots/chromium/RTHydration.spec.ts/rtPreHydration.png differ diff --git a/tests/screenshots/chromium/Rectangle.spec.ts/rectangleDisplayedCorrectly.png b/tests/screenshots/chromium/Rectangle.spec.ts/rectangleDisplayedCorrectly.png new file mode 100644 index 0000000000..1d93b6be54 Binary files /dev/null and b/tests/screenshots/chromium/Rectangle.spec.ts/rectangleDisplayedCorrectly.png differ diff --git a/tests/screenshots/chromium/Reset.spec.ts/resetDisplayedCorrectly.png b/tests/screenshots/chromium/Reset.spec.ts/resetDisplayedCorrectly.png new file mode 100644 index 0000000000..958da098c0 Binary files /dev/null and b/tests/screenshots/chromium/Reset.spec.ts/resetDisplayedCorrectly.png differ diff --git a/tests/screenshots/chromium/RotateRight.spec.ts/rotateRightDisplayedCorrectly.png b/tests/screenshots/chromium/RotateRight.spec.ts/rotateRightDisplayedCorrectly.png new file mode 100644 index 0000000000..6b7bae2f06 Binary files /dev/null and b/tests/screenshots/chromium/RotateRight.spec.ts/rotateRightDisplayedCorrectly.png differ diff --git a/tests/screenshots/chromium/SEGHydration.spec.ts/segJumpToSegment.png b/tests/screenshots/chromium/SEGHydration.spec.ts/segJumpToSegment.png new file mode 100644 index 0000000000..fce62577ac Binary files /dev/null and b/tests/screenshots/chromium/SEGHydration.spec.ts/segJumpToSegment.png differ diff --git a/tests/screenshots/chromium/SEGHydration.spec.ts/segPostHydration.png b/tests/screenshots/chromium/SEGHydration.spec.ts/segPostHydration.png new file mode 100644 index 0000000000..f15ce0f2ca Binary files /dev/null and b/tests/screenshots/chromium/SEGHydration.spec.ts/segPostHydration.png differ diff --git a/tests/screenshots/chromium/SEGHydration.spec.ts/segPreHydration.png b/tests/screenshots/chromium/SEGHydration.spec.ts/segPreHydration.png new file mode 100644 index 0000000000..5a0aa68029 Binary files /dev/null and b/tests/screenshots/chromium/SEGHydration.spec.ts/segPreHydration.png differ diff --git a/tests/screenshots/chromium/SRHydration.spec.ts/srJumpToMeasurement.png b/tests/screenshots/chromium/SRHydration.spec.ts/srJumpToMeasurement.png new file mode 100644 index 0000000000..df610f2552 Binary files /dev/null and b/tests/screenshots/chromium/SRHydration.spec.ts/srJumpToMeasurement.png differ diff --git a/tests/screenshots/chromium/SRHydration.spec.ts/srPostHydration.png b/tests/screenshots/chromium/SRHydration.spec.ts/srPostHydration.png new file mode 100644 index 0000000000..b3533f96e0 Binary files /dev/null and b/tests/screenshots/chromium/SRHydration.spec.ts/srPostHydration.png differ diff --git a/tests/screenshots/chromium/SRHydration.spec.ts/srPreHydration.png b/tests/screenshots/chromium/SRHydration.spec.ts/srPreHydration.png new file mode 100644 index 0000000000..37cbb6d45d Binary files /dev/null and b/tests/screenshots/chromium/SRHydration.spec.ts/srPreHydration.png differ diff --git a/tests/screenshots/chromium/Spline.spec.ts/splineDisplayedCorrectly.png b/tests/screenshots/chromium/Spline.spec.ts/splineDisplayedCorrectly.png new file mode 100644 index 0000000000..f9215f275c Binary files /dev/null and b/tests/screenshots/chromium/Spline.spec.ts/splineDisplayedCorrectly.png differ diff --git a/tests/utils/checkForScreenshot.ts b/tests/utils/checkForScreenshot.ts new file mode 100644 index 0000000000..694b9661be --- /dev/null +++ b/tests/utils/checkForScreenshot.ts @@ -0,0 +1,35 @@ +import { expect } from '@playwright/test'; +import { Locator, Page } from 'playwright'; + +/** + * @param page - The page to interact with + * @param locator - The element to check for screenshot + * @param screenshotPath - The path to save the screenshot + * @param attempts - The number of attempts to check for screenshot + * @param delay - The delay between attempts + * @returns True if the screenshot matches, otherwise throws an error + */ +const checkForScreenshot = async ( + page: Page, + locator: Locator | Page, + screenshotPath: string, + attempts = 10, + delay = 100 +) => { + await page.waitForLoadState('networkidle'); + for (let i = 1; i < attempts; i++) { + try { + await expect(locator).toHaveScreenshot(screenshotPath, { + maxDiffPixelRatio: 0.1, + }); + return true; + } catch (error) { + if (i === attempts) { + throw new Error('Screenshot does not match.'); + } + await new Promise(resolve => setTimeout(resolve, delay)); + } + } +}; + +export { checkForScreenshot }; diff --git a/tests/utils/index.ts b/tests/utils/index.ts new file mode 100644 index 0000000000..a6e9aeb77e --- /dev/null +++ b/tests/utils/index.ts @@ -0,0 +1,9 @@ +import { visitStudy } from './visitStudy'; +import { checkForScreenshot } from './checkForScreenshot'; +import { screenShotPaths } from './screenShotPaths'; +import { simulateClicksOnElement } from './simulateClicksOnElement'; +import { reduce3DViewportSize } from './reduce3DviewportSize'; +import { getMousePosition, initilizeMousePositionTracker } from './mouseUtils'; + + +export { visitStudy, checkForScreenshot, screenShotPaths, simulateClicksOnElement, reduce3DViewportSize, getMousePosition, initilizeMousePositionTracker }; diff --git a/tests/utils/mouseUtils.ts b/tests/utils/mouseUtils.ts new file mode 100644 index 0000000000..c4c008b14d --- /dev/null +++ b/tests/utils/mouseUtils.ts @@ -0,0 +1,25 @@ +import { Page } from "@playwright/test"; + +interface WindowWithMousePosition extends Window { + mouseX: number; + mouseY: number; +} + +export const initilizeMousePositionTracker = async (page: Page) => { + const window = await page.evaluateHandle("window") as any; + await page.evaluate((window: WindowWithMousePosition) => { + window.mouseX = 0; + window.mouseY = 0; + window.addEventListener("mousemove", (event) => { + window.mouseX = event.clientX; + window.mouseY = event.clientY; + }); + }, window); +} + +export const getMousePosition = async (page: Page) => { + const window = await page.evaluateHandle("window") as any; + return await page.evaluate((window: WindowWithMousePosition) => { + return { x: window.mouseX, y: window.mouseY }; + }, window); +} diff --git a/tests/utils/reduce3DviewportSize.ts b/tests/utils/reduce3DviewportSize.ts new file mode 100644 index 0000000000..2ce072c5df --- /dev/null +++ b/tests/utils/reduce3DviewportSize.ts @@ -0,0 +1,9 @@ + +export const reduce3DViewportSize = async (page: any) => { + await page.evaluate(({ cornerstone }: AppTypes.Test) => { + const enabledElement = cornerstone.getEnabledElements().filter(element => element.viewport.type === 'volume3d')[0] + const { viewport } = enabledElement; + viewport.setZoom(0.5); + viewport.render() + }, await page.evaluateHandle('window')); +} diff --git a/tests/utils/screenShotPaths.ts b/tests/utils/screenShotPaths.ts new file mode 100644 index 0000000000..063f9c851b --- /dev/null +++ b/tests/utils/screenShotPaths.ts @@ -0,0 +1,92 @@ +/** + * Paths to the screenshots of the tests. + */ +const screenShotPaths = { + angle: { + angleDisplayedCorrectly: 'angleDisplayedCorrectly.png', + }, + bidirectional: { + bidirectionalDisplayedCorrectly: 'bidirectionalDisplayedCorrectly.png', + }, + circle: { + circleDisplayedCorrectly: 'circleDisplayedCorrectly.png', + }, + cobbangle: { + cobbangleDisplayedCorrectly: 'cobbangleDisplayedCorrectly.png', + }, + ellipse: { + ellipseDisplayedCorrectly: 'ellipseDisplayedCorrectly.png', + }, + length: { + lengthDisplayedCorrectly: 'lengthDisplayedCorrectly.png', + }, + livewire: { + livewireDisplayedCorrectly: 'livewireDisplayedCorrectly.png', + }, + mpr: { + mprDisplayedCorrectly: 'mprDisplayedCorrectly.png', + }, + threeDFourUp: { + threeDFourUpDisplayedCorrectly: 'threeDFourUpDisplayedCorrectly.png', + }, + threeDMain: { + threeDMainDisplayedCorrectly: 'threeDMainDisplayedCorrectly.png', + }, + threeDPrimary: { + threeDPrimaryDisplayedCorrectly: 'threeDPrimaryDisplayedCorrectly.png', + }, + threeDOnly: { + threeDOnlyDisplayedCorrectly: 'threeDOnlyDisplayedCorrectly.png', + }, + axialPrimary: { + axialPrimaryDisplayedCorrectly: 'axialPrimaryDisplayedCorrectly.png', + }, + probe: { + probeDisplayedCorrectly: 'probeDisplayedCorrectly.png', + }, + rectangle: { + rectangleDisplayedCorrectly: 'rectangleDisplayedCorrectly.png', + }, + spline: { + splineDisplayedCorrectly: 'splineDisplayedCorrectly.png', + }, + dicomTagBrowser: { + dicomTagBrowserDisplayedCorrectly: 'dicomTagBrowserDisplayedCorrectly.png', + }, + rotateRight: { + rotateRightDisplayedCorrectly: 'rotateRightDisplayedCorrectly.png', + }, + invert: { + invertDisplayedCorrectly: 'invertDisplayedCorrectly.png', + }, + flipHorizontal: { + flipHorizontalDisplayedCorrectly: 'flipHorizontalDisplayedCorrectly.png', + }, + reset: { + resetDisplayedCorrectly: 'resetDisplayedCorrectly.png', + }, + srHydration: { + srPostHydration: 'srPostHydration.png', + srPreHydration: 'srPreHydration.png', + srJumpToMeasurement: 'srJumpToMeasurement.png', + }, + segHydration: { + segPostHydration: 'segPostHydration.png', + segPreHydration: 'segPreHydration.png', + segJumpToSegment: 'segJumpToSegment.png', + }, + rtHydration: { + rtPostHydration: 'rtPostHydration.png', + rtPreHydration: 'rtPreHydration.png', + rtJumpToStructure: 'rtJumpToStructure.png', + }, + crosshairs: { + crosshairsRendered: 'crosshairsRendered.png', + crosshairsRotated: 'crosshairsRotated.png', + crosshairsSlabThickness: 'crosshairsSlabThickness.png', + crosshairsResetToolbar: 'crosshairsResetToolbar.png', + crosshairsNewDisplayset: 'crosshairsNewDisplayset.png', + } +}; + +export { screenShotPaths }; diff --git a/tests/utils/simulateClicksOnElement.ts b/tests/utils/simulateClicksOnElement.ts new file mode 100644 index 0000000000..d1932faa05 --- /dev/null +++ b/tests/utils/simulateClicksOnElement.ts @@ -0,0 +1,19 @@ +import { Locator } from 'playwright'; + +/** + * + * @parm locator - The locator to click on + * @param points - The points to click on + * @returns Promise + */ +export async function simulateClicksOnElement({ + locator, + points, +}: { + locator: Locator; + points: { x: number; y: number }[]; +}) { + for (const { x, y } of points) { + await locator.click({ delay: 100, position: { x, y } }); + } +} diff --git a/tests/utils/visitStudy.ts b/tests/utils/visitStudy.ts new file mode 100644 index 0000000000..25c9bd80dd --- /dev/null +++ b/tests/utils/visitStudy.ts @@ -0,0 +1,24 @@ +import { Page } from '@playwright/test'; + +/** + * Visit the study + * @param page - The page to interact with + * @param title - The study instance UID of the study to visit + * @param mode - The mode to visit the study in + * @param delay - The delay to wait after visiting the study + * @param datasources - the data source to load the study from + */ +export async function visitStudy( + page: Page, + studyInstanceUID: string, + mode: string, + delay: number = 0, + datasources = 'ohif' +) { + await page.goto(`/?resultsPerPage=100&datasources=${datasources}`); + await page.getByTestId(studyInstanceUID).click(); + await page.getByRole('button', { name: mode }).click(); + await page.waitForLoadState('domcontentloaded'); + await page.waitForLoadState('networkidle'); + await page.waitForTimeout(delay); +} diff --git a/tsconfig.json b/tsconfig.json index 44e34356da..ee01dec9ee 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,10 +15,17 @@ "paths": { "@ohif/core": ["platform/core/src"], "@ohif/ui": ["platform/ui/src"], + "@ohif/ui-next": ["platform/ui-next/src"], "@ohif/i18n": ["platform/i18n/src"], "@ohif/app": ["platform/app/src"] } }, - "include": ["platform/**/src/**/*", "extensions/**/src/**/*", "modes/**/src/**/*"], + "include": [ + "platform/**/src/**/*", + "platform/**/public/**/*", + "extensions/**/src/**/*", + "modes/**/src/**/*", + "tests/**/*", + ], "exclude": ["node_modules", "dist"] } diff --git a/version.json b/version.json index 0b23b9f209..a512e4426d 100644 --- a/version.json +++ b/version.json @@ -1,4 +1,4 @@ { - "version": "3.8.0-beta.82", - "commit": "3754c224b4dab28182adb0a41e37d890942144d8" + "version": "3.9.0-beta.71", + "commit": "aa0e5a59379453bb8e6a4f286447576744ea6bf5" } \ No newline at end of file diff --git a/version.mjs b/version.mjs index 231d13a67f..fa63e4f7a2 100644 --- a/version.mjs +++ b/version.mjs @@ -19,13 +19,15 @@ async function run() { let nextVersion; - if (branchName === 'release') { + if (branchName.startsWith('release')) { console.log('Branch: release'); - nextVersion = semver.inc(currentVersion, 'minor'); + await fs.writeFile('./commit.txt', currentCommitHash); + console.log('the version is automatically picked up from the version.txt file'); + return; } else { console.log('Branch: master'); const prereleaseComponents = semver.prerelease(currentVersion); - const isBumpBeta = lastCommitMessage.trim().endsWith('[BUMP BETA]'); + const isBumpBeta = lastCommitMessage.trim().includes('[BUMP BETA]'); console.log('isBumpBeta', isBumpBeta); if (prereleaseComponents?.includes('beta')) { diff --git a/version.txt b/version.txt index 6bf5a4d55f..9b8f565cf4 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -3.8.0-beta.82 \ No newline at end of file +3.9.0-beta.71 \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 1c38fa79d7..53a20bc3ee 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,15 +2,10 @@ # yarn lockfile v1 -"@aashutoshrathi/word-wrap@^1.2.3": - version "1.2.6" - resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" - integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== - "@adobe/css-tools@^4.0.1": - version "4.3.3" - resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.3.3.tgz#90749bde8b89cd41764224f5aac29cd4138f75ff" - integrity sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ== + version "4.4.0" + resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.4.0.tgz#728c484f4e10df03d5a3acd0d8adcbbebff8ad63" + integrity sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ== "@algolia/autocomplete-core@1.9.3": version "1.9.3" @@ -189,25 +184,18 @@ dependencies: default-browser-id "3.0.0" -"@babel/code-frame@7.12.11": - version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" - integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.24.7", "@babel/code-frame@^7.8.3": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" + integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== dependencies: - "@babel/highlight" "^7.10.4" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.23.5", "@babel/code-frame@^7.24.1", "@babel/code-frame@^7.24.2", "@babel/code-frame@^7.8.3": - version "7.24.2" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.2.tgz#718b4b19841809a58b29b68cde80bc5e1aa6d9ae" - integrity sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ== - dependencies: - "@babel/highlight" "^7.24.2" + "@babel/highlight" "^7.24.7" picocolors "^1.0.0" -"@babel/compat-data@^7.20.5", "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.23.2", "@babel/compat-data@^7.23.5", "@babel/compat-data@^7.24.4": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.4.tgz#6f102372e9094f25d908ca0d34fc74c74606059a" - integrity sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ== +"@babel/compat-data@^7.20.5", "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.23.2", "@babel/compat-data@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.7.tgz#d23bbea508c3883ba8251fb4164982c36ea577ed" + integrity sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw== "@babel/core@7.12.9": version "7.12.9" @@ -231,83 +219,84 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.11.1", "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.18.6", "@babel/core@^7.18.9", "@babel/core@^7.19.6", "@babel/core@^7.23.0", "@babel/core@^7.23.2", "@babel/core@^7.23.9": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.4.tgz#1f758428e88e0d8c563874741bc4ffc4f71a4717" - integrity sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg== +"@babel/core@7.24.7", "@babel/core@^7.11.1", "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.18.6", "@babel/core@^7.18.9", "@babel/core@^7.19.6", "@babel/core@^7.21.3", "@babel/core@^7.23.0", "@babel/core@^7.23.2", "@babel/core@^7.23.9": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.7.tgz#b676450141e0b52a3d43bc91da86aa608f950ac4" + integrity sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g== dependencies: "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.24.2" - "@babel/generator" "^7.24.4" - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helpers" "^7.24.4" - "@babel/parser" "^7.24.4" - "@babel/template" "^7.24.0" - "@babel/traverse" "^7.24.1" - "@babel/types" "^7.24.0" + "@babel/code-frame" "^7.24.7" + "@babel/generator" "^7.24.7" + "@babel/helper-compilation-targets" "^7.24.7" + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helpers" "^7.24.7" + "@babel/parser" "^7.24.7" + "@babel/template" "^7.24.7" + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.2.3" semver "^6.3.1" -"@babel/generator@^7.12.5", "@babel/generator@^7.18.7", "@babel/generator@^7.23.0", "@babel/generator@^7.24.1", "@babel/generator@^7.24.4", "@babel/generator@^7.7.2": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.4.tgz#1fc55532b88adf952025d5d2d1e71f946cb1c498" - integrity sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw== +"@babel/generator@^7.12.5", "@babel/generator@^7.18.7", "@babel/generator@^7.23.0", "@babel/generator@^7.24.7", "@babel/generator@^7.7.2": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.7.tgz#1654d01de20ad66b4b4d99c135471bc654c55e6d" + integrity sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA== dependencies: - "@babel/types" "^7.24.0" + "@babel/types" "^7.24.7" "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.25" jsesc "^2.5.1" -"@babel/helper-annotate-as-pure@^7.18.6", "@babel/helper-annotate-as-pure@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" - integrity sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg== +"@babel/helper-annotate-as-pure@^7.18.6", "@babel/helper-annotate-as-pure@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz#5373c7bc8366b12a033b4be1ac13a206c6656aab" + integrity sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg== dependencies: - "@babel/types" "^7.22.5" + "@babel/types" "^7.24.7" -"@babel/helper-builder-binary-assignment-operator-visitor@^7.22.15": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz#5426b109cf3ad47b91120f8328d8ab1be8b0b956" - integrity sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw== +"@babel/helper-builder-binary-assignment-operator-visitor@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz#37d66feb012024f2422b762b9b2a7cfe27c7fba3" + integrity sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA== dependencies: - "@babel/types" "^7.22.15" + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" -"@babel/helper-compilation-targets@^7.20.7", "@babel/helper-compilation-targets@^7.22.15", "@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" - integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== +"@babel/helper-compilation-targets@^7.20.7", "@babel/helper-compilation-targets@^7.22.15", "@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz#4eb6c4a80d6ffeac25ab8cd9a21b5dfa48d503a9" + integrity sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg== dependencies: - "@babel/compat-data" "^7.23.5" - "@babel/helper-validator-option" "^7.23.5" + "@babel/compat-data" "^7.24.7" + "@babel/helper-validator-option" "^7.24.7" browserslist "^4.22.2" lru-cache "^5.1.1" semver "^6.3.1" -"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.21.0", "@babel/helper-create-class-features-plugin@^7.24.1", "@babel/helper-create-class-features-plugin@^7.24.4": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.4.tgz#c806f73788a6800a5cfbbc04d2df7ee4d927cce3" - integrity sha512-lG75yeuUSVu0pIcbhiYMXBXANHrpUPaOfu7ryAzskCgKUHuAxRQI5ssrtmF0X9UXldPlvT0XM/A4F44OXRt6iQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-member-expression-to-functions" "^7.23.0" - "@babel/helper-optimise-call-expression" "^7.22.5" - "@babel/helper-replace-supers" "^7.24.1" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" +"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.21.0", "@babel/helper-create-class-features-plugin@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.7.tgz#2eaed36b3a1c11c53bdf80d53838b293c52f5b3b" + integrity sha512-kTkaDl7c9vO80zeX1rJxnuRpEsD5tA81yh11X1gQo+PhSti3JS+7qeZo9U4RHobKRiFPKaGK3svUAeb8D0Q7eg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-function-name" "^7.24.7" + "@babel/helper-member-expression-to-functions" "^7.24.7" + "@babel/helper-optimise-call-expression" "^7.24.7" + "@babel/helper-replace-supers" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + "@babel/helper-split-export-declaration" "^7.24.7" semver "^6.3.1" -"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.22.15", "@babel/helper-create-regexp-features-plugin@^7.22.5": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz#5ee90093914ea09639b01c711db0d6775e558be1" - integrity sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w== +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.7.tgz#be4f435a80dc2b053c76eeb4b7d16dd22cfc89da" + integrity sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA== dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-annotate-as-pure" "^7.24.7" regexpu-core "^5.3.1" semver "^6.3.1" @@ -333,10 +322,10 @@ lodash.debounce "^4.0.8" resolve "^1.14.2" -"@babel/helper-define-polyfill-provider@^0.6.1": - version "0.6.1" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.1.tgz#fadc63f0c2ff3c8d02ed905dcea747c5b0fb74fd" - integrity sha512-o7SDgTJuvx5vLKD6SFvkydkSMBvahDKGiNJzG22IZYXhiqoe9efY7zocICBgzHV4IRg5wdgl2nEL/tulKIEIbA== +"@babel/helper-define-polyfill-provider@^0.6.1", "@babel/helper-define-polyfill-provider@^0.6.2": + version "0.6.2" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz#18594f789c3594acb24cfdb4a7f7b7d2e8bd912d" + integrity sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ== dependencies: "@babel/helper-compilation-targets" "^7.22.6" "@babel/helper-plugin-utils" "^7.22.5" @@ -344,186 +333,192 @@ lodash.debounce "^4.0.8" resolve "^1.14.2" -"@babel/helper-environment-visitor@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" - integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== +"@babel/helper-environment-visitor@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz#4b31ba9551d1f90781ba83491dd59cf9b269f7d9" + integrity sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ== + dependencies: + "@babel/types" "^7.24.7" -"@babel/helper-function-name@^7.22.5", "@babel/helper-function-name@^7.23.0": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" - integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== +"@babel/helper-function-name@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz#75f1e1725742f39ac6584ee0b16d94513da38dd2" + integrity sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA== dependencies: - "@babel/template" "^7.22.15" - "@babel/types" "^7.23.0" + "@babel/template" "^7.24.7" + "@babel/types" "^7.24.7" -"@babel/helper-hoist-variables@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" - integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== +"@babel/helper-hoist-variables@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz#b4ede1cde2fd89436397f30dc9376ee06b0f25ee" + integrity sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ== dependencies: - "@babel/types" "^7.22.5" + "@babel/types" "^7.24.7" -"@babel/helper-member-expression-to-functions@^7.23.0": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz#9263e88cc5e41d39ec18c9a3e0eced59a3e7d366" - integrity sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA== +"@babel/helper-member-expression-to-functions@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.7.tgz#67613d068615a70e4ed5101099affc7a41c5225f" + integrity sha512-LGeMaf5JN4hAT471eJdBs/GK1DoYIJ5GCtZN/EsL6KUiiDZOvO/eKE11AMZJa2zP4zk4qe9V2O/hxAmkRc8p6w== dependencies: - "@babel/types" "^7.23.0" + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" -"@babel/helper-module-imports@^7.10.4", "@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.22.15", "@babel/helper-module-imports@^7.24.1", "@babel/helper-module-imports@^7.24.3": - version "7.24.3" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz#6ac476e6d168c7c23ff3ba3cf4f7841d46ac8128" - integrity sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg== +"@babel/helper-module-imports@^7.10.4", "@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz#f2f980392de5b84c3328fc71d38bd81bbb83042b" + integrity sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA== dependencies: - "@babel/types" "^7.24.0" + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" -"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1" - integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ== +"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz#31b6c9a2930679498db65b685b1698bfd6c7daf8" + integrity sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ== dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-module-imports" "^7.22.15" - "@babel/helper-simple-access" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/helper-validator-identifier" "^7.22.20" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-simple-access" "^7.24.7" + "@babel/helper-split-export-declaration" "^7.24.7" + "@babel/helper-validator-identifier" "^7.24.7" -"@babel/helper-optimise-call-expression@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz#f21531a9ccbff644fdd156b4077c16ff0c3f609e" - integrity sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw== +"@babel/helper-optimise-call-expression@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz#8b0a0456c92f6b323d27cfd00d1d664e76692a0f" + integrity sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A== dependencies: - "@babel/types" "^7.22.5" + "@babel/types" "^7.24.7" "@babel/helper-plugin-utils@7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.24.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.24.0" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz#945681931a52f15ce879fd5b86ce2dae6d3d7f2a" - integrity sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w== - -"@babel/helper-remap-async-to-generator@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz#7b68e1cb4fa964d2996fd063723fb48eca8498e0" - integrity sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-wrap-function" "^7.22.20" - -"@babel/helper-replace-supers@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.24.1.tgz#7085bd19d4a0b7ed8f405c1ed73ccb70f323abc1" - integrity sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ== - dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-member-expression-to-functions" "^7.23.0" - "@babel/helper-optimise-call-expression" "^7.22.5" - -"@babel/helper-simple-access@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" - integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-skip-transparent-expression-wrappers@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz#007f15240b5751c537c40e77abb4e89eeaaa8847" - integrity sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-split-export-declaration@^7.22.6": - version "7.22.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" - integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-string-parser@^7.23.4": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz#f99c36d3593db9540705d0739a1f10b5e20c696e" - integrity sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ== - -"@babel/helper-validator-identifier@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" - integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== - -"@babel/helper-validator-option@^7.22.15", "@babel/helper-validator-option@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" - integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== - -"@babel/helper-wrap-function@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz#15352b0b9bfb10fc9c76f79f6342c00e3411a569" - integrity sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw== - dependencies: - "@babel/helper-function-name" "^7.22.5" - "@babel/template" "^7.22.15" - "@babel/types" "^7.22.19" - -"@babel/helpers@^7.12.5", "@babel/helpers@^7.24.4": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.4.tgz#dc00907fd0d95da74563c142ef4cd21f2cb856b6" - integrity sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw== - dependencies: - "@babel/template" "^7.24.0" - "@babel/traverse" "^7.24.1" - "@babel/types" "^7.24.0" - -"@babel/highlight@^7.10.4", "@babel/highlight@^7.24.2": - version "7.24.2" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.2.tgz#3f539503efc83d3c59080a10e6634306e0370d26" - integrity sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA== - dependencies: - "@babel/helper-validator-identifier" "^7.22.20" +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.24.7", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz#98c84fe6fe3d0d3ae7bfc3a5e166a46844feb2a0" + integrity sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg== + +"@babel/helper-remap-async-to-generator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.7.tgz#b3f0f203628522713849d49403f1a414468be4c7" + integrity sha512-9pKLcTlZ92hNZMQfGCHImUpDOlAgkkpqalWEeftW5FBya75k8Li2ilerxkM/uBEj01iBZXcCIB/bwvDYgWyibA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-wrap-function" "^7.24.7" + +"@babel/helper-replace-supers@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz#f933b7eed81a1c0265740edc91491ce51250f765" + integrity sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg== + dependencies: + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-member-expression-to-functions" "^7.24.7" + "@babel/helper-optimise-call-expression" "^7.24.7" + +"@babel/helper-simple-access@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz#bcade8da3aec8ed16b9c4953b74e506b51b5edb3" + integrity sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-skip-transparent-expression-wrappers@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz#5f8fa83b69ed5c27adc56044f8be2b3ea96669d9" + integrity sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-split-export-declaration@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz#83949436890e07fa3d6873c61a96e3bbf692d856" + integrity sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA== + dependencies: + "@babel/types" "^7.24.7" + +"@babel/helper-string-parser@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz#4d2d0f14820ede3b9807ea5fc36dfc8cd7da07f2" + integrity sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg== + +"@babel/helper-validator-identifier@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" + integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== + +"@babel/helper-validator-option@^7.22.15", "@babel/helper-validator-option@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz#24c3bb77c7a425d1742eec8fb433b5a1b38e62f6" + integrity sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw== + +"@babel/helper-wrap-function@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.24.7.tgz#52d893af7e42edca7c6d2c6764549826336aae1f" + integrity sha512-N9JIYk3TD+1vq/wn77YnJOqMtfWhNewNE+DJV4puD2X7Ew9J4JvrzrFDfTfyv5EgEXVy9/Wt8QiOErzEmv5Ifw== + dependencies: + "@babel/helper-function-name" "^7.24.7" + "@babel/template" "^7.24.7" + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helpers@^7.12.5", "@babel/helpers@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.7.tgz#aa2ccda29f62185acb5d42fb4a3a1b1082107416" + integrity sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg== + dependencies: + "@babel/template" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/highlight@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" + integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== + dependencies: + "@babel/helper-validator-identifier" "^7.24.7" chalk "^2.4.2" js-tokens "^4.0.0" picocolors "^1.0.0" -"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.12.7", "@babel/parser@^7.14.7", "@babel/parser@^7.18.8", "@babel/parser@^7.20.7", "@babel/parser@^7.23.0", "@babel/parser@^7.23.9", "@babel/parser@^7.24.0", "@babel/parser@^7.24.1", "@babel/parser@^7.24.4", "@babel/parser@^7.7.0": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.4.tgz#234487a110d89ad5a3ed4a8a566c36b9453e8c88" - integrity sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg== +"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.12.7", "@babel/parser@^7.14.7", "@babel/parser@^7.18.8", "@babel/parser@^7.20.7", "@babel/parser@^7.23.0", "@babel/parser@^7.23.9", "@babel/parser@^7.24.7", "@babel/parser@^7.7.0": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.7.tgz#9a5226f92f0c5c8ead550b750f5608e766c8ce85" + integrity sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw== -"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.24.4": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.4.tgz#6125f0158543fb4edf1c22f322f3db67f21cb3e1" - integrity sha512-qpl6vOOEEzTLLcsuqYYo8yDtrTocmu2xkGvgNebvPjT9DTtfFYGmgDqY+rBYXNlqL4s9qLDn6xkrJv4RxAPiTA== +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.7.tgz#fd059fd27b184ea2b4c7e646868a9a381bbc3055" + integrity sha512-TiT1ss81W80eQsN+722OaeQMY/G4yTb4G9JrqeiDADs3N8lbPMGldWi9x8tyqCW5NLx1Jh2AvkE6r6QvEltMMQ== dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.22.15", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.1.tgz#b645d9ba8c2bc5b7af50f0fe949f9edbeb07c8cf" - integrity sha512-y4HqEnkelJIOQGd+3g1bTeKsA5c6qM7eOn7VggGVbBc0y8MLSKHacwcIE2PplNlQSj0PqS9rrXL/nkPVK+kUNg== +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.22.15", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.7.tgz#468096ca44bbcbe8fcc570574e12eb1950e18107" + integrity sha512-unaQgZ/iRu/By6tsjMZzpeBZjChYfLYry6HrEXPoz3KmfF0sVBQ1l8zKMQ4xRGLWVsjuvB8nQfjNP/DcfEOCsg== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.22.15", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.1.tgz#da8261f2697f0f41b0855b91d3a20a1fbfd271d3" - integrity sha512-Hj791Ii4ci8HqnaKHAlLNs+zaLXb0EzSDhiAWp5VNlyvCNymYfacs64pxTxbH1znW/NcArSmwpmG9IKE/TUVVQ== +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.22.15", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz#e4eabdd5109acc399b38d7999b2ef66fc2022f89" + integrity sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" - "@babel/plugin-transform-optional-chaining" "^7.24.1" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + "@babel/plugin-transform-optional-chaining" "^7.24.7" -"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.1.tgz#1181d9685984c91d657b8ddf14f0487a6bab2988" - integrity sha512-m9m/fXsXLiHfwdgydIFnpk+7jlVbnvlK5B2EKiPdLUb6WX654ZaaEWJUjk8TftRbZpK0XibovlLWX4KIZhV6jw== +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.7.tgz#71b21bb0286d5810e63a1538aa901c58e87375ec" + integrity sha512-utA4HuR6F4Vvcr+o4DnjL8fCOlgRFGbeeBEGNg3ZTrLFw6VWG5XmUrvcQ0FjIYMU2ST4XcR2Wsp7t9qOAPnxMg== dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-proposal-class-properties@^7.16.7": version "7.18.6" @@ -618,26 +613,26 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-syntax-flow@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.1.tgz#875c25e3428d7896c87589765fc8b9d32f24bd8d" - integrity sha512-sxi2kLTI5DeW5vDtMUsk4mTPwvlUDbjOnoWayhynCwrw4QXRld4QEYwqzY8JmQXaJUtgUuCIurtSRH5sn4c7mA== +"@babel/plugin-syntax-flow@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.7.tgz#d1759e84dd4b437cf9fae69b4c06c41d7625bfb7" + integrity sha512-9G8GYT/dxn/D1IIKOUBmGX0mnmj46mGH9NnZyJLwtCpgh5f7D2VbuKodb+2s9m1Yavh1s7ASQN8lf0eqrb1LTw== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-syntax-import-assertions@^7.22.5", "@babel/plugin-syntax-import-assertions@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.1.tgz#db3aad724153a00eaac115a3fb898de544e34971" - integrity sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ== +"@babel/plugin-syntax-import-assertions@^7.22.5", "@babel/plugin-syntax-import-assertions@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz#2a0b406b5871a20a841240586b1300ce2088a778" + integrity sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-syntax-import-attributes@^7.22.5", "@babel/plugin-syntax-import-attributes@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.1.tgz#c66b966c63b714c4eec508fcf5763b1f2d381093" - integrity sha512-zhQTMH0X2nVLnb04tz+s7AMuasX8U0FnpE+nHTOhSOINjWMnopoZTxtIKsd45n4GQ/HIZLyfIpoul8e2m0DnRA== +"@babel/plugin-syntax-import-attributes@^7.22.5", "@babel/plugin-syntax-import-attributes@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz#b4f9ea95a79e6912480c4b626739f86a076624ca" + integrity sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-import-meta@^7.10.4", "@babel/plugin-syntax-import-meta@^7.8.3": version "7.10.4" @@ -660,12 +655,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-jsx@^7.23.3", "@babel/plugin-syntax-jsx@^7.24.1", "@babel/plugin-syntax-jsx@^7.7.2": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz#3f6ca04b8c841811dbc3c5c5f837934e0d626c10" - integrity sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA== +"@babel/plugin-syntax-jsx@^7.24.7", "@babel/plugin-syntax-jsx@^7.7.2": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz#39a1fa4a7e3d3d7f34e2acc6be585b718d30e02d" + integrity sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": version "7.10.4" @@ -723,12 +718,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-typescript@^7.24.1", "@babel/plugin-syntax-typescript@^7.7.2": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz#b3bcc51f396d15f3591683f90239de143c076844" - integrity sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw== +"@babel/plugin-syntax-typescript@^7.24.7", "@babel/plugin-syntax-typescript@^7.7.2": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz#58d458271b4d3b6bb27ee6ac9525acbb259bad1c" + integrity sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-unicode-sets-regex@^7.18.6": version "7.18.6" @@ -738,462 +733,462 @@ "@babel/helper-create-regexp-features-plugin" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-arrow-functions@^7.16.7", "@babel/plugin-transform-arrow-functions@^7.22.5", "@babel/plugin-transform-arrow-functions@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.1.tgz#2bf263617060c9cc45bcdbf492b8cc805082bf27" - integrity sha512-ngT/3NkRhsaep9ck9uj2Xhv9+xB1zShY3tM3g6om4xxCELwCDN4g4Aq5dRn48+0hasAql7s2hdBOysCfNpr4fw== +"@babel/plugin-transform-arrow-functions@^7.16.7", "@babel/plugin-transform-arrow-functions@^7.22.5", "@babel/plugin-transform-arrow-functions@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz#4f6886c11e423bd69f3ce51dbf42424a5f275514" + integrity sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-async-generator-functions@^7.23.2", "@babel/plugin-transform-async-generator-functions@^7.24.3": - version "7.24.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.3.tgz#8fa7ae481b100768cc9842c8617808c5352b8b89" - integrity sha512-Qe26CMYVjpQxJ8zxM1340JFNjZaF+ISWpr1Kt/jGo+ZTUzKkfw/pphEWbRCb+lmSM6k/TOgfYLvmbHkUQ0asIg== +"@babel/plugin-transform-async-generator-functions@^7.23.2", "@babel/plugin-transform-async-generator-functions@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.7.tgz#7330a5c50e05181ca52351b8fd01642000c96cfd" + integrity sha512-o+iF77e3u7ZS4AoAuJvapz9Fm001PuD2V3Lp6OSE4FYQke+cSewYtnek+THqGRWyQloRCyvWL1OkyfNEl9vr/g== dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-remap-async-to-generator" "^7.22.20" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-remap-async-to-generator" "^7.24.7" "@babel/plugin-syntax-async-generators" "^7.8.4" -"@babel/plugin-transform-async-to-generator@^7.22.5", "@babel/plugin-transform-async-to-generator@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.1.tgz#0e220703b89f2216800ce7b1c53cb0cf521c37f4" - integrity sha512-AawPptitRXp1y0n4ilKcGbRYWfbbzFWz2NqNu7dacYDtFtz0CMjG64b3LQsb3KIgnf4/obcUL78hfaOS7iCUfw== +"@babel/plugin-transform-async-to-generator@^7.22.5", "@babel/plugin-transform-async-to-generator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz#72a3af6c451d575842a7e9b5a02863414355bdcc" + integrity sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA== dependencies: - "@babel/helper-module-imports" "^7.24.1" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-remap-async-to-generator" "^7.22.20" + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-remap-async-to-generator" "^7.24.7" -"@babel/plugin-transform-block-scoped-functions@^7.22.5", "@babel/plugin-transform-block-scoped-functions@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.1.tgz#1c94799e20fcd5c4d4589523bbc57b7692979380" - integrity sha512-TWWC18OShZutrv9C6mye1xwtam+uNi2bnTOCBUd5sZxyHOiWbU6ztSROofIMrK84uweEZC219POICK/sTYwfgg== +"@babel/plugin-transform-block-scoped-functions@^7.22.5", "@babel/plugin-transform-block-scoped-functions@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz#a4251d98ea0c0f399dafe1a35801eaba455bbf1f" + integrity sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-block-scoping@^7.23.0", "@babel/plugin-transform-block-scoping@^7.24.4": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.4.tgz#28f5c010b66fbb8ccdeef853bef1935c434d7012" - integrity sha512-nIFUZIpGKDf9O9ttyRXpHFpKC+X3Y5mtshZONuEUYBomAKoM4y029Jr+uB1bHGPhNmK8YXHevDtKDOLmtRrp6g== +"@babel/plugin-transform-block-scoping@^7.23.0", "@babel/plugin-transform-block-scoping@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.7.tgz#42063e4deb850c7bd7c55e626bf4e7ab48e6ce02" + integrity sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-class-properties@^7.22.5", "@babel/plugin-transform-class-properties@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.1.tgz#bcbf1aef6ba6085cfddec9fc8d58871cf011fc29" - integrity sha512-OMLCXi0NqvJfORTaPQBwqLXHhb93wkBKZ4aNwMl6WtehO7ar+cmp+89iPEQPqxAnxsOKTaMcs3POz3rKayJ72g== +"@babel/plugin-transform-class-properties@^7.22.5", "@babel/plugin-transform-class-properties@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz#256879467b57b0b68c7ddfc5b76584f398cd6834" + integrity sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w== dependencies: - "@babel/helper-create-class-features-plugin" "^7.24.1" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-class-static-block@^7.22.11", "@babel/plugin-transform-class-static-block@^7.24.4": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.4.tgz#1a4653c0cf8ac46441ec406dece6e9bc590356a4" - integrity sha512-B8q7Pz870Hz/q9UgP8InNpY01CSLDSCyqX7zcRuv3FcPl87A2G17lASroHWaCtbdIcbYzOZ7kWmXFKbijMSmFg== +"@babel/plugin-transform-class-static-block@^7.22.11", "@babel/plugin-transform-class-static-block@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz#c82027ebb7010bc33c116d4b5044fbbf8c05484d" + integrity sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ== dependencies: - "@babel/helper-create-class-features-plugin" "^7.24.4" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-class-static-block" "^7.14.5" -"@babel/plugin-transform-classes@^7.22.15", "@babel/plugin-transform-classes@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.1.tgz#5bc8fc160ed96378184bc10042af47f50884dcb1" - integrity sha512-ZTIe3W7UejJd3/3R4p7ScyyOoafetUShSf4kCqV0O7F/RiHxVj/wRaRnQlrGwflvcehNA8M42HkAiEDYZu2F1Q== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-replace-supers" "^7.24.1" - "@babel/helper-split-export-declaration" "^7.22.6" +"@babel/plugin-transform-classes@^7.22.15", "@babel/plugin-transform-classes@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.7.tgz#4ae6ef43a12492134138c1e45913f7c46c41b4bf" + integrity sha512-CFbbBigp8ln4FU6Bpy6g7sE8B/WmCmzvivzUC6xDAdWVsjYTXijpuuGJmYkAaoWAzcItGKT3IOAbxRItZ5HTjw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-compilation-targets" "^7.24.7" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-function-name" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-replace-supers" "^7.24.7" + "@babel/helper-split-export-declaration" "^7.24.7" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.22.5", "@babel/plugin-transform-computed-properties@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.1.tgz#bc7e787f8e021eccfb677af5f13c29a9934ed8a7" - integrity sha512-5pJGVIUfJpOS+pAqBQd+QMaTD2vCL/HcePooON6pDpHgRp4gNRmzyHTPIkXntwKsq3ayUFVfJaIKPw2pOkOcTw== +"@babel/plugin-transform-computed-properties@^7.22.5", "@babel/plugin-transform-computed-properties@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz#4cab3214e80bc71fae3853238d13d097b004c707" + integrity sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/template" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/template" "^7.24.7" -"@babel/plugin-transform-destructuring@^7.23.0", "@babel/plugin-transform-destructuring@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.1.tgz#b1e8243af4a0206841973786292b8c8dd8447345" - integrity sha512-ow8jciWqNxR3RYbSNVuF4U2Jx130nwnBnhRw6N6h1bOejNkABmcI5X5oz29K4alWX7vf1C+o6gtKXikzRKkVdw== +"@babel/plugin-transform-destructuring@^7.23.0", "@babel/plugin-transform-destructuring@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.7.tgz#a097f25292defb6e6cc16d6333a4cfc1e3c72d9e" + integrity sha512-19eJO/8kdCQ9zISOf+SEUJM/bAUIsvY3YDnXZTupUCQ8LgrWnsG/gFB9dvXqdXnRXMAM8fvt7b0CBKQHNGy1mw== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-dotall-regex@^7.22.5", "@babel/plugin-transform-dotall-regex@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.1.tgz#d56913d2f12795cc9930801b84c6f8c47513ac13" - integrity sha512-p7uUxgSoZwZ2lPNMzUkqCts3xlp8n+o05ikjy7gbtFJSt9gdU88jAmtfmOxHM14noQXBxfgzf2yRWECiNVhTCw== +"@babel/plugin-transform-dotall-regex@^7.22.5", "@babel/plugin-transform-dotall-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz#5f8bf8a680f2116a7207e16288a5f974ad47a7a0" + integrity sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-duplicate-keys@^7.22.5", "@babel/plugin-transform-duplicate-keys@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.1.tgz#5347a797fe82b8d09749d10e9f5b83665adbca88" - integrity sha512-msyzuUnvsjsaSaocV6L7ErfNsa5nDWL1XKNnDePLgmz+WdU4w/J8+AxBMrWfi9m4IxfL5sZQKUPQKDQeeAT6lA== +"@babel/plugin-transform-duplicate-keys@^7.22.5", "@babel/plugin-transform-duplicate-keys@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz#dd20102897c9a2324e5adfffb67ff3610359a8ee" + integrity sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-dynamic-import@^7.22.11", "@babel/plugin-transform-dynamic-import@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.1.tgz#2a5a49959201970dd09a5fca856cb651e44439dd" - integrity sha512-av2gdSTyXcJVdI+8aFZsCAtR29xJt0S5tas+Ef8NvBNmD1a+N/3ecMLeMBgfcK+xzsjdLDT6oHt+DFPyeqUbDA== +"@babel/plugin-transform-dynamic-import@^7.22.11", "@babel/plugin-transform-dynamic-import@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz#4d8b95e3bae2b037673091aa09cd33fecd6419f4" + integrity sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-dynamic-import" "^7.8.3" -"@babel/plugin-transform-exponentiation-operator@^7.22.5", "@babel/plugin-transform-exponentiation-operator@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.1.tgz#6650ebeb5bd5c012d5f5f90a26613a08162e8ba4" - integrity sha512-U1yX13dVBSwS23DEAqU+Z/PkwE9/m7QQy8Y9/+Tdb8UWYaGNDYwTLi19wqIAiROr8sXVum9A/rtiH5H0boUcTw== +"@babel/plugin-transform-exponentiation-operator@^7.22.5", "@babel/plugin-transform-exponentiation-operator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz#b629ee22645f412024297d5245bce425c31f9b0d" + integrity sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ== dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.22.15" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-export-namespace-from@^7.22.11", "@babel/plugin-transform-export-namespace-from@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.1.tgz#f033541fc036e3efb2dcb58eedafd4f6b8078acd" - integrity sha512-Ft38m/KFOyzKw2UaJFkWG9QnHPG/Q/2SkOrRk4pNBPg5IPZ+dOxcmkK5IyuBcxiNPyyYowPGUReyBvrvZs7IlQ== +"@babel/plugin-transform-export-namespace-from@^7.22.11", "@babel/plugin-transform-export-namespace-from@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz#176d52d8d8ed516aeae7013ee9556d540c53f197" + integrity sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" -"@babel/plugin-transform-flow-strip-types@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.24.1.tgz#fa8d0a146506ea195da1671d38eed459242b2dcc" - integrity sha512-iIYPIWt3dUmUKKE10s3W+jsQ3icFkw0JyRVyY1B7G4yK/nngAOHLVx8xlhA6b/Jzl/Y0nis8gjqhqKtRDQqHWQ== +"@babel/plugin-transform-flow-strip-types@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.24.7.tgz#ae454e62219288fbb734541ab00389bfb13c063e" + integrity sha512-cjRKJ7FobOH2eakx7Ja+KpJRj8+y+/SiB3ooYm/n2UJfxu0oEaOoxOinitkJcPqv9KxS0kxTGPUaR7L2XcXDXA== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/plugin-syntax-flow" "^7.24.1" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-flow" "^7.24.7" -"@babel/plugin-transform-for-of@^7.22.15", "@babel/plugin-transform-for-of@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.1.tgz#67448446b67ab6c091360ce3717e7d3a59e202fd" - integrity sha512-OxBdcnF04bpdQdR3i4giHZNZQn7cm8RQKcSwA17wAAqEELo1ZOwp5FFgeptWUQXFyT9kwHo10aqqauYkRZPCAg== +"@babel/plugin-transform-for-of@^7.22.15", "@babel/plugin-transform-for-of@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz#f25b33f72df1d8be76399e1b8f3f9d366eb5bc70" + integrity sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" -"@babel/plugin-transform-function-name@^7.22.5", "@babel/plugin-transform-function-name@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.1.tgz#8cba6f7730626cc4dfe4ca2fa516215a0592b361" - integrity sha512-BXmDZpPlh7jwicKArQASrj8n22/w6iymRnvHYYd2zO30DbE277JO20/7yXJT3QxDPtiQiOxQBbZH4TpivNXIxA== +"@babel/plugin-transform-function-name@^7.22.5", "@babel/plugin-transform-function-name@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.7.tgz#6d8601fbffe665c894440ab4470bc721dd9131d6" + integrity sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w== dependencies: - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-compilation-targets" "^7.24.7" + "@babel/helper-function-name" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-json-strings@^7.22.11", "@babel/plugin-transform-json-strings@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.1.tgz#08e6369b62ab3e8a7b61089151b161180c8299f7" - integrity sha512-U7RMFmRvoasscrIFy5xA4gIp8iWnWubnKkKuUGJjsuOH7GfbMkB+XZzeslx2kLdEGdOJDamEmCqOks6e8nv8DQ== +"@babel/plugin-transform-json-strings@^7.22.11", "@babel/plugin-transform-json-strings@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz#f3e9c37c0a373fee86e36880d45b3664cedaf73a" + integrity sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-json-strings" "^7.8.3" -"@babel/plugin-transform-literals@^7.22.5", "@babel/plugin-transform-literals@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.1.tgz#0a1982297af83e6b3c94972686067df588c5c096" - integrity sha512-zn9pwz8U7nCqOYIiBaOxoQOtYmMODXTJnkxG4AtX8fPmnCRYWBOHD0qcpwS9e2VDSp1zNJYpdnFMIKb8jmwu6g== +"@babel/plugin-transform-literals@^7.22.5", "@babel/plugin-transform-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.7.tgz#36b505c1e655151a9d7607799a9988fc5467d06c" + integrity sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-logical-assignment-operators@^7.22.11", "@babel/plugin-transform-logical-assignment-operators@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.1.tgz#719d8aded1aa94b8fb34e3a785ae8518e24cfa40" - integrity sha512-OhN6J4Bpz+hIBqItTeWJujDOfNP+unqv/NJgyhlpSqgBTPm37KkMmZV6SYcOj+pnDbdcl1qRGV/ZiIjX9Iy34w== +"@babel/plugin-transform-logical-assignment-operators@^7.22.11", "@babel/plugin-transform-logical-assignment-operators@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz#a58fb6eda16c9dc8f9ff1c7b1ba6deb7f4694cb0" + integrity sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-transform-member-expression-literals@^7.22.5", "@babel/plugin-transform-member-expression-literals@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.1.tgz#896d23601c92f437af8b01371ad34beb75df4489" - integrity sha512-4ojai0KysTWXzHseJKa1XPNXKRbuUrhkOPY4rEGeR+7ChlJVKxFa3H3Bz+7tWaGKgJAXUWKOGmltN+u9B3+CVg== +"@babel/plugin-transform-member-expression-literals@^7.22.5", "@babel/plugin-transform-member-expression-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz#3b4454fb0e302e18ba4945ba3246acb1248315df" + integrity sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-modules-amd@^7.23.0", "@babel/plugin-transform-modules-amd@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.1.tgz#b6d829ed15258536977e9c7cc6437814871ffa39" - integrity sha512-lAxNHi4HVtjnHd5Rxg3D5t99Xm6H7b04hUS7EHIXcUl2EV4yl1gWdqZrNzXnSrHveL9qMdbODlLF55mvgjAfaQ== +"@babel/plugin-transform-modules-amd@^7.23.0", "@babel/plugin-transform-modules-amd@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz#65090ed493c4a834976a3ca1cde776e6ccff32d7" + integrity sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg== dependencies: - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-modules-commonjs@^7.23.0", "@babel/plugin-transform-modules-commonjs@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz#e71ba1d0d69e049a22bf90b3867e263823d3f1b9" - integrity sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw== +"@babel/plugin-transform-modules-commonjs@^7.23.0", "@babel/plugin-transform-modules-commonjs@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.7.tgz#9fd5f7fdadee9085886b183f1ad13d1ab260f4ab" + integrity sha512-iFI8GDxtevHJ/Z22J5xQpVqFLlMNstcLXh994xifFwxxGslr2ZXXLWgtBeLctOD63UFDArdvN6Tg8RFw+aEmjQ== dependencies: - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-simple-access" "^7.22.5" + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-simple-access" "^7.24.7" -"@babel/plugin-transform-modules-systemjs@^7.23.0", "@babel/plugin-transform-modules-systemjs@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.1.tgz#2b9625a3d4e445babac9788daec39094e6b11e3e" - integrity sha512-mqQ3Zh9vFO1Tpmlt8QPnbwGHzNz3lpNEMxQb1kAemn/erstyqw1r9KeOlOfo3y6xAnFEcOv2tSyrXfmMk+/YZA== +"@babel/plugin-transform-modules-systemjs@^7.23.0", "@babel/plugin-transform-modules-systemjs@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.7.tgz#f8012316c5098f6e8dee6ecd58e2bc6f003d0ce7" + integrity sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw== dependencies: - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-validator-identifier" "^7.22.20" + "@babel/helper-hoist-variables" "^7.24.7" + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-validator-identifier" "^7.24.7" -"@babel/plugin-transform-modules-umd@^7.22.5", "@babel/plugin-transform-modules-umd@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.1.tgz#69220c66653a19cf2c0872b9c762b9a48b8bebef" - integrity sha512-tuA3lpPj+5ITfcCluy6nWonSL7RvaG0AOTeAuvXqEKS34lnLzXpDb0dcP6K8jD0zWZFNDVly90AGFJPnm4fOYg== +"@babel/plugin-transform-modules-umd@^7.22.5", "@babel/plugin-transform-modules-umd@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz#edd9f43ec549099620df7df24e7ba13b5c76efc8" + integrity sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A== dependencies: - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-named-capturing-groups-regex@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz#67fe18ee8ce02d57c855185e27e3dc959b2e991f" - integrity sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ== +"@babel/plugin-transform-named-capturing-groups-regex@^7.22.5", "@babel/plugin-transform-named-capturing-groups-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz#9042e9b856bc6b3688c0c2e4060e9e10b1460923" + integrity sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.22.5" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-new-target@^7.22.5", "@babel/plugin-transform-new-target@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.1.tgz#29c59988fa3d0157de1c871a28cd83096363cc34" - integrity sha512-/rurytBM34hYy0HKZQyA0nHbQgQNFm4Q/BOc9Hflxi2X3twRof7NaE5W46j4kQitm7SvACVRXsa6N/tSZxvPug== +"@babel/plugin-transform-new-target@^7.22.5", "@babel/plugin-transform-new-target@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz#31ff54c4e0555cc549d5816e4ab39241dfb6ab00" + integrity sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-nullish-coalescing-operator@^7.22.11", "@babel/plugin-transform-nullish-coalescing-operator@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.1.tgz#0cd494bb97cb07d428bd651632cb9d4140513988" - integrity sha512-iQ+caew8wRrhCikO5DrUYx0mrmdhkaELgFa+7baMcVuhxIkN7oxt06CZ51D65ugIb1UWRQ8oQe+HXAVM6qHFjw== +"@babel/plugin-transform-nullish-coalescing-operator@^7.22.11", "@babel/plugin-transform-nullish-coalescing-operator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz#1de4534c590af9596f53d67f52a92f12db984120" + integrity sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" -"@babel/plugin-transform-numeric-separator@^7.22.11", "@babel/plugin-transform-numeric-separator@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.1.tgz#5bc019ce5b3435c1cadf37215e55e433d674d4e8" - integrity sha512-7GAsGlK4cNL2OExJH1DzmDeKnRv/LXq0eLUSvudrehVA5Rgg4bIrqEUW29FbKMBRT0ztSqisv7kjP+XIC4ZMNw== +"@babel/plugin-transform-numeric-separator@^7.22.11", "@babel/plugin-transform-numeric-separator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz#bea62b538c80605d8a0fac9b40f48e97efa7de63" + integrity sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-transform-object-rest-spread@^7.22.15", "@babel/plugin-transform-object-rest-spread@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.1.tgz#5a3ce73caf0e7871a02e1c31e8b473093af241ff" - integrity sha512-XjD5f0YqOtebto4HGISLNfiNMTTs6tbkFf2TOqJlYKYmbo+mN9Dnpl4SRoofiziuOWMIyq3sZEUqLo3hLITFEA== +"@babel/plugin-transform-object-rest-spread@^7.22.15", "@babel/plugin-transform-object-rest-spread@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz#d13a2b93435aeb8a197e115221cab266ba6e55d6" + integrity sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q== dependencies: - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-compilation-targets" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.24.1" + "@babel/plugin-transform-parameters" "^7.24.7" -"@babel/plugin-transform-object-super@^7.22.5", "@babel/plugin-transform-object-super@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.1.tgz#e71d6ab13483cca89ed95a474f542bbfc20a0520" - integrity sha512-oKJqR3TeI5hSLRxudMjFQ9re9fBVUU0GICqM3J1mi8MqlhVr6hC/ZN4ttAyMuQR6EZZIY6h/exe5swqGNNIkWQ== +"@babel/plugin-transform-object-super@^7.22.5", "@babel/plugin-transform-object-super@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz#66eeaff7830bba945dd8989b632a40c04ed625be" + integrity sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-replace-supers" "^7.24.1" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-replace-supers" "^7.24.7" -"@babel/plugin-transform-optional-catch-binding@^7.22.11", "@babel/plugin-transform-optional-catch-binding@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.1.tgz#92a3d0efe847ba722f1a4508669b23134669e2da" - integrity sha512-oBTH7oURV4Y+3EUrf6cWn1OHio3qG/PVwO5J03iSJmBg6m2EhKjkAu/xuaXaYwWW9miYtvbWv4LNf0AmR43LUA== +"@babel/plugin-transform-optional-catch-binding@^7.22.11", "@babel/plugin-transform-optional-catch-binding@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz#00eabd883d0dd6a60c1c557548785919b6e717b4" + integrity sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" -"@babel/plugin-transform-optional-chaining@^7.23.0", "@babel/plugin-transform-optional-chaining@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.1.tgz#26e588acbedce1ab3519ac40cc748e380c5291e6" - integrity sha512-n03wmDt+987qXwAgcBlnUUivrZBPZ8z1plL0YvgQalLm+ZE5BMhGm94jhxXtA1wzv1Cu2aaOv1BM9vbVttrzSg== +"@babel/plugin-transform-optional-chaining@^7.23.0", "@babel/plugin-transform-optional-chaining@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.7.tgz#b8f6848a80cf2da98a8a204429bec04756c6d454" + integrity sha512-tK+0N9yd4j+x/4hxF3F0e0fu/VdcxU18y5SevtyM/PCFlQvXbR0Zmlo2eBrKtVipGNFzpq56o8WsIIKcJFUCRQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" "@babel/plugin-syntax-optional-chaining" "^7.8.3" -"@babel/plugin-transform-parameters@^7.12.1", "@babel/plugin-transform-parameters@^7.20.7", "@babel/plugin-transform-parameters@^7.22.15", "@babel/plugin-transform-parameters@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.1.tgz#983c15d114da190506c75b616ceb0f817afcc510" - integrity sha512-8Jl6V24g+Uw5OGPeWNKrKqXPDw2YDjLc53ojwfMcKwlEoETKU9rU0mHUtcg9JntWI/QYzGAXNWEcVHZ+fR+XXg== +"@babel/plugin-transform-parameters@^7.12.1", "@babel/plugin-transform-parameters@^7.20.7", "@babel/plugin-transform-parameters@^7.22.15", "@babel/plugin-transform-parameters@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz#5881f0ae21018400e320fc7eb817e529d1254b68" + integrity sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-private-methods@^7.22.5", "@babel/plugin-transform-private-methods@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.1.tgz#a0faa1ae87eff077e1e47a5ec81c3aef383dc15a" - integrity sha512-tGvisebwBO5em4PaYNqt4fkw56K2VALsAbAakY0FjTYqJp7gfdrgr7YX76Or8/cpik0W6+tj3rZ0uHU9Oil4tw== +"@babel/plugin-transform-private-methods@^7.22.5", "@babel/plugin-transform-private-methods@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz#e6318746b2ae70a59d023d5cc1344a2ba7a75f5e" + integrity sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ== dependencies: - "@babel/helper-create-class-features-plugin" "^7.24.1" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-private-property-in-object@^7.22.11", "@babel/plugin-transform-private-property-in-object@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.1.tgz#756443d400274f8fb7896742962cc1b9f25c1f6a" - integrity sha512-pTHxDVa0BpUbvAgX3Gat+7cSciXqUcY9j2VZKTbSB6+VQGpNgNO9ailxTGHSXlqOnX1Hcx1Enme2+yv7VqP9bg== +"@babel/plugin-transform-private-property-in-object@^7.22.11", "@babel/plugin-transform-private-property-in-object@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz#4eec6bc701288c1fab5f72e6a4bbc9d67faca061" + integrity sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA== dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-create-class-features-plugin" "^7.24.1" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" -"@babel/plugin-transform-property-literals@^7.22.5", "@babel/plugin-transform-property-literals@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.1.tgz#d6a9aeab96f03749f4eebeb0b6ea8e90ec958825" - integrity sha512-LetvD7CrHmEx0G442gOomRr66d7q8HzzGGr4PMHGr+5YIm6++Yke+jxj246rpvsbyhJwCLxcTn6zW1P1BSenqA== +"@babel/plugin-transform-property-literals@^7.22.5", "@babel/plugin-transform-property-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz#f0d2ed8380dfbed949c42d4d790266525d63bbdc" + integrity sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-react-constant-elements@^7.12.1", "@babel/plugin-transform-react-constant-elements@^7.18.12": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.24.1.tgz#d493a0918b9fdad7540f5afd9b5eb5c52500d18d" - integrity sha512-QXp1U9x0R7tkiGB0FOk8o74jhnap0FlZ5gNkRIWdG3eP+SvMFg118e1zaWewDzgABb106QSKpVsD3Wgd8t6ifA== +"@babel/plugin-transform-react-constant-elements@^7.12.1", "@babel/plugin-transform-react-constant-elements@^7.18.12", "@babel/plugin-transform-react-constant-elements@^7.21.3": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.24.7.tgz#b85e8f240b14400277f106c9c9b585d9acf608a1" + integrity sha512-7LidzZfUXyfZ8/buRW6qIIHBY8wAZ1OrY9c/wTr8YhZ6vMPo+Uc/CVFLYY1spZrEQlD4w5u8wjqk5NQ3OVqQKA== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-react-display-name@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.1.tgz#554e3e1a25d181f040cf698b93fd289a03bfdcdb" - integrity sha512-mvoQg2f9p2qlpDQRBC7M3c3XTr0k7cp/0+kFKKO/7Gtu0LSw16eKB+Fabe2bDT/UpsyasTBBkAnbdsLrkD5XMw== +"@babel/plugin-transform-react-display-name@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz#9caff79836803bc666bcfe210aeb6626230c293b" + integrity sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-react-jsx-development@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz#e716b6edbef972a92165cd69d92f1255f7e73e87" - integrity sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A== +"@babel/plugin-transform-react-jsx-development@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.7.tgz#eaee12f15a93f6496d852509a850085e6361470b" + integrity sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ== dependencies: - "@babel/plugin-transform-react-jsx" "^7.22.5" + "@babel/plugin-transform-react-jsx" "^7.24.7" -"@babel/plugin-transform-react-jsx@^7.22.5", "@babel/plugin-transform-react-jsx@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.23.4.tgz#393f99185110cea87184ea47bcb4a7b0c2e39312" - integrity sha512-5xOpoPguCZCRbo/JeHlloSkTA8Bld1J/E1/kLfD1nsuiW1m8tduTA1ERCgIZokDflX/IBzKcqR3l7VlRgiIfHA== +"@babel/plugin-transform-react-jsx@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.24.7.tgz#17cd06b75a9f0e2bd076503400e7c4b99beedac4" + integrity sha512-+Dj06GDZEFRYvclU6k4bme55GKBEWUmByM/eoKuqg4zTNQHiApWRhQph5fxQB2wAEFvRzL1tOEj1RJ19wJrhoA== dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-module-imports" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-jsx" "^7.23.3" - "@babel/types" "^7.23.4" + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-jsx" "^7.24.7" + "@babel/types" "^7.24.7" -"@babel/plugin-transform-react-pure-annotations@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.1.tgz#c86bce22a53956331210d268e49a0ff06e392470" - integrity sha512-+pWEAaDJvSm9aFvJNpLiM2+ktl2Sn2U5DdyiWdZBxmLc6+xGt88dvFqsHiAiDS+8WqUwbDfkKz9jRxK3M0k+kA== +"@babel/plugin-transform-react-pure-annotations@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.7.tgz#bdd9d140d1c318b4f28b29a00fb94f97ecab1595" + integrity sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA== dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-regenerator@^7.16.7", "@babel/plugin-transform-regenerator@^7.22.10", "@babel/plugin-transform-regenerator@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.1.tgz#625b7545bae52363bdc1fbbdc7252b5046409c8c" - integrity sha512-sJwZBCzIBE4t+5Q4IGLaaun5ExVMRY0lYwos/jNecjMrVCygCdph3IKv0tkP5Fc87e/1+bebAmEAGBfnRD+cnw== +"@babel/plugin-transform-regenerator@^7.16.7", "@babel/plugin-transform-regenerator@^7.22.10", "@babel/plugin-transform-regenerator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz#021562de4534d8b4b1851759fd7af4e05d2c47f8" + integrity sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" regenerator-transform "^0.15.2" -"@babel/plugin-transform-reserved-words@^7.22.5", "@babel/plugin-transform-reserved-words@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.1.tgz#8de729f5ecbaaf5cf83b67de13bad38a21be57c1" - integrity sha512-JAclqStUfIwKN15HrsQADFgeZt+wexNQ0uLhuqvqAUFoqPMjEcFCYZBhq0LUdz6dZK/mD+rErhW71fbx8RYElg== +"@babel/plugin-transform-reserved-words@^7.22.5", "@babel/plugin-transform-reserved-words@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz#80037fe4fbf031fc1125022178ff3938bb3743a4" + integrity sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-runtime@^7.18.6", "@babel/plugin-transform-runtime@^7.23.2": - version "7.24.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.3.tgz#dc58ad4a31810a890550365cc922e1ff5acb5d7f" - integrity sha512-J0BuRPNlNqlMTRJ72eVptpt9VcInbxO6iP3jaxr+1NPhC0UkKL+6oeX6VXMEYdADnuqmMmsBspt4d5w8Y/TCbQ== +"@babel/plugin-transform-runtime@7.24.7", "@babel/plugin-transform-runtime@^7.18.6": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.7.tgz#00a5bfaf8c43cf5c8703a8a6e82b59d9c58f38ca" + integrity sha512-YqXjrk4C+a1kZjewqt+Mmu2UuV1s07y8kqcUf4qYLnoqemhR4gRQikhdAhSVJioMjVTu6Mo6pAbaypEA3jY6fw== dependencies: - "@babel/helper-module-imports" "^7.24.3" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" babel-plugin-polyfill-corejs2 "^0.4.10" babel-plugin-polyfill-corejs3 "^0.10.1" babel-plugin-polyfill-regenerator "^0.6.1" semver "^6.3.1" -"@babel/plugin-transform-shorthand-properties@^7.22.5", "@babel/plugin-transform-shorthand-properties@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.1.tgz#ba9a09144cf55d35ec6b93a32253becad8ee5b55" - integrity sha512-LyjVB1nsJ6gTTUKRjRWx9C1s9hE7dLfP/knKdrfeH9UPtAGjYGgxIbFfx7xyLIEWs7Xe1Gnf8EWiUqfjLhInZA== +"@babel/plugin-transform-shorthand-properties@^7.22.5", "@babel/plugin-transform-shorthand-properties@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz#85448c6b996e122fa9e289746140aaa99da64e73" + integrity sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-spread@^7.22.5", "@babel/plugin-transform-spread@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.1.tgz#a1acf9152cbf690e4da0ba10790b3ac7d2b2b391" - integrity sha512-KjmcIM+fxgY+KxPVbjelJC6hrH1CgtPmTvdXAfn3/a9CnWGSTY7nH4zm5+cjmWJybdcPSsD0++QssDsjcpe47g== +"@babel/plugin-transform-spread@^7.22.5", "@babel/plugin-transform-spread@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz#e8a38c0fde7882e0fb8f160378f74bd885cc7bb3" + integrity sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" -"@babel/plugin-transform-sticky-regex@^7.22.5", "@babel/plugin-transform-sticky-regex@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.1.tgz#f03e672912c6e203ed8d6e0271d9c2113dc031b9" - integrity sha512-9v0f1bRXgPVcPrngOQvLXeGNNVLc8UjMVfebo9ka0WF3/7+aVUHmaJVT3sa0XCzEFioPfPHZiOcYG9qOsH63cw== +"@babel/plugin-transform-sticky-regex@^7.22.5", "@babel/plugin-transform-sticky-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz#96ae80d7a7e5251f657b5cf18f1ea6bf926f5feb" + integrity sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-template-literals@^7.22.5", "@babel/plugin-transform-template-literals@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.1.tgz#15e2166873a30d8617e3e2ccadb86643d327aab7" - integrity sha512-WRkhROsNzriarqECASCNu/nojeXCDTE/F2HmRgOzi7NGvyfYGq1NEjKBK3ckLfRgGc6/lPAqP0vDOSw3YtG34g== +"@babel/plugin-transform-template-literals@^7.22.5", "@babel/plugin-transform-template-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz#a05debb4a9072ae8f985bcf77f3f215434c8f8c8" + integrity sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-typeof-symbol@^7.22.5", "@babel/plugin-transform-typeof-symbol@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.1.tgz#6831f78647080dec044f7e9f68003d99424f94c7" - integrity sha512-CBfU4l/A+KruSUoW+vTQthwcAdwuqbpRNB8HQKlZABwHRhsdHZ9fezp4Sn18PeAlYxTNiLMlx4xUBV3AWfg1BA== +"@babel/plugin-transform-typeof-symbol@^7.22.5", "@babel/plugin-transform-typeof-symbol@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.7.tgz#f074be466580d47d6e6b27473a840c9f9ca08fb0" + integrity sha512-VtR8hDy7YLB7+Pet9IarXjg/zgCMSF+1mNS/EQEiEaUPoFXCVsHG64SIxcaaI2zJgRiv+YmgaQESUfWAdbjzgg== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-typescript@^7.13.0", "@babel/plugin-transform-typescript@^7.24.1": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.4.tgz#03e0492537a4b953e491f53f2bc88245574ebd15" - integrity sha512-79t3CQ8+oBGk/80SQ8MN3Bs3obf83zJ0YZjDmDaEZN8MqhMI760apl5z6a20kFeMXBwJX99VpKT8CKxEBp5H1g== +"@babel/plugin-transform-typescript@^7.13.0", "@babel/plugin-transform-typescript@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.7.tgz#b006b3e0094bf0813d505e0c5485679eeaf4a881" + integrity sha512-iLD3UNkgx2n/HrjBesVbYX6j0yqn/sJktvbtKKgcaLIQ4bTTQ8obAypc1VpyHPD2y4Phh9zHOaAt8e/L14wCpw== dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-create-class-features-plugin" "^7.24.4" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/plugin-syntax-typescript" "^7.24.1" + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-typescript" "^7.24.7" -"@babel/plugin-transform-unicode-escapes@^7.22.10", "@babel/plugin-transform-unicode-escapes@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.1.tgz#fb3fa16676549ac7c7449db9b342614985c2a3a4" - integrity sha512-RlkVIcWT4TLI96zM660S877E7beKlQw7Ig+wqkKBiWfj0zH5Q4h50q6er4wzZKRNSYpfo6ILJ+hrJAGSX2qcNw== +"@babel/plugin-transform-unicode-escapes@^7.22.10", "@babel/plugin-transform-unicode-escapes@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz#2023a82ced1fb4971630a2e079764502c4148e0e" + integrity sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-unicode-property-regex@^7.22.5", "@babel/plugin-transform-unicode-property-regex@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.1.tgz#56704fd4d99da81e5e9f0c0c93cabd91dbc4889e" - integrity sha512-Ss4VvlfYV5huWApFsF8/Sq0oXnGO+jB+rijFEFugTd3cwSObUSnUi88djgR5528Csl0uKlrI331kRqe56Ov2Ng== +"@babel/plugin-transform-unicode-property-regex@^7.22.5", "@babel/plugin-transform-unicode-property-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz#9073a4cd13b86ea71c3264659590ac086605bbcd" + integrity sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-unicode-regex@^7.22.5", "@babel/plugin-transform-unicode-regex@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.1.tgz#57c3c191d68f998ac46b708380c1ce4d13536385" - integrity sha512-2A/94wgZgxfTsiLaQ2E36XAOdcZmGAaEEgVmxQWwZXWkGhvoHbaqXcKnU8zny4ycpu3vNqg0L/PcCiYtHtA13g== +"@babel/plugin-transform-unicode-regex@^7.22.5", "@babel/plugin-transform-unicode-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz#dfc3d4a51127108099b19817c0963be6a2adf19f" + integrity sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-unicode-sets-regex@^7.22.5", "@babel/plugin-transform-unicode-sets-regex@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.1.tgz#c1ea175b02afcffc9cf57a9c4658326625165b7f" - integrity sha512-fqj4WuzzS+ukpgerpAoOnMfQXwUHFxXUZUE84oL2Kao2N8uSlvcpnAidKASgsNgzZHBsHWvcm8s9FPWUhAb8fA== +"@babel/plugin-transform-unicode-sets-regex@^7.22.5", "@babel/plugin-transform-unicode-sets-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz#d40705d67523803a576e29c63cef6e516b858ed9" + integrity sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/preset-env@7.23.2": version "7.23.2" @@ -1281,27 +1276,27 @@ core-js-compat "^3.31.0" semver "^6.3.1" -"@babel/preset-env@^7.11.0", "@babel/preset-env@^7.12.1", "@babel/preset-env@^7.18.6", "@babel/preset-env@^7.19.4", "@babel/preset-env@^7.23.2": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.24.4.tgz#46dbbcd608771373b88f956ffb67d471dce0d23b" - integrity sha512-7Kl6cSmYkak0FK/FXjSEnLJ1N9T/WA2RkMhu17gZ/dsxKJUuTYNIylahPTzqpLyJN4WhDif8X0XK1R8Wsguo/A== - dependencies: - "@babel/compat-data" "^7.24.4" - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-validator-option" "^7.23.5" - "@babel/plugin-bugfix-firefox-class-in-computed-class-key" "^7.24.4" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.24.1" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.24.1" - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.24.1" +"@babel/preset-env@7.24.7", "@babel/preset-env@^7.11.0", "@babel/preset-env@^7.12.1", "@babel/preset-env@^7.18.6", "@babel/preset-env@^7.19.4", "@babel/preset-env@^7.20.2", "@babel/preset-env@^7.23.2": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.24.7.tgz#ff067b4e30ba4a72f225f12f123173e77b987f37" + integrity sha512-1YZNsc+y6cTvWlDHidMBsQZrZfEFjRIo/BZCT906PMdzOyXtSLTgqGdrpcuTDCXyd11Am5uQULtDIcCfnTc8fQ== + dependencies: + "@babel/compat-data" "^7.24.7" + "@babel/helper-compilation-targets" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-validator-option" "^7.24.7" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key" "^7.24.7" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.24.7" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.24.7" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.24.7" "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-class-properties" "^7.12.13" "@babel/plugin-syntax-class-static-block" "^7.14.5" "@babel/plugin-syntax-dynamic-import" "^7.8.3" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - "@babel/plugin-syntax-import-assertions" "^7.24.1" - "@babel/plugin-syntax-import-attributes" "^7.24.1" + "@babel/plugin-syntax-import-assertions" "^7.24.7" + "@babel/plugin-syntax-import-attributes" "^7.24.7" "@babel/plugin-syntax-import-meta" "^7.10.4" "@babel/plugin-syntax-json-strings" "^7.8.3" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" @@ -1313,54 +1308,54 @@ "@babel/plugin-syntax-private-property-in-object" "^7.14.5" "@babel/plugin-syntax-top-level-await" "^7.14.5" "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" - "@babel/plugin-transform-arrow-functions" "^7.24.1" - "@babel/plugin-transform-async-generator-functions" "^7.24.3" - "@babel/plugin-transform-async-to-generator" "^7.24.1" - "@babel/plugin-transform-block-scoped-functions" "^7.24.1" - "@babel/plugin-transform-block-scoping" "^7.24.4" - "@babel/plugin-transform-class-properties" "^7.24.1" - "@babel/plugin-transform-class-static-block" "^7.24.4" - "@babel/plugin-transform-classes" "^7.24.1" - "@babel/plugin-transform-computed-properties" "^7.24.1" - "@babel/plugin-transform-destructuring" "^7.24.1" - "@babel/plugin-transform-dotall-regex" "^7.24.1" - "@babel/plugin-transform-duplicate-keys" "^7.24.1" - "@babel/plugin-transform-dynamic-import" "^7.24.1" - "@babel/plugin-transform-exponentiation-operator" "^7.24.1" - "@babel/plugin-transform-export-namespace-from" "^7.24.1" - "@babel/plugin-transform-for-of" "^7.24.1" - "@babel/plugin-transform-function-name" "^7.24.1" - "@babel/plugin-transform-json-strings" "^7.24.1" - "@babel/plugin-transform-literals" "^7.24.1" - "@babel/plugin-transform-logical-assignment-operators" "^7.24.1" - "@babel/plugin-transform-member-expression-literals" "^7.24.1" - "@babel/plugin-transform-modules-amd" "^7.24.1" - "@babel/plugin-transform-modules-commonjs" "^7.24.1" - "@babel/plugin-transform-modules-systemjs" "^7.24.1" - "@babel/plugin-transform-modules-umd" "^7.24.1" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.22.5" - "@babel/plugin-transform-new-target" "^7.24.1" - "@babel/plugin-transform-nullish-coalescing-operator" "^7.24.1" - "@babel/plugin-transform-numeric-separator" "^7.24.1" - "@babel/plugin-transform-object-rest-spread" "^7.24.1" - "@babel/plugin-transform-object-super" "^7.24.1" - "@babel/plugin-transform-optional-catch-binding" "^7.24.1" - "@babel/plugin-transform-optional-chaining" "^7.24.1" - "@babel/plugin-transform-parameters" "^7.24.1" - "@babel/plugin-transform-private-methods" "^7.24.1" - "@babel/plugin-transform-private-property-in-object" "^7.24.1" - "@babel/plugin-transform-property-literals" "^7.24.1" - "@babel/plugin-transform-regenerator" "^7.24.1" - "@babel/plugin-transform-reserved-words" "^7.24.1" - "@babel/plugin-transform-shorthand-properties" "^7.24.1" - "@babel/plugin-transform-spread" "^7.24.1" - "@babel/plugin-transform-sticky-regex" "^7.24.1" - "@babel/plugin-transform-template-literals" "^7.24.1" - "@babel/plugin-transform-typeof-symbol" "^7.24.1" - "@babel/plugin-transform-unicode-escapes" "^7.24.1" - "@babel/plugin-transform-unicode-property-regex" "^7.24.1" - "@babel/plugin-transform-unicode-regex" "^7.24.1" - "@babel/plugin-transform-unicode-sets-regex" "^7.24.1" + "@babel/plugin-transform-arrow-functions" "^7.24.7" + "@babel/plugin-transform-async-generator-functions" "^7.24.7" + "@babel/plugin-transform-async-to-generator" "^7.24.7" + "@babel/plugin-transform-block-scoped-functions" "^7.24.7" + "@babel/plugin-transform-block-scoping" "^7.24.7" + "@babel/plugin-transform-class-properties" "^7.24.7" + "@babel/plugin-transform-class-static-block" "^7.24.7" + "@babel/plugin-transform-classes" "^7.24.7" + "@babel/plugin-transform-computed-properties" "^7.24.7" + "@babel/plugin-transform-destructuring" "^7.24.7" + "@babel/plugin-transform-dotall-regex" "^7.24.7" + "@babel/plugin-transform-duplicate-keys" "^7.24.7" + "@babel/plugin-transform-dynamic-import" "^7.24.7" + "@babel/plugin-transform-exponentiation-operator" "^7.24.7" + "@babel/plugin-transform-export-namespace-from" "^7.24.7" + "@babel/plugin-transform-for-of" "^7.24.7" + "@babel/plugin-transform-function-name" "^7.24.7" + "@babel/plugin-transform-json-strings" "^7.24.7" + "@babel/plugin-transform-literals" "^7.24.7" + "@babel/plugin-transform-logical-assignment-operators" "^7.24.7" + "@babel/plugin-transform-member-expression-literals" "^7.24.7" + "@babel/plugin-transform-modules-amd" "^7.24.7" + "@babel/plugin-transform-modules-commonjs" "^7.24.7" + "@babel/plugin-transform-modules-systemjs" "^7.24.7" + "@babel/plugin-transform-modules-umd" "^7.24.7" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.24.7" + "@babel/plugin-transform-new-target" "^7.24.7" + "@babel/plugin-transform-nullish-coalescing-operator" "^7.24.7" + "@babel/plugin-transform-numeric-separator" "^7.24.7" + "@babel/plugin-transform-object-rest-spread" "^7.24.7" + "@babel/plugin-transform-object-super" "^7.24.7" + "@babel/plugin-transform-optional-catch-binding" "^7.24.7" + "@babel/plugin-transform-optional-chaining" "^7.24.7" + "@babel/plugin-transform-parameters" "^7.24.7" + "@babel/plugin-transform-private-methods" "^7.24.7" + "@babel/plugin-transform-private-property-in-object" "^7.24.7" + "@babel/plugin-transform-property-literals" "^7.24.7" + "@babel/plugin-transform-regenerator" "^7.24.7" + "@babel/plugin-transform-reserved-words" "^7.24.7" + "@babel/plugin-transform-shorthand-properties" "^7.24.7" + "@babel/plugin-transform-spread" "^7.24.7" + "@babel/plugin-transform-sticky-regex" "^7.24.7" + "@babel/plugin-transform-template-literals" "^7.24.7" + "@babel/plugin-transform-typeof-symbol" "^7.24.7" + "@babel/plugin-transform-unicode-escapes" "^7.24.7" + "@babel/plugin-transform-unicode-property-regex" "^7.24.7" + "@babel/plugin-transform-unicode-regex" "^7.24.7" + "@babel/plugin-transform-unicode-sets-regex" "^7.24.7" "@babel/preset-modules" "0.1.6-no-external-plugins" babel-plugin-polyfill-corejs2 "^0.4.10" babel-plugin-polyfill-corejs3 "^0.10.4" @@ -1369,13 +1364,13 @@ semver "^6.3.1" "@babel/preset-flow@^7.22.15": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.24.1.tgz#da7196c20c2d7dd4e98cfd8b192fe53b5eb6f0bb" - integrity sha512-sWCV2G9pcqZf+JHyv/RyqEIpFypxdCSxWIxQjpdaQxenNog7cN1pr76hg8u0Fz8Qgg0H4ETkGcJnXL8d4j0PPA== + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.24.7.tgz#eef5cb8e05e97a448fc50c16826f5612fe512c06" + integrity sha512-NL3Lo0NorCU607zU3NwRyJbpaB6E3t0xtd3LfAQKDfkeX4/ggcDXvkmkW42QWT5owUeW/jAe4hn+2qvkV1IbfQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-validator-option" "^7.23.5" - "@babel/plugin-transform-flow-strip-types" "^7.24.1" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-validator-option" "^7.24.7" + "@babel/plugin-transform-flow-strip-types" "^7.24.7" "@babel/preset-modules@0.1.6-no-external-plugins": version "0.1.6-no-external-plugins" @@ -1387,32 +1382,32 @@ esutils "^2.0.2" "@babel/preset-react@^7.12.5", "@babel/preset-react@^7.16.7", "@babel/preset-react@^7.18.6", "@babel/preset-react@^7.22.15": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.24.1.tgz#2450c2ac5cc498ef6101a6ca5474de251e33aa95" - integrity sha512-eFa8up2/8cZXLIpkafhaADTXSnl7IsUFCYenRWrARBz0/qZwcT0RBXpys0LJU4+WfPoF2ZG6ew6s2V6izMCwRA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-validator-option" "^7.23.5" - "@babel/plugin-transform-react-display-name" "^7.24.1" - "@babel/plugin-transform-react-jsx" "^7.23.4" - "@babel/plugin-transform-react-jsx-development" "^7.22.5" - "@babel/plugin-transform-react-pure-annotations" "^7.24.1" - -"@babel/preset-typescript@^7.13.0", "@babel/preset-typescript@^7.18.6", "@babel/preset-typescript@^7.23.0": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.24.1.tgz#89bdf13a3149a17b3b2a2c9c62547f06db8845ec" - integrity sha512-1DBaMmRDpuYQBPWD8Pf/WEwCrtgRHxsZnP4mIy9G/X+hFfbI47Q2G4t1Paakld84+qsk2fSsUPMKg71jkoOOaQ== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-validator-option" "^7.23.5" - "@babel/plugin-syntax-jsx" "^7.24.1" - "@babel/plugin-transform-modules-commonjs" "^7.24.1" - "@babel/plugin-transform-typescript" "^7.24.1" + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.24.7.tgz#480aeb389b2a798880bf1f889199e3641cbb22dc" + integrity sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-validator-option" "^7.24.7" + "@babel/plugin-transform-react-display-name" "^7.24.7" + "@babel/plugin-transform-react-jsx" "^7.24.7" + "@babel/plugin-transform-react-jsx-development" "^7.24.7" + "@babel/plugin-transform-react-pure-annotations" "^7.24.7" + +"@babel/preset-typescript@^7.13.0", "@babel/preset-typescript@^7.18.6", "@babel/preset-typescript@^7.21.0", "@babel/preset-typescript@^7.23.0": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz#66cd86ea8f8c014855671d5ea9a737139cbbfef1" + integrity sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-validator-option" "^7.24.7" + "@babel/plugin-syntax-jsx" "^7.24.7" + "@babel/plugin-transform-modules-commonjs" "^7.24.7" + "@babel/plugin-transform-typescript" "^7.24.7" "@babel/register@^7.22.15": - version "7.23.7" - resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.23.7.tgz#485a5e7951939d21304cae4af1719fdb887bc038" - integrity sha512-EjJeB6+kvpk+Y5DAkEAmbOBEFkh9OASx0huoEkqYTFxAZHzOAX2Oh5uwAUuL2rUddqfM0SA+KPXV2TbzoZ2kvQ== + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.24.6.tgz#59e21dcc79e1d04eed5377633b0f88029a6bef9e" + integrity sha512-WSuFCc2wCqMeXkz/i3yfAAsxwWflEgbVkZzivgAmXl/MxrXeoYFZOOPllbC8R8WTF7u61wSRQtDVZ1879cdu6w== dependencies: clone-deep "^4.0.1" find-cache-dir "^2.0.0" @@ -1426,60 +1421,60 @@ integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== "@babel/runtime-corejs2@^7.17.8": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs2/-/runtime-corejs2-7.24.4.tgz#3dac044ea9989e46b99b5f5ac038dbdd12e20e10" - integrity sha512-ZCKqyUKt/Coimg+3Kafu43yNetgYnTXzNbEGAgxc81J5sI0qFNbQ613w7PNny+SmijAmGVroL0GDvx5rG/JI5Q== + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs2/-/runtime-corejs2-7.24.7.tgz#28e73d50c44812060a58548c5096be4243ee3ee5" + integrity sha512-+Lf6xofiPZLtFwNkpjGHPgJck4b22Yo8h9+WHf3bEbS4ikOyOMNtJk6HSTolEQ2irH1XSoeguaCkrkcgyThrMA== dependencies: core-js "^2.6.12" regenerator-runtime "^0.14.0" "@babel/runtime-corejs3@^7.18.6", "@babel/runtime-corejs3@^7.22.5": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.24.4.tgz#b9ebe728087cfbb22bbaccc6f9a70d69834124a0" - integrity sha512-VOQOexSilscN24VEY810G/PqtpFvx/z6UqDIjIWbDe2368HhDLkYN5TYwaEz/+eRCUkhJ2WaNLLmQAlxzfWj4w== + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.24.7.tgz#65a99097e4c28e6c3a174825591700cc5abd710e" + integrity sha512-eytSX6JLBY6PVAeQa2bFlDx/7Mmln/gaEpsit5a3WEvjGfiIytEsgAwuIXCPM0xvw0v0cJn3ilq0/TvXrW0kgA== dependencies: core-js-pure "^3.30.2" regenerator-runtime "^0.14.0" -"@babel/runtime@7.22.11", "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.18.6", "@babel/runtime@^7.20.13", "@babel/runtime@^7.20.6", "@babel/runtime@^7.23.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.4", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.4.tgz#de795accd698007a66ba44add6cc86542aff1edd" - integrity sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA== +"@babel/runtime@7.22.11", "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.18.6", "@babel/runtime@^7.20.13", "@babel/runtime@^7.20.6", "@babel/runtime@^7.23.2", "@babel/runtime@^7.24.1", "@babel/runtime@^7.24.4", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.4", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.7.tgz#f4f0d5530e8dbdf59b3451b9b3e594b6ba082e12" + integrity sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw== dependencies: regenerator-runtime "^0.14.0" -"@babel/template@^7.12.7", "@babel/template@^7.22.15", "@babel/template@^7.24.0", "@babel/template@^7.3.3": - version "7.24.0" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.0.tgz#c6a524aa93a4a05d66aaf31654258fae69d87d50" - integrity sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA== - dependencies: - "@babel/code-frame" "^7.23.5" - "@babel/parser" "^7.24.0" - "@babel/types" "^7.24.0" - -"@babel/traverse@^7.0.0", "@babel/traverse@^7.12.9", "@babel/traverse@^7.18.8", "@babel/traverse@^7.18.9", "@babel/traverse@^7.23.2", "@babel/traverse@^7.24.1", "@babel/traverse@^7.7.0": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.1.tgz#d65c36ac9dd17282175d1e4a3c49d5b7988f530c" - integrity sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ== - dependencies: - "@babel/code-frame" "^7.24.1" - "@babel/generator" "^7.24.1" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.24.1" - "@babel/types" "^7.24.0" +"@babel/template@^7.12.7", "@babel/template@^7.24.7", "@babel/template@^7.3.3": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.7.tgz#02efcee317d0609d2c07117cb70ef8fb17ab7315" + integrity sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig== + dependencies: + "@babel/code-frame" "^7.24.7" + "@babel/parser" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/traverse@^7.0.0", "@babel/traverse@^7.12.9", "@babel/traverse@^7.18.8", "@babel/traverse@^7.18.9", "@babel/traverse@^7.23.2", "@babel/traverse@^7.24.7", "@babel/traverse@^7.7.0": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.7.tgz#de2b900163fa741721ba382163fe46a936c40cf5" + integrity sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA== + dependencies: + "@babel/code-frame" "^7.24.7" + "@babel/generator" "^7.24.7" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-function-name" "^7.24.7" + "@babel/helper-hoist-variables" "^7.24.7" + "@babel/helper-split-export-declaration" "^7.24.7" + "@babel/parser" "^7.24.7" + "@babel/types" "^7.24.7" debug "^4.3.1" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.12.6", "@babel/types@^7.12.7", "@babel/types@^7.18.9", "@babel/types@^7.20.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.4", "@babel/types@^7.24.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": - version "7.24.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.0.tgz#3b951f435a92e7333eba05b7566fd297960ea1bf" - integrity sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w== +"@babel/types@^7.0.0", "@babel/types@^7.12.6", "@babel/types@^7.12.7", "@babel/types@^7.18.9", "@babel/types@^7.20.0", "@babel/types@^7.20.7", "@babel/types@^7.21.3", "@babel/types@^7.23.0", "@babel/types@^7.24.7", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.7.tgz#6027fe12bc1aa724cd32ab113fb7f1988f1f66f2" + integrity sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q== dependencies: - "@babel/helper-string-parser" "^7.23.4" - "@babel/helper-validator-identifier" "^7.22.20" + "@babel/helper-string-parser" "^7.24.7" + "@babel/helper-validator-identifier" "^7.24.7" to-fast-properties "^2.0.0" "@base2/pretty-print-object@1.0.1": @@ -1497,13 +1492,26 @@ resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== -"@cornerstonejs/adapters@^1.70.6": - version "1.70.6" - resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-1.70.6.tgz#9e04d70af0f69c722a04d55dbe8daaf3023c6d70" - integrity sha512-V5exbaXTcy+jyoCA8IhajEwUMu0QJWjioDZyE6jHtUlL/wlB4cKx5CjD1rSzAnuLPKIcf6mX8MbUsAfsTOj+/g== +"@cornerstonejs/adapters@^1.77.6": + version "1.83.0" + resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-1.83.0.tgz#934c462d98b7857ef9670702547505d112fa13f8" + integrity sha512-PKNdzwI/i79Gu9ZxM4SemttCKJpSnMUSQSBu27mXzFzm5ENyOGnus3sLV5ciqZBRaHiuyteaHosJhxOavxaX1g== dependencies: "@babel/runtime-corejs2" "^7.17.8" - "@cornerstonejs/tools" "^1.70.6" + "@cornerstonejs/tools" "^1.83.0" + buffer "^6.0.3" + dcmjs "^0.29.8" + gl-matrix "^3.4.3" + lodash.clonedeep "^4.5.0" + ndarray "^1.0.19" + +"@cornerstonejs/adapters@^1.81.6", "@cornerstonejs/adapters@^1.82.0": + version "1.82.0" + resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-1.82.0.tgz#4c7ae6341ad7bcf5cf0213e5252fbac009da23b6" + integrity sha512-hcLmba3b7jC1wEorCzaS4OSFBuHz5V5I3IJW1PHbwIAWNHiuKMcC4j6ndMeQhVXHtmy56HUQP+yKAPez59k8Yw== + dependencies: + "@babel/runtime-corejs2" "^7.17.8" + "@cornerstonejs/tools" "^1.82.0" buffer "^6.0.3" dcmjs "^0.29.8" gl-matrix "^3.4.3" @@ -1515,80 +1523,99 @@ resolved "https://registry.yarnpkg.com/@cornerstonejs/calculate-suv/-/calculate-suv-1.1.0.tgz#35c8049d3eea03611225a8398d398cd81bf0031a" integrity sha512-Q9XraiDJif9aMFArD2iEuDO/HXbcRVCqB7KfaHgDrdTTjgDFovS91Psbdim7crypRSvE6dh/+HKeFNHdvNkA6w== -"@cornerstonejs/codec-charls@^0.1.1": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@cornerstonejs/codec-charls/-/codec-charls-0.1.1.tgz#e55d4aa908732d0cc902888b7f3856c5a996df7f" - integrity sha512-Y250DGVzmownJ7WgpHxNqWvfTnv4/malaKm/tWm0xE1FxhQE8iErMWFpKxpNDk3MdfXO4/98piVsUwmJMiWoDQ== - "@cornerstonejs/codec-charls@^1.2.3": version "1.2.3" resolved "https://registry.yarnpkg.com/@cornerstonejs/codec-charls/-/codec-charls-1.2.3.tgz#6952c420486822ac8404409ae0ed5a559aff6e25" integrity sha512-qKUe6DN0dnGzhhfZLYhH9UZacMcudjxcaLXCrpxJImT/M/PQvZCT2rllu6VGJbWKJWG+dMVV2zmmleZcdJ7/cA== -"@cornerstonejs/codec-libjpeg-turbo-8bit@^0.0.7": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@cornerstonejs/codec-libjpeg-turbo-8bit/-/codec-libjpeg-turbo-8bit-0.0.7.tgz#2ea9b575eed19e6e7e3701b7a50a4ae0ffbef0c4" - integrity sha512-qgm6BuVAy5mNP8SJ+A6+VbmPnqgj8jPvJrw4HbUoAzndmf9/VHjTYwawn3kmZWya5ErFAsXQ6c0U0noB1LKAiA== - "@cornerstonejs/codec-libjpeg-turbo-8bit@^1.2.2": version "1.2.2" resolved "https://registry.yarnpkg.com/@cornerstonejs/codec-libjpeg-turbo-8bit/-/codec-libjpeg-turbo-8bit-1.2.2.tgz#ae384b149d6655e3dd6e18b9891fab479ab5e144" integrity sha512-aAUMK2958YNpOb/7G6e2/aG7hExTiFTASlMt/v90XA0pRHdWiNg5ny4S5SAju0FbIw4zcMnR0qfY+yW3VG2ivg== -"@cornerstonejs/codec-openjpeg@^0.1.1": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@cornerstonejs/codec-openjpeg/-/codec-openjpeg-0.1.1.tgz#5bd1c52a33a425299299e970312731fa0cc2711b" - integrity sha512-HOMMOLV6xy8O/agNGGvrl0a8DwShpBvWxAzEzv2pqq12d3r5z/3MyIgNA3Oj/8bIBVvvVXxh9RX7rMDRHJdowg== - "@cornerstonejs/codec-openjpeg@^1.2.2": - version "1.2.3" - resolved "https://registry.yarnpkg.com/@cornerstonejs/codec-openjpeg/-/codec-openjpeg-1.2.3.tgz#52bd61e7fe6fbe19f5997c8c7fddc3cd0e2072e8" - integrity sha512-zAWv+O/7LpfHUJDKXwwo7z+l1E1rQQZYePiROv0PFhlMvMTs6RBa+n3r7fbph0aJtd9iUPfX9QKpokiMzr0mdw== + version "1.2.4" + resolved "https://registry.yarnpkg.com/@cornerstonejs/codec-openjpeg/-/codec-openjpeg-1.2.4.tgz#c7cf67a34091eb74a6676abec80a5251c412b551" + integrity sha512-UT2su6xZZnCPSuWf2ldzKa/2+guQ7BGgfBSKqxanggwJHh48gZqIAzekmsLyJHMMK5YDK+ti+fzvVJhBS3Xi/g== "@cornerstonejs/codec-openjph@^2.4.5": version "2.4.5" resolved "https://registry.yarnpkg.com/@cornerstonejs/codec-openjph/-/codec-openjph-2.4.5.tgz#8690b61a86fa53ef38a70eee9d665a79229517c0" integrity sha512-MZCUy8VG0VG5Nl1l58+g+kH3LujAzLYTfJqkwpWI2gjSrGXnP6lgwyy4GmPRZWVoS40/B1LDNALK905cNWm+sg== -"@cornerstonejs/core@^1.70.6": - version "1.70.6" - resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-1.70.6.tgz#8a78696b1b2a79909d034a223988844e805a8154" - integrity sha512-XOEVS9qK2gQHwuKZJc21I2ImcFNFHIyDXGQjYLOTe6reUlWow9y1ZqvLMF+dVhRs7WVNAwJNPibe5ky8759dkw== +"@cornerstonejs/core@^1.77.6", "@cornerstonejs/core@^1.83.0": + version "1.83.0" + resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-1.83.0.tgz#d8781fe95a404f609ebd25a3f3fd93a3a4f58c70" + integrity sha512-EEOHw+G6pjSmuPvTsANPKbY/sAuskIkt24qpuE6+1tpKMt7/1pTrJY8mVHIO4/g6cfyWJl9RO8w5nLyR77SomA== + dependencies: + "@kitware/vtk.js" "30.4.1" + comlink "^4.4.1" + detect-gpu "^5.0.22" + gl-matrix "^3.4.3" + lodash.clonedeep "4.5.0" + +"@cornerstonejs/core@^1.81.3": + version "1.81.3" + resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-1.81.3.tgz#76deaee4a2cce24db5695cb87857accea5645263" + integrity sha512-Uievs/wBpw20Xj4B+8UEjb/qe+cmSfz2oWfQzBANcWoqI5pXD77evXE0s6hORCMr4yFUmTIMbGnWwXT2fF2bYw== dependencies: - "@kitware/vtk.js" "30.3.3" + "@kitware/vtk.js" "30.4.1" comlink "^4.4.1" detect-gpu "^5.0.22" gl-matrix "^3.4.3" lodash.clonedeep "4.5.0" -"@cornerstonejs/dicom-image-loader@^1.70.6": - version "1.70.6" - resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-1.70.6.tgz#ce16e2a4544768a55fbcb916391850908276a606" - integrity sha512-KZNR+i9CdjWvzPxWzhUon2H9IAsvg9Axdzj2qQgM/8+sVz2yKa6TPxlnLKFlW8QEwuZsP/AHkVQuqzJ92PVnlw== +"@cornerstonejs/core@^1.81.6", "@cornerstonejs/core@^1.82.0": + version "1.82.0" + resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-1.82.0.tgz#ad9169e912370a2f0c984923edd9782d9d9402ec" + integrity sha512-Pnqug+ZMPADd59CAISK7L+I2RiXlJFvdodV5CCgLkwLfqPXZv2nVyr9/BphE7gFAPhwBwKQwIr568Tuxlwim4Q== + dependencies: + "@kitware/vtk.js" "30.4.1" + comlink "^4.4.1" + detect-gpu "^5.0.22" + gl-matrix "^3.4.3" + lodash.clonedeep "4.5.0" + +"@cornerstonejs/dicom-image-loader@^1.77.6": + version "1.81.3" + resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-1.81.3.tgz#8d9165b351954999bbc566d811a9eedd2363d55c" + integrity sha512-QFqr0Jq9DWvoBB1rTwI6gL4fc3pawpnG6ebDSZpz+uPmG/QcGYaeGNT+Szrcu2V/q1ByOU/Jxn8ZG5Nuo+kD6A== dependencies: "@cornerstonejs/codec-charls" "^1.2.3" "@cornerstonejs/codec-libjpeg-turbo-8bit" "^1.2.2" "@cornerstonejs/codec-openjpeg" "^1.2.2" "@cornerstonejs/codec-openjph" "^2.4.5" - "@cornerstonejs/core" "^1.70.6" + "@cornerstonejs/core" "^1.81.3" dicom-parser "^1.8.9" pako "^2.0.4" uuid "^9.0.0" -"@cornerstonejs/streaming-image-volume-loader@^1.70.6": - version "1.70.6" - resolved "https://registry.yarnpkg.com/@cornerstonejs/streaming-image-volume-loader/-/streaming-image-volume-loader-1.70.6.tgz#00c6ba40e9a5fc14409d56b08f1512d3e24df6d5" - integrity sha512-A78awLgJh1bl6zq7SbjeXjn/vIFX3Q5rb4hAlk09/rFwmNJtJbxH4z6/gUnVBh/rLSDnpyxzie4VgJje3/WPRQ== +"@cornerstonejs/streaming-image-volume-loader@^1.82.0": + version "1.82.0" + resolved "https://registry.yarnpkg.com/@cornerstonejs/streaming-image-volume-loader/-/streaming-image-volume-loader-1.82.0.tgz#a513ca57236f13af0045f2118352e1919120db1c" + integrity sha512-BW/ncOf0ouP82o8jQkj2hhWdjqlA23mNls1gYrpsWBUnyYQOBeto2XZ2LgIOfIgvCrtbhXlE03/nkwxdvTgp3w== dependencies: - "@cornerstonejs/core" "^1.70.6" + "@cornerstonejs/core" "^1.82.0" comlink "^4.4.1" -"@cornerstonejs/tools@^1.70.6": - version "1.70.6" - resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-1.70.6.tgz#6e4fe7872dd9aed32062cc76d59c9b567012b408" - integrity sha512-Su3bzD6y0k9VjxDGkyh6QM6HHW/QJ4PzfpfE5fYpGeQzHJnpjmUpM5/YTBnRMxlqtI8IW8EJuKUgMMjnzvsQfw== +"@cornerstonejs/tools@^1.82.0": + version "1.82.0" + resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-1.82.0.tgz#c7c9a24cc80755121c2209489e348b8c9d252d0d" + integrity sha512-1nnlloa6g5zfirAbVnZ+lfuM6DdtcN8kHkZ29xkedzpP24Le4fRHNeuNf6jTSGcgDXPhoZ+WA+q8NnH6wj1h1Q== dependencies: - "@cornerstonejs/core" "^1.70.6" + "@cornerstonejs/core" "^1.82.0" + "@icr/polyseg-wasm" "0.4.0" + "@types/offscreencanvas" "2019.7.3" + comlink "^4.4.1" + lodash.clonedeep "4.5.0" + lodash.get "^4.4.2" + +"@cornerstonejs/tools@^1.83.0": + version "1.83.0" + resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-1.83.0.tgz#6148e72972d826abfa640924f5c34f0d4acd75a3" + integrity sha512-P7b0iPGidBJ7rlfnpiIZV2jgivdVZKQ7emWd59CGN4HgEStPQOMrb6lnrDvZs1BDK2d2TjZB6vhwH0G/B/quUw== + dependencies: + "@cornerstonejs/core" "^1.83.0" "@icr/polyseg-wasm" "0.4.0" "@types/offscreencanvas" "2019.7.3" comlink "^4.4.1" @@ -2086,7 +2113,7 @@ "@docusaurus/theme-search-algolia" "2.4.3" "@docusaurus/types" "2.4.3" -"@docusaurus/react-loadable@5.5.2", "react-loadable@npm:@docusaurus/react-loadable@5.5.2": +"@docusaurus/react-loadable@5.5.2": version "5.5.2" resolved "https://registry.yarnpkg.com/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz#81aae0db81ecafbdaee3651f12804580868fa6ce" integrity sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ== @@ -2295,6 +2322,18 @@ resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.1.tgz#4ffb0055f7ef676ebc3a5a91fb621393294e2f43" integrity sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ== +"@emotion/is-prop-valid@^0.8.2": + version "0.8.8" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a" + integrity sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA== + dependencies: + "@emotion/memoize" "0.7.4" + +"@emotion/memoize@0.7.4": + version "0.7.4" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb" + integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw== + "@emotion/memoize@^0.8.1": version "0.8.1" resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.1.tgz#c1ddb040429c6d21d38cc945fe75c818cfb68e17" @@ -2465,64 +2504,69 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz#786c5f41f043b07afb1af37683d7c33668858f6d" integrity sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ== -"@eslint-community/eslint-utils@^4.4.0": +"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== dependencies: eslint-visitor-keys "^3.3.0" -"@eslint-community/regexpp@^4.5.1": - version "4.10.0" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" - integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== +"@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1": + version "4.10.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.1.tgz#361461e5cb3845d874e61731c11cfedd664d83a0" + integrity sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA== -"@eslint/eslintrc@^0.4.3": - version "0.4.3" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" - integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw== +"@eslint/eslintrc@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" + integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== dependencies: ajv "^6.12.4" - debug "^4.1.1" - espree "^7.3.0" - globals "^13.9.0" - ignore "^4.0.6" + debug "^4.3.2" + espree "^9.6.0" + globals "^13.19.0" + ignore "^5.2.0" import-fresh "^3.2.1" - js-yaml "^3.13.1" - minimatch "^3.0.4" + js-yaml "^4.1.0" + minimatch "^3.1.2" strip-json-comments "^3.1.1" +"@eslint/js@8.57.0": + version "8.57.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" + integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== + "@fal-works/esbuild-plugin-global-externals@^2.1.2": version "2.1.2" resolved "https://registry.yarnpkg.com/@fal-works/esbuild-plugin-global-externals/-/esbuild-plugin-global-externals-2.1.2.tgz#c05ed35ad82df8e6ac616c68b92c2282bd083ba4" integrity sha512-cEee/Z+I12mZcFJshKcCqC8tuX5hG3s+d+9nZ3LabqKF1vKdF41B92pJVCBggjAGORAeOzyyDDKrZwIkLffeOQ== "@floating-ui/core@^1.0.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.0.tgz#fa41b87812a16bf123122bf945946bae3fdf7fc1" - integrity sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g== + version "1.6.2" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.2.tgz#d37f3e0ac1f1c756c7de45db13303a266226851a" + integrity sha512-+2XpQV9LLZeanU4ZevzRnGFg2neDeKHgFLjP6YLW+tly0IvrhqT4u8enLGjLH3qeh85g19xY5rsAusfwTdn5lg== dependencies: - "@floating-ui/utils" "^0.2.1" + "@floating-ui/utils" "^0.2.0" -"@floating-ui/dom@^1.0.1", "@floating-ui/dom@^1.6.1": - version "1.6.3" - resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.3.tgz#954e46c1dd3ad48e49db9ada7218b0985cee75ef" - integrity sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw== +"@floating-ui/dom@^1.0.0", "@floating-ui/dom@^1.0.1": + version "1.6.5" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.5.tgz#323f065c003f1d3ecf0ff16d2c2c4d38979f4cb9" + integrity sha512-Nsdud2X65Dz+1RHjAIP0t8z5e2ff/IRbei6BqFrl1urT8sDVzM1HMQ+R0XcU5ceRfyO3I6ayeqIfh+6Wb8LGTw== dependencies: "@floating-ui/core" "^1.0.0" "@floating-ui/utils" "^0.2.0" "@floating-ui/react-dom@^2.0.0": - version "2.0.8" - resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.0.8.tgz#afc24f9756d1b433e1fe0d047c24bd4d9cefaa5d" - integrity sha512-HOdqOt3R3OGeTKidaLvJKcgg75S6tibQ3Tif4eyd91QnIJWr0NLvoXFpJA/j8HqkFSL68GDca9AuyWEHlhyClw== + version "2.1.0" + resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.1.0.tgz#4f0e5e9920137874b2405f7d6c862873baf4beff" + integrity sha512-lNzj5EQmEKn5FFKc04+zasr09h/uX8RtJRNj5gUXsSQIXHVWTVh+hVAg1vOMCexkX8EgvemMvIFpQfkosnVNyA== dependencies: - "@floating-ui/dom" "^1.6.1" + "@floating-ui/dom" "^1.0.0" -"@floating-ui/utils@^0.2.0", "@floating-ui/utils@^0.2.1": - version "0.2.1" - resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.1.tgz#16308cea045f0fc777b6ff20a9f25474dd8293d2" - integrity sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q== +"@floating-ui/utils@^0.2.0": + version "0.2.2" + resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.2.tgz#d8bae93ac8b815b2bd7a98078cf91e2724ef11e5" + integrity sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw== "@gar/promisify@^1.1.3": version "1.1.3" @@ -2541,19 +2585,24 @@ dependencies: "@hapi/hoek" "^9.0.0" -"@humanwhocodes/config-array@^0.5.0": - version "0.5.0" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9" - integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg== +"@humanwhocodes/config-array@^0.11.14": + version "0.11.14" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" + integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== dependencies: - "@humanwhocodes/object-schema" "^1.2.0" - debug "^4.1.1" - minimatch "^3.0.4" + "@humanwhocodes/object-schema" "^2.0.2" + debug "^4.3.1" + minimatch "^3.0.5" -"@humanwhocodes/object-schema@^1.2.0": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" - integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/object-schema@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" + integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== "@hutson/parse-repository-url@^3.0.0": version "3.0.2" @@ -2844,10 +2893,10 @@ resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60" integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA== -"@kitware/vtk.js@30.3.3": - version "30.3.3" - resolved "https://registry.yarnpkg.com/@kitware/vtk.js/-/vtk.js-30.3.3.tgz#348e17fdc896c912eca7036f607d21ef6128bca1" - integrity sha512-es9I5LLlg+TpaIXk5aHSPzyI/YnCI4egHA1cbG98IP7t9W4KODUcJjyrXFAa7aSvfXZ8y2jhD9qrsaEnstEkJA== +"@kitware/vtk.js@30.4.1": + version "30.4.1" + resolved "https://registry.yarnpkg.com/@kitware/vtk.js/-/vtk.js-30.4.1.tgz#ce8a50012e56341d2d01708a32a2ac3afa675b67" + integrity sha512-jBJFm8AyWpJjNFFBadXyvBwegdD9M6WRdxmIb+x/MVpCyA5lEZSMemhiMn71oKsznaEe5Pjv2VDVJWmwK0vhUg== dependencies: "@babel/runtime" "7.22.11" "@types/webxr" "^0.5.5" @@ -3060,7 +3109,7 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== -"@nodelib/fs.walk@^1.2.3": +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": version "1.2.8" resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== @@ -3077,9 +3126,9 @@ semver "^7.3.5" "@npmcli/fs@^3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-3.1.0.tgz#233d43a25a91d68c3a863ba0da6a3f00924a173e" - integrity sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w== + version "3.1.1" + resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-3.1.1.tgz#59cdaa5adca95d135fc00f2bb53f5771575ce726" + integrity sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg== dependencies: semver "^7.3.5" @@ -3098,9 +3147,9 @@ which "^3.0.0" "@npmcli/installed-package-contents@^2.0.1": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@npmcli/installed-package-contents/-/installed-package-contents-2.0.2.tgz#bfd817eccd9e8df200919e73f57f9e3d9e4f9e33" - integrity sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ== + version "2.1.0" + resolved "https://registry.yarnpkg.com/@npmcli/installed-package-contents/-/installed-package-contents-2.1.0.tgz#63048e5f6e40947a3a88dcbcb4fd9b76fdd37c17" + integrity sha512-c8UuGLeZpm69BryRykLuKRyKFZYJsZSCT4aVY5ds4omyZqJ172ApzgfKJ5eV/r3HgLdUYgFVe54KSFVjKoe27w== dependencies: npm-bundled "^3.0.0" npm-normalize-package-bin "^3.0.0" @@ -3375,14 +3424,14 @@ "@percy/sdk-utils" "^1.3.1" "@percy/sdk-utils@^1.3.1": - version "1.28.2" - resolved "https://registry.yarnpkg.com/@percy/sdk-utils/-/sdk-utils-1.28.2.tgz#22d48ab0a281bbf39add303fcb1687ccac0e91a1" - integrity sha512-cMFz8AjZ2KunN0dVwzA+Wosk4B+6G9dUkh2YPhYvqs0KLcCyYs3s91IzOQmtBOYwAUVja/W/u6XmBHw0jaxg0A== + version "1.28.7" + resolved "https://registry.yarnpkg.com/@percy/sdk-utils/-/sdk-utils-1.28.7.tgz#22393f76d69ffee2f4def79aa41f15a7369f7503" + integrity sha512-LIhfHnkcS0fyIdo3gvKn7rwodZjbEtyLkgiDRSRulcBOatI2mhn2Bh269sXXiiFTyAW2BDQjyE3DWc4hkGbsbQ== "@petamoriken/float16@^3.4.7": - version "3.8.6" - resolved "https://registry.yarnpkg.com/@petamoriken/float16/-/float16-3.8.6.tgz#580701cb97a510882342333d31c7cbfd9e14b4f4" - integrity sha512-GNJhABTtcmt9al/nqdJPycwFD46ww2+q2zwZzTjY0dFFwUAFRw9zszvEr9osyJRd9krRGy6hUDopWUg9fX7VVw== + version "3.8.7" + resolved "https://registry.yarnpkg.com/@petamoriken/float16/-/float16-3.8.7.tgz#16073fb1b9867eaa5b254573484d09100700aaa4" + integrity sha512-/Ri4xDDpe12NT6Ex/DRgHzLlobiQXEW/hmG08w1wj/YU7hLemk97c+zHQFp0iZQ9r7YqgLEXZR2sls4HxBf9NA== "@philpl/buble@^0.19.7": version "0.19.7" @@ -3409,19 +3458,24 @@ resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== -"@pmmmwh/react-refresh-webpack-plugin@^0.5.11": - version "0.5.11" - resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.11.tgz#7c2268cedaa0644d677e8c4f377bc8fb304f714a" - integrity sha512-7j/6vdTym0+qZ6u4XbSAxrWBGYSdCfTzySkj7WAFgDLmSyWlOrWvpyzxlFh5jtw9dn0oL/jtW+06XfFiisN3JQ== +"@playwright/test@^1.44.0": + version "1.44.1" + resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.44.1.tgz#cc874ec31342479ad99838040e99b5f604299bcb" + integrity sha512-1hZ4TNvD5z9VuhNJ/walIjvMVvYkZKf71axoF/uiAqpntQJXpG64dlXhoDXE3OczPuTuvjf/M5KWFg5VAVUS3Q== dependencies: - ansi-html-community "^0.0.8" - common-path-prefix "^3.0.0" + playwright "1.44.1" + +"@pmmmwh/react-refresh-webpack-plugin@^0.5.11", "@pmmmwh/react-refresh-webpack-plugin@^0.5.15": + version "0.5.15" + resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.15.tgz#f126be97c30b83ed777e2aeabd518bc592e6e7c4" + integrity sha512-LFWllMA55pzB9D34w/wXUCf8+c+IYKuJDgxiZ3qMhl64KRMBHYM1I3VdGaD2BV5FNPV2/S2596bppxHbv2ZydQ== + dependencies: + ansi-html "^0.0.9" core-js-pure "^3.23.3" error-stack-parser "^2.0.6" - find-up "^5.0.0" html-entities "^2.1.0" loader-utils "^2.0.4" - schema-utils "^3.0.0" + schema-utils "^4.2.0" source-map "^0.7.3" "@pnpm/config.env-replace@^1.1.0": @@ -3464,6 +3518,11 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/primitive@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.0.tgz#42ef83b3b56dccad5d703ae8c42919a68798bbe2" + integrity sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA== + "@radix-ui/react-arrow@1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz#c24f7968996ed934d57fe6cde5d6ec7266e1d25d" @@ -3472,6 +3531,13 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-primitive" "1.0.3" +"@radix-ui/react-arrow@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz#744f388182d360b86285217e43b6c63633f39e7a" + integrity sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw== + dependencies: + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-collection@1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.0.3.tgz#9595a66e09026187524a36c6e7e9c7d286469159" @@ -3490,6 +3556,11 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-compose-refs@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz#656432461fc8283d7b591dcf0d79152fae9ecc74" + integrity sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw== + "@radix-ui/react-context@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.0.1.tgz#fe46e67c96b240de59187dcb7a1a50ce3e2ec00c" @@ -3497,6 +3568,32 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-context@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.0.tgz#6df8d983546cfd1999c8512f3a8ad85a6e7fcee8" + integrity sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A== + +"@radix-ui/react-dialog@1.0.5", "@radix-ui/react-dialog@^1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.0.5.tgz#71657b1b116de6c7a0b03242d7d43e01062c7300" + integrity sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.1" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-context" "1.0.1" + "@radix-ui/react-dismissable-layer" "1.0.5" + "@radix-ui/react-focus-guards" "1.0.1" + "@radix-ui/react-focus-scope" "1.0.4" + "@radix-ui/react-id" "1.0.1" + "@radix-ui/react-portal" "1.0.4" + "@radix-ui/react-presence" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-slot" "1.0.2" + "@radix-ui/react-use-controllable-state" "1.0.1" + aria-hidden "^1.1.1" + react-remove-scroll "2.5.5" + "@radix-ui/react-direction@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.0.1.tgz#9cb61bf2ccf568f3421422d182637b7f47596c9b" @@ -3516,6 +3613,29 @@ "@radix-ui/react-use-callback-ref" "1.0.1" "@radix-ui/react-use-escape-keydown" "1.0.3" +"@radix-ui/react-dismissable-layer@1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.5.tgz#3f98425b82b9068dfbab5db5fff3df6ebf48b9d4" + integrity sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.1" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-use-callback-ref" "1.0.1" + "@radix-ui/react-use-escape-keydown" "1.0.3" + +"@radix-ui/react-dismissable-layer@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.0.tgz#2cd0a49a732372513733754e6032d3fb7988834e" + integrity sha512-/UovfmmXGptwGcBQawLzvn2jOfM0t4z3/uKffoBlj724+n3FvBbZ7M0aaBOmkp6pqFYpO4yx8tSVJjx3Fl2jig== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-escape-keydown" "1.1.0" + "@radix-ui/react-focus-guards@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz#1ea7e32092216b946397866199d892f71f7f98ad" @@ -3533,6 +3653,21 @@ "@radix-ui/react-primitive" "1.0.3" "@radix-ui/react-use-callback-ref" "1.0.1" +"@radix-ui/react-focus-scope@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.4.tgz#2ac45fce8c5bb33eb18419cdc1905ef4f1906525" + integrity sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-use-callback-ref" "1.0.1" + +"@radix-ui/react-icons@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-icons/-/react-icons-1.3.0.tgz#c61af8f323d87682c5ca76b856d60c2312dbcb69" + integrity sha512-jQxj/0LKgp+j9BiTXz3O3sgs26RNet2iLWmsPyRz2SIcR4q/4SbazXfnYwbAr+vLYKSfc7qxzyGQA1HLlYiuNw== + "@radix-ui/react-id@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.0.1.tgz#73cdc181f650e4df24f0b6a5b7aa426b912c88c0" @@ -3541,6 +3676,35 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-use-layout-effect" "1.0.1" +"@radix-ui/react-id@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.1.0.tgz#de47339656594ad722eb87f94a6b25f9cffae0ed" + integrity sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA== + dependencies: + "@radix-ui/react-use-layout-effect" "1.1.0" + +"@radix-ui/react-popover@^1.0.7": + version "1.0.7" + resolved "https://registry.yarnpkg.com/@radix-ui/react-popover/-/react-popover-1.0.7.tgz#23eb7e3327330cb75ec7b4092d685398c1654e3c" + integrity sha512-shtvVnlsxT6faMnK/a7n0wptwBD23xc1Z5mdrtKLwVEfsEMXodS0r5s0/g5P0hX//EKYZS2sxUjqfzlg52ZSnQ== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.1" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-context" "1.0.1" + "@radix-ui/react-dismissable-layer" "1.0.5" + "@radix-ui/react-focus-guards" "1.0.1" + "@radix-ui/react-focus-scope" "1.0.4" + "@radix-ui/react-id" "1.0.1" + "@radix-ui/react-popper" "1.1.3" + "@radix-ui/react-portal" "1.0.4" + "@radix-ui/react-presence" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-slot" "1.0.2" + "@radix-ui/react-use-controllable-state" "1.0.1" + aria-hidden "^1.1.1" + react-remove-scroll "2.5.5" + "@radix-ui/react-popper@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.1.2.tgz#4c0b96fcd188dc1f334e02dba2d538973ad842e9" @@ -3558,6 +3722,39 @@ "@radix-ui/react-use-size" "1.0.1" "@radix-ui/rect" "1.0.1" +"@radix-ui/react-popper@1.1.3": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.1.3.tgz#24c03f527e7ac348fabf18c89795d85d21b00b42" + integrity sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w== + dependencies: + "@babel/runtime" "^7.13.10" + "@floating-ui/react-dom" "^2.0.0" + "@radix-ui/react-arrow" "1.0.3" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-context" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-use-callback-ref" "1.0.1" + "@radix-ui/react-use-layout-effect" "1.0.1" + "@radix-ui/react-use-rect" "1.0.1" + "@radix-ui/react-use-size" "1.0.1" + "@radix-ui/rect" "1.0.1" + +"@radix-ui/react-popper@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.2.0.tgz#a3e500193d144fe2d8f5d5e60e393d64111f2a7a" + integrity sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg== + dependencies: + "@floating-ui/react-dom" "^2.0.0" + "@radix-ui/react-arrow" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-use-rect" "1.1.0" + "@radix-ui/react-use-size" "1.1.0" + "@radix-ui/rect" "1.1.0" + "@radix-ui/react-portal@1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.0.3.tgz#ffb961244c8ed1b46f039e6c215a6c4d9989bda1" @@ -3566,6 +3763,39 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-primitive" "1.0.3" +"@radix-ui/react-portal@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.0.4.tgz#df4bfd353db3b1e84e639e9c63a5f2565fb00e15" + integrity sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-primitive" "1.0.3" + +"@radix-ui/react-portal@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.1.tgz#1957f1eb2e1aedfb4a5475bd6867d67b50b1d15f" + integrity sha512-A3UtLk85UtqhzFqtoC8Q0KvR2GbXF3mtPgACSazajqq6A41mEQgo53iPzY4i6BwDxlIFqWIhiQ2G729n+2aw/g== + dependencies: + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + +"@radix-ui/react-presence@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.0.1.tgz#491990ba913b8e2a5db1b06b203cb24b5cdef9ba" + integrity sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-use-layout-effect" "1.0.1" + +"@radix-ui/react-presence@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.0.tgz#227d84d20ca6bfe7da97104b1a8b48a833bfb478" + integrity sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ== + dependencies: + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-primitive@1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz#d49ea0f3f0b2fe3ab1cb5667eb03e8b843b914d0" @@ -3574,6 +3804,13 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-slot" "1.0.2" +"@radix-ui/react-primitive@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz#fe05715faa9203a223ccc0be15dc44b9f9822884" + integrity sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw== + dependencies: + "@radix-ui/react-slot" "1.1.0" + "@radix-ui/react-roving-focus@1.0.4": version "1.0.4" resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.4.tgz#e90c4a6a5f6ac09d3b8c1f5b5e81aab2f0db1974" @@ -3626,7 +3863,7 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-primitive" "1.0.3" -"@radix-ui/react-slot@1.0.2": +"@radix-ui/react-slot@1.0.2", "@radix-ui/react-slot@^1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.0.2.tgz#a9ff4423eade67f501ffb32ec22064bc9d3099ab" integrity sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg== @@ -3634,6 +3871,13 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-compose-refs" "1.0.1" +"@radix-ui/react-slot@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.1.0.tgz#7c5e48c36ef5496d97b08f1357bb26ed7c714b84" + integrity sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw== + dependencies: + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-toggle-group@1.0.4": version "1.0.4" resolved "https://registry.yarnpkg.com/@radix-ui/react-toggle-group/-/react-toggle-group-1.0.4.tgz#f5b5c8c477831b013bec3580c55e20a68179d6ec" @@ -3672,6 +3916,24 @@ "@radix-ui/react-separator" "1.0.3" "@radix-ui/react-toggle-group" "1.0.4" +"@radix-ui/react-tooltip@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-tooltip/-/react-tooltip-1.1.2.tgz#c42db2ffd7dcc6ff3d65407c8cb70490288f518d" + integrity sha512-9XRsLwe6Yb9B/tlnYCPVUd/TFS4J7HuOZW345DCeC6vKIxQGMZdx21RK4VoZauPD5frgkXTYVS5y90L+3YBn4w== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-dismissable-layer" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-popper" "1.2.0" + "@radix-ui/react-portal" "1.1.1" + "@radix-ui/react-presence" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-slot" "1.1.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-visually-hidden" "1.1.0" + "@radix-ui/react-use-callback-ref@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz#f4bb1f27f2023c984e6534317ebc411fc181107a" @@ -3679,6 +3941,11 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-use-callback-ref@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz#bce938ca413675bc937944b0d01ef6f4a6dc5bf1" + integrity sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw== + "@radix-ui/react-use-controllable-state@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz#ecd2ced34e6330caf89a82854aa2f77e07440286" @@ -3687,6 +3954,13 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-use-callback-ref" "1.0.1" +"@radix-ui/react-use-controllable-state@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz#1321446857bb786917df54c0d4d084877aab04b0" + integrity sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw== + dependencies: + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-escape-keydown@1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz#217b840c250541609c66f67ed7bab2b733620755" @@ -3695,6 +3969,13 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-use-callback-ref" "1.0.1" +"@radix-ui/react-use-escape-keydown@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz#31a5b87c3b726504b74e05dac1edce7437b98754" + integrity sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw== + dependencies: + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-layout-effect@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz#be8c7bc809b0c8934acf6657b577daf948a75399" @@ -3702,6 +3983,11 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-use-layout-effect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz#3c2c8ce04827b26a39e442ff4888d9212268bd27" + integrity sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w== + "@radix-ui/react-use-previous@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-use-previous/-/react-use-previous-1.0.1.tgz#b595c087b07317a4f143696c6a01de43b0d0ec66" @@ -3717,6 +4003,13 @@ "@babel/runtime" "^7.13.10" "@radix-ui/rect" "1.0.1" +"@radix-ui/react-use-rect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz#13b25b913bd3e3987cc9b073a1a164bb1cf47b88" + integrity sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ== + dependencies: + "@radix-ui/rect" "1.1.0" + "@radix-ui/react-use-size@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.0.1.tgz#1c5f5fea940a7d7ade77694bb98116fb49f870b2" @@ -3725,6 +4018,13 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-use-layout-effect" "1.0.1" +"@radix-ui/react-use-size@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz#b4dba7fbd3882ee09e8d2a44a3eed3a7e555246b" + integrity sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw== + dependencies: + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-visually-hidden@1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.3.tgz#51aed9dd0fe5abcad7dee2a234ad36106a6984ac" @@ -3733,6 +4033,13 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-primitive" "1.0.3" +"@radix-ui/react-visually-hidden@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.0.tgz#ad47a8572580f7034b3807c8e6740cd41038a5a2" + integrity sha512-N8MDZqtgCgG5S3aV60INAB475osJousYpZ4cTJ2cFbMpdHS5Y6loLTH8LPtkj2QN0x93J30HT/M3qJXM0+lyeQ== + dependencies: + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/rect@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.0.1.tgz#bf8e7d947671996da2e30f4904ece343bc4a883f" @@ -3740,6 +4047,11 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/rect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.1.0.tgz#f817d1d3265ac5415dadc67edab30ae196696438" + integrity sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg== + "@react-dnd/asap@^4.0.0": version "4.0.1" resolved "https://registry.yarnpkg.com/@react-dnd/asap/-/asap-4.0.1.tgz#5291850a6b58ce6f2da25352a64f1b0674871aab" @@ -3755,10 +4067,10 @@ resolved "https://registry.yarnpkg.com/@react-dnd/shallowequal/-/shallowequal-2.0.0.tgz#a3031eb54129f2c66b2753f8404266ec7bf67f0a" integrity sha512-Pc/AFTdwZwEKJxFJvlxrSmGe/di+aAOBn60sremrpLo6VI/6cmiUYNNwlI5KNYttg7uypzA3ILPMPgxB2GYZEg== -"@remix-run/router@1.15.3": - version "1.15.3" - resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.15.3.tgz#d2509048d69dbb72d5389a14945339f1430b2d3c" - integrity sha512-Oy8rmScVrVxWZVOpEF57ovlnhpZ8CCPlnIIumVcV9nFdiSIrus99+Lw78ekXyGvVDlIsFJbSfmSovJUhCWYV3w== +"@remix-run/router@1.16.1": + version "1.16.1" + resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.16.1.tgz#73db3c48b975eeb06d0006481bde4f5f2d17d1cd" + integrity sha512-es2g3dq6Nb07iFxGk5GuHN20RwBZOsuDQN7izWIisUcv9r+d2C5jQxqmgkdebXgReWfiyUabcki6Fg77mSNrig== "@rollup/plugin-babel@^5.2.0": version "5.3.1" @@ -3883,141 +4195,141 @@ p-map "^4.0.0" webpack-sources "^3.2.2" -"@storybook/addon-actions@7.6.17", "@storybook/addon-actions@^7.6.10": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-7.6.17.tgz#b1be5ab28b22b4a50c6aa0cd0a3671ca5b6f5f71" - integrity sha512-TBphs4v6LRfyTpFo/WINF0TkMaE3rrNog7wW5mbz6n0j8o53kDN4o9ZEcygSL5zQX43CAaghQTeDCss7ueG7ZQ== +"@storybook/addon-actions@7.6.19", "@storybook/addon-actions@^7.6.10": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-7.6.19.tgz#f131faf51c2baf036aa0fff33d77a1fa74e22ad0" + integrity sha512-ATLrA5QKFJt7tIAScRHz5T3eBQ+RG3jaZk08L7gChvyQZhei8knWwePElZ7GaWbCr9BgznQp1lQUUXq/UUblAQ== dependencies: - "@storybook/core-events" "7.6.17" + "@storybook/core-events" "7.6.19" "@storybook/global" "^5.0.0" "@types/uuid" "^9.0.1" dequal "^2.0.2" polished "^4.2.2" uuid "^9.0.0" -"@storybook/addon-backgrounds@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/addon-backgrounds/-/addon-backgrounds-7.6.17.tgz#a3c96cb73e6053dc2cf9968cb02b437c4d752812" - integrity sha512-7dize7x8+37PH77kmt69b0xSaeDqOcZ4fpzW6+hk53hIaCVU26eGs4+j+743Xva31eOgZWNLupUhOpUDc6SqZw== +"@storybook/addon-backgrounds@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/addon-backgrounds/-/addon-backgrounds-7.6.19.tgz#cd4cf6a6415c32a0e813573553efa592400c6c2f" + integrity sha512-Nu3LAZODRSV2e5bOroKm/Jp6BIFzwu/nJxD5OvLWkkwNCh+vDXUFbbaVrZf5xRL+fHd9iLFPtWbJQpF/w7UsCw== dependencies: "@storybook/global" "^5.0.0" memoizerific "^1.11.3" ts-dedent "^2.0.0" -"@storybook/addon-controls@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/addon-controls/-/addon-controls-7.6.17.tgz#354f3f85481e0a3318519b8c8aa5a3b1152e8de0" - integrity sha512-zR0aLaUF7FtV/nMRyfniFbCls/e0DAAoXACuOAUAwNAv0lbIS8AyZZiHSmKucCvziUQ6WceeCC7+du3C+9y0rQ== +"@storybook/addon-controls@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/addon-controls/-/addon-controls-7.6.19.tgz#86c0433b3d5e2e74f6ca3e58e492730d27f0220f" + integrity sha512-cl6PCNEwihDjuWIUsKTyDNKk+/IE4J3oMbSY5AZV/9Z0jJbpMV2shVm5DMZm5LhCCVcu5obWcxCIa4FMIMJAMQ== dependencies: - "@storybook/blocks" "7.6.17" + "@storybook/blocks" "7.6.19" lodash "^4.17.21" ts-dedent "^2.0.0" -"@storybook/addon-docs@7.6.17", "@storybook/addon-docs@^7.6.10": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/addon-docs/-/addon-docs-7.6.17.tgz#ea62be2da8b31df2c80a47cac4c30f66af4d2fbf" - integrity sha512-FKa4Mdy7nhgvEVZJHpMkHriDzpVHbohn87zv9NCL+Ctjs1iAmzGwxEm0culszyDS1HN2ToVoY0h8CSi2RSSZqA== +"@storybook/addon-docs@7.6.19", "@storybook/addon-docs@^7.6.10": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/addon-docs/-/addon-docs-7.6.19.tgz#4f0866072a5105e667ed75bd388584bb46206884" + integrity sha512-nv+9SR/NOtM8Od2esOXHcg0NQT8Pk8BMUyGwZu5Q3MLI4JxNVEG65dY0IP2j6Knc4UtlvQTpM0f7m5xp4seHjQ== dependencies: "@jest/transform" "^29.3.1" "@mdx-js/react" "^2.1.5" - "@storybook/blocks" "7.6.17" - "@storybook/client-logger" "7.6.17" - "@storybook/components" "7.6.17" - "@storybook/csf-plugin" "7.6.17" - "@storybook/csf-tools" "7.6.17" + "@storybook/blocks" "7.6.19" + "@storybook/client-logger" "7.6.19" + "@storybook/components" "7.6.19" + "@storybook/csf-plugin" "7.6.19" + "@storybook/csf-tools" "7.6.19" "@storybook/global" "^5.0.0" "@storybook/mdx2-csf" "^1.0.0" - "@storybook/node-logger" "7.6.17" - "@storybook/postinstall" "7.6.17" - "@storybook/preview-api" "7.6.17" - "@storybook/react-dom-shim" "7.6.17" - "@storybook/theming" "7.6.17" - "@storybook/types" "7.6.17" + "@storybook/node-logger" "7.6.19" + "@storybook/postinstall" "7.6.19" + "@storybook/preview-api" "7.6.19" + "@storybook/react-dom-shim" "7.6.19" + "@storybook/theming" "7.6.19" + "@storybook/types" "7.6.19" fs-extra "^11.1.0" remark-external-links "^8.0.0" remark-slug "^6.0.0" ts-dedent "^2.0.0" "@storybook/addon-essentials@^7.6.10": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/addon-essentials/-/addon-essentials-7.6.17.tgz#d49d9a77edc999518c6871b66032a647787c39f4" - integrity sha512-qlSpamxuYfT2taF953nC9QijGF2pSbg1ewMNpdwLTj16PTZvR/d8NCDMTJujI1bDwM2m18u8Yc43ibh5LEmxCw== - dependencies: - "@storybook/addon-actions" "7.6.17" - "@storybook/addon-backgrounds" "7.6.17" - "@storybook/addon-controls" "7.6.17" - "@storybook/addon-docs" "7.6.17" - "@storybook/addon-highlight" "7.6.17" - "@storybook/addon-measure" "7.6.17" - "@storybook/addon-outline" "7.6.17" - "@storybook/addon-toolbars" "7.6.17" - "@storybook/addon-viewport" "7.6.17" - "@storybook/core-common" "7.6.17" - "@storybook/manager-api" "7.6.17" - "@storybook/node-logger" "7.6.17" - "@storybook/preview-api" "7.6.17" + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/addon-essentials/-/addon-essentials-7.6.19.tgz#1f2a7af9388e1f50b3cfd2fd9ee5fd763a1ac35a" + integrity sha512-SC33ZEQ5YaOt9wDkrdZmwQgqPWo9om/gqnyif06eug3SwrTe9JjO5iq1PIBfQodLD9MAxr9cwBvO0NG505oszQ== + dependencies: + "@storybook/addon-actions" "7.6.19" + "@storybook/addon-backgrounds" "7.6.19" + "@storybook/addon-controls" "7.6.19" + "@storybook/addon-docs" "7.6.19" + "@storybook/addon-highlight" "7.6.19" + "@storybook/addon-measure" "7.6.19" + "@storybook/addon-outline" "7.6.19" + "@storybook/addon-toolbars" "7.6.19" + "@storybook/addon-viewport" "7.6.19" + "@storybook/core-common" "7.6.19" + "@storybook/manager-api" "7.6.19" + "@storybook/node-logger" "7.6.19" + "@storybook/preview-api" "7.6.19" ts-dedent "^2.0.0" -"@storybook/addon-highlight@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/addon-highlight/-/addon-highlight-7.6.17.tgz#6d8549aa95eb007888f4d272e9ab7316cbcc001c" - integrity sha512-R1yBPUUqGn+60aJakn8q+5Zt34E/gU3n3VmgPdryP0LJUdZ5q1/RZShoVDV+yYQ40htMH6oaCv3OyyPzFAGJ6A== +"@storybook/addon-highlight@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/addon-highlight/-/addon-highlight-7.6.19.tgz#7e88fe924e822426ef54c33ad1522a9676ef57aa" + integrity sha512-/pApl0oiVU1CQ8xETRNDLDthMBjeTmvFnTRq8RJ9m0JYTrSsoyHDmj9zS4K1k9gReqijE7brslhP8d2tblBpNw== dependencies: "@storybook/global" "^5.0.0" "@storybook/addon-links@^7.6.10": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/addon-links/-/addon-links-7.6.17.tgz#5a678ff09c1b5056b67cb345c115cfcd343ffe86" - integrity sha512-iFUwKObRn0EKI0zMETsil2p9a/81rCuSMEWECsi+khkCAs1FUnD2cT6Ag5ydcNcBXsdtdfDJdtXQrkw+TSoStQ== + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/addon-links/-/addon-links-7.6.19.tgz#7b48683533ada47268a60393fb1930415e67113f" + integrity sha512-qMIFfcsMf4olxhYUHUV2ZJhxphh6Xpf1DMd0lxKqAibfxl/sX1m0rJkyiqWSBxbCmAy/pwdgqEOJ1lpDUsJ33w== dependencies: "@storybook/csf" "^0.1.2" "@storybook/global" "^5.0.0" ts-dedent "^2.0.0" -"@storybook/addon-measure@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/addon-measure/-/addon-measure-7.6.17.tgz#a348b40dfa592c66b348457bd4f535f4ba481279" - integrity sha512-O5vnHZNkduvZ95jf1UssbOl6ivIxzl5tv+4EpScPYId7w700bxWsJH+QX7ip6KlrCf2o3iUhmPe8bm05ghG2KA== +"@storybook/addon-measure@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/addon-measure/-/addon-measure-7.6.19.tgz#4f12580eff40038a8d514be1059b2d063e5d0ed4" + integrity sha512-n+cfhVXXouBv9oQr3a77vvip5dTznaNoBDWMafP2ohauc8jBlAxeBwCjk5r3pyThMRIFCTG/ypZrhiJcSJT3bw== dependencies: "@storybook/global" "^5.0.0" tiny-invariant "^1.3.1" -"@storybook/addon-outline@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/addon-outline/-/addon-outline-7.6.17.tgz#f87c7bea4ecba783c79a3026f8fc7e0acc26c460" - integrity sha512-9o9JXDsYjNaDgz/cY5+jv694+aik/1aiRGGvsCv68e1p/ob0glkGKav4lnJe2VJqD+gCmaARoD8GOJlhoQl8JQ== +"@storybook/addon-outline@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/addon-outline/-/addon-outline-7.6.19.tgz#519cdba12d3f27f1282897d2abe8762a5640b45f" + integrity sha512-Tt4MrfjK5j/Mdh8nJ8ccVyh78Dy7aiEPxO31YVvr5XUkge0pDi1PX328mHRDPur0i56NM8ssVbekWBZr+9MxlA== dependencies: "@storybook/global" "^5.0.0" ts-dedent "^2.0.0" -"@storybook/addon-toolbars@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/addon-toolbars/-/addon-toolbars-7.6.17.tgz#98c1cee88a8f5f61464d28a09648994884d7bd0a" - integrity sha512-UMrchbUHiyWrh6WuGnpy34Jqzkx/63B+MSgb3CW7YsQaXz64kE0Rol0TNSznnB+mYXplcqH+ndI4r4kFsmgwDg== +"@storybook/addon-toolbars@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/addon-toolbars/-/addon-toolbars-7.6.19.tgz#4800d5d8679334b4a3353bb7e4933af5a6545d4b" + integrity sha512-+qGbPP2Vo/HoPiS4EJopZ127HGculCV74Hkz6ot7ob6AkYdA1yLMPzWns/ZXNIWm6ab3jV+iq+mQCM/i1qJzvA== -"@storybook/addon-viewport@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/addon-viewport/-/addon-viewport-7.6.17.tgz#db3c1f14bb4185f20d745c4e8cf2bd10f70ea336" - integrity sha512-sA0QCcf4QAMixWvn8uvRYPfkKCSl6JajJaAspoPqXSxHEpK7uwOlpg3kqFU5XJJPXD0X957M+ONgNvBzYqSpEw== +"@storybook/addon-viewport@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/addon-viewport/-/addon-viewport-7.6.19.tgz#602aa2c0431f4b8119f9cf4e668eb3155ad5bcb7" + integrity sha512-OQQtJ2kYwImbvE9QiC3I3yR0O0EBgNjq+XSaSS4ixJrvUyesfuB7Lm7RkubhEEiP4yANi9OlbzsqZelmPOnk6w== dependencies: memoizerific "^1.11.3" -"@storybook/blocks@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/blocks/-/blocks-7.6.17.tgz#1329885be158f08104f806e5f23b7eb7f99c8b1c" - integrity sha512-PsNVoe0bX1mMn4Kk3nbKZ0ItDZZ0YJnYAFJ6toAbsyBAbgzg1sce88sQinzvbn58/RT9MPKeWMPB45ZS7ggiNg== +"@storybook/blocks@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/blocks/-/blocks-7.6.19.tgz#11bd3126245be33df091b48df9f25c1c07920825" + integrity sha512-/c/bVQRmyRPoviJhPrFdLfubRcrnZWTwkjxsCvrOTJ/UDOyEl0t/H8yY1mGq7KWWTdbIznnZWhAIofHnH4/Esw== dependencies: - "@storybook/channels" "7.6.17" - "@storybook/client-logger" "7.6.17" - "@storybook/components" "7.6.17" - "@storybook/core-events" "7.6.17" + "@storybook/channels" "7.6.19" + "@storybook/client-logger" "7.6.19" + "@storybook/components" "7.6.19" + "@storybook/core-events" "7.6.19" "@storybook/csf" "^0.1.2" - "@storybook/docs-tools" "7.6.17" + "@storybook/docs-tools" "7.6.19" "@storybook/global" "^5.0.0" - "@storybook/manager-api" "7.6.17" - "@storybook/preview-api" "7.6.17" - "@storybook/theming" "7.6.17" - "@storybook/types" "7.6.17" + "@storybook/manager-api" "7.6.19" + "@storybook/preview-api" "7.6.19" + "@storybook/theming" "7.6.19" + "@storybook/types" "7.6.19" "@types/lodash" "^4.14.167" color-convert "^2.0.1" dequal "^2.0.2" @@ -4031,15 +4343,15 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/builder-manager@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/builder-manager/-/builder-manager-7.6.17.tgz#0d329bea94b5c4a7f88eaee02c42d49c4370c8b4" - integrity sha512-Sj8hcDYiPCCMfeLzus37czl0zdrAxAz4IyYam2jBjVymrIrcDAFyL1OCZvnq33ft179QYQWhUs9qwzVmlR/ZWg== +"@storybook/builder-manager@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/builder-manager/-/builder-manager-7.6.19.tgz#1356fab233181a06c8cea9094b53c84aac218bae" + integrity sha512-Dt5OLh97xeWh4h2mk9uG0SbCxBKHPhIiHLHAKEIDzIZBdwUhuyncVNDPHW2NlXM+S7U0/iKs2tw05waqh2lHvg== dependencies: "@fal-works/esbuild-plugin-global-externals" "^2.1.2" - "@storybook/core-common" "7.6.17" - "@storybook/manager" "7.6.17" - "@storybook/node-logger" "7.6.17" + "@storybook/core-common" "7.6.19" + "@storybook/manager" "7.6.19" + "@storybook/node-logger" "7.6.19" "@types/ejs" "^3.1.1" "@types/find-cache-dir" "^3.2.1" "@yarnpkg/esbuild-plugin-pnp" "^3.0.0-rc.10" @@ -4053,20 +4365,20 @@ process "^0.11.10" util "^0.12.4" -"@storybook/builder-webpack5@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/builder-webpack5/-/builder-webpack5-7.6.17.tgz#1bf52b4cf62c66cbfe95e189fa4303a542bb645a" - integrity sha512-GMaBd8/RzivuAmWrYSt9Rga3j8WLcu5LCMYiPVs+XKXsKAC8lTkV0WRWh8Nk6wTmfzsRQ2acwFjSG5oE4ClZKA== +"@storybook/builder-webpack5@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/builder-webpack5/-/builder-webpack5-7.6.19.tgz#1e2ff6328ead8d1fa0fef6aa552ee8c6d1d434ee" + integrity sha512-PeP66orYG0tWoWeOGNcCDKtk/kpDBFfosViCkd0Pxb6c2MtvjOuHSGWGB/9AI3hjodsoe5p9xo/SqGf7lDzpoA== dependencies: "@babel/core" "^7.23.2" - "@storybook/channels" "7.6.17" - "@storybook/client-logger" "7.6.17" - "@storybook/core-common" "7.6.17" - "@storybook/core-events" "7.6.17" - "@storybook/core-webpack" "7.6.17" - "@storybook/node-logger" "7.6.17" - "@storybook/preview" "7.6.17" - "@storybook/preview-api" "7.6.17" + "@storybook/channels" "7.6.19" + "@storybook/client-logger" "7.6.19" + "@storybook/core-common" "7.6.19" + "@storybook/core-events" "7.6.19" + "@storybook/core-webpack" "7.6.19" + "@storybook/node-logger" "7.6.19" + "@storybook/preview" "7.6.19" + "@storybook/preview-api" "7.6.19" "@swc/core" "^1.3.82" "@types/node" "^18.0.0" "@types/semver" "^7.3.4" @@ -4097,35 +4409,35 @@ webpack-hot-middleware "^2.25.1" webpack-virtual-modules "^0.5.0" -"@storybook/channels@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-7.6.17.tgz#5be1d1222a3ffdc90e1868230c2b2ee5dfc7a97f" - integrity sha512-GFG40pzaSxk1hUr/J/TMqW5AFDDPUSu+HkeE/oqSWJbOodBOLJzHN6CReJS6y1DjYSZLNFt1jftPWZZInG/XUA== +"@storybook/channels@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-7.6.19.tgz#730fa74f7800e2069707f8a880996ca6fc8957ab" + integrity sha512-2JGh+i95GwjtjqWqhtEh15jM5ifwbRGmXeFqkY7dpdHH50EEWafYHr2mg3opK3heVDwg0rJ/VBptkmshloXuvA== dependencies: - "@storybook/client-logger" "7.6.17" - "@storybook/core-events" "7.6.17" + "@storybook/client-logger" "7.6.19" + "@storybook/core-events" "7.6.19" "@storybook/global" "^5.0.0" qs "^6.10.0" telejson "^7.2.0" tiny-invariant "^1.3.1" -"@storybook/cli@7.6.17", "@storybook/cli@^7.6.10": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/cli/-/cli-7.6.17.tgz#04462c97a926e3dfcc18f3df02519effe29740e2" - integrity sha512-1sCo+nCqyR+nKfTcEidVu8XzNoECC7Y1l+uW38/r7s2f/TdDorXaIGAVrpjbSaXSoQpx5DxYJVaKCcQuOgqwcA== +"@storybook/cli@7.6.19", "@storybook/cli@^7.6.10": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/cli/-/cli-7.6.19.tgz#b4f36ccd51e02ceadb92c3e2341f82ee1bbd6598" + integrity sha512-7OVy7nPgkLfgivv6/dmvoyU6pKl9EzWFk+g9izyQHiM/jS8jOiEyn6akG8Ebj6k5pWslo5lgiXUSW+cEEZUnqQ== dependencies: "@babel/core" "^7.23.2" "@babel/preset-env" "^7.23.2" "@babel/types" "^7.23.0" "@ndelangen/get-tarball" "^3.0.7" - "@storybook/codemod" "7.6.17" - "@storybook/core-common" "7.6.17" - "@storybook/core-events" "7.6.17" - "@storybook/core-server" "7.6.17" - "@storybook/csf-tools" "7.6.17" - "@storybook/node-logger" "7.6.17" - "@storybook/telemetry" "7.6.17" - "@storybook/types" "7.6.17" + "@storybook/codemod" "7.6.19" + "@storybook/core-common" "7.6.19" + "@storybook/core-events" "7.6.19" + "@storybook/core-server" "7.6.19" + "@storybook/csf-tools" "7.6.19" + "@storybook/node-logger" "7.6.19" + "@storybook/telemetry" "7.6.19" + "@storybook/types" "7.6.19" "@types/semver" "^7.3.4" "@yarnpkg/fslib" "2.10.3" "@yarnpkg/libzip" "2.3.0" @@ -4155,25 +4467,25 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/client-logger@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-7.6.17.tgz#5031c47b7df8d8792fe9dfed5828222f515e5803" - integrity sha512-6WBYqixAXNAXlSaBWwgljWpAu10tPRBJrcFvx2gPUne58EeMM20Gi/iHYBz2kMCY+JLAgeIH7ZxInqwO8vDwiQ== +"@storybook/client-logger@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-7.6.19.tgz#a6f91af8cdc640ace9903674b6340ad8173238cc" + integrity sha512-oGzOxbmLmciSIfd5gsxDzPmX8DttWhoYdPKxjMuCuWLTO2TWpkCWp1FTUMWO72mm/6V/FswT/aqpJJBBvdZ3RQ== dependencies: "@storybook/global" "^5.0.0" -"@storybook/codemod@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/codemod/-/codemod-7.6.17.tgz#c93d87d74f43fd475d48edb178233e89329b72c2" - integrity sha512-JuTmf2u3C4fCnjO7o3dqRgrq3ozNYfWlrRP8xuIdvT7niMap7a396hJtSKqS10FxCgKFcMAOsRgrCalH1dWxUg== +"@storybook/codemod@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/codemod/-/codemod-7.6.19.tgz#ac6690a5ef18903cdb132a005b3c520f96ae92f8" + integrity sha512-bmHE0iEEgWZ65dXCmasd+GreChjPiWkXu2FEa0cJmNz/PqY12GsXGls4ke1TkNTj4gdSZnbtJxbclPZZnib2tQ== dependencies: "@babel/core" "^7.23.2" "@babel/preset-env" "^7.23.2" "@babel/types" "^7.23.0" "@storybook/csf" "^0.1.2" - "@storybook/csf-tools" "7.6.17" - "@storybook/node-logger" "7.6.17" - "@storybook/types" "7.6.17" + "@storybook/csf-tools" "7.6.19" + "@storybook/node-logger" "7.6.19" + "@storybook/types" "7.6.19" "@types/cross-spawn" "^6.0.2" cross-spawn "^7.0.3" globby "^11.0.2" @@ -4182,38 +4494,38 @@ prettier "^2.8.0" recast "^0.23.1" -"@storybook/components@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/components/-/components-7.6.17.tgz#f02a47ad42432f8ea518321a145a074e4c11649f" - integrity sha512-lbh7GynMidA+CZcJnstVku6Nhs+YkqjYaZ+mKPugvlVhGVWv0DaaeQFVuZ8cJtUGJ/5FFU4Y+n+gylYUHkGBMA== +"@storybook/components@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/components/-/components-7.6.19.tgz#c9e36100faef6310455daf5bf915a21447c332d1" + integrity sha512-8Zw/RQ4crzKkUR7ojxvRIj8vktKiBBO8Nq93qv4JfDqDWrcR7cro0hOlZgmZmrzbFunBBt6WlsNNO6nVP7R4Xw== dependencies: "@radix-ui/react-select" "^1.2.2" "@radix-ui/react-toolbar" "^1.0.4" - "@storybook/client-logger" "7.6.17" + "@storybook/client-logger" "7.6.19" "@storybook/csf" "^0.1.2" "@storybook/global" "^5.0.0" - "@storybook/theming" "7.6.17" - "@storybook/types" "7.6.17" + "@storybook/theming" "7.6.19" + "@storybook/types" "7.6.19" memoizerific "^1.11.3" use-resize-observer "^9.1.0" util-deprecate "^1.0.2" -"@storybook/core-client@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/core-client/-/core-client-7.6.17.tgz#eace9819b64febf0d5ab2743f65ec5dfe4e3a410" - integrity sha512-LuDbADK+DPNAOOCXOlvY09hdGVueXlDetsdOJ/DgYnSa9QSWv9Uv+F8QcEgR3QckZJbPlztKJIVLgP2n/Xkijw== +"@storybook/core-client@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/core-client/-/core-client-7.6.19.tgz#ca47b71bfebb0e1e5cb112b5b88e9f7b0c88eee4" + integrity sha512-F0V9nzcEnj6DIpnw2ilrxsV4d9ibyyQS+Wi2uQtXy+wCQQm9PeBVqrOywjXAY2F9pcoftXOaepfhp8jrxX4MXw== dependencies: - "@storybook/client-logger" "7.6.17" - "@storybook/preview-api" "7.6.17" + "@storybook/client-logger" "7.6.19" + "@storybook/preview-api" "7.6.19" -"@storybook/core-common@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/core-common/-/core-common-7.6.17.tgz#12760703f08d8f741de0f1fe7026346438251951" - integrity sha512-me2TP3Q9/qzqCLoDHUSsUF+VS1MHxfHbTVF6vAz0D/COTxzsxLpu9TxTbzJoBCxse6XRb6wWI1RgF1mIcjic7g== +"@storybook/core-common@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/core-common/-/core-common-7.6.19.tgz#fdbfc3c5b24d12e74ef9d1f0e15cd4b1ee2cd02c" + integrity sha512-njwpGzFJrfbJr/AFxGP8KMrfPfxN85KOfSlxYnQwRm5Z0H1D/lT33LhEBf5m37gaGawHeG7KryxO6RvaioMt2Q== dependencies: - "@storybook/core-events" "7.6.17" - "@storybook/node-logger" "7.6.17" - "@storybook/types" "7.6.17" + "@storybook/core-events" "7.6.19" + "@storybook/node-logger" "7.6.19" + "@storybook/types" "7.6.19" "@types/find-cache-dir" "^3.2.1" "@types/node" "^18.0.0" "@types/node-fetch" "^2.6.4" @@ -4235,33 +4547,33 @@ resolve-from "^5.0.0" ts-dedent "^2.0.0" -"@storybook/core-events@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-7.6.17.tgz#9e1a795558193089fb227cfe2cf768c99418a640" - integrity sha512-AriWMCm/k1cxlv10f+jZ1wavThTRpLaN3kY019kHWbYT9XgaSuLU67G7GPr3cGnJ6HuA6uhbzu8qtqVCd6OfXA== +"@storybook/core-events@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-7.6.19.tgz#cfa7d4581ad6cff1ee7eeade31d602a7d879d2b7" + integrity sha512-K/W6Uvum0ocZSgjbi8hiotpe+wDEHDZlvN+KlPqdh9ae9xDK8aBNBq9IelCoqM+uKO1Zj+dDfSQds7CD781DJg== dependencies: ts-dedent "^2.0.0" -"@storybook/core-server@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/core-server/-/core-server-7.6.17.tgz#bf5b7a9db7abe157a14dba6279936e43efa79250" - integrity sha512-KWGhTTaL1Q14FolcoKKZgytlPJUbH6sbJ1Ptj/84EYWFewcnEgVs0Zlnh1VStRZg+Rd1WC1V4yVd/bbDzxrvQA== +"@storybook/core-server@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/core-server/-/core-server-7.6.19.tgz#07f4f0d4b05dd7dc52e9c60be97df7b5cb3150a9" + integrity sha512-7mKL73Wv5R2bEl0kJ6QJ9bOu5YY53Idu24QgvTnUdNsQazp2yUONBNwHIrNDnNEXm8SfCi4Mc9o0mmNRMIoiRA== dependencies: "@aw-web-design/x-default-browser" "1.4.126" "@discoveryjs/json-ext" "^0.5.3" - "@storybook/builder-manager" "7.6.17" - "@storybook/channels" "7.6.17" - "@storybook/core-common" "7.6.17" - "@storybook/core-events" "7.6.17" + "@storybook/builder-manager" "7.6.19" + "@storybook/channels" "7.6.19" + "@storybook/core-common" "7.6.19" + "@storybook/core-events" "7.6.19" "@storybook/csf" "^0.1.2" - "@storybook/csf-tools" "7.6.17" + "@storybook/csf-tools" "7.6.19" "@storybook/docs-mdx" "^0.1.0" "@storybook/global" "^5.0.0" - "@storybook/manager" "7.6.17" - "@storybook/node-logger" "7.6.17" - "@storybook/preview-api" "7.6.17" - "@storybook/telemetry" "7.6.17" - "@storybook/types" "7.6.17" + "@storybook/manager" "7.6.19" + "@storybook/node-logger" "7.6.19" + "@storybook/preview-api" "7.6.19" + "@storybook/telemetry" "7.6.19" + "@storybook/types" "7.6.19" "@types/detect-port" "^1.3.0" "@types/node" "^18.0.0" "@types/pretty-hrtime" "^1.0.0" @@ -4289,44 +4601,44 @@ watchpack "^2.2.0" ws "^8.2.3" -"@storybook/core-webpack@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/core-webpack/-/core-webpack-7.6.17.tgz#0cca6bd165d4cea0e53856520c6409127869f6b7" - integrity sha512-PyGrFhRM8sTONGwwLWLqBQ1HO+LBnVZ+5TOQO7ejQfdV2FWyNOzjBXm2e5jL/C6XlqiEhmL5pyHEyDBaQJQ3KA== +"@storybook/core-webpack@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/core-webpack/-/core-webpack-7.6.19.tgz#bf1bdcc6899c21c8a3c7702737dd5e1847380dbb" + integrity sha512-Ezvn54hFN99qwP8kDOQa7/IEk2V3NyJys2eg0Afqz1cy9Uc3SkL7U7hQorKOHr5+66dsryNDfJdPzM1YMKFMBQ== dependencies: - "@storybook/core-common" "7.6.17" - "@storybook/node-logger" "7.6.17" - "@storybook/types" "7.6.17" + "@storybook/core-common" "7.6.19" + "@storybook/node-logger" "7.6.19" + "@storybook/types" "7.6.19" "@types/node" "^18.0.0" ts-dedent "^2.0.0" -"@storybook/csf-plugin@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/csf-plugin/-/csf-plugin-7.6.17.tgz#6acf738b62e14a74a90ef68d7567e2fc1d1bd68f" - integrity sha512-xTHv9BUh3bkDVCvcbmdfVF0/e96BdrEgqPJ3G3RmKbSzWLOkQ2U9yiPfHzT0KJWPhVwj12fjfZp0zunu+pcS6Q== +"@storybook/csf-plugin@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/csf-plugin/-/csf-plugin-7.6.19.tgz#5c88767f6b4f47826c9fc7fdf028132ff243239b" + integrity sha512-yUP0xfJyR8e6fmCgKoEt4c1EvslF8dZ8wtwVLE5hnC3kfs7xt8RVDiKLB/9NhYjY3mD/oOesX60HqRXDgJQHwA== dependencies: - "@storybook/csf-tools" "7.6.17" + "@storybook/csf-tools" "7.6.19" unplugin "^1.3.1" -"@storybook/csf-tools@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/csf-tools/-/csf-tools-7.6.17.tgz#366bb2348fc1a62f90cdbd6cce4aa5e7293984eb" - integrity sha512-dAQtam0EBPeTJYcQPLxXgz4L9JFqD+HWbLFG9CmNIhMMjticrB0mpk1EFIS6vPXk/VsVWpBgMLD7dZlD6YMKcQ== +"@storybook/csf-tools@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/csf-tools/-/csf-tools-7.6.19.tgz#5925f313b8ac4ebdd1c0b9d71279e18bbaab269a" + integrity sha512-8Vzia3cHhDdGHuS3XKXJReCRxmfRq3vmTm/Te9yKZnPSAsC58CCKcMh8FNEFJ44vxYF9itKTkRutjGs+DprKLQ== dependencies: "@babel/generator" "^7.23.0" "@babel/parser" "^7.23.0" "@babel/traverse" "^7.23.2" "@babel/types" "^7.23.0" "@storybook/csf" "^0.1.2" - "@storybook/types" "7.6.17" + "@storybook/types" "7.6.19" fs-extra "^11.1.0" recast "^0.23.1" ts-dedent "^2.0.0" "@storybook/csf@^0.1.2": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@storybook/csf/-/csf-0.1.3.tgz#79047a4dece94ba7c8e78003723e9bd9e071379a" - integrity sha512-IPZvXXo4b3G+gpmgBSBqVM81jbp2ePOKsvhgJdhyZJtkYQCII7rg9KKLQhvBQM5sLaF1eU6r0iuwmyynC9d9SA== + version "0.1.8" + resolved "https://registry.yarnpkg.com/@storybook/csf/-/csf-0.1.8.tgz#63a83dc493c462d84e0f333e3f3264d319bec716" + integrity sha512-Ntab9o7LjBCbFIao5l42itFiaSh/Qu+l16l/r/9qmV9LnYZkO+JQ7tzhdlwpgJfhs+B5xeejpdAtftDRyXNajw== dependencies: type-fest "^2.19.0" @@ -4335,14 +4647,14 @@ resolved "https://registry.yarnpkg.com/@storybook/docs-mdx/-/docs-mdx-0.1.0.tgz#33ba0e39d1461caf048b57db354b2cc410705316" integrity sha512-JDaBR9lwVY4eSH5W8EGHrhODjygPd6QImRbwjAuJNEnY0Vw4ie3bPkeGfnacB3OBW6u/agqPv2aRlR46JcAQLg== -"@storybook/docs-tools@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/docs-tools/-/docs-tools-7.6.17.tgz#4c38025be46c991bfe994bd82996708210e51d2f" - integrity sha512-bYrLoj06adqklyLkEwD32C0Ww6t+9ZVvrJHiVT42bIhTRpFiFPAetl1a9KPHtFLnfduh4n2IxIr1jv32ThPDTA== +"@storybook/docs-tools@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/docs-tools/-/docs-tools-7.6.19.tgz#d63b68af1d425f4b94a3a229af611bbaf822f4b4" + integrity sha512-JuwV6wtm7Hb7Kb5ValChfxy4J7XngfrSQNpvwsDCSBNVcQUv2y843hvclpa26Ptfr/c7zpUX8r9FGSaMDy+2aQ== dependencies: - "@storybook/core-common" "7.6.17" - "@storybook/preview-api" "7.6.17" - "@storybook/types" "7.6.17" + "@storybook/core-common" "7.6.19" + "@storybook/preview-api" "7.6.19" + "@storybook/types" "7.6.19" "@types/doctrine" "^0.0.3" assert "^2.1.0" doctrine "^3.0.0" @@ -4353,19 +4665,19 @@ resolved "https://registry.yarnpkg.com/@storybook/global/-/global-5.0.0.tgz#b793d34b94f572c1d7d9e0f44fac4e0dbc9572ed" integrity sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ== -"@storybook/manager-api@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/manager-api/-/manager-api-7.6.17.tgz#cdf0bb8e5bdc3da2559150125b3d6a3ff72f0def" - integrity sha512-IJIV1Yc6yw1dhCY4tReHCfBnUKDqEBnMyHp3mbXpsaHxnxJZrXO45WjRAZIKlQKhl/Ge1CrnznmHRCmYgqmrWg== +"@storybook/manager-api@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/manager-api/-/manager-api-7.6.19.tgz#d08787dabe4143cf34d5805a023499889d572032" + integrity sha512-dVCx1Q+HZEA4U08XqYljiG88BeS3I3ahnPAQLZAeWQXQRkoc9G2jMgLNPKYPIqEtq7Xrn6SRlFMIofhwWrwZpg== dependencies: - "@storybook/channels" "7.6.17" - "@storybook/client-logger" "7.6.17" - "@storybook/core-events" "7.6.17" + "@storybook/channels" "7.6.19" + "@storybook/client-logger" "7.6.19" + "@storybook/core-events" "7.6.19" "@storybook/csf" "^0.1.2" "@storybook/global" "^5.0.0" - "@storybook/router" "7.6.17" - "@storybook/theming" "7.6.17" - "@storybook/types" "7.6.17" + "@storybook/router" "7.6.19" + "@storybook/theming" "7.6.19" + "@storybook/types" "7.6.19" dequal "^2.0.2" lodash "^4.17.21" memoizerific "^1.11.3" @@ -4373,38 +4685,38 @@ telejson "^7.2.0" ts-dedent "^2.0.0" -"@storybook/manager@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/manager/-/manager-7.6.17.tgz#56e820ede16f6b824ec6b016082d1d10dbb02759" - integrity sha512-A1LDDIqMpwRzq/dqkbbiza0QI04o4ZHCl2a3UMDZUV/+QLc2nsr2DAaLk4CVL4/cIc5zGqmIcaOTvprx2YKVBw== +"@storybook/manager@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/manager/-/manager-7.6.19.tgz#d7ee419e48feed79c1d9f0f469efa7742a2ef3d2" + integrity sha512-fZWQcf59x4P0iiBhrL74PZrqKJAPuk9sWjP8BIkGbf8wTZtUunbY5Sv4225fOL4NLJbuX9/RYLUPoxQ3nucGHA== "@storybook/mdx2-csf@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@storybook/mdx2-csf/-/mdx2-csf-1.1.0.tgz#97f6df04d0bf616991cc1005a073ac004a7281e5" integrity sha512-TXJJd5RAKakWx4BtpwvSNdgTDkKM6RkXU8GK34S/LhidQ5Pjz3wcnqb0TxEkfhK/ztbP8nKHqXFwLfa2CYkvQw== -"@storybook/node-logger@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-7.6.17.tgz#2747cee5395c3644408df2423d98502663c4bcf6" - integrity sha512-w59MQuXhhUNrUVmVkXhMwIg2nvFWjdDczLTwYLorhfsE36CWeUOY5QCZWQy0Qf/h+jz8Uo7Evy64qn18v9C4wA== +"@storybook/node-logger@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-7.6.19.tgz#8a911288ee8052cf2c77cf5e2db2367b1b852b43" + integrity sha512-2g29QC44Zl1jKY37DmQ0/dO7+VSKnGgPI/x0mwVwQffypSapxH3rwLLT5Q5XLHeFyD+fhRu5w9Cj4vTGynJgpA== -"@storybook/postinstall@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/postinstall/-/postinstall-7.6.17.tgz#7218b416dfa6d36b5bdbd3e61afc9a2381f82c28" - integrity sha512-WaWqB8o9vUc9aaVls+povQSVirf1Xd1LZcVhUKfAocAF3mzYUsnJsVqvnbjRj/F96UFVihOyDt9Zjl/9OvrCvQ== +"@storybook/postinstall@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/postinstall/-/postinstall-7.6.19.tgz#8f75f43ea786a26a8677dedbedc5e8f947c56456" + integrity sha512-s6p1vpgMfn+QGDfCK2YNdyyWKidUgb3nGicB81FANRyzYqGB//QlJlghEc2LKCIQbGIZQiwP3l8PdZQmczEJRw== -"@storybook/preset-react-webpack@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/preset-react-webpack/-/preset-react-webpack-7.6.17.tgz#af112cef0fb93ebfb22363b8a7eec6be7128fde6" - integrity sha512-gn/LvIbll9loOkzwbFlxzOZGmJ6t1vF2/gfi+p/N/AifDYe8+LVM1QV4KRVKt6UEJwsQd79lKf7vPH92AQaKKQ== +"@storybook/preset-react-webpack@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/preset-react-webpack/-/preset-react-webpack-7.6.19.tgz#c79e1e3727175012fe6f2ac92a58c19426a4dd3f" + integrity sha512-WvfDE4upH7jmisx5XOn4E07p9Fm8YJn4Aywc9vYM1jqQ8A1lEH8VSC1KR6dPfdmGr94jRscQkD6fjs9sUNTdrw== dependencies: "@babel/preset-flow" "^7.22.15" "@babel/preset-react" "^7.22.15" "@pmmmwh/react-refresh-webpack-plugin" "^0.5.11" - "@storybook/core-webpack" "7.6.17" - "@storybook/docs-tools" "7.6.17" - "@storybook/node-logger" "7.6.17" - "@storybook/react" "7.6.17" + "@storybook/core-webpack" "7.6.19" + "@storybook/docs-tools" "7.6.19" + "@storybook/node-logger" "7.6.19" + "@storybook/react" "7.6.19" "@storybook/react-docgen-typescript-plugin" "1.0.6--canary.9.0c3f3b7.0" "@types/node" "^18.0.0" "@types/semver" "^7.3.4" @@ -4416,17 +4728,17 @@ semver "^7.3.7" webpack "5" -"@storybook/preview-api@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/preview-api/-/preview-api-7.6.17.tgz#03dd399bf3bb8ac6f4aad3c738365b86b8790157" - integrity sha512-wLfDdI9RWo1f2zzFe54yRhg+2YWyxLZvqdZnSQ45mTs4/7xXV5Wfbv3QNTtcdw8tT3U5KRTrN1mTfTCiRJc0Kw== +"@storybook/preview-api@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/preview-api/-/preview-api-7.6.19.tgz#5f4b36489a7662e4671030dc2580cc11a1dd854e" + integrity sha512-04hdMSQucroJT4dBjQzRd7ZwH2hij8yx2nm5qd4HYGkd1ORkvlH6GOLph4XewNJl5Um3xfzFQzBhvkqvG0WaCQ== dependencies: - "@storybook/channels" "7.6.17" - "@storybook/client-logger" "7.6.17" - "@storybook/core-events" "7.6.17" + "@storybook/channels" "7.6.19" + "@storybook/client-logger" "7.6.19" + "@storybook/core-events" "7.6.19" "@storybook/csf" "^0.1.2" "@storybook/global" "^5.0.0" - "@storybook/types" "7.6.17" + "@storybook/types" "7.6.19" "@types/qs" "^6.9.5" dequal "^2.0.2" lodash "^4.17.21" @@ -4436,10 +4748,10 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/preview@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/preview/-/preview-7.6.17.tgz#e0c9727c7cfbd8f1d504848a57acaab8e54abe90" - integrity sha512-LvkMYK/y6alGjwRVNDIKL1lFlbyZ0H0c8iAbcQkiMoaFiujMQyVswMDKlWcj42Upfr/B1igydiruomc+eUt0mw== +"@storybook/preview@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/preview/-/preview-7.6.19.tgz#4cb2b2e1730aea8612c07d80a7908835f9806265" + integrity sha512-VqRPua2koOQTOteB+VvuKNXFYQ7IDEopaPpj9Nx+3kom+bqp0hWdAysWcm6CtKN2GGzBQm+5PvGibMNdawsaVg== "@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0": version "1.0.6--canary.9.0c3f3b7.0" @@ -4454,33 +4766,33 @@ react-docgen-typescript "^2.2.2" tslib "^2.0.0" -"@storybook/react-dom-shim@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/react-dom-shim/-/react-dom-shim-7.6.17.tgz#5875915316f687bf658cc6686ea49f2928eae4b2" - integrity sha512-32Sa/G+WnvaPiQ1Wvjjw5UM9rr2c4GDohwCcWVv3/LJuiFPqNS6zglAtmnsrlIBnUwRBMLMh/ekCTdqMiUmfDw== +"@storybook/react-dom-shim@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/react-dom-shim/-/react-dom-shim-7.6.19.tgz#c6472be7c53b8d9d3ed3007f5fc5d41daa76ac09" + integrity sha512-tpt2AC1428d1gF4fetMkpkeFZ1WdDr1CLKoLbSInWQZ7i96nbnIMIA9raR/W8ai1bo55KSz9Bq5ytC/1Pac2qQ== "@storybook/react-webpack5@^7.6.10": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/react-webpack5/-/react-webpack5-7.6.17.tgz#c1ab808bac41dde4a9bd96c3afc800b914eda9e6" - integrity sha512-qGc2JxaSmvPXV7ndxA/8qPtPLK7lAwejL/QdrzLXhxEmVdZLMew640FBYgOV/zWnehV3BnivThln/8PsQyst/g== + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/react-webpack5/-/react-webpack5-7.6.19.tgz#efd4ba044d3d18020ef60a7c352080d0773bee3e" + integrity sha512-QPnDv5eimvgc0zBIvc1H49iBUfZhs0hhrs9eO0+rAC6sIo5BiDcX9nQJZEuamRPVuLjqoRByj6vUpqGI25zASg== dependencies: - "@storybook/builder-webpack5" "7.6.17" - "@storybook/preset-react-webpack" "7.6.17" - "@storybook/react" "7.6.17" + "@storybook/builder-webpack5" "7.6.19" + "@storybook/preset-react-webpack" "7.6.19" + "@storybook/react" "7.6.19" "@types/node" "^18.0.0" -"@storybook/react@7.6.17", "@storybook/react@^7.6.10": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/react/-/react-7.6.17.tgz#3e585b37f4a45d01b60543e1952a46ae3da70e81" - integrity sha512-lVqzQSU03rRJWYW+gK2gq6mSo3/qtnVICY8B8oP7gc36jVu4ksDIu45bTfukM618ODkUZy0vZe6T4engK3azjA== +"@storybook/react@7.6.19", "@storybook/react@^7.6.10": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/react/-/react-7.6.19.tgz#a15b41fc98a80086b2f40d025f34f8641b3dea8b" + integrity sha512-uKShAAp1/pRki1YnRjBveH/jAD3f8V0W2WP1LxTQqnKVFkl01mTbDZ/9ZIK6rVTSILUlmsk3fwsNyRbOKVgBGQ== dependencies: - "@storybook/client-logger" "7.6.17" - "@storybook/core-client" "7.6.17" - "@storybook/docs-tools" "7.6.17" + "@storybook/client-logger" "7.6.19" + "@storybook/core-client" "7.6.19" + "@storybook/docs-tools" "7.6.19" "@storybook/global" "^5.0.0" - "@storybook/preview-api" "7.6.17" - "@storybook/react-dom-shim" "7.6.17" - "@storybook/types" "7.6.17" + "@storybook/preview-api" "7.6.19" + "@storybook/react-dom-shim" "7.6.19" + "@storybook/types" "7.6.19" "@types/escodegen" "^0.0.6" "@types/estree" "^0.0.51" "@types/node" "^18.0.0" @@ -4496,56 +4808,56 @@ type-fest "~2.19" util-deprecate "^1.0.2" -"@storybook/router@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/router/-/router-7.6.17.tgz#de5016086191846ed12af7495aeddcc373cbd0d4" - integrity sha512-GnyC0j6Wi5hT4qRhSyT8NPtJfGmf82uZw97LQRWeyYu5gWEshUdM7aj40XlNiScd5cZDp0owO1idduVF2k2l2A== +"@storybook/router@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/router/-/router-7.6.19.tgz#b9805344d35bb00c9139787f7c561603ffe0d3c2" + integrity sha512-q2/AvY8rG0znFEfbg50OIhkS5yQ6OmyzdCdztoEsDDdsbq87YPmsDj7k8Op1EkTa2T5CB8XhBOCQDtcj7gUUtg== dependencies: - "@storybook/client-logger" "7.6.17" + "@storybook/client-logger" "7.6.19" memoizerific "^1.11.3" qs "^6.10.0" "@storybook/source-loader@^7.6.10": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/source-loader/-/source-loader-7.6.17.tgz#a9ebc2ed6e6fa3041f80cd1df1775505b5bc8513" - integrity sha512-90v1es7dHmHgkGbflPlaRBYcn2+mqdC8OG4QtyYqOUq6xsLsyg+5CX2rupfHbuSLw9r0A3o1ViOII2J/kWtFow== + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/source-loader/-/source-loader-7.6.19.tgz#5d910b4874f7bfb121d854c7921e777ee7df2a6e" + integrity sha512-Pbbq2RrS0Ct7e1MXVKW62a61Wh4iZQ66LWwksZKqW0bMM4Ohdw8v+OZI00y7Wk4+/u1gbUDplQk2k0JlueOrMw== dependencies: "@storybook/csf" "^0.1.2" - "@storybook/types" "7.6.17" + "@storybook/types" "7.6.19" estraverse "^5.2.0" lodash "^4.17.21" prettier "^2.8.0" -"@storybook/telemetry@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/telemetry/-/telemetry-7.6.17.tgz#472dd6a8d87240c1fcc01bb9d6247e134e539b5b" - integrity sha512-WOcOAmmengYnGInH98Px44F47DSpLyk20BM+Z/IIQDzfttGOLlxNqBBG1XTEhNRn+AYuk4aZ2JEed2lCjVIxcA== +"@storybook/telemetry@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/telemetry/-/telemetry-7.6.19.tgz#c0e11bea942057fd8eef66680c39e0cd4e0d9970" + integrity sha512-rA5xum4I36M57iiD3uzmW0MOdpl0vEpHWBSAa5hK0a0ALPeY9TgAsQlI/0dSyNYJ/K7aczEEN6d4qm1NC4u10A== dependencies: - "@storybook/client-logger" "7.6.17" - "@storybook/core-common" "7.6.17" - "@storybook/csf-tools" "7.6.17" + "@storybook/client-logger" "7.6.19" + "@storybook/core-common" "7.6.19" + "@storybook/csf-tools" "7.6.19" chalk "^4.1.0" detect-package-manager "^2.0.1" fetch-retry "^5.0.2" fs-extra "^11.1.0" read-pkg-up "^7.0.1" -"@storybook/theming@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-7.6.17.tgz#8170e3e72b921380c51a3970890d4cb479a65c2f" - integrity sha512-ZbaBt3KAbmBtfjNqgMY7wPMBshhSJlhodyMNQypv+95xLD/R+Az6aBYbpVAOygLaUQaQk4ar7H/Ww6lFIoiFbA== +"@storybook/theming@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-7.6.19.tgz#f5032d74d5c0cf5f7c7a389a0b9d2d3bc5e62a25" + integrity sha512-sAho13MmtA80ctOaLn8lpkQBsPyiqSdLcOPH5BWFhatQzzBQCpTAKQk+q/xGju8bNiPZ+yQBaBzbN8SfX8ceCg== dependencies: "@emotion/use-insertion-effect-with-fallbacks" "^1.0.0" - "@storybook/client-logger" "7.6.17" + "@storybook/client-logger" "7.6.19" "@storybook/global" "^5.0.0" memoizerific "^1.11.3" -"@storybook/types@7.6.17": - version "7.6.17" - resolved "https://registry.yarnpkg.com/@storybook/types/-/types-7.6.17.tgz#0b3c27cb1708c0545a9ea1a23b73aa8852dd47c4" - integrity sha512-GRY0xEJQ0PrL7DY2qCNUdIfUOE0Gsue6N+GBJw9ku1IUDFLJRDOF+4Dx2BvYcVCPI5XPqdWKlEyZdMdKjiQN7Q== +"@storybook/types@7.6.19": + version "7.6.19" + resolved "https://registry.yarnpkg.com/@storybook/types/-/types-7.6.19.tgz#ec73c9afb6003c57e260e1709441af4db9f50190" + integrity sha512-DeGYrRPRMGTVfT7o2rEZtRzyLT2yKTI2exgpnxbwPWEFAduZCSfzBrcBXZ/nb5B0pjA9tUNWls1YzGkJGlkhpg== dependencies: - "@storybook/channels" "7.6.17" + "@storybook/channels" "7.6.19" "@types/babel__core" "^7.0.0" "@types/express" "^4.7.0" file-system-cache "2.3.0" @@ -4560,6 +4872,11 @@ magic-string "^0.25.0" string.prototype.matchall "^4.0.6" +"@svgr/babel-plugin-add-jsx-attribute@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz#4001f5d5dd87fa13303e36ee106e3ff3a7eb8b22" + integrity sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g== + "@svgr/babel-plugin-add-jsx-attribute@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz#81ef61947bb268eb9d50523446f9c638fb355906" @@ -4570,7 +4887,7 @@ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.5.1.tgz#74a5d648bd0347bda99d82409d87b8ca80b9a1ba" integrity sha512-9PYGcXrAxitycIjRmZB+Q0JaN07GZIWaTBIGQzfaZv+qr1n8X1XUEJ5rZ/vx6OVD9RRYlrNnXWExQXcmZeD/BQ== -"@svgr/babel-plugin-remove-jsx-attribute@*": +"@svgr/babel-plugin-remove-jsx-attribute@*", "@svgr/babel-plugin-remove-jsx-attribute@8.0.0": version "8.0.0" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz#69177f7937233caca3a1afb051906698f2f59186" integrity sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA== @@ -4580,7 +4897,7 @@ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-5.4.0.tgz#6b2c770c95c874654fd5e1d5ef475b78a0a962ef" integrity sha512-yaS4o2PgUtwLFGTKbsiAy6D0o3ugcUhWK0Z45umJ66EPWunAz9fuFw2gJuje6wqQvQWOTJvIahUwndOXb7QCPg== -"@svgr/babel-plugin-remove-jsx-empty-expression@*": +"@svgr/babel-plugin-remove-jsx-empty-expression@*", "@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0": version "8.0.0" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz#c2c48104cfd7dcd557f373b70a56e9e3bdae1d44" integrity sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA== @@ -4590,6 +4907,11 @@ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-5.0.1.tgz#25621a8915ed7ad70da6cea3d0a6dbc2ea933efd" integrity sha512-LA72+88A11ND/yFIMzyuLRSMJ+tRKeYKeQ+mR3DcAZ5I4h5CPWN9AHyUzJbWSYp/u2u0xhmgOe0+E41+GjEueA== +"@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz#8fbb6b2e91fa26ac5d4aa25c6b6e4f20f9c0ae27" + integrity sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ== + "@svgr/babel-plugin-replace-jsx-attribute-value@^5.0.1": version "5.0.1" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-5.0.1.tgz#0b221fc57f9fcd10e91fe219e2cd0dd03145a897" @@ -4600,6 +4922,11 @@ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.5.1.tgz#fb9d22ea26d2bc5e0a44b763d4c46d5d3f596c60" integrity sha512-8DPaVVE3fd5JKuIC29dqyMB54sA6mfgki2H2+swh+zNJoynC8pMPzOkidqHOSc6Wj032fhl8Z0TVn1GiPpAiJg== +"@svgr/babel-plugin-svg-dynamic-title@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz#1d5ba1d281363fc0f2f29a60d6d936f9bbc657b0" + integrity sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og== + "@svgr/babel-plugin-svg-dynamic-title@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-5.4.0.tgz#139b546dd0c3186b6e5db4fefc26cb0baea729d7" @@ -4610,6 +4937,11 @@ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.5.1.tgz#01b2024a2b53ffaa5efceaa0bf3e1d5a4c520ce4" integrity sha512-FwOEi0Il72iAzlkaHrlemVurgSQRDFbk0OC8dSvD5fSBPHltNh7JtLsxmZUhjYBZo2PpcU/RJvvi6Q0l7O7ogw== +"@svgr/babel-plugin-svg-em-dimensions@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz#35e08df300ea8b1d41cb8f62309c241b0369e501" + integrity sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g== + "@svgr/babel-plugin-svg-em-dimensions@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-5.4.0.tgz#6543f69526632a133ce5cabab965deeaea2234a0" @@ -4620,6 +4952,11 @@ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.5.1.tgz#dd3fa9f5b24eb4f93bcf121c3d40ff5facecb217" integrity sha512-gWGsiwjb4tw+ITOJ86ndY/DZZ6cuXMNE/SjcDRg+HLuCmwpcjOktwRF9WgAiycTqJD/QXqL2f8IzE2Rzh7aVXA== +"@svgr/babel-plugin-transform-react-native-svg@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz#90a8b63998b688b284f255c6a5248abd5b28d754" + integrity sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q== + "@svgr/babel-plugin-transform-react-native-svg@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-5.4.0.tgz#00bf9a7a73f1cad3948cdab1f8dfb774750f8c80" @@ -4630,6 +4967,11 @@ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.5.1.tgz#1d8e945a03df65b601551097d8f5e34351d3d305" integrity sha512-2jT3nTayyYP7kI6aGutkyfJ7UMGtuguD72OjeGLwVNyfPRBD8zQthlvL+fAbAKk5n9ZNcvFkp/b1lZ7VsYqVJg== +"@svgr/babel-plugin-transform-svg-component@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz#013b4bfca88779711f0ed2739f3f7efcefcf4f7e" + integrity sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw== + "@svgr/babel-plugin-transform-svg-component@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-5.5.0.tgz#583a5e2a193e214da2f3afeb0b9e8d3250126b4a" @@ -4640,6 +4982,20 @@ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.5.1.tgz#48620b9e590e25ff95a80f811544218d27f8a250" integrity sha512-a1p6LF5Jt33O3rZoVRBqdxL350oge54iZWHNI6LJB5tQ7EelvD/Mb1mfBiZNAan0dt4i3VArkFRjA4iObuNykQ== +"@svgr/babel-preset@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-8.1.0.tgz#0e87119aecdf1c424840b9d4565b7137cabf9ece" + integrity sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug== + dependencies: + "@svgr/babel-plugin-add-jsx-attribute" "8.0.0" + "@svgr/babel-plugin-remove-jsx-attribute" "8.0.0" + "@svgr/babel-plugin-remove-jsx-empty-expression" "8.0.0" + "@svgr/babel-plugin-replace-jsx-attribute-value" "8.0.0" + "@svgr/babel-plugin-svg-dynamic-title" "8.0.0" + "@svgr/babel-plugin-svg-em-dimensions" "8.0.0" + "@svgr/babel-plugin-transform-react-native-svg" "8.1.0" + "@svgr/babel-plugin-transform-svg-component" "8.0.0" + "@svgr/babel-preset@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-5.5.0.tgz#8af54f3e0a8add7b1e2b0fcd5a882c55393df327" @@ -4668,6 +5024,17 @@ "@svgr/babel-plugin-transform-react-native-svg" "^6.5.1" "@svgr/babel-plugin-transform-svg-component" "^6.5.1" +"@svgr/core@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@svgr/core/-/core-8.1.0.tgz#41146f9b40b1a10beaf5cc4f361a16a3c1885e88" + integrity sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA== + dependencies: + "@babel/core" "^7.21.3" + "@svgr/babel-preset" "8.1.0" + camelcase "^6.2.0" + cosmiconfig "^8.1.3" + snake-case "^3.0.4" + "@svgr/core@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@svgr/core/-/core-5.5.0.tgz#82e826b8715d71083120fe8f2492ec7d7874a579" @@ -4688,6 +5055,14 @@ camelcase "^6.2.0" cosmiconfig "^7.0.1" +"@svgr/hast-util-to-babel-ast@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz#6952fd9ce0f470e1aded293b792a2705faf4ffd4" + integrity sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q== + dependencies: + "@babel/types" "^7.21.3" + entities "^4.4.0" + "@svgr/hast-util-to-babel-ast@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-5.5.0.tgz#5ee52a9c2533f73e63f8f22b779f93cd432a5461" @@ -4703,6 +5078,16 @@ "@babel/types" "^7.20.0" entities "^4.4.0" +"@svgr/plugin-jsx@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz#96969f04a24b58b174ee4cd974c60475acbd6928" + integrity sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA== + dependencies: + "@babel/core" "^7.21.3" + "@svgr/babel-preset" "8.1.0" + "@svgr/hast-util-to-babel-ast" "8.0.0" + svg-parser "^2.0.4" + "@svgr/plugin-jsx@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-5.5.0.tgz#1aa8cd798a1db7173ac043466d7b52236b369000" @@ -4723,6 +5108,15 @@ "@svgr/hast-util-to-babel-ast" "^6.5.1" svg-parser "^2.0.4" +"@svgr/plugin-svgo@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz#b115b7b967b564f89ac58feae89b88c3decd0f00" + integrity sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA== + dependencies: + cosmiconfig "^8.1.3" + deepmerge "^4.3.1" + svgo "^3.0.2" + "@svgr/plugin-svgo@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-5.5.0.tgz#02da55d85320549324e201c7b2e53bf431fcc246" @@ -4769,84 +5163,98 @@ "@svgr/plugin-jsx" "^6.5.1" "@svgr/plugin-svgo" "^6.5.1" -"@swc/core-darwin-arm64@1.4.13": - version "1.4.13" - resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.4.13.tgz#9b1ff4477a9b9eb76275e1dd1af52fbe8d11a0d3" - integrity sha512-36P72FLpm5iq85IvoEjBvi22DiqkkEIanJ1M0E8bkxcFHUbjBrYfPY9T6cpPyK5oQqkaTBvNAc3j1BlVD6IH6w== - -"@swc/core-darwin-x64@1.4.13": - version "1.4.13" - resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.4.13.tgz#a293492337e337404742988897f7d3befce83d4b" - integrity sha512-ye7OgKpDdyA8AMIVVdmD1ICDaFXgoEXORnVO8bBHyul0WN71yUBZMX+YxEx2lpWtiftA2vY/1MAuOR80vHkBCw== - -"@swc/core-linux-arm-gnueabihf@1.4.13": - version "1.4.13" - resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.4.13.tgz#685016a0b2ed7195e2aa78d92a0aea0dc2567610" - integrity sha512-+x593Jlmu4c3lJtZUKRejWpV2MAij1Js5nmQLLdjo6ChR2D4B2rzj3iMiKn5gITew7fraF9t3fvXALdWh7HmUg== - -"@swc/core-linux-arm64-gnu@1.4.13": - version "1.4.13" - resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.4.13.tgz#ef4fd6552c508e2196bad152330123205d34dca7" - integrity sha512-0x8OVw4dfyNerrs/9eZX9wNnmvwbwXSMCi+LbE6Xt1pXOIwvoLtFIXcV3NsrlkFboO3sr5UAQIwDxKqbIZA9pQ== - -"@swc/core-linux-arm64-musl@1.4.13": - version "1.4.13" - resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.4.13.tgz#214b7d3469366e880a3d69b23846ad217203b798" - integrity sha512-Z9c4JiequtZvngPcxbCuAOkmWBxi2vInZbjjhD5I+Q9oiJdXUz1t2USGwsGPS41Xvk1BOA3ecK2Sn1ilY3titg== - -"@swc/core-linux-x64-gnu@1.4.13": - version "1.4.13" - resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.4.13.tgz#f165ab1baa4cc7eea997ee58db7eb860608f4b1d" - integrity sha512-ChatHtk+vX0Ke5QG+jO+rIapw/KwZsi9MedCBHFXHH6iWF4z8d51cJeN68ykcn+vAXzjNeFNdlNy5Vbkd1zAqg== - -"@swc/core-linux-x64-musl@1.4.13": - version "1.4.13" - resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.13.tgz#18c3748ca0aa50a4062ee61de7b41af92c3753c7" - integrity sha512-0Pz39YR530mXpsztwQkmEKdkkZy4fY4Smdh4pkm6Ly8Nndyo0te/l4bcAGqN24Jp7aVwF/QSy14SAtw4HRjU9g== - -"@swc/core-win32-arm64-msvc@1.4.13": - version "1.4.13" - resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.4.13.tgz#89f60481ad06b39ca6b9e56593564fb9bd86b886" - integrity sha512-LVZfhlD+jHcAbz5NN+gAJ1BEasB0WpcvUzcsJt0nQSRsojgzPzFjJ+fzEBnvT7SMtqKkrnVJ0OmDYeh88bDRpw== - -"@swc/core-win32-ia32-msvc@1.4.13": - version "1.4.13" - resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.4.13.tgz#8f4bff548e3eae7b7ef0667f31866c5b5ee4dbfa" - integrity sha512-78hxHWUvUZtWsnhcf8DKwhBcNFJw+j4y4fN2B9ioXmBWX2tIyw+BqUHOrismOtjPihaZmwe/Ok2e4qmkawE2fw== - -"@swc/core-win32-x64-msvc@1.4.13": - version "1.4.13" - resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.4.13.tgz#57fb58f6c81526b17c432db3159bf540bd977a12" - integrity sha512-WSfy1u2Xde6jU7UpHIInCUMW98Zw9iZglddKUAvmr1obkZji5U6EX0Oca3asEJdZPFb+2lMLjt0Mh5a1YisROg== +"@svgr/webpack@^8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@svgr/webpack/-/webpack-8.1.0.tgz#16f1b5346f102f89fda6ec7338b96a701d8be0c2" + integrity sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA== + dependencies: + "@babel/core" "^7.21.3" + "@babel/plugin-transform-react-constant-elements" "^7.21.3" + "@babel/preset-env" "^7.20.2" + "@babel/preset-react" "^7.18.6" + "@babel/preset-typescript" "^7.21.0" + "@svgr/core" "8.1.0" + "@svgr/plugin-jsx" "8.1.0" + "@svgr/plugin-svgo" "8.1.0" + +"@swc/core-darwin-arm64@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.6.1.tgz#72d861fb7094b7a0004f4f300e2c5d4ea1549d9e" + integrity sha512-u6GdwOXsOEdNAdSI6nWq6G2BQw5HiSNIZVcBaH1iSvBnxZvWbnIKyDiZKaYnDwTLHLzig2GuUjjE2NaCJPy4jg== + +"@swc/core-darwin-x64@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.6.1.tgz#8b7070fcee4a4570d0af245c4614ca4e492dfd5b" + integrity sha512-/tXwQibkDNLVbAtr7PUQI0iQjoB708fjhDDDfJ6WILSBVZ3+qs/LHjJ7jHwumEYxVq1XA7Fv2Q7SE/ZSQoWHcQ== + +"@swc/core-linux-arm-gnueabihf@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.6.1.tgz#bea6d2e75127bbc65a664284f012ffa90c8325d5" + integrity sha512-aDgipxhJTms8iH78emHVutFR2c16LNhO+NTRCdYi+X4PyIn58/DyYTH6VDZ0AeEcS5f132ZFldU5AEgExwihXA== + +"@swc/core-linux-arm64-gnu@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.6.1.tgz#5c84d804ec23cf54b31c0bc0b4bdd30ec5d43ce8" + integrity sha512-XkJ+eO4zUKG5g458RyhmKPyBGxI0FwfWFgpfIj5eDybxYJ6s4HBT5MoxyBLorB5kMlZ0XoY/usUMobPVY3nL0g== + +"@swc/core-linux-arm64-musl@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.6.1.tgz#e167a350bec12caebc97304068c3ffbad6c398ce" + integrity sha512-dr6YbLBg/SsNxs1hDqJhxdcrS8dGMlOXJwXIrUvACiA8jAd6S5BxYCaqsCefLYXtaOmu0bbx1FB/evfodqB70Q== + +"@swc/core-linux-x64-gnu@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.6.1.tgz#fdd4e1d63b3e53d195e2ddcb9cb5ad9f31995796" + integrity sha512-A0b/3V+yFy4LXh3O9umIE7LXPC7NBWdjl6AQYqymSMcMu0EOb1/iygA6s6uWhz9y3e172Hpb9b/CGsuD8Px/bg== + +"@swc/core-linux-x64-musl@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.6.1.tgz#81a312dd9e62da5f4c48e3cd23b6c6d28a31ac42" + integrity sha512-5dJjlzZXhC87nZZZWbpiDP8kBIO0ibis893F/rtPIQBI5poH+iJuA32EU3wN4/WFHeK4et8z6SGSVghPtWyk4g== + +"@swc/core-win32-arm64-msvc@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.6.1.tgz#e131f579a69c5d807013e54ccb311e10caa27bcb" + integrity sha512-HBi1ZlwvfcUibLtT3g/lP57FaDPC799AD6InolB2KSgkqyBbZJ9wAXM8/CcH67GLIP0tZ7FqblrJTzGXxetTJQ== + +"@swc/core-win32-ia32-msvc@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.6.1.tgz#9f3d88cf0e826aa8222a695177a065ed2899eb21" + integrity sha512-AKqHohlWERclexar5y6ux4sQ8yaMejEXNxeKXm7xPhXrp13/1p4/I3E5bPVX/jMnvpm4HpcKSP0ee2WsqmhhPw== + +"@swc/core-win32-x64-msvc@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.6.1.tgz#b2082710bc46c484a2c9f2e33a15973806e5031d" + integrity sha512-0dLdTLd+ONve8kgC5T6VQ2Y5G+OZ7y0ujjapnK66wpvCBM6BKYGdT/OKhZKZydrC5gUKaxFN6Y5oOt9JOFUrOQ== "@swc/core@^1.3.82": - version "1.4.13" - resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.4.13.tgz#c679664cae722fc404a59fc6d687e80bf7dbae99" - integrity sha512-rOtusBE+2gaeRkAJn5E4zp5yzZekZOypzSOz5ZG6P1hFbd+Cc26fWEdK6sUSnrkkvTd0Oj33KXLB/4UkbK/UHA== + version "1.6.1" + resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.6.1.tgz#a899a205cfaa8e23f805451ef4787987e03b8920" + integrity sha512-Yz5uj5hNZpS5brLtBvKY0L4s2tBAbQ4TjmW8xF1EC3YLFxQRrUjMP49Zm1kp/KYyYvTkSaG48Ffj2YWLu9nChw== dependencies: - "@swc/counter" "^0.1.2" - "@swc/types" "^0.1.5" + "@swc/counter" "^0.1.3" + "@swc/types" "^0.1.8" optionalDependencies: - "@swc/core-darwin-arm64" "1.4.13" - "@swc/core-darwin-x64" "1.4.13" - "@swc/core-linux-arm-gnueabihf" "1.4.13" - "@swc/core-linux-arm64-gnu" "1.4.13" - "@swc/core-linux-arm64-musl" "1.4.13" - "@swc/core-linux-x64-gnu" "1.4.13" - "@swc/core-linux-x64-musl" "1.4.13" - "@swc/core-win32-arm64-msvc" "1.4.13" - "@swc/core-win32-ia32-msvc" "1.4.13" - "@swc/core-win32-x64-msvc" "1.4.13" - -"@swc/counter@^0.1.2", "@swc/counter@^0.1.3": + "@swc/core-darwin-arm64" "1.6.1" + "@swc/core-darwin-x64" "1.6.1" + "@swc/core-linux-arm-gnueabihf" "1.6.1" + "@swc/core-linux-arm64-gnu" "1.6.1" + "@swc/core-linux-arm64-musl" "1.6.1" + "@swc/core-linux-x64-gnu" "1.6.1" + "@swc/core-linux-x64-musl" "1.6.1" + "@swc/core-win32-arm64-msvc" "1.6.1" + "@swc/core-win32-ia32-msvc" "1.6.1" + "@swc/core-win32-x64-msvc" "1.6.1" + +"@swc/counter@^0.1.3": version "0.1.3" resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== -"@swc/types@^0.1.5": - version "0.1.6" - resolved "https://registry.yarnpkg.com/@swc/types/-/types-0.1.6.tgz#2f13f748995b247d146de2784d3eb7195410faba" - integrity sha512-/JLo/l2JsT/LRd80C3HfbmVpxOAJ11FO2RCEslFrgzLltoP9j8XIbsyDcfCt2WWyX+CM96rBoNM+IToAkFOugg== +"@swc/types@^0.1.8": + version "0.1.8" + resolved "https://registry.yarnpkg.com/@swc/types/-/types-0.1.8.tgz#2c81d107c86cfbd0c3a05ecf7bb54c50dfa58a95" + integrity sha512-RNFA3+7OJFNYY78x0FYwi1Ow+iF1eF5WvmfY1nXPOEH4R2p/D4Cr1vzje7dNAI2aLFqpv8Wyz4oKSWqIZArpQA== dependencies: "@swc/counter" "^0.1.3" @@ -4857,13 +5265,28 @@ dependencies: defer-to-connect "^2.0.1" -"@testing-library/react-hooks@^3.2.1": - version "3.7.0" - resolved "https://registry.yarnpkg.com/@testing-library/react-hooks/-/react-hooks-3.7.0.tgz#6d75c5255ef49bce39b6465bf6b49e2dac84919e" - integrity sha512-TwfbY6BWtWIHitjT05sbllyLIProcysC0dF0q1bbDa7OHLC6A6rJOYJwZ13hzfz3O4RtOuInmprBozJRyyo7/g== +"@testing-library/dom@^8.5.0": + version "8.20.1" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.20.1.tgz#2e52a32e46fc88369eef7eef634ac2a192decd9f" + integrity sha512-/DiOQ5xBxgdYRC8LNk7U+RWat0S3qRLeIw3ZIkMQ9kkVlRmwD/Eg8k8CqIpD6GW7u20JIUOfMKbxtiLutpjQ4g== dependencies: + "@babel/code-frame" "^7.10.4" "@babel/runtime" "^7.12.5" - "@types/testing-library__react-hooks" "^3.4.0" + "@types/aria-query" "^5.0.1" + aria-query "5.1.3" + chalk "^4.1.0" + dom-accessibility-api "^0.5.9" + lz-string "^1.5.0" + pretty-format "^27.0.2" + +"@testing-library/react@^13.1.0": + version "13.4.0" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-13.4.0.tgz#6a31e3bf5951615593ad984e96b9e5e2d9380966" + integrity sha512-sXOGON+WNTh3MLE9rve97ftaZukN3oNf2KjDy7YTx6hcTO2uuLHuCGynMDhFwGw/jYf4OJ2Qk0i4i79qMNNkyw== + dependencies: + "@babel/runtime" "^7.12.5" + "@testing-library/dom" "^8.5.0" + "@types/react-dom" "^18.0.0" "@tootallnate/once@2": version "2.0.0" @@ -4888,6 +5311,11 @@ "@tufjs/canonical-json" "1.0.0" minimatch "^9.0.0" +"@types/aria-query@^5.0.1": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.4.tgz#1a31c3d378850d2778dabb6374d036dcba4ba708" + integrity sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw== + "@types/babel__core@^7.0.0", "@types/babel__core@^7.1.14", "@types/babel__core@^7.18.0": version "7.20.5" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" @@ -4915,9 +5343,9 @@ "@babel/types" "^7.0.0" "@types/babel__traverse@*", "@types/babel__traverse@^7.0.6", "@types/babel__traverse@^7.18.0": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.5.tgz#7b7502be0aa80cc4ef22978846b983edaafcd4dd" - integrity sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ== + version "7.20.6" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.6.tgz#8dc9f0ae0f202c08d8d4dab648912c8d6038e3f7" + integrity sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg== dependencies: "@babel/types" "^7.20.7" @@ -4993,9 +5421,9 @@ integrity sha512-nv+GSx77ZtXiJzwKdsASqi+YQ5Z7vwHsTP0JY2SiQgjGckkBRKZnk8nIM+7oUZ1VCtuTz0+By4qVR7fqzp/Dfg== "@types/emscripten@^1.39.6": - version "1.39.10" - resolved "https://registry.yarnpkg.com/@types/emscripten/-/emscripten-1.39.10.tgz#da6e58a6171b46a41d3694f812d845d515c77e18" - integrity sha512-TB/6hBkYQJxsZHSqyeuO1Jt0AB/bW6G7rHt9g7lML7SOF6lbgcHvw/Lr+69iqN0qxgXLhWKScAon73JNnptuDw== + version "1.39.13" + resolved "https://registry.yarnpkg.com/@types/emscripten/-/emscripten-1.39.13.tgz#afeb1648648dc096efe57983e20387627306e2aa" + integrity sha512-cFq+fO/isvhvmuP/+Sl4K4jtU6E23DoivtbO4r50e3odaxAiVdbfSYRDdJ4gCdxx+3aRjhphS5ZMwIH4hFy/Cw== "@types/escodegen@^0.0.6": version "0.0.6" @@ -5011,9 +5439,9 @@ "@types/estree" "*" "@types/eslint@*": - version "8.56.8" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.56.8.tgz#e927fdc742a98fc3195a9d047631e6ab95029b50" - integrity sha512-LdDdQVDzDXf3ijhhMnE27C5vc0QEknD8GiMR/Hi+fVbdZNfAfCy2j69m0LjUd2MAy0+kIgnOtd5ndTmDk/VWCA== + version "8.56.10" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.56.10.tgz#eb2370a73bf04a901eeba8f22595c7ee0f7eb58d" + integrity sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ== dependencies: "@types/estree" "*" "@types/json-schema" "*" @@ -5026,7 +5454,7 @@ "@types/estree" "*" "@types/json-schema" "*" -"@types/estree@*", "@types/estree@^1.0.5": +"@types/estree@*", "@types/estree@^1.0.0", "@types/estree@^1.0.5": version "1.0.5" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== @@ -5049,9 +5477,9 @@ "@types/node" "*" "@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.33": - version "4.19.0" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.0.tgz#3ae8ab3767d98d0b682cda063c3339e1e86ccfaa" - integrity sha512-bGyep3JqPCRry1wq+O5n7oiBgGWmeIJXPjXXCo8EK0u8duZGSYar7cGqd3ML2JUsLGeB7fmc06KYo9fLGWqPvQ== + version "4.19.3" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.3.tgz#e469a13e4186c9e1c0418fb17be8bc8ff1b19a7a" + integrity sha512-KOzM7MhcBFlmnlr/fzISFF5vGWVSvN6fTd4T+ExOt08bA/dA5kpSzY52nMsI1KDFmUREpJelPYyuslLRSjjgCg== dependencies: "@types/node" "*" "@types/qs" "*" @@ -5177,9 +5605,9 @@ integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== "@types/lodash@^4.14.167": - version "4.17.0" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.0.tgz#d774355e41f372d5350a4d0714abb48194a489c3" - integrity sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA== + version "4.17.5" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.5.tgz#e6c29b58e66995d57cd170ce3e2a61926d55ee04" + integrity sha512-MBIOHVZqVqgfro1euRDWX7OO0fBVUUMrN6Pwm8LQsz8cWhEpihlvR70ENj3f40j58TNxZaWv2ndSkInykNBBJw== "@types/mdast@^3.0.0": version "3.0.15" @@ -5239,9 +5667,9 @@ "@types/node" "*" "@types/node@*": - version "20.12.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.7.tgz#04080362fa3dd6c5822061aa3124f5c152cff384" - integrity sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg== + version "20.14.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.9.tgz#12e8e765ab27f8c421a1820c99f5f313a933b420" + integrity sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg== dependencies: undici-types "~5.26.4" @@ -5256,9 +5684,16 @@ integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw== "@types/node@^18.0.0": - version "18.19.31" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.31.tgz#b7d4a00f7cb826b60a543cebdbda5d189aaecdcd" - integrity sha512-ArgCD39YpyyrtFKIqMDvjz79jto5fcI/SVUs2HwB+f0dAzq68yqOdyaSivLiLugSziTpNXLQrVb7RZFmdZzbhA== + version "18.19.36" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.36.tgz#c9861e84727e07ecf79a5ff6d0e14f91bab2b478" + integrity sha512-tX1BNmYSWEvViftB26VLNxT6mEr37M7+ldUtq7rlKnv4/2fKYsJIOmqJAjT6h1DNuwQjIKgw3VJ/Dtw3yiTIQw== + dependencies: + undici-types "~5.26.4" + +"@types/node@^20.12.12": + version "20.14.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.5.tgz#fe35e3022ebe58b8f201580eb24e1fcfc0f2487d" + integrity sha512-aoRR+fJkZT2l0aGOJhuA8frnCSoNX6W7U2mpNq63+BxBIj5BQFt8rHy627kijCmm63ijdSdwvGgpUsU6MBsZZA== dependencies: undici-types "~5.26.4" @@ -5298,15 +5733,22 @@ integrity sha512-hroOstUScF6zhIi+5+x0dzqrHA1EJi+Irri6b1fxolMTqqHIV/Cg77EtnQcZqZCu8hR3mX2BzIxN4/GzI68Kfw== "@types/qs@*", "@types/qs@^6.9.5": - version "6.9.14" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.14.tgz#169e142bfe493895287bee382af6039795e9b75b" - integrity sha512-5khscbd3SwWMhFqylJBLQ0zIu7c1K6Vz0uBIt915BI3zV0q1nfjRQD3RqSBcPaO6PHEF4ov/t9y89fSiyThlPA== + version "6.9.15" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.15.tgz#adde8a060ec9c305a82de1babc1056e73bd64dce" + integrity sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg== "@types/range-parser@*": version "1.2.7" resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ== +"@types/react-dom@^18.0.0": + version "18.3.0" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.0.tgz#0cbc818755d87066ab6ca74fbedb2547d74a82b0" + integrity sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg== + dependencies: + "@types/react" "*" + "@types/react-router-config@*", "@types/react-router-config@^5.0.6": version "5.0.11" resolved "https://registry.yarnpkg.com/@types/react-router-config/-/react-router-config-5.0.11.tgz#2761a23acc7905a66a94419ee40294a65aaa483a" @@ -5333,13 +5775,6 @@ "@types/history" "^4.7.11" "@types/react" "*" -"@types/react-test-renderer@*": - version "18.0.7" - resolved "https://registry.yarnpkg.com/@types/react-test-renderer/-/react-test-renderer-18.0.7.tgz#2cfe657adb3688cdf543995eceb2e062b5a68728" - integrity sha512-1+ANPOWc6rB3IkSnElhjv6VLlKg2dSv/OWClUyZimbLsQyBn8Js9Vtdsi3UICJ2rIQ3k2la06dkB+C92QfhKmg== - dependencies: - "@types/react" "*" - "@types/react-transition-group@^4.4.0": version "4.4.10" resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.10.tgz#6ee71127bdab1f18f11ad8fb3322c6da27c327ac" @@ -5347,23 +5782,14 @@ dependencies: "@types/react" "*" -"@types/react@*", "@types/react@>=16": - version "18.2.75" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.75.tgz#45d18f384939306d35312def1bf532eb38a68562" - integrity sha512-+DNnF7yc5y0bHkBTiLKqXFe+L4B3nvOphiMY3tuA5X10esmjqk7smyBZzbGTy2vsiy/Bnzj8yFIBL8xhRacoOg== +"@types/react@*", "@types/react@>=16", "@types/react@^18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.3.tgz#9679020895318b0915d7a3ab004d92d33375c45f" + integrity sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw== dependencies: "@types/prop-types" "*" csstype "^3.0.2" -"@types/react@^17.0.38": - version "17.0.80" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.80.tgz#a5dfc351d6a41257eb592d73d3a85d3b7dbcbb41" - integrity sha512-LrgHIu2lEtIo8M7d1FcI3BdwXWoRQwMoXOZ7+dPTW0lYREjmlHl3P0U1VD0i/9tppOuv8/sam7sOjx34TxSFbA== - dependencies: - "@types/prop-types" "*" - "@types/scheduler" "^0.16" - csstype "^3.0.2" - "@types/resolve@1.17.1": version "1.17.1" resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6" @@ -5388,11 +5814,6 @@ dependencies: "@types/node" "*" -"@types/scheduler@^0.16": - version "0.16.8" - resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.8.tgz#ce5ace04cfeabe7ef87c0091e50752e36707deff" - integrity sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A== - "@types/semver@^7.3.4", "@types/semver@^7.5.0": version "7.5.8" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" @@ -5454,13 +5875,6 @@ resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.12.tgz#bc2cab12e87978eee89fb21576b670350d6d86ab" integrity sha512-bTHG8fcxEqv1M9+TD14P8ok8hjxoOCkfKc8XXLaaD05kI7ohpeI956jtDOD3XHKBQrlyPughUtzm1jtVhHpA5Q== -"@types/testing-library__react-hooks@^3.4.0": - version "3.4.1" - resolved "https://registry.yarnpkg.com/@types/testing-library__react-hooks/-/testing-library__react-hooks-3.4.1.tgz#b8d7311c6c1f7db3103e94095fe901f8fef6e433" - integrity sha512-G4JdzEcq61fUyV6wVW9ebHWEiLK2iQvaBuCHHn9eMSbZzVh4Z4wHnUGIvQOYCCYeu5DnUtFyNYuAAgbSaO/43Q== - dependencies: - "@types/react-test-renderer" "*" - "@types/tough-cookie@*": version "4.0.5" resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz#cb6e2a691b70cb177c6e3ae9c1d2e8b2ea8cd304" @@ -5510,9 +5924,9 @@ source-map "^0.6.0" "@types/webxr@^0.5.5": - version "0.5.15" - resolved "https://registry.yarnpkg.com/@types/webxr/-/webxr-0.5.15.tgz#21cd63e83a997c14ff91c7c537efabb787d1af09" - integrity sha512-nC9116Gd4N+CqTxqo6gvCfhAMAzgRcfS8ZsciNodHq8uwW4JCVKwhagw8yN0XmC7mHrLnWqniJpoVEiR+72Drw== + version "0.5.19" + resolved "https://registry.yarnpkg.com/@types/webxr/-/webxr-0.5.19.tgz#463a27bc06ff1c0a0c997e86b48bf24c5f50a4af" + integrity sha512-4hxA+NwohSgImdTSlPXEqDqqFktNgmTXQ05ff1uWam05tNGroCMp4G+4XVl6qWm1p7GQ/9oD41kAYsSssF6Mzw== "@types/ws@^8.2.2", "@types/ws@^8.5.5": version "8.5.10" @@ -5633,7 +6047,12 @@ "@typescript-eslint/types" "6.21.0" eslint-visitor-keys "^3.4.1" -"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1": +"@ungap/structured-clone@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" + integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== + +"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.11.5", "@webassemblyjs/ast@^1.12.1": version "1.12.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb" integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg== @@ -5699,7 +6118,7 @@ resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== -"@webassemblyjs/wasm-edit@^1.12.1": +"@webassemblyjs/wasm-edit@^1.11.5", "@webassemblyjs/wasm-edit@^1.12.1": version "1.12.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b" integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g== @@ -5734,7 +6153,7 @@ "@webassemblyjs/wasm-gen" "1.12.1" "@webassemblyjs/wasm-parser" "1.12.1" -"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.12.1": +"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.11.5", "@webassemblyjs/wasm-parser@^1.12.1": version "1.12.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937" integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ== @@ -5825,10 +6244,10 @@ js-yaml "^3.10.0" tslib "^2.4.0" -"@zeit/schemas@2.29.0": - version "2.29.0" - resolved "https://registry.yarnpkg.com/@zeit/schemas/-/schemas-2.29.0.tgz#a59ae6ebfdf4ddc66a876872dd736baa58b6696c" - integrity sha512-g5QiLIfbg3pLuYUJPlisNKY+epQJTcMDsOnVNkscrDP1oi7vmJnzOANYJI/1pZcVJ6umUkBv3aFtlg1UvUHGzA== +"@zeit/schemas@2.36.0": + version "2.36.0" + resolved "https://registry.yarnpkg.com/@zeit/schemas/-/schemas-2.36.0.tgz#7a1b53f4091e18d0b404873ea3e3c83589c765f2" + integrity sha512-7kjMwcChYEzMKjeex9ZFXkt1AyNov9R5HZtjBKVsmVpw7pa7ZtlCGvCBC2vnnXctaYN+aRI61HjIqeetZW5ROg== "@zkochan/js-yaml@0.0.6": version "0.0.6" @@ -5886,7 +6305,12 @@ acorn-import-assertions@^1.9.0: resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== -acorn-jsx@^5.0.0, acorn-jsx@^5.0.1, acorn-jsx@^5.3.1: +acorn-import-attributes@^1.9.5: + version "1.9.5" + resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef" + integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ== + +acorn-jsx@^5.0.1, acorn-jsx@^5.3.1, acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== @@ -5906,24 +6330,26 @@ acorn-walk@^7.0.0, acorn-walk@^7.2.0: integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== acorn-walk@^8.0.0, acorn-walk@^8.0.2: - version "8.3.2" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" - integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== + version "8.3.3" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.3.tgz#9caeac29eefaa0c41e3d4c65137de4d6f34df43e" + integrity sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw== + dependencies: + acorn "^8.11.0" -acorn@^6.0.7, acorn@^6.1.1: +acorn@^6.1.1: version "6.4.2" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== -acorn@^7.0.0, acorn@^7.4.0, acorn@^7.4.1: +acorn@^7.0.0, acorn@^7.4.1: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.0.4, acorn@^8.1.0, acorn@^8.11.3, acorn@^8.7.1, acorn@^8.8.1, acorn@^8.8.2: - version "8.11.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" - integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== +acorn@^8.0.4, acorn@^8.1.0, acorn@^8.11.0, acorn@^8.11.3, acorn@^8.7.1, acorn@^8.8.1, acorn@^8.8.2, acorn@^8.9.0: + version "8.12.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.0.tgz#1627bfa2e058148036133b8d9b51a700663c294c" + integrity sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw== add-stream@^1.0.0: version "1.0.0" @@ -5936,9 +6362,9 @@ address@^1.0.1, address@^1.1.2: integrity sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA== adm-zip@^0.5.10: - version "0.5.12" - resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.5.12.tgz#87786328e91d54b37358d8a50f954c4cd73ba60b" - integrity sha512-6TVU49mK6KZb4qG6xWaaM4C7sA/sgUMLy/JYMOzkcp3BvVLpW0fXDFQiIzAuxFCt/2+xD7fNIiPFAoLZPhVNLQ== + version "0.5.14" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.5.14.tgz#2c557c0bf12af4311cf6d32970f4060cf8133b2a" + integrity sha512-DnyqqifT4Jrcvb8USYjp6FHtBpEIz1mnXu6pTRHZ0RL69LbQYiO+0lDFg5+OKA7U29oWSs3a/i8fhn8ZcceIWg== agent-base@5: version "5.1.1" @@ -6006,17 +6432,17 @@ ajv-keywords@^5.1.0: dependencies: fast-deep-equal "^3.1.3" -ajv@8.11.0: - version "8.11.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.0.tgz#977e91dd96ca669f54a11e23e378e33b884a565f" - integrity sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg== +ajv@8.12.0: + version "8.12.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" + integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== dependencies: fast-deep-equal "^3.1.1" json-schema-traverse "^1.0.0" require-from-string "^2.0.2" uri-js "^4.2.2" -ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5, ajv@^6.9.1, ajv@~6.12.6: +ajv@^6.1.0, ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5, ajv@~6.12.6: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -6026,20 +6452,20 @@ ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5, ajv json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.0.0, ajv@^8.0.1, ajv@^8.6.0, ajv@^8.9.0: - version "8.12.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" - integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== +ajv@^8.0.0, ajv@^8.6.0, ajv@^8.9.0: + version "8.16.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.16.0.tgz#22e2a92b94f005f7e0f9c9d39652ef0b8f6f0cb4" + integrity sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw== dependencies: - fast-deep-equal "^3.1.1" + fast-deep-equal "^3.1.3" json-schema-traverse "^1.0.0" require-from-string "^2.0.2" - uri-js "^4.2.2" + uri-js "^4.4.1" algoliasearch-helper@^3.10.0: - version "3.17.0" - resolved "https://registry.yarnpkg.com/algoliasearch-helper/-/algoliasearch-helper-3.17.0.tgz#b8f2f98c9a49d9affb51205f8df116164050a842" - integrity sha512-R5422OiQjvjlK3VdpNQ/Qk7KsTIGeM5ACm8civGifOVWdRRV/3SgXuKmeNxe94Dz6fwj/IgpVmXbHutU4mHubg== + version "3.22.0" + resolved "https://registry.yarnpkg.com/algoliasearch-helper/-/algoliasearch-helper-3.22.0.tgz#d639e14c2eca201c1c8367be3e1a0e316bc32238" + integrity sha512-ZIVcE0929m2g00GuMiRWpemsGW3589qYxIcQonB7ms4B/KoeS94OiqPRMJ9hGoL23SlYJOmMNjZyXSoItDXO1w== dependencies: "@algolia/events" "^4.0.1" @@ -6076,7 +6502,7 @@ ansi-colors@^4.1.1: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== -ansi-escapes@^3.0.0, ansi-escapes@^3.2.0: +ansi-escapes@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== @@ -6093,6 +6519,11 @@ ansi-html-community@0.0.8, ansi-html-community@^0.0.8: resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw== +ansi-html@^0.0.9: + version "0.0.9" + resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.9.tgz#6512d02342ae2cc68131952644a129cb734cd3f0" + integrity sha512-ozbS3LuenHVxNRh/wdnN16QapUHzauqSomAl1jwwJRRsGwFwtj644lIhxfWu0Fy0acCij2+AEgHvjscq3dlVXg== + ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -6103,7 +6534,7 @@ ansi-regex@^3.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== -ansi-regex@^4.0.0, ansi-regex@^4.1.0: +ansi-regex@^4.0.0: version "4.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== @@ -6207,6 +6638,13 @@ aria-hidden@^1.1.1: dependencies: tslib "^2.0.0" +aria-query@5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.1.3.tgz#19db27cd101152773631396f7a95a3b58c22c35e" + integrity sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ== + dependencies: + deep-equal "^2.0.5" + aria-query@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e" @@ -6214,7 +6652,7 @@ aria-query@^5.3.0: dependencies: dequal "^2.0.3" -array-buffer-byte-length@^1.0.1: +array-buffer-byte-length@^1.0.0, array-buffer-byte-length@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz#1e5583ec16763540a27ae52eed99ff899223568f" integrity sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg== @@ -6242,7 +6680,7 @@ array-ify@^1.0.0: resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" integrity sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng== -array-includes@^3.1.6, array-includes@^3.1.7: +array-includes@^3.1.6, array-includes@^3.1.7, array-includes@^3.1.8: version "3.1.8" resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.8.tgz#5e370cbe172fdd5dd6530c1d4aadda25281ba97d" integrity sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ== @@ -6287,7 +6725,7 @@ array.prototype.find@^2.1.1: es-object-atoms "^1.0.0" es-shim-unscopables "^1.0.2" -array.prototype.findlast@^1.2.4: +array.prototype.findlast@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz#3e4fbcb30a15a7f5bf64cf2faae22d139c2e4904" integrity sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ== @@ -6355,14 +6793,14 @@ array.prototype.toreversed@^1.1.2: es-shim-unscopables "^1.0.0" array.prototype.tosorted@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz#c8c89348337e51b8a3c48a9227f9ce93ceedcba8" - integrity sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg== + version "1.1.4" + resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz#fe954678ff53034e717ea3352a03f0b0b86f7ffc" + integrity sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA== dependencies: - call-bind "^1.0.5" + call-bind "^1.0.7" define-properties "^1.2.1" - es-abstract "^1.22.3" - es-errors "^1.1.0" + es-abstract "^1.23.3" + es-errors "^1.3.0" es-shim-unscopables "^1.0.2" arraybuffer.prototype.slice@^1.0.3: @@ -6429,11 +6867,6 @@ ast-types@^0.16.1: dependencies: tslib "^2.0.1" -astral-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== - astral-regex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" @@ -6496,9 +6929,9 @@ aws-sign2@~0.7.0: integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== aws4@^1.8.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3" - integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg== + version "1.13.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.13.0.tgz#d9b802e9bb9c248d7be5f7f5ef178dc3684e9dcc" + integrity sha512-3AungXC4I8kKsS9PuS4JH2nc+0bVY/mjgrephHTIi8fpEeGsTHBUJeosp0Wc1myYMElmD0B3Oc4XL/HVJ4PV2g== axe-core@=4.7.0: version "4.7.0" @@ -6512,13 +6945,6 @@ axios@^0.25.0: dependencies: follow-redirects "^1.14.7" -axios@^0.26.1: - version "0.26.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.26.1.tgz#1ede41c51fcf51bbbd6fd43669caaa4f0495aaa9" - integrity sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA== - dependencies: - follow-redirects "^1.14.8" - axios@^0.27.2: version "0.27.2" resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972" @@ -6527,10 +6953,19 @@ axios@^0.27.2: follow-redirects "^1.14.9" form-data "^4.0.0" +axios@^0.28.0: + version "0.28.1" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.28.1.tgz#2a7bcd34a3837b71ee1a5ca3762214b86b703e70" + integrity sha512-iUcGA5a7p0mVb4Gm/sy+FSECNkPFT4y7wt6OM/CDpO/OnNCvSs3PoMG8ibrC9jRoGYU0gUK5pXVC4NPXq6lHRQ== + dependencies: + follow-redirects "^1.15.0" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + axios@^1.0.0: - version "1.6.8" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.8.tgz#66d294951f5d988a00e87a0ffb955316a619ea66" - integrity sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ== + version "1.7.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.2.tgz#b625db8a7051fbea61c35a3cbb3a1daa7b9c7621" + integrity sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw== dependencies: follow-redirects "^1.15.6" form-data "^4.0.0" @@ -6631,20 +7066,9 @@ babel-plugin-dynamic-import-node@^2.3.3: babel-plugin-extract-import-names@1.6.22: version "1.6.22" resolved "https://registry.yarnpkg.com/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz#de5f9a28eb12f3eb2578bf74472204e66d1a13dc" - integrity sha512-yJ9BsJaISua7d8zNT7oRG1ZLBJCIdZ4PZqmH8qa9N5AK01ifk3fnkc98AXhtzE7UkfCsEumvoQWgoYLhOnJ7jQ== - dependencies: - "@babel/helper-plugin-utils" "7.10.4" - -babel-plugin-inline-react-svg@^2.0.1, babel-plugin-inline-react-svg@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/babel-plugin-inline-react-svg/-/babel-plugin-inline-react-svg-2.0.2.tgz#3a7bc4dc791c2d809a54d43f1a5ac53f3be8acb9" - integrity sha512-iM9obPpCcdPE1EJE+UF+tni7CZ4q/OvdDm/TeBBHAYAEOqDcFd7fdnmym6OYAQMYfEpUnRYUYx2KxSUyo4cQxQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/parser" "^7.0.0" - lodash.isplainobject "^4.0.6" - resolve "^2.0.0-next.4" - svgo "^2.8.0" + integrity sha512-yJ9BsJaISua7d8zNT7oRG1ZLBJCIdZ4PZqmH8qa9N5AK01ifk3fnkc98AXhtzE7UkfCsEumvoQWgoYLhOnJ7jQ== + dependencies: + "@babel/helper-plugin-utils" "7.10.4" babel-plugin-istanbul@^6.1.1: version "6.1.1" @@ -6677,23 +7101,23 @@ babel-plugin-macros@^3.1.0: resolve "^1.19.0" babel-plugin-module-resolver@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/babel-plugin-module-resolver/-/babel-plugin-module-resolver-5.0.0.tgz#2b7fc176bd55da25f516abf96015617b4f70fc73" - integrity sha512-g0u+/ChLSJ5+PzYwLwP8Rp8Rcfowz58TJNCe+L/ui4rpzE/mg//JVX0EWBUYoxaextqnwuGHzfGp2hh0PPV25Q== + version "5.0.2" + resolved "https://registry.yarnpkg.com/babel-plugin-module-resolver/-/babel-plugin-module-resolver-5.0.2.tgz#cdeac5d4aaa3b08dd1ac23ddbf516660ed2d293e" + integrity sha512-9KtaCazHee2xc0ibfqsDeamwDps6FZNo5S0Q81dUqEuFzVwPhcT4J5jOqIVvgCA3Q/wO9hKYxN/Ds3tIsp5ygg== dependencies: - find-babel-config "^2.0.0" - glob "^8.0.3" + find-babel-config "^2.1.1" + glob "^9.3.3" pkg-up "^3.1.0" reselect "^4.1.7" - resolve "^1.22.1" + resolve "^1.22.8" babel-plugin-polyfill-corejs2@^0.4.10, babel-plugin-polyfill-corejs2@^0.4.6: - version "0.4.10" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.10.tgz#276f41710b03a64f6467433cab72cbc2653c38b1" - integrity sha512-rpIuu//y5OX6jVU+a5BCn1R5RSZYWAl2Nar76iwaOdycqb6JPxediskWFMMl7stfwNJR4b7eiQvh5fB5TEQJTQ== + version "0.4.11" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz#30320dfe3ffe1a336c15afdcdafd6fd615b25e33" + integrity sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q== dependencies: "@babel/compat-data" "^7.22.6" - "@babel/helper-define-polyfill-provider" "^0.6.1" + "@babel/helper-define-polyfill-provider" "^0.6.2" semver "^6.3.1" babel-plugin-polyfill-corejs3@^0.10.1, babel-plugin-polyfill-corejs3@^0.10.4: @@ -6720,11 +7144,11 @@ babel-plugin-polyfill-regenerator@^0.5.3: "@babel/helper-define-polyfill-provider" "^0.5.0" babel-plugin-polyfill-regenerator@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.1.tgz#4f08ef4c62c7a7f66a35ed4c0d75e30506acc6be" - integrity sha512-JfTApdE++cgcTWjsiCQlLyFBMbTUft9ja17saCc93lgV33h4tuCVj7tlvu//qpLwaG+3yEz7/KhahGrUMkVq9g== + version "0.6.2" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz#addc47e240edd1da1058ebda03021f382bba785e" + integrity sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg== dependencies: - "@babel/helper-define-polyfill-provider" "^0.6.1" + "@babel/helper-define-polyfill-provider" "^0.6.2" babel-preset-current-node-syntax@^1.0.0: version "1.0.1" @@ -6768,31 +7192,38 @@ balanced-match@^1.0.0: integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== bare-events@^2.0.0, bare-events@^2.2.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/bare-events/-/bare-events-2.2.2.tgz#a98a41841f98b2efe7ecc5c5468814469b018078" - integrity sha512-h7z00dWdG0PYOQEvChhOSWvOfkIKsdZGkWr083FgN/HyoQuebSew/cgirYqh9SCuy/hRvxc5Vy6Fw8xAmYHLkQ== + version "2.4.2" + resolved "https://registry.yarnpkg.com/bare-events/-/bare-events-2.4.2.tgz#3140cca7a0e11d49b3edc5041ab560659fd8e1f8" + integrity sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q== bare-fs@^2.1.1: - version "2.2.3" - resolved "https://registry.yarnpkg.com/bare-fs/-/bare-fs-2.2.3.tgz#34f8b81b8c79de7ef043383c05e57d4a10392a68" - integrity sha512-amG72llr9pstfXOBOHve1WjiuKKAMnebcmMbPWDZ7BCevAoJLpugjuAPRsDINEyjT0a6tbaVx3DctkXIRbLuJw== + version "2.3.1" + resolved "https://registry.yarnpkg.com/bare-fs/-/bare-fs-2.3.1.tgz#cdbd63dac7a552dfb2b87d18c822298d1efd213d" + integrity sha512-W/Hfxc/6VehXlsgFtbB5B4xFcsCl+pAh30cYhoFyXErf6oGrwjh8SwiPAdHgpmWonKuYpZgGywN0SXt7dgsADA== dependencies: bare-events "^2.0.0" bare-path "^2.0.0" - streamx "^2.13.0" + bare-stream "^2.0.0" bare-os@^2.1.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/bare-os/-/bare-os-2.2.1.tgz#c94a258c7a408ca6766399e44675136c0964913d" - integrity sha512-OwPyHgBBMkhC29Hl3O4/YfxW9n7mdTr2+SsO29XBWKKJsbgj3mnorDB80r5TiCQgQstgE5ga1qNYrpes6NvX2w== + version "2.4.0" + resolved "https://registry.yarnpkg.com/bare-os/-/bare-os-2.4.0.tgz#5de5e3ba7704f459c9656629edca7cc736e06608" + integrity sha512-v8DTT08AS/G0F9xrhyLtepoo9EJBJ85FRSMbu1pQUlAf6A8T0tEEQGMVObWeqpjhSPXsE0VGlluFBJu2fdoTNg== bare-path@^2.0.0, bare-path@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/bare-path/-/bare-path-2.1.1.tgz#111db5bf2db0aed40081aa4ba38b8dfc2bb782eb" - integrity sha512-OHM+iwRDRMDBsSW7kl3dO62JyHdBKO3B25FB9vNQBPcGHMo4+eA8Yj41Lfbk3pS/seDY+siNge0LdRTulAau/A== + version "2.1.3" + resolved "https://registry.yarnpkg.com/bare-path/-/bare-path-2.1.3.tgz#594104c829ef660e43b5589ec8daef7df6cedb3e" + integrity sha512-lh/eITfU8hrj9Ru5quUp0Io1kJWIk1bTjzo7JH1P5dWmQ2EL4hFUlfI8FonAhSlgIfhn63p84CDY/x+PisgcXA== dependencies: bare-os "^2.1.0" +bare-stream@^2.0.0: + version "2.1.3" + resolved "https://registry.yarnpkg.com/bare-stream/-/bare-stream-2.1.3.tgz#070b69919963a437cc9e20554ede079ce0a129b2" + integrity sha512-tiDAH9H/kP+tvNO5sczyn9ZAA7utrSMobyDchsnyyXBuUe2FSQWbxhtuHB8jwpHYYevVo2UJpcmvvjrbHboUUQ== + dependencies: + streamx "^2.18.0" + base16@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/base16/-/base16-1.0.0.tgz#e297f60d7ec1014a7a971a39ebc8a98c0b681e70" @@ -6973,12 +7404,12 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" -braces@^3.0.2, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== +braces@^3.0.3, braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== dependencies: - fill-range "^7.0.1" + fill-range "^7.1.1" brcast@^2.0.2: version "2.0.2" @@ -7004,15 +7435,15 @@ browserify-zlib@^0.1.4: dependencies: pako "~0.2.0" -browserslist@^4.0.0, browserslist@^4.18.1, browserslist@^4.21.10, browserslist@^4.21.4, browserslist@^4.22.2, browserslist@^4.23.0: - version "4.23.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab" - integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== +browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.18.1, browserslist@^4.21.10, browserslist@^4.21.4, browserslist@^4.22.2, browserslist@^4.23.0: + version "4.23.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.1.tgz#ce4af0534b3d37db5c1a4ca98b9080f985041e96" + integrity sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw== dependencies: - caniuse-lite "^1.0.30001587" - electron-to-chromium "^1.4.668" + caniuse-lite "^1.0.30001629" + electron-to-chromium "^1.4.796" node-releases "^2.0.14" - update-browserslist-db "^1.0.13" + update-browserslist-db "^1.0.16" bser@2.1.1: version "2.1.1" @@ -7243,10 +7674,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001587, caniuse-lite@^1.0.30001599: - version "1.0.30001608" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001608.tgz#7ae6e92ffb300e4b4ec2f795e0abab456ec06cc0" - integrity sha512-cjUJTQkk9fQlJR2s4HMuPMvTiRggl0rAVMtthQuyOlDWuqHXqN8azLq+pi8B2TjwKJ32diHjUqRIKeFX4z1FoA== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001599, caniuse-lite@^1.0.30001629: + version "1.0.30001636" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001636.tgz#b15f52d2bdb95fad32c2f53c0b68032b85188a78" + integrity sha512-bMg2vmr8XBsbL6Lr0UHXy/21m84FTxDLWn2FSqMd5PrlbMxwJlQnC2YWYxVgp66PZE+BBNF2jYQUBKCo1FDeZg== case-sensitive-paths-webpack-plugin@^2.4.0: version "2.4.0" @@ -7416,9 +7847,9 @@ chownr@^2.0.0: integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== chrome-trace-event@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" - integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== + version "1.0.4" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz#05bffd7ff928465093314708c93bdfa9bd1f0f5b" + integrity sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ== ci-info@^2.0.0: version "2.0.0" @@ -7438,11 +7869,18 @@ citty@^0.1.6: consola "^3.2.3" cjs-module-lexer@^1.0.0, cjs-module-lexer@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" - integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== + version "1.3.1" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz#c485341ae8fd999ca4ee5af2d7a1c9ae01e0099c" + integrity sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q== + +class-variance-authority@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/class-variance-authority/-/class-variance-authority-0.7.0.tgz#1c3134d634d80271b1837452b06d821915954522" + integrity sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A== + dependencies: + clsx "2.0.0" -classnames@^2.2.5, classnames@^2.3.2: +classnames@^2.3.2: version "2.5.1" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b" integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow== @@ -7509,9 +7947,9 @@ cli-spinners@^2.5.0: integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== cli-table3@^0.6.1, cli-table3@^0.6.2, cli-table3@~0.6.1: - version "0.6.4" - resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.4.tgz#d1c536b8a3f2e7bec58f67ac9e5769b1b30088b0" - integrity sha512-Lm3L0p+/npIQWNIiyF/nAn7T5dnOwR3xNTHXYEBFBFVPXzCVNZ5lqEC/1eo/EVfpDsQ1I+TX4ORPQgp+UI0CRw== + version "0.6.5" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.5.tgz#013b91351762739c16a9567c21a04632e449bf2f" + integrity sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ== dependencies: string-width "^4.2.0" optionalDependencies: @@ -7533,11 +7971,6 @@ cli-truncate@^2.1.0: slice-ansi "^3.0.0" string-width "^4.2.0" -cli-width@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" - integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== - cli-width@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" @@ -7584,6 +8017,16 @@ clone@^1.0.2: resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== +clsx@*, clsx@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999" + integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== + +clsx@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.0.0.tgz#12658f3fd98fafe62075595a5c30e43d18f3d00b" + integrity sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q== + clsx@^1.1.1, clsx@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" @@ -7594,6 +8037,14 @@ cmd-shim@6.0.1: resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-6.0.1.tgz#a65878080548e1dca760b3aea1e21ed05194da9d" integrity sha512-S9iI9y0nKR4hwEQsVWpyxld/6kRfGepGfzff83FcaiEBpmvlbA2nnGe7Cylgrx2f/p1P5S5wpRm9oL8z1PbS3Q== +cmdk@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cmdk/-/cmdk-1.0.0.tgz#0a095fdafca3dfabed82d1db78a6262fb163ded9" + integrity sha512-gDzVf0a09TvoJ5jnuPvygTB77+XdOSwEmJ88L6XPFPlv7T3RxbP9jgenfylrAMD0+Le1aO0nVjQUzl2g+vjz5Q== + dependencies: + "@radix-ui/react-dialog" "1.0.5" + "@radix-ui/react-primitive" "1.0.3" + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -8015,27 +8466,27 @@ copy-webpack-plugin@^9.0.1: serialize-javascript "^6.0.0" core-js-compat@^3.31.0, core-js-compat@^3.33.1, core-js-compat@^3.36.1: - version "3.36.1" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.36.1.tgz#1818695d72c99c25d621dca94e6883e190cea3c8" - integrity sha512-Dk997v9ZCt3X/npqzyGdTlq6t7lDBhZwGvV94PKzDArjp7BTRm7WlDAXYd/OWdeFHO8OChQYRJNJvUCqCbrtKA== + version "3.37.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.37.1.tgz#c844310c7852f4bdf49b8d339730b97e17ff09ee" + integrity sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg== dependencies: browserslist "^4.23.0" core-js-pure@^3.23.3, core-js-pure@^3.30.2: - version "3.36.1" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.36.1.tgz#1461c89e76116528b54eba20a0aff30164087a94" - integrity sha512-NXCvHvSVYSrewP0L5OhltzXeWFJLo2AL2TYnj6iLV3Bw8mM62wAQMNgUCRI6EBu6hVVpbCxmOPlxh1Ikw2PfUA== + version "3.37.1" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.37.1.tgz#2b4b34281f54db06c9a9a5bd60105046900553bd" + integrity sha512-J/r5JTHSmzTxbiYYrzXg9w1VpqrYt+gexenBE9pugeyhwPZTAEJddyiReJWsLO6uNQ8xJZFbod6XC7KKwatCiA== + +core-js@*, core-js@^3.2.1, core-js@^3.23.3, core-js@^3.8.3: + version "3.37.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.37.1.tgz#d21751ddb756518ac5a00e4d66499df981a62db9" + integrity sha512-Xn6qmxrQZyB0FFY8E3bgRXei3lWDJHhvI+u0q9TKIYM49G8pAr0FgnnrFRAmsbptZL1yxRADVXn+x5AGsbBfyw== core-js@^2.4.1, core-js@^2.5.7, core-js@^2.6.12: version "2.6.12" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== -core-js@^3.16.1, core-js@^3.2.1, core-js@^3.23.3, core-js@^3.8.3: - version "3.36.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.36.1.tgz#c97a7160ebd00b2de19e62f4bbd3406ab720e578" - integrity sha512-BTvUrwxVBezj5SZ3f10ImnX2oRByMxql3EimVqMysepbC9EeMUOpLwdy6Eoili2x6E4kf+ZUB5k/+Jv55alPfA== - core-util-is@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -8083,7 +8534,7 @@ cosmiconfig@^7.0.0, cosmiconfig@^7.0.1: path-type "^4.0.0" yaml "^1.10.0" -cosmiconfig@^8.2.0, cosmiconfig@^8.3.5: +cosmiconfig@^8.1.3, cosmiconfig@^8.2.0, cosmiconfig@^8.3.5: version "8.3.6" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz#060a2b871d66dba6c8538ea1118ba1ac16f5fae3" integrity sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA== @@ -8275,6 +8726,22 @@ css-tree@^1.1.2, css-tree@^1.1.3: mdn-data "2.0.14" source-map "^0.6.1" +css-tree@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-2.3.1.tgz#10264ce1e5442e8572fc82fbe490644ff54b5c20" + integrity sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw== + dependencies: + mdn-data "2.0.30" + source-map-js "^1.0.1" + +css-tree@~2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-2.2.1.tgz#36115d382d60afd271e377f9c5f67d02bd48c032" + integrity sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA== + dependencies: + mdn-data "2.0.28" + source-map-js "^1.0.1" + css-what@^3.2.1: version "3.4.2" resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.4.2.tgz#ea7026fcb01777edbde52124e21f327e7ae950e4" @@ -8373,6 +8840,13 @@ csso@^4.0.2, csso@^4.2.0: dependencies: css-tree "^1.1.2" +csso@^5.0.5: + version "5.0.5" + resolved "https://registry.yarnpkg.com/csso/-/csso-5.0.5.tgz#f9b7fe6cc6ac0b7d90781bb16d5e9874303e2ca6" + integrity sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ== + dependencies: + css-tree "~2.2.0" + cssom@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.5.0.tgz#d254fa92cd8b6fbd83811b9fbaed34663cc17c36" @@ -8635,31 +9109,25 @@ date-fns@^1.27.2: resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw== +date-fns@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-3.6.0.tgz#f20ca4fe94f8b754951b24240676e8618c0206bf" + integrity sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww== + dateformat@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== dayjs@^1.10.4: - version "1.11.10" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.10.tgz#68acea85317a6e164457d6d6947564029a6a16a0" - integrity sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ== - -dcmjs@^0.27: - version "0.27.0" - resolved "https://registry.yarnpkg.com/dcmjs/-/dcmjs-0.27.0.tgz#2662818c8b20494e366583e6dd3577c20d04d6ff" - integrity sha512-26wtatOLh+0b0aFy9iOg7PdOLG9EHevn9nEOn7Aoo5l7P9aFAMZ3XAa9Q+NULzLE2Q7DcIf2TQvfyVtdzhQzeg== - dependencies: - "@babel/runtime-corejs2" "^7.17.8" - gl-matrix "^3.1.0" - lodash.clonedeep "^4.5.0" - loglevelnext "^3.0.1" - ndarray "^1.0.19" + version "1.11.11" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.11.tgz#dfe0e9d54c5f8b68ccf8ca5f72ac603e7e5ed59e" + integrity sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg== -dcmjs@^0.29.12, dcmjs@^0.29.8: - version "0.29.13" - resolved "https://registry.yarnpkg.com/dcmjs/-/dcmjs-0.29.13.tgz#a74df541bf3948366b25630dbe1e8376f108ea3b" - integrity sha512-Bf9tKzJNWqk4kbV210N5TLEHDqaZvO3S+MH9vezFAU8WKcG4cR6z4/II3TQVqhLI185eNUL+lhfPCVH1Uu2yTA== +dcmjs@*, dcmjs@>=0.33.0, dcmjs@^0.29.8: + version "0.33.0" + resolved "https://registry.yarnpkg.com/dcmjs/-/dcmjs-0.33.0.tgz#e4387056fcd4f5a40be1f76f2441bf0b2b58c514" + integrity sha512-8QfVA+TeuuKoVyhkJo/iCFDnpiNGDDrRQdM/tsi7gm1a/gNt4yYUBXLDho+CmVgvsaKccv7UMZBrGfmVDfNLvg== dependencies: "@babel/runtime-corejs3" "^7.22.5" adm-zip "^0.5.10" @@ -8686,7 +9154,14 @@ debug@2.6.9, debug@^2.6.0, debug@^2.6.9: dependencies: ms "2.0.0" -debug@4, debug@4.3.4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: +debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: + version "4.3.5" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" + integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== + dependencies: + ms "2.1.2" + +debug@4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -8759,12 +9234,36 @@ deep-equal@^1.0.1: object-keys "^1.1.1" regexp.prototype.flags "^1.5.1" +deep-equal@^2.0.5: + version "2.2.3" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.2.3.tgz#af89dafb23a396c7da3e862abc0be27cf51d56e1" + integrity sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA== + dependencies: + array-buffer-byte-length "^1.0.0" + call-bind "^1.0.5" + es-get-iterator "^1.1.3" + get-intrinsic "^1.2.2" + is-arguments "^1.1.1" + is-array-buffer "^3.0.2" + is-date-object "^1.0.5" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + isarray "^2.0.5" + object-is "^1.1.5" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.5.1" + side-channel "^1.0.4" + which-boxed-primitive "^1.0.2" + which-collection "^1.0.1" + which-typed-array "^1.1.13" + deep-extend@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== -deep-is@^0.1.3, deep-is@~0.1.3: +deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== @@ -8774,7 +9273,7 @@ deepmerge@^1.5.2: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-1.5.2.tgz#10499d868844cdad4fee0842df8c7f6f0c95a753" integrity sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ== -deepmerge@^4.2.2: +deepmerge@^4.2.2, deepmerge@^4.3.1: version "4.3.1" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== @@ -8994,9 +9493,9 @@ detect-port-alt@^1.1.6: debug "^2.6.0" detect-port@^1.3.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.5.1.tgz#451ca9b6eaf20451acb0799b8ab40dff7718727b" - integrity sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ== + version "1.6.1" + resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.6.1.tgz#45e4073997c5f292b957cb678fb0bb8ed4250a67" + integrity sha512-CmnVc+Hek2egPx1PeTFVta2W78xy2K/9Rkf6cC4T59S50tVnzKj+tnx5mmx5lwvCkujZ4uRrpRSuV+IVs3f90Q== dependencies: address "^1.0.1" debug "4" @@ -9010,18 +9509,19 @@ detective@^5.2.1: defined "^1.0.0" minimist "^1.2.6" -dicom-microscopy-viewer@^0.44.0: - version "0.44.0" - resolved "https://registry.yarnpkg.com/dicom-microscopy-viewer/-/dicom-microscopy-viewer-0.44.0.tgz#d4a9e985acb23c5b82a9aedbe379b39198b8fd55" - integrity sha512-7rcm8bXTcOLsXrhBPwWe5gf4Sj1Rz1lRh+ECcaznOEr/uvX6BTAYLqNJNmeAUMoKcadboEeDrmLihCwCteRSJQ== +dicom-microscopy-viewer@^0.46.1: + version "0.46.1" + resolved "https://registry.yarnpkg.com/dicom-microscopy-viewer/-/dicom-microscopy-viewer-0.46.1.tgz#33405d8cbe0e5d51dfe515af9c9742d2efbb1a23" + integrity sha512-QLozX/iM6ZA0TxheHQnTNiLg+RbSVlxYKMNG9qdqV5oNbEDOf+z4/8mDqnAQ8wjlQXE2MbUDX8JRa0LmO9mDTg== dependencies: - "@cornerstonejs/codec-charls" "^0.1.1" - "@cornerstonejs/codec-libjpeg-turbo-8bit" "^0.0.7" - "@cornerstonejs/codec-openjpeg" "^0.1.1" + "@cornerstonejs/codec-charls" "^1.2.3" + "@cornerstonejs/codec-libjpeg-turbo-8bit" "^1.2.2" + "@cornerstonejs/codec-openjpeg" "^1.2.2" + "@cornerstonejs/codec-openjph" "^2.4.5" colormap "^2.3" - dcmjs "^0.27" + dcmjs "^0.29.8" dicomicc "^0.1" - dicomweb-client "^0.8" + dicomweb-client "^0.8.4" image-type "^4.1" mathjs "^11.2" ol "^7.1" @@ -9037,16 +9537,11 @@ dicomicc@^0.1: resolved "https://registry.yarnpkg.com/dicomicc/-/dicomicc-0.1.0.tgz#c73acc60a8e2d73a20f462c8c7d0e1e0d977c486" integrity sha512-kZejPGjLQ9NsgovSyVsiAuCpq6LofNR9Erc8Tt/vQAYGYCoQnTyWDlg5D0TJJQATKul7cSr9k/q0TF8G9qdDkQ== -dicomweb-client@^0.10.4: +dicomweb-client@>=0.10.4, dicomweb-client@^0.10.4, dicomweb-client@^0.8.4: version "0.10.4" resolved "https://registry.yarnpkg.com/dicomweb-client/-/dicomweb-client-0.10.4.tgz#f32f8659e51fbaf3f924c81fe8b7ad80297f2bc5" integrity sha512-TEt26c0JI37IGmSqoj1k1/Y/ZIyq33/ysVaUwE0/Haosn2IBM55NEIPkT+AnhFss2nFAMVtKKWKWLox4luthVw== -dicomweb-client@^0.8: - version "0.8.4" - resolved "https://registry.yarnpkg.com/dicomweb-client/-/dicomweb-client-0.8.4.tgz#3da814cedb9415facb50bc5f43af8d961a991c74" - integrity sha512-/6oY3/Fg9JyAlbTWuJOYbVqici3+nlZt43+Z/Y47RNiqLc028JcxNlY28u4VQqksxfB59f1hhNbsqsHyDT4vhw== - didyoumean@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037" @@ -9149,6 +9644,11 @@ docusaurus-plugin-image-zoom@^1.0.1: medium-zoom "^1.0.6" validate-peer-dependencies "^2.2.0" +dom-accessibility-api@^0.5.9: + version "0.5.16" + resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz#5a7429e6066eb3664d911e33fb0e45de8eb08453" + integrity sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg== + dom-converter@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" @@ -9198,11 +9698,6 @@ dom-serializer@^2.0.0: domhandler "^5.0.2" entities "^4.2.0" -dom-walk@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" - integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w== - dom7@^4.0.4: version "4.0.6" resolved "https://registry.yarnpkg.com/dom7/-/dom7-4.0.6.tgz#091a51621d7a19ce0fb86045cafb3c10035e97ed" @@ -9379,16 +9874,16 @@ ee-first@1.1.1: integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== ejs@^3.1.6, ejs@^3.1.7, ejs@^3.1.8: - version "3.1.9" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.9.tgz#03c9e8777fe12686a9effcef22303ca3d8eeb361" - integrity sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ== + version "3.1.10" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.10.tgz#69ab8358b14e896f80cc39e62087b88500c3ac3b" + integrity sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA== dependencies: jake "^10.8.5" -electron-to-chromium@^1.4.668: - version "1.4.733" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.733.tgz#708d51ce01a7ed3b401d5ced85e9f5d504fd4217" - integrity sha512-gUI9nhI2iBGF0OaYYLKOaOtliFMl+Bt1rY7VmEjwxOxqoYLub/D9xmduPEhbw2imE6gYkJKhIE5it+KE2ulVxQ== +electron-to-chromium@^1.4.796: + version "1.4.805" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.805.tgz#1d526e384c20944a3c68f618f9774edc384c4733" + integrity sha512-8W4UJwX/w9T0QSzINJckTKG6CYpAUTqsaWcWIsdud3I1FYJcMgW9QqT1/4CBff/pP/TihWh13OmiyY8neto6vw== elegant-spinner@^1.0.1: version "1.0.1" @@ -9400,11 +9895,6 @@ emittery@^0.13.1: resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== - emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -9453,15 +9943,15 @@ endent@^2.0.1: fast-json-parse "^1.0.3" objectorarray "^1.0.5" -enhanced-resolve@^5.16.0: - version "5.16.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz#65ec88778083056cb32487faa9aef82ed0864787" - integrity sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA== +enhanced-resolve@^5.15.0, enhanced-resolve@^5.17.0: + version "5.17.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz#d037603789dd9555b89aaec7eb78845c49089bc5" + integrity sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" -enquirer@^2.3.5, enquirer@^2.3.6: +enquirer@^2.3.6: version "2.4.1" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56" integrity sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ== @@ -9497,9 +9987,9 @@ envinfo@7.8.1: integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== envinfo@^7.7.3: - version "7.12.0" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.12.0.tgz#b56723b39c2053d67ea5714f026d05d4f5cc7acd" - integrity sha512-Iw9rQJBGpJRd3rwXm9ft/JiGoAZmLxxJZELYDQoPRZ4USVhkKtIcNBPw6U+/K2mBpaqM25JSV6Yl4Az9vO2wJg== + version "7.13.0" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.13.0.tgz#81fbb81e5da35d74e814941aeab7c325a606fb31" + integrity sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q== enzyme-shallow-equal@^1.0.0: version "1.0.7" @@ -9528,7 +10018,7 @@ error-stack-parser@^2.0.6: dependencies: stackframe "^1.3.4" -es-abstract@^1.17.2, es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.1, es-abstract@^1.23.2: +es-abstract@^1.17.2, es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.1, es-abstract@^1.23.2, es-abstract@^1.23.3: version "1.23.3" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0" integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A== @@ -9592,19 +10082,34 @@ es-define-property@^1.0.0: dependencies: get-intrinsic "^1.2.4" -es-errors@^1.1.0, es-errors@^1.2.1, es-errors@^1.3.0: +es-errors@^1.2.1, es-errors@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== -es-iterator-helpers@^1.0.15, es-iterator-helpers@^1.0.17: - version "1.0.18" - resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.18.tgz#4d3424f46b24df38d064af6fbbc89274e29ea69d" - integrity sha512-scxAJaewsahbqTYrGKJihhViaM6DDZDDoucfvzNbK0pOren1g/daDQ3IAhzn+1G14rBG7w+i5N+qul60++zlKA== +es-get-iterator@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.3.tgz#3ef87523c5d464d41084b2c3c9c214f1199763d6" + integrity sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + has-symbols "^1.0.3" + is-arguments "^1.1.1" + is-map "^2.0.2" + is-set "^2.0.2" + is-string "^1.0.7" + isarray "^2.0.5" + stop-iteration-iterator "^1.0.0" + +es-iterator-helpers@^1.0.15, es-iterator-helpers@^1.0.19: + version "1.0.19" + resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz#117003d0e5fec237b4b5c08aded722e0c6d50ca8" + integrity sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw== dependencies: call-bind "^1.0.7" define-properties "^1.2.1" - es-abstract "^1.23.0" + es-abstract "^1.23.3" es-errors "^1.3.0" es-set-tostringtag "^2.0.3" function-bind "^1.1.2" @@ -9618,9 +10123,9 @@ es-iterator-helpers@^1.0.15, es-iterator-helpers@^1.0.17: safe-array-concat "^1.1.2" es-module-lexer@^1.2.1, es-module-lexer@^1.4.1: - version "1.5.0" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.5.0.tgz#4878fee3789ad99e065f975fdd3c645529ff0236" - integrity sha512-pqrTKmwEIgafsYZAGw9kszYzmagcE/n4dbgwGWLEXg7J4QFJVQRBld8j3Q3GNez79jzxZshq0bcT962QHOghjw== + version "1.5.3" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.5.3.tgz#25969419de9c0b1fbe54279789023e8a9a788412" + integrity sha512-i1gCgmR9dCl6Vil6UKPI/trA69s08g/syhiDK9TG0Nf1RJjjFI+AzoWW7sPufzkgYAn861skuCwJa0pIIHYxvg== es-object-atoms@^1.0.0: version "1.0.0" @@ -9629,7 +10134,7 @@ es-object-atoms@^1.0.0: dependencies: es-errors "^1.3.0" -es-set-tostringtag@^2.0.3: +es-set-tostringtag@^2.0.1, es-set-tostringtag@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz#8bb60f0a440c2e4281962428438d58545af39777" integrity sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ== @@ -9694,7 +10199,7 @@ esbuild@^0.18.0: "@esbuild/win32-ia32" "0.18.20" "@esbuild/win32-x64" "0.18.20" -escalade@^3.1.1: +escalade@^3.1.1, escalade@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== @@ -9785,9 +10290,9 @@ eslint-module-utils@^2.8.0: debug "^3.2.7" eslint-plugin-cypress@^2.12.1: - version "2.15.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-cypress/-/eslint-plugin-cypress-2.15.1.tgz#336afa7e8e27451afaf65aa359c9509e0a4f3a7b" - integrity sha512-eLHLWP5Q+I4j2AWepYq0PgFEei9/s5LvjuSqWrxurkg1YZ8ltxdvMNmdSf0drnsNo57CTgYY/NIHHLRSWejR7w== + version "2.15.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-cypress/-/eslint-plugin-cypress-2.15.2.tgz#f22e12fad4c434edad7b298ef92bac8fa087ffa0" + integrity sha512-CtcFEQTDKyftpI22FVGpx8bkpKyYXBlNge6zSo0pl5/qJvBAnzaD76Vu2AsP16d6mTj478Ldn2mhgrWV+Xr0vQ== dependencies: globals "^13.20.0" @@ -9878,33 +10383,33 @@ eslint-plugin-promise@^5.2.0: integrity sha512-SftLb1pUG01QYq2A/hGAWfDRXqYD82zE7j7TopDOyNdU+7SvvoXREls/+PRTY17vUXzXnZA/zfnyKgRH6x4JJw== eslint-plugin-react-hooks@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3" - integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g== + version "4.6.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz#c829eb06c0e6f484b3fbb85a97e57784f328c596" + integrity sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ== eslint-plugin-react@^7.29.4: - version "7.34.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz#6806b70c97796f5bbfb235a5d3379ece5f4da997" - integrity sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw== + version "7.34.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.34.2.tgz#2780a1a35a51aca379d86d29b9a72adc6bfe6b66" + integrity sha512-2HCmrU+/JNigDN6tg55cRDKCQWicYAPB38JGSFDQt95jDm8rrvSUo7YPkOIm5l6ts1j1zCvysNcasvfTMQzUOw== dependencies: - array-includes "^3.1.7" - array.prototype.findlast "^1.2.4" + array-includes "^3.1.8" + array.prototype.findlast "^1.2.5" array.prototype.flatmap "^1.3.2" array.prototype.toreversed "^1.1.2" array.prototype.tosorted "^1.1.3" doctrine "^2.1.0" - es-iterator-helpers "^1.0.17" + es-iterator-helpers "^1.0.19" estraverse "^5.3.0" jsx-ast-utils "^2.4.1 || ^3.0.0" minimatch "^3.1.2" - object.entries "^1.1.7" - object.fromentries "^2.0.7" - object.hasown "^1.1.3" - object.values "^1.1.7" + object.entries "^1.1.8" + object.fromentries "^2.0.8" + object.hasown "^1.1.4" + object.values "^1.2.0" prop-types "^15.8.1" resolve "^2.0.0-next.5" semver "^6.3.1" - string.prototype.matchall "^4.0.10" + string.prototype.matchall "^4.0.11" eslint-plugin-tsdoc@^0.2.11: version "0.2.17" @@ -9922,7 +10427,7 @@ eslint-scope@3.7.1: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-scope@5.1.1, eslint-scope@^5.1.1: +eslint-scope@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== @@ -9930,39 +10435,27 @@ eslint-scope@5.1.1, eslint-scope@^5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-scope@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" - integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== - dependencies: - esrecurse "^4.1.0" - estraverse "^4.1.1" - -eslint-utils@^1.3.1: - version "1.4.3" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" - integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== +eslint-scope@^7.2.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== dependencies: - eslint-visitor-keys "^1.1.0" + esrecurse "^4.3.0" + estraverse "^5.2.0" -eslint-utils@^2.0.0, eslint-utils@^2.1.0: +eslint-utils@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== dependencies: eslint-visitor-keys "^1.1.0" -eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: +eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== -eslint-visitor-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" - integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== - -eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1: +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: version "3.4.3" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== @@ -9979,118 +10472,65 @@ eslint-webpack-plugin@^2.5.3: normalize-path "^3.0.0" schema-utils "^3.1.1" -eslint@^5.0.1: - version "5.16.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" - integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== - dependencies: - "@babel/code-frame" "^7.0.0" - ajv "^6.9.1" - chalk "^2.1.0" - cross-spawn "^6.0.5" - debug "^4.0.1" - doctrine "^3.0.0" - eslint-scope "^4.0.3" - eslint-utils "^1.3.1" - eslint-visitor-keys "^1.0.0" - espree "^5.0.1" - esquery "^1.0.1" - esutils "^2.0.2" - file-entry-cache "^5.0.1" - functional-red-black-tree "^1.0.1" - glob "^7.1.2" - globals "^11.7.0" - ignore "^4.0.6" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - inquirer "^6.2.2" - js-yaml "^3.13.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.11" - minimatch "^3.0.4" - mkdirp "^0.5.1" - natural-compare "^1.4.0" - optionator "^0.8.2" - path-is-inside "^1.0.2" - progress "^2.0.0" - regexpp "^2.0.1" - semver "^5.5.1" - strip-ansi "^4.0.0" - strip-json-comments "^2.0.1" - table "^5.2.3" - text-table "^0.2.0" - -eslint@^7.32.0: - version "7.32.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d" - integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA== - dependencies: - "@babel/code-frame" "7.12.11" - "@eslint/eslintrc" "^0.4.3" - "@humanwhocodes/config-array" "^0.5.0" - ajv "^6.10.0" +eslint@^8.39.0: + version "8.57.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668" + integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.6.1" + "@eslint/eslintrc" "^2.1.4" + "@eslint/js" "8.57.0" + "@humanwhocodes/config-array" "^0.11.14" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" + "@ungap/structured-clone" "^1.2.0" + ajv "^6.12.4" chalk "^4.0.0" cross-spawn "^7.0.2" - debug "^4.0.1" + debug "^4.3.2" doctrine "^3.0.0" - enquirer "^2.3.5" escape-string-regexp "^4.0.0" - eslint-scope "^5.1.1" - eslint-utils "^2.1.0" - eslint-visitor-keys "^2.0.0" - espree "^7.3.1" - esquery "^1.4.0" + eslint-scope "^7.2.2" + eslint-visitor-keys "^3.4.3" + espree "^9.6.1" + esquery "^1.4.2" esutils "^2.0.2" fast-deep-equal "^3.1.3" file-entry-cache "^6.0.1" - functional-red-black-tree "^1.0.1" - glob-parent "^5.1.2" - globals "^13.6.0" - ignore "^4.0.6" - import-fresh "^3.0.0" + find-up "^5.0.0" + glob-parent "^6.0.2" + globals "^13.19.0" + graphemer "^1.4.0" + ignore "^5.2.0" imurmurhash "^0.1.4" is-glob "^4.0.0" - js-yaml "^3.13.1" + is-path-inside "^3.0.3" + js-yaml "^4.1.0" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.4.1" lodash.merge "^4.6.2" - minimatch "^3.0.4" + minimatch "^3.1.2" natural-compare "^1.4.0" - optionator "^0.9.1" - progress "^2.0.0" - regexpp "^3.1.0" - semver "^7.2.1" - strip-ansi "^6.0.0" - strip-json-comments "^3.1.0" - table "^6.0.9" + optionator "^0.9.3" + strip-ansi "^6.0.1" text-table "^0.2.0" - v8-compile-cache "^2.0.3" -espree@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" - integrity sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A== - dependencies: - acorn "^6.0.7" - acorn-jsx "^5.0.0" - eslint-visitor-keys "^1.0.0" - -espree@^7.3.0, espree@^7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" - integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== +espree@^9.6.0, espree@^9.6.1: + version "9.6.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== dependencies: - acorn "^7.4.0" - acorn-jsx "^5.3.1" - eslint-visitor-keys "^1.3.0" + acorn "^8.9.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.0.1, esquery@^1.4.0: +esquery@^1.4.2: version "1.5.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== @@ -10243,21 +10683,6 @@ execa@^2.0.3: signal-exit "^3.0.2" strip-final-newline "^2.0.0" -execa@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-6.1.0.tgz#cea16dee211ff011246556388effa0818394fb20" - integrity sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA== - dependencies: - cross-spawn "^7.0.3" - get-stream "^6.0.1" - human-signals "^3.0.1" - is-stream "^3.0.0" - merge-stream "^2.0.0" - npm-run-path "^5.1.0" - onetime "^6.0.0" - signal-exit "^3.0.7" - strip-final-newline "^3.0.0" - execa@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/execa/-/execa-8.0.1.tgz#51f6a5943b580f963c3ca9c6321796db8cc39b8c" @@ -10420,7 +10845,7 @@ fast-diff@^1.1.2: resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== -fast-fifo@^1.1.0, fast-fifo@^1.2.0: +fast-fifo@^1.2.0, fast-fifo@^1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c" integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ== @@ -10446,7 +10871,7 @@ fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: +fast-levenshtein@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== @@ -10563,13 +10988,6 @@ figures@^2.0.0: dependencies: escape-string-regexp "^1.0.5" -file-entry-cache@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" - integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== - dependencies: - flat-cache "^2.0.1" - file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -10617,10 +11035,10 @@ filesize@^8.0.6: resolved "https://registry.yarnpkg.com/filesize/-/filesize-8.0.7.tgz#695e70d80f4e47012c132d57a059e80c6b580bd8" integrity sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ== -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== dependencies: to-regex-range "^5.0.1" @@ -10642,12 +11060,12 @@ finalhandler@1.2.0: statuses "2.0.1" unpipe "~1.0.0" -find-babel-config@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/find-babel-config/-/find-babel-config-2.0.0.tgz#a8216f825415a839d0f23f4d18338a1cc966f701" - integrity sha512-dOKT7jvF3hGzlW60Gc3ONox/0rRZ/tz7WCil0bqA1In/3I8f1BctpXahRnEKDySZqci7u+dqq93sZST9fOJpFw== +find-babel-config@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/find-babel-config/-/find-babel-config-2.1.1.tgz#93703fc8e068db5e4c57592900c5715dd04b7e5b" + integrity sha512-5Ji+EAysHGe1OipH7GN4qDjok5Z1uw5KAwDCbicU/4wyTZY7CqOCzcWbG7J5ad9mazq67k89fXlbc1MuIfl9uA== dependencies: - json5 "^2.1.1" + json5 "^2.2.3" path-exists "^4.0.0" find-cache-dir@^0.1.1: @@ -10736,15 +11154,6 @@ find-up@^6.3.0: locate-path "^7.1.0" path-exists "^5.0.0" -flat-cache@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" - integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== - dependencies: - flatted "^2.0.0" - rimraf "2.6.3" - write "1.0.3" - flat-cache@^3.0.4: version "3.2.0" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" @@ -10759,20 +11168,15 @@ flat@^5.0.2: resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== -flatted@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" - integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== - flatted@^3.2.9: version "3.3.1" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== flow-parser@0.*: - version "0.233.0" - resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.233.0.tgz#b983e65812d5ecae79f08ae3ed8ad2e131a9b966" - integrity sha512-E/mv51GYJfLuRX6fZnw4M52gBxYa8pkHUOgNEZOcQK2RTXS8YXeU5rlalkTcY99UpwbeNVCSUFKaavpOksi/pQ== + version "0.238.0" + resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.238.0.tgz#b465753c2630a38f459413a745c69ec11a0b5291" + integrity sha512-VE7XSv1epljsIN2YeBnxCmGJihpNIAnLLu/pPOdA+Gkso7qDltJwUi6vfHjgxdBbjSdAuPGnhuOHJUQG+yYwIg== flux@^4.0.1: version "4.0.4" @@ -10782,7 +11186,7 @@ flux@^4.0.1: fbemitter "^3.0.0" fbjs "^3.0.1" -follow-redirects@^1.0.0, follow-redirects@^1.14.7, follow-redirects@^1.14.8, follow-redirects@^1.14.9, follow-redirects@^1.15.6: +follow-redirects@^1.0.0, follow-redirects@^1.14.7, follow-redirects@^1.14.9, follow-redirects@^1.15.0, follow-redirects@^1.15.6: version "1.15.6" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== @@ -10795,9 +11199,9 @@ for-each@^0.3.3: is-callable "^1.1.3" foreground-child@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" - integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== + version "3.2.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.2.1.tgz#767004ccf3a5b30df39bed90718bab43fe0a59f7" + integrity sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA== dependencies: cross-spawn "^7.0.0" signal-exit "^4.0.1" @@ -10889,6 +11293,26 @@ fraction.js@^4.3.7: resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7" integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew== +framer-motion@6.2.4: + version "6.2.4" + resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-6.2.4.tgz#3d9c61be3fb8381a770efccdb56cc421de662979" + integrity sha512-1UfnSG4c4CefKft6QMYGx8AWt3TtaFoR/Ax4dkuDDD5BDDeIuUm7gesmJrF8GzxeX/i6fMm8+MEdPngUyPVdLA== + dependencies: + framesync "6.0.1" + hey-listen "^1.0.8" + popmotion "11.0.3" + style-value-types "5.0.0" + tslib "^2.1.0" + optionalDependencies: + "@emotion/is-prop-valid" "^0.8.2" + +framesync@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/framesync/-/framesync-6.0.1.tgz#5e32fc01f1c42b39c654c35b16440e07a25d6f20" + integrity sha512-fUY88kXvGiIItgNC7wcTOl0SNRCVXMKSWW2Yzfmn7EKNc+MpCzcz9DhdHcdjbrtN3c6R4H5dTY2jiCpPdysEjA== + dependencies: + tslib "^2.1.0" + fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" @@ -10956,15 +11380,20 @@ fs-minipass@^3.0.0: minipass "^7.0.3" fs-monkey@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.5.tgz#fe450175f0db0d7ea758102e1d84096acb925788" - integrity sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew== + version "1.0.6" + resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.6.tgz#8ead082953e88d992cf3ff844faa907b26756da2" + integrity sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg== fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== +fsevents@2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + fsevents@^2.3.2, fsevents@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" @@ -10985,11 +11414,6 @@ function.prototype.name@^1.1.2, function.prototype.name@^1.1.5, function.prototy es-abstract "^1.22.1" functions-have-names "^1.2.3" -functional-red-black-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== - functions-have-names@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" @@ -11033,7 +11457,7 @@ get-caller-file@^2.0.5: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: +get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== @@ -11242,17 +11666,17 @@ glob@7.1.4: path-is-absolute "^1.0.0" glob@^10.0.0, glob@^10.2.2: - version "10.3.12" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.12.tgz#3a65c363c2e9998d220338e88a5f6ac97302960b" - integrity sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg== + version "10.4.1" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.1.tgz#0cfb01ab6a6b438177bfe6a58e2576f6efe909c2" + integrity sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw== dependencies: foreground-child "^3.1.0" - jackspeak "^2.3.6" - minimatch "^9.0.1" - minipass "^7.0.4" - path-scurry "^1.10.2" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + path-scurry "^1.11.1" -glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: +glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -11264,7 +11688,7 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, gl once "^1.3.0" path-is-absolute "^1.0.0" -glob@^8.0.1, glob@^8.0.3: +glob@^8.0.1: version "8.1.0" resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== @@ -11275,7 +11699,7 @@ glob@^8.0.1, glob@^8.0.3: minimatch "^5.0.1" once "^1.3.0" -glob@^9.2.0: +glob@^9.2.0, glob@^9.3.3: version "9.3.5" resolved "https://registry.yarnpkg.com/glob/-/glob-9.3.5.tgz#ca2ed8ca452781a3009685607fdf025a899dfe21" integrity sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q== @@ -11316,33 +11740,33 @@ global-prefix@^3.0.0: kind-of "^6.0.2" which "^1.3.1" -global@^4.3.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406" - integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w== - dependencies: - min-document "^2.19.0" - process "^0.11.10" - -globals@^11.1.0, globals@^11.7.0: +globals@^11.1.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -globals@^13.20.0, globals@^13.6.0, globals@^13.9.0: +globals@^13.19.0, globals@^13.20.0: version "13.24.0" resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== dependencies: type-fest "^0.20.2" -globalthis@1.0.3, globalthis@^1.0.3: +globalthis@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== dependencies: define-properties "^1.1.3" +globalthis@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" + integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ== + dependencies: + define-properties "^1.2.1" + gopd "^1.0.1" + globby@11.1.0, globby@^11.0.1, globby@^11.0.2, globby@^11.0.3, globby@^11.0.4, globby@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" @@ -11559,11 +11983,6 @@ has-yarn@^2.1.0: resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== -has@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.4.tgz#2eb2860e000011dae4f1406a86fe80e530fb2ec6" - integrity sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ== - hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" @@ -11644,6 +12063,11 @@ he@^1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +hey-listen@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/hey-listen/-/hey-listen-1.0.8.tgz#8e59561ff724908de1aa924ed6ecc84a56a9aa68" + integrity sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q== + history@^4.9.0: version "4.10.1" resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3" @@ -11663,7 +12087,7 @@ history@^5.3.0: dependencies: "@babel/runtime" "^7.7.6" -hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.2.1, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2: +hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.2.1, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== @@ -11900,11 +12324,6 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== -human-signals@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-3.0.1.tgz#c740920859dafa50e5a3222da9d3bf4bb0e5eef5" - integrity sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ== - human-signals@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28" @@ -11997,17 +12416,12 @@ ignore-walk@^5.0.1: minimatch "^5.0.1" ignore-walk@^6.0.0: - version "6.0.4" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-6.0.4.tgz#89950be94b4f522225eb63a13c56badb639190e9" - integrity sha512-t7sv42WkwFkyKbivUCglsQW5YWMskWtbEf4MNKX5u/CCWHKSPzN4FtBQGsQZgCLbxOzpVlcbWVK5KB3auIOjSw== + version "6.0.5" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-6.0.5.tgz#ef8d61eab7da169078723d1f82833b36e200b0dd" + integrity sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A== dependencies: minimatch "^9.0.0" -ignore@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" - integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== - ignore@^5.0.0, ignore@^5.0.4, ignore@^5.1.1, ignore@^5.1.9, ignore@^5.2.0, ignore@^5.2.4: version "5.3.1" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" @@ -12040,7 +12454,7 @@ import-fresh@^2.0.0: caller-path "^2.0.0" resolve-from "^3.0.0" -import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1, import-fresh@^3.3.0: +import-fresh@^3.1.0, import-fresh@^3.2.1, import-fresh@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== @@ -12132,25 +12546,6 @@ inline-style-parser@0.1.1: resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== -inquirer@^6.2.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" - integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== - dependencies: - ansi-escapes "^3.2.0" - chalk "^2.4.2" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^3.0.3" - figures "^2.0.0" - lodash "^4.17.12" - mute-stream "0.0.7" - run-async "^2.2.0" - rxjs "^6.4.0" - string-width "^2.1.0" - strip-ansi "^5.1.0" - through "^2.3.6" - inquirer@^8.2.0, inquirer@^8.2.4: version "8.2.6" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.6.tgz#733b74888195d8d400a67ac332011b5fae5ea562" @@ -12172,7 +12567,7 @@ inquirer@^8.2.0, inquirer@^8.2.4: through "^2.3.6" wrap-ansi "^6.0.1" -internal-slot@^1.0.7: +internal-slot@^1.0.4, internal-slot@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" integrity sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g== @@ -12216,15 +12611,12 @@ ip-address@^9.0.5: jsbn "1.1.0" sprintf-js "^1.1.3" -ip@^1.1.0: - version "1.1.9" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.9.tgz#8dfbcc99a754d07f425310b86a99546b1151e396" - integrity sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ== - -ip@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.1.tgz#e8f3595d33a3ea66490204234b77636965307105" - integrity sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ== +ip@^1.1.0, ip@^2.0.1, "ip@https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz": + version "9.0.5" + resolved "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz#117a960819b08780c3bd1f14ef3c1cc1d3f3ea5a" + dependencies: + jsbn "1.1.0" + sprintf-js "^1.1.3" ipaddr.js@1.9.1: version "1.9.1" @@ -12232,9 +12624,9 @@ ipaddr.js@1.9.1: integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== ipaddr.js@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.1.0.tgz#2119bc447ff8c257753b196fc5f1ce08a4cdf39f" - integrity sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ== + version "2.2.0" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz#d33fa7bac284f4de7af949638c9d68157c6b92e8" + integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA== is-absolute-url@^3.0.0: version "3.0.3" @@ -12262,7 +12654,7 @@ is-arguments@^1.0.4, is-arguments@^1.1.1: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-array-buffer@^3.0.4: +is-array-buffer@^3.0.2, is-array-buffer@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" integrity sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw== @@ -12338,13 +12730,20 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" -is-core-module@^2.1.0, is-core-module@^2.13.0, is-core-module@^2.13.1, is-core-module@^2.5.0, is-core-module@^2.8.1: +is-core-module@^2.1.0, is-core-module@^2.13.1, is-core-module@^2.5.0, is-core-module@^2.8.1: version "2.13.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== dependencies: hasown "^2.0.0" +is-core-module@^2.13.0: + version "2.14.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.14.0.tgz#43b8ef9f46a6a08888db67b1ffd4ec9e3dfd59d1" + integrity sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A== + dependencies: + hasown "^2.0.2" + is-data-view@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.1.tgz#4b4d3a511b70f3dc26d42c03ca9ca515d847759f" @@ -12460,7 +12859,7 @@ is-lambda@^1.0.1: resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" integrity sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ== -is-map@^2.0.3: +is-map@^2.0.2, is-map@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw== @@ -12536,7 +12935,7 @@ is-path-inside@^2.1.0: dependencies: path-is-inside "^1.0.2" -is-path-inside@^3.0.1, is-path-inside@^3.0.2: +is-path-inside@^3.0.1, is-path-inside@^3.0.2, is-path-inside@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== @@ -12606,7 +13005,7 @@ is-root@^2.1.0: resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c" integrity sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg== -is-set@^2.0.3: +is-set@^2.0.2, is-set@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d" integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg== @@ -12829,19 +13228,19 @@ iterator.prototype@^1.1.2: reflect.getprototypeof "^1.0.4" set-function-name "^2.0.1" -jackspeak@^2.3.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" - integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== +jackspeak@^3.1.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.0.tgz#a75763ff36ad778ede6a156d8ee8b124de445b4a" + integrity sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw== dependencies: "@isaacs/cliui" "^8.0.2" optionalDependencies: "@pkgjs/parseargs" "^0.11.0" jake@^10.8.5: - version "10.8.7" - resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.7.tgz#63a32821177940c33f356e0ba44ff9d34e1c7d8f" - integrity sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w== + version "10.9.1" + resolved "https://registry.yarnpkg.com/jake/-/jake-10.9.1.tgz#8dc96b7fcc41cb19aa502af506da4e1d56f5e62b" + integrity sha512-61btcOHNnLnsOdtLgA5efqQWjnSi/vow5HbI7HMdKKWqvrKR1bLK3BPlJn9gcSaP2ewuamUSMB5XEy76KUIS2w== dependencies: async "^3.2.3" chalk "^4.0.2" @@ -13304,9 +13703,9 @@ jest@^29.5.0: jest-cli "^29.7.0" jiti@^1.20.0: - version "1.21.0" - resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d" - integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q== + version "1.21.6" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.6.tgz#6c7f7398dd4b3142767f9a168af2f317a428d268" + integrity sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w== jju@~1.4.0: version "1.4.0" @@ -13314,9 +13713,9 @@ jju@~1.4.0: integrity sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA== joi@^17.6.0, joi@^17.7.0: - version "17.12.3" - resolved "https://registry.yarnpkg.com/joi/-/joi-17.12.3.tgz#944646979cd3b460178547b12ba37aca8482f63d" - integrity sha512-2RRziagf555owrm9IRVtdKynOBeITiDpuZqIpgwqXShPncPKNiRQoiGsl/T8SQdq+8ugRzH2LqY67irr2y/d+g== + version "17.13.1" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.13.1.tgz#9c7b53dc3b44dd9ae200255cc3b398874918a6ca" + integrity sha512-vaBlIKCyo4FCUtCm7Eu4QZd/q02bWcxfUO6YSXAZOWF6gzcLBeba8kwotUdYJjDLW8Cz8RywsSOqiNJZW0mNvg== dependencies: "@hapi/hoek" "^9.3.0" "@hapi/topo" "^5.1.0" @@ -13344,7 +13743,7 @@ js-yaml@4.1.0, js-yaml@^4.1.0: dependencies: argparse "^2.0.1" -js-yaml@^3.10.0, js-yaml@^3.13.0, js-yaml@^3.13.1: +js-yaml@^3.10.0, js-yaml@^3.13.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== @@ -13446,9 +13845,9 @@ json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== json-parse-even-better-errors@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz#02bb29fb5da90b5444581749c22cedd3597c6cb0" - integrity sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg== + version "3.0.2" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz#b43d35e89c0f3be6b5fbbe9dc6c82467b30c28da" + integrity sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ== json-schema-traverse@^0.4.1: version "0.4.1" @@ -13487,7 +13886,7 @@ json5@^1.0.1, json5@^1.0.2: dependencies: minimist "^1.2.0" -json5@^2.1.1, json5@^2.1.2, json5@^2.2.0, json5@^2.2.2, json5@^2.2.3: +json5@^2.1.2, json5@^2.2.0, json5@^2.2.2, json5@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== @@ -13536,6 +13935,11 @@ jsprim@^2.0.2: object.assign "^4.1.4" object.values "^1.1.6" +jwt-decode@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-4.0.0.tgz#2270352425fd413785b2faf11f6e755c5151bd4b" + integrity sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA== + keyv@^4.5.3: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" @@ -13564,9 +13968,9 @@ klona@^2.0.5: integrity sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA== language-subtag-registry@^0.3.20: - version "0.3.22" - resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz#2e1500861b2e457eba7e7ae86877cbd08fa1fd1d" - integrity sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w== + version "0.3.23" + resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz#23529e04d9e3b74679d70142df3fd2eb6ec572e7" + integrity sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ== language-tags@^1.0.9: version "1.0.9" @@ -13591,9 +13995,9 @@ latest-version@^5.1.0: package-json "^6.3.0" launch-editor@^2.6.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/launch-editor/-/launch-editor-2.6.1.tgz#f259c9ef95cbc9425620bbbd14b468fcdb4ffe3c" - integrity sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw== + version "2.7.0" + resolved "https://registry.yarnpkg.com/launch-editor/-/launch-editor-2.7.0.tgz#53ba12b3eb131edefee99acaef7850c40272273f" + integrity sha512-KAc66u6LxWL8MifQ94oG3YGKYWDwz/Gi0T15lN//GaQoZe08vQGFJxrXkPAeu50UXgvJPPaRKVGuP1TRUm/aHQ== dependencies: picocolors "^1.0.0" shell-quote "^1.8.1" @@ -13708,14 +14112,6 @@ leven@^3.1.0: resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== -levn@^0.3.0, levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -13881,7 +14277,7 @@ loader-utils@^1.0.2, loader-utils@^1.1.0: emojis-list "^3.0.0" json5 "^1.0.1" -loader-utils@^2.0.0, loader-utils@^2.0.3, loader-utils@^2.0.4: +loader-utils@^2.0.0, loader-utils@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.4.tgz#8b5cb38b5c34a9a018ee1fc0e6a066d1dfcc528c" integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw== @@ -13891,9 +14287,9 @@ loader-utils@^2.0.0, loader-utils@^2.0.3, loader-utils@^2.0.4: json5 "^2.1.2" loader-utils@^3.2.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.2.1.tgz#4fb104b599daafd82ef3e1a41fb9265f87e1f576" - integrity sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw== + version "3.3.1" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.3.1.tgz#735b9a19fd63648ca7adbd31c2327dfe281304e5" + integrity sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg== locate-path@^2.0.0: version "2.0.0" @@ -13984,21 +14380,21 @@ lodash.ismatch@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37" integrity sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g== -lodash.isplainobject@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" - integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== - lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== -lodash.merge@^4.6.1, lodash.merge@^4.6.2: +lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== +lodash.mergewith@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55" + integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ== + lodash.once@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" @@ -14007,19 +14403,14 @@ lodash.once@^4.1.1: lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" - integrity sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA== - -lodash.truncate@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" - integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== + integrity sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA== lodash.uniq@4.5.0, lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== -lodash@^4.0.1, lodash@^4.1.1, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.5: +lodash@^4.0.1, lodash@^4.1.1, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.5: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -14095,9 +14486,9 @@ lowercase-keys@^3.0.0: integrity sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ== lru-cache@^10.2.0: - version "10.2.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3" - integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q== + version "10.2.2" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.2.tgz#48206bc114c1252940c41b25b41af5b545aca878" + integrity sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ== lru-cache@^4.0.1: version "4.1.5" @@ -14126,6 +14517,16 @@ lru-cache@^7.4.4, lru-cache@^7.5.1, lru-cache@^7.7.1: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89" integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== +lucide-react@^0.379.0: + version "0.379.0" + resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.379.0.tgz#29e34eeffae7fb241b64b09868cbe3ab888ef7cc" + integrity sha512-KcdeVPqmhRldldAAgptb8FjIunM2x2Zy26ZBh1RsEUcdLIvsEmbcw7KpzFYUy5BbpGeWhPu9Z9J5YXfStiXwhg== + +lz-string@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" + integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ== + magic-string@^0.25.0, magic-string@^0.25.1, magic-string@^0.25.2, magic-string@^0.25.7: version "0.25.9" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c" @@ -14134,9 +14535,9 @@ magic-string@^0.25.0, magic-string@^0.25.1, magic-string@^0.25.2, magic-string@^ sourcemap-codec "^1.4.8" magic-string@^0.30.5: - version "0.30.9" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.9.tgz#8927ae21bfdd856310e07a1bc8dd5e73cb6c251d" - integrity sha512-S1+hd+dIrC8EZqKyT9DstTH/0Z+f76kmmvZnkfQVmOpDEF9iVgdYif3Q/pIWHmCoo59bQVGW0kVL3e2nl+9+Sw== + version "0.30.10" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.10.tgz#123d9c41a0cb5640c892b041d4cfb3bd0aa4b39e" + integrity sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ== dependencies: "@jridgewell/sourcemap-codec" "^1.4.15" @@ -14248,9 +14649,9 @@ markdown-table@^3.0.0: integrity sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw== markdown-to-jsx@^7.1.8: - version "7.4.6" - resolved "https://registry.yarnpkg.com/markdown-to-jsx/-/markdown-to-jsx-7.4.6.tgz#1ea0018c549bf00c9ce35e8f4ea57e48028d9cf7" - integrity sha512-3cyNxI/PwotvYkjg6KmFaN1uyN/7NqETteD2DobBB8ro/FR9jsHIh4Fi7ywAz0s9QHRKCmGlOUggs5GxSWACKA== + version "7.4.7" + resolved "https://registry.yarnpkg.com/markdown-to-jsx/-/markdown-to-jsx-7.4.7.tgz#740ee7ec933865ef5cc683a0992797685a75e2ee" + integrity sha512-0+ls1IQZdU6cwM1yu0ZjjiVWYtkbExSyUIFU2ZeDIFuZM1W42Mh4OlJ4nb4apX4H8smxDHRdFaoIVJGwfv5hkg== material-colors@^1.2.1: version "1.2.6" @@ -14272,6 +14673,21 @@ mathjs@^11.2: tiny-emitter "^2.1.0" typed-function "^4.1.1" +mathjs@^12.4.2: + version "12.4.3" + resolved "https://registry.yarnpkg.com/mathjs/-/mathjs-12.4.3.tgz#eef86baf8ee4c2467fc8c4619107bf4a650b9954" + integrity sha512-oHdGPDbp7gO873xxG90RLq36IuicuKvbpr/bBG5g9c8Obm/VsKVrK9uoRZZHUodohzlnmCEqfDzbR3LH6m+aAQ== + dependencies: + "@babel/runtime" "^7.24.4" + complex.js "^2.1.1" + decimal.js "^10.4.3" + escape-latex "^1.2.0" + fraction.js "4.3.4" + javascript-natural-sort "^0.7.1" + seedrandom "^3.0.5" + tiny-emitter "^2.1.0" + typed-function "^4.1.1" + mdast-squeeze-paragraphs@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-4.0.0.tgz#7c4c114679c3bee27ef10b58e2e015be79f1ef97" @@ -14430,6 +14846,16 @@ mdn-data@2.0.14: resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== +mdn-data@2.0.28: + version "2.0.28" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.28.tgz#5ec48e7bef120654539069e1ae4ddc81ca490eba" + integrity sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g== + +mdn-data@2.0.30: + version "2.0.30" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.30.tgz#ce4df6f80af6cfbe218ecd5c552ba13c4dfa08cc" + integrity sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA== + mdn-data@2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" @@ -14785,11 +15211,11 @@ micromark@^3.0.0: uvu "^0.5.0" micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + version "4.0.7" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.7.tgz#33e8190d9fe474a9895525f5618eee136d46c2e5" + integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q== dependencies: - braces "^3.0.2" + braces "^3.0.3" picomatch "^2.3.1" mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": @@ -14851,22 +15277,15 @@ mimic-response@^4.0.0: resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-4.0.0.tgz#35468b19e7c75d10f5165ea25e75a5ceea7cf70f" integrity sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg== -min-document@^2.19.0: - version "2.19.0" - resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" - integrity sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ== - dependencies: - dom-walk "^0.1.0" - min-indent@^1.0.0, min-indent@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== mini-css-extract-plugin@^2.1.0, mini-css-extract-plugin@^2.6.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.8.1.tgz#75245f3f30ce3a56dbdd478084df6fe475f02dc7" - integrity sha512-/1HDlyFRxWIZPI1ZpgqlZ8jMw/1Dp/dl3P0L1jtZ+zVcHqwPhGwaJwKL00WVgfnBy6PWCde9W65or7IIETImuA== + version "2.9.0" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.0.tgz#c73a1327ccf466f69026ac22a8e8fd707b78a235" + integrity sha512-Zs1YsZVfemekSZG+44vBsYTLQORkPMwnlv+aehcxK/NLKC+EGhDB39/YePYYqx/sTk6NnYpuqikhSn7+JIevTA== dependencies: schema-utils "^4.0.0" tapable "^2.2.1" @@ -14911,7 +15330,7 @@ minimatch@^8.0.2: dependencies: brace-expansion "^2.0.1" -minimatch@^9.0.0, minimatch@^9.0.1: +minimatch@^9.0.0, minimatch@^9.0.4: version "9.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== @@ -14951,9 +15370,9 @@ minipass-fetch@^2.0.3: encoding "^0.1.13" minipass-fetch@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-3.0.4.tgz#4d4d9b9f34053af6c6e597a64be8e66e42bf45b7" - integrity sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg== + version "3.0.5" + resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-3.0.5.tgz#f0f97e40580affc4a35cc4a1349f05ae36cb1e4c" + integrity sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg== dependencies: minipass "^7.0.3" minipass-sized "^1.0.3" @@ -15007,10 +15426,10 @@ minipass@^5.0.0: resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.3, minipass@^7.0.4: - version "7.0.4" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" - integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.3, minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== minizlib@^2.1.1, minizlib@^2.1.2: version "2.1.2" @@ -15042,12 +15461,7 @@ modify-values@^1.0.1: resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw== -moment@2.29.4: - version "2.29.4" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" - integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== - -moment@>=1.6.0, moment@^2.24.0: +moment@*, moment@>=1.6.0, moment@^2.9.4: version "2.30.1" resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== @@ -15126,11 +15540,6 @@ mustache@^4.2.0: resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.2.0.tgz#e5892324d60a12ec9c2a73359edca52972bf6f64" integrity sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ== -mute-stream@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" - integrity sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ== - mute-stream@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" @@ -15179,6 +15588,11 @@ neo-async@^2.5.0, neo-async@^2.6.2: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== +next-themes@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/next-themes/-/next-themes-0.3.0.tgz#b4d2a866137a67d42564b07f3a3e720e2ff3871a" + integrity sha512-/QHIrsYpd6Kfk7xakK4svpDI5mmXP0gfvCoJdGpZQ2TOrQZmsW0QxjaiLn8wbIKjtm4BTSqLoix4lxYYOnLJ/w== + nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" @@ -15193,9 +15607,9 @@ no-case@^3.0.4: tslib "^2.0.3" node-abi@^3.3.0: - version "3.57.0" - resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.57.0.tgz#d772cb899236c0aa46778d0d25256917cf15eb15" - integrity sha512-Dp+A9JWxRaKuHP35H77I4kCKesDy5HUDEmScia2FyncMTOXASMyg251F5PhFoDA5uqBrDDffiLpbqnrZmNXW+g== + version "3.65.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.65.0.tgz#ca92d559388e1e9cab1680a18c1a18757cdac9d3" + integrity sha512-ThjYBfoDNr08AWx6hGaRbfPwxKV9kVzAzOzlLKbk2CuqXE2xnCh+cbAGnwM3t8Lq4v9rUB7VfondlkBckcJrVA== dependencies: semver "^7.3.5" @@ -15267,9 +15681,9 @@ node-forge@^1: integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== node-gyp-build@^4.3.0: - version "4.8.0" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.0.tgz#3fee9c1731df4581a3f9ead74664369ff00d26dd" - integrity sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og== + version "4.8.1" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.1.tgz#976d3ad905e71b76086f4f0b0d3637fe79b6cda5" + integrity sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw== node-gyp@^9.0.0: version "9.4.1" @@ -15383,9 +15797,9 @@ npm-bundled@^1.1.2: npm-normalize-package-bin "^1.0.1" npm-bundled@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-3.0.0.tgz#7e8e2f8bb26b794265028491be60321a25a39db7" - integrity sha512-Vq0eyEQy+elFpzsKjMss9kxqb9tG3YHg4dsyWuUENuzvSUWe1TCnW/vV9FkhvBk/brEDoDiVd+M1Btosa6ImdQ== + version "3.0.1" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-3.0.1.tgz#cca73e15560237696254b10170d8f86dad62da25" + integrity sha512-+AvaheE/ww1JEwRHOrn4WHNzOxGtVp+adrg2AeZS/7KuxGUYFuBta98wYpfHBbJp6Tg6j1NKSEVHNcfZzJHQwQ== dependencies: npm-normalize-package-bin "^3.0.0" @@ -15526,9 +15940,9 @@ number-is-nan@^1.0.0: integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ== nwsapi@^2.2.2: - version "2.2.7" - resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.7.tgz#738e0707d3128cb750dddcfe90e4610482df0f30" - integrity sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ== + version "2.2.10" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.10.tgz#0b77a68e21a0b483db70b11fad055906e867cda8" + integrity sha512-QK0sRs7MKv0tKe1+5uZIQk/C8XGza4DAnztJG8iD+TpJIORARrCxczA738awHrZoHeTjSSoHqao2teO0dC/gFQ== nx@16.10.0, "nx@>=16.5.1 < 17": version "16.10.0" @@ -15642,7 +16056,7 @@ object.assign@^4.1.0, object.assign@^4.1.2, object.assign@^4.1.4, object.assign@ has-symbols "^1.0.3" object-keys "^1.1.1" -object.entries@^1.1.2, object.entries@^1.1.7: +object.entries@^1.1.2, object.entries@^1.1.7, object.entries@^1.1.8: version "1.1.8" resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.8.tgz#bffe6f282e01f4d17807204a24f8edd823599c41" integrity sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ== @@ -15651,7 +16065,7 @@ object.entries@^1.1.2, object.entries@^1.1.7: define-properties "^1.2.1" es-object-atoms "^1.0.0" -object.fromentries@^2.0.7: +object.fromentries@^2.0.7, object.fromentries@^2.0.8: version "2.0.8" resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.8.tgz#f7195d8a9b97bd95cbc1999ea939ecd1a2b00c65" integrity sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ== @@ -15683,7 +16097,7 @@ object.groupby@^1.0.1: define-properties "^1.2.1" es-abstract "^1.23.2" -object.hasown@^1.1.3: +object.hasown@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.4.tgz#e270ae377e4c120cdcb7656ce66884a6218283dc" integrity sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg== @@ -15692,7 +16106,7 @@ object.hasown@^1.1.3: es-abstract "^1.23.2" es-object-atoms "^1.0.0" -object.values@^1.1.0, object.values@^1.1.5, object.values@^1.1.6, object.values@^1.1.7: +object.values@^1.1.0, object.values@^1.1.5, object.values@^1.1.6, object.values@^1.1.7, object.values@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.2.0.tgz#65405a9d92cee68ac2d303002e0b8470a4d9ab1b" integrity sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ== @@ -15728,6 +16142,13 @@ ohash@^1.1.3: dependencies: "@babel/runtime" "^7.20.13" +oidc-client-ts@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/oidc-client-ts/-/oidc-client-ts-3.0.1.tgz#be264fb87c89f74f73863646431c32cd06f5ceb7" + integrity sha512-xX8unZNtmtw3sOz4FPSqDhkLFnxCDsdo2qhFEH2opgWnF/iXMFoYdBQzkwCxAZVgt3FT3DnuBY3k80EZHT0RYg== + dependencies: + jwt-decode "^4.0.0" + oidc-client@1.11.5: version "1.11.5" resolved "https://registry.yarnpkg.com/oidc-client/-/oidc-client-1.11.5.tgz#020aa193d68a3e1f87a24fcbf50073b738de92bb" @@ -15827,29 +16248,17 @@ optimize-css-assets-webpack-plugin@^6.0.1: last-call-webpack-plugin "^3.0.0" postcss "^8.2.1" -optionator@^0.8.2: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" - -optionator@^0.9.1: - version "0.9.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" - integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== +optionator@^0.9.3: + version "0.9.4" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" + integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== dependencies: - "@aashutoshrathi/word-wrap" "^1.2.3" deep-is "^0.1.3" fast-levenshtein "^2.0.6" levn "^0.4.1" prelude-ls "^1.2.1" type-check "^0.4.0" + word-wrap "^1.2.5" ora@^5.4.1: version "5.4.1" @@ -16248,10 +16657,10 @@ path-root@^0.1.1: dependencies: path-root-regex "^0.1.0" -path-scurry@^1.10.2, path-scurry@^1.6.1: - version "1.10.2" - resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.2.tgz#8f6357eb1239d5fa1da8b9f70e9c080675458ba7" - integrity sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA== +path-scurry@^1.11.1, path-scurry@^1.6.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== dependencies: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" @@ -16324,10 +16733,10 @@ performance-now@^2.1.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== +picocolors@^1.0.0, picocolors@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" + integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3, picomatch@^2.3.0, picomatch@^2.3.1: version "2.3.1" @@ -16431,6 +16840,20 @@ pkg-up@^3.1.0: dependencies: find-up "^3.0.0" +playwright-core@1.44.1: + version "1.44.1" + resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.44.1.tgz#53ec975503b763af6fc1a7aa995f34bc09ff447c" + integrity sha512-wh0JWtYTrhv1+OSsLPgFzGzt67Y7BE/ZS3jEqgGBlp2ppp1ZDj8c+9IARNW4dwf1poq5MgHreEM2KV/GuR4cFA== + +playwright@1.44.1: + version "1.44.1" + resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.44.1.tgz#5634369d777111c1eea9180430b7a184028e7892" + integrity sha512-qr/0UJ5CFAtloI3avF95Y0L1xQo6r3LQArLIg/z/PoGJ6xa+EwzrwO5lpNr/09STxdHuUoP2mvuELJS+hLdtgg== + dependencies: + playwright-core "1.44.1" + optionalDependencies: + fsevents "2.3.2" + please-upgrade-node@^3.1.1, please-upgrade-node@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942" @@ -16445,6 +16868,16 @@ polished@^4.2.2: dependencies: "@babel/runtime" "^7.17.8" +popmotion@11.0.3: + version "11.0.3" + resolved "https://registry.yarnpkg.com/popmotion/-/popmotion-11.0.3.tgz#565c5f6590bbcddab7a33a074bb2ba97e24b0cc9" + integrity sha512-Y55FLdj3UxkR7Vl3s7Qr4e9m0onSnP8W7d/xQLsoJM40vs6UKHFdygs6SWryasTZYqugMjm3BepCF4CWXDiHgA== + dependencies: + framesync "6.0.1" + hey-listen "^1.0.8" + style-value-types "5.0.0" + tslib "^2.1.0" + portfinder@^1.0.28: version "1.0.32" resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.32.tgz#2fe1b9e58389712429dc2bea5beb2146146c7f81" @@ -16979,9 +17412,9 @@ postcss-selector-not@^6.0.1: postcss-selector-parser "^6.0.10" postcss-selector-parser@^6.0.10, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.9: - version "6.0.16" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz#3b88b9f5c5abd989ef4e2fc9ec8eedd34b20fb04" - integrity sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw== + version "6.1.0" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz#49694cb4e7c649299fea510a29fa6577104bcf53" + integrity sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ== dependencies: cssesc "^3.0.0" util-deprecate "^1.0.2" @@ -17050,11 +17483,6 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== - prepend-http@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" @@ -17068,19 +17496,24 @@ prettier-linter-helpers@^1.0.0: fast-diff "^1.1.2" prettier-plugin-tailwindcss@^0.5.4: - version "0.5.13" - resolved "https://registry.yarnpkg.com/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.5.13.tgz#ee3c1e07848c90abdd1edde36a09366327e31e26" - integrity sha512-2tPWHCFNC+WRjAC4SIWQNSOdcL1NNkydXim8w7TDqlZi+/ulZYz2OouAI6qMtkggnPt7lGamboj6LcTMwcCvoQ== + version "0.5.14" + resolved "https://registry.yarnpkg.com/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.5.14.tgz#4482eed357d5e22eac259541c70aca5a4c7b9d5c" + integrity sha512-Puaz+wPUAhFp8Lo9HuciYKM2Y2XExESjeT+9NQoVFXZsPPnc9VYss2SpxdQ6vbatmt8/4+SN0oe0I1cPDABg9Q== + +prettier-plugin-tailwindcss@^0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.5.tgz#e05202784a3f41889711ae38c75c5b8cad72f368" + integrity sha512-axfeOArc/RiGHjOIy9HytehlC0ZLeMaqY09mm8YCkMzznKiDkwFzOpBvtuhuv3xG5qB73+Mj7OCe2j/L1ryfuQ== prettier@^2.8.0: version "2.8.8" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== -prettier@^3.0.3: - version "3.2.5" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368" - integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A== +prettier@^3.0.3, prettier@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.2.tgz#03ff86dc7c835f2d2559ee76876a3914cec4a90a" + integrity sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA== pretty-bytes@^5.3.0, pretty-bytes@^5.4.1, pretty-bytes@^5.6.0: version "5.6.0" @@ -17105,7 +17538,7 @@ pretty-format@^24.9.0: ansi-styles "^3.2.0" react-is "^16.8.4" -pretty-format@^27.0.0, pretty-format@^27.5.1: +pretty-format@^27.0.0, pretty-format@^27.0.2, pretty-format@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== @@ -17158,7 +17591,7 @@ process@^0.11.10: resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== -progress@^2.0.0, progress@^2.0.1: +progress@^2.0.1: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== @@ -17197,22 +17630,24 @@ prompts@^2.0.1, prompts@^2.4.0, prompts@^2.4.2: sisteransi "^1.0.5" promzard@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/promzard/-/promzard-1.0.1.tgz#3b77251a24f988c0886f5649d4f642bcdd53e558" - integrity sha512-ulDF77aULEHUoJkN5XZgRV5loHXBaqd9eorMvLNLvi2gXMuRAtwH6Gh4zsMHQY1kTt7tyv/YZwZW5C2gtj8F2A== + version "1.0.2" + resolved "https://registry.yarnpkg.com/promzard/-/promzard-1.0.2.tgz#2226e7c6508b1da3471008ae17066a7c3251e660" + integrity sha512-2FPputGL+mP3jJ3UZg/Dl9YOkovB7DX0oOr+ck5QbZ5MtORtds8k/BZdn+02peDLI8/YWbmzx34k5fA+fHvCVQ== dependencies: read "^3.0.1" prop-types-exact@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/prop-types-exact/-/prop-types-exact-1.2.0.tgz#825d6be46094663848237e3925a98c6e944e9869" - integrity sha512-K+Tk3Kd9V0odiXFP9fwDHUYRyvK3Nun3GVyPapSIs5OBkITAm15W0CPFD/YKTkMUAbc0b9CUwRQp2ybiBIq+eA== + version "1.2.4" + resolved "https://registry.yarnpkg.com/prop-types-exact/-/prop-types-exact-1.2.4.tgz#9010e6b844a0782f6636a597e1738ed494bf7943" + integrity sha512-vKfETKgBHRCLQwZgpl0pGPvMFxCX/06dAkz5jwNYHfrU0I8bgVhryaHA6O/KlqwtQi0IdnjAhDiZqzD+uJuVjA== dependencies: - has "^1.0.3" - object.assign "^4.1.0" - reflect.ownkeys "^0.2.0" + es-errors "^1.3.0" + hasown "^2.0.2" + isarray "^2.0.5" + object.assign "^4.1.5" + reflect.ownkeys "^1.1.4" -prop-types@^15.0.0, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: +prop-types@^15.0.0, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -17366,9 +17801,9 @@ qs@6.11.0: side-channel "^1.0.4" qs@^6.10.0, qs@^6.11.2: - version "6.12.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.12.0.tgz#edd40c3b823995946a8a0b1f208669c7a200db77" - integrity sha512-trVZiI6RMOkO476zLGaBIzszOdFPnCCXHPG9kn0yuS1uz6xdVxPfZdB3vUig9pxPFDM9BRAgz/YUIVQ1/vuiUg== + version "6.12.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.12.1.tgz#39422111ca7cbdb70425541cba20c7d7b216599a" + integrity sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ== dependencies: side-channel "^1.0.6" @@ -17537,6 +17972,11 @@ react-dates@^21.8.0: react-with-styles "^4.1.0" react-with-styles-interface-css "^6.0.0" +react-day-picker@^8.10.1: + version "8.10.1" + resolved "https://registry.yarnpkg.com/react-day-picker/-/react-day-picker-8.10.1.tgz#4762ec298865919b93ec09ba69621580835b8e80" + integrity sha512-TMx7fNbhLk15eqcMt+7Z7S2KF7mfTId/XJDjKE8f+IUcFn0l08/kI4FiYTL/0yuOLmEcbR4Fwe3GJf/NiiMnPA== + react-dev-utils@^12.0.1: version "12.0.1" resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-12.0.1.tgz#ba92edb4a1f379bd46ccd6bcd4e7bc398df33e73" @@ -17606,22 +18046,21 @@ react-docgen@^7.0.0: resolve "^1.22.1" strip-indent "^4.0.0" -react-dom@^17.0.2: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" - integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA== +react-dom@^18.3.1: + version "18.3.1" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4" + integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw== dependencies: loose-envify "^1.1.0" - object-assign "^4.1.1" - scheduler "^0.20.2" + scheduler "^0.23.2" -react-draggable@4.4.3: - version "4.4.3" - resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.4.3.tgz#0727f2cae5813e36b0e4962bf11b2f9ef2b406f3" - integrity sha512-jV4TE59MBuWm7gb6Ns3Q1mxX8Azffb7oTtDtBgFkxRvhDp38YAARmRplrj0+XGkhOJB5XziArX+4HUUABtyZ0w== +react-draggable@^4.4.6: + version "4.4.6" + resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.4.6.tgz#63343ee945770881ca1256a5b6fa5c9f5983fe1e" + integrity sha512-LtY5Xw1zTPqHkVmtM3X8MUOxNDOUhv/khTgBgrUvwaS064bwVvxT+q5El0uUFNx5IEPKXuRejr7UqLwBIg5pdw== dependencies: - classnames "^2.2.5" - prop-types "^15.6.0" + clsx "^1.1.1" + prop-types "^15.8.1" react-dropzone@^10.1.7: version "10.2.2" @@ -17659,9 +18098,9 @@ react-fast-compare@^3.2.0, react-fast-compare@^3.2.2: integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ== react-helmet-async@*: - version "2.0.4" - resolved "https://registry.yarnpkg.com/react-helmet-async/-/react-helmet-async-2.0.4.tgz#50a4377778f380ed1d0136303916b38eff1bf153" - integrity sha512-yxjQMWposw+akRfvpl5+8xejl4JtUlHnEBcji6u8/e6oc7ozT+P9PNTWMhCbz2y9tc5zPegw2BvKjQA+NwdEjQ== + version "2.0.5" + resolved "https://registry.yarnpkg.com/react-helmet-async/-/react-helmet-async-2.0.5.tgz#cfc70cd7bb32df7883a8ed55502a1513747223ec" + integrity sha512-rYUYHeus+i27MvFE+Jaa4WsyBKGkL6qVgbJvSBoX8mbsWoABJXdEO0bZyi0F6i+4f0NuIb8AvqPMj3iXFHkMwg== dependencies: invariant "^2.2.4" react-fast-compare "^3.2.2" @@ -17678,20 +18117,6 @@ react-helmet-async@^1.3.0: react-fast-compare "^3.2.0" shallowequal "^1.1.0" -react-hot-loader@^4.13.0: - version "4.13.1" - resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-4.13.1.tgz#979fd7598e27338b3faffae6ed01c65374dace5e" - integrity sha512-ZlqCfVRqDJmMXTulUGic4lN7Ic1SXgHAFw7y/Jb7t25GBgTR0fYAJ8uY4mrpxjRyWGWmqw77qJQGnYbzCvBU7g== - dependencies: - fast-levenshtein "^2.0.6" - global "^4.3.0" - hoist-non-react-statics "^3.3.0" - loader-utils "^2.0.3" - prop-types "^15.6.1" - react-lifecycles-compat "^3.0.4" - shallowequal "^1.1.0" - source-map "^0.7.3" - react-i18next@^12.2.2: version "12.3.1" resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-12.3.1.tgz#30134a41a2a71c61dc69c6383504929aed1c99e7" @@ -17705,7 +18130,12 @@ react-is@18.1.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.1.0.tgz#61aaed3096d30eacf2a2127118b5b41387d32a67" integrity sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg== -react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.4, react-is@^16.8.6: +"react-is@^16.12.0 || ^17.0.0 || ^18.0.0", "react-is@^17.0.1 || ^18.0.0", react-is@^18.0.0, react-is@^18.3.1: + version "18.3.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" + integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== + +react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.4: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== @@ -17715,11 +18145,6 @@ react-is@^17.0.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== -"react-is@^17.0.1 || ^18.0.0", react-is@^18.0.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" - integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== - react-json-view@^1.21.3: version "1.21.3" resolved "https://registry.yarnpkg.com/react-json-view/-/react-json-view-1.21.3.tgz#f184209ee8f1bf374fb0c41b0813cff54549c475" @@ -17755,6 +18180,14 @@ react-loadable-ssr-addon-v5-slorber@^1.0.1: dependencies: "@babel/runtime" "^7.10.3" +"react-loadable@npm:@docusaurus/react-loadable@5.5.2": + version "5.5.2" + resolved "https://registry.yarnpkg.com/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz#81aae0db81ecafbdaee3651f12804580868fa6ce" + integrity sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ== + dependencies: + "@types/react" "*" + prop-types "^15.6.2" + react-modal@3.11.2: version "3.11.2" resolved "https://registry.yarnpkg.com/react-modal/-/react-modal-3.11.2.tgz#bad911976d4add31aa30dba8a41d11e21c4ac8a4" @@ -17790,10 +18223,10 @@ react-portal@^4.2.0: dependencies: prop-types "^15.5.8" -react-refresh@^0.14.0: - version "0.14.0" - resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.0.tgz#4e02825378a5f227079554d4284889354e5f553e" - integrity sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ== +react-refresh@^0.14.0, react-refresh@^0.14.2: + version "0.14.2" + resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9" + integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA== react-remove-scroll-bar@^2.3.3: version "2.3.6" @@ -17814,10 +18247,10 @@ react-remove-scroll@2.5.5: use-callback-ref "^1.3.0" use-sidecar "^1.1.2" -react-resize-detector@^9.1.0: - version "9.1.1" - resolved "https://registry.yarnpkg.com/react-resize-detector/-/react-resize-detector-9.1.1.tgz#ce13cf55b9b09d9978fc51e0c87bb3639704921e" - integrity sha512-siLzop7i4xIvZIACE/PHTvRegA8QRCEt0TfmvJ/qCIFQJ4U+3NuYcF8tNDmDWxfIn+X1eNCyY2rauH4KRxge8w== +react-resize-detector@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/react-resize-detector/-/react-resize-detector-10.0.1.tgz#ae9a8c5b6b93c4c11e03b3eb87e57fd7b62f1020" + integrity sha512-CR2EdP83ycGlWkhhrd6+hhZVhPJO4xnzClFCTBXlODVTHOgiDJQu77sBt67J7P3gfU4ec/kOuf2c5EcyTUNLXQ== dependencies: lodash "^4.17.21" @@ -17842,12 +18275,12 @@ react-router-dom@^5.3.3: tiny-warning "^1.0.0" react-router-dom@^6.8.1: - version "6.22.3" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.22.3.tgz#9781415667fd1361a475146c5826d9f16752a691" - integrity sha512-7ZILI7HjcE+p31oQvwbokjk6OA/bnFxrhJ19n82Ex9Ph8fNAq+Hm/7KchpMGlTgWhUxRHMMCut+vEtNpWpowKw== + version "6.23.1" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.23.1.tgz#30cbf266669693e9492aa4fc0dde2541ab02322f" + integrity sha512-utP+K+aSTtEdbWpC+4gxhdlPFwuEfDKq8ZrPFU65bbRJY+l706qjR7yaidBpo3MSeA/fzwbXWbKBI6ftOnP3OQ== dependencies: - "@remix-run/router" "1.15.3" - react-router "6.22.3" + "@remix-run/router" "1.16.1" + react-router "6.23.1" react-router@5.3.4, react-router@^5.3.3: version "5.3.4" @@ -17864,12 +18297,12 @@ react-router@5.3.4, react-router@^5.3.3: tiny-invariant "^1.0.2" tiny-warning "^1.0.0" -react-router@6.22.3, react-router@^6.8.1: - version "6.22.3" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.22.3.tgz#9d9142f35e08be08c736a2082db5f0c9540a885e" - integrity sha512-dr2eb3Mj5zK2YISHK++foM9w4eBnO23eKnZEDs7c880P6oKbrjz/Svg9+nxqtHQK+oMW4OtjZca0RqPglXxguQ== +react-router@6.23.1, react-router@^6.23.1: + version "6.23.1" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.23.1.tgz#d08cbdbd9d6aedc13eea6e94bc6d9b29cb1c4be9" + integrity sha512-fzcOaRF69uvqbbM7OhvQyBTFDVrrGlsFdS3AL+1KfIBtGETibHzi3FkoTRyiDJnWNc2VxrfvR+657ROHjaNjqQ== dependencies: - "@remix-run/router" "1.15.3" + "@remix-run/router" "1.16.1" react-select@5.7.4: version "5.7.4" @@ -17886,6 +18319,14 @@ react-select@5.7.4: react-transition-group "^4.3.0" use-isomorphic-layout-effect "^1.1.2" +react-shallow-renderer@^16.15.0: + version "16.15.0" + resolved "https://registry.yarnpkg.com/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz#48fb2cf9b23d23cde96708fe5273a7d3446f4457" + integrity sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA== + dependencies: + object-assign "^4.1.1" + react-is "^16.12.0 || ^17.0.0 || ^18.0.0" + react-simple-code-editor@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/react-simple-code-editor/-/react-simple-code-editor-0.10.0.tgz#73e7ac550a928069715482aeb33ccba36efe2373" @@ -17900,15 +18341,14 @@ react-style-singleton@^2.2.1: invariant "^2.2.4" tslib "^2.0.0" -react-test-renderer@^16.12.0: - version "16.14.0" - resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.14.0.tgz#e98360087348e260c56d4fe2315e970480c228ae" - integrity sha512-L8yPjqPE5CZO6rKsKXRO/rVPiaCOy0tQQJbC+UjPNlobl5mad59lvPjwFsQHTvL03caVDIVr9x9/OSgDe6I5Eg== +react-test-renderer@^18.3.1: + version "18.3.1" + resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-18.3.1.tgz#e693608a1f96283400d4a3afead6893f958b80b4" + integrity sha512-KkAgygexHUkQqtvvx/otwxtuFu5cVjfzTCtjXLH9boS19/Nbtg84zS7wIQn39G8IlrhThBpQsMKkq5ZHZIYFXA== dependencies: - object-assign "^4.1.1" - prop-types "^15.6.2" - react-is "^16.8.6" - scheduler "^0.19.1" + react-is "^18.3.1" + react-shallow-renderer "^16.15.0" + scheduler "^0.23.2" react-textarea-autosize@^8.3.2: version "8.5.3" @@ -17980,13 +18420,12 @@ react-with-styles@^4.1.0: prop-types "^15.7.2" react-with-direction "^1.3.1" -react@^17.0.2: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" - integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA== +react@^18.3.1: + version "18.3.1" + resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" + integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== dependencies: loose-envify "^1.1.0" - object-assign "^4.1.1" reactcss@^1.2.0: version "1.2.3" @@ -18110,9 +18549,9 @@ reading-time@^1.5.0: integrity sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg== recast@^0.23.1, recast@^0.23.3: - version "0.23.6" - resolved "https://registry.yarnpkg.com/recast/-/recast-0.23.6.tgz#198fba74f66143a30acc81929302d214ce4e3bfa" - integrity sha512-9FHoNjX1yjuesMwuthAmPKabxYQdOgihFYmT5ebXfYGBcnqXZf3WOVz+5foEZ8Y83P4ZY6yQD5GMmtV+pgCCAQ== + version "0.23.9" + resolved "https://registry.yarnpkg.com/recast/-/recast-0.23.9.tgz#587c5d3a77c2cfcb0c18ccce6da4361528c2587b" + integrity sha512-Hx/BGIbwj+Des3+xy5uAtAbdCyqK9y9wbBcDFDYanLS9JnMqf7OeF87HQwUimE87OEc72mr6tkKUKMBBL+hF9Q== dependencies: ast-types "^0.16.1" esprima "~4.0.0" @@ -18169,10 +18608,16 @@ reflect.getprototypeof@^1.0.4: globalthis "^1.0.3" which-builtin-type "^1.1.3" -reflect.ownkeys@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz#749aceec7f3fdf8b63f927a04809e90c5c0b3460" - integrity sha512-qOLsBKHCpSOFKK1NUOCGC5VyeufB6lEsFe92AL2bhIJsacZS1qdoOZSbPk3MYKuT2cFlRDnulKXuuElIrMjGUg== +reflect.ownkeys@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/reflect.ownkeys/-/reflect.ownkeys-1.1.4.tgz#3cf21da448f2aff8aba63ca601f65c99482e692c" + integrity sha512-iUNmtLgzudssL+qnTUosCmnq3eczlrVd1wXrgx/GhiI/8FvwrTYWtCJ9PNvWIRX+4ftupj2WUfB5mu5s9t6LnA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-set-tostringtag "^2.0.1" + globalthis "^1.0.3" regenerate-unicode-properties@^10.1.0: version "10.1.1" @@ -18215,12 +18660,7 @@ regexp.prototype.flags@^1.5.1, regexp.prototype.flags@^1.5.2: es-errors "^1.3.0" set-function-name "^2.0.1" -regexpp@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" - integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== - -regexpp@^3.0.0, regexpp@^3.1.0: +regexpp@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== @@ -18488,7 +18928,7 @@ resolve.exports@^2.0.0: resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== -resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.1, resolve@^1.22.4, resolve@^1.3.2, resolve@^1.9.0: +resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.1, resolve@^1.22.4, resolve@^1.22.8, resolve@^1.3.2, resolve@^1.9.0: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== @@ -18497,7 +18937,7 @@ resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.12. path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -resolve@^2.0.0-next.4, resolve@^2.0.0-next.5: +resolve@^2.0.0-next.5: version "2.0.0-next.5" resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.5.tgz#6b0ec3107e671e52b68cd068ef327173b90dc03c" integrity sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA== @@ -18553,16 +18993,9 @@ reusify@^1.0.4: integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== rfdc@^1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.1.tgz#2b6d4df52dffe8bb346992a10ea9451f24373a8f" - integrity sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg== - -rimraf@2.6.3, rimraf@~2.6.2: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" + version "1.4.1" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca" + integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== rimraf@^2.6.1, rimraf@^2.6.3: version "2.7.1" @@ -18585,6 +19018,13 @@ rimraf@^4.4.1: dependencies: glob "^9.2.0" +rimraf@~2.6.2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + rollup-plugin-terser@^7.0.0: version "7.0.2" resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz#e8fbba4869981b2dc35ae7e8a502d5c6c04d324d" @@ -18617,7 +19057,7 @@ rtlcss@^3.5.0: postcss "^8.3.11" strip-json-comments "^3.1.1" -run-async@^2.2.0, run-async@^2.4.0: +run-async@^2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== @@ -18639,7 +19079,7 @@ rw@^1.3.3: resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4" integrity sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ== -rxjs@^6.3.3, rxjs@^6.4.0: +rxjs@^6.3.3: version "6.6.7" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== @@ -18695,9 +19135,9 @@ safe-regex-test@^1.0.3: integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== sax@^1.2.4: - version "1.3.0" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.3.0.tgz#a5dbe77db3be05c9d1ee7785dbd3ea9de51593d0" - integrity sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA== + version "1.4.1" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f" + integrity sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg== sax@~1.2.4: version "1.2.4" @@ -18711,21 +19151,12 @@ saxes@^6.0.0: dependencies: xmlchars "^2.2.0" -scheduler@^0.19.1: - version "0.19.1" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196" - integrity sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - -scheduler@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91" - integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ== +scheduler@^0.23.2: + version "0.23.2" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3" + integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ== dependencies: loose-envify "^1.1.0" - object-assign "^4.1.1" schema-utils@2.7.0: version "2.7.0" @@ -18763,7 +19194,7 @@ schema-utils@^3.0.0, schema-utils@^3.1.1, schema-utils@^3.2.0: ajv "^6.12.5" ajv-keywords "^3.5.2" -schema-utils@^4.0.0: +schema-utils@^4.0.0, schema-utils@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.2.0.tgz#70d7c93e153a273a805801882ebd3bff20d89c8b" integrity sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw== @@ -18811,7 +19242,7 @@ semver-diff@^3.1.1: dependencies: semver "^6.3.0" -"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: +"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: version "5.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== @@ -18828,12 +19259,10 @@ semver@^6.0.0, semver@^6.1.0, semver@^6.3.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.0.0, semver@^7.1.1, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.1, semver@^7.5.3, semver@^7.5.4: - version "7.6.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" - integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== - dependencies: - lru-cache "^6.0.0" +semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.1, semver@^7.5.3, semver@^7.5.4: + version "7.6.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" + integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== send@0.18.0: version "0.18.0" @@ -18906,12 +19335,12 @@ serve-static@1.15.0: send "0.18.0" serve@^14.2.0: - version "14.2.1" - resolved "https://registry.yarnpkg.com/serve/-/serve-14.2.1.tgz#3f078d292ed5e7b2c5a64f957af2765b0459798b" - integrity sha512-48er5fzHh7GCShLnNyPBRPEjs2I6QBozeGr02gaacROiyS/8ARADlj595j39iZXAqBbJHH/ivJJyPRWY9sQWZA== + version "14.2.3" + resolved "https://registry.yarnpkg.com/serve/-/serve-14.2.3.tgz#047ba2b349354255bc09e0332cd41a92787836c9" + integrity sha512-VqUFMC7K3LDGeGnJM9h56D3XGKb6KGgOw0cVNtA26yYXHCcpxf3xwCTUaQoWlVS7i8Jdh3GjQkOB23qsXyjoyQ== dependencies: - "@zeit/schemas" "2.29.0" - ajv "8.11.0" + "@zeit/schemas" "2.36.0" + ajv "8.12.0" arg "5.0.2" boxen "7.0.0" chalk "5.0.1" @@ -19110,9 +19539,9 @@ sisteransi@^1.0.5: integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== sitemap@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/sitemap/-/sitemap-7.1.1.tgz#eeed9ad6d95499161a3eadc60f8c6dce4bea2bef" - integrity sha512-mK3aFtjz4VdJN0igpIJrinf3EO8U8mxOPsTBzSsy06UtjZQJ3YY3o3Xa7zSc5nMqcMrRwlChHZ18Kxg0caiPBg== + version "7.1.2" + resolved "https://registry.yarnpkg.com/sitemap/-/sitemap-7.1.2.tgz#6ce1deb43f6f177c68bc59cf93632f54e3ae6b72" + integrity sha512-ARCqzHJ0p4gWt+j7NlU5eDlIO9+Rkr/JhPFZKKQ1l5GCus7rJH4UdrlVAh0xC/gDS/Qir2UMxqYNHtsKr2rpCw== dependencies: "@types/node" "^17.0.5" "@types/sax" "^1.2.1" @@ -19134,15 +19563,6 @@ slice-ansi@0.0.4: resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" integrity sha512-up04hB2hR92PgjpyU3y/eg91yIBILyjVY26NvvciY3EVVPjybkMszMpXQ9QAkcS3I5rtJBDLoTxxg+qvW8c7rw== -slice-ansi@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== - dependencies: - ansi-styles "^3.2.0" - astral-regex "^1.0.0" - is-fullwidth-code-point "^2.0.0" - slice-ansi@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" @@ -19166,6 +19586,14 @@ smart-buffer@^4.2.0: resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== +snake-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c" + integrity sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg== + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" + sockjs@^0.3.21, sockjs@^0.3.24: version "0.3.24" resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" @@ -19192,6 +19620,11 @@ socks@^2.6.2: ip-address "^9.0.5" smart-buffer "^4.2.0" +sonner@^1.4.41: + version "1.5.0" + resolved "https://registry.yarnpkg.com/sonner/-/sonner-1.5.0.tgz#af359f817063318415326b33aab54c5d17c747b7" + integrity sha512-FBjhG/gnnbN6FY0jaNnqZOMmB73R+5IiyYAw8yBj7L54ER7HB3fOSE5OFiQiE2iXWxeXKvg6fIP4LtVppHEdJA== + sort-asc@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/sort-asc/-/sort-asc-0.1.0.tgz#ab799df61fc73ea0956c79c4b531ed1e9e7727e9" @@ -19234,7 +19667,7 @@ source-list-map@^2.0.0: resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== -source-map-js@^1.0.2, source-map-js@^1.2.0: +source-map-js@^1.0.1, source-map-js@^1.0.2, source-map-js@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== @@ -19322,9 +19755,9 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.17" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz#887da8aa73218e51a1d917502d79863161a93f9c" - integrity sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg== + version "3.0.18" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz#22aa922dcf2f2885a6494a261f2d8b75345d0326" + integrity sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ== spdx-license-list@^6.4.0: version "6.9.0" @@ -19411,9 +19844,9 @@ ssr-window@^4.0.0, ssr-window@^4.0.2: integrity sha512-ISv/Ch+ig7SOtw7G2+qkwfVASzazUnvlDTwypdLoPoySv+6MqlOV10VwPSE6EWkGjhW50lUmghPmpYZXMu/+AQ== ssri@^10.0.0, ssri@^10.0.1: - version "10.0.5" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-10.0.5.tgz#e49efcd6e36385196cb515d3a2ad6c3f0265ef8c" - integrity sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A== + version "10.0.6" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-10.0.6.tgz#a8aade2de60ba2bce8688e3fa349bad05c7dc1e5" + integrity sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ== dependencies: minipass "^7.0.3" @@ -19475,17 +19908,24 @@ std-env@^3.0.1: resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2" integrity sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg== +stop-iteration-iterator@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz#6a60be0b4ee757d1ed5254858ec66b10c49285e4" + integrity sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ== + dependencies: + internal-slot "^1.0.4" + store2@^2.14.2: version "2.14.3" resolved "https://registry.yarnpkg.com/store2/-/store2-2.14.3.tgz#24077d7ba110711864e4f691d2af941ec533deb5" integrity sha512-4QcZ+yx7nzEFiV4BMLnr/pRa5HYzNITX2ri0Zh6sT9EyQHbBHacC6YigllUPU9X3D0f/22QCgfokpKs52YRrUg== storybook@^7.6.10: - version "7.6.17" - resolved "https://registry.yarnpkg.com/storybook/-/storybook-7.6.17.tgz#d7fdbbf57d61d386b3ccc6721285bc914f54269b" - integrity sha512-8+EIo91bwmeFWPg1eysrxXlhIYv3OsXrznTr4+4Eq0NikqAoq6oBhtlN5K2RGS2lBVF537eN+9jTCNbR+WrzDA== + version "7.6.19" + resolved "https://registry.yarnpkg.com/storybook/-/storybook-7.6.19.tgz#3edb81cfd26d8f710e562419f38bc39ff25da84c" + integrity sha512-xWD1C4vD/4KMffCrBBrUpsLUO/9uNpm8BVW8+Vcb30gkQDfficZ0oziWkmLexpT53VSioa24iazGXMwBqllYjQ== dependencies: - "@storybook/cli" "7.6.17" + "@storybook/cli" "7.6.19" stream-browserify@3.0.0: version "3.0.0" @@ -19507,13 +19947,14 @@ stream-shift@^1.0.0: resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.3.tgz#85b8fab4d71010fc3ba8772e8046cc49b8a3864b" integrity sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ== -streamx@^2.13.0, streamx@^2.15.0: - version "2.16.1" - resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.16.1.tgz#2b311bd34832f08aa6bb4d6a80297c9caef89614" - integrity sha512-m9QYj6WygWyWa3H1YY69amr4nVgy61xfjys7xO7kviL5rfIEc2naf+ewFiOA+aEJD7y0JO3h2GoiUv4TDwEGzQ== +streamx@^2.15.0, streamx@^2.18.0: + version "2.18.0" + resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.18.0.tgz#5bc1a51eb412a667ebfdcd4e6cf6a6fc65721ac7" + integrity sha512-LLUC1TWdjVdn1weXGcSxyTR3T4+acB6tVGXT95y0nGbca4t4o/ng1wKAGTljm9VicuCVLvRlqFYXYy5GwgM7sQ== dependencies: - fast-fifo "^1.1.0" + fast-fifo "^1.3.2" queue-tick "^1.0.1" + text-decoder "^1.1.0" optionalDependencies: bare-events "^2.2.0" @@ -19545,7 +19986,7 @@ string-natural-compare@^3.0.1: resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -19563,7 +20004,16 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -string-width@^2.1.0, string-width@^2.1.1: +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -19571,15 +20021,6 @@ string-width@^2.1.0, string-width@^2.1.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string-width@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -19589,7 +20030,7 @@ string-width@^5.0.1, string-width@^5.1.2: emoji-regex "^9.2.2" strip-ansi "^7.0.1" -string.prototype.matchall@^4.0.10, string.prototype.matchall@^4.0.6: +string.prototype.matchall@^4.0.11, string.prototype.matchall@^4.0.6: version "4.0.11" resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz#1092a72c59268d2abaad76582dccc687c0297e0a" integrity sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg== @@ -19658,7 +20099,7 @@ stringify-object@^3.3.0: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -19679,12 +20120,12 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: - ansi-regex "^4.1.0" + ansi-regex "^5.0.1" strip-ansi@^7.0.0, strip-ansi@^7.0.1: version "7.1.0" @@ -19742,16 +20183,16 @@ strip-indent@^4.0.0: dependencies: min-indent "^1.0.1" -strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== - -strip-json-comments@^3.0.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: +strip-json-comments@^3.0.1, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + strong-log-transformer@2.1.0, strong-log-transformer@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz#0f5ed78d325e0421ac6f90f7f10e691d6ae3ae10" @@ -19781,6 +20222,14 @@ style-to-object@0.3.0, style-to-object@^0.3.0: dependencies: inline-style-parser "0.1.1" +style-value-types@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/style-value-types/-/style-value-types-5.0.0.tgz#76c35f0e579843d523187989da866729411fc8ad" + integrity sha512-08yq36Ikn4kx4YU6RD7jWEv27v4V+PUsOGa4n/as8Et3CuODMJQ00ENeAVXAeydX4Z2j1XHZF1K2sX4mGl18fA== + dependencies: + hey-listen "^1.0.8" + tslib "^2.1.0" + stylehacks@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.1.1.tgz#7934a34eb59d7152149fa69d6e9e56f2fc34bcc9" @@ -19881,6 +20330,19 @@ svgo@^2.7.0, svgo@^2.8.0: picocolors "^1.0.0" stable "^0.1.8" +svgo@^3.0.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-3.3.2.tgz#ad58002652dffbb5986fc9716afe52d869ecbda8" + integrity sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw== + dependencies: + "@trysound/sax" "0.2.0" + commander "^7.2.0" + css-select "^5.1.0" + css-tree "^2.3.1" + css-what "^6.1.0" + csso "^5.0.5" + picocolors "^1.0.0" + swc-loader@^0.2.3: version "0.2.6" resolved "https://registry.yarnpkg.com/swc-loader/-/swc-loader-0.2.6.tgz#bf0cba8eeff34bb19620ead81d1277fefaec6bc8" @@ -19919,26 +20381,17 @@ synckit@^0.8.6: "@pkgr/core" "^0.1.0" tslib "^2.6.2" -table@^5.2.3: - version "5.4.6" - resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" - integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== +tailwind-merge@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/tailwind-merge/-/tailwind-merge-2.3.0.tgz#27d2134fd00a1f77eca22bcaafdd67055917d286" + integrity sha512-vkYrLpIP+lgR0tQCG6AP7zZXCTLc1Lnv/CCRT3BqJ9CZ3ui2++GPaGb1x/ILsINIMSYqqvrpqjUFsMNLlW99EA== dependencies: - ajv "^6.10.2" - lodash "^4.17.14" - slice-ansi "^2.1.0" - string-width "^3.0.0" + "@babel/runtime" "^7.24.1" -table@^6.0.9: - version "6.8.2" - resolved "https://registry.yarnpkg.com/table/-/table-6.8.2.tgz#c5504ccf201213fa227248bdc8c5569716ac6c58" - integrity sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA== - dependencies: - ajv "^8.0.1" - lodash.truncate "^4.4.2" - slice-ansi "^4.0.0" - string-width "^4.2.3" - strip-ansi "^6.0.1" +tailwindcss-animate@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz#318b692c4c42676cc9e67b19b78775742388bef4" + integrity sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA== tailwindcss@3.2.4: version "3.2.4" @@ -19990,9 +20443,9 @@ tar-fs@^2.0.0, tar-fs@^2.1.1: tar-stream "^2.1.4" tar-fs@^3.0.4: - version "3.0.5" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-3.0.5.tgz#f954d77767e4e6edf973384e1eb95f8f81d64ed9" - integrity sha512-JOgGAmZyMgbqpLwct7ZV8VzkEB6pxXFBVErLtb+XCOqzc6w1xiWKI9GVd6bwk68EX7eJ4DWmfXVmq8K2ziZTGg== + version "3.0.6" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-3.0.6.tgz#eaccd3a67d5672f09ca8e8f9c3d2b89fa173f217" + integrity sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w== dependencies: pump "^3.0.0" tar-stream "^3.1.5" @@ -20089,7 +20542,7 @@ tempy@^1.0.1: type-fest "^0.16.0" unique-string "^2.0.0" -terser-webpack-plugin@^5.1.1, terser-webpack-plugin@^5.1.4, terser-webpack-plugin@^5.3.1, terser-webpack-plugin@^5.3.10, terser-webpack-plugin@^5.3.3: +terser-webpack-plugin@^5.1.4, terser-webpack-plugin@^5.3.1, terser-webpack-plugin@^5.3.10, terser-webpack-plugin@^5.3.3, terser-webpack-plugin@^5.3.7: version "5.3.10" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== @@ -20101,9 +20554,9 @@ terser-webpack-plugin@^5.1.1, terser-webpack-plugin@^5.1.4, terser-webpack-plugi terser "^5.26.0" terser@^5.0.0, terser@^5.10.0, terser@^5.26.0: - version "5.30.3" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.30.3.tgz#f1bb68ded42408c316b548e3ec2526d7dd03f4d2" - integrity sha512-STdUgOUx8rLbMGO9IOwHLpCqolkDITFFQSMYYwKE1N2lY6MVSaeoi10z/EhWxRc6ybqoVmKSkhKYH/XUpl7vSA== + version "5.31.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.31.1.tgz#735de3c987dd671e95190e6b98cfe2f07f3cf0d4" + integrity sha512-37upzU1+viGvuFtBo9NPufCb9dwM0+l9hMxYyWfBA+fbwrPqNJAhbZ6W47bBFnZHKHTUBnMvi87434qq+qnxOg== dependencies: "@jridgewell/source-map" "^0.3.3" acorn "^8.8.2" @@ -20119,6 +20572,13 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" +text-decoder@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/text-decoder/-/text-decoder-1.1.1.tgz#5df9c224cebac4a7977720b9f083f9efa1aefde8" + integrity sha512-8zll7REEv4GDD3x4/0pW+ppIxSNs7H1J10IKFZsuOMscumCdM2a+toDGLPA3T+1+fLBql4zbt5z83GEQGGV5VA== + dependencies: + b4a "^1.6.4" + text-extensions@^1.0.0: version "1.9.0" resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26" @@ -20209,9 +20669,9 @@ to-regex-range@^5.0.1: is-number "^7.0.0" tocbot@^4.20.1: - version "4.25.0" - resolved "https://registry.yarnpkg.com/tocbot/-/tocbot-4.25.0.tgz#bc38aea5ec8f076779bb39636f431b044129a237" - integrity sha512-kE5wyCQJ40hqUaRVkyQ4z5+4juzYsv/eK+aqD97N62YH0TxFhzJvo22RUQQZdO3YnXAk42ZOfOpjVdy+Z0YokA== + version "4.28.2" + resolved "https://registry.yarnpkg.com/tocbot/-/tocbot-4.28.2.tgz#5a51b34cefd39f6b556b936b380a838a0a8c49ea" + integrity sha512-/MaSa9xI6mIo84IxqqliSCtPlH0oy7sLcY9s26qPMyH/2CxtZ2vNAXYlIdEQ7kjAkCQnc0rbLygf//F5c663oQ== toidentifier@1.0.1: version "1.0.1" @@ -20224,9 +20684,9 @@ totalist@^3.0.0: integrity sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ== tough-cookie@^4.1.2, tough-cookie@^4.1.3: - version "4.1.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf" - integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw== + version "4.1.4" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.4.tgz#945f1461b45b5a8c76821c33ea49c3ac192c1b36" + integrity sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag== dependencies: psl "^1.1.33" punycode "^2.1.1" @@ -20312,9 +20772,9 @@ tslib@^1.13.0, tslib@^1.9.0: integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.4.0, tslib@^2.4.1, tslib@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" - integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== + version "2.6.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" + integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== tuf-js@^1.1.7: version "1.1.7" @@ -20344,13 +20804,6 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== - dependencies: - prelude-ls "~1.1.2" - type-detect@4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" @@ -20449,9 +20902,9 @@ typed-array-length@^1.0.6: possible-typed-array-names "^1.0.0" typed-function@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/typed-function/-/typed-function-4.1.1.tgz#38ce3cae31f4f513bcb263563fdad27b2afa73e8" - integrity sha512-Pq1DVubcvibmm8bYcMowjVnnMwPVMeh0DIdA8ad8NZY2sJgapANJmiigSUwlt+EgXxpfIv8MWrQXTIzkfYZLYQ== + version "4.2.1" + resolved "https://registry.yarnpkg.com/typed-function/-/typed-function-4.2.1.tgz#19aa51847aa2dea9ef5e7fb7641c060179a74426" + integrity sha512-EGjWssW7Tsk4DGfE+5yluuljS1OGYWiI1J6e8puZz9nTMM51Oug8CD5Zo4gWMsOhq5BI+1bF+rWTm4Vbj3ivRA== typedarray-to-buffer@^3.1.5: version "3.1.5" @@ -20465,20 +20918,15 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== -typescript@4.6.4: +typescript@4.6.4, "typescript@>=3 < 6": version "4.6.4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.4.tgz#caa78bbc3a59e6a5c510d35703f6a09877ce45e9" integrity sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg== -"typescript@>=3 < 6": - version "5.4.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611" - integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== - ua-parser-js@^1.0.35: - version "1.0.37" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.37.tgz#b5dc7b163a5c1f0c510b08446aed4da92c46373f" - integrity sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ== + version "1.0.38" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.38.tgz#66bb0c4c0e322fe48edfe6d446df6042e62f25e2" + integrity sha512-Aq5ppTOfvrCMgAPneW1HfWj66Xi7XL+/mIy996R1/CLS/rcyJQm6QZdsKrUeivDFQ+Oc9Wyuwor8Ze8peEoUoQ== ufo@^1.4.0: version "1.5.3" @@ -20486,9 +20934,9 @@ ufo@^1.4.0: integrity sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw== uglify-js@^3.1.4: - version "3.17.4" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c" - integrity sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g== + version "3.18.0" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.18.0.tgz#73b576a7e8fda63d2831e293aeead73e0a270deb" + integrity sha512-SyVVbcNBCk0dzr9XL/R/ySrmYf0s372K6/hFklzgcp2lBFyXtw4I7BOdDjlLhE1aVqaI/SHWXWmYdlZxuyF38A== unbox-primitive@^1.0.2: version "1.0.2" @@ -20767,13 +21215,13 @@ upath@^1.2.0: resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== -update-browserslist-db@^1.0.13: - version "1.0.13" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" - integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== +update-browserslist-db@^1.0.16: + version "1.0.16" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz#f6d489ed90fb2f07d67784eb3f53d7891f736356" + integrity sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ== dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" + escalade "^3.1.2" + picocolors "^1.0.1" update-check@1.5.4: version "1.5.4" @@ -20803,7 +21251,7 @@ update-notifier@^5.1.0: semver-diff "^3.1.1" xdg-basedir "^4.0.0" -uri-js@^4.2.2: +uri-js@^4.2.2, uri-js@^4.4.1: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== @@ -20875,9 +21323,9 @@ use-sidecar@^1.1.2: tslib "^2.0.0" use-sync-external-store@^1.0.0, use-sync-external-store@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" - integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== + version "1.2.2" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz#c3b6390f3a30eba13200d2302dcdf1e7b57b2ef9" + integrity sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw== util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" @@ -20952,11 +21400,6 @@ v8-compile-cache@2.3.0: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== -v8-compile-cache@^2.0.3: - version "2.4.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz#cdada8bec61e15865f05d097c5f4fd30e94dc128" - integrity sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw== - v8-to-istanbul@^9.0.1: version "9.2.0" resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz#2ed7644a245cddd83d4e087b9b33b3e62dfd10ad" @@ -20974,7 +21417,7 @@ validate-npm-package-license@3.0.4, validate-npm-package-license@^3.0.1, validat spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -validate-npm-package-name@5.0.0, validate-npm-package-name@^5.0.0: +validate-npm-package-name@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz#f16afd48318e6f90a1ec101377fa0384cfc8c713" integrity sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ== @@ -20988,6 +21431,11 @@ validate-npm-package-name@^3.0.0: dependencies: builtins "^1.0.3" +validate-npm-package-name@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz#a316573e9b49f3ccd90dbb6eb52b3f06c6d604e8" + integrity sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ== + validate-peer-dependencies@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/validate-peer-dependencies/-/validate-peer-dependencies-2.2.0.tgz#47b8ff008f66a66fc5d8699123844522c1d874f4" @@ -21114,7 +21562,7 @@ warning@^4.0.3: dependencies: loose-envify "^1.0.0" -watchpack@^2.2.0, watchpack@^2.4.1: +watchpack@^2.2.0, watchpack@^2.4.0, watchpack@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.1.tgz#29308f2cac150fa8e4c92f90e0ec954a9fed7fff" integrity sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg== @@ -21171,7 +21619,7 @@ webidl-conversions@^7.0.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== -webpack-bundle-analyzer@^4.4.2, webpack-bundle-analyzer@^4.5.0: +webpack-bundle-analyzer@^4.5.0, webpack-bundle-analyzer@^4.8.0: version "4.10.2" resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.2.tgz#633af2862c213730be3dbdf40456db171b60d5bd" integrity sha512-vJptkMm9pk5si4Bv922ZbKLV8UTT4zib4FPgXMhgzUny0bfDDkLXAVQs3ly3fS4/TN9ROFtb0NFrm04UXFE/Vw== @@ -21309,15 +21757,7 @@ webpack-hot-middleware@^2.25.0, webpack-hot-middleware@^2.25.1: html-entities "^2.1.0" strip-ansi "^6.0.0" -webpack-merge@5.7.3: - version "5.7.3" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.7.3.tgz#2a0754e1877a25a8bbab3d2475ca70a052708213" - integrity sha512-6/JUQv0ELQ1igjGDzHkXbVDRxkfA57Zw7PfiupdLFJYrgFqY5ZP8xxbpp2lU3EPwYx89ht5Z/aDkD40hFCm5AA== - dependencies: - clone-deep "^4.0.1" - wildcard "^2.0.0" - -webpack-merge@^5.7.3, webpack-merge@^5.8.0: +webpack-merge@*, webpack-merge@^5.7.3, webpack-merge@^5.8.0: version "5.10.0" resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.10.0.tgz#a3ad5d773241e9c682803abf628d4cd62b8a4177" integrity sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA== @@ -21345,14 +21785,14 @@ webpack-virtual-modules@^0.5.0: integrity sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw== webpack-virtual-modules@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/webpack-virtual-modules/-/webpack-virtual-modules-0.6.1.tgz#ac6fdb9c5adb8caecd82ec241c9631b7a3681b6f" - integrity sha512-poXpCylU7ExuvZK8z+On3kX+S8o/2dQ/SVYueKA0D4WEMXROXgY8Ez50/bQEUmvoSMMrWcrJqCHuhAbsiwg7Dg== + version "0.6.2" + resolved "https://registry.yarnpkg.com/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz#057faa9065c8acf48f24cb57ac0e77739ab9a7e8" + integrity sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ== -webpack@5, webpack@^5.50.0, webpack@^5.73.0, webpack@^5.81.0, webpack@^5.90.3: - version "5.91.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.91.0.tgz#ffa92c1c618d18c878f06892bbdc3373c71a01d9" - integrity sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw== +webpack@5, webpack@^5.73.0: + version "5.92.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.92.0.tgz#cc114c71e6851d220b1feaae90159ed52c876bdf" + integrity sha512-Bsw2X39MYIgxouNATyVpCNVWBCuUwDgWtN78g6lSdPJRLaQ/PUVm/oXcaRAyY/sMFoKFQrsPeqvTizWtq7QPCA== dependencies: "@types/eslint-scope" "^3.7.3" "@types/estree" "^1.0.5" @@ -21360,10 +21800,10 @@ webpack@5, webpack@^5.50.0, webpack@^5.73.0, webpack@^5.81.0, webpack@^5.90.3: "@webassemblyjs/wasm-edit" "^1.12.1" "@webassemblyjs/wasm-parser" "^1.12.1" acorn "^8.7.1" - acorn-import-assertions "^1.9.0" + acorn-import-attributes "^1.9.5" browserslist "^4.21.10" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.16.0" + enhanced-resolve "^5.17.0" es-module-lexer "^1.2.1" eslint-scope "5.1.1" events "^3.2.0" @@ -21379,6 +21819,36 @@ webpack@5, webpack@^5.50.0, webpack@^5.73.0, webpack@^5.81.0, webpack@^5.90.3: watchpack "^2.4.1" webpack-sources "^3.2.3" +webpack@5.89.0: + version "5.89.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.89.0.tgz#56b8bf9a34356e93a6625770006490bf3a7f32dc" + integrity sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw== + dependencies: + "@types/eslint-scope" "^3.7.3" + "@types/estree" "^1.0.0" + "@webassemblyjs/ast" "^1.11.5" + "@webassemblyjs/wasm-edit" "^1.11.5" + "@webassemblyjs/wasm-parser" "^1.11.5" + acorn "^8.7.1" + acorn-import-assertions "^1.9.0" + browserslist "^4.14.5" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.15.0" + es-module-lexer "^1.2.1" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.9" + json-parse-even-better-errors "^2.3.1" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.2.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.3.7" + watchpack "^2.4.0" + webpack-sources "^3.2.3" + webpackbar@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/webpackbar/-/webpackbar-5.0.2.tgz#d3dd466211c73852741dfc842b7556dcbc2b0570" @@ -21484,7 +21954,7 @@ which-collection@^1.0.1: is-weakmap "^2.0.2" is-weakset "^2.0.3" -which-typed-array@^1.1.14, which-typed-array@^1.1.15, which-typed-array@^1.1.2, which-typed-array@^1.1.9: +which-typed-array@^1.1.13, which-typed-array@^1.1.14, which-typed-array@^1.1.15, which-typed-array@^1.1.2, which-typed-array@^1.1.9: version "1.1.15" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== @@ -21542,7 +22012,7 @@ wildcard@^2.0.0: resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== -word-wrap@~1.2.3: +word-wrap@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== @@ -21729,7 +22199,7 @@ worker-loader@3.0.8, worker-loader@^3.0.8: loader-utils "^2.0.0" schema-utils "^3.0.0" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -21755,6 +22225,15 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.0.1, wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" @@ -21825,29 +22304,22 @@ write-pkg@4.0.0: type-fest "^0.4.1" write-json-file "^3.2.0" -write@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" - integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== - dependencies: - mkdirp "^0.5.1" - ws@^6.1.0: - version "6.2.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.2.tgz#dd5cdbd57a9979916097652d78f1cc5faea0c32e" - integrity sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw== + version "6.2.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.3.tgz#ccc96e4add5fd6fedbc491903075c85c5a11d9ee" + integrity sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA== dependencies: async-limiter "~1.0.0" ws@^7.3.1: - version "7.5.9" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" - integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== + version "7.5.10" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" + integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== ws@^8.1.0, ws@^8.11.0, ws@^8.13.0, ws@^8.2.3: - version "8.16.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.16.0.tgz#d1cd774f36fbc07165066a60e40323eab6446fd4" - integrity sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ== + version "8.17.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" + integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== xdg-basedir@^4.0.0: version "4.0.0" @@ -21867,9 +22339,9 @@ xml-name-validator@^4.0.0: integrity sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw== xml-utils@^1.0.2: - version "1.8.0" - resolved "https://registry.yarnpkg.com/xml-utils/-/xml-utils-1.8.0.tgz#dd9baa161012849b97703d8423d09d9d815a5910" - integrity sha512-1TY5yLw8DApowZAUsWCniNr8HH6Ebt6O7UQvmIwziGKwUNsQx6e+4NkfOvCfnqmYIcPjCeoI6dh1JenPJ9a1hQ== + version "1.10.1" + resolved "https://registry.yarnpkg.com/xml-utils/-/xml-utils-1.10.1.tgz#fa0c9b38545760532d4cf89003f90c3b24e7200f" + integrity sha512-Dn6vJ1Z9v1tepSjvnCpwk5QqwIPcEFKdgnjqfYOABv1ngSofuAhtlugcUC3ehS1OHdgDWSG6C5mvj+Qm15udTQ== xml@^1.0.1: version "1.0.1"