fix(layouts): and fix thumbnail in touch and update migration guide for 3.8 release (#4052)

This commit is contained in:
Alireza 2024-04-18 23:21:02 -04:00 committed by GitHub
parent 28bc8914a8
commit d250d04580
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
30 changed files with 209 additions and 158 deletions

View File

@ -46,8 +46,8 @@
}, },
"dependencies": { "dependencies": {
"@babel/runtime": "^7.20.13", "@babel/runtime": "^7.20.13",
"@cornerstonejs/adapters": "^1.70.8", "@cornerstonejs/adapters": "^1.70.9",
"@cornerstonejs/core": "^1.70.8", "@cornerstonejs/core": "^1.70.9",
"@kitware/vtk.js": "30.3.3", "@kitware/vtk.js": "30.3.3",
"react-color": "^2.19.3" "react-color": "^2.19.3"
} }

View File

@ -138,7 +138,7 @@ function getUpdatedViewportsForSegmentation({
const { hangingProtocolService, displaySetService, segmentationService, viewportGridService } = const { hangingProtocolService, displaySetService, segmentationService, viewportGridService } =
servicesManager.services; servicesManager.services;
const { viewports } = viewportGridService.getState(); const { viewports, isHangingProtocolLayout } = viewportGridService.getState();
const viewport = getTargetViewport({ viewportId, viewportGridService }); const viewport = getTargetViewport({ viewportId, viewportGridService });
const targetViewportId = viewport.viewportOptions.viewportId; const targetViewportId = viewport.viewportOptions.viewportId;
@ -153,7 +153,8 @@ function getUpdatedViewportsForSegmentation({
const updatedViewports = hangingProtocolService.getViewportsRequireUpdate( const updatedViewports = hangingProtocolService.getViewportsRequireUpdate(
targetViewportId, targetViewportId,
referenceDisplaySetInstanceUID referenceDisplaySetInstanceUID,
isHangingProtocolLayout
); );
viewports.forEach((viewport, viewportId) => { viewports.forEach((viewport, viewportId) => {

View File

@ -46,9 +46,9 @@
}, },
"dependencies": { "dependencies": {
"@babel/runtime": "^7.20.13", "@babel/runtime": "^7.20.13",
"@cornerstonejs/adapters": "^1.70.8", "@cornerstonejs/adapters": "^1.70.9",
"@cornerstonejs/core": "^1.70.8", "@cornerstonejs/core": "^1.70.9",
"@cornerstonejs/tools": "^1.70.8", "@cornerstonejs/tools": "^1.70.9",
"classnames": "^2.3.2" "classnames": "^2.3.2"
} }
} }

View File

@ -42,9 +42,9 @@
}, },
"dependencies": { "dependencies": {
"@babel/runtime": "^7.20.13", "@babel/runtime": "^7.20.13",
"@cornerstonejs/core": "^1.70.8", "@cornerstonejs/core": "^1.70.9",
"@cornerstonejs/streaming-image-volume-loader": "^1.70.8", "@cornerstonejs/streaming-image-volume-loader": "^1.70.9",
"@cornerstonejs/tools": "^1.70.8", "@cornerstonejs/tools": "^1.70.9",
"classnames": "^2.3.2" "classnames": "^2.3.2"
} }
} }

View File

@ -38,7 +38,7 @@
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2", "@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
"@cornerstonejs/codec-openjpeg": "^1.2.2", "@cornerstonejs/codec-openjpeg": "^1.2.2",
"@cornerstonejs/codec-openjph": "^2.4.2", "@cornerstonejs/codec-openjph": "^2.4.2",
"@cornerstonejs/dicom-image-loader": "^1.70.8", "@cornerstonejs/dicom-image-loader": "^1.70.9",
"@icr/polyseg-wasm": "^0.4.0", "@icr/polyseg-wasm": "^0.4.0",
"@ohif/core": "3.8.0-beta.85", "@ohif/core": "3.8.0-beta.85",
"@ohif/ui": "3.8.0-beta.85", "@ohif/ui": "3.8.0-beta.85",
@ -55,10 +55,10 @@
}, },
"dependencies": { "dependencies": {
"@babel/runtime": "^7.20.13", "@babel/runtime": "^7.20.13",
"@cornerstonejs/adapters": "^1.70.8", "@cornerstonejs/adapters": "^1.70.9",
"@cornerstonejs/core": "^1.70.8", "@cornerstonejs/core": "^1.70.9",
"@cornerstonejs/streaming-image-volume-loader": "^1.70.8", "@cornerstonejs/streaming-image-volume-loader": "^1.70.9",
"@cornerstonejs/tools": "^1.70.8", "@cornerstonejs/tools": "^1.70.9",
"@icr/polyseg-wasm": "^0.4.0", "@icr/polyseg-wasm": "^0.4.0",
"@kitware/vtk.js": "30.3.3", "@kitware/vtk.js": "30.3.3",
"html2canvas": "^1.4.1", "html2canvas": "^1.4.1",

View File

@ -14,17 +14,7 @@ export const mpr: Types.HangingProtocol.Protocol = {
numberOfPriorsReferenced: 0, numberOfPriorsReferenced: 0,
protocolMatchingRules: [], protocolMatchingRules: [],
imageLoadStrategy: 'nth', imageLoadStrategy: 'nth',
callbacks: { callbacks: {},
// Switches out of MPR mode when the layout change button is used
onLayoutChange: [
{
commandName: 'toggleHangingProtocol',
commandOptions: { protocolId: 'mpr' },
context: 'DEFAULT',
},
],
// Turns off crosshairs when switching out of MPR mode
},
displaySetSelectors: { displaySetSelectors: {
activeDisplaySet: { activeDisplaySet: {
seriesMatchingRules: [ seriesMatchingRules: [

View File

@ -44,6 +44,7 @@ import ImageOverlayViewerTool from './tools/ImageOverlayViewerTool';
export default function initCornerstoneTools(configuration = {}) { export default function initCornerstoneTools(configuration = {}) {
CrosshairsTool.isAnnotation = false; CrosshairsTool.isAnnotation = false;
ReferenceLinesTool.isAnnotation = false; ReferenceLinesTool.isAnnotation = false;
AdvancedMagnifyTool.isAnnotation = false;
init(configuration); init(configuration);
addTool(PanTool); addTool(PanTool);

View File

@ -25,7 +25,8 @@ function PanelStudyBrowser({
// doesn't have to have such an intense shape. This works well enough for now. // doesn't have to have such an intense shape. This works well enough for now.
// Tabs --> Studies --> DisplaySets --> Thumbnails // Tabs --> Studies --> DisplaySets --> Thumbnails
const { StudyInstanceUIDs } = useImageViewer(); const { StudyInstanceUIDs } = useImageViewer();
const [{ activeViewportId, viewports }, viewportGridService] = useViewportGrid(); const [{ activeViewportId, viewports, isHangingProtocolLayout }, viewportGridService] =
useViewportGrid();
const [activeTabName, setActiveTabName] = useState('primary'); const [activeTabName, setActiveTabName] = useState('primary');
const [expandedStudyInstanceUIDs, setExpandedStudyInstanceUIDs] = useState([ const [expandedStudyInstanceUIDs, setExpandedStudyInstanceUIDs] = useState([
...StudyInstanceUIDs, ...StudyInstanceUIDs,
@ -40,7 +41,8 @@ function PanelStudyBrowser({
try { try {
updatedViewports = hangingProtocolService.getViewportsRequireUpdate( updatedViewports = hangingProtocolService.getViewportsRequireUpdate(
viewportId, viewportId,
displaySetInstanceUID displaySetInstanceUID,
isHangingProtocolLayout
); );
} catch (error) { } catch (error) {
console.warn(error); console.warn(error);

View File

@ -58,6 +58,10 @@ const generateAdvancedPresets = ({ servicesManager }) => {
} }
const displaySetInsaneUIDs = viewportGridService.getDisplaySetsUIDsForViewport(viewportId); const displaySetInsaneUIDs = viewportGridService.getDisplaySetsUIDsForViewport(viewportId);
if (!displaySetInsaneUIDs) {
return [];
}
const displaySets = displaySetInsaneUIDs.map(uid => displaySetService.getDisplaySetByUID(uid)); const displaySets = displaySetInsaneUIDs.map(uid => displaySetService.getDisplaySetByUID(uid));
return hangingProtocols return hangingProtocols

View File

@ -286,6 +286,7 @@ const commandsModule = ({
const findOrCreateViewport = layoutFindOrCreate.bind( const findOrCreateViewport = layoutFindOrCreate.bind(
null, null,
hangingProtocolService, hangingProtocolService,
isHangingProtocolLayout,
stateReduce.viewportsByPosition stateReduce.viewportsByPosition
); );
@ -303,7 +304,7 @@ const commandsModule = ({
toggleOneUp() { toggleOneUp() {
const viewportGridState = viewportGridService.getState(); const viewportGridState = viewportGridService.getState();
const { activeViewportId, viewports, layout } = viewportGridState; const { activeViewportId, viewports, layout, isHangingProtocolLayout } = viewportGridState;
const { displaySetInstanceUIDs, displaySetOptions, viewportOptions } = const { displaySetInstanceUIDs, displaySetOptions, viewportOptions } =
viewports.get(activeViewportId); viewports.get(activeViewportId);
@ -330,7 +331,8 @@ const commandsModule = ({
.map(displaySetInstanceUID => .map(displaySetInstanceUID =>
hangingProtocolService.getViewportsRequireUpdate( hangingProtocolService.getViewportsRequireUpdate(
viewportIdToUpdate, viewportIdToUpdate,
displaySetInstanceUID displaySetInstanceUID,
isHangingProtocolLayout
) )
) )
.flat(); .flat();
@ -511,7 +513,8 @@ const commandsModule = ({
currentDisplaySets.sort(dsSortFn); currentDisplaySets.sort(dsSortFn);
const { activeViewportId, viewports } = viewportGridService.getState(); const { activeViewportId, viewports, isHangingProtocolLayout } =
viewportGridService.getState();
const { displaySetInstanceUIDs } = viewports.get(activeViewportId); const { displaySetInstanceUIDs } = viewports.get(activeViewportId);
@ -545,7 +548,8 @@ const commandsModule = ({
try { try {
updatedViewports = hangingProtocolService.getViewportsRequireUpdate( updatedViewports = hangingProtocolService.getViewportsRequireUpdate(
activeViewportId, activeViewportId,
displaySetInstanceUID displaySetInstanceUID,
isHangingProtocolLayout
); );
} catch (error) { } catch (error) {
console.warn(error); console.warn(error);

View File

@ -16,6 +16,7 @@ import { StateSyncService } from '@ohif/core';
*/ */
export const findOrCreateViewport = ( export const findOrCreateViewport = (
hangingProtocolService, hangingProtocolService,
isHangingProtocolLayout,
viewportsByPosition, viewportsByPosition,
position: number, position: number,
positionId: string, positionId: string,
@ -31,8 +32,13 @@ export const findOrCreateViewport = (
if (!options.inDisplay) { if (!options.inDisplay) {
options.inDisplay = [...viewportsByPosition.initialInDisplay]; options.inDisplay = [...viewportsByPosition.initialInDisplay];
} }
// See if there is a default viewport for new views.
const missing = hangingProtocolService.getMissingViewport(protocolId, stageIndex, options); // See if there is a default viewport for new views
const missing = hangingProtocolService.getMissingViewport(
isHangingProtocolLayout ? protocolId : 'default',
stageIndex,
options
);
if (missing) { if (missing) {
const displaySetInstanceUIDs = missing.displaySetsInfo.map(it => it.displaySetInstanceUID); const displaySetInstanceUIDs = missing.displaySetsInfo.map(it => it.displaySetInstanceUID);
options.inDisplay.push(...displaySetInstanceUIDs); options.inDisplay.push(...displaySetInstanceUIDs);

View File

@ -37,6 +37,8 @@ function getDisplaySetInfo(instances) {
const { isDynamicVolume, timePoints } = dynamicVolumeInfo; const { isDynamicVolume, timePoints } = dynamicVolumeInfo;
let displaySetInfo; let displaySetInfo;
const { appConfig } = appContext;
if (isDynamicVolume) { if (isDynamicVolume) {
const timePoint = timePoints[0]; const timePoint = timePoints[0];
const instancesMap = new Map(); const instancesMap = new Map();
@ -46,9 +48,9 @@ function getDisplaySetInfo(instances) {
const firstTimePointInstances = timePoint.map(imageId => instancesMap.get(imageId)); const firstTimePointInstances = timePoint.map(imageId => instancesMap.get(imageId));
displaySetInfo = isDisplaySetReconstructable(firstTimePointInstances); displaySetInfo = isDisplaySetReconstructable(firstTimePointInstances, appConfig);
} else { } else {
displaySetInfo = isDisplaySetReconstructable(instances); displaySetInfo = isDisplaySetReconstructable(instances, appConfig);
} }
return { return {

View File

@ -32,8 +32,8 @@
"start": "yarn run dev" "start": "yarn run dev"
}, },
"peerDependencies": { "peerDependencies": {
"@cornerstonejs/core": "^1.70.8", "@cornerstonejs/core": "^1.70.9",
"@cornerstonejs/tools": "^1.70.8", "@cornerstonejs/tools": "^1.70.9",
"@ohif/core": "3.8.0-beta.85", "@ohif/core": "3.8.0-beta.85",
"@ohif/extension-cornerstone-dicom-sr": "3.8.0-beta.85", "@ohif/extension-cornerstone-dicom-sr": "3.8.0-beta.85",
"@ohif/ui": "3.8.0-beta.85", "@ohif/ui": "3.8.0-beta.85",

View File

@ -34,7 +34,8 @@ function PanelStudyBrowserTracking({
// doesn't have to have such an intense shape. This works well enough for now. // doesn't have to have such an intense shape. This works well enough for now.
// Tabs --> Studies --> DisplaySets --> Thumbnails // Tabs --> Studies --> DisplaySets --> Thumbnails
const { StudyInstanceUIDs } = useImageViewer(); const { StudyInstanceUIDs } = useImageViewer();
const [{ activeViewportId, viewports }, viewportGridService] = useViewportGrid(); const [{ activeViewportId, viewports, isHangingProtocolLayout }, viewportGridService] =
useViewportGrid();
const [trackedMeasurements, sendTrackedMeasurementsEvent] = useTrackedMeasurements(); const [trackedMeasurements, sendTrackedMeasurementsEvent] = useTrackedMeasurements();
const [activeTabName, setActiveTabName] = useState('primary'); const [activeTabName, setActiveTabName] = useState('primary');
const [expandedStudyInstanceUIDs, setExpandedStudyInstanceUIDs] = useState([ const [expandedStudyInstanceUIDs, setExpandedStudyInstanceUIDs] = useState([
@ -51,7 +52,8 @@ function PanelStudyBrowserTracking({
try { try {
updatedViewports = hangingProtocolService.getViewportsRequireUpdate( updatedViewports = hangingProtocolService.getViewportsRequireUpdate(
viewportId, viewportId,
displaySetInstanceUID displaySetInstanceUID,
isHangingProtocolLayout
); );
} catch (error) { } catch (error) {
console.warn(error); console.warn(error);

View File

@ -138,8 +138,8 @@ const moreTools = [
createButton({ createButton({
id: 'Magnify', id: 'Magnify',
icon: 'tool-magnify', icon: 'tool-magnify',
label: 'Magnify', label: 'Zoom-in',
tooltip: 'Magnify', tooltip: 'Zoom-in',
commands: setToolActiveToolbar, commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool', evaluate: 'evaluate.cornerstoneTool',
}), }),
@ -169,8 +169,8 @@ const moreTools = [
createButton({ createButton({
id: 'AdvancedMagnify', id: 'AdvancedMagnify',
icon: 'icon-tool-loupe', icon: 'icon-tool-loupe',
label: 'Loupe', label: 'Magnify Probe',
tooltip: 'Loupe', tooltip: 'Magnify Probe',
commands: 'toggleActiveDisabledToolbar', commands: 'toggleActiveDisabledToolbar',
evaluate: 'evaluate.cornerstoneTool.toggle.ifStrictlyDisabled', evaluate: 'evaluate.cornerstoneTool.toggle.ifStrictlyDisabled',
}), }),

View File

@ -138,8 +138,8 @@ const moreTools = [
createButton({ createButton({
id: 'Magnify', id: 'Magnify',
icon: 'tool-magnify', icon: 'tool-magnify',
label: 'Magnify', label: 'Zoom-in',
tooltip: 'Magnify', tooltip: 'Zoom-in',
commands: setToolActiveToolbar, commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool', evaluate: 'evaluate.cornerstoneTool',
}), }),
@ -161,8 +161,8 @@ const moreTools = [
createButton({ createButton({
id: 'AdvancedMagnify', id: 'AdvancedMagnify',
icon: 'icon-tool-loupe', icon: 'icon-tool-loupe',
label: 'Loupe', label: 'Magnify Probe',
tooltip: 'Loupe', tooltip: 'Magnify Probe',
commands: 'toggleActiveDisabledToolbar', commands: 'toggleActiveDisabledToolbar',
evaluate: 'evaluate.cornerstoneTool.toggle.ifStrictlyDisabled', evaluate: 'evaluate.cornerstoneTool.toggle.ifStrictlyDisabled',
}), }),

View File

@ -207,8 +207,8 @@ const toolbarButtons: Button[] = [
createButton({ createButton({
id: 'Magnify', id: 'Magnify',
icon: 'tool-magnify', icon: 'tool-magnify',
label: 'Magnify', label: 'Zoom-in',
tooltip: 'Magnify', tooltip: 'Zoom-in',
commands: setToolActiveToolbar, commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool', evaluate: 'evaluate.cornerstoneTool',
}), }),
@ -238,8 +238,8 @@ const toolbarButtons: Button[] = [
createButton({ createButton({
id: 'AdvancedMagnify', id: 'AdvancedMagnify',
icon: 'icon-tool-loupe', icon: 'icon-tool-loupe',
label: 'Loupe', label: 'Magnify Probe',
tooltip: 'Loupe', tooltip: 'Magnify Probe',
commands: 'toggleActiveDisabledToolbar', commands: 'toggleActiveDisabledToolbar',
evaluate: 'evaluate.cornerstoneTool.toggle.ifStrictlyDisabled', evaluate: 'evaluate.cornerstoneTool.toggle.ifStrictlyDisabled',
}), }),

View File

@ -47,6 +47,8 @@ describe('OHIF Study List', function () {
'[data-cy="mode-basic-test-1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1"]' '[data-cy="mode-basic-test-1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1"]'
).click(); ).click();
cy.get('[data-cy="return-to-work-list"]').click(); cy.get('[data-cy="return-to-work-list"]').click();
cy.wait(2000);
cy.get('@searchResult2').should($list => { cy.get('@searchResult2').should($list => {
expect($list.length).to.be.eq(1); expect($list.length).to.be.eq(1);
expect($list).to.contain('Juno'); expect($list).to.contain('Juno');
@ -72,6 +74,8 @@ describe('OHIF Study List', function () {
'[data-cy="mode-basic-test-1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1"]' '[data-cy="mode-basic-test-1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1"]'
).click(); ).click();
cy.get('[data-cy="return-to-work-list"]').click(); cy.get('[data-cy="return-to-work-list"]').click();
cy.wait(2000);
cy.get('@searchResult2').should($list => { cy.get('@searchResult2').should($list => {
expect($list.length).to.be.eq(1); expect($list.length).to.be.eq(1);
expect($list).to.contain('0000003'); expect($list).to.contain('0000003');
@ -82,6 +86,7 @@ describe('OHIF Study List', function () {
cy.get('@AccessionNumber').type('321'); cy.get('@AccessionNumber').type('321');
//Wait result list to be displayed //Wait result list to be displayed
cy.waitStudyList(); cy.waitStudyList();
cy.wait(2000);
cy.get('@searchResult2').should($list => { cy.get('@searchResult2').should($list => {
expect($list.length).to.be.eq(1); expect($list.length).to.be.eq(1);
expect($list).to.contain('321'); expect($list).to.contain('321');
@ -92,11 +97,15 @@ describe('OHIF Study List', function () {
cy.get('@AccessionNumber').type('0000155811'); cy.get('@AccessionNumber').type('0000155811');
//Wait result list to be displayed //Wait result list to be displayed
cy.waitStudyList(); cy.waitStudyList();
cy.wait(2000);
cy.get('[data-cy="studyRow-1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1"]').click(); cy.get('[data-cy="studyRow-1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1"]').click();
cy.get( cy.get(
'[data-cy="mode-basic-test-1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1"]' '[data-cy="mode-basic-test-1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1"]'
).click(); ).click();
cy.get('[data-cy="return-to-work-list"]').click(); cy.get('[data-cy="return-to-work-list"]').click();
cy.wait(2000);
cy.get('@searchResult2').should($list => { cy.get('@searchResult2').should($list => {
expect($list.length).to.be.eq(1); expect($list.length).to.be.eq(1);
expect($list).to.contain('0000155811'); expect($list).to.contain('0000155811');
@ -107,6 +116,8 @@ describe('OHIF Study List', function () {
cy.get('@StudyDescription').type('PETCT'); cy.get('@StudyDescription').type('PETCT');
//Wait result list to be displayed //Wait result list to be displayed
cy.waitStudyList(); cy.waitStudyList();
cy.wait(2000);
cy.get('@searchResult2').should($list => { cy.get('@searchResult2').should($list => {
expect($list.length).to.be.eq(1); expect($list.length).to.be.eq(1);
expect($list).to.contain('PETCT'); expect($list).to.contain('PETCT');
@ -117,13 +128,15 @@ describe('OHIF Study List', function () {
cy.get('@StudyDescription').type('PETCT'); cy.get('@StudyDescription').type('PETCT');
//Wait result list to be displayed //Wait result list to be displayed
cy.waitStudyList(); cy.waitStudyList();
cy.wait(2000);
cy.get('[data-cy="studyRow-1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1"]').click(); cy.get('[data-cy="studyRow-1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1"]').click();
cy.get( cy.get(
'[data-cy="mode-basic-test-1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1"]' '[data-cy="mode-basic-test-1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1"]'
).click(); ).click();
cy.get('[data-cy="return-to-work-list"]').click(); cy.get('[data-cy="return-to-work-list"]').click();
cy.wait(2000);
cy.wait(1000);
cy.get('@searchResult2').should($list => { cy.get('@searchResult2').should($list => {
expect($list.length).to.be.eq(1); expect($list.length).to.be.eq(1);
expect($list).to.contain('PETCT'); expect($list).to.contain('PETCT');

View File

@ -54,7 +54,7 @@
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2", "@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
"@cornerstonejs/codec-openjpeg": "^1.2.2", "@cornerstonejs/codec-openjpeg": "^1.2.2",
"@cornerstonejs/codec-openjph": "^2.4.5", "@cornerstonejs/codec-openjph": "^2.4.5",
"@cornerstonejs/dicom-image-loader": "^1.70.8", "@cornerstonejs/dicom-image-loader": "^1.70.9",
"@emotion/serialize": "^1.1.3", "@emotion/serialize": "^1.1.3",
"@ohif/core": "3.8.0-beta.85", "@ohif/core": "3.8.0-beta.85",
"@ohif/extension-cornerstone": "3.8.0-beta.85", "@ohif/extension-cornerstone": "3.8.0-beta.85",

View File

@ -62,6 +62,13 @@ function App({ config, defaultExtensions, defaultModes }) {
const appConfigState = init.appConfig; const appConfigState = init.appConfig;
const { routerBasename, modes, dataSources, oidc, showStudyList } = appConfigState; const { routerBasename, modes, dataSources, oidc, showStudyList } = appConfigState;
// get the maximum 3D texture size
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl2');
const max3DTextureSize = gl.getParameter(gl.MAX_3D_TEXTURE_SIZE);
appConfigState.max3DTextureSize = max3DTextureSize;
const { const {
uiDialogService, uiDialogService,
uiModalService, uiModalService,

View File

@ -103,20 +103,12 @@ function ViewerViewportGrid(props) {
const _getUpdatedViewports = useCallback( const _getUpdatedViewports = useCallback(
(viewportId, displaySetInstanceUID) => { (viewportId, displaySetInstanceUID) => {
if (!isHangingProtocolLayout) {
return [
{
viewportId,
displaySetInstanceUIDs: [displaySetInstanceUID],
},
];
}
let updatedViewports = []; let updatedViewports = [];
try { try {
updatedViewports = hangingProtocolService.getViewportsRequireUpdate( updatedViewports = hangingProtocolService.getViewportsRequireUpdate(
viewportId, viewportId,
displaySetInstanceUID displaySetInstanceUID,
isHangingProtocolLayout
); );
} catch (error) { } catch (error) {
console.warn(error); console.warn(error);

View File

@ -37,7 +37,7 @@
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2", "@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
"@cornerstonejs/codec-openjpeg": "^1.2.2", "@cornerstonejs/codec-openjpeg": "^1.2.2",
"@cornerstonejs/codec-openjph": "^2.4.2", "@cornerstonejs/codec-openjph": "^2.4.2",
"@cornerstonejs/dicom-image-loader": "^1.70.8", "@cornerstonejs/dicom-image-loader": "^1.70.9",
"@ohif/ui": "3.8.0-beta.85", "@ohif/ui": "3.8.0-beta.85",
"cornerstone-math": "0.1.9", "cornerstone-math": "0.1.9",
"dicom-parser": "^1.8.21" "dicom-parser": "^1.8.21"

View File

@ -601,17 +601,25 @@ export default class HangingProtocolService extends PubSubService {
}; };
} }
getViewportsRequireUpdate(viewportId, displaySetInstanceUID) { /**
const { displaySetService } = this._servicesManager.services; * This will return the viewports that need to be updated based on the
const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID); * hanging protocol layout and the displaySetInstanceUID that needs to be updated.
if (displaySet?.unsupported) { *
throw new Error('Unsupported displaySet'); * This is useful, when for instance we drag and drop a displaySet into a viewport
} * which is in MPR, and we need to update the other viewports that are showing the same
* layout.
*
* However, sometimes since we get out of sync with the hanging protocol layout, when
* the user use the custom grid layout, we should not update the other viewports, and that is
* when the isHangingProtocolLayout is set to false.
*
* @param viewportId - the id of the viewport that needs to be updated
* @param displaySetInstanceUID - the displaySetInstanceUID that needs to be updated
* @param isHangingProtocolLayout - whether the layout is a hanging protocol layout
* @returns
*/
getViewportsRequireUpdate(viewportId, displaySetInstanceUID, isHangingProtocolLayout = true) {
const newDisplaySetInstanceUID = displaySetInstanceUID; const newDisplaySetInstanceUID = displaySetInstanceUID;
const protocol = this.protocol;
const protocolStage = protocol.stages[this.stageIndex];
const protocolViewports = protocolStage.viewports;
const defaultReturn = [ const defaultReturn = [
{ {
viewportId, viewportId,
@ -619,6 +627,19 @@ export default class HangingProtocolService extends PubSubService {
}, },
]; ];
if (!isHangingProtocolLayout) {
return defaultReturn;
}
const { displaySetService } = this._servicesManager.services;
const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
if (displaySet?.unsupported) {
throw new Error('Unsupported displaySet');
}
const protocol = this.protocol;
const protocolStage = protocol.stages[this.stageIndex];
const protocolViewports = protocolStage.viewports;
if (!protocolViewports) { if (!protocolViewports) {
return defaultReturn; return defaultReturn;
} }
@ -1084,9 +1105,8 @@ export default class HangingProtocolService extends PubSubService {
options options
): HangingProtocol.ViewportMatchDetails { ): HangingProtocol.ViewportMatchDetails {
if (this.protocol.id !== protocolId) { if (this.protocol.id !== protocolId) {
throw new Error( console.warn('setting protocol');
`Currently applied protocol ${this.protocol.id} is different from ${protocolId}` this.protocol = this.getProtocolById(protocolId);
);
} }
const protocol = this.protocol; const protocol = this.protocol;
const stage = protocol.stages[stageIdx]; const stage = protocol.stages[stageIdx];

View File

@ -10,7 +10,7 @@ const iopTolerance = 0.01;
* *
* @param {Object[]} instances An array of `OHIFInstanceMetadata` objects. * @param {Object[]} instances An array of `OHIFInstanceMetadata` objects.
*/ */
export default function isDisplaySetReconstructable(instances) { export default function isDisplaySetReconstructable(instances, appConfig) {
if (!instances.length) { if (!instances.length) {
return { value: false }; return { value: false };
} }
@ -18,6 +18,14 @@ export default function isDisplaySetReconstructable(instances) {
const isMultiframe = firstInstance.NumberOfFrames > 1; const isMultiframe = firstInstance.NumberOfFrames > 1;
if (appConfig) {
const rows = toNumber(firstInstance.Rows);
const columns = toNumber(firstInstance.Columns);
if (rows > appConfig.max3DTextureSize || columns > appConfig.max3DTextureSize) {
return { value: false };
}
}
// We used to check is reconstructable modalities here, but the logic is removed // We used to check is reconstructable modalities here, but the logic is removed
// in favor of the calculation by metadata (orientation and positions) // in favor of the calculation by metadata (orientation and positions)

View File

@ -135,3 +135,8 @@ Additional Resources
## leftPanelDefaultClosed and rightPanelDefaultClosed ## leftPanelDefaultClosed and rightPanelDefaultClosed
Now they are renamed to `leftPanelClosed` and `rightPanelClosed` respectively. Now they are renamed to `leftPanelClosed` and `rightPanelClosed` respectively.
## StudyInstanceUID in the URL param
Previously there were two params that you could choose: seriesInstanceUID and seriesInstanceUIDs, they have been replaced with seriesInstanceUIDs so even if you would like to filter one series use ``seriesInstanceUIDs`

View File

@ -69,7 +69,6 @@ list as state stores are added:
* `viewportGridStore` has viewport grid restore information for returning to an earlier grid layout. * `viewportGridStore` has viewport grid restore information for returning to an earlier grid layout.
* `reuseIdMap` has a map of names to display sets for preserving user changes to hp display set selections. * `reuseIdMap` has a map of names to display sets for preserving user changes to hp display set selections.
* `hanging` has a map of the hanging protocol stage information applied (HPInfo) * `hanging` has a map of the hanging protocol stage information applied (HPInfo)
* `toggleHangingProtocol` has the previously applied hanging protocol, to toggle an HP off.
### Cornerstone Extension Stores ### Cornerstone Extension Stores

View File

@ -1,4 +1,4 @@
import React from 'react'; import React, { useState } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import classnames from 'classnames'; import classnames from 'classnames';
import { useDrag } from 'react-dnd'; import { useDrag } from 'react-dnd';
@ -35,6 +35,19 @@ const Thumbnail = ({
}, },
}); });
const [lastTap, setLastTap] = useState(0);
const handleTouchEnd = e => {
const currentTime = new Date().getTime();
const tapLength = currentTime - lastTap;
if (tapLength < 300 && tapLength > 0) {
onDoubleClick(e);
} else {
onClick(e);
}
setLastTap(currentTime);
};
return ( return (
<div <div
className={classnames( className={classnames(
@ -45,6 +58,7 @@ const Thumbnail = ({
data-cy={`study-browser-thumbnail`} data-cy={`study-browser-thumbnail`}
onClick={onClick} onClick={onClick}
onDoubleClick={onDoubleClick} onDoubleClick={onDoubleClick}
onTouchEnd={handleTouchEnd}
role="button" role="button"
tabIndex="0" tabIndex="0"
> >
@ -56,9 +70,6 @@ const Thumbnail = ({
? 'border-primary-light border-2' ? 'border-primary-light border-2'
: 'border-secondary-light border hover:border-blue-300' : 'border-secondary-light border hover:border-blue-300'
)} )}
style={{
margin: isActive ? '0' : '1px',
}}
> >
{imageSrc ? ( {imageSrc ? (
<img <img

View File

@ -1,4 +1,4 @@
import React from 'react'; import React, { useState } from 'react';
import classnames from 'classnames'; import classnames from 'classnames';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { useDrag } from 'react-dnd'; import { useDrag } from 'react-dnd';
@ -30,6 +30,19 @@ const ThumbnailNoImage = ({
}, },
}); });
const [lastTap, setLastTap] = useState(0);
const handleTouchEnd = e => {
const currentTime = new Date().getTime();
const tapLength = currentTime - lastTap;
if (tapLength < 300 && tapLength > 0) {
onDoubleClick(e);
} else {
onClick(e);
}
setLastTap(currentTime);
};
return ( return (
<div <div
className={classnames( className={classnames(
@ -42,6 +55,7 @@ const ThumbnailNoImage = ({
id={`thumbnail-${displaySetInstanceUID}`} id={`thumbnail-${displaySetInstanceUID}`}
onClick={onClick} onClick={onClick}
onDoubleClick={onDoubleClick} onDoubleClick={onDoubleClick}
onTouchEnd={handleTouchEnd}
role="button" role="button"
tabIndex="0" tabIndex="0"
data-cy={`study-browser-thumbnail-no-image`} data-cy={`study-browser-thumbnail-no-image`}

View File

@ -224,7 +224,6 @@ export function ViewportGridProvider({ children, service }) {
// If empty viewportOptions, we use numRow and numCols to calculate number of viewports // If empty viewportOptions, we use numRow and numCols to calculate number of viewports
const hasOptions = layoutOptions?.length; const hasOptions = layoutOptions?.length;
const viewports = new Map<string, Viewport>(); const viewports = new Map<string, Viewport>();
// Options is a temporary state store which can be used by the // Options is a temporary state store which can be used by the
// findOrCreate to store state about already found viewports. Typically, // findOrCreate to store state about already found viewports. Typically,
// it will be used to store the display set UID's which are already // it will be used to store the display set UID's which are already
@ -237,7 +236,21 @@ export function ViewportGridProvider({ children, service }) {
for (let col = 0; col < numCols; col++) { for (let col = 0; col < numCols; col++) {
const position = col + row * numCols; const position = col + row * numCols;
const layoutOption = layoutOptions[position]; const layoutOption = layoutOptions[position];
const positionId = layoutOption?.positionId || `${col}-${row}`;
let xPos, yPos, w, h;
if (layoutOptions && layoutOptions[position]) {
({ x: xPos, y: yPos, width: w, height: h } = layoutOptions[position]);
} else {
w = 1 / numCols;
h = 1 / numRows;
xPos = col * w;
yPos = row * h;
}
const colIndex = Math.round(xPos * numCols);
const rowIndex = Math.round(yPos * numRows);
const positionId = layoutOption?.positionId || `${colIndex}-${rowIndex}`;
if (hasOptions && position >= layoutOptions.length) { if (hasOptions && position >= layoutOptions.length) {
continue; continue;
@ -264,16 +277,6 @@ export function ViewportGridProvider({ children, service }) {
// and it is part of the read only state // and it is part of the read only state
viewports.set(viewport.viewportId, viewport); viewports.set(viewport.viewportId, viewport);
let xPos, yPos, w, h;
if (layoutOptions && layoutOptions[position]) {
({ x: xPos, y: yPos, width: w, height: h } = layoutOptions[position]);
} else {
w = 1 / numCols;
h = 1 / numRows;
xPos = col * w;
yPos = row * h;
}
Object.assign(viewport, { Object.assign(viewport, {
width: w, width: w,
height: h, height: h,

View File

@ -1497,13 +1497,13 @@
resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==
"@cornerstonejs/adapters@^1.70.8": "@cornerstonejs/adapters@^1.70.9":
version "1.70.8" version "1.70.9"
resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-1.70.8.tgz#b812a2ce00cf48404703237399e2c347d2e29d90" resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-1.70.9.tgz#77f96dbdd2d53225ad8d13d4912afa3538c84baa"
integrity sha512-dShI7qQdG/1l3JqeBhaBFT8RmfEHUGLfvKby3tPh6bgo5bj+2KRcnlW1hmDuAHxWIkCDnftoExSUIJqXGlvbdA== integrity sha512-eGJu9Skb2WUYvXn1JNO/5NB3EMEHj9rGAelrTozFclqPjnfHbxXlMBeScdE8YTmwR6wHtwiB/lXgu6hhrbYOMQ==
dependencies: dependencies:
"@babel/runtime-corejs2" "^7.17.8" "@babel/runtime-corejs2" "^7.17.8"
"@cornerstonejs/tools" "^1.70.8" "@cornerstonejs/tools" "^1.70.9"
buffer "^6.0.3" buffer "^6.0.3"
dcmjs "^0.29.8" dcmjs "^0.29.8"
gl-matrix "^3.4.3" gl-matrix "^3.4.3"
@ -1550,10 +1550,10 @@
resolved "https://registry.yarnpkg.com/@cornerstonejs/codec-openjph/-/codec-openjph-2.4.5.tgz#8690b61a86fa53ef38a70eee9d665a79229517c0" resolved "https://registry.yarnpkg.com/@cornerstonejs/codec-openjph/-/codec-openjph-2.4.5.tgz#8690b61a86fa53ef38a70eee9d665a79229517c0"
integrity sha512-MZCUy8VG0VG5Nl1l58+g+kH3LujAzLYTfJqkwpWI2gjSrGXnP6lgwyy4GmPRZWVoS40/B1LDNALK905cNWm+sg== integrity sha512-MZCUy8VG0VG5Nl1l58+g+kH3LujAzLYTfJqkwpWI2gjSrGXnP6lgwyy4GmPRZWVoS40/B1LDNALK905cNWm+sg==
"@cornerstonejs/core@^1.70.8": "@cornerstonejs/core@^1.70.9":
version "1.70.8" version "1.70.9"
resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-1.70.8.tgz#e66731986de638ebd7307fec19508544bb5fe7dc" resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-1.70.9.tgz#c08aa055a786aac79c457e744f18c5fe3f3203f5"
integrity sha512-xDAHxw4eGqJ4sPHc/+wPdRhZd2CYCkEuA7dE43e4rS6XKAN2X2BCjvTlZkAjECnOIsAnIOg//Pq7V6I09L28vg== integrity sha512-2Gu6SXRKuWFoP0aD0dC5et5pcWExxJOE2DWXUKuVdXollbIC+uq3I5FSWOwM8Zzu/Z3JzWWY5IYYPKdJqb8ogQ==
dependencies: dependencies:
"@kitware/vtk.js" "30.3.3" "@kitware/vtk.js" "30.3.3"
comlink "^4.4.1" comlink "^4.4.1"
@ -1561,34 +1561,34 @@
gl-matrix "^3.4.3" gl-matrix "^3.4.3"
lodash.clonedeep "4.5.0" lodash.clonedeep "4.5.0"
"@cornerstonejs/dicom-image-loader@^1.70.8": "@cornerstonejs/dicom-image-loader@^1.70.9":
version "1.70.8" version "1.70.9"
resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-1.70.8.tgz#e8107177298c0e9b314c225b93b0e28db59c8142" resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-1.70.9.tgz#e329eb86343651f3d6148e03eb1e9d4390b79a6a"
integrity sha512-YoTN/gINulfZr80tecbwqijNwm+UpbRuq6gOACmXGQ4y9MjT78p8e6NMdvU/40rwT41FR3KNySbKEXJSDRURgA== integrity sha512-M4qd88NA+z62d8w6eaDUbYfFCn3dmDqGkF0iI2s67LlySmeDo7pUmSG8gQbuJMOUPQMxD1Hy8EXBexaTAsBiaQ==
dependencies: dependencies:
"@cornerstonejs/codec-charls" "^1.2.3" "@cornerstonejs/codec-charls" "^1.2.3"
"@cornerstonejs/codec-libjpeg-turbo-8bit" "^1.2.2" "@cornerstonejs/codec-libjpeg-turbo-8bit" "^1.2.2"
"@cornerstonejs/codec-openjpeg" "^1.2.2" "@cornerstonejs/codec-openjpeg" "^1.2.2"
"@cornerstonejs/codec-openjph" "^2.4.5" "@cornerstonejs/codec-openjph" "^2.4.5"
"@cornerstonejs/core" "^1.70.8" "@cornerstonejs/core" "^1.70.9"
dicom-parser "^1.8.9" dicom-parser "^1.8.9"
pako "^2.0.4" pako "^2.0.4"
uuid "^9.0.0" uuid "^9.0.0"
"@cornerstonejs/streaming-image-volume-loader@^1.70.8": "@cornerstonejs/streaming-image-volume-loader@^1.70.9":
version "1.70.8" version "1.70.9"
resolved "https://registry.yarnpkg.com/@cornerstonejs/streaming-image-volume-loader/-/streaming-image-volume-loader-1.70.8.tgz#97a6b72b254564aef9b3b4e10896d5ed42b13c50" resolved "https://registry.yarnpkg.com/@cornerstonejs/streaming-image-volume-loader/-/streaming-image-volume-loader-1.70.9.tgz#3f3b7c04b3db6c303cb278e5ab8d1916cd91a3b1"
integrity sha512-d53GB3Q0TMWOOzW9kmD03OUFCfTrVRoM/0O2ZRNdrtkj5H87YYLtKSyJsFrey7kC+3VfNVd+KLu4H0RsW/SulQ== integrity sha512-Uay1IIRJMge0Tp7DrgisaqIXowh5IdROXbexmbGVT++0qeyzIQIzXdaUrJpuXDpaB2bYppWEY9moKja0mtlBHw==
dependencies: dependencies:
"@cornerstonejs/core" "^1.70.8" "@cornerstonejs/core" "^1.70.9"
comlink "^4.4.1" comlink "^4.4.1"
"@cornerstonejs/tools@^1.70.8": "@cornerstonejs/tools@^1.70.9":
version "1.70.8" version "1.70.9"
resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-1.70.8.tgz#2318f8d9a31ff77692fe2c7ec3ed1a758b82d13a" resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-1.70.9.tgz#e71b709ba5652918a9c92ad344638d3188d8af2b"
integrity sha512-/hS8FckYtPXK5OYnDPzJUIjMgTyaYQOkwxo0eoRYwbCPFrHoqeT87drSdWdXm2RWR7fR+95ScRNaB1ZGBPEqcA== integrity sha512-/Pbbb/hAeYd0bgrXtAEwQOksdL5qy+zwosk3HMsUCa5S7FnvEOSnSQbs0h8UZwKIkW09LtzAkSiPgJpP7A3cwg==
dependencies: dependencies:
"@cornerstonejs/core" "^1.70.8" "@cornerstonejs/core" "^1.70.9"
"@icr/polyseg-wasm" "0.4.0" "@icr/polyseg-wasm" "0.4.0"
"@types/offscreencanvas" "2019.7.3" "@types/offscreencanvas" "2019.7.3"
comlink "^4.4.1" comlink "^4.4.1"
@ -2086,7 +2086,7 @@
"@docusaurus/theme-search-algolia" "2.4.3" "@docusaurus/theme-search-algolia" "2.4.3"
"@docusaurus/types" "2.4.3" "@docusaurus/types" "2.4.3"
"@docusaurus/react-loadable@5.5.2": "@docusaurus/react-loadable@5.5.2", "react-loadable@npm:@docusaurus/react-loadable@5.5.2":
version "5.5.2" version "5.5.2"
resolved "https://registry.yarnpkg.com/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz#81aae0db81ecafbdaee3651f12804580868fa6ce" resolved "https://registry.yarnpkg.com/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz#81aae0db81ecafbdaee3651f12804580868fa6ce"
integrity sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ== integrity sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==
@ -17743,14 +17743,6 @@ react-loadable-ssr-addon-v5-slorber@^1.0.1:
dependencies: dependencies:
"@babel/runtime" "^7.10.3" "@babel/runtime" "^7.10.3"
"react-loadable@npm:@docusaurus/react-loadable@5.5.2":
version "5.5.2"
resolved "https://registry.yarnpkg.com/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz#81aae0db81ecafbdaee3651f12804580868fa6ce"
integrity sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==
dependencies:
"@types/react" "*"
prop-types "^15.6.2"
react-modal@3.11.2: react-modal@3.11.2:
version "3.11.2" version "3.11.2"
resolved "https://registry.yarnpkg.com/react-modal/-/react-modal-3.11.2.tgz#bad911976d4add31aa30dba8a41d11e21c4ac8a4" resolved "https://registry.yarnpkg.com/react-modal/-/react-modal-3.11.2.tgz#bad911976d4add31aa30dba8a41d11e21c4ac8a4"
@ -19541,7 +19533,7 @@ string-natural-compare@^3.0.1:
resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4"
integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==
"string-width-cjs@npm:string-width@^4.2.0": "string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3:
version "4.2.3" version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@ -19559,15 +19551,6 @@ string-width@^1.0.1:
is-fullwidth-code-point "^1.0.0" is-fullwidth-code-point "^1.0.0"
strip-ansi "^3.0.0" strip-ansi "^3.0.0"
"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
string-width@^2.1.0, string-width@^2.1.1: string-width@^2.1.0, string-width@^2.1.1:
version "2.1.1" version "2.1.1"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
@ -19663,7 +19646,7 @@ stringify-object@^3.3.0:
is-obj "^1.0.1" is-obj "^1.0.1"
is-regexp "^1.0.0" is-regexp "^1.0.0"
"strip-ansi-cjs@npm:strip-ansi@^6.0.1": "strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1" version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@ -19691,13 +19674,6 @@ strip-ansi@^5.1.0:
dependencies: dependencies:
ansi-regex "^4.1.0" ansi-regex "^4.1.0"
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"
strip-ansi@^7.0.0, strip-ansi@^7.0.1: strip-ansi@^7.0.0, strip-ansi@^7.0.1:
version "7.1.0" version "7.1.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
@ -21741,7 +21717,7 @@ worker-loader@3.0.8, worker-loader@^3.0.8:
loader-utils "^2.0.0" loader-utils "^2.0.0"
schema-utils "^3.0.0" schema-utils "^3.0.0"
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
version "7.0.0" version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@ -21767,15 +21743,6 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0:
string-width "^4.1.0" string-width "^4.1.0"
strip-ansi "^6.0.0" strip-ansi "^6.0.0"
wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrap-ansi@^8.0.1, wrap-ansi@^8.1.0: wrap-ansi@^8.0.1, wrap-ansi@^8.1.0:
version "8.1.0" version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"