Compare commits
28
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
db16341a4f | ||
|
|
0fcf3a9dc1 | ||
|
|
75a24a3393 | ||
|
|
104de8d833 | ||
|
|
647fd025cf | ||
|
|
3fc8706126 | ||
|
|
539ff44f47 | ||
|
|
146897f216 | ||
|
|
a264413124 | ||
|
|
838f51957e | ||
|
|
bab20143fd | ||
|
|
946735bf90 | ||
|
|
a5be4c3dce | ||
|
|
171ea857cf | ||
|
|
9754fc1e92 | ||
|
|
6772deb4c6 | ||
|
|
1d0a8744b2 | ||
|
|
555c87f1c5 | ||
|
|
51d267e707 | ||
|
|
c5c18f9516 | ||
|
|
213a0974bb | ||
|
|
0d882a425d | ||
|
|
49ea3ac82b | ||
|
|
99736b6437 | ||
|
|
7fb67d2396 | ||
|
|
04b121c1ba | ||
|
|
9782980a7a | ||
|
|
27b1afe040 |
No files matched your search
+56
-67
@@ -112,6 +112,62 @@ jobs:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: ~/repo
|
||||
# SECURITY AUDIT - only when bun.lock has changed
|
||||
- run:
|
||||
name: 'Security Audit - High Risk Vulnerabilities'
|
||||
command: |
|
||||
git fetch origin master 2>/dev/null || true
|
||||
BASE_REF=$(git merge-base HEAD origin/master 2>/dev/null)
|
||||
if [[ -z "$BASE_REF" ]]; then
|
||||
echo "Could not determine base ref (e.g. shallow clone or no origin/master), skipping security audit."
|
||||
exit 0
|
||||
fi
|
||||
CHANGED_FILES=$(git diff --name-only origin/master...HEAD 2>/dev/null || echo "")
|
||||
if ! echo "$CHANGED_FILES" | grep -qx 'bun.lock'; then
|
||||
echo "⏭️ bun.lock unchanged - skipping security audit."
|
||||
exit 0
|
||||
fi
|
||||
echo "🔍 bun.lock changed - running bun audit for security vulnerabilities..."
|
||||
echo "Checking for HIGH-RISK vulnerabilities..."
|
||||
|
||||
# Define ignored vulnerabilities with comments
|
||||
IGNORED_VULNS=(
|
||||
"GHSA-3ppc-4f35-3m26" # CVE-2026-26996 - minimatch via itk-wasm and glob is safe because it does NOT use the CLI
|
||||
# CVE-2026-26996 - minimatch via other packages are strictly for building and CI/CD purposes; no user supplied expressions are passed to minimatch
|
||||
"GHSA-7r86-cg39-jmmj" # CVE-2026-27903 - minimatch same as above
|
||||
"GHSA-23c5-xmqv-rm74" # CVE-2026-27904 - minimatch same as above
|
||||
"GHSA-c2c7-rcm5-vvqj" # CVE-2026-33671 - picomatch is generally used for development and CI/CD purposes
|
||||
)
|
||||
|
||||
# Build ignore flags
|
||||
IGNORE_FLAGS=""
|
||||
for vuln in "${IGNORED_VULNS[@]}"; do
|
||||
IGNORE_FLAGS="$IGNORE_FLAGS --ignore=$vuln"
|
||||
done
|
||||
|
||||
if bun audit $IGNORE_FLAGS --audit-level high; then
|
||||
echo "✅ No high-risk vulnerabilities found"
|
||||
echo "🎉 Security audit passed!"
|
||||
else
|
||||
echo ""
|
||||
echo "❌ HIGH-RISK VULNERABILITIES DETECTED!"
|
||||
echo "======================================"
|
||||
echo ""
|
||||
echo "🔧 To fix these issues:"
|
||||
echo " 1. Run: bun audit"
|
||||
echo " 2. Review the vulnerability details"
|
||||
echo " 3. Update affected packages to secure versions"
|
||||
echo " 4. Test your changes"
|
||||
echo " 5. Re-run: bun audit --audit-level high"
|
||||
echo ""
|
||||
echo "📋 Full audit report:"
|
||||
|
||||
bun audit $IGNORE_FLAGS --audit-level low || true
|
||||
|
||||
echo ""
|
||||
echo "❌ This build cannot proceed until high-risk vulnerabilities are resolved."
|
||||
exit 1
|
||||
fi
|
||||
- run:
|
||||
name: Install Dependencies
|
||||
command: bun install --frozen-lockfile
|
||||
@@ -350,69 +406,6 @@ jobs:
|
||||
npx wait-on@latest http://localhost:3000 && cd platform/app && npx cypress run --record --parallel
|
||||
start-command: yarn run test:data && yarn run test:e2e:serve
|
||||
|
||||
SECURITY_AUDIT:
|
||||
<<: *defaults
|
||||
resource_class: large
|
||||
steps:
|
||||
- install_bun
|
||||
- checkout
|
||||
- run:
|
||||
name: 'Security Audit - High Risk Vulnerabilities'
|
||||
command: |
|
||||
git fetch origin master 2>/dev/null || true
|
||||
BASE_REF=$(git merge-base HEAD origin/master 2>/dev/null)
|
||||
if [[ -z "$BASE_REF" ]]; then
|
||||
echo "Could not determine base ref (e.g. shallow clone or no origin/master), skipping security audit."
|
||||
exit 0
|
||||
fi
|
||||
CHANGED_FILES=$(git diff --name-only origin/master...HEAD 2>/dev/null || echo "")
|
||||
if ! echo "$CHANGED_FILES" | grep -qx 'bun.lock'; then
|
||||
echo "⏭️ bun.lock unchanged - skipping security audit."
|
||||
exit 0
|
||||
fi
|
||||
echo "🔍 bun.lock changed - running bun audit for security vulnerabilities..."
|
||||
echo "Checking for HIGH-RISK vulnerabilities..."
|
||||
|
||||
# Define ignored vulnerabilities with comments
|
||||
IGNORED_VULNS=(
|
||||
"GHSA-3ppc-4f35-3m26" # CVE-2026-26996 - minimatch via itk-wasm and glob is safe because it does NOT use the CLI
|
||||
# CVE-2026-26996 - minimatch via other packages are strictly for building and CI/CD purposes; no user supplied expressions are passed to minimatch
|
||||
"GHSA-7r86-cg39-jmmj" # CVE-2026-27903 - minimatch same as above
|
||||
"GHSA-23c5-xmqv-rm74" # CVE-2026-27904 - minimatch same as above
|
||||
"GHSA-c2c7-rcm5-vvqj" # CVE-2026-33671 - picomatch is generally used for development and CI/CD purposes
|
||||
)
|
||||
|
||||
# Build ignore flags
|
||||
IGNORE_FLAGS=""
|
||||
for vuln in "${IGNORED_VULNS[@]}"; do
|
||||
IGNORE_FLAGS="$IGNORE_FLAGS --ignore=$vuln"
|
||||
done
|
||||
|
||||
if bun audit $IGNORE_FLAGS --audit-level high; then
|
||||
echo "✅ No high-risk vulnerabilities found"
|
||||
echo "🎉 Security audit passed!"
|
||||
exit 0
|
||||
else
|
||||
echo ""
|
||||
echo "❌ HIGH-RISK VULNERABILITIES DETECTED!"
|
||||
echo "======================================"
|
||||
echo ""
|
||||
echo "🔧 To fix these issues:"
|
||||
echo " 1. Run: bun audit"
|
||||
echo " 2. Review the vulnerability details"
|
||||
echo " 3. Update affected packages to secure versions"
|
||||
echo " 4. Test your changes"
|
||||
echo " 5. Re-run: bun audit --audit-level high"
|
||||
echo ""
|
||||
echo "📋 Full audit report:"
|
||||
|
||||
bun audit $IGNORE_FLAGS --audit-level low || true
|
||||
|
||||
echo ""
|
||||
echo "❌ This build cannot proceed until high-risk vulnerabilities are resolved."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
DOCKER_MULTIARCH_MANIFEST:
|
||||
<<: *defaults
|
||||
resource_class: large
|
||||
@@ -502,10 +495,6 @@ workflows:
|
||||
- CYPRESS:
|
||||
name: 'Cypress Tests'
|
||||
context: cypress
|
||||
- SECURITY_AUDIT:
|
||||
filters:
|
||||
branches:
|
||||
ignore: master
|
||||
|
||||
# viewer-dev.ohif.org
|
||||
DEPLOY_MASTER:
|
||||
|
||||
@@ -2,19 +2,6 @@ name: Playwright Tests
|
||||
on:
|
||||
pull_request:
|
||||
branches: [master, release/*]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
cs3d_ref:
|
||||
description: >-
|
||||
CS3D branch (e.g. main, origin:feat/foo) or version (e.g. 4.18.2, 4.19+, 4.x). Only used
|
||||
when ohif-integration label is present or via workflow_dispatch.
|
||||
required: false
|
||||
default: '4.19+'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
issues: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
@@ -22,7 +9,7 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
playwright-tests:
|
||||
timeout-minutes: 120
|
||||
timeout-minutes: 60
|
||||
runs-on: self-hosted
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -38,85 +25,14 @@ jobs:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Install Yarn
|
||||
run: npm install -g yarn@1.22.22
|
||||
|
||||
# ── CS3D integration: detect label and ref type ──────────────────────
|
||||
- name: Check for CS3D integration label
|
||||
id: cs3d-check
|
||||
run: bash .scripts/ci/cs3d-check-integration.sh
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
CS3D_REF_INPUT: ${{ github.event.inputs.cs3d_ref || '4.19+' }}
|
||||
REPO: ${{ github.repository }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
|
||||
- name: Detect CS3D ref type
|
||||
id: cs3d-ref
|
||||
if: steps.cs3d-check.outputs.enabled == 'true'
|
||||
run: |
|
||||
REF="${CS3D_REF}"
|
||||
if [[ "$REF" =~ ^[0-9]+\.[0-9x]+\+?(\.[0-9x]+)?(-[a-zA-Z0-9._]+)?$ ]]; then
|
||||
echo "type=version" >> "$GITHUB_OUTPUT"
|
||||
RESOLVED=$(node .scripts/cs3d-resolve-version.mjs "$REF")
|
||||
echo "version=$RESOLVED" >> "$GITHUB_OUTPUT"
|
||||
echo "::notice::CS3D version: $REF -> $RESOLVED"
|
||||
else
|
||||
echo "type=branch" >> "$GITHUB_OUTPUT"
|
||||
echo "::notice::CS3D branch: $REF"
|
||||
fi
|
||||
env:
|
||||
CS3D_REF: ${{ steps.cs3d-check.outputs.cs3d_ref }}
|
||||
|
||||
# ── CS3D branch path: clone and build before OHIF install ───────────
|
||||
- name: Clone CS3D
|
||||
if: steps.cs3d-check.outputs.enabled == 'true' && steps.cs3d-ref.outputs.type == 'branch'
|
||||
run: |
|
||||
REF="${CS3D_REF}"
|
||||
if [[ "$REF" == *:* ]]; then
|
||||
REPO="https://github.com/${REF%%:*}/cornerstone3D.git"
|
||||
BRANCH="${REF#*:}"
|
||||
else
|
||||
REPO="https://github.com/cornerstonejs/cornerstone3D.git"
|
||||
BRANCH="$REF"
|
||||
fi
|
||||
echo "::notice::Cloning CS3D from $REPO branch $BRANCH"
|
||||
git clone --depth 1 --branch "$BRANCH" "$REPO" libs/@cornerstonejs
|
||||
env:
|
||||
CS3D_REF: ${{ steps.cs3d-check.outputs.cs3d_ref }}
|
||||
|
||||
- name: Install & Build CS3D
|
||||
if: steps.cs3d-check.outputs.enabled == 'true' && steps.cs3d-ref.outputs.type == 'branch'
|
||||
working-directory: libs/@cornerstonejs
|
||||
run: bun install --frozen-lockfile && bun run build:esm
|
||||
|
||||
# ── Common: install OHIF dependencies ───────────────────────────────
|
||||
- name: Install dependencies
|
||||
run: bun install --frozen-lockfile
|
||||
|
||||
# ── CS3D branch path: link packages after OHIF install ──────────────
|
||||
- name: Link CS3D packages
|
||||
if: steps.cs3d-check.outputs.enabled == 'true' && steps.cs3d-ref.outputs.type == 'branch'
|
||||
working-directory: libs/@cornerstonejs
|
||||
run: node scripts/link-ohif-cornerstone-node-modules.mjs "$GITHUB_WORKSPACE"
|
||||
|
||||
# ── CS3D version path: update versions after OHIF install ───────────
|
||||
- name: Set CS3D version
|
||||
if: steps.cs3d-check.outputs.enabled == 'true' && steps.cs3d-ref.outputs.type == 'version'
|
||||
run: |
|
||||
node .scripts/cs3d-set-version.mjs "${CS3D_VERSION}"
|
||||
bun install
|
||||
env:
|
||||
CS3D_VERSION: ${{ steps.cs3d-ref.outputs.version }}
|
||||
|
||||
# ── Common: run tests ───────────────────────────────────────────────
|
||||
- name: Install Playwright browsers
|
||||
run: npx playwright install
|
||||
- name: Run Playwright tests
|
||||
run: |
|
||||
export NODE_OPTIONS="--max_old_space_size=10192"
|
||||
bun run test:e2e:coverage
|
||||
|
||||
# ── Common: collect test results and coverage ───────────────────────
|
||||
- name: Create directory of test results
|
||||
if: ${{ !cancelled() }}
|
||||
run: |
|
||||
@@ -140,70 +56,3 @@ jobs:
|
||||
name: coverage-report-pr
|
||||
path: coverage
|
||||
retention-days: 3
|
||||
|
||||
# ── CS3D: build and deploy preview to Netlify ───────────────────────
|
||||
- name: Log build context (OHIF/CS3D branch and version for build diagnosis)
|
||||
if: steps.cs3d-check.outputs.enabled == 'true'
|
||||
run: |
|
||||
if [[ "$CS3D_REF_TYPE" == "branch" ]]; then
|
||||
echo "::notice::Build type: ohif-downstream | OHIF: ${{ github.repository }}@${{ github.ref }} (${{ github.sha }}) | CS3D: branch ${{ steps.cs3d-check.outputs.cs3d_ref }}"
|
||||
else
|
||||
echo "::notice::Build type: ohif-upstream | OHIF: ${{ github.repository }}@${{ github.ref }} (${{ github.sha }}) | CS3D: version ${{ steps.cs3d-ref.outputs.version }}"
|
||||
fi
|
||||
node .scripts/log-build-context.mjs
|
||||
env:
|
||||
BUILD_TYPE: ${{ steps.cs3d-ref.outputs.type == 'branch' && 'ohif-downstream' || 'ohif-upstream' }}
|
||||
CS3D_REF_TYPE: ${{ steps.cs3d-ref.outputs.type }}
|
||||
|
||||
- name: Build OHIF viewer (CS3D preview)
|
||||
if: steps.cs3d-check.outputs.enabled == 'true'
|
||||
run: bun run build:ci
|
||||
|
||||
- name: Deploy CS3D preview to Netlify
|
||||
if: steps.cs3d-check.outputs.enabled == 'true'
|
||||
run: |
|
||||
RESULT=$(npx netlify-cli deploy --dir=platform/app/dist --alias="cs3d-pr-${PR_NUM}" --json --filter=@ohif/app) || {
|
||||
echo "::error::Netlify deploy command failed"
|
||||
exit 1
|
||||
}
|
||||
URL=$(echo "$RESULT" | jq -r '.deploy_url')
|
||||
if [[ -z "$URL" || "$URL" == "null" ]]; then
|
||||
echo "::error::Netlify deploy did not return a valid URL"
|
||||
echo "$RESULT"
|
||||
exit 1
|
||||
fi
|
||||
echo "::notice::CS3D preview deployed: $URL"
|
||||
env:
|
||||
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
||||
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
|
||||
PR_NUM: ${{ github.event.pull_request.number || 'manual' }}
|
||||
|
||||
# ── CS3D: log results ───────────────────────────────────────────────
|
||||
- name: Log CS3D build used
|
||||
if: steps.cs3d-check.outputs.enabled == 'true'
|
||||
run: |
|
||||
if [[ "$CS3D_REF_TYPE" == "branch" ]]; then
|
||||
echo "::notice::CS3D integration PASSED with branch ${CS3D_REF} (linked from libs/@cornerstonejs)"
|
||||
else
|
||||
echo "::notice::CS3D integration PASSED with @cornerstonejs/*@${CS3D_VERSION}"
|
||||
fi
|
||||
env:
|
||||
CS3D_REF_TYPE: ${{ steps.cs3d-ref.outputs.type }}
|
||||
CS3D_REF: ${{ steps.cs3d-check.outputs.cs3d_ref }}
|
||||
CS3D_VERSION: ${{ steps.cs3d-ref.outputs.version }}
|
||||
|
||||
# ── Separate job: block merge when using a CS3D branch ─────────────
|
||||
cs3d-branch-merge-guard:
|
||||
name: "CS3D Branch Merge Guard"
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Check for CS3D branch usage
|
||||
run: bash .scripts/ci/cs3d-branch-merge-guard.sh
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
CS3D_REF_INPUT: ${{ github.event.inputs.cs3d_ref || '4.19+' }}
|
||||
REPO: ${{ github.repository }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
@@ -61,13 +61,5 @@ tests/playwright-report/
|
||||
|
||||
**/.claude/settings.local.json
|
||||
|
||||
# cornerstone3D local linking
|
||||
libs/
|
||||
|
||||
# Backup files
|
||||
*~
|
||||
|
||||
# cornerstone3D local linking
|
||||
libs/
|
||||
link-cs3d.js
|
||||
unlink-cs3d.js
|
||||
@@ -1,42 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# CS3D branch merge guard: blocks merge when tests ran against a CS3D branch (not a version).
|
||||
# Exits 0 when merge is allowed or guard is skipped; exits 1 when merge must be blocked.
|
||||
#
|
||||
# Required env: GH_TOKEN, EVENT_NAME, REPO, PR_NUMBER
|
||||
# Optional env: CS3D_REF_INPUT (for workflow_dispatch, default 4.19+)
|
||||
|
||||
set -e
|
||||
|
||||
if [[ "$EVENT_NAME" == "workflow_dispatch" ]]; then
|
||||
echo "::notice::workflow_dispatch — no merge to block, skipping guard."
|
||||
exit 0
|
||||
elif [[ "$EVENT_NAME" == "pull_request" ]]; then
|
||||
LABELS=$(gh api "repos/${REPO}/issues/${PR_NUMBER}/labels" --jq '.[].name')
|
||||
if echo "$LABELS" | grep -q "ohif-integration"; then
|
||||
ENABLED=true
|
||||
CS3D_REF=$(gh api "repos/${REPO}/pulls/${PR_NUMBER}" --jq '.body' \
|
||||
| sed -n 's/^[[:space:]]*CS3D_REF:[[:space:]]*\([^[:space:]]*\).*/\1/p' | head -1)
|
||||
if [[ -z "$CS3D_REF" ]]; then
|
||||
CS3D_REF="4.19+"
|
||||
fi
|
||||
else
|
||||
ENABLED=false
|
||||
fi
|
||||
else
|
||||
ENABLED=false
|
||||
fi
|
||||
|
||||
if [[ "$ENABLED" != "true" ]]; then
|
||||
echo "::notice::No ohif-integration label — skipping merge guard."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check if the ref is a branch (not a version)
|
||||
if [[ "$CS3D_REF" =~ ^[0-9]+\.[0-9x]+\+?(\.[0-9x]+)?(-[a-zA-Z0-9._]+)?$ ]]; then
|
||||
echo "::notice::CS3D ref '$CS3D_REF' is a version — merge allowed."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "::error::Tests ran against CS3D branch '${CS3D_REF}' — this build cannot be merged."
|
||||
echo "::error::Re-run with a published CS3D version (e.g. 4.19+) before merging."
|
||||
exit 1
|
||||
@@ -1,29 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# CS3D integration check: detects ohif-integration label and parses CS3D_REF.
|
||||
# Writes to GITHUB_OUTPUT: enabled (true|false), cs3d_ref (when enabled).
|
||||
#
|
||||
# Required env: GH_TOKEN, EVENT_NAME, REPO, PR_NUMBER, GITHUB_OUTPUT
|
||||
# Optional env: CS3D_REF_INPUT (for workflow_dispatch, default 4.19+)
|
||||
|
||||
set -e
|
||||
|
||||
if [[ "$EVENT_NAME" == "workflow_dispatch" ]]; then
|
||||
echo "enabled=true" >> "$GITHUB_OUTPUT"
|
||||
echo "cs3d_ref=${CS3D_REF_INPUT:-4.19+}" >> "$GITHUB_OUTPUT"
|
||||
elif [[ "$EVENT_NAME" == "pull_request" ]]; then
|
||||
LABELS=$(gh api "repos/${REPO}/issues/${PR_NUMBER}/labels" --jq '.[].name')
|
||||
if echo "$LABELS" | grep -q "ohif-integration"; then
|
||||
echo "enabled=true" >> "$GITHUB_OUTPUT"
|
||||
REF=$(gh api "repos/${REPO}/pulls/${PR_NUMBER}" --jq '.body' \
|
||||
| sed -n 's/^[[:space:]]*CS3D_REF:[[:space:]]*\([^[:space:]]*\).*/\1/p' | head -1)
|
||||
if [[ -z "$REF" ]]; then
|
||||
REF="4.19+"
|
||||
fi
|
||||
echo "cs3d_ref=${REF}" >> "$GITHUB_OUTPUT"
|
||||
echo "::notice::CS3D ref from PR body: ${REF}"
|
||||
else
|
||||
echo "enabled=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
else
|
||||
echo "enabled=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
@@ -1,63 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Resolves a version pattern to a concrete npm version of @cornerstonejs/core.
|
||||
*
|
||||
* Patterns:
|
||||
* 4.18.2 -> 4.18.2 (exact, returned as-is)
|
||||
* 4.18.2-beta.3 -> 4.18.2-beta.3 (exact prerelease)
|
||||
* 4.x -> latest 4.* from npm
|
||||
* 4.17.x -> latest 4.17.* from npm
|
||||
* 4.19+ -> latest >=4.19.0 <5.0.0-0 from npm (4.19 and later, same major)
|
||||
*
|
||||
* Prints the resolved version to stdout.
|
||||
*/
|
||||
|
||||
import { execSync } from 'child_process';
|
||||
|
||||
const pattern = process.argv[2];
|
||||
if (!pattern) {
|
||||
console.error('Usage: cs3d-resolve-version.mjs <pattern>');
|
||||
console.error(' e.g. 4.x, 4.17.x, 4.19+, 4.18.2, 4.18.2-beta.3');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Exact version (no wildcard or range) — pass through unchanged
|
||||
if (!pattern.includes('x') && !pattern.endsWith('+')) {
|
||||
console.log(pattern);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Convert "M.m+" to npm semver range ">=M.m.0 <(M+1).0.0-0"
|
||||
let npmRange = pattern;
|
||||
const plusMatch = pattern.match(/^(\d+)\.(\d+)\+$/);
|
||||
if (plusMatch) {
|
||||
const major = Number(plusMatch[1]);
|
||||
const minor = Number(plusMatch[2]);
|
||||
npmRange = `>=${major}.${minor}.0 <${major + 1}.0.0-0`;
|
||||
}
|
||||
|
||||
try {
|
||||
// Let npm resolve the range: @package@<range> → concrete version
|
||||
const raw = execSync(`npm view @cornerstonejs/core@"${npmRange}" version --json`, {
|
||||
encoding: 'utf8',
|
||||
timeout: 30_000,
|
||||
});
|
||||
|
||||
const resolved = JSON.parse(raw);
|
||||
if (!resolved) {
|
||||
console.error(`npm returned no version when resolving @cornerstonejs/core@${npmRange}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// npm may return an array of versions for ranges; pick the latest (last) one
|
||||
const version = Array.isArray(resolved) ? resolved[resolved.length - 1] : resolved;
|
||||
console.log(version);
|
||||
} catch (err) {
|
||||
const message =
|
||||
(err && (err.stderr?.toString() || err.message || String(err))) ||
|
||||
`Unknown error resolving @cornerstonejs/core@${pattern}`;
|
||||
console.error(`Failed to resolve @cornerstonejs/core version for pattern "${pattern}":`);
|
||||
console.error(message);
|
||||
process.exit(1);
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Updates all @cornerstonejs/* package versions across the OHIF workspace.
|
||||
*
|
||||
* Usage: node .scripts/cs3d-set-version.mjs <version>
|
||||
*
|
||||
* Only updates the 8 main CS3D packages (not codec packages):
|
||||
* adapters, ai, core, dicom-image-loader, labelmap-interpolation,
|
||||
* nifti-volume-loader, polymorphic-segmentation, tools
|
||||
*/
|
||||
|
||||
import { readFileSync, writeFileSync, existsSync, readdirSync } from 'fs';
|
||||
import { resolve, dirname, join } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const rootDir = resolve(__dirname, '..');
|
||||
|
||||
const version = process.argv[2];
|
||||
if (!version) {
|
||||
console.error('Usage: cs3d-set-version.mjs <version>');
|
||||
console.error(' e.g. 4.18.2, 4.19.0-beta.1');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// The 8 CS3D packages that are built from source (not codecs)
|
||||
const CS3D_PACKAGES = [
|
||||
'@cornerstonejs/adapters',
|
||||
'@cornerstonejs/ai',
|
||||
'@cornerstonejs/core',
|
||||
'@cornerstonejs/dicom-image-loader',
|
||||
'@cornerstonejs/labelmap-interpolation',
|
||||
'@cornerstonejs/nifti-volume-loader',
|
||||
'@cornerstonejs/polymorphic-segmentation',
|
||||
'@cornerstonejs/tools',
|
||||
];
|
||||
|
||||
// Read root package.json to get workspace globs
|
||||
const rootPkgPath = resolve(rootDir, 'package.json');
|
||||
const rootPkg = JSON.parse(readFileSync(rootPkgPath, 'utf8'));
|
||||
const workspaceGlobs = rootPkg.workspaces?.packages || rootPkg.workspaces || [];
|
||||
|
||||
// Collect all package.json paths from workspace globs
|
||||
function findWorkspacePackageJsons() {
|
||||
const paths = [rootPkgPath]; // include root
|
||||
|
||||
for (const pattern of workspaceGlobs) {
|
||||
const parts = pattern.split('/');
|
||||
let searchDir = rootDir;
|
||||
let hasWildcard = false;
|
||||
|
||||
for (const part of parts) {
|
||||
if (part === '*') {
|
||||
hasWildcard = true;
|
||||
break;
|
||||
}
|
||||
searchDir = join(searchDir, part);
|
||||
}
|
||||
|
||||
if (hasWildcard) {
|
||||
try {
|
||||
const entries = readdirSync(searchDir, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
if (entry.isDirectory()) {
|
||||
const pkgJson = join(searchDir, entry.name, 'package.json');
|
||||
if (existsSync(pkgJson)) {
|
||||
paths.push(pkgJson);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// directory doesn't exist, skip
|
||||
}
|
||||
} else {
|
||||
const pkgJson = join(rootDir, pattern, 'package.json');
|
||||
if (existsSync(pkgJson)) {
|
||||
paths.push(pkgJson);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
// Update a dependencies object, returning count of changes
|
||||
function updateDeps(deps, targetVersion) {
|
||||
let count = 0;
|
||||
if (!deps) return count;
|
||||
for (const pkg of CS3D_PACKAGES) {
|
||||
if (pkg in deps && deps[pkg] !== targetVersion) {
|
||||
deps[pkg] = targetVersion;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
const pkgPaths = findWorkspacePackageJsons();
|
||||
let totalChanges = 0;
|
||||
|
||||
for (const pkgPath of pkgPaths) {
|
||||
const content = readFileSync(pkgPath, 'utf8');
|
||||
const pkg = JSON.parse(content);
|
||||
let changes = 0;
|
||||
|
||||
changes += updateDeps(pkg.dependencies, version);
|
||||
changes += updateDeps(pkg.devDependencies, version);
|
||||
changes += updateDeps(pkg.peerDependencies, version);
|
||||
changes += updateDeps(pkg.resolutions, version);
|
||||
|
||||
if (changes > 0) {
|
||||
// Preserve original formatting (detect indent)
|
||||
const indent = content.match(/^(\s+)/m)?.[1] || ' ';
|
||||
writeFileSync(pkgPath, JSON.stringify(pkg, null, indent) + '\n');
|
||||
const rel = pkgPath.replace(rootDir + '/', '').replace(rootDir + '\\', '');
|
||||
console.log(` Updated ${rel} (${changes} packages)`);
|
||||
totalChanges += changes;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(
|
||||
`\nDone: ${totalChanges} version(s) updated to ${version} across ${pkgPaths.length} package files.`
|
||||
);
|
||||
@@ -1,108 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Logs build context (OHIF branch/version, CS3D source) for diagnosing build issues on GitHub.
|
||||
* Run from repo root. Used by version.mjs and can be invoked from CI workflows.
|
||||
*/
|
||||
import { execa } from 'execa';
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const REPO_ROOT = path.resolve(__dirname, '..');
|
||||
|
||||
function log(msg) {
|
||||
console.log(`[build-context] ${msg}`);
|
||||
}
|
||||
|
||||
async function detectCs3dSource() {
|
||||
const libsCs3d = path.join(REPO_ROOT, 'libs/@cornerstonejs');
|
||||
const coreInNodeModules = path.join(REPO_ROOT, 'node_modules/@cornerstonejs/core');
|
||||
|
||||
try {
|
||||
const libsExists = await fs.access(libsCs3d).then(() => true).catch(() => false);
|
||||
if (!libsExists) {
|
||||
return { source: 'npm', detail: 'published @cornerstonejs packages (no libs/@cornerstonejs)' };
|
||||
}
|
||||
|
||||
const coreStat = await fs.lstat(coreInNodeModules).catch(() => null);
|
||||
const isSymlink = coreStat?.isSymbolicLink();
|
||||
if (isSymlink) {
|
||||
const target = await fs.readlink(coreInNodeModules);
|
||||
return { source: 'integrated', detail: `linked from libs/@cornerstonejs (→ ${target})` };
|
||||
}
|
||||
|
||||
return { source: 'npm', detail: 'published @cornerstonejs packages (libs exists but not linked)' };
|
||||
} catch {
|
||||
return { source: 'unknown', detail: 'could not detect' };
|
||||
}
|
||||
}
|
||||
|
||||
async function getCs3dVersion() {
|
||||
try {
|
||||
const corePkg = path.join(REPO_ROOT, 'node_modules/@cornerstonejs/core/package.json');
|
||||
const pkg = JSON.parse(await fs.readFile(corePkg, 'utf-8'));
|
||||
return pkg.version || 'unknown';
|
||||
} catch {
|
||||
return 'unknown';
|
||||
}
|
||||
}
|
||||
|
||||
async function getCs3dBranchFromLibs() {
|
||||
try {
|
||||
const libsCs3d = path.join(REPO_ROOT, 'libs/@cornerstonejs');
|
||||
const { stdout } = await execa('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {
|
||||
cwd: libsCs3d,
|
||||
});
|
||||
return stdout;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function run() {
|
||||
const inCI = process.env.GITHUB_ACTIONS === 'true';
|
||||
const buildType = inCI ? (process.env.BUILD_TYPE || 'ohif-upstream') : 'local';
|
||||
|
||||
log('═══════════════════════════════════════════════════════════════');
|
||||
log('Build context (for diagnosing GitHub build issues)');
|
||||
log('═══════════════════════════════════════════════════════════════');
|
||||
|
||||
if (inCI) {
|
||||
log(`Build type: ${process.env.BUILD_TYPE || 'ohif-upstream'}`);
|
||||
log(`GitHub repo: ${process.env.GITHUB_REPOSITORY || 'unknown'}`);
|
||||
log(`GitHub ref: ${process.env.GITHUB_REF || 'unknown'}`);
|
||||
log(`GitHub SHA: ${process.env.GITHUB_SHA || 'unknown'}`);
|
||||
log(`Workflow: ${process.env.GITHUB_WORKFLOW || 'unknown'}`);
|
||||
}
|
||||
|
||||
try {
|
||||
const { stdout: branch } = await execa('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {
|
||||
cwd: REPO_ROOT,
|
||||
});
|
||||
const { stdout: sha } = await execa('git', ['rev-parse', '--short', 'HEAD'], {
|
||||
cwd: REPO_ROOT,
|
||||
});
|
||||
log(`OHIF branch: ${branch} (${sha})`);
|
||||
} catch {
|
||||
log('OHIF branch: (not a git repo or error)');
|
||||
}
|
||||
|
||||
const cs3d = await detectCs3dSource();
|
||||
log(`CS3D source: ${cs3d.source} — ${cs3d.detail}`);
|
||||
|
||||
if (cs3d.source === 'integrated') {
|
||||
const branch = await getCs3dBranchFromLibs();
|
||||
if (branch) log(`CS3D branch (libs/@cornerstonejs): ${branch}`);
|
||||
} else {
|
||||
const ver = await getCs3dVersion();
|
||||
log(`CS3D version (@cornerstonejs/core): ${ver}`);
|
||||
}
|
||||
|
||||
log('═══════════════════════════════════════════════════════════════');
|
||||
}
|
||||
|
||||
run().catch((err) => {
|
||||
console.error('[build-context] Error:', err.message);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
+4
-563
@@ -3,578 +3,19 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [3.13.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.53...v3.13.0-beta.54) (2026-04-08)
|
||||
## [3.12.2](https://github.com/OHIF/Viewers/compare/v3.12.1...v3.12.2) (2026-05-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cornerstone:** read FrameOfReferenceUID from display set in viewport service ([#5950](https://github.com/OHIF/Viewers/issues/5950)) ([d219171](https://github.com/OHIF/Viewers/commit/d219171e25caf5a7c575080f63819d6f4fe45016))
|
||||
* **release:** make publish-version.mjs idempotent for re-runs ([647fd02](https://github.com/OHIF/Viewers/commit/647fd025cf7212acc03b66807974f5d0f8ba0708))
|
||||
* **security:** Update various dependencies to fix security vulnerabilities. Release 3.12.2 ([#6024](https://github.com/OHIF/Viewers/issues/6024)) ([75a24a3](https://github.com/OHIF/Viewers/commit/75a24a33935bda8779da30ef9b725b387d80723d))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.52...v3.13.0-beta.53) (2026-04-06)
|
||||
|
||||
|
||||
### Reverts
|
||||
|
||||
* rename DisplaySet.frameOfReferenceUID back to FrameOfReferenceUID ([#5943](https://github.com/OHIF/Viewers/issues/5943)) ([0e933c2](https://github.com/OHIF/Viewers/commit/0e933c256e07b7cda35ed2ba3cfb1ab35d895d57))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.51...v3.13.0-beta.52) (2026-04-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **defaultRouteInit:** pass sorted display sets to hanging protocol for deterministic viewport order ([#5933](https://github.com/OHIF/Viewers/issues/5933)) ([68b10d3](https://github.com/OHIF/Viewers/commit/68b10d365a72d656c83a1c61624dcbd245fff5db))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **component:** Adds SmartScrollbar to ui-next - OHIF-2558 ([#5924](https://github.com/OHIF/Viewers/issues/5924)) ([91a8715](https://github.com/OHIF/Viewers/commit/91a8715795c1501b271f10b361382331eb836bf9))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.50...v3.13.0-beta.51) (2026-04-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **security:** Update yarn.lock that was missed in PR [#5936](https://github.com/OHIF/Viewers/issues/5936). ([#5940](https://github.com/OHIF/Viewers/issues/5940)) ([84ddf78](https://github.com/OHIF/Viewers/commit/84ddf78c879a7cb1aa62c3aaef4428adf67065da))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.49...v3.13.0-beta.50) (2026-04-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **security:** update dependencies to fix security vulnerabilities ([#5936](https://github.com/OHIF/Viewers/issues/5936)) ([5358a39](https://github.com/OHIF/Viewers/commit/5358a3985a1fa87eb1e3e7493dd61254f790b6d8))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.48...v3.13.0-beta.49) (2026-04-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation:** restrict overlay segmentation menu to same frame of reference as viewport background display set ([#5900](https://github.com/OHIF/Viewers/issues/5900)) ([b9029ef](https://github.com/OHIF/Viewers/commit/b9029ef6f8d63a0e36ec929310c1c5ad3f563ef8))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.47...v3.13.0-beta.48) (2026-04-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **measurement:** Restore viewport interactivity when deleting in-progress Spline or Livewire measurement ([#5905](https://github.com/OHIF/Viewers/issues/5905)) ([7929f08](https://github.com/OHIF/Viewers/commit/7929f0898f1bf882682a912b1c32d93d0944726f))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.46...v3.13.0-beta.47) (2026-03-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* prevent black viewport when navigating series with client-created segmentation ([#5919](https://github.com/OHIF/Viewers/issues/5919)) ([e66fb5a](https://github.com/OHIF/Viewers/commit/e66fb5a2b8c93a60ea20d315f73def7a02ea205f))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.45...v3.13.0-beta.46) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package ohif-monorepo-root
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.44...v3.13.0-beta.45) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package ohif-monorepo-root
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.43...v3.13.0-beta.44) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package ohif-monorepo-root
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.42...v3.13.0-beta.43) (2026-03-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **SR:** Added support for spline and live wire SR items. ([#5870](https://github.com/OHIF/Viewers/issues/5870)) ([1d4802c](https://github.com/OHIF/Viewers/commit/1d4802c2a38dd75dca7afca87913e100453c9135))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.41...v3.13.0-beta.42) (2026-03-17)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add combined build ([#5895](https://github.com/OHIF/Viewers/issues/5895)) ([1df671e](https://github.com/OHIF/Viewers/commit/1df671e9ab67d43f98bf09f6838ddc0a5f220277))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.40...v3.13.0-beta.41) (2026-03-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **sr-hydration:** enable hydration and arrow navigation for 3D SR measurements ([#5887](https://github.com/OHIF/Viewers/issues/5887)) ([7a38903](https://github.com/OHIF/Viewers/commit/7a38903b1977b1cf0f3a0ba8a4a823fac5e8fdeb))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.39...v3.13.0-beta.40) (2026-03-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **security:** Bump flattened version to address CVE-2026-32141. ([#5897](https://github.com/OHIF/Viewers/issues/5897)) ([d8d376e](https://github.com/OHIF/Viewers/commit/d8d376edaf9c2b7af237182657e3e2203cca5abb))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.38...v3.13.0-beta.39) (2026-03-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **window level:** The window level value is not displayed by default on all the viewports when selecting common/custom layout and TMTV. ([#5865](https://github.com/OHIF/Viewers/issues/5865)) ([fe1ecfe](https://github.com/OHIF/Viewers/commit/fe1ecfe0cc5d1bcf82686d821f356da8936a8c4b))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.37...v3.13.0-beta.38) (2026-03-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation:** Display "No description S:{series number} {modality}" for segmentations with no label. ([#5874](https://github.com/OHIF/Viewers/issues/5874)) ([7b5d0ce](https://github.com/OHIF/Viewers/commit/7b5d0ce40e5422ccfce6091ac3d7559586cbe57e))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.36...v3.13.0-beta.37) (2026-03-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **security:** Bump tar version to address CVE-2026-31802. ([#5893](https://github.com/OHIF/Viewers/issues/5893)) ([d015b2e](https://github.com/OHIF/Viewers/commit/d015b2e32a418042034c4f557c5a36499c72f702))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.35...v3.13.0-beta.36) (2026-03-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Modalities in study list should select starts with as primary ([#5886](https://github.com/OHIF/Viewers/issues/5886)) ([b83e978](https://github.com/OHIF/Viewers/commit/b83e978df8c9ffda3759378318267b8d0020653c))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.34...v3.13.0-beta.35) (2026-03-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Threshold tool:** Threshold tool no longer becomes deselected when the Dynamic option is selected ([#5884](https://github.com/OHIF/Viewers/issues/5884)) ([889026f](https://github.com/OHIF/Viewers/commit/889026f8a9c20cd21c31b4a02128afd5f057b14b))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.33...v3.13.0-beta.34) (2026-03-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **seg hydration:** auto-hydrate RT struct on second load with disableConfirmationPrompts ([#5875](https://github.com/OHIF/Viewers/issues/5875)) ([6f773f9](https://github.com/OHIF/Viewers/commit/6f773f997214c388409f3af3e9fc0e5b84debc10))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.32...v3.13.0-beta.33) (2026-03-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **security:** Bump svgo and tar to fix vulnerabilities. ([#5877](https://github.com/OHIF/Viewers/issues/5877)) ([61a1fcc](https://github.com/OHIF/Viewers/commit/61a1fccd7d47965831a6c80357219eed979ce4d6))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.31...v3.13.0-beta.32) (2026-03-05)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **ecg:** add DICOM ECG waveform extension ([#5856](https://github.com/OHIF/Viewers/issues/5856)) ([70f76ae](https://github.com/OHIF/Viewers/commit/70f76aeba1b27f8e4de5ec73a7b831428e38e3d2))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.30...v3.13.0-beta.31) (2026-03-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **microscopy:** rename measurement in microscopy mode ([#5866](https://github.com/OHIF/Viewers/issues/5866)) ([2358a73](https://github.com/OHIF/Viewers/commit/2358a73c3cd24953430064480fb9e66bfe36ea69))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.29...v3.13.0-beta.30) (2026-03-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation:** segment bidirectional tool error and show toast notification when no segment is drawn ([#5861](https://github.com/OHIF/Viewers/issues/5861)) ([7e10830](https://github.com/OHIF/Viewers/commit/7e10830d5802e22bda4df6a3f8008e9a414b4cd4))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.28...v3.13.0-beta.29) (2026-03-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **security:** Address various security vulnerabilities. ([#5869](https://github.com/OHIF/Viewers/issues/5869)) ([be8e266](https://github.com/OHIF/Viewers/commit/be8e266a80f13d03ce9dc4a21a0227d3e1bc36ac))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.27...v3.13.0-beta.28) (2026-03-03)
|
||||
|
||||
**Note:** Version bump only for package ohif-monorepo-root
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.26...v3.13.0-beta.27) (2026-03-02)
|
||||
|
||||
**Note:** Version bump only for package ohif-monorepo-root
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.25...v3.13.0-beta.26) (2026-02-28)
|
||||
|
||||
**Note:** Version bump only for package ohif-monorepo-root
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.24...v3.13.0-beta.25) (2026-02-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Update CS3D 4.18.2 ([#5837](https://github.com/OHIF/Viewers/issues/5837)) ([5370b93](https://github.com/OHIF/Viewers/commit/5370b9382e7bfddeadd69bab9e653f5f997a6e19))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.23...v3.13.0-beta.24) (2026-02-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* prevent viewer crash when opening DICOM Tag Browser from empty viewport ([#5827](https://github.com/OHIF/Viewers/issues/5827)) ([d11d6d4](https://github.com/OHIF/Viewers/commit/d11d6d401bc92a3870ec1089d97235b01a6b27c3))
|
||||
* **ui-next:** Add validation for opacity and border inputs in the segmentation panel - OHIF-2332 ([#5819](https://github.com/OHIF/Viewers/issues/5819)) ([a8f7099](https://github.com/OHIF/Viewers/commit/a8f709982f16983a11c780e696521df5aa05b604))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.22...v3.13.0-beta.23) (2026-02-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* palette color 8 encoded 16 ([#5823](https://github.com/OHIF/Viewers/issues/5823)) ([eeca1f7](https://github.com/OHIF/Viewers/commit/eeca1f7a7b529d1700f5d281a6fd98074547ffe9)), closes [#5813](https://github.com/OHIF/Viewers/issues/5813)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.21...v3.13.0-beta.22) (2026-02-23)
|
||||
|
||||
**Note:** Version bump only for package ohif-monorepo-root
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.20...v3.13.0-beta.21) (2026-02-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **RTStruct:** RTSTRUCT contours rendered on first slice for multi-frame images without IPP ([#5811](https://github.com/OHIF/Viewers/issues/5811)) ([b5573ca](https://github.com/OHIF/Viewers/commit/b5573caaa65d0d7ff3e83df0ec70b4aa7ea898ca))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.19...v3.13.0-beta.20) (2026-02-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Published version should match ([#5813](https://github.com/OHIF/Viewers/issues/5813)) ([d359a3b](https://github.com/OHIF/Viewers/commit/d359a3b784227b248c5b09548db363c7f8adbcb8))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.18...v3.13.0-beta.19) (2026-02-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **security:** CVE-2026-27212 patched. Various dependency updates as a result of CVE-2026-26996. ([#5830](https://github.com/OHIF/Viewers/issues/5830)) ([2722960](https://github.com/OHIF/Viewers/commit/27229609cda3162e37573418ef82ca5d4e365075))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.17...v3.13.0-beta.18) (2026-02-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation overlay:** update viewport ds list upon seg delete - OHIF-2425 ([#5729](https://github.com/OHIF/Viewers/issues/5729)) ([b353541](https://github.com/OHIF/Viewers/commit/b35354120a01d89b27844f967c32c052bba8b096))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.16...v3.13.0-beta.17) (2026-02-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Add copy to clipboard option for capture ([#5720](https://github.com/OHIF/Viewers/issues/5720)) ([53c67f3](https://github.com/OHIF/Viewers/commit/53c67f361234a0b4160c1b11fafcb143a0723336))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.15...v3.13.0-beta.16) (2026-02-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **security:** Bump tar to 7.5.9 and lerna to 9.0.4 to fix CVE-2026-26960. ([#5824](https://github.com/OHIF/Viewers/issues/5824)) ([3d59c0d](https://github.com/OHIF/Viewers/commit/3d59c0d9d3783336eaa8d37cfc0172818942bf00))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.14...v3.13.0-beta.15) (2026-02-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **dicom-tag-browser:** Prevent long series names from overlapping - OHIF-2406 ([#5809](https://github.com/OHIF/Viewers/issues/5809)) ([cca1a86](https://github.com/OHIF/Viewers/commit/cca1a8683bc7d392a3a07268f24585642d13b1cd))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.13...v3.13.0-beta.14) (2026-02-13)
|
||||
|
||||
**Note:** Version bump only for package ohif-monorepo-root
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.12...v3.13.0-beta.13) (2026-02-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **colors:** Replace hardcoded black with background color token ([#5815](https://github.com/OHIF/Viewers/issues/5815)) ([dbc31a5](https://github.com/OHIF/Viewers/commit/dbc31a5d4ec5b2238683a580af96aff23d9fafeb))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.11...v3.13.0-beta.12) (2026-02-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **usAnnotation:** Prevent error after JSON download ([#5814](https://github.com/OHIF/Viewers/issues/5814)) ([739e323](https://github.com/OHIF/Viewers/commit/739e3239cf5765711050b673b373c0145747824f))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.10...v3.13.0-beta.11) (2026-02-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **colors:** Replaces legacy colors with ui-next colors ([#5351](https://github.com/OHIF/Viewers/issues/5351)) ([9a2691a](https://github.com/OHIF/Viewers/commit/9a2691a71fe3723bb05cbd148968b64e5d0fa951))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.9...v3.13.0-beta.10) (2026-02-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **microscopy:** Prevent measurement clearing on viewport resize ([#5796](https://github.com/OHIF/Viewers/issues/5796)) ([baef707](https://github.com/OHIF/Viewers/commit/baef707e46fd76b50f8b510b45da64e12d71ed0e))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.9) (2026-02-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Add a single version number with commit process ([#5746](https://github.com/OHIF/Viewers/issues/5746)) ([fb7329f](https://github.com/OHIF/Viewers/commit/fb7329f3fe0edc04833f15cd515522353d465912))
|
||||
* Missing tag ([#5808](https://github.com/OHIF/Viewers/issues/5808)) ([c92bdd5](https://github.com/OHIF/Viewers/commit/c92bdd5b48b8805e9ea4cbac72007391b9ba0efe))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.8) (2026-02-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Add a single version number with commit process ([#5746](https://github.com/OHIF/Viewers/issues/5746)) ([fb7329f](https://github.com/OHIF/Viewers/commit/fb7329f3fe0edc04833f15cd515522353d465912))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.7) (2026-02-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Add a single version number with commit process ([#5746](https://github.com/OHIF/Viewers/issues/5746)) ([fb7329f](https://github.com/OHIF/Viewers/commit/fb7329f3fe0edc04833f15cd515522353d465912))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.5...v3.13.0-beta.6) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package ohif-monorepo-root
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.4...v3.13.0-beta.5) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package ohif-monorepo-root
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.3...v3.13.0-beta.4) (2026-02-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Better handle octet stream case ([#5789](https://github.com/OHIF/Viewers/issues/5789)) ([037402f](https://github.com/OHIF/Viewers/commit/037402f7f6a1fc07593be302e4f578f6c4870c6e))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.2...v3.13.0-beta.3) (2026-02-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **app:** display study not found message for all modes ([#5752](https://github.com/OHIF/Viewers/issues/5752)) ([7f9e59e](https://github.com/OHIF/Viewers/commit/7f9e59ee3074e3511d22c7f0075856a7bd2cc32e))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.1...v3.13.0-beta.2) (2026-02-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cine:** prevent crash on second view/hydration of SR series ([#5724](https://github.com/OHIF/Viewers/issues/5724)) ([f70c9b9](https://github.com/OHIF/Viewers/commit/f70c9b932db2bb14173acae675d38ce250d244fa))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.0...v3.13.0-beta.1) (2026-02-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **security:** Use a resolution for axios to address CVE-2026-25639. ([#5793](https://github.com/OHIF/Viewers/issues/5793)) ([94c9e16](https://github.com/OHIF/Viewers/commit/94c9e162f3d17840c7e9659557f685ca8642d06f))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.135...v3.13.0-beta.0) (2026-02-07)
|
||||
# [3.12.0](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.135...v3.12.0) (2026-02-06)
|
||||
|
||||
**Note:** Version bump only for package ohif-monorepo-root
|
||||
|
||||
|
||||
@@ -49,7 +49,6 @@ provided by the <a href="https://ohif.org/">Open Health Imaging Foundation (OHIF
|
||||
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-4d.webp?raw=true" alt="4D" width="350"/> | 4D | [Demo](https://viewer.ohif.org/dynamic-volume?StudyInstanceUIDs=2.25.232704420736447710317909004159492840763) |
|
||||
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-video.webp?raw=true" alt="VIDEO" width="350"/> | Video | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=2.25.96975534054447904995905761963464388233) |
|
||||
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/microscopy.webp?raw=true" alt="microscopy" width="350"/> | Slide Microscopy | [Demo](https://viewer.ohif.org/microscopy?StudyInstanceUIDs=2.25.141277760791347900862109212450152067508) |
|
||||
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-ecg.webp?raw=true" alt="ECG" width="350"/> | ECG Waveform | [Demo](https://viewer-dev.ohif.org/viewer?StudyInstanceUIDs=2.25.209974489360710696739324151261716440238) |
|
||||
|
||||
## About
|
||||
|
||||
@@ -105,6 +104,7 @@ For commercial support, academic collaborations, and answers to common
|
||||
questions; please use [Get Support](https://ohif.org/get-support/) to contact
|
||||
us.
|
||||
|
||||
|
||||
## Developing
|
||||
|
||||
### Branches
|
||||
@@ -168,64 +168,6 @@ yarn config set workspaces-experimental true
|
||||
yarn install --frozen-lockfile
|
||||
```
|
||||
|
||||
### Cornerstone3D Integration Testing
|
||||
|
||||
OHIF's Playwright end-to-end tests can run against a **CS3D branch** or a
|
||||
**published CS3D version**, allowing changes that span both repositories to be
|
||||
validated together before merging.
|
||||
|
||||
#### Setting up an integration build
|
||||
|
||||
1. Add the **`ohif-integration`** label to your OHIF pull request.
|
||||
2. In the PR body, add a line specifying the CS3D ref:
|
||||
```
|
||||
CS3D_REF: feat/my-feature
|
||||
```
|
||||
- **Version ref** (e.g. `4.19+`, `4.18.2`) — the workflow resolves it to an
|
||||
exact published version and swaps the CS3D dependency via npm.
|
||||
- **Branch ref** (e.g. `main`, `cornerstonejs:feat/foo`) — the workflow
|
||||
clones the branch, builds CS3D from source with `bun run build:esm`, and
|
||||
symlinks the built packages into OHIF's `node_modules`.
|
||||
- For forks, use the `<owner>:<branch>` format
|
||||
(e.g. `myGithubUser:feat/foo`).
|
||||
- If no `CS3D_REF` is specified, the default is `4.19+`.
|
||||
3. The workflow can also be triggered manually via **workflow_dispatch** with a
|
||||
`cs3d_ref` input.
|
||||
|
||||
#### What happens in CI
|
||||
|
||||
The [Playwright workflow](.github/workflows/playwright.yml) runs two jobs:
|
||||
|
||||
| Job | Purpose |
|
||||
|-----|---------|
|
||||
| **Playwright Tests** | Builds OHIF (with CS3D linked or version-swapped), runs the full Playwright suite, uploads test results and coverage, and deploys a Netlify preview when `ohif-integration` is active. |
|
||||
| **CS3D Branch Merge Guard** | A lightweight check that **fails** when the `ohif-integration` label is present and `CS3D_REF` points to a branch (not a version). This prevents merging while still letting the Playwright tests show green so you can see whether the code actually works. |
|
||||
|
||||
#### Testing changes that span both repos
|
||||
|
||||
If a feature requires changes in both Cornerstone3D and OHIF:
|
||||
|
||||
1. Create your feature branch in CS3D and push it.
|
||||
2. Create a matching branch in OHIF.
|
||||
3. Add the `ohif-integration` label to the OHIF pull request.
|
||||
4. In the PR body, add: `CS3D_REF: <your-cs3d-branch>`.
|
||||
5. Playwright tests will build CS3D from source, link it, and run the full
|
||||
suite. The merge guard will block merge until you switch to a published
|
||||
version — but you can see the test results and the preview deploy while
|
||||
iterating.
|
||||
6. Once the CS3D side is merged and published, update the PR body to reference
|
||||
the published version (e.g. `CS3D_REF: 4.19+`). The tests will run against
|
||||
the registry version and the merge guard will pass.
|
||||
|
||||
#### Preview deploys
|
||||
|
||||
When `ohif-integration` is active, the Playwright workflow also builds the OHIF
|
||||
viewer and deploys it to Netlify as a preview. This gives you a live URL to
|
||||
manually test the combined CS3D + OHIF changes without running anything locally.
|
||||
|
||||
For details on linking CS3D locally for development, see the
|
||||
[Cornerstone3D README](libs/@cornerstonejs/README.md#local-development-linking--unlinking).
|
||||
|
||||
## Commands
|
||||
|
||||
These commands are available from the root directory. Each project directory
|
||||
|
||||
+2
-432
@@ -3,7 +3,7 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [3.13.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.53...v3.13.0-beta.54) (2026-04-08)
|
||||
## [3.12.2](https://github.com/OHIF/Viewers/compare/v3.12.1...v3.12.2) (2026-05-18)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
@@ -11,437 +11,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.52...v3.13.0-beta.53) (2026-04-06)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.51...v3.13.0-beta.52) (2026-04-06)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.50...v3.13.0-beta.51) (2026-04-03)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.49...v3.13.0-beta.50) (2026-04-02)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.48...v3.13.0-beta.49) (2026-04-02)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.47...v3.13.0-beta.48) (2026-04-01)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.46...v3.13.0-beta.47) (2026-03-28)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.45...v3.13.0-beta.46) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.44...v3.13.0-beta.45) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.43...v3.13.0-beta.44) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.42...v3.13.0-beta.43) (2026-03-17)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.41...v3.13.0-beta.42) (2026-03-17)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.40...v3.13.0-beta.41) (2026-03-16)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.39...v3.13.0-beta.40) (2026-03-13)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.38...v3.13.0-beta.39) (2026-03-13)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.37...v3.13.0-beta.38) (2026-03-12)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.36...v3.13.0-beta.37) (2026-03-12)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.35...v3.13.0-beta.36) (2026-03-11)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.34...v3.13.0-beta.35) (2026-03-09)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.33...v3.13.0-beta.34) (2026-03-09)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.32...v3.13.0-beta.33) (2026-03-05)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.31...v3.13.0-beta.32) (2026-03-05)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.30...v3.13.0-beta.31) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.29...v3.13.0-beta.30) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.28...v3.13.0-beta.29) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.27...v3.13.0-beta.28) (2026-03-03)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.26...v3.13.0-beta.27) (2026-03-02)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.25...v3.13.0-beta.26) (2026-02-28)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.24...v3.13.0-beta.25) (2026-02-26)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.23...v3.13.0-beta.24) (2026-02-24)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.22...v3.13.0-beta.23) (2026-02-23)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.21...v3.13.0-beta.22) (2026-02-23)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.20...v3.13.0-beta.21) (2026-02-23)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.19...v3.13.0-beta.20) (2026-02-21)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.18...v3.13.0-beta.19) (2026-02-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **security:** CVE-2026-27212 patched. Various dependency updates as a result of CVE-2026-26996. ([#5830](https://github.com/OHIF/Viewers/issues/5830)) ([2722960](https://github.com/OHIF/Viewers/commit/27229609cda3162e37573418ef82ca5d4e365075))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.17...v3.13.0-beta.18) (2026-02-19)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.16...v3.13.0-beta.17) (2026-02-19)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.15...v3.13.0-beta.16) (2026-02-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **security:** Bump tar to 7.5.9 and lerna to 9.0.4 to fix CVE-2026-26960. ([#5824](https://github.com/OHIF/Viewers/issues/5824)) ([3d59c0d](https://github.com/OHIF/Viewers/commit/3d59c0d9d3783336eaa8d37cfc0172818942bf00))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.14...v3.13.0-beta.15) (2026-02-17)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.13...v3.13.0-beta.14) (2026-02-13)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.12...v3.13.0-beta.13) (2026-02-12)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.11...v3.13.0-beta.12) (2026-02-12)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.10...v3.13.0-beta.11) (2026-02-12)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.9...v3.13.0-beta.10) (2026-02-11)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.9) (2026-02-11)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.8) (2026-02-11)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.7) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.5...v3.13.0-beta.6) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.4...v3.13.0-beta.5) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.3...v3.13.0-beta.4) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.2...v3.13.0-beta.3) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.1...v3.13.0-beta.2) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.0...v3.13.0-beta.1) (2026-02-09)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.135...v3.13.0-beta.0) (2026-02-07)
|
||||
# [3.12.0](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.135...v3.12.0) (2026-02-06)
|
||||
|
||||
**Note:** Version bump only for package @externals/devDependencies
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@externals/devDependencies",
|
||||
"description": "External dev dependencies - put dev build dependencies here",
|
||||
"version": "3.13.0-beta.54",
|
||||
"version": "3.12.2",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"engines": {
|
||||
|
||||
+2
-426
@@ -3,7 +3,7 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [3.13.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.53...v3.13.0-beta.54) (2026-04-08)
|
||||
## [3.12.2](https://github.com/OHIF/Viewers/compare/v3.12.1...v3.12.2) (2026-05-18)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
@@ -11,431 +11,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.52...v3.13.0-beta.53) (2026-04-06)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.51...v3.13.0-beta.52) (2026-04-06)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.50...v3.13.0-beta.51) (2026-04-03)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.49...v3.13.0-beta.50) (2026-04-02)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.48...v3.13.0-beta.49) (2026-04-02)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.47...v3.13.0-beta.48) (2026-04-01)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.46...v3.13.0-beta.47) (2026-03-28)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.45...v3.13.0-beta.46) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.44...v3.13.0-beta.45) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.43...v3.13.0-beta.44) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.42...v3.13.0-beta.43) (2026-03-17)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.41...v3.13.0-beta.42) (2026-03-17)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.40...v3.13.0-beta.41) (2026-03-16)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.39...v3.13.0-beta.40) (2026-03-13)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.38...v3.13.0-beta.39) (2026-03-13)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.37...v3.13.0-beta.38) (2026-03-12)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.36...v3.13.0-beta.37) (2026-03-12)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.35...v3.13.0-beta.36) (2026-03-11)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.34...v3.13.0-beta.35) (2026-03-09)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.33...v3.13.0-beta.34) (2026-03-09)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.32...v3.13.0-beta.33) (2026-03-05)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.31...v3.13.0-beta.32) (2026-03-05)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.30...v3.13.0-beta.31) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.29...v3.13.0-beta.30) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.28...v3.13.0-beta.29) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.27...v3.13.0-beta.28) (2026-03-03)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.26...v3.13.0-beta.27) (2026-03-02)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.25...v3.13.0-beta.26) (2026-02-28)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.24...v3.13.0-beta.25) (2026-02-26)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.23...v3.13.0-beta.24) (2026-02-24)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.22...v3.13.0-beta.23) (2026-02-23)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.21...v3.13.0-beta.22) (2026-02-23)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.20...v3.13.0-beta.21) (2026-02-23)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.19...v3.13.0-beta.20) (2026-02-21)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.18...v3.13.0-beta.19) (2026-02-20)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.17...v3.13.0-beta.18) (2026-02-19)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.16...v3.13.0-beta.17) (2026-02-19)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.15...v3.13.0-beta.16) (2026-02-18)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.14...v3.13.0-beta.15) (2026-02-17)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.13...v3.13.0-beta.14) (2026-02-13)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.12...v3.13.0-beta.13) (2026-02-12)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.11...v3.13.0-beta.12) (2026-02-12)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.10...v3.13.0-beta.11) (2026-02-12)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.9...v3.13.0-beta.10) (2026-02-11)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.9) (2026-02-11)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.8) (2026-02-11)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.7) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.5...v3.13.0-beta.6) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.4...v3.13.0-beta.5) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.3...v3.13.0-beta.4) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.2...v3.13.0-beta.3) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.1...v3.13.0-beta.2) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.0...v3.13.0-beta.1) (2026-02-09)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.135...v3.13.0-beta.0) (2026-02-07)
|
||||
# [3.12.0](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.135...v3.12.0) (2026-02-06)
|
||||
|
||||
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@externals/dicom-microscopy-viewer",
|
||||
"description": "External reference to dicom-microscopy-viewer",
|
||||
"version": "3.13.0-beta.54",
|
||||
"version": "3.12.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"dicom-microscopy-viewer": "0.48.17"
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
"@babel/plugin-transform-regenerator": "7.28.1",
|
||||
"@babel/plugin-transform-runtime": "7.28.0",
|
||||
"@babel/plugin-transform-typescript": "7.28.0",
|
||||
"@babel/preset-env": "7.28.0",
|
||||
"@babel/preset-env": "7.29.5",
|
||||
"@babel/preset-react": "7.27.1",
|
||||
"@babel/preset-typescript": "7.27.1"
|
||||
},
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
d219171e25caf5a7c575080f63819d6f4fe45016
|
||||
75a24a33935bda8779da30ef9b725b387d80723d
|
||||
@@ -3,7 +3,7 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [3.13.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.53...v3.13.0-beta.54) (2026-04-08)
|
||||
## [3.12.2](https://github.com/OHIF/Viewers/compare/v3.12.1...v3.12.2) (2026-05-18)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
@@ -11,443 +11,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.52...v3.13.0-beta.53) (2026-04-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.51...v3.13.0-beta.52) (2026-04-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.50...v3.13.0-beta.51) (2026-04-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.49...v3.13.0-beta.50) (2026-04-02)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.48...v3.13.0-beta.49) (2026-04-02)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.47...v3.13.0-beta.48) (2026-04-01)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.46...v3.13.0-beta.47) (2026-03-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.45...v3.13.0-beta.46) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.44...v3.13.0-beta.45) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.43...v3.13.0-beta.44) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.42...v3.13.0-beta.43) (2026-03-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.41...v3.13.0-beta.42) (2026-03-17)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add combined build ([#5895](https://github.com/OHIF/Viewers/issues/5895)) ([1df671e](https://github.com/OHIF/Viewers/commit/1df671e9ab67d43f98bf09f6838ddc0a5f220277))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.40...v3.13.0-beta.41) (2026-03-16)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.39...v3.13.0-beta.40) (2026-03-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.38...v3.13.0-beta.39) (2026-03-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.37...v3.13.0-beta.38) (2026-03-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation:** Display "No description S:{series number} {modality}" for segmentations with no label. ([#5874](https://github.com/OHIF/Viewers/issues/5874)) ([7b5d0ce](https://github.com/OHIF/Viewers/commit/7b5d0ce40e5422ccfce6091ac3d7559586cbe57e))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.36...v3.13.0-beta.37) (2026-03-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.35...v3.13.0-beta.36) (2026-03-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.34...v3.13.0-beta.35) (2026-03-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.33...v3.13.0-beta.34) (2026-03-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.32...v3.13.0-beta.33) (2026-03-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.31...v3.13.0-beta.32) (2026-03-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.30...v3.13.0-beta.31) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.29...v3.13.0-beta.30) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.28...v3.13.0-beta.29) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.27...v3.13.0-beta.28) (2026-03-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.26...v3.13.0-beta.27) (2026-03-02)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.25...v3.13.0-beta.26) (2026-02-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.24...v3.13.0-beta.25) (2026-02-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Update CS3D 4.18.2 ([#5837](https://github.com/OHIF/Viewers/issues/5837)) ([5370b93](https://github.com/OHIF/Viewers/commit/5370b9382e7bfddeadd69bab9e653f5f997a6e19))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.23...v3.13.0-beta.24) (2026-02-24)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.22...v3.13.0-beta.23) (2026-02-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* palette color 8 encoded 16 ([#5823](https://github.com/OHIF/Viewers/issues/5823)) ([eeca1f7](https://github.com/OHIF/Viewers/commit/eeca1f7a7b529d1700f5d281a6fd98074547ffe9)), closes [#5813](https://github.com/OHIF/Viewers/issues/5813)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.21...v3.13.0-beta.22) (2026-02-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.20...v3.13.0-beta.21) (2026-02-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.19...v3.13.0-beta.20) (2026-02-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.18...v3.13.0-beta.19) (2026-02-20)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.17...v3.13.0-beta.18) (2026-02-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.16...v3.13.0-beta.17) (2026-02-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.15...v3.13.0-beta.16) (2026-02-18)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.14...v3.13.0-beta.15) (2026-02-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.13...v3.13.0-beta.14) (2026-02-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.12...v3.13.0-beta.13) (2026-02-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.11...v3.13.0-beta.12) (2026-02-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.10...v3.13.0-beta.11) (2026-02-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.9...v3.13.0-beta.10) (2026-02-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.9) (2026-02-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.8) (2026-02-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.7) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.5...v3.13.0-beta.6) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.4...v3.13.0-beta.5) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.3...v3.13.0-beta.4) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.2...v3.13.0-beta.3) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.1...v3.13.0-beta.2) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.0...v3.13.0-beta.1) (2026-02-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.135...v3.13.0-beta.0) (2026-02-07)
|
||||
# [3.12.0](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.135...v3.12.0) (2026-02-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone-dicom-pmap",
|
||||
"version": "3.13.0-beta.54",
|
||||
"version": "3.12.2",
|
||||
"description": "DICOM Parametric Map read workflow",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -33,10 +33,10 @@
|
||||
"start": "yarn run dev"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.13.0-beta.54",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.54",
|
||||
"@ohif/extension-default": "3.13.0-beta.54",
|
||||
"@ohif/i18n": "3.13.0-beta.54",
|
||||
"@ohif/core": "3.12.2",
|
||||
"@ohif/extension-cornerstone": "3.12.2",
|
||||
"@ohif/extension-default": "3.12.2",
|
||||
"@ohif/i18n": "3.12.2",
|
||||
"prop-types": "15.8.1",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
@@ -46,8 +46,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@cornerstonejs/adapters": "4.20.0",
|
||||
"@cornerstonejs/core": "4.20.0",
|
||||
"@cornerstonejs/adapters": "4.15.29",
|
||||
"@cornerstonejs/core": "4.15.29",
|
||||
"@kitware/vtk.js": "34.15.1"
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [3.13.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.53...v3.13.0-beta.54) (2026-04-08)
|
||||
## [3.12.2](https://github.com/OHIF/Viewers/compare/v3.12.1...v3.12.2) (2026-05-18)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
@@ -11,440 +11,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.52...v3.13.0-beta.53) (2026-04-06)
|
||||
|
||||
|
||||
### Reverts
|
||||
|
||||
* rename DisplaySet.frameOfReferenceUID back to FrameOfReferenceUID ([#5943](https://github.com/OHIF/Viewers/issues/5943)) ([0e933c2](https://github.com/OHIF/Viewers/commit/0e933c256e07b7cda35ed2ba3cfb1ab35d895d57))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.51...v3.13.0-beta.52) (2026-04-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.50...v3.13.0-beta.51) (2026-04-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.49...v3.13.0-beta.50) (2026-04-02)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.48...v3.13.0-beta.49) (2026-04-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation:** restrict overlay segmentation menu to same frame of reference as viewport background display set ([#5900](https://github.com/OHIF/Viewers/issues/5900)) ([b9029ef](https://github.com/OHIF/Viewers/commit/b9029ef6f8d63a0e36ec929310c1c5ad3f563ef8))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.47...v3.13.0-beta.48) (2026-04-01)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.46...v3.13.0-beta.47) (2026-03-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.45...v3.13.0-beta.46) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.44...v3.13.0-beta.45) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.43...v3.13.0-beta.44) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.42...v3.13.0-beta.43) (2026-03-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.41...v3.13.0-beta.42) (2026-03-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.40...v3.13.0-beta.41) (2026-03-16)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.39...v3.13.0-beta.40) (2026-03-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.38...v3.13.0-beta.39) (2026-03-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.37...v3.13.0-beta.38) (2026-03-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.36...v3.13.0-beta.37) (2026-03-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.35...v3.13.0-beta.36) (2026-03-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.34...v3.13.0-beta.35) (2026-03-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.33...v3.13.0-beta.34) (2026-03-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.32...v3.13.0-beta.33) (2026-03-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.31...v3.13.0-beta.32) (2026-03-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.30...v3.13.0-beta.31) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.29...v3.13.0-beta.30) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.28...v3.13.0-beta.29) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.27...v3.13.0-beta.28) (2026-03-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.26...v3.13.0-beta.27) (2026-03-02)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.25...v3.13.0-beta.26) (2026-02-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.24...v3.13.0-beta.25) (2026-02-26)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.23...v3.13.0-beta.24) (2026-02-24)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.22...v3.13.0-beta.23) (2026-02-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.21...v3.13.0-beta.22) (2026-02-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.20...v3.13.0-beta.21) (2026-02-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.19...v3.13.0-beta.20) (2026-02-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.18...v3.13.0-beta.19) (2026-02-20)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.17...v3.13.0-beta.18) (2026-02-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation overlay:** update viewport ds list upon seg delete - OHIF-2425 ([#5729](https://github.com/OHIF/Viewers/issues/5729)) ([b353541](https://github.com/OHIF/Viewers/commit/b35354120a01d89b27844f967c32c052bba8b096))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.16...v3.13.0-beta.17) (2026-02-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.15...v3.13.0-beta.16) (2026-02-18)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.14...v3.13.0-beta.15) (2026-02-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.13...v3.13.0-beta.14) (2026-02-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.12...v3.13.0-beta.13) (2026-02-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.11...v3.13.0-beta.12) (2026-02-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.10...v3.13.0-beta.11) (2026-02-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.9...v3.13.0-beta.10) (2026-02-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.9) (2026-02-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.8) (2026-02-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.7) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.5...v3.13.0-beta.6) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.4...v3.13.0-beta.5) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.3...v3.13.0-beta.4) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.2...v3.13.0-beta.3) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.1...v3.13.0-beta.2) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.0...v3.13.0-beta.1) (2026-02-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.135...v3.13.0-beta.0) (2026-02-07)
|
||||
# [3.12.0](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.135...v3.12.0) (2026-02-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone-dicom-rt",
|
||||
"version": "3.13.0-beta.54",
|
||||
"version": "3.12.2",
|
||||
"description": "DICOM RT read workflow",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -33,10 +33,10 @@
|
||||
"start": "yarn run dev"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.13.0-beta.54",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.54",
|
||||
"@ohif/extension-default": "3.13.0-beta.54",
|
||||
"@ohif/i18n": "3.13.0-beta.54",
|
||||
"@ohif/core": "3.12.2",
|
||||
"@ohif/extension-cornerstone": "3.12.2",
|
||||
"@ohif/extension-default": "3.12.2",
|
||||
"@ohif/i18n": "3.12.2",
|
||||
"prop-types": "15.8.1",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { utils, Types as OhifTypes } from '@ohif/core';
|
||||
import i18n from '@ohif/i18n';
|
||||
import { segmentation as cstSegmentation } from '@cornerstonejs/tools';
|
||||
|
||||
import { SOPClassHandlerId } from './id';
|
||||
import loadRTStruct from './loadRTStruct';
|
||||
@@ -9,6 +8,8 @@ const { sopClassDictionary } = utils;
|
||||
|
||||
const sopClassUids = [sopClassDictionary.RTStructureSetStorage];
|
||||
|
||||
const cachedRTStructsSEG = new Set<string>();
|
||||
|
||||
const loadPromises = {};
|
||||
|
||||
function _getDisplaySetsFromSeries(
|
||||
@@ -56,7 +57,6 @@ function _getDisplaySetsFromSeries(
|
||||
StudyInstanceUID,
|
||||
SOPClassHandlerId,
|
||||
SOPClassUID,
|
||||
FrameOfReferenceUID: null,
|
||||
referencedImages: null,
|
||||
referencedSeriesInstanceUID: null,
|
||||
referencedDisplaySetInstanceUID: null,
|
||||
@@ -96,9 +96,6 @@ function _getDisplaySetsFromSeries(
|
||||
displaySet.referencedImages = instance.ReferencedSeriesSequence.ReferencedInstanceSequence;
|
||||
displaySet.referencedSeriesInstanceUID = referencedSeries.SeriesInstanceUID;
|
||||
|
||||
displaySet.FrameOfReferenceUID =
|
||||
instance.ReferencedFrameOfReferenceSequence?.[0]?.FrameOfReferenceUID;
|
||||
|
||||
const { displaySetService } = servicesManager.services;
|
||||
const referencedDisplaySets =
|
||||
displaySetService.getDisplaySetsForReferences(referencedSeriesSequence);
|
||||
@@ -117,7 +114,6 @@ function _getDisplaySetsFromSeries(
|
||||
if (addedDisplaySet.SeriesInstanceUID === displaySet.referencedSeriesInstanceUID) {
|
||||
displaySet.referencedDisplaySetInstanceUID = addedDisplaySet.displaySetInstanceUID;
|
||||
displaySet.isReconstructable = addedDisplaySet.isReconstructable;
|
||||
displaySet.FrameOfReferenceUID = addedDisplaySet.FrameOfReferenceUID;
|
||||
unsubscribe();
|
||||
}
|
||||
}
|
||||
@@ -126,7 +122,6 @@ function _getDisplaySetsFromSeries(
|
||||
const [referencedDisplaySet] = referencedDisplaySets;
|
||||
displaySet.referencedDisplaySetInstanceUID = referencedDisplaySet.displaySetInstanceUID;
|
||||
displaySet.isReconstructable = referencedDisplaySet.isReconstructable;
|
||||
displaySet.FrameOfReferenceUID = referencedDisplaySet.FrameOfReferenceUID;
|
||||
}
|
||||
|
||||
displaySet.load = ({ headers, createSegmentation = true }) =>
|
||||
@@ -148,13 +143,23 @@ function _load(
|
||||
if (
|
||||
(rtDisplaySet.loading || rtDisplaySet.isLoaded) &&
|
||||
loadPromises[SOPInstanceUID] &&
|
||||
_segmentationExists(rtDisplaySet)
|
||||
cachedRTStructsSEG.has(rtDisplaySet.displaySetInstanceUID)
|
||||
) {
|
||||
return loadPromises[SOPInstanceUID];
|
||||
}
|
||||
|
||||
rtDisplaySet.loading = true;
|
||||
|
||||
const { unsubscribe } = segmentationService.subscribe(
|
||||
segmentationService.EVENTS.SEGMENTATION_LOADING_COMPLETE,
|
||||
(evt: { rtDisplaySet: { displaySetInstanceUID: string } }) => {
|
||||
if (evt.rtDisplaySet?.displaySetInstanceUID === rtDisplaySet.displaySetInstanceUID) {
|
||||
cachedRTStructsSEG.add(rtDisplaySet.displaySetInstanceUID);
|
||||
unsubscribe();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// 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<void>(async (resolve, reject) => {
|
||||
@@ -214,10 +219,6 @@ function _deriveReferencedSeriesSequenceFromFrameOfReferenceSequence(
|
||||
return ReferencedSeriesSequence;
|
||||
}
|
||||
|
||||
function _segmentationExists(segDisplaySet) {
|
||||
return !!cstSegmentation.state.getSegmentation(segDisplaySet.displaySetInstanceUID);
|
||||
}
|
||||
|
||||
function getSopClassHandlerModule(params: OhifTypes.Extensions.ExtensionParams) {
|
||||
const { servicesManager, extensionManager } = params;
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@ function OHIFCornerstoneRTViewport(props: withAppTypes) {
|
||||
|
||||
return () => {
|
||||
// remove the segmentation representations if seg displayset changed
|
||||
segmentationService.removeRepresentationsFromViewport(viewportId);
|
||||
segmentationService.removeSegmentationRepresentations(viewportId);
|
||||
referencedDisplaySetRef.current = null;
|
||||
toolGroupService.destroyToolGroup(toolGroupId);
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [3.13.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.53...v3.13.0-beta.54) (2026-04-08)
|
||||
## [3.12.2](https://github.com/OHIF/Viewers/compare/v3.12.1...v3.12.2) (2026-05-18)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
@@ -11,455 +11,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.52...v3.13.0-beta.53) (2026-04-06)
|
||||
|
||||
|
||||
### Reverts
|
||||
|
||||
* rename DisplaySet.frameOfReferenceUID back to FrameOfReferenceUID ([#5943](https://github.com/OHIF/Viewers/issues/5943)) ([0e933c2](https://github.com/OHIF/Viewers/commit/0e933c256e07b7cda35ed2ba3cfb1ab35d895d57))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.51...v3.13.0-beta.52) (2026-04-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.50...v3.13.0-beta.51) (2026-04-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.49...v3.13.0-beta.50) (2026-04-02)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.48...v3.13.0-beta.49) (2026-04-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation:** restrict overlay segmentation menu to same frame of reference as viewport background display set ([#5900](https://github.com/OHIF/Viewers/issues/5900)) ([b9029ef](https://github.com/OHIF/Viewers/commit/b9029ef6f8d63a0e36ec929310c1c5ad3f563ef8))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.47...v3.13.0-beta.48) (2026-04-01)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.46...v3.13.0-beta.47) (2026-03-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.45...v3.13.0-beta.46) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.44...v3.13.0-beta.45) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.43...v3.13.0-beta.44) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.42...v3.13.0-beta.43) (2026-03-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **SR:** Added support for spline and live wire SR items. ([#5870](https://github.com/OHIF/Viewers/issues/5870)) ([1d4802c](https://github.com/OHIF/Viewers/commit/1d4802c2a38dd75dca7afca87913e100453c9135))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.41...v3.13.0-beta.42) (2026-03-17)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add combined build ([#5895](https://github.com/OHIF/Viewers/issues/5895)) ([1df671e](https://github.com/OHIF/Viewers/commit/1df671e9ab67d43f98bf09f6838ddc0a5f220277))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.40...v3.13.0-beta.41) (2026-03-16)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.39...v3.13.0-beta.40) (2026-03-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.38...v3.13.0-beta.39) (2026-03-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.37...v3.13.0-beta.38) (2026-03-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation:** Display "No description S:{series number} {modality}" for segmentations with no label. ([#5874](https://github.com/OHIF/Viewers/issues/5874)) ([7b5d0ce](https://github.com/OHIF/Viewers/commit/7b5d0ce40e5422ccfce6091ac3d7559586cbe57e))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.36...v3.13.0-beta.37) (2026-03-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.35...v3.13.0-beta.36) (2026-03-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.34...v3.13.0-beta.35) (2026-03-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.33...v3.13.0-beta.34) (2026-03-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.32...v3.13.0-beta.33) (2026-03-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.31...v3.13.0-beta.32) (2026-03-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.30...v3.13.0-beta.31) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.29...v3.13.0-beta.30) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.28...v3.13.0-beta.29) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.27...v3.13.0-beta.28) (2026-03-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.26...v3.13.0-beta.27) (2026-03-02)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.25...v3.13.0-beta.26) (2026-02-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.24...v3.13.0-beta.25) (2026-02-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Update CS3D 4.18.2 ([#5837](https://github.com/OHIF/Viewers/issues/5837)) ([5370b93](https://github.com/OHIF/Viewers/commit/5370b9382e7bfddeadd69bab9e653f5f997a6e19))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.23...v3.13.0-beta.24) (2026-02-24)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.22...v3.13.0-beta.23) (2026-02-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* palette color 8 encoded 16 ([#5823](https://github.com/OHIF/Viewers/issues/5823)) ([eeca1f7](https://github.com/OHIF/Viewers/commit/eeca1f7a7b529d1700f5d281a6fd98074547ffe9)), closes [#5813](https://github.com/OHIF/Viewers/issues/5813)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.21...v3.13.0-beta.22) (2026-02-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.20...v3.13.0-beta.21) (2026-02-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.19...v3.13.0-beta.20) (2026-02-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.18...v3.13.0-beta.19) (2026-02-20)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.17...v3.13.0-beta.18) (2026-02-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.16...v3.13.0-beta.17) (2026-02-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.15...v3.13.0-beta.16) (2026-02-18)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.14...v3.13.0-beta.15) (2026-02-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.13...v3.13.0-beta.14) (2026-02-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.12...v3.13.0-beta.13) (2026-02-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.11...v3.13.0-beta.12) (2026-02-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.10...v3.13.0-beta.11) (2026-02-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **colors:** Replaces legacy colors with ui-next colors ([#5351](https://github.com/OHIF/Viewers/issues/5351)) ([9a2691a](https://github.com/OHIF/Viewers/commit/9a2691a71fe3723bb05cbd148968b64e5d0fa951))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.9...v3.13.0-beta.10) (2026-02-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.9) (2026-02-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.8) (2026-02-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.7) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.5...v3.13.0-beta.6) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.4...v3.13.0-beta.5) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.3...v3.13.0-beta.4) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.2...v3.13.0-beta.3) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.1...v3.13.0-beta.2) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.0...v3.13.0-beta.1) (2026-02-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.135...v3.13.0-beta.0) (2026-02-07)
|
||||
# [3.12.0](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.135...v3.12.0) (2026-02-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone-dicom-seg",
|
||||
"version": "3.13.0-beta.54",
|
||||
"version": "3.12.2",
|
||||
"description": "DICOM SEG read workflow",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -33,10 +33,10 @@
|
||||
"start": "yarn run dev"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.13.0-beta.54",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.54",
|
||||
"@ohif/extension-default": "3.13.0-beta.54",
|
||||
"@ohif/i18n": "3.13.0-beta.54",
|
||||
"@ohif/core": "3.12.2",
|
||||
"@ohif/extension-cornerstone": "3.12.2",
|
||||
"@ohif/extension-default": "3.12.2",
|
||||
"@ohif/i18n": "3.12.2",
|
||||
"prop-types": "15.8.1",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
@@ -46,8 +46,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@cornerstonejs/adapters": "4.20.0",
|
||||
"@cornerstonejs/core": "4.20.0",
|
||||
"@cornerstonejs/adapters": "4.15.29",
|
||||
"@cornerstonejs/core": "4.15.29",
|
||||
"@kitware/vtk.js": "34.15.1"
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,9 @@ import dcmjs from 'dcmjs';
|
||||
import { classes, Types, utils } from '@ohif/core';
|
||||
import { cache, metaData } from '@cornerstonejs/core';
|
||||
import { segmentation as cornerstoneToolsSegmentation } from '@cornerstonejs/tools';
|
||||
import { adaptersRT, adaptersSEG } from '@cornerstonejs/adapters';
|
||||
import { adaptersRT, helpers, adaptersSEG } from '@cornerstonejs/adapters';
|
||||
import { createReportDialogPrompt, useUIStateStore } from '@ohif/extension-default';
|
||||
import { DicomMetadataStore } from '@ohif/core';
|
||||
|
||||
import PROMPT_RESPONSES from '../../default/src/utils/_shared/PROMPT_RESPONSES';
|
||||
|
||||
@@ -28,11 +29,11 @@ const {
|
||||
},
|
||||
} = adaptersRT;
|
||||
|
||||
const { downloadDICOMData } = helpers;
|
||||
|
||||
const commandsModule = ({
|
||||
servicesManager,
|
||||
extensionManager,
|
||||
commandsManager,
|
||||
}: Types.Extensions.ExtensionParams): Types.Extensions.CommandsModule => {
|
||||
const { segmentationService, displaySetService, viewportGridService } =
|
||||
servicesManager.services as AppTypes.Services;
|
||||
@@ -193,11 +194,8 @@ const commandsModule = ({
|
||||
const generatedSegmentation = actions.generateSegmentation({
|
||||
segmentationId,
|
||||
});
|
||||
const storeFn = commandsManager.runCommand('createStoreFunction', {
|
||||
dataSource: 'download',
|
||||
defaultFileName: `${segmentationInOHIF.label}.dcm`,
|
||||
});
|
||||
storeFn(generatedSegmentation.dataset);
|
||||
|
||||
downloadDICOMData(generatedSegmentation.dataset, `${segmentationInOHIF.label}`);
|
||||
},
|
||||
/**
|
||||
* Stores a segmentation based on the provided segmentationId into a specified data source.
|
||||
@@ -219,10 +217,11 @@ const commandsModule = ({
|
||||
}
|
||||
|
||||
const { label, predecessorImageId } = segmentation;
|
||||
const defaultDataSource = dataSource ?? extensionManager.getActiveDataSource()[0];
|
||||
|
||||
const {
|
||||
value: reportName,
|
||||
dataSourceName,
|
||||
dataSourceName: selectedDataSource,
|
||||
series,
|
||||
priorSeriesNumber,
|
||||
action,
|
||||
@@ -232,58 +231,50 @@ const commandsModule = ({
|
||||
predecessorImageId,
|
||||
title: 'Store Segmentation',
|
||||
modality,
|
||||
enableDownload: true,
|
||||
});
|
||||
|
||||
if (action !== PROMPT_RESPONSES.CREATE_REPORT) {
|
||||
return;
|
||||
}
|
||||
if (action === PROMPT_RESPONSES.CREATE_REPORT) {
|
||||
try {
|
||||
const selectedDataSourceConfig = selectedDataSource
|
||||
? extensionManager.getDataSources(selectedDataSource)[0]
|
||||
: defaultDataSource;
|
||||
|
||||
const defaultFileName =
|
||||
modality === 'RTSTRUCT'
|
||||
? `rtss-${segmentationId}.dcm`
|
||||
: `${label || 'segmentation'}.dcm`;
|
||||
const args = {
|
||||
segmentationId,
|
||||
options: {
|
||||
SeriesDescription: series ? undefined : reportName || label || 'Contour Series',
|
||||
SeriesNumber: series ? undefined : 1 + priorSeriesNumber,
|
||||
predecessorImageId: series,
|
||||
},
|
||||
};
|
||||
const generatedDataAsync =
|
||||
(modality === 'SEG' && actions.generateSegmentation(args)) ||
|
||||
(modality === 'RTSTRUCT' && actions.generateContour(args));
|
||||
const generatedData = await generatedDataAsync;
|
||||
|
||||
const storeFn = commandsManager.runCommand('createStoreFunction', {
|
||||
dataSource: dataSourceName,
|
||||
defaultFileName,
|
||||
});
|
||||
if (!generatedData || !generatedData.dataset) {
|
||||
throw new Error('Error during segmentation generation');
|
||||
}
|
||||
|
||||
if (!storeFn) {
|
||||
throw new Error(`No valid store for dataSource: ${dataSourceName}`);
|
||||
}
|
||||
const { dataset: naturalizedReport } = generatedData;
|
||||
|
||||
try {
|
||||
const args = {
|
||||
segmentationId,
|
||||
options: {
|
||||
SeriesDescription: series ? undefined : reportName || label || 'Contour Series',
|
||||
SeriesNumber: series ? undefined : 1 + priorSeriesNumber,
|
||||
predecessorImageId: series,
|
||||
},
|
||||
};
|
||||
const generatedDataAsync =
|
||||
(modality === 'SEG' && actions.generateSegmentation(args)) ||
|
||||
(modality === 'RTSTRUCT' && actions.generateContour(args));
|
||||
const generatedData = await generatedDataAsync;
|
||||
// DCMJS assigns a dummy study id during creation, and this can cause problems, so clearing it out
|
||||
if (naturalizedReport.StudyID === 'No Study ID') {
|
||||
naturalizedReport.StudyID = '';
|
||||
}
|
||||
|
||||
if (!generatedData?.dataset) {
|
||||
throw new Error('Error during segmentation generation');
|
||||
await selectedDataSourceConfig.store.dicom(naturalizedReport);
|
||||
|
||||
// add the information for where we stored it to the instance as well
|
||||
naturalizedReport.wadoRoot = selectedDataSourceConfig.getConfig().wadoRoot;
|
||||
|
||||
DicomMetadataStore.addInstances([naturalizedReport], true);
|
||||
|
||||
return naturalizedReport;
|
||||
} catch (error) {
|
||||
console.debug('Error storing segmentation:', error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
const { dataset: naturalizedReport } = generatedData;
|
||||
|
||||
// DCMJS assigns a dummy study id during creation, and this can cause problems, so clearing it out
|
||||
if (naturalizedReport.StudyID === 'No Study ID') {
|
||||
naturalizedReport.StudyID = '';
|
||||
}
|
||||
|
||||
await storeFn(naturalizedReport, {});
|
||||
|
||||
return naturalizedReport;
|
||||
} catch (error) {
|
||||
console.debug('Error storing segmentation:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -316,11 +307,14 @@ const commandsModule = ({
|
||||
downloadRTSS: async args => {
|
||||
const { dataset } = await actions.generateContour(args);
|
||||
const { InstanceNumber: instanceNumber = 1, SeriesInstanceUID: seriesUID } = dataset;
|
||||
const storeFn = commandsManager.runCommand('createStoreFunction', {
|
||||
dataSource: 'download',
|
||||
defaultFileName: `rtss-${seriesUID}-${instanceNumber}.dcm`,
|
||||
});
|
||||
await storeFn(dataset);
|
||||
|
||||
try {
|
||||
//Create a URL for the binary.
|
||||
const filename = `rtss-${seriesUID}-${instanceNumber}.dcm`;
|
||||
downloadDICOMData(dataset, filename);
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
}
|
||||
},
|
||||
|
||||
toggleActiveSegmentationUtility: ({ itemId: buttonId }) => {
|
||||
|
||||
@@ -189,7 +189,7 @@ function LogicalContourOperationOptions() {
|
||||
</Tabs>
|
||||
<div>{t(operation.label)}</div>
|
||||
</div>
|
||||
<div className="bg-muted flex h-[62px] w-[88px] items-center justify-center rounded-lg">
|
||||
<div className="bg-primary-dark flex h-[62px] w-[88px] items-center justify-center rounded-lg">
|
||||
<Icons.ByName name={operation.helperIcon}></Icons.ByName>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -30,7 +30,6 @@ function _getDisplaySetsFromSeries(
|
||||
SeriesDate,
|
||||
StructureSetDate,
|
||||
SOPClassUID,
|
||||
FrameOfReferenceUID,
|
||||
wadoRoot,
|
||||
wadoUri,
|
||||
wadoUriRoot,
|
||||
@@ -50,7 +49,6 @@ function _getDisplaySetsFromSeries(
|
||||
StudyInstanceUID,
|
||||
SOPClassHandlerId,
|
||||
SOPClassUID,
|
||||
FrameOfReferenceUID,
|
||||
referencedImages: null,
|
||||
referencedSeriesInstanceUID: null,
|
||||
referencedDisplaySetInstanceUID: null,
|
||||
@@ -106,7 +104,6 @@ function _getDisplaySetsFromSeries(
|
||||
if (addedDisplaySet.SeriesInstanceUID === displaySet.referencedSeriesInstanceUID) {
|
||||
displaySet.referencedDisplaySetInstanceUID = addedDisplaySet.displaySetInstanceUID;
|
||||
displaySet.isReconstructable = addedDisplaySet.isReconstructable;
|
||||
displaySet.FrameOfReferenceUID = addedDisplaySet.FrameOfReferenceUID;
|
||||
unsubscribe();
|
||||
}
|
||||
}
|
||||
@@ -114,7 +111,6 @@ function _getDisplaySetsFromSeries(
|
||||
} else {
|
||||
displaySet.referencedDisplaySetInstanceUID = referencedDisplaySet.displaySetInstanceUID;
|
||||
displaySet.isReconstructable = referencedDisplaySet.isReconstructable;
|
||||
displaySet.FrameOfReferenceUID = referencedDisplaySet.FrameOfReferenceUID;
|
||||
}
|
||||
|
||||
displaySet.load = async ({ headers }) =>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [3.13.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.53...v3.13.0-beta.54) (2026-04-08)
|
||||
## [3.12.2](https://github.com/OHIF/Viewers/compare/v3.12.1...v3.12.2) (2026-05-18)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
@@ -11,458 +11,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.52...v3.13.0-beta.53) (2026-04-06)
|
||||
|
||||
|
||||
### Reverts
|
||||
|
||||
* rename DisplaySet.frameOfReferenceUID back to FrameOfReferenceUID ([#5943](https://github.com/OHIF/Viewers/issues/5943)) ([0e933c2](https://github.com/OHIF/Viewers/commit/0e933c256e07b7cda35ed2ba3cfb1ab35d895d57))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.51...v3.13.0-beta.52) (2026-04-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.50...v3.13.0-beta.51) (2026-04-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.49...v3.13.0-beta.50) (2026-04-02)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.48...v3.13.0-beta.49) (2026-04-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation:** restrict overlay segmentation menu to same frame of reference as viewport background display set ([#5900](https://github.com/OHIF/Viewers/issues/5900)) ([b9029ef](https://github.com/OHIF/Viewers/commit/b9029ef6f8d63a0e36ec929310c1c5ad3f563ef8))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.47...v3.13.0-beta.48) (2026-04-01)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.46...v3.13.0-beta.47) (2026-03-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.45...v3.13.0-beta.46) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.44...v3.13.0-beta.45) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.43...v3.13.0-beta.44) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.42...v3.13.0-beta.43) (2026-03-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **SR:** Added support for spline and live wire SR items. ([#5870](https://github.com/OHIF/Viewers/issues/5870)) ([1d4802c](https://github.com/OHIF/Viewers/commit/1d4802c2a38dd75dca7afca87913e100453c9135))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.41...v3.13.0-beta.42) (2026-03-17)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add combined build ([#5895](https://github.com/OHIF/Viewers/issues/5895)) ([1df671e](https://github.com/OHIF/Viewers/commit/1df671e9ab67d43f98bf09f6838ddc0a5f220277))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.40...v3.13.0-beta.41) (2026-03-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **sr-hydration:** enable hydration and arrow navigation for 3D SR measurements ([#5887](https://github.com/OHIF/Viewers/issues/5887)) ([7a38903](https://github.com/OHIF/Viewers/commit/7a38903b1977b1cf0f3a0ba8a4a823fac5e8fdeb))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.39...v3.13.0-beta.40) (2026-03-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.38...v3.13.0-beta.39) (2026-03-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.37...v3.13.0-beta.38) (2026-03-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation:** Display "No description S:{series number} {modality}" for segmentations with no label. ([#5874](https://github.com/OHIF/Viewers/issues/5874)) ([7b5d0ce](https://github.com/OHIF/Viewers/commit/7b5d0ce40e5422ccfce6091ac3d7559586cbe57e))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.36...v3.13.0-beta.37) (2026-03-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.35...v3.13.0-beta.36) (2026-03-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.34...v3.13.0-beta.35) (2026-03-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.33...v3.13.0-beta.34) (2026-03-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.32...v3.13.0-beta.33) (2026-03-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.31...v3.13.0-beta.32) (2026-03-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.30...v3.13.0-beta.31) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.29...v3.13.0-beta.30) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.28...v3.13.0-beta.29) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.27...v3.13.0-beta.28) (2026-03-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.26...v3.13.0-beta.27) (2026-03-02)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.25...v3.13.0-beta.26) (2026-02-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.24...v3.13.0-beta.25) (2026-02-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Update CS3D 4.18.2 ([#5837](https://github.com/OHIF/Viewers/issues/5837)) ([5370b93](https://github.com/OHIF/Viewers/commit/5370b9382e7bfddeadd69bab9e653f5f997a6e19))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.23...v3.13.0-beta.24) (2026-02-24)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.22...v3.13.0-beta.23) (2026-02-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* palette color 8 encoded 16 ([#5823](https://github.com/OHIF/Viewers/issues/5823)) ([eeca1f7](https://github.com/OHIF/Viewers/commit/eeca1f7a7b529d1700f5d281a6fd98074547ffe9)), closes [#5813](https://github.com/OHIF/Viewers/issues/5813)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.21...v3.13.0-beta.22) (2026-02-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.20...v3.13.0-beta.21) (2026-02-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.19...v3.13.0-beta.20) (2026-02-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.18...v3.13.0-beta.19) (2026-02-20)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.17...v3.13.0-beta.18) (2026-02-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.16...v3.13.0-beta.17) (2026-02-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.15...v3.13.0-beta.16) (2026-02-18)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.14...v3.13.0-beta.15) (2026-02-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.13...v3.13.0-beta.14) (2026-02-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.12...v3.13.0-beta.13) (2026-02-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.11...v3.13.0-beta.12) (2026-02-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.10...v3.13.0-beta.11) (2026-02-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **colors:** Replaces legacy colors with ui-next colors ([#5351](https://github.com/OHIF/Viewers/issues/5351)) ([9a2691a](https://github.com/OHIF/Viewers/commit/9a2691a71fe3723bb05cbd148968b64e5d0fa951))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.9...v3.13.0-beta.10) (2026-02-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.9) (2026-02-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.8) (2026-02-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.7) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.5...v3.13.0-beta.6) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.4...v3.13.0-beta.5) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.3...v3.13.0-beta.4) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.2...v3.13.0-beta.3) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.1...v3.13.0-beta.2) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.0...v3.13.0-beta.1) (2026-02-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.135...v3.13.0-beta.0) (2026-02-07)
|
||||
# [3.12.0](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.135...v3.12.0) (2026-02-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone-dicom-sr",
|
||||
"version": "3.13.0-beta.54",
|
||||
"version": "3.12.2",
|
||||
"description": "OHIF extension for an SR Cornerstone Viewport",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -34,10 +34,10 @@
|
||||
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.13.0-beta.54",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.54",
|
||||
"@ohif/extension-measurement-tracking": "3.13.0-beta.54",
|
||||
"@ohif/ui": "3.13.0-beta.54",
|
||||
"@ohif/core": "3.12.2",
|
||||
"@ohif/extension-cornerstone": "3.12.2",
|
||||
"@ohif/extension-measurement-tracking": "3.12.2",
|
||||
"@ohif/ui": "3.12.2",
|
||||
"dcmjs": "0.49.4",
|
||||
"dicom-parser": "1.8.21",
|
||||
"hammerjs": "2.0.8",
|
||||
@@ -46,9 +46,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@cornerstonejs/adapters": "4.20.0",
|
||||
"@cornerstonejs/core": "4.20.0",
|
||||
"@cornerstonejs/tools": "4.20.0",
|
||||
"@cornerstonejs/adapters": "4.15.29",
|
||||
"@cornerstonejs/core": "4.15.29",
|
||||
"@cornerstonejs/tools": "4.15.29",
|
||||
"classnames": "2.5.1"
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,14 @@
|
||||
import { metaData } from '@cornerstonejs/core';
|
||||
|
||||
import OHIF from '@ohif/core';
|
||||
import OHIF, { DicomMetadataStore, utils } from '@ohif/core';
|
||||
import dcmjs from 'dcmjs';
|
||||
import { adaptersSR } from '@cornerstonejs/adapters';
|
||||
|
||||
import getFilteredCornerstoneToolState from './utils/getFilteredCornerstoneToolState';
|
||||
import hydrateStructuredReport from './utils/hydrateStructuredReport';
|
||||
|
||||
const { downloadBlob } = utils;
|
||||
|
||||
const { MeasurementReport } = adaptersSR.Cornerstone3D;
|
||||
const { log } = OHIF;
|
||||
|
||||
@@ -72,8 +75,24 @@ const commandsModule = (props: withAppTypes) => {
|
||||
/**
|
||||
*
|
||||
* @param measurementData An array of measurements from the measurements service
|
||||
* @param additionalFindingTypes toolTypes that should be stored with labels as Findings
|
||||
* @param options Naturalized DICOM JSON headers to merge into the displaySet.
|
||||
* as opposed to Finding Sites.
|
||||
* that you wish to serialize.
|
||||
* @param dataSource The data source name ('download', 'copyToClipboard', or a named data source).
|
||||
*/
|
||||
downloadReport: ({ measurementData, additionalFindingTypes, options = {} }) => {
|
||||
const srDataset = _generateReport(measurementData, additionalFindingTypes, options);
|
||||
const reportBlob = dcmjs.data.datasetToBlob(srDataset);
|
||||
|
||||
//Create a URL for the binary.
|
||||
downloadBlob(reportBlob, { filename: 'dicom-sr.dcm' });
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* @param measurementData An array of measurements from the measurements service
|
||||
* that you wish to serialize.
|
||||
* @param dataSource The dataSource that you wish to use to persist the data.
|
||||
* @param additionalFindingTypes toolTypes that should be stored with labels as Findings
|
||||
* @param options Naturalized DICOM JSON headers to merge into the displaySet.
|
||||
* @return The naturalized report
|
||||
@@ -84,30 +103,23 @@ const commandsModule = (props: withAppTypes) => {
|
||||
additionalFindingTypes,
|
||||
options = {},
|
||||
}) => {
|
||||
// Use the @cornerstonejs adapter for converting to/from DICOM
|
||||
// But it is good enough for now whilst we only have cornerstone as a datasource.
|
||||
log.info('[DICOMSR] storeMeasurements');
|
||||
|
||||
const storeFn = commandsManager.runCommand('createStoreFunction', {
|
||||
dataSource,
|
||||
defaultFileName: 'dicom-sr.dcm',
|
||||
});
|
||||
|
||||
if (!storeFn) {
|
||||
log.error('[DICOMSR] No valid store for dataSource:', dataSource);
|
||||
if (!dataSource || !dataSource.store || !dataSource.store.dicom) {
|
||||
log.error('[DICOMSR] datasource has no dataSource.store.dicom endpoint!');
|
||||
return Promise.reject({});
|
||||
}
|
||||
|
||||
try {
|
||||
const naturalizedReport = _generateReport(
|
||||
measurementData,
|
||||
additionalFindingTypes,
|
||||
options
|
||||
);
|
||||
const naturalizedReport = _generateReport(measurementData, additionalFindingTypes, options);
|
||||
|
||||
const { ContentSequence } = naturalizedReport;
|
||||
const { StudyInstanceUID, ContentSequence } = naturalizedReport;
|
||||
// The content sequence has 5 or more elements, of which
|
||||
// the `[4]` element contains the annotation data, so this is
|
||||
// checking that there is some annotation data present.
|
||||
if (!ContentSequence?.[4]?.ContentSequence?.length) {
|
||||
if (!ContentSequence?.[4].ContentSequence?.length) {
|
||||
console.log('naturalizedReport missing imaging content', naturalizedReport);
|
||||
throw new Error('Invalid report, no content');
|
||||
}
|
||||
@@ -116,12 +128,22 @@ const commandsModule = (props: withAppTypes) => {
|
||||
}
|
||||
|
||||
const onBeforeDicomStore = customizationService.getCustomization('onBeforeDicomStore');
|
||||
|
||||
let dicomDict;
|
||||
if (typeof onBeforeDicomStore === 'function') {
|
||||
dicomDict = onBeforeDicomStore({ dicomDict, measurementData, naturalizedReport });
|
||||
}
|
||||
|
||||
await storeFn(naturalizedReport, { measurementData, dicomDict });
|
||||
await dataSource.store.dicom(naturalizedReport, null, dicomDict);
|
||||
|
||||
if (StudyInstanceUID) {
|
||||
dataSource.deleteStudyMetadataPromise(StudyInstanceUID);
|
||||
}
|
||||
|
||||
// The "Mode" route listens for DicomMetadataStore changes
|
||||
// When a new instance is added, it listens and
|
||||
// automatically calls makeDisplaySets
|
||||
DicomMetadataStore.addInstances([naturalizedReport], true);
|
||||
|
||||
return naturalizedReport;
|
||||
} catch (error) {
|
||||
@@ -144,6 +166,7 @@ const commandsModule = (props: withAppTypes) => {
|
||||
};
|
||||
|
||||
const definitions = {
|
||||
downloadReport: actions.downloadReport,
|
||||
storeMeasurements: actions.storeMeasurements,
|
||||
hydrateStructuredReport: actions.hydrateStructuredReport,
|
||||
};
|
||||
|
||||
@@ -9,7 +9,7 @@ function OHIFCornerstoneSRTextViewport(props: withAppTypes) {
|
||||
const instance = displaySet.instances[0];
|
||||
|
||||
return (
|
||||
<div className="text-foreground relative flex h-full w-full flex-col overflow-auto p-4">
|
||||
<div className="relative flex h-full w-full flex-col overflow-auto p-4 text-white">
|
||||
<div>
|
||||
{/* The root level is always a container */}
|
||||
<OHIFCornerstoneSRContainer container={instance} />
|
||||
|
||||
@@ -637,35 +637,16 @@ function _processNonGeometricallyDefinedMeasurement(mergedContentSequence) {
|
||||
NUMContentItems.forEach(item => {
|
||||
const { ConceptNameCodeSequence, ContentSequence, MeasuredValueSequence } = item;
|
||||
|
||||
// Handle spatial reference ONLY if ContentSequence exists.
|
||||
// ContentSequence may be a scalar SCOORD or an array when additional named
|
||||
// SCOORDs (e.g. control points) are nested alongside the primary geometry.
|
||||
// Pick the primary geometry entry: prefer the SCOORD without a
|
||||
// ConceptNameCodeSequence (plain polyline), falling back to the first SCOORD.
|
||||
// Handle spatial reference ONLY if ContentSequence exists
|
||||
if (ContentSequence) {
|
||||
const scoordItem = Array.isArray(ContentSequence)
|
||||
? (ContentSequence.find(
|
||||
cs =>
|
||||
(cs.ValueType === 'SCOORD' || cs.ValueType === 'SCOORD3D') &&
|
||||
!cs.ConceptNameCodeSequence
|
||||
) ?? ContentSequence.find(cs => cs.ValueType === 'SCOORD' || cs.ValueType === 'SCOORD3D'))
|
||||
: ContentSequence;
|
||||
|
||||
if (!scoordItem) {
|
||||
console.warn(
|
||||
'ContentSequence array contains no SCOORD or SCOORD3D entry, skipping annotation.'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const { ValueType } = scoordItem;
|
||||
const { ValueType } = ContentSequence;
|
||||
|
||||
if (ValueType !== 'SCOORD' && ValueType !== 'SCOORD3D') {
|
||||
console.warn(`Graphic ${ValueType} not currently supported, skipping annotation.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const coords = _getCoordsFromSCOORDOrSCOORD3D(scoordItem);
|
||||
const coords = _getCoordsFromSCOORDOrSCOORD3D(ContentSequence);
|
||||
|
||||
if (coords) {
|
||||
measurement.coords.push(coords);
|
||||
|
||||
@@ -80,7 +80,7 @@ export default function hydrateStructuredReport(
|
||||
const { ReferencedSOPInstanceUID, imageId, frameNumber = 1 } = measurement;
|
||||
const key = `${ReferencedSOPInstanceUID}:${frameNumber}`;
|
||||
|
||||
if (imageId && !sopInstanceUIDToImageId[key]) {
|
||||
if (!sopInstanceUIDToImageId[key]) {
|
||||
sopInstanceUIDToImageId[key] = imageId;
|
||||
}
|
||||
});
|
||||
@@ -118,17 +118,41 @@ export default function hydrateStructuredReport(
|
||||
}
|
||||
});
|
||||
|
||||
// Set the series touched as tracked.
|
||||
const imageIds = [];
|
||||
|
||||
// TODO: notification if no hydratable?
|
||||
Object.keys(hydratableMeasurementsInSR).forEach(annotationType => {
|
||||
const toolDataForAnnotationType = hydratableMeasurementsInSR[annotationType];
|
||||
|
||||
toolDataForAnnotationType.forEach(toolData => {
|
||||
// Add the measurement to toolState
|
||||
// dcmjs and Cornerstone3D has structural defect in supporting multi-frame
|
||||
// files, and looking up the imageId from sopInstanceUIDToImageId results
|
||||
// in the wrong value.
|
||||
const frameNumber = toolData.annotation.data?.frameNumber || 1;
|
||||
const imageId = sopInstanceUIDToImageId[`${toolData.sopInstanceUid}:${frameNumber}`];
|
||||
|
||||
if (!imageIds.includes(imageId)) {
|
||||
imageIds.push(imageId);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
let targetStudyInstanceUID;
|
||||
const SeriesInstanceUIDs = [];
|
||||
|
||||
// Set the series touched as tracked.
|
||||
const imageIds = getImageIds(hydratableMeasurementsInSR, sopInstanceUIDToImageId);
|
||||
|
||||
for (const imageId of imageIds) {
|
||||
for (let i = 0; i < imageIds.length; i++) {
|
||||
const imageId = imageIds[i];
|
||||
if (!imageId) {
|
||||
continue;
|
||||
}
|
||||
const { SeriesInstanceUID, StudyInstanceUID } = metaData.get('instance', imageId);
|
||||
|
||||
if (!SeriesInstanceUIDs.includes(SeriesInstanceUID)) {
|
||||
SeriesInstanceUIDs.push(SeriesInstanceUID);
|
||||
}
|
||||
|
||||
if (!targetStudyInstanceUID) {
|
||||
targetStudyInstanceUID = StudyInstanceUID;
|
||||
} else if (targetStudyInstanceUID !== StudyInstanceUID) {
|
||||
@@ -136,31 +160,6 @@ export default function hydrateStructuredReport(
|
||||
}
|
||||
}
|
||||
|
||||
// For 3d annotations there are no image IDs,
|
||||
// so we need to find the display sets by frame of reference to get the SeriesInstanceUIDs
|
||||
const frameOfReferenceUIDs = getFrameOfReferenceUIDs(
|
||||
hydratableMeasurementsInSR,
|
||||
sopInstanceUIDToImageId
|
||||
);
|
||||
|
||||
for (const FrameOfReferenceUID of frameOfReferenceUIDs) {
|
||||
const displaySetsFOR = displaySetService.getDisplaySetsBy(
|
||||
ds => ds.FrameOfReferenceUID === FrameOfReferenceUID && !ds.isDerivedDisplaySet
|
||||
);
|
||||
const ds = chooseDisplaySet(displaySetsFOR, FrameOfReferenceUID);
|
||||
if (!ds) {
|
||||
continue;
|
||||
}
|
||||
if (!SeriesInstanceUIDs.includes(ds.SeriesInstanceUID)) {
|
||||
SeriesInstanceUIDs.push(ds.SeriesInstanceUID);
|
||||
}
|
||||
if (!targetStudyInstanceUID) {
|
||||
targetStudyInstanceUID = ds.StudyInstanceUID;
|
||||
} else if (targetStudyInstanceUID !== ds.StudyInstanceUID) {
|
||||
console.warn('NO SUPPORT FOR SRs THAT HAVE MEASUREMENTS FROM MULTIPLE STUDIES.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets reference data for what frame of reference and the referenced
|
||||
* image id, or for 3d measurements, the volumeId to apply this annotation to.
|
||||
@@ -197,7 +196,7 @@ export default function hydrateStructuredReport(
|
||||
toolDataForAnnotationType.forEach(toolData => {
|
||||
toolData.uid = guid();
|
||||
const referenceData = getReferenceData(toolData);
|
||||
const { referencedImageId } = referenceData;
|
||||
const { imageId } = referenceData;
|
||||
|
||||
const annotation = {
|
||||
annotationUID: toolData.annotation.annotationUID,
|
||||
@@ -242,8 +241,8 @@ export default function hydrateStructuredReport(
|
||||
locking.setAnnotationLocked(newAnnotationUID, true);
|
||||
}
|
||||
|
||||
if (referencedImageId && !imageIds.includes(referencedImageId)) {
|
||||
imageIds.push(referencedImageId);
|
||||
if (imageId && !imageIds.includes(imageId)) {
|
||||
imageIds.push(imageId);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -256,64 +255,15 @@ export default function hydrateStructuredReport(
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the unique imageIds from hydratable measurements that have an imageId reference
|
||||
* (i.e., 2D/SCOORD annotations).
|
||||
*/
|
||||
function getImageIds(hydratableMeasurementsInSR, sopInstanceUIDToImageId): string[] {
|
||||
const imageIds: string[] = [];
|
||||
Object.keys(hydratableMeasurementsInSR).forEach(annotationType => {
|
||||
const toolDataForAnnotationType = hydratableMeasurementsInSR[annotationType];
|
||||
|
||||
toolDataForAnnotationType.forEach(toolData => {
|
||||
// Add the measurement to toolState
|
||||
// dcmjs and Cornerstone3D has structural defect in supporting multi-frame
|
||||
// files, and looking up the imageId from sopInstanceUIDToImageId results
|
||||
// in the wrong value.
|
||||
const frameNumber = toolData.annotation.data?.frameNumber || 1;
|
||||
const imageId = sopInstanceUIDToImageId[`${toolData.sopInstanceUid}:${frameNumber}`];
|
||||
|
||||
if (imageId && !imageIds.includes(imageId)) {
|
||||
imageIds.push(imageId);
|
||||
}
|
||||
});
|
||||
});
|
||||
return imageIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the unique FrameOfReferenceUIDs from hydratable measurements that have no imageId reference
|
||||
* (i.e., 3D/SCOORD3D annotations). This excludes annotations handled by the getImageIds function.
|
||||
*/
|
||||
function getFrameOfReferenceUIDs(hydratableMeasurementsInSR, sopInstanceUIDToImageId): string[] {
|
||||
const frameOfReferenceUIDs: string[] = [];
|
||||
|
||||
Object.keys(hydratableMeasurementsInSR).forEach(annotationType => {
|
||||
const toolDataForAnnotationType = hydratableMeasurementsInSR[annotationType];
|
||||
toolDataForAnnotationType.forEach(toolData => {
|
||||
const frameNumber = toolData.annotation.data?.frameNumber || 1;
|
||||
const imageId = sopInstanceUIDToImageId[`${toolData.sopInstanceUid}:${frameNumber}`];
|
||||
|
||||
if (!imageId) {
|
||||
const { FrameOfReferenceUID } = toolData.annotation.metadata;
|
||||
if (FrameOfReferenceUID && !frameOfReferenceUIDs.includes(FrameOfReferenceUID)) {
|
||||
frameOfReferenceUIDs.push(FrameOfReferenceUID);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
return frameOfReferenceUIDs;
|
||||
}
|
||||
|
||||
/**
|
||||
* For 3d annotations, there are often several display sets which could
|
||||
* be used to display the annotation. Choose the first annotation with the
|
||||
* same frame of reference that is reconstructable, or the first display set
|
||||
* otherwise.
|
||||
*/
|
||||
function chooseDisplaySet(displaySets, reference) {
|
||||
function chooseDisplaySet(displaySets, annotation) {
|
||||
if (!displaySets?.length) {
|
||||
console.warn('No display set found for', reference);
|
||||
console.warn('No display set found for', annotation);
|
||||
return;
|
||||
}
|
||||
if (displaySets.length === 1) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [3.13.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.53...v3.13.0-beta.54) (2026-04-08)
|
||||
## [3.12.2](https://github.com/OHIF/Viewers/compare/v3.12.1...v3.12.2) (2026-05-18)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
@@ -11,446 +11,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.52...v3.13.0-beta.53) (2026-04-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.51...v3.13.0-beta.52) (2026-04-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.50...v3.13.0-beta.51) (2026-04-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.49...v3.13.0-beta.50) (2026-04-02)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.48...v3.13.0-beta.49) (2026-04-02)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.47...v3.13.0-beta.48) (2026-04-01)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.46...v3.13.0-beta.47) (2026-03-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.45...v3.13.0-beta.46) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.44...v3.13.0-beta.45) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.43...v3.13.0-beta.44) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.42...v3.13.0-beta.43) (2026-03-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.41...v3.13.0-beta.42) (2026-03-17)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add combined build ([#5895](https://github.com/OHIF/Viewers/issues/5895)) ([1df671e](https://github.com/OHIF/Viewers/commit/1df671e9ab67d43f98bf09f6838ddc0a5f220277))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.40...v3.13.0-beta.41) (2026-03-16)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.39...v3.13.0-beta.40) (2026-03-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.38...v3.13.0-beta.39) (2026-03-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.37...v3.13.0-beta.38) (2026-03-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation:** Display "No description S:{series number} {modality}" for segmentations with no label. ([#5874](https://github.com/OHIF/Viewers/issues/5874)) ([7b5d0ce](https://github.com/OHIF/Viewers/commit/7b5d0ce40e5422ccfce6091ac3d7559586cbe57e))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.36...v3.13.0-beta.37) (2026-03-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.35...v3.13.0-beta.36) (2026-03-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.34...v3.13.0-beta.35) (2026-03-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.33...v3.13.0-beta.34) (2026-03-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.32...v3.13.0-beta.33) (2026-03-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.31...v3.13.0-beta.32) (2026-03-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.30...v3.13.0-beta.31) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.29...v3.13.0-beta.30) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.28...v3.13.0-beta.29) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.27...v3.13.0-beta.28) (2026-03-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.26...v3.13.0-beta.27) (2026-03-02)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.25...v3.13.0-beta.26) (2026-02-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.24...v3.13.0-beta.25) (2026-02-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Update CS3D 4.18.2 ([#5837](https://github.com/OHIF/Viewers/issues/5837)) ([5370b93](https://github.com/OHIF/Viewers/commit/5370b9382e7bfddeadd69bab9e653f5f997a6e19))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.23...v3.13.0-beta.24) (2026-02-24)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.22...v3.13.0-beta.23) (2026-02-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* palette color 8 encoded 16 ([#5823](https://github.com/OHIF/Viewers/issues/5823)) ([eeca1f7](https://github.com/OHIF/Viewers/commit/eeca1f7a7b529d1700f5d281a6fd98074547ffe9)), closes [#5813](https://github.com/OHIF/Viewers/issues/5813)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.21...v3.13.0-beta.22) (2026-02-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.20...v3.13.0-beta.21) (2026-02-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.19...v3.13.0-beta.20) (2026-02-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.18...v3.13.0-beta.19) (2026-02-20)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.17...v3.13.0-beta.18) (2026-02-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.16...v3.13.0-beta.17) (2026-02-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.15...v3.13.0-beta.16) (2026-02-18)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.14...v3.13.0-beta.15) (2026-02-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.13...v3.13.0-beta.14) (2026-02-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.12...v3.13.0-beta.13) (2026-02-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.11...v3.13.0-beta.12) (2026-02-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.10...v3.13.0-beta.11) (2026-02-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **colors:** Replaces legacy colors with ui-next colors ([#5351](https://github.com/OHIF/Viewers/issues/5351)) ([9a2691a](https://github.com/OHIF/Viewers/commit/9a2691a71fe3723bb05cbd148968b64e5d0fa951))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.9...v3.13.0-beta.10) (2026-02-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.9) (2026-02-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.8) (2026-02-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.7) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.5...v3.13.0-beta.6) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.4...v3.13.0-beta.5) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.3...v3.13.0-beta.4) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.2...v3.13.0-beta.3) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.1...v3.13.0-beta.2) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.0...v3.13.0-beta.1) (2026-02-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.135...v3.13.0-beta.0) (2026-02-07)
|
||||
# [3.12.0](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.135...v3.12.0) (2026-02-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone-dynamic-volume",
|
||||
"version": "3.13.0-beta.54",
|
||||
"version": "3.12.2",
|
||||
"description": "OHIF extension for 4D volumes data",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -29,11 +29,11 @@
|
||||
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.13.0-beta.54",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.54",
|
||||
"@ohif/extension-default": "3.13.0-beta.54",
|
||||
"@ohif/i18n": "3.13.0-beta.54",
|
||||
"@ohif/ui": "3.13.0-beta.54",
|
||||
"@ohif/core": "3.12.2",
|
||||
"@ohif/extension-cornerstone": "3.12.2",
|
||||
"@ohif/extension-default": "3.12.2",
|
||||
"@ohif/i18n": "3.12.2",
|
||||
"@ohif/ui": "3.12.2",
|
||||
"dcmjs": "0.49.4",
|
||||
"dicom-parser": "1.8.21",
|
||||
"hammerjs": "2.0.8",
|
||||
@@ -42,8 +42,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@cornerstonejs/core": "4.20.0",
|
||||
"@cornerstonejs/tools": "4.20.0",
|
||||
"@cornerstonejs/core": "4.15.29",
|
||||
"@cornerstonejs/tools": "4.15.29",
|
||||
"classnames": "2.5.1"
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ function DynamicDataPanel({ servicesManager, commandsManager, tab }: withAppType
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className="text-foreground flex flex-col"
|
||||
className="flex flex-col text-white"
|
||||
data-cy={'dynamic-volume-panel'}
|
||||
>
|
||||
<PanelGenerateImage
|
||||
|
||||
@@ -10,7 +10,7 @@ function WorkflowPanel({ servicesManager }: { servicesManager: ServicesManager }
|
||||
return (
|
||||
<div
|
||||
data-cy={'workflow-panel'}
|
||||
className="bg-popover mb-1 px-3 py-4"
|
||||
className="bg-secondary-dark mb-1 px-3 py-4"
|
||||
>
|
||||
<div className="mb-1">Workflow</div>
|
||||
<div>
|
||||
|
||||
@@ -3,29 +3,7 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [3.13.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.53...v3.13.0-beta.54) (2026-04-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cornerstone:** read FrameOfReferenceUID from display set in viewport service ([#5950](https://github.com/OHIF/Viewers/issues/5950)) ([d219171](https://github.com/OHIF/Viewers/commit/d219171e25caf5a7c575080f63819d6f4fe45016))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.52...v3.13.0-beta.53) (2026-04-06)
|
||||
|
||||
|
||||
### Reverts
|
||||
|
||||
* rename DisplaySet.frameOfReferenceUID back to FrameOfReferenceUID ([#5943](https://github.com/OHIF/Viewers/issues/5943)) ([0e933c2](https://github.com/OHIF/Viewers/commit/0e933c256e07b7cda35ed2ba3cfb1ab35d895d57))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.51...v3.13.0-beta.52) (2026-04-06)
|
||||
## [3.12.2](https://github.com/OHIF/Viewers/compare/v3.12.1...v3.12.2) (2026-05-18)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
@@ -33,466 +11,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.50...v3.13.0-beta.51) (2026-04-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.49...v3.13.0-beta.50) (2026-04-02)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.48...v3.13.0-beta.49) (2026-04-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation:** restrict overlay segmentation menu to same frame of reference as viewport background display set ([#5900](https://github.com/OHIF/Viewers/issues/5900)) ([b9029ef](https://github.com/OHIF/Viewers/commit/b9029ef6f8d63a0e36ec929310c1c5ad3f563ef8))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.47...v3.13.0-beta.48) (2026-04-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **measurement:** Restore viewport interactivity when deleting in-progress Spline or Livewire measurement ([#5905](https://github.com/OHIF/Viewers/issues/5905)) ([7929f08](https://github.com/OHIF/Viewers/commit/7929f0898f1bf882682a912b1c32d93d0944726f))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.46...v3.13.0-beta.47) (2026-03-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.45...v3.13.0-beta.46) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.44...v3.13.0-beta.45) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.43...v3.13.0-beta.44) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.42...v3.13.0-beta.43) (2026-03-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **SR:** Added support for spline and live wire SR items. ([#5870](https://github.com/OHIF/Viewers/issues/5870)) ([1d4802c](https://github.com/OHIF/Viewers/commit/1d4802c2a38dd75dca7afca87913e100453c9135))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.41...v3.13.0-beta.42) (2026-03-17)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add combined build ([#5895](https://github.com/OHIF/Viewers/issues/5895)) ([1df671e](https://github.com/OHIF/Viewers/commit/1df671e9ab67d43f98bf09f6838ddc0a5f220277))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.40...v3.13.0-beta.41) (2026-03-16)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.39...v3.13.0-beta.40) (2026-03-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.38...v3.13.0-beta.39) (2026-03-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **window level:** The window level value is not displayed by default on all the viewports when selecting common/custom layout and TMTV. ([#5865](https://github.com/OHIF/Viewers/issues/5865)) ([fe1ecfe](https://github.com/OHIF/Viewers/commit/fe1ecfe0cc5d1bcf82686d821f356da8936a8c4b))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.37...v3.13.0-beta.38) (2026-03-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation:** Display "No description S:{series number} {modality}" for segmentations with no label. ([#5874](https://github.com/OHIF/Viewers/issues/5874)) ([7b5d0ce](https://github.com/OHIF/Viewers/commit/7b5d0ce40e5422ccfce6091ac3d7559586cbe57e))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.36...v3.13.0-beta.37) (2026-03-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.35...v3.13.0-beta.36) (2026-03-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.34...v3.13.0-beta.35) (2026-03-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.33...v3.13.0-beta.34) (2026-03-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **seg hydration:** auto-hydrate RT struct on second load with disableConfirmationPrompts ([#5875](https://github.com/OHIF/Viewers/issues/5875)) ([6f773f9](https://github.com/OHIF/Viewers/commit/6f773f997214c388409f3af3e9fc0e5b84debc10))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.32...v3.13.0-beta.33) (2026-03-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.31...v3.13.0-beta.32) (2026-03-05)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **ecg:** add DICOM ECG waveform extension ([#5856](https://github.com/OHIF/Viewers/issues/5856)) ([70f76ae](https://github.com/OHIF/Viewers/commit/70f76aeba1b27f8e4de5ec73a7b831428e38e3d2))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.30...v3.13.0-beta.31) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.29...v3.13.0-beta.30) (2026-03-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation:** segment bidirectional tool error and show toast notification when no segment is drawn ([#5861](https://github.com/OHIF/Viewers/issues/5861)) ([7e10830](https://github.com/OHIF/Viewers/commit/7e10830d5802e22bda4df6a3f8008e9a414b4cd4))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.28...v3.13.0-beta.29) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.27...v3.13.0-beta.28) (2026-03-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.26...v3.13.0-beta.27) (2026-03-02)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.25...v3.13.0-beta.26) (2026-02-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.24...v3.13.0-beta.25) (2026-02-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Update CS3D 4.18.2 ([#5837](https://github.com/OHIF/Viewers/issues/5837)) ([5370b93](https://github.com/OHIF/Viewers/commit/5370b9382e7bfddeadd69bab9e653f5f997a6e19))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.23...v3.13.0-beta.24) (2026-02-24)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.22...v3.13.0-beta.23) (2026-02-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* palette color 8 encoded 16 ([#5823](https://github.com/OHIF/Viewers/issues/5823)) ([eeca1f7](https://github.com/OHIF/Viewers/commit/eeca1f7a7b529d1700f5d281a6fd98074547ffe9)), closes [#5813](https://github.com/OHIF/Viewers/issues/5813)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.21...v3.13.0-beta.22) (2026-02-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.20...v3.13.0-beta.21) (2026-02-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.19...v3.13.0-beta.20) (2026-02-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.18...v3.13.0-beta.19) (2026-02-20)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.17...v3.13.0-beta.18) (2026-02-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation overlay:** update viewport ds list upon seg delete - OHIF-2425 ([#5729](https://github.com/OHIF/Viewers/issues/5729)) ([b353541](https://github.com/OHIF/Viewers/commit/b35354120a01d89b27844f967c32c052bba8b096))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.16...v3.13.0-beta.17) (2026-02-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Add copy to clipboard option for capture ([#5720](https://github.com/OHIF/Viewers/issues/5720)) ([53c67f3](https://github.com/OHIF/Viewers/commit/53c67f361234a0b4160c1b11fafcb143a0723336))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.15...v3.13.0-beta.16) (2026-02-18)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.14...v3.13.0-beta.15) (2026-02-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.13...v3.13.0-beta.14) (2026-02-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.12...v3.13.0-beta.13) (2026-02-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **colors:** Replace hardcoded black with background color token ([#5815](https://github.com/OHIF/Viewers/issues/5815)) ([dbc31a5](https://github.com/OHIF/Viewers/commit/dbc31a5d4ec5b2238683a580af96aff23d9fafeb))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.11...v3.13.0-beta.12) (2026-02-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.10...v3.13.0-beta.11) (2026-02-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **colors:** Replaces legacy colors with ui-next colors ([#5351](https://github.com/OHIF/Viewers/issues/5351)) ([9a2691a](https://github.com/OHIF/Viewers/commit/9a2691a71fe3723bb05cbd148968b64e5d0fa951))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.9...v3.13.0-beta.10) (2026-02-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.9) (2026-02-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.8) (2026-02-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.7) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.5...v3.13.0-beta.6) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.4...v3.13.0-beta.5) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.3...v3.13.0-beta.4) (2026-02-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Better handle octet stream case ([#5789](https://github.com/OHIF/Viewers/issues/5789)) ([037402f](https://github.com/OHIF/Viewers/commit/037402f7f6a1fc07593be302e4f578f6c4870c6e))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.2...v3.13.0-beta.3) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.1...v3.13.0-beta.2) (2026-02-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cine:** prevent crash on second view/hydration of SR series ([#5724](https://github.com/OHIF/Viewers/issues/5724)) ([f70c9b9](https://github.com/OHIF/Viewers/commit/f70c9b932db2bb14173acae675d38ce250d244fa))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.0...v3.13.0-beta.1) (2026-02-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.135...v3.13.0-beta.0) (2026-02-07)
|
||||
# [3.12.0](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.135...v3.12.0) (2026-02-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone",
|
||||
"version": "3.13.0-beta.54",
|
||||
"version": "3.12.2",
|
||||
"description": "OHIF extension for Cornerstone",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -40,9 +40,9 @@
|
||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "1.2.2",
|
||||
"@cornerstonejs/codec-openjpeg": "1.3.0",
|
||||
"@cornerstonejs/codec-openjph": "2.4.7",
|
||||
"@cornerstonejs/dicom-image-loader": "4.20.0",
|
||||
"@ohif/core": "3.13.0-beta.54",
|
||||
"@ohif/ui": "3.13.0-beta.54",
|
||||
"@cornerstonejs/dicom-image-loader": "4.15.29",
|
||||
"@ohif/core": "3.12.2",
|
||||
"@ohif/ui": "3.12.2",
|
||||
"dcmjs": "0.49.4",
|
||||
"dicom-parser": "1.8.21",
|
||||
"hammerjs": "2.0.8",
|
||||
@@ -53,12 +53,12 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@cornerstonejs/adapters": "4.20.0",
|
||||
"@cornerstonejs/ai": "4.20.0",
|
||||
"@cornerstonejs/core": "4.20.0",
|
||||
"@cornerstonejs/labelmap-interpolation": "4.20.0",
|
||||
"@cornerstonejs/polymorphic-segmentation": "4.20.0",
|
||||
"@cornerstonejs/tools": "4.20.0",
|
||||
"@cornerstonejs/adapters": "4.15.29",
|
||||
"@cornerstonejs/ai": "4.15.29",
|
||||
"@cornerstonejs/core": "4.15.29",
|
||||
"@cornerstonejs/labelmap-interpolation": "4.15.29",
|
||||
"@cornerstonejs/polymorphic-segmentation": "4.15.29",
|
||||
"@cornerstonejs/tools": "4.15.29",
|
||||
"@icr/polyseg-wasm": "0.4.0",
|
||||
"@itk-wasm/morphological-contour-interpolation": "1.1.0",
|
||||
"@kitware/vtk.js": "34.15.1",
|
||||
|
||||
@@ -67,9 +67,10 @@ function CustomizableViewportOverlay({
|
||||
}) {
|
||||
const { cornerstoneViewportService, customizationService, toolGroupService, displaySetService } =
|
||||
servicesManager.services;
|
||||
const [voi, setVOI] = useState({ windowCenter: null, windowWidth: null });
|
||||
const [scale, setScale] = useState(1);
|
||||
const [annotationState, setAnnotationState] = useState(0);
|
||||
const { isViewportBackgroundLight: isLight, windowLevel: voi } = useViewportRendering(viewportId);
|
||||
const { isViewportBackgroundLight: isLight } = useViewportRendering(viewportId);
|
||||
const { imageIndex } = imageSliceData;
|
||||
|
||||
// Historical usage defined the overlays as separate items due to lack of
|
||||
@@ -109,6 +110,30 @@ function CustomizableViewportOverlay({
|
||||
};
|
||||
}, [viewportData, viewportId, instanceNumber, cornerstoneViewportService]);
|
||||
|
||||
/**
|
||||
* Updating the VOI when the viewport changes its voi
|
||||
*/
|
||||
useEffect(() => {
|
||||
const updateVOI = eventDetail => {
|
||||
const { range } = eventDetail.detail;
|
||||
|
||||
if (!range) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { lower, upper } = range;
|
||||
const { windowWidth, windowCenter } = utilities.windowLevel.toWindowLevel(lower, upper);
|
||||
|
||||
setVOI({ windowCenter, windowWidth });
|
||||
};
|
||||
|
||||
element.addEventListener(Enums.Events.VOI_MODIFIED, updateVOI);
|
||||
|
||||
return () => {
|
||||
element.removeEventListener(Enums.Events.VOI_MODIFIED, updateVOI);
|
||||
};
|
||||
}, [viewportId, viewportData, voi, element]);
|
||||
|
||||
const annotationModified = useCallback(evt => {
|
||||
if (evt.detail.annotation.metadata.toolName === UltrasoundPleuraBLineTool.toolName) {
|
||||
// Update the annotation state to trigger a re-render
|
||||
@@ -201,7 +226,6 @@ function CustomizableViewportOverlay({
|
||||
scale,
|
||||
instanceNumber,
|
||||
annotationState,
|
||||
isLight,
|
||||
]
|
||||
);
|
||||
|
||||
@@ -378,7 +402,6 @@ function OverlayItem(props) {
|
||||
*/
|
||||
function VOIOverlayItem({ voi, customization }: OverlayItemProps) {
|
||||
const { windowWidth, windowCenter } = voi;
|
||||
const { title } = customization;
|
||||
if (typeof windowCenter !== 'number' || typeof windowWidth !== 'number') {
|
||||
return null;
|
||||
}
|
||||
@@ -387,7 +410,6 @@ function VOIOverlayItem({ voi, customization }: OverlayItemProps) {
|
||||
<div
|
||||
className="overlay-item flex flex-row"
|
||||
style={{ color: customization?.color }}
|
||||
title={title}
|
||||
>
|
||||
<span className="mr-0.5 shrink-0 opacity-[0.70]">W:</span>
|
||||
<span className="mr-2.5 shrink-0">{windowWidth.toFixed(0)}</span>
|
||||
@@ -421,13 +443,11 @@ function InstanceNumberOverlayItem({
|
||||
customization,
|
||||
}: OverlayItemProps) {
|
||||
const { imageIndex, numberOfSlices } = imageSliceData;
|
||||
const { title } = customization;
|
||||
|
||||
return (
|
||||
<div
|
||||
className="overlay-item flex flex-row"
|
||||
style={{ color: (customization && customization.color) || undefined }}
|
||||
title={title}
|
||||
>
|
||||
<span>
|
||||
{instanceNumber !== undefined && instanceNumber !== null ? (
|
||||
|
||||
@@ -51,7 +51,7 @@ function ViewportImageSliceLoadingIndicator({ viewportData, element }) {
|
||||
<>
|
||||
<div className="absolute top-0 left-0 h-full w-full bg-black opacity-50">
|
||||
<div className="transparent flex h-full w-full items-center justify-center">
|
||||
<p className="text-highlight text-xl font-light">
|
||||
<p className="text-primary-light text-xl font-light">
|
||||
<h4>Error Loading Image</h4>
|
||||
<p>An error has occurred.</p>
|
||||
<p>{error}</p>
|
||||
@@ -68,7 +68,7 @@ function ViewportImageSliceLoadingIndicator({ viewportData, element }) {
|
||||
// interacting with the mouse, since scrolling should propagate to the viewport underneath
|
||||
<div className="pointer-events-none absolute top-0 left-0 h-full w-full bg-black opacity-50">
|
||||
<div className="transparent flex h-full w-full items-center justify-center">
|
||||
<p className="text-highlight text-xl font-light">Loading...</p>
|
||||
<p className="text-primary-light text-xl font-light">Loading...</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -398,31 +398,12 @@ function commandsModule({
|
||||
|
||||
const { segmentationId: targetId, segmentIndex: targetIndex } = targetSegmentation;
|
||||
|
||||
// Check if the segment has voxels before computing bidirectional measurement
|
||||
const uniqueSegmentIndices = cstUtils.segmentation.getUniqueSegmentIndices(targetId);
|
||||
const hasVoxels = uniqueSegmentIndices.includes(targetIndex);
|
||||
|
||||
if (!hasVoxels) {
|
||||
uiNotificationService.show({
|
||||
title: i18n.t('SegmentationPanel:Segment Bidirectional'),
|
||||
message: i18n.t(
|
||||
'SegmentationPanel:Draw a segment before using bidirectional measurement'
|
||||
),
|
||||
type: 'warning',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Get bidirectional measurement data
|
||||
const bidirectionalData = await cstUtils.segmentation.getSegmentLargestBidirectional({
|
||||
segmentationId: targetId,
|
||||
segmentIndices: [targetIndex],
|
||||
});
|
||||
|
||||
if (!bidirectionalData.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const activeViewportId = viewportGridService.getActiveViewportId();
|
||||
|
||||
// Process each bidirectional measurement
|
||||
@@ -1754,14 +1735,12 @@ function commandsModule({
|
||||
* Removes a segmentation from the viewport
|
||||
* @param props.segmentationId - The ID of the segmentation to remove
|
||||
*/
|
||||
removeSegmentationFromViewportCommand: ({ segmentationId: displaySetInstanceUID }) => {
|
||||
const { viewportGridService } = servicesManager.services;
|
||||
const viewportId = viewportGridService.getActiveViewportId();
|
||||
|
||||
commandsManager.runCommand('removeDisplaySetLayer', {
|
||||
viewportId,
|
||||
displaySetInstanceUID,
|
||||
});
|
||||
removeSegmentationFromViewportCommand: ({ segmentationId }) => {
|
||||
const { segmentationService, viewportGridService } = servicesManager.services;
|
||||
segmentationService.removeSegmentationRepresentations(
|
||||
viewportGridService.getActiveViewportId(),
|
||||
{ segmentationId }
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -91,14 +91,14 @@ function DefaultAccordion(props) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (asChild) {
|
||||
if (Boolean(asChild)) {
|
||||
return React.cloneElement(props.children, props);
|
||||
}
|
||||
|
||||
return (
|
||||
<Accordion
|
||||
type={grouping.type || 'multiple'}
|
||||
className="text-foreground"
|
||||
className="text-white"
|
||||
defaultValue={defaultValue}
|
||||
>
|
||||
{[...groups.entries()].map(([key, group]) => {
|
||||
|
||||
@@ -16,7 +16,7 @@ type DicomUploadProps = {
|
||||
|
||||
function DicomUpload({ dataSource, onComplete, onStarted }: DicomUploadProps): ReactElement {
|
||||
const baseClassNames =
|
||||
'min-h-[375px] flex flex-col bg-background select-none rounded-lg overflow-hidden';
|
||||
'min-h-[375px] flex flex-col bg-black select-none rounded-lg overflow-hidden';
|
||||
const [dicomFileUploaderArr, setDicomFileUploaderArr] = useState([]);
|
||||
|
||||
const onDrop = useCallback(async acceptedFiles => {
|
||||
|
||||
@@ -276,7 +276,7 @@ function DicomUploadProgress({
|
||||
|
||||
const getNumCompletedAndTimeRemainingComponent = (): ReactElement => {
|
||||
return (
|
||||
<div className="bg-muted text-foreground flex h-14 items-center px-1 pb-4 text-lg">
|
||||
<div className="bg-muted flex h-14 items-center px-1 pb-4 text-lg text-white">
|
||||
{numFilesCompleted === dicomFileUploaderArr.length ? (
|
||||
<>
|
||||
<span className={NO_WRAP_ELLIPSIS_CLASS_NAMES}>{`${dicomFileUploaderArr.length} ${
|
||||
@@ -372,7 +372,7 @@ function DicomUploadProgress({
|
||||
return (
|
||||
<div className="flex grow flex-col">
|
||||
{getNumCompletedAndTimeRemainingComponent()}
|
||||
<div className="flex grow flex-col overflow-hidden bg-background text-lg">
|
||||
<div className="flex grow flex-col overflow-hidden bg-black text-lg">
|
||||
{getPercentCompleteComponent()}
|
||||
<div className="ohif-scrollbar h-1 grow overflow-y-scroll px-2">
|
||||
{dicomFileUploaderArr
|
||||
|
||||
@@ -75,7 +75,7 @@ const DicomUploadProgressItem = memo(
|
||||
<div className="self-top flex w-0 shrink grow flex-col gap-1">
|
||||
<div className="flex gap-4">
|
||||
<div className="flex w-6 shrink-0 items-center justify-center">{getStatusIcon()}</div>
|
||||
<div className="text-foreground overflow-hidden text-ellipsis whitespace-nowrap">
|
||||
<div className="overflow-hidden text-ellipsis whitespace-nowrap text-white">
|
||||
{dicomFileUploader.getFileName()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,9 @@ import {
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuPortal,
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuSeparator,
|
||||
Icons,
|
||||
} from '@ohif/ui-next';
|
||||
|
||||
@@ -17,6 +19,8 @@ interface ExportSegmentationSubMenuItemProps {
|
||||
allowExport: boolean;
|
||||
actions: {
|
||||
storeSegmentation: (segmentationId: string, modality?: string) => Promise<unknown>;
|
||||
onSegmentationDownloadRTSS: (segmentationId: string) => void;
|
||||
onSegmentationDownload: (segmentationId: string) => void;
|
||||
downloadCSVSegmentationReport: (segmentationId: string) => void;
|
||||
};
|
||||
}
|
||||
@@ -33,10 +37,14 @@ export const ExportSegmentationSubMenuItem: React.FC<ExportSegmentationSubMenuIt
|
||||
<DropdownMenuSub>
|
||||
<DropdownMenuSubTrigger className="pl-1">
|
||||
<Icons.Export className="text-foreground" />
|
||||
<span className="pl-2">{t('Export')}</span>
|
||||
<span className="pl-2">{t('Download & Export')}</span>
|
||||
</DropdownMenuSubTrigger>
|
||||
<DropdownMenuPortal>
|
||||
<DropdownMenuSubContent>
|
||||
<DropdownMenuLabel className="flex items-center pl-0">
|
||||
<Icons.Download className="h-5 w-5" />
|
||||
<span className="pl-1">{t('Download')}</span>
|
||||
</DropdownMenuLabel>
|
||||
{segmentationRepresentationType === SegmentationRepresentations.Labelmap && (
|
||||
<DropdownMenuItem
|
||||
onClick={e => {
|
||||
@@ -48,6 +56,31 @@ export const ExportSegmentationSubMenuItem: React.FC<ExportSegmentationSubMenuIt
|
||||
{t('CSV Report')}
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
{segmentationRepresentationType === SegmentationRepresentations.Labelmap && (
|
||||
<DropdownMenuItem
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
actions.onSegmentationDownload(segmentationId);
|
||||
}}
|
||||
disabled={!allowExport}
|
||||
>
|
||||
{t('DICOM SEG')}
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
<DropdownMenuItem
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
actions.onSegmentationDownloadRTSS(segmentationId);
|
||||
}}
|
||||
disabled={!allowExport}
|
||||
>
|
||||
{t('DICOM RTSS')}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuLabel className="flex items-center pl-0">
|
||||
<Icons.Export className="h-5 w-5" />
|
||||
<span className="pl-1 pt-1">{t('Export')}</span>
|
||||
</DropdownMenuLabel>
|
||||
{segmentationRepresentationType === SegmentationRepresentations.Labelmap && (
|
||||
<DropdownMenuItem
|
||||
onClick={e => {
|
||||
|
||||
@@ -122,9 +122,9 @@ function ModalityLoadBadge({ viewportId }: { viewportId: string }) {
|
||||
return (
|
||||
<div
|
||||
data-cy={`ModalityLoadBadge-${viewportId}`}
|
||||
className="text-foreground flex h-6 cursor-default text-sm leading-6"
|
||||
className="flex h-6 cursor-default text-sm leading-6 text-white"
|
||||
>
|
||||
<div className="bg-popover flex min-w-[45px] items-center rounded-l-xl rounded-r p-1">
|
||||
<div className="bg-customgray-100 flex min-w-[45px] items-center rounded-l-xl rounded-r p-1">
|
||||
<StatusIcon />
|
||||
<span className="ml-1">{statusInfo.type}</span>
|
||||
</div>
|
||||
|
||||
@@ -28,7 +28,7 @@ export default function PanelAccordionTrigger(props) {
|
||||
<div className={`inline-flex text-base ${isActive ? 'bg-popover' : 'bg-muted'} flex-grow`}>
|
||||
<button onClick={onClickDefault.bind(props)}>
|
||||
<span
|
||||
className={`inline-flex rounded-l border-r border-background ${isActive ? 'bg-highlight' : 'bg-muted'}`}
|
||||
className={`inline-flex rounded-l border-r border-black ${isActive ? 'bg-highlight' : 'bg-muted'}`}
|
||||
>
|
||||
{count !== undefined ? <span className="px-2">{count}</span> : null}
|
||||
{colorHex && <ColorCircle colorHex={colorHex} />}
|
||||
|
||||
@@ -34,7 +34,7 @@ export default function SegmentationToolConfig() {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="bg-muted flex flex-col gap-2 border-b border-b-[2px] border-background px-2 py-3">
|
||||
<div className="bg-muted flex flex-col gap-2 border-b border-b-[2px] border-black px-2 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<Switch
|
||||
checked={previewEdits}
|
||||
|
||||
+2
-9
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
Button,
|
||||
Icons,
|
||||
@@ -43,10 +43,6 @@ function ViewportDataOverlayMenu({ viewportId }: withAppTypes<{ viewportId: stri
|
||||
|
||||
const [thresholdOpacityEnabled, setThresholdOpacityEnabled] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setOptimisticOverlayDisplaySets(overlayDisplaySets);
|
||||
}, [backgroundDisplaySet?.displaySetInstanceUID, overlayDisplaySets]);
|
||||
|
||||
/**
|
||||
* Change the background display set
|
||||
*/
|
||||
@@ -486,10 +482,7 @@ function ViewportDataOverlayMenu({ viewportId }: withAppTypes<{ viewportId: stri
|
||||
}
|
||||
}}
|
||||
>
|
||||
<SelectTrigger
|
||||
className="flex-1"
|
||||
data-cy={`overlay-background-ds-select-${viewportId}`}
|
||||
>
|
||||
<SelectTrigger className="flex-1">
|
||||
<SelectValue>
|
||||
{(
|
||||
backgroundDisplaySet?.SeriesDescription ||
|
||||
|
||||
+1
-1
@@ -203,7 +203,7 @@ function ViewportOrientationMenu({
|
||||
<div className="flex-1 text-left">Acquisition</div>
|
||||
</Button>
|
||||
{/* Divider */}
|
||||
<div className="border-input mx-1 my-2 border-t" />
|
||||
<div className="mx-1 my-2 border-t border-white/20" />
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="flex h-7 w-full flex-shrink-0 items-center justify-start self-stretch px-1 py-0"
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ export function VolumeRenderingPresetsContent({ presets, viewportId, hide }: Pro
|
||||
className={
|
||||
selectedPreset?.name === preset.name
|
||||
? 'border-highlight h-[75px] w-[95px] max-w-none rounded border-2'
|
||||
: 'hover:border-highlight h-[75px] w-[95px] max-w-none rounded border-2 border-background'
|
||||
: 'hover:border-highlight h-[75px] w-[95px] max-w-none rounded border-2 border-black'
|
||||
}
|
||||
/>
|
||||
<label className="text-muted-foreground mt-1 text-left text-xs">
|
||||
|
||||
@@ -64,6 +64,12 @@ export const CustomDropdownMenuContent = () => {
|
||||
context: 'CORNERSTONE',
|
||||
});
|
||||
},
|
||||
onSegmentationDownloadRTSS: segmentationId => {
|
||||
commandsManager.run('downloadRTSS', { segmentationId });
|
||||
},
|
||||
onSegmentationDownload: segmentationId => {
|
||||
commandsManager.run('downloadSegmentation', { segmentationId });
|
||||
},
|
||||
downloadCSVSegmentationReport: segmentationId => {
|
||||
commandsManager.run('downloadCSVSegmentationReport', { segmentationId });
|
||||
},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { ImageModal, FooterAction, toast } from '@ohif/ui-next';
|
||||
import { ImageModal, FooterAction } from '@ohif/ui-next';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
const MAX_TEXTURE_SIZE = 10000;
|
||||
const DEFAULT_FILENAME = 'image';
|
||||
@@ -16,7 +16,6 @@ interface ViewportDownloadFormNewProps {
|
||||
onEnableViewport: (element: HTMLElement) => void;
|
||||
onDisableViewport: () => void;
|
||||
onDownload: (filename: string, fileType: string) => void;
|
||||
onCopyToClipboard: () => void;
|
||||
warningState: { enabled: boolean; value: string };
|
||||
}
|
||||
|
||||
@@ -33,7 +32,6 @@ function ViewportDownloadFormNew({
|
||||
onEnableViewport,
|
||||
onDisableViewport,
|
||||
onDownload,
|
||||
onCopyToClipboard,
|
||||
}: ViewportDownloadFormNewProps) {
|
||||
const [viewportElement, setViewportElement] = useState<HTMLElement | null>(null);
|
||||
const [showWarningMessage, setShowWarningMessage] = useState(true);
|
||||
@@ -68,7 +66,7 @@ function ViewportDownloadFormNew({
|
||||
>
|
||||
{warningState.enabled && showWarningMessage && (
|
||||
<div
|
||||
className="text-foreground absolute left-1/2 bottom-[5px] z-[1000] -translate-x-1/2 whitespace-nowrap rounded bg-background p-3 text-xs font-bold"
|
||||
className="text-foreground absolute left-1/2 bottom-[5px] z-[1000] -translate-x-1/2 whitespace-nowrap rounded bg-black p-3 text-xs font-bold"
|
||||
style={{
|
||||
fontSize: '12px',
|
||||
}}
|
||||
@@ -140,27 +138,13 @@ function ViewportDownloadFormNew({
|
||||
<FooterAction.Secondary onClick={onClose}>
|
||||
{t('Common:Cancel')}
|
||||
</FooterAction.Secondary>
|
||||
<FooterAction.Secondary
|
||||
onClick={async () => {
|
||||
try {
|
||||
await onCopyToClipboard();
|
||||
toast.success(t('Image copied to clipboard'));
|
||||
onClose();
|
||||
} catch (error) {
|
||||
toast.error(t('Failed to copy image to clipboard'));
|
||||
console.error('Failed to copy to clipboard:', error);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{t('Copy to Clipboard')}
|
||||
</FooterAction.Secondary>
|
||||
<FooterAction.Primary
|
||||
onClick={() => {
|
||||
onDownload(filename || DEFAULT_FILENAME, fileType);
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
{t('Save Image')}
|
||||
{t('Common:Save')}
|
||||
</FooterAction.Primary>
|
||||
</FooterAction.Right>
|
||||
</FooterAction>
|
||||
|
||||
@@ -25,7 +25,6 @@ export default {
|
||||
{
|
||||
id: 'WindowLevel',
|
||||
inheritsFrom: 'ohif.overlayItem.windowLevel',
|
||||
title: 'Window Level',
|
||||
},
|
||||
{
|
||||
id: 'ZoomLevel',
|
||||
@@ -40,7 +39,6 @@ export default {
|
||||
{
|
||||
id: 'InstanceNumber',
|
||||
inheritsFrom: 'ohif.overlayItem.instanceNumber',
|
||||
title: 'Instance Number',
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -3,7 +3,6 @@ import i18n from '@ohif/i18n';
|
||||
import { utilities as csUtils, Enums as csEnums } from '@cornerstonejs/core';
|
||||
import dcmjs from 'dcmjs';
|
||||
import { dicomWebUtils } from '@ohif/extension-default';
|
||||
import { buildEcgModule } from './utils/ecgMetadata';
|
||||
|
||||
const { MetadataModules } = csEnums;
|
||||
const { utils } = OHIF;
|
||||
@@ -156,84 +155,6 @@ export function getDicomMicroscopySopClassHandler({ servicesManager, extensionMa
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* DICOM Waveform SOP Class UIDs for ECG / cardiac electrophysiology.
|
||||
* Reference: https://dicom.nema.org/medical/dicom/current/output/chtml/part04/sect_B.5.html
|
||||
*/
|
||||
const ECG_SOP_CLASS_UIDS = {
|
||||
TWELVE_LEAD_ECG_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.1.1',
|
||||
GENERAL_ECG_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.1.2',
|
||||
AMBULATORY_ECG_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.1.3',
|
||||
HEMODYNAMIC_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.2.1',
|
||||
CARDIAC_ELECTROPHYSIOLOGY_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.3.1',
|
||||
};
|
||||
|
||||
const ecgSopClassUids = Object.values(ECG_SOP_CLASS_UIDS);
|
||||
|
||||
const DicomEcgSOPClassHandlerId =
|
||||
'@ohif/extension-cornerstone.sopClassHandlerModule.DicomEcgSopClassHandler';
|
||||
|
||||
function _getEcgDisplaySetsFromSeries(instances, servicesManager) {
|
||||
const { userAuthenticationService } = servicesManager.services;
|
||||
|
||||
return instances.map(instance => {
|
||||
const { Modality, SOPInstanceUID } = instance;
|
||||
const { SeriesDescription, SeriesNumber, SeriesDate } = instance;
|
||||
const { SeriesInstanceUID, StudyInstanceUID, SOPClassUID } = instance;
|
||||
const imageId = instance.imageId;
|
||||
|
||||
// Register ECG metadata in the OHIF metadata provider so that
|
||||
// Cornerstone's ECGViewport can retrieve it via metaData.get('ecgModule', imageId).
|
||||
if (imageId) {
|
||||
const ecgModule = buildEcgModule(instance, userAuthenticationService);
|
||||
if (ecgModule) {
|
||||
csUtils.genericMetadataProvider.addRaw(imageId, {
|
||||
type: MetadataModules.ECG,
|
||||
metadata: ecgModule,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
Modality,
|
||||
displaySetInstanceUID: utils.guid(),
|
||||
SeriesDescription,
|
||||
SeriesNumber,
|
||||
SeriesDate,
|
||||
SOPInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
StudyInstanceUID,
|
||||
SOPClassHandlerId: DicomEcgSOPClassHandlerId,
|
||||
SOPClassUID,
|
||||
referencedImages: null,
|
||||
measurements: null,
|
||||
viewportType: csEnums.ViewportType.ECG,
|
||||
instances: [instance],
|
||||
instance,
|
||||
thumbnailSrc: null,
|
||||
isDerivedDisplaySet: false,
|
||||
isLoaded: false,
|
||||
sopClassUids: ecgSopClassUids,
|
||||
numImageFrames: 0,
|
||||
numInstances: 1,
|
||||
imageIds: imageId ? [imageId] : [],
|
||||
supportsWindowLevel: false,
|
||||
label: SeriesDescription || 'ECG',
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export function getDicomEcgSopClassHandler({ servicesManager }) {
|
||||
const getDisplaySetsFromSeries = instances =>
|
||||
_getEcgDisplaySetsFromSeries(instances, servicesManager);
|
||||
|
||||
return {
|
||||
name: 'DicomEcgSopClassHandler',
|
||||
sopClassUids: ecgSopClassUids,
|
||||
getDisplaySetsFromSeries,
|
||||
};
|
||||
}
|
||||
|
||||
export function getSopClassHandlerModule(params) {
|
||||
return [getDicomMicroscopySopClassHandler(params), getDicomEcgSopClassHandler(params)];
|
||||
return [getDicomMicroscopySopClassHandler(params)];
|
||||
}
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
BaseVolumeViewport,
|
||||
cache,
|
||||
} from '@cornerstonejs/core';
|
||||
import { getDataIdForViewport } from '../utils/getDataIdForViewport';
|
||||
import { WindowLevelPreset } from '../types/WindowLevel';
|
||||
import { ColorbarPositionType, ColorbarOptions, ColorbarProperties } from '../types/Colorbar';
|
||||
import { VolumeRenderingConfig } from '../types/VolumeRenderingConfig';
|
||||
@@ -105,6 +104,11 @@ const opacityToLinear = (opacityValue: number): number => {
|
||||
return Math.pow(opacityValue, 1.0 / GAMMA);
|
||||
};
|
||||
|
||||
const is3DViewport = ({ viewportId, cornerstoneViewportService }) => {
|
||||
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
||||
return viewport instanceof VolumeViewport3D;
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to access window level functionality for a specific viewport
|
||||
*
|
||||
@@ -120,17 +124,15 @@ export function useViewportRendering(
|
||||
const { cornerstoneViewportService, colorbarService, customizationService } =
|
||||
servicesManager.services;
|
||||
|
||||
const [is3DVolume, setIs3DVolume] = useState(
|
||||
is3DViewport({ viewportId, cornerstoneViewportService })
|
||||
);
|
||||
const [hasColorbar, setHasColorbar] = useState(colorbarService.hasColorbar(viewportId));
|
||||
const [colorbarPosition, setColorbarPosition] = useState<ColorbarPositionType>(
|
||||
options?.location ? getPosition(options.location) : 'bottom'
|
||||
);
|
||||
const [voiRange, setVoiRange] = useState<{ lower: number; upper: number } | undefined>();
|
||||
const voiRangeRef = React.useRef<{ lower: number; upper: number } | undefined>();
|
||||
// Viewport from service; kept in state so we can subscribe to VIEWPORT_DATA_CHANGED when null and re-run effects when it becomes available
|
||||
const [viewport, setViewport] = useState<Types.IViewport | null>(() =>
|
||||
viewportId ? (cornerstoneViewportService.getCornerstoneViewport(viewportId) ?? null) : null
|
||||
);
|
||||
const [is3DVolume, setIs3DVolume] = useState(viewport instanceof VolumeViewport3D);
|
||||
const [opacity, setOpacityState] = useState<number | undefined>();
|
||||
const [opacityLinear, setOpacityLinearState] = useState<number | undefined>();
|
||||
const [threshold, setThresholdState] = useState<number | undefined>();
|
||||
@@ -176,34 +178,6 @@ export function useViewportRendering(
|
||||
);
|
||||
}, [viewportDisplaySets, presets]);
|
||||
|
||||
// Keep viewport in state; when not available, subscribe to VIEWPORT_DATA_CHANGED so we set it when the viewport is ready
|
||||
useEffect(() => {
|
||||
if (!viewportId) {
|
||||
setViewport(null);
|
||||
return;
|
||||
}
|
||||
const vp = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
||||
setViewport(vp ?? null);
|
||||
if (vp) {
|
||||
return;
|
||||
}
|
||||
const { unsubscribe } = cornerstoneViewportService.subscribe(
|
||||
cornerstoneViewportService.EVENTS.VIEWPORT_DATA_CHANGED,
|
||||
({ viewportId: eventViewportId }) => {
|
||||
if (eventViewportId !== viewportId) {
|
||||
return;
|
||||
}
|
||||
const next = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
||||
if (next) {
|
||||
setViewport(next);
|
||||
}
|
||||
}
|
||||
);
|
||||
return () => {
|
||||
unsubscribe();
|
||||
};
|
||||
}, [viewportId, cornerstoneViewportService]);
|
||||
|
||||
// Calculate pixel value range for the active display set
|
||||
useEffect(() => {
|
||||
if (!activeDisplaySetInstanceUID) {
|
||||
@@ -215,15 +189,17 @@ export function useViewportRendering(
|
||||
return;
|
||||
}
|
||||
|
||||
if (!viewport) {
|
||||
const csViewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
||||
|
||||
if (!csViewport) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(viewport instanceof BaseVolumeViewport)) {
|
||||
if (!(csViewport instanceof BaseVolumeViewport)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const volumeIds = viewport.getAllVolumeIds();
|
||||
const volumeIds = csViewport.getAllVolumeIds();
|
||||
const volumeId = volumeIds.find(id => id.includes(activeDisplaySetInstanceUID));
|
||||
|
||||
if (!volumeId) {
|
||||
@@ -231,7 +207,7 @@ export function useViewportRendering(
|
||||
}
|
||||
|
||||
// only handle volume viewports for now
|
||||
const imageData = viewport.getImageData(volumeId);
|
||||
const imageData = csViewport.getImageData(volumeId);
|
||||
|
||||
if (!imageData) {
|
||||
return;
|
||||
@@ -244,7 +220,7 @@ export function useViewportRendering(
|
||||
const range = voxelManager.getRange();
|
||||
|
||||
setPixelValueRange({ min: range[0], max: range[1] });
|
||||
}, [activeDisplaySetInstanceUID, displaySetService, viewport]);
|
||||
}, [activeDisplaySetInstanceUID, displaySetService, cornerstoneViewportService, viewportId]);
|
||||
|
||||
// Get the presets specifically for the active display set
|
||||
const activeDisplaySetPresets = useMemo(() => {
|
||||
@@ -264,47 +240,55 @@ export function useViewportRendering(
|
||||
}, [allWindowLevelPresets, activeDisplaySetInstanceUID]);
|
||||
|
||||
useEffect(() => {
|
||||
setIs3DVolume(viewport instanceof VolumeViewport3D);
|
||||
setIs3DVolume(is3DViewport({ viewportId, cornerstoneViewportService }));
|
||||
|
||||
if (!viewport || !activeDisplaySetInstanceUID) {
|
||||
return;
|
||||
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
||||
|
||||
// Initialize the VOI range from the viewport
|
||||
if (viewport && activeDisplaySetInstanceUID) {
|
||||
try {
|
||||
let properties;
|
||||
|
||||
if (viewport instanceof StackViewport) {
|
||||
properties = viewport.getProperties();
|
||||
if (properties.voiRange) {
|
||||
setVoiRange(properties.voiRange);
|
||||
voiRangeRef.current = properties.voiRange;
|
||||
}
|
||||
} else if (viewport instanceof BaseVolumeViewport) {
|
||||
// For volume viewports, find the actor for the active display set
|
||||
const volumeIds = viewport.getAllVolumeIds();
|
||||
const volumeId = volumeIds.find(id => id.includes(activeDisplaySetInstanceUID));
|
||||
|
||||
if (volumeId) {
|
||||
properties = viewport.getProperties(volumeId);
|
||||
if (properties?.voiRange) {
|
||||
setVoiRange(properties.voiRange);
|
||||
voiRangeRef.current = properties.voiRange;
|
||||
}
|
||||
|
||||
// Get opacity from colormap if available
|
||||
if (properties?.colormap?.opacity !== undefined) {
|
||||
const isArray = Array.isArray(properties.colormap.opacity);
|
||||
const opacity = isArray
|
||||
? properties.colormap.opacity.reduce((max, current) => Math.max(max, current), 0)
|
||||
: properties.colormap.opacity;
|
||||
|
||||
setOpacityState(opacity);
|
||||
setOpacityLinearState(opacityToLinear(opacity));
|
||||
}
|
||||
|
||||
// Get threshold from colormap if available
|
||||
if (properties?.colormap && properties.colormap.threshold !== undefined) {
|
||||
setThresholdState(properties.colormap.threshold);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error initializing VOI range:', error);
|
||||
}
|
||||
}
|
||||
try {
|
||||
const dataId = getDataIdForViewport(viewport as unknown, activeDisplaySetInstanceUID);
|
||||
|
||||
const properties =
|
||||
dataId != null
|
||||
? (viewport as Types.IBaseVolumeViewport).getProperties(dataId)
|
||||
: viewport.getProperties();
|
||||
|
||||
if (!properties) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (properties.voiRange) {
|
||||
setVoiRange(properties.voiRange);
|
||||
voiRangeRef.current = properties.voiRange;
|
||||
}
|
||||
|
||||
if (properties.colormap?.opacity !== undefined) {
|
||||
const opacityVal = properties.colormap.opacity;
|
||||
const opacity = Array.isArray(opacityVal)
|
||||
? (opacityVal as unknown as number[]).reduce(
|
||||
(max, current) => Math.max(max, current),
|
||||
0
|
||||
)
|
||||
: opacityVal;
|
||||
setOpacityState(opacity);
|
||||
setOpacityLinearState(opacityToLinear(opacity));
|
||||
}
|
||||
|
||||
if (properties.colormap?.threshold !== undefined) {
|
||||
setThresholdState(properties.colormap.threshold);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error initializing VOI range:', error);
|
||||
}
|
||||
}, [activeDisplaySetInstanceUID, viewport]);
|
||||
}, [cornerstoneViewportService, viewportId, activeDisplaySetInstanceUID]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!viewportId) {
|
||||
@@ -329,11 +313,19 @@ export function useViewportRendering(
|
||||
}, [colorbarService, viewportId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!activeDisplaySetInstanceUID || !viewport?.element) {
|
||||
if (!viewportId || !activeDisplaySetInstanceUID) {
|
||||
return;
|
||||
}
|
||||
|
||||
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
||||
if (!viewport) {
|
||||
return;
|
||||
}
|
||||
|
||||
const element = viewport.element;
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
|
||||
const updateVOI = eventDetail => {
|
||||
const { range } = eventDetail.detail;
|
||||
@@ -377,7 +369,7 @@ export function useViewportRendering(
|
||||
element.removeEventListener(Enums.Events.VOI_MODIFIED, updateVOI);
|
||||
element.removeEventListener(Enums.Events.COLORMAP_MODIFIED, updateColormap);
|
||||
};
|
||||
}, [activeDisplaySetInstanceUID, viewport, opacityToLinear]);
|
||||
}, [viewportId, activeDisplaySetInstanceUID, cornerstoneViewportService, opacityToLinear]);
|
||||
|
||||
const validateActiveDisplaySet = useCallback(() => {
|
||||
if (!activeDisplaySetInstanceUID) {
|
||||
@@ -568,11 +560,16 @@ export function useViewportRendering(
|
||||
context: 'CORNERSTONE',
|
||||
});
|
||||
},
|
||||
[commandsManager, validateActiveDisplaySet, viewport, viewportId]
|
||||
[commandsManager, viewportId, validateActiveDisplaySet]
|
||||
);
|
||||
|
||||
const setOpacity = useCallback(
|
||||
(opacityValue: number) => {
|
||||
if (!viewportId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
||||
if (!viewport || !(viewport instanceof BaseVolumeViewport)) {
|
||||
return;
|
||||
}
|
||||
@@ -610,7 +607,7 @@ export function useViewportRendering(
|
||||
|
||||
viewport.render();
|
||||
},
|
||||
[validateActiveDisplaySet, opacityToLinear, viewport]
|
||||
[cornerstoneViewportService, viewportId, validateActiveDisplaySet, opacityToLinear]
|
||||
);
|
||||
|
||||
const setOpacityLinear = useCallback(
|
||||
@@ -624,6 +621,11 @@ export function useViewportRendering(
|
||||
|
||||
const setThreshold = useCallback(
|
||||
(thresholdValue: number) => {
|
||||
if (!viewportId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
||||
if (!viewport || !(viewport instanceof BaseVolumeViewport)) {
|
||||
return;
|
||||
}
|
||||
@@ -651,16 +653,18 @@ export function useViewportRendering(
|
||||
|
||||
viewport.render();
|
||||
},
|
||||
[validateActiveDisplaySet, viewport]
|
||||
[cornerstoneViewportService, viewportId, validateActiveDisplaySet]
|
||||
);
|
||||
|
||||
// Get the current colormap for the active display set
|
||||
const colormap = useMemo(() => {
|
||||
if (!activeDisplaySetInstanceUID || !viewportDisplaySets?.length) {
|
||||
if (!viewportId || !activeDisplaySetInstanceUID || !viewportDisplaySets?.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
||||
|
||||
if (!viewport) {
|
||||
return null;
|
||||
}
|
||||
@@ -707,7 +711,13 @@ export function useViewportRendering(
|
||||
colorbarProperties?.colormaps?.[0]
|
||||
);
|
||||
}
|
||||
}, [activeDisplaySetInstanceUID, viewportDisplaySets, colorbarProperties?.colormaps, viewport]);
|
||||
}, [
|
||||
cornerstoneViewportService,
|
||||
viewportId,
|
||||
activeDisplaySetInstanceUID,
|
||||
viewportDisplaySets,
|
||||
colorbarProperties?.colormaps,
|
||||
]);
|
||||
|
||||
// 3D volume rendering functions
|
||||
const setVolumeRenderingPreset = useCallback(
|
||||
@@ -791,9 +801,7 @@ export function useViewportRendering(
|
||||
setWindowLevel,
|
||||
setVOIRange,
|
||||
voiRange,
|
||||
windowLevel: voiRange
|
||||
? utilities.windowLevel.toWindowLevel(voiRange?.lower, voiRange?.upper)
|
||||
: { windowCenter: null, windowWidth: null },
|
||||
windowLevel: utilities.windowLevel.toWindowLevel(voiRange?.lower, voiRange?.upper),
|
||||
|
||||
// Colorbar functions
|
||||
hasColorbar,
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useSystem } from '@ohif/core';
|
||||
const excludedModalities = ['SM', 'OT', 'DOC', 'ECG'];
|
||||
|
||||
function mapSegmentationToDisplay(segmentation, customizationService) {
|
||||
const { label, segments, fallbackLabel } = segmentation;
|
||||
const { label, segments } = segmentation;
|
||||
|
||||
// Get the readable text mapping once
|
||||
const readableTextMap = customizationService.getCustomization('panelSegmentation.readableText');
|
||||
@@ -76,7 +76,6 @@ function mapSegmentationToDisplay(segmentation, customizationService) {
|
||||
return {
|
||||
...segmentation,
|
||||
label,
|
||||
fallbackLabel,
|
||||
segments: updatedSegments,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,11 +2,6 @@ import { cache, Types } from '@cornerstonejs/core';
|
||||
import { utilities } from '@cornerstonejs/tools';
|
||||
|
||||
function _getVolumeFromViewport(viewport: Types.IBaseVolumeViewport) {
|
||||
// Handle non-volume viewports that don't have getAllVolumeIds
|
||||
if (!viewport?.getAllVolumeIds) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const volumeIds = viewport.getAllVolumeIds();
|
||||
const volumes = volumeIds.map(id => cache.getVolume(id));
|
||||
const dynamicVolume = volumes.find(volume => volume.isDynamicVolume());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { eventTarget, Types } from '@cornerstonejs/core';
|
||||
import { Enums, annotation, cancelActiveManipulations } from '@cornerstonejs/tools';
|
||||
import { Enums, annotation } from '@cornerstonejs/tools';
|
||||
import { DicomMetadataStore } from '@ohif/core';
|
||||
|
||||
import * as CSExtensionEnums from './enums';
|
||||
@@ -504,12 +504,6 @@ const connectMeasurementServiceToTools = ({
|
||||
if (source?.name && source.name !== CORNERSTONE_3D_TOOLS_SOURCE_NAME) {
|
||||
return;
|
||||
}
|
||||
// Cancel any active tool manipulation (e.g., Spline/Livewire) to avoid leaving the tool
|
||||
// in a drawing state after deleting a not completed measurement, which can block viewport interactivity.
|
||||
const element = getActiveViewportEnabledElement(viewportGridService)?.viewport?.element;
|
||||
if (element) {
|
||||
cancelActiveManipulations(element);
|
||||
}
|
||||
const removedAnnotation = annotation.state.getAnnotation(removedMeasurementId);
|
||||
removeAnnotation(removedMeasurementId);
|
||||
// Ensure `removedAnnotation` is available before triggering the memo,
|
||||
|
||||
@@ -65,7 +65,7 @@ export default function PanelMeasurement(props): React.ReactNode {
|
||||
return EmptyComponent ? (
|
||||
<EmptyComponent items={displayMeasurements} />
|
||||
) : (
|
||||
<span className="text-foreground">No Measurements</span>
|
||||
<span className="text-white">No Measurements</span>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { PubSubService, Types as OhifTypes } from '@ohif/core';
|
||||
import { RENDERING_ENGINE_ID } from '../ViewportService/constants';
|
||||
import { getRenderingEngine } from '@cornerstonejs/core';
|
||||
import { getDataIdForViewport } from '../../utils/getDataIdForViewport';
|
||||
import { ColorbarOptions, ChangeTypes } from '../../types/Colorbar';
|
||||
|
||||
export default class ColorbarService extends PubSubService {
|
||||
@@ -39,6 +38,25 @@ export default class ColorbarService extends PubSubService {
|
||||
this.servicesManager = servicesManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the appropriate data ID for a viewport and display set
|
||||
* @param viewport - The viewport instance
|
||||
* @param displaySetInstanceUID - The display set instance UID to identify data
|
||||
* @returns The appropriate data ID for the viewport type (volumeId for volume viewports, undefined for stack)
|
||||
*/
|
||||
private getDataIdForViewport(viewport, displaySetInstanceUID: string): string | undefined {
|
||||
// For volume viewports, find the matching volumeId
|
||||
if (viewport.getAllVolumeIds) {
|
||||
const volumeIds = viewport.getAllVolumeIds() || [];
|
||||
return volumeIds.length > 0
|
||||
? volumeIds.find(id => id.includes(displaySetInstanceUID)) || undefined
|
||||
: undefined;
|
||||
}
|
||||
|
||||
// For other viewports, no specific dataId is needed for now
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a colorbar to a specific viewport identified by `viewportId`, using the provided `displaySetInstanceUIDs` and `options`.
|
||||
* This method prepares the colorbar state that will be used by the ViewportColorbarsContainer component.
|
||||
@@ -74,7 +92,7 @@ export default class ColorbarService extends PubSubService {
|
||||
return;
|
||||
}
|
||||
|
||||
const dataId = getDataIdForViewport(viewport, displaySetInstanceUID);
|
||||
const dataId = this.getDataIdForViewport(viewport, displaySetInstanceUID);
|
||||
const properties = dataId ? viewport.getProperties(dataId) : viewport.getProperties();
|
||||
const colormap = properties?.colormap;
|
||||
|
||||
@@ -228,7 +246,7 @@ export default class ColorbarService extends PubSubService {
|
||||
}
|
||||
|
||||
// Get the appropriate dataId for this viewport/displaySet combination
|
||||
const dataId = getDataIdForViewport(viewport, displaySetInstanceUID);
|
||||
const dataId = this.getDataIdForViewport(viewport, displaySetInstanceUID);
|
||||
|
||||
// Set properties with or without dataId based on what the viewport supports
|
||||
viewport.setProperties({ colormap }, dataId);
|
||||
|
||||
+6
-15
@@ -1120,7 +1120,6 @@ describe('SegmentationService', () => {
|
||||
isDynamicVolume: false,
|
||||
SeriesNumber: 1,
|
||||
SeriesDescription: 'Series Description',
|
||||
Modality: 'SEG',
|
||||
} as unknown as AppTypes.DisplaySet;
|
||||
|
||||
jest
|
||||
@@ -1146,7 +1145,6 @@ describe('SegmentationService', () => {
|
||||
info: 'S1: Series Description',
|
||||
},
|
||||
label: 'Segmentation 2',
|
||||
fallbackLabel: 'S:1 SEG',
|
||||
segments: {
|
||||
'1': {
|
||||
active: true,
|
||||
@@ -1177,7 +1175,6 @@ describe('SegmentationService', () => {
|
||||
dynamicVolumeInfo: {
|
||||
timePoints: ['timePoint1', 'timePoint2', 'timePoint3'],
|
||||
},
|
||||
Modality: 'SEG',
|
||||
} as unknown as AppTypes.DisplaySet;
|
||||
|
||||
jest
|
||||
@@ -1215,7 +1212,6 @@ describe('SegmentationService', () => {
|
||||
info: 'S1: Series Description',
|
||||
},
|
||||
label: 'Segmentation 2',
|
||||
fallbackLabel: 'S:1 SEG',
|
||||
segments: {
|
||||
'1': {
|
||||
active: true,
|
||||
@@ -1324,8 +1320,6 @@ describe('SegmentationService', () => {
|
||||
},
|
||||
SeriesDate: '2025-01-01',
|
||||
SeriesDescription: 'Series Description',
|
||||
Modality: 'SEG',
|
||||
SeriesNumber: 1,
|
||||
};
|
||||
|
||||
const referencedDisplaySet = {
|
||||
@@ -1385,7 +1379,6 @@ describe('SegmentationService', () => {
|
||||
const expectedSegmentation = {
|
||||
config: {
|
||||
label: segDisplaySet.SeriesDescription,
|
||||
fallbackLabel: 'S:1 SEG',
|
||||
segments: {
|
||||
'1': {
|
||||
active: false,
|
||||
@@ -1541,7 +1534,7 @@ describe('SegmentationService', () => {
|
||||
it('should create a segmentation for a RTSTRUCT display set', async () => {
|
||||
const segmentationId = 'segmentationId';
|
||||
const rtStructDisplaySet = {
|
||||
Modality: 'RTSTRUCT',
|
||||
modality: 'RTSTRUCT',
|
||||
displaySetInstanceUID: 'display-set-uid',
|
||||
referencedDisplaySetInstanceUID: 'existent-display-set-uid',
|
||||
SeriesDate: '2025-01-01',
|
||||
@@ -1551,7 +1544,6 @@ describe('SegmentationService', () => {
|
||||
ROIContours: [{}, {}, {}],
|
||||
frameOfReferenceUID: 'frameOfReferenceUID',
|
||||
},
|
||||
SeriesNumber: 1,
|
||||
};
|
||||
|
||||
const referencedDisplaySet = {
|
||||
@@ -1658,7 +1650,6 @@ describe('SegmentationService', () => {
|
||||
const expectedSegmentation = {
|
||||
config: {
|
||||
label: rtStructDisplaySet.SeriesDescription,
|
||||
fallbackLabel: 'S:1 RTSTRUCT',
|
||||
segments: {
|
||||
'1': {
|
||||
active: false,
|
||||
@@ -2576,12 +2567,12 @@ describe('SegmentationService', () => {
|
||||
describe('clearSegmentationRepresentations', () => {
|
||||
it('should clear the segmentation representations', () => {
|
||||
const viewportId = 'viewportId';
|
||||
jest.spyOn(service, 'removeRepresentationsFromViewport').mockReturnValue(undefined);
|
||||
jest.spyOn(service, 'removeSegmentationRepresentations').mockReturnValue(undefined);
|
||||
|
||||
service.clearSegmentationRepresentations(viewportId);
|
||||
|
||||
expect(service.removeRepresentationsFromViewport).toHaveBeenCalledTimes(1);
|
||||
expect(service.removeRepresentationsFromViewport).toHaveBeenCalledWith(viewportId);
|
||||
expect(service.removeSegmentationRepresentations).toHaveBeenCalledTimes(1);
|
||||
expect(service.removeSegmentationRepresentations).toHaveBeenCalledWith(viewportId);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2609,7 +2600,7 @@ describe('SegmentationService', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('removeRepresentationsFromViewport', () => {
|
||||
describe('removeSegmentationRepresentations', () => {
|
||||
it('should remove the segmentation representations', () => {
|
||||
const viewportId = 'viewportId';
|
||||
const specifier = {
|
||||
@@ -2618,7 +2609,7 @@ describe('SegmentationService', () => {
|
||||
};
|
||||
jest.spyOn(cstSegmentation, 'removeSegmentationRepresentations').mockReturnValue(undefined);
|
||||
|
||||
service.removeRepresentationsFromViewport(viewportId, specifier);
|
||||
service.removeSegmentationRepresentations(viewportId, specifier);
|
||||
|
||||
expect(cstSegmentation.removeSegmentationRepresentations).toHaveBeenCalledTimes(1);
|
||||
expect(cstSegmentation.removeSegmentationRepresentations).toHaveBeenCalledWith(
|
||||
|
||||
@@ -55,7 +55,6 @@ export type SegmentationRepresentation = cstTypes.SegmentationRepresentation & {
|
||||
viewportId: string;
|
||||
id: string;
|
||||
label: string;
|
||||
fallbackLabel?: string;
|
||||
styles: cstTypes.RepresentationStyle;
|
||||
segments: {
|
||||
[key: number]: SegmentRepresentation;
|
||||
@@ -248,7 +247,7 @@ class SegmentationService extends PubSubService {
|
||||
|
||||
eventTarget.removeEventListener(
|
||||
csToolsEnums.Events.SEGMENTATION_REMOVED,
|
||||
this._onSegmentationRemovedFromSource
|
||||
this._onSegmentationModifiedFromSource
|
||||
);
|
||||
|
||||
eventTarget.removeEventListener(
|
||||
@@ -268,7 +267,7 @@ class SegmentationService extends PubSubService {
|
||||
|
||||
eventTarget.removeEventListener(
|
||||
csToolsEnums.Events.SEGMENTATION_REPRESENTATION_REMOVED,
|
||||
this._onSegmentationRepresentationRemovedFromSource
|
||||
this._onSegmentationRepresentationModifiedFromSource
|
||||
);
|
||||
|
||||
eventTarget.removeEventListener(
|
||||
@@ -431,7 +430,6 @@ class SegmentationService extends PubSubService {
|
||||
},
|
||||
config: {
|
||||
label,
|
||||
fallbackLabel: `S:${displaySet.SeriesNumber} ${displaySet.Modality}`,
|
||||
segments:
|
||||
options?.segments && Object.keys(options.segments).length > 0
|
||||
? options.segments
|
||||
@@ -585,7 +583,6 @@ class SegmentationService extends PubSubService {
|
||||
},
|
||||
config: {
|
||||
label: segDisplaySet.SeriesDescription,
|
||||
fallbackLabel: `S:${segDisplaySet.SeriesNumber} ${segDisplaySet.Modality}`,
|
||||
segments,
|
||||
},
|
||||
};
|
||||
@@ -667,7 +664,6 @@ class SegmentationService extends PubSubService {
|
||||
},
|
||||
config: {
|
||||
label: rtDisplaySet.SeriesDescription,
|
||||
fallbackLabel: `S:${rtDisplaySet.SeriesNumber} ${rtDisplaySet.Modality}`,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1288,14 +1284,14 @@ class SegmentationService extends PubSubService {
|
||||
|
||||
/**
|
||||
* Clears segmentation representations from the viewport.
|
||||
* Unlike removeRepresentationsFromViewport, this doesn't update
|
||||
* Unlike removeSegmentationRepresentations, this doesn't update
|
||||
* removed display set and representation maps.
|
||||
* We track removed segmentations manually to avoid re-adding them
|
||||
* when the display set is added again.
|
||||
* @param viewportId - The viewport ID to clear segmentation representations from.
|
||||
*/
|
||||
public clearSegmentationRepresentations(viewportId: string): void {
|
||||
this.removeRepresentationsFromViewport(viewportId);
|
||||
this.removeSegmentationRepresentations(viewportId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1311,7 +1307,7 @@ class SegmentationService extends PubSubService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes segmentation representations from the viewport.
|
||||
* It removes the segmentation representations from the viewport.
|
||||
* @param viewportId - The viewport id to remove the segmentation representations from.
|
||||
* @param specifier - The specifier to remove the segmentation representations.
|
||||
*
|
||||
@@ -1321,7 +1317,7 @@ class SegmentationService extends PubSubService {
|
||||
* If a type specifier is provided, only the segmentation representation with the specified type are removed.
|
||||
* If both a segmentationId and type specifier are provided, only the segmentation representation with the specified segmentationId and type are removed.
|
||||
*/
|
||||
public removeRepresentationsFromViewport(
|
||||
public removeSegmentationRepresentations(
|
||||
viewportId: string,
|
||||
specifier: {
|
||||
segmentationId?: string;
|
||||
@@ -1846,7 +1842,6 @@ class SegmentationService extends PubSubService {
|
||||
id: id,
|
||||
segmentationId,
|
||||
label: segmentation.label,
|
||||
fallbackLabel: segmentation.fallbackLabel,
|
||||
active,
|
||||
type,
|
||||
visible,
|
||||
@@ -1866,7 +1861,7 @@ class SegmentationService extends PubSubService {
|
||||
|
||||
eventTarget.addEventListener(
|
||||
csToolsEnums.Events.SEGMENTATION_REMOVED,
|
||||
this._onSegmentationRemovedFromSource
|
||||
this._onSegmentationModifiedFromSource
|
||||
);
|
||||
|
||||
eventTarget.addEventListener(
|
||||
@@ -1886,7 +1881,7 @@ class SegmentationService extends PubSubService {
|
||||
|
||||
eventTarget.addEventListener(
|
||||
csToolsEnums.Events.SEGMENTATION_REPRESENTATION_REMOVED,
|
||||
this._onSegmentationRepresentationRemovedFromSource
|
||||
this._onSegmentationRepresentationModifiedFromSource
|
||||
);
|
||||
|
||||
eventTarget.addEventListener(
|
||||
@@ -2125,14 +2120,6 @@ class SegmentationService extends PubSubService {
|
||||
});
|
||||
};
|
||||
|
||||
private _onSegmentationRepresentationRemovedFromSource = evt => {
|
||||
const { segmentationId, viewportId } = evt.detail;
|
||||
this._broadcastEvent(this.EVENTS.SEGMENTATION_REPRESENTATION_REMOVED, {
|
||||
segmentationId,
|
||||
viewportId,
|
||||
});
|
||||
};
|
||||
|
||||
private _onSegmentationModifiedFromSource = (
|
||||
evt: cstTypes.EventTypes.SegmentationModifiedEventType
|
||||
) => {
|
||||
@@ -2153,16 +2140,6 @@ class SegmentationService extends PubSubService {
|
||||
});
|
||||
};
|
||||
|
||||
private _onSegmentationRemovedFromSource = (
|
||||
evt: cstTypes.EventTypes.SegmentationRemovedEventType
|
||||
) => {
|
||||
const { segmentationId } = evt.detail;
|
||||
|
||||
this._broadcastEvent(this.EVENTS.SEGMENTATION_REMOVED, {
|
||||
segmentationId,
|
||||
});
|
||||
};
|
||||
|
||||
private _onAnnotationCutMergeProcessCompletedFromSource = evt => {
|
||||
const { segmentationId } = evt.detail;
|
||||
this._broadcastEvent(this.EVENTS.SEGMENTATION_ANNOTATION_CUT_MERGE_PROCESS_COMPLETED, {
|
||||
|
||||
+1
-9
@@ -66,15 +66,7 @@ const segmentationRepresentationModifiedCallback = async (
|
||||
|
||||
const sharedDisplaySetExists = isAnyDisplaySetCommon(sourceDisplaySetUIDs, targetDisplaySetUIDs);
|
||||
|
||||
const targetFrameOfReferenceUID = viewport.getFrameOfReferenceUID();
|
||||
const sourceFrameOfReferenceUID =
|
||||
getEnabledElementByViewportId(sourceViewportId)?.viewport?.getFrameOfReferenceUID();
|
||||
|
||||
if (!sharedDisplaySetExists && !targetFrameOfReferenceUID) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sharedDisplaySetExists && targetFrameOfReferenceUID !== sourceFrameOfReferenceUID) {
|
||||
if (!sharedDisplaySetExists && !viewport.getFrameOfReferenceUID()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
utilities as csUtils,
|
||||
VolumeViewport,
|
||||
VolumeViewport3D,
|
||||
ECGViewport,
|
||||
cache,
|
||||
Enums as csEnums,
|
||||
BaseVolumeViewport,
|
||||
@@ -779,19 +778,6 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
/**
|
||||
* Sets the image data for the given viewport.
|
||||
*/
|
||||
private async _setEcgViewport(
|
||||
viewport: Types.IECGViewport,
|
||||
viewportData: StackViewportData
|
||||
): Promise<void> {
|
||||
const [displaySet] = viewportData.data;
|
||||
const imageId = displaySet.imageIds?.[0];
|
||||
if (!imageId) {
|
||||
console.error('[CornerstoneViewportService] ECG display set has no imageId');
|
||||
return;
|
||||
}
|
||||
return viewport.setEcg(imageId);
|
||||
}
|
||||
|
||||
private async _setOtherViewport(
|
||||
viewport: Types.IStackViewport,
|
||||
viewportData: StackViewportData,
|
||||
@@ -870,21 +856,28 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
initialImageIndexToUse = this._getInitialImageIndexForViewport(viewportInfo, imageIds) || 0;
|
||||
}
|
||||
|
||||
await viewport.setStack(imageIds, initialImageIndexToUse);
|
||||
viewport.setProperties({ ...properties });
|
||||
this.setPresentations(viewport.id, presentations, viewportInfo);
|
||||
return viewport.setStack(imageIds, initialImageIndexToUse).then(() => {
|
||||
viewport.setProperties({ ...properties });
|
||||
this.setPresentations(viewport.id, presentations, viewportInfo);
|
||||
|
||||
await this._addOverlayRepresentations(overlayProcessingResults);
|
||||
if (overlayProcessingResults?.length) {
|
||||
overlayProcessingResults.forEach(overlayProcessingResult => {
|
||||
if (overlayProcessingResult?.addOverlayFn) {
|
||||
overlayProcessingResult.addOverlayFn();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (displayArea) {
|
||||
viewport.setDisplayArea(displayArea);
|
||||
}
|
||||
if (rotation) {
|
||||
viewport.setProperties({ rotation });
|
||||
}
|
||||
if (flipHorizontal) {
|
||||
viewport.setCamera({ flipHorizontal: true });
|
||||
}
|
||||
if (displayArea) {
|
||||
viewport.setDisplayArea(displayArea);
|
||||
}
|
||||
if (rotation) {
|
||||
viewport.setProperties({ rotation });
|
||||
}
|
||||
if (flipHorizontal) {
|
||||
viewport.setCamera({ flipHorizontal: true });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private _getInitialImageIndexForViewport(
|
||||
@@ -1113,7 +1106,14 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
}
|
||||
|
||||
await viewport.setVolumes(volumeInputArray);
|
||||
await this._addOverlayRepresentations(overlayProcessingResults);
|
||||
|
||||
if (overlayProcessingResults?.length) {
|
||||
overlayProcessingResults.forEach(({ addOverlayFn }) => {
|
||||
if (addOverlayFn) {
|
||||
addOverlayFn();
|
||||
}
|
||||
});
|
||||
}
|
||||
viewport.render();
|
||||
|
||||
volumesProperties.forEach(({ properties, volumeId }) => {
|
||||
@@ -1179,7 +1179,7 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
private addOverlayRepresentationForDisplaySet(
|
||||
displaySet: OhifTypes.DisplaySet,
|
||||
viewport: Types.IViewport
|
||||
): Promise<void> {
|
||||
) {
|
||||
const { segmentationService } = this.servicesManager.services;
|
||||
const segmentationId = displaySet.displaySetInstanceUID;
|
||||
|
||||
@@ -1189,36 +1189,18 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
: csToolsEnums.SegmentationRepresentations.Contour;
|
||||
|
||||
const { predecessorImageId } = displaySet;
|
||||
const segmentationRepresentationPromise = segmentationService.addSegmentationRepresentation(
|
||||
viewport.id,
|
||||
{
|
||||
segmentationId,
|
||||
predecessorImageId,
|
||||
type: representationType,
|
||||
config: {
|
||||
blendMode:
|
||||
viewport?.getBlendMode?.() === 1
|
||||
? BlendModes.LABELMAP_EDGE_PROJECTION_BLEND
|
||||
: undefined,
|
||||
},
|
||||
}
|
||||
);
|
||||
segmentationService.addSegmentationRepresentation(viewport.id, {
|
||||
segmentationId,
|
||||
predecessorImageId,
|
||||
type: representationType,
|
||||
config: {
|
||||
blendMode:
|
||||
viewport?.getBlendMode?.() === 1 ? BlendModes.LABELMAP_EDGE_PROJECTION_BLEND : undefined,
|
||||
},
|
||||
});
|
||||
|
||||
// store the segmentation presentation id in the viewport info
|
||||
this.storePresentation({ viewportId: viewport.id });
|
||||
return segmentationRepresentationPromise;
|
||||
}
|
||||
|
||||
private async _addOverlayRepresentations(
|
||||
overlayProcessingResults?: Array<{ addOverlayFn?: () => Promise<void> }>
|
||||
): Promise<void> {
|
||||
if (!overlayProcessingResults?.length) {
|
||||
return;
|
||||
}
|
||||
for (const overlayProcessingResult of overlayProcessingResults) {
|
||||
if (overlayProcessingResult?.addOverlayFn) {
|
||||
await overlayProcessingResult.addOverlayFn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Todo: keepCamera is an interim solution until we have a better solution for
|
||||
@@ -1275,13 +1257,6 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
);
|
||||
}
|
||||
|
||||
if (viewport instanceof ECGViewport) {
|
||||
return this._setEcgViewport(
|
||||
viewport as unknown as Types.IECGViewport,
|
||||
viewportData as StackViewportData
|
||||
);
|
||||
}
|
||||
|
||||
return this._setOtherViewport(
|
||||
viewport,
|
||||
viewportData as StackViewportData,
|
||||
@@ -1333,8 +1308,8 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
return;
|
||||
}
|
||||
|
||||
if (displaySet.FrameOfReferenceUID) {
|
||||
return displaySet.FrameOfReferenceUID;
|
||||
if (displaySet.frameOfReferenceUID) {
|
||||
return displaySet.frameOfReferenceUID;
|
||||
}
|
||||
|
||||
if (displaySet.Modality === 'SEG') {
|
||||
|
||||
@@ -118,50 +118,29 @@ const CornerstoneViewportDownloadForm = ({
|
||||
const downloadViewport = renderingEngine.getViewport(VIEWPORT_ID);
|
||||
|
||||
try {
|
||||
// Capture current viewport state
|
||||
// - properties: VOI, colormap, interpolation, etc.
|
||||
// - viewPresentation: flip/rotate/zoom presentation state added for
|
||||
// saving flip and rotation for capture
|
||||
// - viewReference: image/volume reference
|
||||
const properties = viewport.getProperties();
|
||||
const viewPresentation = viewport.getViewPresentation?.();
|
||||
const viewRef = viewport.getViewReference?.();
|
||||
|
||||
if (downloadViewport instanceof StackViewport) {
|
||||
const imageId = viewport.getCurrentImageId();
|
||||
const properties = viewport.getProperties();
|
||||
|
||||
await downloadViewport.setStack([imageId]);
|
||||
downloadViewport.setProperties(properties);
|
||||
} else if (downloadViewport instanceof BaseVolumeViewport) {
|
||||
const volumeIds = viewport.getAllVolumeIds();
|
||||
await downloadViewport.setVolumes([{ volumeId: volumeIds[0] }]);
|
||||
downloadViewport.setVolumes([{ volumeId: volumeIds[0] }]);
|
||||
}
|
||||
|
||||
// Apply presentation state so captured image preserves flip/rotate
|
||||
if (viewPresentation && downloadViewport.setViewPresentation) {
|
||||
downloadViewport.setViewPresentation(viewPresentation);
|
||||
}
|
||||
|
||||
// Apply viewport display properties
|
||||
downloadViewport.setProperties(properties);
|
||||
|
||||
// Ensure correct image/volume reference
|
||||
if (viewRef && downloadViewport.setViewReference) {
|
||||
downloadViewport.setViewReference(viewRef);
|
||||
}
|
||||
|
||||
downloadViewport.render();
|
||||
|
||||
// Re-apply segmentation overlays to the download viewport
|
||||
if (segmentationRepresentations?.length) {
|
||||
segmentationRepresentations.forEach(segRepresentation => {
|
||||
const { segmentationId, colorLUTIndex, type } = segRepresentation;
|
||||
|
||||
if (type === Enums.SegmentationRepresentations.Labelmap) {
|
||||
segmentation.addLabelmapRepresentationToViewportMap({
|
||||
[downloadViewport.id]: [
|
||||
{
|
||||
segmentationId,
|
||||
type: Enums.SegmentationRepresentations.Labelmap,
|
||||
config: { colorLUTOrIndex: colorLUTIndex },
|
||||
config: {
|
||||
colorLUTOrIndex: colorLUTIndex,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -173,7 +152,9 @@ const CornerstoneViewportDownloadForm = ({
|
||||
{
|
||||
segmentationId,
|
||||
type: Enums.SegmentationRepresentations.Contour,
|
||||
config: { colorLUTOrIndex: colorLUTIndex },
|
||||
config: {
|
||||
colorLUTOrIndex: colorLUTIndex,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -249,48 +230,6 @@ const CornerstoneViewportDownloadForm = ({
|
||||
downloadUrl(canvas.toDataURL(`image/${fileType}`, 1.0), { filename });
|
||||
};
|
||||
|
||||
const handleCopyToClipboard = async () => {
|
||||
const divForDownloadViewport = document.querySelector(
|
||||
`div[data-viewport-uid="${VIEWPORT_ID}"]`
|
||||
);
|
||||
|
||||
if (!divForDownloadViewport) {
|
||||
console.debug('No viewport found for copy');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const canvas = await html2canvas(divForDownloadViewport as HTMLElement);
|
||||
|
||||
// Clipboard API only supports PNG format in most browsers
|
||||
const blob = await new Promise<Blob>((resolve, reject) => {
|
||||
canvas.toBlob(
|
||||
blob => {
|
||||
if (blob) {
|
||||
resolve(blob);
|
||||
} else {
|
||||
reject(new Error('Failed to create blob from canvas'));
|
||||
}
|
||||
},
|
||||
'image/png',
|
||||
1.0
|
||||
);
|
||||
});
|
||||
|
||||
// Copy to clipboard using the Clipboard API
|
||||
await navigator.clipboard.write([
|
||||
new ClipboardItem({
|
||||
'image/png': blob,
|
||||
}),
|
||||
]);
|
||||
|
||||
console.log('Image copied to clipboard successfully');
|
||||
} catch (error) {
|
||||
console.error('Failed to copy image to clipboard:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
const ViewportDownloadFormNew = customizationService.getCustomization(
|
||||
'ohif.captureViewportModal'
|
||||
);
|
||||
@@ -308,7 +247,6 @@ const CornerstoneViewportDownloadForm = ({
|
||||
onEnableViewport={handleEnableViewport}
|
||||
onDisableViewport={handleDisableViewport}
|
||||
onDownload={handleDownload}
|
||||
onCopyToClipboard={handleCopyToClipboard}
|
||||
warningState={warningState}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -1,217 +0,0 @@
|
||||
import { decodeInt16Multiplex, base64ToArrayBuffer, buildEcgModule } from './ecgMetadata';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// decodeInt16Multiplex
|
||||
// ---------------------------------------------------------------------------
|
||||
describe('decodeInt16Multiplex', () => {
|
||||
it('demultiplexes 2 channels correctly', () => {
|
||||
// Interleaved layout: [ch0_s0, ch1_s0, ch0_s1, ch1_s1, ch0_s2, ch1_s2]
|
||||
const interleaved = new Int16Array([10, 20, 30, 40, 50, 60]);
|
||||
const channels = decodeInt16Multiplex(interleaved.buffer, 2, 3);
|
||||
|
||||
expect(channels).toHaveLength(2);
|
||||
expect(Array.from(channels[0])).toEqual([10, 30, 50]);
|
||||
expect(Array.from(channels[1])).toEqual([20, 40, 60]);
|
||||
});
|
||||
|
||||
it('handles a single channel', () => {
|
||||
const data = new Int16Array([100, 200, 300]);
|
||||
const channels = decodeInt16Multiplex(data.buffer, 1, 3);
|
||||
|
||||
expect(channels).toHaveLength(1);
|
||||
expect(Array.from(channels[0])).toEqual([100, 200, 300]);
|
||||
});
|
||||
|
||||
it('handles negative values (signed short)', () => {
|
||||
const data = new Int16Array([-1000, -2000, -3000]);
|
||||
const channels = decodeInt16Multiplex(data.buffer, 1, 3);
|
||||
|
||||
expect(Array.from(channels[0])).toEqual([-1000, -2000, -3000]);
|
||||
});
|
||||
|
||||
it('returns empty arrays when numberOfChannels or numberOfSamples is 0', () => {
|
||||
const emptyBuffer = new Int16Array([]).buffer;
|
||||
|
||||
expect(decodeInt16Multiplex(emptyBuffer, 0, 0)).toHaveLength(0);
|
||||
expect(decodeInt16Multiplex(emptyBuffer, 0, 10)).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('produces Int16Array instances for each channel', () => {
|
||||
const data = new Int16Array([1, 2]);
|
||||
const channels = decodeInt16Multiplex(data.buffer, 2, 1);
|
||||
|
||||
expect(channels[0]).toBeInstanceOf(Int16Array);
|
||||
expect(channels[1]).toBeInstanceOf(Int16Array);
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// base64ToArrayBuffer
|
||||
// ---------------------------------------------------------------------------
|
||||
describe('base64ToArrayBuffer', () => {
|
||||
it('decodes a simple base64 string to the correct bytes', () => {
|
||||
// "ABC" in ASCII = [65, 66, 67]; base64 of that is 'QUJD'
|
||||
const buffer = base64ToArrayBuffer('QUJD');
|
||||
const bytes = new Uint8Array(buffer);
|
||||
|
||||
expect(bytes).toHaveLength(3);
|
||||
expect(Array.from(bytes)).toEqual([65, 66, 67]);
|
||||
});
|
||||
|
||||
it('round-trips an Int16Array through base64', () => {
|
||||
const original = new Int16Array([500, -300, 0, 32767]);
|
||||
const base64 = btoa(String.fromCharCode(...new Uint8Array(original.buffer)));
|
||||
const recovered = new Int16Array(base64ToArrayBuffer(base64));
|
||||
|
||||
expect(Array.from(recovered)).toEqual(Array.from(original));
|
||||
});
|
||||
|
||||
it('returns an ArrayBuffer', () => {
|
||||
const result = base64ToArrayBuffer('AA=='); // single zero byte
|
||||
expect(result).toBeInstanceOf(ArrayBuffer);
|
||||
expect(result.byteLength).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// buildEcgModule
|
||||
// ---------------------------------------------------------------------------
|
||||
describe('buildEcgModule', () => {
|
||||
const makeInstance = (overrides = {}) => ({
|
||||
WaveformSequence: [
|
||||
{
|
||||
NumberOfWaveformChannels: 12,
|
||||
NumberOfWaveformSamples: 5000,
|
||||
SamplingFrequency: 500,
|
||||
WaveformBitsAllocated: 16,
|
||||
WaveformSampleInterpretation: 'SS',
|
||||
MultiplexGroupLabel: '12 Lead ECG',
|
||||
ChannelDefinitionSequence: [
|
||||
{ ChannelSourceSequence: [{ CodeMeaning: 'Lead I' }] },
|
||||
{ ChannelSourceSequence: [{ CodeMeaning: 'Lead II' }] },
|
||||
],
|
||||
WaveformData: { InlineBinary: btoa('\x00\x01') },
|
||||
},
|
||||
],
|
||||
...overrides,
|
||||
});
|
||||
|
||||
it('returns null when WaveformSequence is absent', () => {
|
||||
expect(buildEcgModule({})).toBeNull();
|
||||
expect(buildEcgModule({ WaveformSequence: [] })).toBeNull();
|
||||
});
|
||||
|
||||
it('returns a valid ecgModule for a complete instance', () => {
|
||||
const module = buildEcgModule(makeInstance());
|
||||
|
||||
expect(module).not.toBeNull();
|
||||
expect(module!.numberOfWaveformChannels).toBe(12);
|
||||
expect(module!.numberOfWaveformSamples).toBe(5000);
|
||||
expect(module!.samplingFrequency).toBe(500);
|
||||
expect(module!.waveformBitsAllocated).toBe(16);
|
||||
expect(module!.waveformSampleInterpretation).toBe('SS');
|
||||
expect(module!.multiplexGroupLabel).toBe('12 Lead ECG');
|
||||
expect(module!.channelDefinitionSequence).toHaveLength(2);
|
||||
expect(module!.channelDefinitionSequence[0].channelSourceSequence.codeMeaning).toBe('Lead I');
|
||||
expect(typeof module!.waveformData.retrieveBulkData).toBe('function');
|
||||
});
|
||||
|
||||
it('applies defaults for missing optional fields', () => {
|
||||
const instance = {
|
||||
WaveformSequence: [
|
||||
{
|
||||
// No explicit values — all defaults
|
||||
WaveformData: { InlineBinary: btoa('\x00\x00') },
|
||||
},
|
||||
],
|
||||
};
|
||||
const module = buildEcgModule(instance);
|
||||
|
||||
expect(module!.numberOfWaveformChannels).toBe(0);
|
||||
expect(module!.numberOfWaveformSamples).toBe(0);
|
||||
expect(module!.samplingFrequency).toBe(1);
|
||||
expect(module!.waveformBitsAllocated).toBe(16);
|
||||
expect(module!.waveformSampleInterpretation).toBe('SS');
|
||||
expect(module!.multiplexGroupLabel).toBe('');
|
||||
expect(module!.channelDefinitionSequence).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('retrieveBulkData decodes InlineBinary data correctly', async () => {
|
||||
const samples = new Int16Array([10, 20, 30]);
|
||||
const base64 = btoa(String.fromCharCode(...new Uint8Array(samples.buffer)));
|
||||
|
||||
const instance = {
|
||||
WaveformSequence: [
|
||||
{
|
||||
NumberOfWaveformChannels: 1,
|
||||
NumberOfWaveformSamples: 3,
|
||||
WaveformData: { InlineBinary: base64 },
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const module = buildEcgModule(instance);
|
||||
const channels = await module!.waveformData.retrieveBulkData();
|
||||
|
||||
expect(channels).toHaveLength(1);
|
||||
expect(Array.from(channels[0])).toEqual([10, 20, 30]);
|
||||
});
|
||||
|
||||
it('retrieveBulkData returns [] when WaveformData is absent', async () => {
|
||||
const instance = {
|
||||
WaveformSequence: [
|
||||
{ NumberOfWaveformChannels: 1, NumberOfWaveformSamples: 1 },
|
||||
],
|
||||
};
|
||||
const module = buildEcgModule(instance);
|
||||
const channels = await module!.waveformData.retrieveBulkData();
|
||||
|
||||
expect(channels).toEqual([]);
|
||||
});
|
||||
|
||||
it('retrieveBulkData fetches BulkDataURI with auth header when provided', async () => {
|
||||
const samples = new Int16Array([1, 2]);
|
||||
global.fetch = jest.fn().mockResolvedValue({
|
||||
ok: true,
|
||||
arrayBuffer: () => Promise.resolve(samples.buffer),
|
||||
});
|
||||
|
||||
const userAuthenticationService = {
|
||||
getAuthorizationHeader: () => ({ Authorization: 'Bearer token123' }),
|
||||
};
|
||||
const instance = {
|
||||
WaveformSequence: [
|
||||
{
|
||||
NumberOfWaveformChannels: 1,
|
||||
NumberOfWaveformSamples: 2,
|
||||
WaveformData: { BulkDataURI: 'http://example.com/waveform' },
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const module = buildEcgModule(instance, userAuthenticationService);
|
||||
await module!.waveformData.retrieveBulkData();
|
||||
|
||||
expect(global.fetch).toHaveBeenCalledWith('http://example.com/waveform', {
|
||||
headers: {
|
||||
Accept: 'application/octet-stream',
|
||||
Authorization: 'Bearer token123',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('retrieveBulkData throws when BulkDataURI response is not ok', async () => {
|
||||
global.fetch = jest.fn().mockResolvedValue({ ok: false, status: 403 });
|
||||
|
||||
const instance = {
|
||||
WaveformSequence: [
|
||||
{
|
||||
WaveformData: { BulkDataURI: 'http://example.com/waveform' },
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const module = buildEcgModule(instance);
|
||||
await expect(module!.waveformData.retrieveBulkData()).rejects.toThrow('403');
|
||||
});
|
||||
});
|
||||
@@ -1,129 +0,0 @@
|
||||
/**
|
||||
* Decode a multiplexed Int16 buffer into per-channel arrays.
|
||||
* Layout: sample0ch0, sample0ch1 ... sample0chN, sample1ch0, …
|
||||
* Note: DICOM ECG data is canonically SS (signed short). The sampleInterpretation
|
||||
* field is forwarded to ECGViewport for its own use; the raw buffer is always
|
||||
* treated as Int16 because Cornerstone ECGViewport expects Int16Array[].
|
||||
*/
|
||||
export function decodeInt16Multiplex(
|
||||
buffer: ArrayBuffer,
|
||||
numberOfChannels: number,
|
||||
numberOfSamples: number
|
||||
): Int16Array[] {
|
||||
const src = new Int16Array(buffer);
|
||||
const channels: Int16Array[] = [];
|
||||
for (let ch = 0; ch < numberOfChannels; ch++) {
|
||||
const out = new Int16Array(numberOfSamples);
|
||||
for (let s = 0; s < numberOfSamples; s++) {
|
||||
out[s] = src[s * numberOfChannels + ch];
|
||||
}
|
||||
channels.push(out);
|
||||
}
|
||||
return channels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a base64 InlineBinary string into a raw ArrayBuffer.
|
||||
*/
|
||||
export function base64ToArrayBuffer(base64: string): ArrayBuffer {
|
||||
const binaryStr = atob(base64);
|
||||
const bytes = new Uint8Array(binaryStr.length);
|
||||
for (let i = 0; i < binaryStr.length; i++) {
|
||||
bytes[i] = binaryStr.charCodeAt(i);
|
||||
}
|
||||
return bytes.buffer;
|
||||
}
|
||||
|
||||
export type EcgModule = {
|
||||
numberOfWaveformChannels: number;
|
||||
numberOfWaveformSamples: number;
|
||||
samplingFrequency: number;
|
||||
waveformBitsAllocated: number;
|
||||
waveformSampleInterpretation: string;
|
||||
multiplexGroupLabel: string;
|
||||
channelDefinitionSequence: Array<{ channelSourceSequence: { codeMeaning: string } }>;
|
||||
waveformData: { retrieveBulkData: () => Promise<Int16Array[]> };
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse the naturalized DICOM instance's WaveformSequence and build the ecgModule
|
||||
* that Cornerstone's ECGViewport.setEcg() expects via
|
||||
* metaData.get(MetadataModules.ECG, imageId).
|
||||
*
|
||||
* Returns null if the instance has no WaveformSequence.
|
||||
*/
|
||||
export function buildEcgModule(
|
||||
instance: any,
|
||||
userAuthenticationService?: any
|
||||
): EcgModule | null {
|
||||
const waveformGroups = instance?.WaveformSequence;
|
||||
if (!waveformGroups?.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Use the first (and typically only) multiplex group
|
||||
const group = waveformGroups[0];
|
||||
|
||||
const numberOfChannels = group.NumberOfWaveformChannels ?? 0;
|
||||
const numberOfSamples = group.NumberOfWaveformSamples ?? 0;
|
||||
const samplingFrequency = group.SamplingFrequency ?? 1;
|
||||
const bitsAllocated = group.WaveformBitsAllocated ?? 16;
|
||||
const sampleInterpretation = group.WaveformSampleInterpretation ?? 'SS';
|
||||
const multiplexGroupLabel = group.MultiplexGroupLabel ?? '';
|
||||
|
||||
const channelDefinitionSequence = (group.ChannelDefinitionSequence ?? []).map(ch => ({
|
||||
channelSourceSequence: {
|
||||
codeMeaning:
|
||||
ch?.ChannelSourceSequence?.[0]?.CodeMeaning ??
|
||||
ch?.ChannelSourceSequence?.[0]?.codeMeaning ??
|
||||
'',
|
||||
},
|
||||
}));
|
||||
|
||||
const retrieveBulkData = async (): Promise<Int16Array[]> => {
|
||||
const waveformData = group.WaveformData;
|
||||
|
||||
if (!waveformData) {
|
||||
console.warn('[ECGViewport] No WaveformData found on instance');
|
||||
return [];
|
||||
}
|
||||
|
||||
let buffer: ArrayBuffer;
|
||||
|
||||
if (waveformData.InlineBinary) {
|
||||
buffer = base64ToArrayBuffer(waveformData.InlineBinary);
|
||||
} else if (waveformData.BulkDataURI) {
|
||||
const headers: Record<string, string> = {
|
||||
Accept: 'application/octet-stream',
|
||||
};
|
||||
const authHeader = userAuthenticationService?.getAuthorizationHeader?.();
|
||||
if (authHeader) {
|
||||
Object.assign(headers, authHeader);
|
||||
}
|
||||
|
||||
const response = await fetch(waveformData.BulkDataURI, { headers });
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`[ECGViewport] Failed to fetch waveform BulkDataURI: ${response.status}`
|
||||
);
|
||||
}
|
||||
buffer = await response.arrayBuffer();
|
||||
} else {
|
||||
console.warn('[ECGViewport] WaveformData has no InlineBinary or BulkDataURI');
|
||||
return [];
|
||||
}
|
||||
|
||||
return decodeInt16Multiplex(buffer, numberOfChannels, numberOfSamples);
|
||||
};
|
||||
|
||||
return {
|
||||
numberOfWaveformChannels: numberOfChannels,
|
||||
numberOfWaveformSamples: numberOfSamples,
|
||||
samplingFrequency,
|
||||
waveformBitsAllocated: bitsAllocated,
|
||||
waveformSampleInterpretation: sampleInterpretation,
|
||||
multiplexGroupLabel,
|
||||
channelDefinitionSequence,
|
||||
waveformData: { retrieveBulkData },
|
||||
};
|
||||
}
|
||||
@@ -10,7 +10,6 @@ jest.mock('@cornerstonejs/core', () => ({
|
||||
WHOLE_SLIDE: 'wholeslide',
|
||||
ORTHOGRAPHIC: 'orthographic',
|
||||
VOLUME_3D: 'volume3d',
|
||||
ECG: 'ecg',
|
||||
},
|
||||
},
|
||||
}));
|
||||
@@ -51,14 +50,9 @@ describe('getCornerstoneViewportType', () => {
|
||||
expect(result).toBe(Enums.ViewportType.VOLUME_3D);
|
||||
});
|
||||
|
||||
it('should return ECG when viewportType is ecg', () => {
|
||||
const result = getCornerstoneViewportType('ecg');
|
||||
expect(result).toBe(Enums.ViewportType.ECG);
|
||||
});
|
||||
|
||||
it('should throw error for invalid viewport type', () => {
|
||||
expect(() => getCornerstoneViewportType('invalid')).toThrow(
|
||||
'Invalid viewport type: invalid. Valid types are: stack, volume, video, wholeslide, ecg'
|
||||
'Invalid viewport type: invalid. Valid types are: stack, volume, video, wholeslide'
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ const ORTHOGRAPHIC = 'orthographic';
|
||||
const VOLUME_3D = 'volume3d';
|
||||
const VIDEO = 'video';
|
||||
const WHOLESLIDE = 'wholeslide';
|
||||
const ECG = 'ecg';
|
||||
|
||||
export default function getCornerstoneViewportType(
|
||||
viewportType: string,
|
||||
@@ -26,10 +25,6 @@ export default function getCornerstoneViewportType(
|
||||
return Enums.ViewportType.WHOLE_SLIDE;
|
||||
}
|
||||
|
||||
if (lowerViewportType === ECG) {
|
||||
return Enums.ViewportType.ECG;
|
||||
}
|
||||
|
||||
if (lowerViewportType === VOLUME || lowerViewportType === ORTHOGRAPHIC) {
|
||||
return Enums.ViewportType.ORTHOGRAPHIC;
|
||||
}
|
||||
@@ -39,6 +34,6 @@ export default function getCornerstoneViewportType(
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Invalid viewport type: ${viewportType}. Valid types are: stack, volume, video, wholeslide, ecg`
|
||||
`Invalid viewport type: ${viewportType}. Valid types are: stack, volume, video, wholeslide`
|
||||
);
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
/**
|
||||
* Resolves the data ID (e.g. volumeId) for a viewport and display set.
|
||||
* For viewports with multiple volumes/actors, returns the id that matches the display set; otherwise undefined.
|
||||
* Use this to call viewport.getProperties(dataId) in a viewport-type-agnostic way.
|
||||
*
|
||||
* @param viewport - Viewport instance (stack, volume, or future types with optional getAllVolumeIds)
|
||||
* @param displaySetInstanceUID - Display set instance UID to match
|
||||
* @returns volumeId (or equivalent) for multi-actor viewports, undefined for single-actor
|
||||
*/
|
||||
export function getDataIdForViewport(
|
||||
viewport: unknown,
|
||||
displaySetInstanceUID: string
|
||||
): string | undefined {
|
||||
const vp = viewport as { getAllVolumeIds?: () => string[] };
|
||||
if (typeof vp.getAllVolumeIds !== 'function') {
|
||||
return undefined;
|
||||
}
|
||||
const volumeIds = vp.getAllVolumeIds() || [];
|
||||
return volumeIds.length > 0
|
||||
? volumeIds.find(id => id.includes(displaySetInstanceUID)) ?? undefined
|
||||
: undefined;
|
||||
}
|
||||
@@ -11,7 +11,7 @@ describe('promptHydrationDialog', () => {
|
||||
};
|
||||
|
||||
const mockExtensionManager = {
|
||||
appConfig: {
|
||||
_appConfig: {
|
||||
measurementTrackingMode: 'standard',
|
||||
disableConfirmationPrompts: false,
|
||||
},
|
||||
@@ -57,7 +57,7 @@ describe('promptHydrationDialog', () => {
|
||||
});
|
||||
|
||||
it('should return HYDRATE response when disableConfirmationPrompts is true for non-SR types', async () => {
|
||||
mockExtensionManager.appConfig.disableConfirmationPrompts = true;
|
||||
mockExtensionManager._appConfig.disableConfirmationPrompts = true;
|
||||
|
||||
const result = await promptHydrationDialog(defaultParameters);
|
||||
|
||||
@@ -71,7 +71,7 @@ describe('promptHydrationDialog', () => {
|
||||
});
|
||||
|
||||
it('should show dialog when disableConfirmationPrompts is false for non-SR types', async () => {
|
||||
mockExtensionManager.appConfig.disableConfirmationPrompts = false;
|
||||
mockExtensionManager._appConfig.disableConfirmationPrompts = false;
|
||||
|
||||
const promise = promptHydrationDialog(defaultParameters);
|
||||
|
||||
@@ -107,7 +107,7 @@ describe('promptHydrationDialog', () => {
|
||||
});
|
||||
|
||||
it('should handle CANCEL response', async () => {
|
||||
mockExtensionManager.appConfig.disableConfirmationPrompts = false;
|
||||
mockExtensionManager._appConfig.disableConfirmationPrompts = false;
|
||||
|
||||
const promise = promptHydrationDialog(defaultParameters);
|
||||
|
||||
@@ -120,7 +120,7 @@ describe('promptHydrationDialog', () => {
|
||||
});
|
||||
|
||||
it('should handle onOutsideClick', async () => {
|
||||
mockExtensionManager.appConfig.disableConfirmationPrompts = false;
|
||||
mockExtensionManager._appConfig.disableConfirmationPrompts = false;
|
||||
|
||||
const promise = promptHydrationDialog(defaultParameters);
|
||||
|
||||
@@ -133,7 +133,7 @@ describe('promptHydrationDialog', () => {
|
||||
});
|
||||
|
||||
it('should handle onKeyPress Enter', async () => {
|
||||
mockExtensionManager.appConfig.disableConfirmationPrompts = false;
|
||||
mockExtensionManager._appConfig.disableConfirmationPrompts = false;
|
||||
|
||||
const promise = promptHydrationDialog(defaultParameters);
|
||||
|
||||
@@ -146,7 +146,7 @@ describe('promptHydrationDialog', () => {
|
||||
});
|
||||
|
||||
it('should handle onKeyPress non-Enter key', async () => {
|
||||
mockExtensionManager.appConfig.disableConfirmationPrompts = false;
|
||||
mockExtensionManager._appConfig.disableConfirmationPrompts = false;
|
||||
|
||||
const promise = promptHydrationDialog(defaultParameters);
|
||||
|
||||
@@ -163,7 +163,7 @@ describe('promptHydrationDialog', () => {
|
||||
});
|
||||
|
||||
it('should handle SEG type hydration with setTimeout', async () => {
|
||||
mockExtensionManager.appConfig.disableConfirmationPrompts = true;
|
||||
mockExtensionManager._appConfig.disableConfirmationPrompts = true;
|
||||
|
||||
await promptHydrationDialog({
|
||||
...defaultParameters,
|
||||
@@ -178,7 +178,7 @@ describe('promptHydrationDialog', () => {
|
||||
});
|
||||
|
||||
it('should handle RTSTRUCT type hydration', async () => {
|
||||
mockExtensionManager.appConfig.disableConfirmationPrompts = true;
|
||||
mockExtensionManager._appConfig.disableConfirmationPrompts = true;
|
||||
|
||||
const result = await promptHydrationDialog({
|
||||
...defaultParameters,
|
||||
@@ -194,7 +194,7 @@ describe('promptHydrationDialog', () => {
|
||||
});
|
||||
|
||||
it('should handle SR type hydration when standardMode is true', async () => {
|
||||
mockExtensionManager.appConfig.measurementTrackingMode = 'standard';
|
||||
mockExtensionManager._appConfig.measurementTrackingMode = 'standard';
|
||||
const mockHydrationResult = {
|
||||
StudyInstanceUID: 'test-study-uid',
|
||||
SeriesInstanceUIDs: ['series-1', 'series-2'],
|
||||
@@ -222,7 +222,7 @@ describe('promptHydrationDialog', () => {
|
||||
});
|
||||
|
||||
it('should handle SR type hydration when standardMode is false', async () => {
|
||||
mockExtensionManager.appConfig.measurementTrackingMode = 'other';
|
||||
mockExtensionManager._appConfig.measurementTrackingMode = 'other';
|
||||
|
||||
const result = await promptHydrationDialog({
|
||||
...defaultParameters,
|
||||
@@ -241,7 +241,7 @@ describe('promptHydrationDialog', () => {
|
||||
});
|
||||
|
||||
it('should handle SR type with CANCEL response', async () => {
|
||||
mockExtensionManager.appConfig.measurementTrackingMode = 'standard';
|
||||
mockExtensionManager._appConfig.measurementTrackingMode = 'standard';
|
||||
|
||||
const promise = promptHydrationDialog({
|
||||
...defaultParameters,
|
||||
@@ -262,7 +262,7 @@ describe('promptHydrationDialog', () => {
|
||||
});
|
||||
|
||||
it('should handle undefined preHydrateCallbacks', async () => {
|
||||
mockExtensionManager.appConfig.disableConfirmationPrompts = true;
|
||||
mockExtensionManager._appConfig.disableConfirmationPrompts = true;
|
||||
|
||||
await promptHydrationDialog({
|
||||
...defaultParameters,
|
||||
@@ -273,7 +273,7 @@ describe('promptHydrationDialog', () => {
|
||||
});
|
||||
|
||||
it('should handle empty preHydrateCallbacks array', async () => {
|
||||
mockExtensionManager.appConfig.disableConfirmationPrompts = true;
|
||||
mockExtensionManager._appConfig.disableConfirmationPrompts = true;
|
||||
|
||||
await promptHydrationDialog({
|
||||
...defaultParameters,
|
||||
@@ -285,7 +285,7 @@ describe('promptHydrationDialog', () => {
|
||||
|
||||
it('should execute multiple preHydrateCallbacks', async () => {
|
||||
const mockPreHydrateCallback2 = jest.fn();
|
||||
mockExtensionManager.appConfig.disableConfirmationPrompts = true;
|
||||
mockExtensionManager._appConfig.disableConfirmationPrompts = true;
|
||||
|
||||
await promptHydrationDialog({
|
||||
...defaultParameters,
|
||||
@@ -297,7 +297,7 @@ describe('promptHydrationDialog', () => {
|
||||
});
|
||||
|
||||
it('should get correct customization message key for SEG type', async () => {
|
||||
mockExtensionManager.appConfig.disableConfirmationPrompts = false;
|
||||
mockExtensionManager._appConfig.disableConfirmationPrompts = false;
|
||||
|
||||
const promise = promptHydrationDialog({
|
||||
...defaultParameters,
|
||||
@@ -314,7 +314,7 @@ describe('promptHydrationDialog', () => {
|
||||
});
|
||||
|
||||
it('should get correct customization message key for RTSTRUCT type', async () => {
|
||||
mockExtensionManager.appConfig.disableConfirmationPrompts = false;
|
||||
mockExtensionManager._appConfig.disableConfirmationPrompts = false;
|
||||
|
||||
const promise = promptHydrationDialog({
|
||||
...defaultParameters,
|
||||
@@ -331,7 +331,7 @@ describe('promptHydrationDialog', () => {
|
||||
});
|
||||
|
||||
it('should get correct customization message key for SR type', async () => {
|
||||
mockExtensionManager.appConfig.measurementTrackingMode = 'standard';
|
||||
mockExtensionManager._appConfig.measurementTrackingMode = 'standard';
|
||||
|
||||
const promise = promptHydrationDialog({
|
||||
...defaultParameters,
|
||||
@@ -348,7 +348,7 @@ describe('promptHydrationDialog', () => {
|
||||
});
|
||||
|
||||
it('should get default customization message key for unknown type', async () => {
|
||||
mockExtensionManager.appConfig.disableConfirmationPrompts = false;
|
||||
mockExtensionManager._appConfig.disableConfirmationPrompts = false;
|
||||
|
||||
const promise = promptHydrationDialog({
|
||||
...defaultParameters,
|
||||
@@ -365,7 +365,7 @@ describe('promptHydrationDialog', () => {
|
||||
});
|
||||
|
||||
it('should get correct dialog id for SEG type', async () => {
|
||||
mockExtensionManager.appConfig.disableConfirmationPrompts = false;
|
||||
mockExtensionManager._appConfig.disableConfirmationPrompts = false;
|
||||
|
||||
const promise = promptHydrationDialog({
|
||||
...defaultParameters,
|
||||
@@ -384,7 +384,7 @@ describe('promptHydrationDialog', () => {
|
||||
});
|
||||
|
||||
it('should get correct dialog id for SR type', async () => {
|
||||
mockExtensionManager.appConfig.measurementTrackingMode = 'standard';
|
||||
mockExtensionManager._appConfig.measurementTrackingMode = 'standard';
|
||||
|
||||
const promise = promptHydrationDialog({
|
||||
...defaultParameters,
|
||||
@@ -403,7 +403,7 @@ describe('promptHydrationDialog', () => {
|
||||
});
|
||||
|
||||
it('should get default dialog id for unknown type', async () => {
|
||||
mockExtensionManager.appConfig.disableConfirmationPrompts = false;
|
||||
mockExtensionManager._appConfig.disableConfirmationPrompts = false;
|
||||
|
||||
const promise = promptHydrationDialog({
|
||||
...defaultParameters,
|
||||
@@ -422,7 +422,7 @@ describe('promptHydrationDialog', () => {
|
||||
});
|
||||
|
||||
it('should handle hydrateCallback returning false for SEG', async () => {
|
||||
mockExtensionManager.appConfig.disableConfirmationPrompts = true;
|
||||
mockExtensionManager._appConfig.disableConfirmationPrompts = true;
|
||||
mockHydrateCallback.mockResolvedValue(false);
|
||||
|
||||
const result = await promptHydrationDialog({
|
||||
@@ -434,7 +434,7 @@ describe('promptHydrationDialog', () => {
|
||||
});
|
||||
|
||||
it('should handle hydrateCallback returning false for RTSTRUCT', async () => {
|
||||
mockExtensionManager.appConfig.disableConfirmationPrompts = true;
|
||||
mockExtensionManager._appConfig.disableConfirmationPrompts = true;
|
||||
mockHydrateCallback.mockResolvedValue(false);
|
||||
|
||||
const result = await promptHydrationDialog({
|
||||
@@ -446,7 +446,7 @@ describe('promptHydrationDialog', () => {
|
||||
});
|
||||
|
||||
it('should handle SR hydration with null result', async () => {
|
||||
mockExtensionManager.appConfig.measurementTrackingMode = 'standard';
|
||||
mockExtensionManager._appConfig.measurementTrackingMode = 'standard';
|
||||
mockHydrateCallback.mockResolvedValue(null);
|
||||
|
||||
const promise = promptHydrationDialog({
|
||||
@@ -470,7 +470,7 @@ describe('promptHydrationDialog', () => {
|
||||
});
|
||||
|
||||
it('should handle RTSTRUCT type in getDialogId', async () => {
|
||||
mockExtensionManager.appConfig.disableConfirmationPrompts = false;
|
||||
mockExtensionManager._appConfig.disableConfirmationPrompts = false;
|
||||
|
||||
const promise = promptHydrationDialog({
|
||||
...defaultParameters,
|
||||
|
||||
@@ -70,7 +70,7 @@ function promptHydrationDialog({
|
||||
}: HydrationDialogProps): Promise<boolean | HydrationSRResult> {
|
||||
const { uiViewportDialogService, customizationService } = servicesManager.services;
|
||||
const extensionManager = servicesManager._extensionManager;
|
||||
const appConfig = extensionManager.appConfig;
|
||||
const appConfig = extensionManager._appConfig;
|
||||
|
||||
// Todo: make this use enum from the extension, we should move the enum
|
||||
const standardMode = appConfig?.measurementTrackingMode === 'standard';
|
||||
@@ -94,30 +94,22 @@ function promptHydrationDialog({
|
||||
if (type === HydrationType.SEG) {
|
||||
// SEG needs setTimeout
|
||||
window.setTimeout(async () => {
|
||||
try {
|
||||
const isHydrated = await hydrateCallback({
|
||||
segDisplaySet: displaySet,
|
||||
viewportId,
|
||||
});
|
||||
resolve(isHydrated);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
const isHydrated = await hydrateCallback({
|
||||
segDisplaySet: displaySet,
|
||||
viewportId,
|
||||
});
|
||||
|
||||
resolve(isHydrated);
|
||||
}, 0);
|
||||
} else if (type === HydrationType.RTSTRUCT) {
|
||||
// RT hydration
|
||||
window.setTimeout(async () => {
|
||||
try {
|
||||
const isHydrated = await hydrateCallback({
|
||||
rtDisplaySet: displaySet,
|
||||
viewportId,
|
||||
servicesManager,
|
||||
});
|
||||
resolve(isHydrated);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
}, 0);
|
||||
const isHydrated = await hydrateCallback({
|
||||
rtDisplaySet: displaySet,
|
||||
viewportId,
|
||||
servicesManager,
|
||||
});
|
||||
|
||||
resolve(isHydrated);
|
||||
} else if (type === HydrationType.SR) {
|
||||
// SR has a different result structure
|
||||
const hydrationResult = await hydrateCallback(displaySet);
|
||||
|
||||
@@ -15,7 +15,6 @@ describe('setUpSegmentationEventHandlers', () => {
|
||||
const mockSegmentationService = {
|
||||
EVENTS: {
|
||||
SEGMENTATION_ADDED: 'SEGMENTATION_ADDED',
|
||||
SEGMENTATION_REMOVED: 'SEGMENTATION_REMOVED',
|
||||
},
|
||||
subscribe: jest.fn(),
|
||||
getSegmentation: jest.fn(),
|
||||
@@ -41,7 +40,6 @@ describe('setUpSegmentationEventHandlers', () => {
|
||||
const mockUnsubscribeDataModified = jest.fn();
|
||||
const mockUnsubscribeModified = jest.fn();
|
||||
const mockUnsubscribeCreated = jest.fn();
|
||||
const mockUnsubscribeRemoved = jest.fn();
|
||||
const mockUnsubscribeSelectedSegmentationsForViewportEvents = [jest.fn(), jest.fn()];
|
||||
|
||||
const defaultParameters = {
|
||||
@@ -61,14 +59,8 @@ describe('setUpSegmentationEventHandlers', () => {
|
||||
unsubscribeSelectedSegmentationsForViewportEvents:
|
||||
mockUnsubscribeSelectedSegmentationsForViewportEvents,
|
||||
});
|
||||
mockSegmentationService.subscribe.mockImplementation((eventName: string) => {
|
||||
if (eventName === mockSegmentationService.EVENTS.SEGMENTATION_ADDED) {
|
||||
return { unsubscribe: mockUnsubscribeCreated };
|
||||
}
|
||||
if (eventName === mockSegmentationService.EVENTS.SEGMENTATION_REMOVED) {
|
||||
return { unsubscribe: mockUnsubscribeRemoved };
|
||||
}
|
||||
return { unsubscribe: jest.fn() };
|
||||
mockSegmentationService.subscribe.mockReturnValue({
|
||||
unsubscribe: mockUnsubscribeCreated,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -107,7 +99,6 @@ describe('setUpSegmentationEventHandlers', () => {
|
||||
mockUnsubscribeDataModified,
|
||||
mockUnsubscribeModified,
|
||||
mockUnsubscribeCreated,
|
||||
mockUnsubscribeRemoved,
|
||||
...mockUnsubscribeSelectedSegmentationsForViewportEvents,
|
||||
],
|
||||
});
|
||||
@@ -367,6 +358,5 @@ describe('setUpSegmentationEventHandlers', () => {
|
||||
expect(mockUnsubscribeDataModified).toHaveBeenCalled();
|
||||
expect(mockUnsubscribeModified).toHaveBeenCalled();
|
||||
expect(mockUnsubscribeCreated).toHaveBeenCalled();
|
||||
expect(mockUnsubscribeRemoved).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -7,8 +7,7 @@ import {
|
||||
} from './segmentationHandlers';
|
||||
|
||||
export const setUpSegmentationEventHandlers = ({ servicesManager, commandsManager }) => {
|
||||
const { segmentationService, customizationService, displaySetService, viewportGridService } =
|
||||
servicesManager.services;
|
||||
const { segmentationService, customizationService, displaySetService } = servicesManager.services;
|
||||
|
||||
const { unsubscribe: unsubscribeSegmentationDataModifiedHandler } =
|
||||
setupSegmentationDataModifiedHandler({
|
||||
@@ -58,36 +57,6 @@ export const setUpSegmentationEventHandlers = ({ servicesManager, commandsManage
|
||||
}
|
||||
);
|
||||
|
||||
const { unsubscribe: unsubscribeSegmentationRemoved } = segmentationService.subscribe(
|
||||
segmentationService.EVENTS.SEGMENTATION_REMOVED,
|
||||
({ segmentationId }) => {
|
||||
const displaySet = displaySetService.getDisplaySetByUID(segmentationId);
|
||||
|
||||
// Remove the display set layer from all viewports that have it
|
||||
if (displaySet) {
|
||||
const state = viewportGridService.getState();
|
||||
const viewports = state.viewports;
|
||||
|
||||
// Find all viewports that contain this segmentation's display set as a layer
|
||||
for (const [viewportId, viewport] of viewports.entries()) {
|
||||
const displaySetInstanceUIDs = viewport.displaySetInstanceUIDs || [];
|
||||
if (displaySetInstanceUIDs.includes(segmentationId)) {
|
||||
// Remove the display set layer from this viewport
|
||||
commandsManager.runCommand('removeDisplaySetLayer', {
|
||||
viewportId,
|
||||
displaySetInstanceUID: segmentationId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Delete the display set from the service if it was made in client
|
||||
if (displaySet.madeInClient) {
|
||||
displaySetService.deleteDisplaySet(segmentationId);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const { unsubscribeSelectedSegmentationsForViewportEvents } =
|
||||
setUpSelectedSegmentationsForViewportHandler({
|
||||
segmentationService,
|
||||
@@ -97,7 +66,6 @@ export const setUpSegmentationEventHandlers = ({ servicesManager, commandsManage
|
||||
unsubscribeSegmentationDataModifiedHandler,
|
||||
unsubscribeSegmentationModifiedHandler,
|
||||
unsubscribeSegmentationCreated,
|
||||
unsubscribeSegmentationRemoved,
|
||||
...unsubscribeSelectedSegmentationsForViewportEvents,
|
||||
];
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [3.13.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.53...v3.13.0-beta.54) (2026-04-08)
|
||||
## [3.12.2](https://github.com/OHIF/Viewers/compare/v3.12.1...v3.12.2) (2026-05-18)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
@@ -11,464 +11,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.52...v3.13.0-beta.53) (2026-04-06)
|
||||
|
||||
|
||||
### Reverts
|
||||
|
||||
* rename DisplaySet.frameOfReferenceUID back to FrameOfReferenceUID ([#5943](https://github.com/OHIF/Viewers/issues/5943)) ([0e933c2](https://github.com/OHIF/Viewers/commit/0e933c256e07b7cda35ed2ba3cfb1ab35d895d57))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.51...v3.13.0-beta.52) (2026-04-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.50...v3.13.0-beta.51) (2026-04-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.49...v3.13.0-beta.50) (2026-04-02)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.48...v3.13.0-beta.49) (2026-04-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation:** restrict overlay segmentation menu to same frame of reference as viewport background display set ([#5900](https://github.com/OHIF/Viewers/issues/5900)) ([b9029ef](https://github.com/OHIF/Viewers/commit/b9029ef6f8d63a0e36ec929310c1c5ad3f563ef8))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.47...v3.13.0-beta.48) (2026-04-01)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.46...v3.13.0-beta.47) (2026-03-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* prevent black viewport when navigating series with client-created segmentation ([#5919](https://github.com/OHIF/Viewers/issues/5919)) ([e66fb5a](https://github.com/OHIF/Viewers/commit/e66fb5a2b8c93a60ea20d315f73def7a02ea205f))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.45...v3.13.0-beta.46) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.44...v3.13.0-beta.45) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.43...v3.13.0-beta.44) (2026-03-27)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.42...v3.13.0-beta.43) (2026-03-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **SR:** Added support for spline and live wire SR items. ([#5870](https://github.com/OHIF/Viewers/issues/5870)) ([1d4802c](https://github.com/OHIF/Viewers/commit/1d4802c2a38dd75dca7afca87913e100453c9135))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.41...v3.13.0-beta.42) (2026-03-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.40...v3.13.0-beta.41) (2026-03-16)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.39...v3.13.0-beta.40) (2026-03-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.38...v3.13.0-beta.39) (2026-03-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.37...v3.13.0-beta.38) (2026-03-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.36...v3.13.0-beta.37) (2026-03-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.35...v3.13.0-beta.36) (2026-03-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.34...v3.13.0-beta.35) (2026-03-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.33...v3.13.0-beta.34) (2026-03-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.32...v3.13.0-beta.33) (2026-03-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.31...v3.13.0-beta.32) (2026-03-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.30...v3.13.0-beta.31) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.29...v3.13.0-beta.30) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.28...v3.13.0-beta.29) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.27...v3.13.0-beta.28) (2026-03-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.26...v3.13.0-beta.27) (2026-03-02)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.25...v3.13.0-beta.26) (2026-02-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.24...v3.13.0-beta.25) (2026-02-26)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.23...v3.13.0-beta.24) (2026-02-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* prevent viewer crash when opening DICOM Tag Browser from empty viewport ([#5827](https://github.com/OHIF/Viewers/issues/5827)) ([d11d6d4](https://github.com/OHIF/Viewers/commit/d11d6d401bc92a3870ec1089d97235b01a6b27c3))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.22...v3.13.0-beta.23) (2026-02-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* palette color 8 encoded 16 ([#5823](https://github.com/OHIF/Viewers/issues/5823)) ([eeca1f7](https://github.com/OHIF/Viewers/commit/eeca1f7a7b529d1700f5d281a6fd98074547ffe9)), closes [#5813](https://github.com/OHIF/Viewers/issues/5813)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.21...v3.13.0-beta.22) (2026-02-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.20...v3.13.0-beta.21) (2026-02-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.19...v3.13.0-beta.20) (2026-02-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.18...v3.13.0-beta.19) (2026-02-20)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.17...v3.13.0-beta.18) (2026-02-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation overlay:** update viewport ds list upon seg delete - OHIF-2425 ([#5729](https://github.com/OHIF/Viewers/issues/5729)) ([b353541](https://github.com/OHIF/Viewers/commit/b35354120a01d89b27844f967c32c052bba8b096))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.16...v3.13.0-beta.17) (2026-02-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.15...v3.13.0-beta.16) (2026-02-18)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.14...v3.13.0-beta.15) (2026-02-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **dicom-tag-browser:** Prevent long series names from overlapping - OHIF-2406 ([#5809](https://github.com/OHIF/Viewers/issues/5809)) ([cca1a86](https://github.com/OHIF/Viewers/commit/cca1a8683bc7d392a3a07268f24585642d13b1cd))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.13...v3.13.0-beta.14) (2026-02-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.12...v3.13.0-beta.13) (2026-02-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **colors:** Replace hardcoded black with background color token ([#5815](https://github.com/OHIF/Viewers/issues/5815)) ([dbc31a5](https://github.com/OHIF/Viewers/commit/dbc31a5d4ec5b2238683a580af96aff23d9fafeb))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.11...v3.13.0-beta.12) (2026-02-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.10...v3.13.0-beta.11) (2026-02-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **colors:** Replaces legacy colors with ui-next colors ([#5351](https://github.com/OHIF/Viewers/issues/5351)) ([9a2691a](https://github.com/OHIF/Viewers/commit/9a2691a71fe3723bb05cbd148968b64e5d0fa951))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.9...v3.13.0-beta.10) (2026-02-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.9) (2026-02-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.8) (2026-02-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.6...v3.13.0-beta.7) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.5...v3.13.0-beta.6) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.4...v3.13.0-beta.5) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.3...v3.13.0-beta.4) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.2...v3.13.0-beta.3) (2026-02-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **app:** display study not found message for all modes ([#5752](https://github.com/OHIF/Viewers/issues/5752)) ([7f9e59e](https://github.com/OHIF/Viewers/commit/7f9e59ee3074e3511d22c7f0075856a7bd2cc32e))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.1...v3.13.0-beta.2) (2026-02-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.13.0-beta.0...v3.13.0-beta.1) (2026-02-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.13.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.135...v3.13.0-beta.0) (2026-02-07)
|
||||
# [3.12.0](https://github.com/OHIF/Viewers/compare/v3.12.0-beta.135...v3.12.0) (2026-02-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-default",
|
||||
"version": "3.13.0-beta.54",
|
||||
"version": "3.12.2",
|
||||
"description": "Common/default features and functionality for basic image viewing",
|
||||
"author": "OHIF Core Team",
|
||||
"license": "MIT",
|
||||
@@ -34,8 +34,8 @@
|
||||
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.13.0-beta.54",
|
||||
"@ohif/i18n": "3.13.0-beta.54",
|
||||
"@ohif/core": "3.12.2",
|
||||
"@ohif/i18n": "3.12.2",
|
||||
"dcmjs": "0.49.4",
|
||||
"dicomweb-client": "0.10.4",
|
||||
"prop-types": "15.8.1",
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { DicomMetadataStore } from '@ohif/core';
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} servicesManager
|
||||
@@ -5,8 +7,7 @@
|
||||
async function createReportAsync({
|
||||
servicesManager,
|
||||
getReport,
|
||||
reportType = 'Measurements',
|
||||
successMessage,
|
||||
reportType = 'measurement',
|
||||
}: withAppTypes) {
|
||||
const { displaySetService, uiNotificationService, uiDialogService } = servicesManager.services;
|
||||
|
||||
@@ -17,15 +18,18 @@ async function createReportAsync({
|
||||
return;
|
||||
}
|
||||
|
||||
// addInstances is called by the store command (storeMeasurements/storeSegmentation),
|
||||
// so the display set should already exist at this point.
|
||||
// The "Mode" route listens for DicomMetadataStore changes
|
||||
// When a new instance is added, it listens and
|
||||
// automatically calls makeDisplaySets
|
||||
DicomMetadataStore.addInstances([naturalizedReport], true);
|
||||
|
||||
const displaySet = displaySetService.getMostRecentDisplaySet();
|
||||
|
||||
const displaySetInstanceUID = displaySet.displaySetInstanceUID;
|
||||
|
||||
uiNotificationService.show({
|
||||
title: 'Create Report',
|
||||
message: successMessage ?? `${reportType} saved successfully`,
|
||||
message: `${reportType} saved successfully`,
|
||||
type: 'success',
|
||||
});
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ function DataSourceConfigurationComponent({
|
||||
}, [configurationAPI, configuredItems, showConfigurationModal]);
|
||||
|
||||
return configuredItems ? (
|
||||
<div className="text-muted-foreground flex items-center overflow-hidden">
|
||||
<div className="text-aqua-pale flex items-center overflow-hidden">
|
||||
<Icons.Settings
|
||||
className="mr-2.5 h-3.5 w-3.5 shrink-0 cursor-pointer"
|
||||
onClick={showConfigurationModal}
|
||||
|
||||
@@ -100,28 +100,28 @@ function DataSourceConfigurationModalComponent({
|
||||
const getSelectedItemBackgroundClasses = itemIndex =>
|
||||
itemIndex < selectedItems.length
|
||||
? classNames(
|
||||
'bg-background/[.4]',
|
||||
itemIndex !== itemLabels.length - 1 ? 'hover:bg-transparent active:bg-popover' : ''
|
||||
'bg-black/[.4]',
|
||||
itemIndex !== itemLabels.length - 1 ? 'hover:bg-transparent active:bg-secondary-dark' : ''
|
||||
)
|
||||
: 'bg-transparent';
|
||||
|
||||
const getSelectedItemBorderClasses = itemIndex =>
|
||||
itemIndex === currentSelectedItemIndex + 1
|
||||
? classNames('border-2', 'border-solid', 'border-highlight')
|
||||
? classNames('border-2', 'border-solid', 'border-primary-light')
|
||||
: itemIndex < selectedItems.length
|
||||
? 'border border-solid border-primary hover:border-highlight active:border-white'
|
||||
: 'border border-dashed border-input';
|
||||
? 'border border-solid border-primary-active hover:border-primary-light active:border-white'
|
||||
: 'border border-dashed border-secondary-light';
|
||||
|
||||
const getSelectedItemTextClasses = itemIndex =>
|
||||
itemIndex <= selectedItems.length ? 'text-highlight' : 'text-primary';
|
||||
itemIndex <= selectedItems.length ? 'text-primary-light' : 'text-primary';
|
||||
|
||||
const getErrorComponent = (): ReactElement => {
|
||||
return (
|
||||
<div className="flex min-h-[1px] grow flex-col gap-4">
|
||||
<div className="text-highlight text-[20px]">
|
||||
<div className="text-primary-light text-[20px]">
|
||||
{t(`Error fetching ${itemLabels[selectedItems.length]} list`)}
|
||||
</div>
|
||||
<div className="grow bg-background p-4 text-[14px]">{errorMessage}</div>
|
||||
<div className="grow bg-black p-4 text-[14px]">{errorMessage}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -159,12 +159,7 @@ function DataSourceConfigurationModalComponent({
|
||||
<div className={classNames(NO_WRAP_ELLIPSIS_CLASS_NAMES)}>{t(itemLabel)}</div>
|
||||
</div>
|
||||
{itemLabelIndex < selectedItems.length ? (
|
||||
<div
|
||||
className={classNames(
|
||||
'text-foreground text-[14px]',
|
||||
NO_WRAP_ELLIPSIS_CLASS_NAMES
|
||||
)}
|
||||
>
|
||||
<div className={classNames('text-[14px] text-white', NO_WRAP_ELLIPSIS_CLASS_NAMES)}>
|
||||
{selectedItems[itemLabelIndex].name}
|
||||
</div>
|
||||
) : (
|
||||
@@ -180,7 +175,7 @@ function DataSourceConfigurationModalComponent({
|
||||
return (
|
||||
<div className="flex h-[calc(100vh-300px)] select-none flex-col gap-4 pt-0.5">
|
||||
{getSelectedItemsComponent()}
|
||||
<div className="h-0.5 w-full shrink-0 bg-background"></div>
|
||||
<div className="h-0.5 w-full shrink-0 bg-black"></div>
|
||||
{errorMessage ? (
|
||||
getErrorComponent()
|
||||
) : (
|
||||
|
||||
@@ -44,7 +44,7 @@ function ItemListComponent({
|
||||
<InputFilter.ClearButton className="text-primary mr-0.5 p-0.5" />
|
||||
</InputFilter>
|
||||
</div>
|
||||
<div className="relative flex min-h-[1px] grow flex-col bg-background text-[14px]">
|
||||
<div className="relative flex min-h-[1px] grow flex-col bg-black text-[14px]">
|
||||
{itemList == null ? (
|
||||
<LoadingIndicatorProgress className={'h-full w-full'} />
|
||||
) : itemList.length === 0 ? (
|
||||
|
||||
@@ -4,6 +4,7 @@ import qs from 'query-string';
|
||||
|
||||
import getImageId from '../DicomWebDataSource/utils/getImageId';
|
||||
import getDirectURL from '../utils/getDirectURL';
|
||||
import { resolveConfigFetchPolicy, fetchConfigJson } from '../utils/secureConfigFetch';
|
||||
|
||||
const metadataProvider = OHIF.classes.MetadataProvider;
|
||||
|
||||
@@ -59,13 +60,18 @@ const findStudies = (key, value) => {
|
||||
return studies;
|
||||
};
|
||||
|
||||
function createDicomJSONApi(dicomJsonConfig) {
|
||||
function createDicomJSONApi(dicomJsonConfig, servicesManager) {
|
||||
const { userAuthenticationService } = servicesManager.services;
|
||||
const implementation = {
|
||||
initialize: async ({ query, url }) => {
|
||||
if (!url) {
|
||||
url = query.get('url');
|
||||
}
|
||||
let metaData = getMetaDataByURL(url);
|
||||
const evaluatedUrl = resolveConfigFetchPolicy(url, {
|
||||
allowedOrigins: dicomJsonConfig.dangerouslyAllowedOriginsForAuthenticatedEnvironments,
|
||||
userAuthenticationService,
|
||||
});
|
||||
let metaData = getMetaDataByURL(evaluatedUrl.normalizedUrl);
|
||||
|
||||
// if we have already cached the data from this specific url
|
||||
// We are only handling one StudyInstanceUID to run; however,
|
||||
@@ -76,8 +82,7 @@ function createDicomJSONApi(dicomJsonConfig) {
|
||||
});
|
||||
}
|
||||
|
||||
const response = await fetch(url);
|
||||
const data = await response.json();
|
||||
const data = await fetchConfigJson(evaluatedUrl);
|
||||
|
||||
let StudyInstanceUID;
|
||||
let SeriesInstanceUID;
|
||||
@@ -105,11 +110,11 @@ function createDicomJSONApi(dicomJsonConfig) {
|
||||
});
|
||||
|
||||
_store.urls.push({
|
||||
url,
|
||||
url: evaluatedUrl.normalizedUrl,
|
||||
studies: [...data.studies],
|
||||
});
|
||||
_store.studyInstanceUIDMap.set(
|
||||
url,
|
||||
evaluatedUrl.normalizedUrl,
|
||||
data.studies.map(study => study.StudyInstanceUID)
|
||||
);
|
||||
},
|
||||
@@ -252,6 +257,8 @@ function createDicomJSONApi(dicomJsonConfig) {
|
||||
console.warn(' DICOMJson store dicom not implemented');
|
||||
},
|
||||
},
|
||||
reject: {},
|
||||
deleteStudyMetadataPromise: () => {},
|
||||
getImageIdsForDisplaySet(displaySet) {
|
||||
const images = displaySet.images;
|
||||
const imageIds = [];
|
||||
@@ -297,8 +304,21 @@ function createDicomJSONApi(dicomJsonConfig) {
|
||||
},
|
||||
getStudyInstanceUIDs: ({ params, query }) => {
|
||||
const url = query.get('url');
|
||||
return _store.studyInstanceUIDMap.get(url);
|
||||
if (!url) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const evaluatedUrl = resolveConfigFetchPolicy(url, {
|
||||
allowedOrigins: dicomJsonConfig.dangerouslyAllowedOriginsForAuthenticatedEnvironments,
|
||||
userAuthenticationService,
|
||||
});
|
||||
return _store.studyInstanceUIDMap.get(evaluatedUrl.normalizedUrl);
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
},
|
||||
getConfig: () => dicomJsonConfig,
|
||||
};
|
||||
return IWebApiDataSource.create(implementation);
|
||||
}
|
||||
|
||||
@@ -3,14 +3,7 @@ import moment from 'moment';
|
||||
import React, { useState, useMemo, useCallback } from 'react';
|
||||
import { classes, Types } from '@ohif/core';
|
||||
import { InputFilter } from '@ohif/ui-next';
|
||||
import {
|
||||
Select,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
Slider,
|
||||
} from '@ohif/ui-next';
|
||||
import { Select, SelectTrigger, SelectContent, SelectItem, Slider } from '@ohif/ui-next';
|
||||
|
||||
import DicomTagTable from './DicomTagTable';
|
||||
import './DicomTagBrowser.css';
|
||||
@@ -133,7 +126,7 @@ const DicomTagBrowser = ({
|
||||
return (
|
||||
<div className="dicom-tag-browser-content bg-muted">
|
||||
<div className="mb-6 flex flex-row items-start pl-1">
|
||||
<div className="flex w-full flex-row items-start gap-6">
|
||||
<div className="flex w-full flex-row items-start gap-4">
|
||||
<div className="flex w-1/3 flex-col">
|
||||
<span className="text-muted-foreground flex h-6 items-center pb-2 text-base">
|
||||
Series
|
||||
@@ -142,11 +135,9 @@ const DicomTagBrowser = ({
|
||||
value={selectedDisplaySetInstanceUID}
|
||||
onValueChange={value => onSelectChange({ value })}
|
||||
>
|
||||
<SelectTrigger data-cy="dicom-tag-series-select-trigger">
|
||||
<SelectValue data-cy="dicom-tag-series-select-value">
|
||||
{displaySetList.find(ds => ds.value === selectedDisplaySetInstanceUID)?.label ||
|
||||
'Select Series'}
|
||||
</SelectValue>
|
||||
<SelectTrigger>
|
||||
{displaySetList.find(ds => ds.value === selectedDisplaySetInstanceUID)?.label ||
|
||||
'Select Series'}
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{displaySetList.map(item => {
|
||||
@@ -176,7 +167,7 @@ const DicomTagBrowser = ({
|
||||
min={1}
|
||||
max={activeDisplaySet?.images?.length}
|
||||
step={1}
|
||||
className="pt-3"
|
||||
className="pt-4"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -39,7 +39,7 @@ const RowComponent = ({
|
||||
<div
|
||||
style={{ ...style, ...rowStyle }}
|
||||
className={classNames(
|
||||
'hover:bg-primary/25 border-input text-foreground flex w-full flex-row items-center break-all bg-background text-base',
|
||||
'hover:bg-secondary-main border-secondary-light text-foreground flex w-full flex-row items-center break-all bg-black text-base transition duration-300',
|
||||
lineHeightClassName
|
||||
)}
|
||||
key={keyPrefix}
|
||||
@@ -74,13 +74,15 @@ const RowComponent = ({
|
||||
function ColumnHeaders({ tagRef, vrRef, keywordRef, valueRef }) {
|
||||
return (
|
||||
<div
|
||||
className={classNames('bg-popover ohif-scrollbar flex w-full flex-row overflow-y-scroll')}
|
||||
className={classNames(
|
||||
'bg-secondary-dark ohif-scrollbar flex w-full flex-row overflow-y-scroll'
|
||||
)}
|
||||
style={rowVerticalPaddingStyle}
|
||||
>
|
||||
<div className="w-4/24 px-3">
|
||||
<label
|
||||
ref={tagRef}
|
||||
className="text-foreground flex flex-1 select-none flex-col pl-1 text-lg"
|
||||
className="flex flex-1 select-none flex-col pl-1 text-lg text-white"
|
||||
>
|
||||
<span className="flex flex-row items-center focus:outline-none">Tag</span>
|
||||
</label>
|
||||
@@ -88,7 +90,7 @@ function ColumnHeaders({ tagRef, vrRef, keywordRef, valueRef }) {
|
||||
<div className="w-2/24 px-3">
|
||||
<label
|
||||
ref={vrRef}
|
||||
className="text-foreground flex flex-1 select-none flex-col pl-1 text-lg"
|
||||
className="flex flex-1 select-none flex-col pl-1 text-lg text-white"
|
||||
>
|
||||
<span className="flex flex-row items-center focus:outline-none">VR</span>
|
||||
</label>
|
||||
@@ -96,7 +98,7 @@ function ColumnHeaders({ tagRef, vrRef, keywordRef, valueRef }) {
|
||||
<div className="w-6/24 px-3">
|
||||
<label
|
||||
ref={keywordRef}
|
||||
className="text-foreground flex flex-1 select-none flex-col pl-1 text-lg"
|
||||
className="flex flex-1 select-none flex-col pl-1 text-lg text-white"
|
||||
>
|
||||
<span className="flex flex-row items-center focus:outline-none">Keyword</span>
|
||||
</label>
|
||||
@@ -104,7 +106,7 @@ function ColumnHeaders({ tagRef, vrRef, keywordRef, valueRef }) {
|
||||
<div className="w-5/24 grow px-3">
|
||||
<label
|
||||
ref={valueRef}
|
||||
className="text-foreground flex flex-1 select-none flex-col pl-1 text-lg"
|
||||
className="flex flex-1 select-none flex-col pl-1 text-lg text-white"
|
||||
>
|
||||
<span className="flex flex-row items-center focus:outline-none">Value</span>
|
||||
</label>
|
||||
@@ -281,7 +283,7 @@ function DicomTagTable({ rows }: { rows: Row[] }) {
|
||||
valueRef={valueRef}
|
||||
/>
|
||||
<div
|
||||
className="relative m-auto border-2 border-background bg-background"
|
||||
className="relative m-auto border-2 border-black bg-black"
|
||||
style={{ height: '32rem' }}
|
||||
>
|
||||
{isHeaderRendered() && (
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { IWebApiDataSource } from '@ohif/core';
|
||||
import { createDicomWebApi } from '../DicomWebDataSource/index';
|
||||
import { resolveConfigFetchPolicy, fetchConfigJson } from '../utils/secureConfigFetch';
|
||||
|
||||
/**
|
||||
* This datasource is initialized with a url that returns a JSON object with a
|
||||
@@ -11,6 +12,7 @@ import { createDicomWebApi } from '../DicomWebDataSource/index';
|
||||
*/
|
||||
function createDicomWebProxyApi(dicomWebProxyConfig, servicesManager: AppTypes.ServicesManager) {
|
||||
const { name } = dicomWebProxyConfig;
|
||||
const { userAuthenticationService } = servicesManager.services;
|
||||
let dicomWebDelegate = undefined;
|
||||
|
||||
const implementation = {
|
||||
@@ -20,12 +22,14 @@ function createDicomWebProxyApi(dicomWebProxyConfig, servicesManager: AppTypes.S
|
||||
if (!url) {
|
||||
throw new Error(`No url for '${name}'`);
|
||||
} else {
|
||||
const response = await fetch(url);
|
||||
const data = await response.json();
|
||||
const evaluatedUrl = resolveConfigFetchPolicy(url, {
|
||||
allowedOrigins: dicomWebProxyConfig.dangerouslyAllowedOriginsForAuthenticatedEnvironments,
|
||||
userAuthenticationService,
|
||||
});
|
||||
const data = await fetchConfigJson(evaluatedUrl);
|
||||
if (!data.servers?.dicomWeb?.[0]) {
|
||||
throw new Error('Invalid configuration returned by url');
|
||||
}
|
||||
|
||||
dicomWebDelegate = createDicomWebApi(
|
||||
data.servers.dicomWeb[0].configuration || data.servers.dicomWeb[0],
|
||||
servicesManager
|
||||
@@ -54,9 +58,16 @@ function createDicomWebProxyApi(dicomWebProxyConfig, servicesManager: AppTypes.S
|
||||
store: {
|
||||
dicom: (...args) => dicomWebDelegate.store.dicom(...args),
|
||||
},
|
||||
deleteStudyMetadataPromise: (...args) => dicomWebDelegate.deleteStudyMetadataPromise(...args),
|
||||
getImageIdsForDisplaySet: (...args) => dicomWebDelegate.getImageIdsForDisplaySet(...args),
|
||||
getImageIdsForInstance: (...args) => dicomWebDelegate.getImageIdsForInstance(...args),
|
||||
reject: {
|
||||
series: (...args) => dicomWebDelegate?.reject?.series?.(...args),
|
||||
},
|
||||
deleteStudyMetadataPromise: (...args) => dicomWebDelegate?.deleteStudyMetadataPromise?.(...args),
|
||||
getImageIdsForDisplaySet: (...args) => dicomWebDelegate?.getImageIdsForDisplaySet?.(...args),
|
||||
getImageIdsForInstance: (...args) => dicomWebDelegate?.getImageIdsForInstance?.(...args),
|
||||
getConfig: (...args) =>
|
||||
dicomWebDelegate?.getConfig?.(...args) ?? {
|
||||
dicomUploadEnabled: false,
|
||||
},
|
||||
getStudyInstanceUIDs({ params, query }) {
|
||||
let studyInstanceUIDs = [];
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ function DataSourceSelector() {
|
||||
return (
|
||||
<div style={{ width: '100%', height: '100%' }}>
|
||||
<div className="flex h-screen w-screen items-center justify-center">
|
||||
<div className="bg-popover mx-auto space-y-2 rounded-lg py-8 px-8 drop-shadow-md">
|
||||
<div className="bg-secondary-dark mx-auto space-y-2 rounded-lg py-8 px-8 drop-shadow-md">
|
||||
<img
|
||||
className="mx-auto block h-14"
|
||||
src="./ohif-logo.svg"
|
||||
@@ -27,7 +27,7 @@ function DataSourceSelector() {
|
||||
.filter(it => it.sourceName !== 'dicomjson' && it.sourceName !== 'dicomlocal')
|
||||
.map(ds => (
|
||||
<div key={ds.sourceName}>
|
||||
<h1 className="text-foreground">
|
||||
<h1 className="text-white">
|
||||
{ds.configuration?.friendlyName || ds.friendlyName}
|
||||
</h1>
|
||||
<Button
|
||||
|
||||
@@ -87,7 +87,7 @@ function PanelStudyBrowser({
|
||||
commandsManager,
|
||||
servicesManager,
|
||||
isHangingProtocolLayout,
|
||||
appConfig: extensionManager.appConfig,
|
||||
appConfig: extensionManager._appConfig,
|
||||
};
|
||||
|
||||
const handlers = customHandler?.callbacks.map(callback => callback(setupArgs));
|
||||
@@ -122,6 +122,11 @@ function PanelStudyBrowser({
|
||||
studyInstanceUid: StudyInstanceUID,
|
||||
});
|
||||
|
||||
if (!qidoForStudyUID?.length) {
|
||||
navigate('/notfoundstudy', '_self');
|
||||
throw new Error('Invalid study URL');
|
||||
}
|
||||
|
||||
let qidoStudiesForPatient = qidoForStudyUID;
|
||||
|
||||
// try to fetch the prior studies based on the patientID if the
|
||||
@@ -410,7 +415,7 @@ function PanelStudyBrowser({
|
||||
/>
|
||||
<Separator
|
||||
orientation="horizontal"
|
||||
className="bg-background"
|
||||
className="bg-black"
|
||||
thickness="2px"
|
||||
/>
|
||||
</>
|
||||
|
||||
@@ -45,7 +45,7 @@ function PanelStudyBrowserHeader({
|
||||
key={index}
|
||||
aria-label={viewPreset.id}
|
||||
value={viewPreset.id}
|
||||
className="text-primary"
|
||||
className="text-actions-primary"
|
||||
>
|
||||
{React.createElement(Icons[viewPreset.iconName] || Icons.MissingIcon)}
|
||||
</ToggleGroupItem>
|
||||
|
||||
@@ -30,7 +30,6 @@ export default function CreateReportDialogPrompt({
|
||||
predecessorImageId,
|
||||
extensionManager,
|
||||
servicesManager,
|
||||
enableDownload = false,
|
||||
}): Promise<{
|
||||
value: string;
|
||||
dataSourceName: string;
|
||||
@@ -60,7 +59,6 @@ export default function CreateReportDialogPrompt({
|
||||
predecessorImageId,
|
||||
minSeriesNumber,
|
||||
modality,
|
||||
enableDownload,
|
||||
onSave: async ({
|
||||
reportName,
|
||||
dataSource: selectedDataSource,
|
||||
|
||||
@@ -176,7 +176,7 @@ function ToolbarLayoutSelectorWithServices({
|
||||
)}
|
||||
|
||||
{/* Right Side - Grid Layout */}
|
||||
<div className="bg-muted flex flex-col gap-2.5 border-l-2 border-solid border-background p-2">
|
||||
<div className="bg-muted flex flex-col gap-2.5 border-l-2 border-solid border-black p-2">
|
||||
<div className="text-muted-foreground text-xs">{t('Custom')}</div>
|
||||
<LayoutSelector.GridSelector
|
||||
rows={rows}
|
||||
|
||||
@@ -40,7 +40,7 @@ function HeaderPatientInfo({ servicesManager, appConfig }: withAppTypes) {
|
||||
|
||||
return (
|
||||
<div
|
||||
className="hover:bg-muted flex cursor-pointer items-center justify-center gap-1 rounded-lg"
|
||||
className="hover:bg-primary-dark flex cursor-pointer items-center justify-center gap-1 rounded-lg"
|
||||
onClick={handleOnClick}
|
||||
>
|
||||
{isMixedPatients ? (
|
||||
@@ -51,10 +51,10 @@ function HeaderPatientInfo({ servicesManager, appConfig }: withAppTypes) {
|
||||
<div className="flex flex-col justify-center">
|
||||
{expanded ? (
|
||||
<>
|
||||
<div className="text-foreground self-start text-[13px] font-bold">
|
||||
<div className="self-start text-[13px] font-bold text-white">
|
||||
{formattedPatientName}
|
||||
</div>
|
||||
<div className="text-muted-foreground flex gap-2 text-[11px]">
|
||||
<div className="text-aqua-pale flex gap-2 text-[11px]">
|
||||
<div>{formattedPatientID}</div>
|
||||
<div>{patientInfo.PatientSex}</div>
|
||||
<div>{patientInfo.PatientDOB}</div>
|
||||
|
||||
@@ -100,7 +100,7 @@ function ViewerHeader({ appConfig }: withAppTypes<{ appConfig: AppTypes.Config }
|
||||
<div className="text-primary flex cursor-pointer items-center">
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="hover:bg-muted"
|
||||
className="hover:bg-primary-dark"
|
||||
onClick={() => {
|
||||
commandsManager.run('undo');
|
||||
}}
|
||||
@@ -109,7 +109,7 @@ function ViewerHeader({ appConfig }: withAppTypes<{ appConfig: AppTypes.Config }
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="hover:bg-muted"
|
||||
className="hover:bg-primary-dark"
|
||||
onClick={() => {
|
||||
commandsManager.run('redo');
|
||||
}}
|
||||
|
||||
@@ -9,7 +9,7 @@ import SidePanelWithServices from '../Components/SidePanelWithServices';
|
||||
import { Onboarding, ResizablePanelGroup, ResizablePanel, ResizableHandle } from '@ohif/ui-next';
|
||||
import useResizablePanels from './ResizablePanelsHook';
|
||||
|
||||
const resizableHandleClassName = 'mt-[1px] bg-background';
|
||||
const resizableHandleClassName = 'mt-[1px] bg-black';
|
||||
|
||||
function ViewerLayout({
|
||||
// From Extension Module Params
|
||||
@@ -79,11 +79,11 @@ function ViewerLayout({
|
||||
* is sized to our viewport.
|
||||
*/
|
||||
useEffect(() => {
|
||||
document.body.classList.add('bg-background');
|
||||
document.body.classList.add('bg-black');
|
||||
document.body.classList.add('overflow-hidden');
|
||||
|
||||
return () => {
|
||||
document.body.classList.remove('bg-background');
|
||||
document.body.classList.remove('bg-black');
|
||||
document.body.classList.remove('overflow-hidden');
|
||||
};
|
||||
}, []);
|
||||
@@ -158,11 +158,11 @@ function ViewerLayout({
|
||||
appConfig={appConfig}
|
||||
/>
|
||||
<div
|
||||
className="relative flex w-full flex-row flex-nowrap items-stretch overflow-hidden bg-background"
|
||||
className="relative flex w-full flex-row flex-nowrap items-stretch overflow-hidden bg-black"
|
||||
style={{ height: 'calc(100vh - 52px' }}
|
||||
>
|
||||
<React.Fragment>
|
||||
{showLoadingIndicator && <LoadingIndicatorProgress className="h-full w-full bg-background" />}
|
||||
{showLoadingIndicator && <LoadingIndicatorProgress className="h-full w-full bg-black" />}
|
||||
<ResizablePanelGroup {...resizablePanelGroupProps}>
|
||||
{/* LEFT SIDEPANELS */}
|
||||
{hasLeftPanels ? (
|
||||
@@ -186,7 +186,7 @@ function ViewerLayout({
|
||||
<ResizablePanel {...resizableViewportGridPanelProps}>
|
||||
<div className="flex h-full flex-1 flex-col">
|
||||
<div
|
||||
className="relative flex h-full flex-1 items-center justify-center overflow-hidden bg-background"
|
||||
className="relative flex h-full flex-1 items-center justify-center overflow-hidden bg-black"
|
||||
onMouseEnter={handleMouseEnter}
|
||||
>
|
||||
<ViewportGridComp
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import { Types, DicomMetadataStore, utils } from '@ohif/core';
|
||||
import dcmjs from 'dcmjs';
|
||||
|
||||
const { downloadBlob } = utils;
|
||||
import { Types, DicomMetadataStore } from '@ohif/core';
|
||||
|
||||
import { ContextMenuController } from './CustomizableContextMenu';
|
||||
import DicomTagBrowser from './DicomTagBrowser/DicomTagBrowser';
|
||||
@@ -69,8 +66,8 @@ const commandsModule = ({
|
||||
*/
|
||||
addDisplaySetAsLayer: ({ viewportId, displaySetInstanceUID, removeFirst = false }) => {
|
||||
if (!viewportId) {
|
||||
const { activeViewportId } = servicesManager.services.viewportGridService.getState();
|
||||
viewportId = activeViewportId;
|
||||
const { activeViewportId } = servicesManager.services.viewportGridService.getState();
|
||||
viewportId = activeViewportId;
|
||||
}
|
||||
|
||||
if (!viewportId || !displaySetInstanceUID) {
|
||||
@@ -154,19 +151,6 @@ const commandsModule = ({
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if it's a segmentation and handle accordingly.
|
||||
// Note that for the sake of hydrated segmentations, we remove the
|
||||
// segmentation before checking if the display set is indeed in the viewport.
|
||||
// This is because hydrated segmentations are not in the viewport per se
|
||||
// {i.e. they are not layered) but are simply referenced by the display
|
||||
// set in the viewport.
|
||||
const isSegmentation = DERIVED_OVERLAY_MODALITIES.includes(displaySet.Modality);
|
||||
if (isSegmentation) {
|
||||
segmentationService.removeRepresentationsFromViewport(viewportId, {
|
||||
segmentationId: displaySetInstanceUID,
|
||||
});
|
||||
}
|
||||
|
||||
// Get current display sets for the viewport
|
||||
const currentDisplaySetUIDs = viewportGridService.getDisplaySetsUIDsForViewport(viewportId);
|
||||
|
||||
@@ -175,6 +159,14 @@ const commandsModule = ({
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if it's a segmentation and handle accordingly
|
||||
const isSegmentation = DERIVED_OVERLAY_MODALITIES.includes(displaySet.Modality);
|
||||
if (isSegmentation) {
|
||||
segmentationService.removeSegmentationRepresentations(viewportId, {
|
||||
segmentationId: displaySetInstanceUID,
|
||||
});
|
||||
}
|
||||
|
||||
const updatedViewports = hangingProtocolService.getViewportsRequireUpdate(
|
||||
viewportId,
|
||||
displaySetInstanceUID
|
||||
@@ -659,9 +651,7 @@ const commandsModule = ({
|
||||
const displaySets = displaySetService.activeDisplaySets;
|
||||
const { UIModalService } = servicesManager.services;
|
||||
|
||||
const defaultDisplaySetInstanceUID =
|
||||
displaySetInstanceUID || displaySetInstanceUIDs[0] || displaySets[0]?.displaySetInstanceUID;
|
||||
|
||||
const defaultDisplaySetInstanceUID = displaySetInstanceUID || displaySetInstanceUIDs[0];
|
||||
UIModalService.show({
|
||||
content: DicomTagBrowser,
|
||||
contentProps: {
|
||||
@@ -734,11 +724,10 @@ const commandsModule = ({
|
||||
displaySetIndexToShow > -1 && displaySetIndexToShow < currentDisplaySets.length;
|
||||
displaySetIndexToShow += direction
|
||||
) {
|
||||
const nextDisplaySet = currentDisplaySets[displaySetIndexToShow];
|
||||
if (nextDisplaySet.madeInClient) {
|
||||
continue;
|
||||
}
|
||||
if (!excludeNonImageModalities || !nonImageModalities.includes(nextDisplaySet.Modality)) {
|
||||
if (
|
||||
!excludeNonImageModalities ||
|
||||
!nonImageModalities.includes(currentDisplaySets[displaySetIndexToShow].Modality)
|
||||
) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -772,67 +761,6 @@ const commandsModule = ({
|
||||
|
||||
setTimeout(() => actions.scrollActiveThumbnailIntoView(), 0);
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a store function based on the data source type.
|
||||
* @param dataSource - 'download', 'copyToClipboard', or a named data source
|
||||
* @param defaultFileName - Default filename for download/clipboard
|
||||
* @param defaultContentType - Default content type for clipboard
|
||||
* @returns A store function, or null if no valid store exists
|
||||
*/
|
||||
createStoreFunction: ({ dataSource, defaultFileName, defaultContentType }) => {
|
||||
if (dataSource === 'download') {
|
||||
return async dicom => {
|
||||
const instances = Array.isArray(dicom) ? dicom : [dicom];
|
||||
DicomMetadataStore.addInstances(instances, true);
|
||||
if (instances.length !== 1) {
|
||||
throw new Error('Download only supports a single DICOM instance');
|
||||
}
|
||||
const reportBlob = dcmjs.data.datasetToBlob(instances[0]);
|
||||
downloadBlob(reportBlob, { filename: defaultFileName || 'dicom.dcm' });
|
||||
};
|
||||
}
|
||||
|
||||
if (dataSource === 'copyToClipboard') {
|
||||
return async dicom => {
|
||||
const instances = Array.isArray(dicom) ? dicom : [dicom];
|
||||
DicomMetadataStore.addInstances(instances, true);
|
||||
if (instances.length !== 1) {
|
||||
throw new Error('Copy to clipboard only supports a single DICOM instance');
|
||||
}
|
||||
const reportBlob = dcmjs.data.datasetToBlob(instances[0]);
|
||||
const type = defaultContentType || 'application/dicom';
|
||||
await navigator.clipboard.write([
|
||||
new ClipboardItem({ [type]: new Blob([reportBlob], { type }) }),
|
||||
]);
|
||||
};
|
||||
}
|
||||
|
||||
// DICOM STOW path — resolve the named data source
|
||||
const dataSources = extensionManager.getDataSources(dataSource);
|
||||
const resolvedDataSource = dataSources?.[0];
|
||||
if (!resolvedDataSource?.store?.dicom) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return async (dicom, { dicomDict } = {}) => {
|
||||
const instances = Array.isArray(dicom) ? dicom : [dicom];
|
||||
const config = resolvedDataSource.getConfig?.();
|
||||
if (config?.wadoRoot) {
|
||||
instances.forEach(instance => {
|
||||
instance.wadoRoot = config.wadoRoot;
|
||||
});
|
||||
}
|
||||
DicomMetadataStore.addInstances(instances, true);
|
||||
for (const instance of instances) {
|
||||
await resolvedDataSource.store.dicom(instance, null, dicomDict);
|
||||
}
|
||||
const studyUIDs = new Set(instances.map(i => i.StudyInstanceUID).filter(Boolean));
|
||||
for (const uid of studyUIDs) {
|
||||
resolvedDataSource.deleteStudyMetadataPromise(uid);
|
||||
}
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
const definitions = {
|
||||
@@ -861,7 +789,6 @@ const commandsModule = ({
|
||||
scrollActiveThumbnailIntoView: actions.scrollActiveThumbnailIntoView,
|
||||
addDisplaySetAsLayer: actions.addDisplaySetAsLayer,
|
||||
removeDisplaySetLayer: actions.removeDisplaySetLayer,
|
||||
createStoreFunction: actions.createStoreFunction,
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { InputDialog } from '@ohif/ui-next';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@ohif/ui-next';
|
||||
import { useSystem } from '@ohif/core';
|
||||
@@ -22,7 +21,6 @@ type ReportDialogProps = {
|
||||
priorSeriesNumber: number;
|
||||
}) => void;
|
||||
onCancel: () => void;
|
||||
enableDownload?: boolean;
|
||||
};
|
||||
|
||||
function ReportDialog({
|
||||
@@ -33,11 +31,8 @@ function ReportDialog({
|
||||
hide,
|
||||
onSave,
|
||||
onCancel,
|
||||
enableDownload = false,
|
||||
}: ReportDialogProps) {
|
||||
const { t } = useTranslation('Buttons');
|
||||
const { servicesManager } = useSystem();
|
||||
const actionTakenRef = useRef(false);
|
||||
const [selectedDataSource, setSelectedDataSource] = useState<string | null>(
|
||||
dataSources?.[0]?.value ?? null
|
||||
);
|
||||
@@ -77,7 +72,6 @@ function ReportDialog({
|
||||
}, [selectedSeries, seriesOptions]);
|
||||
|
||||
const handleSave = useCallback(() => {
|
||||
actionTakenRef.current = true;
|
||||
onSave({
|
||||
reportName,
|
||||
dataSource: selectedDataSource,
|
||||
@@ -88,33 +82,11 @@ function ReportDialog({
|
||||
}, [selectedDataSource, selectedSeries, reportName, hide, onSave]);
|
||||
|
||||
const handleCancel = useCallback(() => {
|
||||
actionTakenRef.current = true;
|
||||
onCancel();
|
||||
hide();
|
||||
}, [onCancel, hide]);
|
||||
|
||||
const handleDownload = useCallback(() => {
|
||||
actionTakenRef.current = true;
|
||||
onSave({
|
||||
reportName,
|
||||
dataSource: 'download',
|
||||
priorSeriesNumber: Math.max(...seriesOptions.map(it => it.seriesNumber)),
|
||||
series: selectedSeries,
|
||||
});
|
||||
hide();
|
||||
}, [selectedDataSource, selectedSeries, reportName, hide, onSave]);
|
||||
|
||||
// Handles the close dialog button/external close as a cancel
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (!actionTakenRef.current) {
|
||||
onCancel();
|
||||
}
|
||||
};
|
||||
}, [onCancel]);
|
||||
|
||||
const showDataSourceSelect = dataSources?.length > 1;
|
||||
const showDownloadButton = enableDownload;
|
||||
|
||||
return (
|
||||
<div className="text-foreground flex min-w-[400px] max-w-md flex-col">
|
||||
@@ -209,11 +181,9 @@ function ReportDialog({
|
||||
<div className="flex justify-end gap-2">
|
||||
<InputDialog>
|
||||
<InputDialog.Actions>
|
||||
{showDownloadButton && (
|
||||
<InputDialog.ActionsSecondary onClick={handleDownload}>
|
||||
{t('Download')}
|
||||
</InputDialog.ActionsSecondary>
|
||||
)}
|
||||
<InputDialog.ActionsSecondary onClick={handleCancel}>
|
||||
Cancel
|
||||
</InputDialog.ActionsSecondary>
|
||||
<InputDialog.ActionsPrimary onClick={handleSave}>Save</InputDialog.ActionsPrimary>
|
||||
</InputDialog.Actions>
|
||||
</InputDialog>
|
||||
|
||||
@@ -6,7 +6,13 @@ import getDisplaySetsFromUnsupportedSeries from './getDisplaySetsFromUnsupported
|
||||
import { chartHandler } from './SOPClassHandlers/chartSOPClassHandler';
|
||||
import { metaData } from '@cornerstonejs/core';
|
||||
|
||||
const { isImage, sortStudyInstances, sopClassDictionary, isDisplaySetReconstructable } = utils;
|
||||
const {
|
||||
isImage,
|
||||
sortStudyInstances,
|
||||
instancesSortCriteria,
|
||||
sopClassDictionary,
|
||||
isDisplaySetReconstructable,
|
||||
} = utils;
|
||||
const { ImageSet } = classes;
|
||||
|
||||
const DEFAULT_VOLUME_LOADER_SCHEME = 'cornerstoneStreamingImageVolume';
|
||||
@@ -261,7 +267,6 @@ const sopClassUids = [
|
||||
sopClassDictionary.XRay3DAngiographicImageStorage,
|
||||
sopClassDictionary.XRay3DCraniofacialImageStorage,
|
||||
sopClassDictionary.BreastTomosynthesisImageStorage,
|
||||
sopClassDictionary.CornealTopographyMapStorage,
|
||||
sopClassDictionary.BreastProjectionXRayImageStorageForPresentation,
|
||||
sopClassDictionary.BreastProjectionXRayImageStorageForProcessing,
|
||||
sopClassDictionary.IntravascularOpticalCoherenceTomographyImageStorageForPresentation,
|
||||
|
||||
@@ -113,7 +113,7 @@ export function Toolbox({ buttonSectionId, title }: ToolboxProps) {
|
||||
);
|
||||
})}
|
||||
{activeToolOptions && (
|
||||
<div className="bg-muted mt-1 h-auto px-2">
|
||||
<div className="bg-primary-dark mt-1 h-auto px-2">
|
||||
<ToolSettings options={activeToolOptions} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
Loaded 100 of 352 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user