{
/>
)}
+
+
+
+ OIDC Configuration (optional)
+
+ {`Example JSON format:
+{
+ "authority": "https://accounts.google.com",
+ "clientId": "your-client-id.apps.googleusercontent.com",
+ "scope": "email profile openid https://www.googleapis.com/auth/cloud-healthcare",
+ "grantType": "implicit"
+}`}
+
+ }
+ overlayStyle={{ maxWidth: '450px' }}
+ >
+
+
+
+
+ {this.state.oidcConfigInput.trim() !== '' &&
+ !this.state.isOidcConfigValid && (
+
+ Invalid JSON format. Required fields: authority, clientId,
+ scope
+
+ )}
+
>
)
diff --git a/src/components/SegmentItem.tsx b/src/components/SegmentItem.tsx
index 81331f86..1812631a 100644
--- a/src/components/SegmentItem.tsx
+++ b/src/components/SegmentItem.tsx
@@ -1,5 +1,5 @@
import { SettingOutlined } from '@ant-design/icons'
-import { Button, Divider, Menu, Popover, Space, Switch } from 'antd'
+import { Button, Divider, Menu, Popover, Space, Switch, Tag } from 'antd'
// skipcq: JS-C1003
import type * as dmv from 'dicom-microscopy-viewer'
import React from 'react'
@@ -34,6 +34,7 @@ interface SegmentItemProps {
color?: number[]
}
}) => void
+ onClick: (segmentUID: string) => void
}
interface SegmentItemState {
@@ -52,7 +53,7 @@ class SegmentItem extends React.Component {
super(props)
/** Initialize with default color if not provided */
- const defaultColor = this.props.defaultStyle.color ?? [255, 255, 0] // Default yellow
+ const defaultColor = this.props.defaultStyle.color ?? [255, 255, 0]
this.state = {
isVisible: this.props.isVisible,
currentStyle: {
@@ -66,6 +67,9 @@ class SegmentItem extends React.Component {
checked: boolean,
_event: React.MouseEvent,
): void => {
+ if (this.props.segment.isAbsent) {
+ return
+ }
this.props.onVisibilityChange({
segmentUID: this.props.segment.uid,
isVisible: checked,
@@ -111,7 +115,15 @@ class SegmentItem extends React.Component {
}
}
+ handleClick = (): void => {
+ if (this.props.segment.isAbsent) {
+ return
+ }
+ this.props.onClick(this.props.segment.uid)
+ }
+
render(): React.ReactNode {
+ const isAbsent = this.props.segment.isAbsent === true
const attributes: Array<{ name: string; value: string }> = [
{
name: 'Property Type',
@@ -137,7 +149,6 @@ class SegmentItem extends React.Component {
| undefined
const segmentationType = getSegmentationType(segmentationMetadata)
- // Add SegmentationType from metadata if available
if (segmentationMetadata?.SegmentationType !== undefined) {
attributes.push({
name: 'Segmentation Type',
@@ -175,6 +186,7 @@ class SegmentItem extends React.Component {
metadata,
onVisibilityChange,
onStyleChange,
+ onClick: _onClick,
...otherProps
} = this.props
return (
@@ -189,9 +201,15 @@ class SegmentItem extends React.Component {
}
unCheckedChildren={}
+ title={
+ isAbsent
+ ? 'Segment has no pixel data'
+ : 'Toggle segment visibility'
+ }
/>
{
type="primary"
shape="circle"
icon={}
+ disabled={isAbsent}
/>
- {/* Color indicator - only show for non-fractional segmentation */}
- {segmentationType !== 'FRACTIONAL' && (
+ {segmentationType !== 'FRACTIONAL' && !isAbsent && (
{
)}
-
+
+ ) : (
+ this.props.segment.label
+ )
+ }
attributes={attributes}
- selectable
+ selectable={!isAbsent}
hasLongValues
/>
-
+
)
diff --git a/src/components/SegmentList.tsx b/src/components/SegmentList.tsx
index 212723f9..1dd34830 100644
--- a/src/components/SegmentList.tsx
+++ b/src/components/SegmentList.tsx
@@ -35,6 +35,7 @@ interface SegmentListProps {
color?: number[]
}
}) => void
+ onSegmentClick: (segmentUID: string) => void
}
/**
@@ -47,6 +48,9 @@ class SegmentList extends React.Component<
handleVisibilityChange = (checked: boolean): void => {
if (checked) {
this.props.segments.forEach((segment) => {
+ if (segment.isAbsent) {
+ return
+ }
this.props.onSegmentVisibilityChange({
segmentUID: segment.uid,
isVisible: checked,
@@ -75,6 +79,7 @@ class SegmentList extends React.Component<
defaultStyle={this.props.defaultSegmentStyles[uid]}
onVisibilityChange={this.props.onSegmentVisibilityChange}
onStyleChange={this.props.onSegmentStyleChange}
+ onClick={this.props.onSegmentClick}
/>
)
})
diff --git a/src/components/SlideViewer.tsx b/src/components/SlideViewer.tsx
index a95b4b87..dfd8cab2 100644
--- a/src/components/SlideViewer.tsx
+++ b/src/components/SlideViewer.tsx
@@ -841,6 +841,12 @@ class SlideViewer extends React.Component {
*/
const shownSegmentUIDs: string[] = []
matchingSegments.forEach((segment) => {
+ if (segment.isAbsent) {
+ logger.debug(
+ `auto-load Segmentation: skipping absent segment "${segment.uid}"`,
+ )
+ return
+ }
try {
this.volumeViewer.showSegment(segment.uid)
shownSegmentUIDs.push(segment.uid)
@@ -3082,6 +3088,13 @@ class SlideViewer extends React.Component {
segmentUID: string
isVisible: boolean
}): void => {
+ const segment = this.volumeViewer
+ .getAllSegments()
+ .find((item) => item.uid === segmentUID)
+ if (segment?.isAbsent) {
+ logger.debug(`ignore visibility change for absent segment ${segmentUID}`)
+ return
+ }
logger.log(`change visibility of segment ${segmentUID}`)
if (isVisible) {
logger.log(`show segment ${segmentUID}`)
@@ -3102,6 +3115,16 @@ class SlideViewer extends React.Component {
}
}
+ handleSegmentClick = (segmentUID: string): void => {
+ const segment = this.volumeViewer
+ .getAllSegments()
+ .find((item) => item.uid === segmentUID)
+ if (segment?.isAbsent) {
+ return
+ }
+ this.volumeViewer.zoomToSegment(segmentUID)
+ }
+
/**
* Handle change of segment style.
*/
@@ -4288,6 +4311,7 @@ class SlideViewer extends React.Component {
visibleSegmentUIDs={this.state.visibleSegmentUIDs}
onSegmentVisibilityChange={this.handleSegmentVisibilityChange}
onSegmentStyleChange={this.handleSegmentStyleChange}
+ onSegmentClick={this.handleSegmentClick}
/>
)}
diff --git a/types/dicom-microscopy-viewer/index.d.ts b/types/dicom-microscopy-viewer/index.d.ts
index 540d47c9..a52415a4 100644
--- a/types/dicom-microscopy-viewer/index.d.ts
+++ b/types/dicom-microscopy-viewer/index.d.ts
@@ -156,9 +156,11 @@ declare module 'dicom-microscopy-viewer' {
segmentUID: string,
styleOptions?: {
opacity?: number
- }
+ },
+ shouldZoomIn?: boolean
): void
hideSegment (segmentUID: string): void
+ zoomToSegment (segmentUID: string): void
setSegmentStyle (
segmentUID: string,
styleOptions: {
@@ -412,6 +414,7 @@ declare module 'dicom-microscopy-viewer' {
studyInstanceUID: string
seriesInstanceUID: string
sopInstanceUIDs: string[]
+ isAbsent?: boolean
}
export class Segment {
@@ -426,6 +429,8 @@ declare module 'dicom-microscopy-viewer' {
get studyInstanceUID (): string
get seriesInstanceUID (): string
get sopInstanceUIDs (): string[]
+ /** True when Segment Sequence lists the segment but no frames exist. */
+ get isAbsent (): boolean
}
}