Compare commits
28
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e074da64e | ||
|
|
d66bad664a | ||
|
|
e1c21a7ce1 | ||
|
|
c785a5e975 | ||
|
|
f133be75d1 | ||
|
|
2f459a0f64 | ||
|
|
ee80e02661 | ||
|
|
4e53fbfe9d | ||
|
|
64dfbeab7a | ||
|
|
9c1112f768 | ||
|
|
9b3be9b0c0 | ||
|
|
6829542c00 | ||
|
|
846c9c1c54 | ||
|
|
85fed49eb1 | ||
|
|
298da03e2f | ||
|
|
141e1cf648 | ||
|
|
ea2ab1a25e | ||
|
|
3d0357c9c0 | ||
|
|
f68aaf973c | ||
|
|
f04d459a63 | ||
|
|
4cf9f2c9cb | ||
|
|
c0cc9752c6 | ||
|
|
06075ecb51 | ||
|
|
509a7b7e57 | ||
|
|
4bbf24b250 | ||
|
|
ebc01a8ca2 | ||
|
|
4fd0c6dfcb | ||
|
|
06a4af06fa |
No files matched your search
Vendored
+4
-1
@@ -28,5 +28,8 @@
|
|||||||
],
|
],
|
||||||
"prettier.disableLanguages": ["html"],
|
"prettier.disableLanguages": ["html"],
|
||||||
"prettier.endOfLine": "lf",
|
"prettier.endOfLine": "lf",
|
||||||
"workbench.colorCustomizations": {}
|
"workbench.colorCustomizations": {},
|
||||||
|
"editor.codeActionsOnSave": {
|
||||||
|
"source.fixAll.eslint": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -40,6 +40,10 @@ export default {
|
|||||||
from: 'right',
|
from: 'right',
|
||||||
// The target component to toggle open/close
|
// The target component to toggle open/close
|
||||||
target: 'target-component-id',
|
target: 'target-component-id',
|
||||||
|
// UI Hint; If the target panel is in a "disabled" state
|
||||||
|
isDisabled: studies => {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
// Overrides `defaultContext`, if specified
|
// Overrides `defaultContext`, if specified
|
||||||
context: ['ACTIVE_VIEWPORT:MAGIC'],
|
context: ['ACTIVE_VIEWPORT:MAGIC'],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ export default {
|
|||||||
/**
|
/**
|
||||||
* MODULE GETTERS
|
* MODULE GETTERS
|
||||||
*/
|
*/
|
||||||
|
|
||||||
getViewportModule() {
|
getViewportModule() {
|
||||||
return '... react component ...';
|
return '... react component ...';
|
||||||
},
|
},
|
||||||
@@ -98,6 +97,9 @@ const panelModule = {
|
|||||||
icon: 'th-list',
|
icon: 'th-list',
|
||||||
label: 'Segments',
|
label: 'Segments',
|
||||||
target: 'segment-panel',
|
target: 'segment-panel',
|
||||||
|
isDisabled: studies => {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
components: [
|
components: [
|
||||||
|
|||||||
@@ -3,6 +3,39 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [2.4.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.4.0...@ohif/extension-cornerstone@2.4.1) (2020-03-03)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* bump react-cornerstone-viewport version to address critical issue ([#1473](https://github.com/OHIF/Viewers/issues/1473)) ([ee80e02](https://github.com/OHIF/Viewers/commit/ee80e026610442e94caf5e4e3e4d193220cd0ece))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [2.4.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.3.1...@ohif/extension-cornerstone@2.4.0) (2020-02-20)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* [#1342](https://github.com/OHIF/Viewers/issues/1342) - Window level tab ([#1429](https://github.com/OHIF/Viewers/issues/1429)) ([ebc01a8](https://github.com/OHIF/Viewers/commit/ebc01a8ca238d5a3437b44d81f75aa8a5e8d0574))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [2.3.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.3.0...@ohif/extension-cornerstone@2.3.1) (2020-02-14)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Creating 2 commands to activate zoom tool and also to move between displaySets ([#1446](https://github.com/OHIF/Viewers/issues/1446)) ([06a4af0](https://github.com/OHIF/Viewers/commit/06a4af06faaecf6fa06ccd90cdfa879ee8d53053))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.3.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.2.2...@ohif/extension-cornerstone@2.3.0) (2020-02-10)
|
# [2.3.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.2.2...@ohif/extension-cornerstone@2.3.0) (2020-02-10)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ohif/extension-cornerstone",
|
"name": "@ohif/extension-cornerstone",
|
||||||
"version": "2.3.0",
|
"version": "2.4.1",
|
||||||
"description": "OHIF extension for Cornerstone",
|
"description": "OHIF extension for Cornerstone",
|
||||||
"author": "OHIF",
|
"author": "OHIF",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -52,6 +52,6 @@
|
|||||||
"lodash.merge": "^4.6.2",
|
"lodash.merge": "^4.6.2",
|
||||||
"lodash.throttle": "^4.1.1",
|
"lodash.throttle": "^4.1.1",
|
||||||
"query-string": "^6.8.3",
|
"query-string": "^6.8.3",
|
||||||
"react-cornerstone-viewport": "2.x.x"
|
"react-cornerstone-viewport": "^2.3.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -74,10 +74,6 @@ const commandsModule = ({ servicesManager }) => {
|
|||||||
}
|
}
|
||||||
cornerstoneTools.setToolActive(toolName, { mouseButtonMask: 1 });
|
cornerstoneTools.setToolActive(toolName, { mouseButtonMask: 1 });
|
||||||
},
|
},
|
||||||
updateViewportDisplaySet: ({ direction }) => {
|
|
||||||
// TODO
|
|
||||||
console.warn('updateDisplaySet: ', direction);
|
|
||||||
},
|
|
||||||
clearAnnotations: ({ viewports }) => {
|
clearAnnotations: ({ viewports }) => {
|
||||||
const element = getEnabledElement(viewports.activeViewportIndex);
|
const element = getEnabledElement(viewports.activeViewportIndex);
|
||||||
if (!element) {
|
if (!element) {
|
||||||
@@ -245,7 +241,19 @@ const commandsModule = ({ servicesManager }) => {
|
|||||||
},
|
},
|
||||||
setCornerstoneLayout: () => {
|
setCornerstoneLayout: () => {
|
||||||
setCornerstoneLayout();
|
setCornerstoneLayout();
|
||||||
}
|
},
|
||||||
|
setWindowLevel: ({ viewports, window, level }) => {
|
||||||
|
const enabledElement = getEnabledElement(viewports.activeViewportIndex);
|
||||||
|
|
||||||
|
if (enabledElement) {
|
||||||
|
let viewport = cornerstone.getViewport(enabledElement);
|
||||||
|
viewport.voi = {
|
||||||
|
windowWidth: Number(window),
|
||||||
|
windowCenter: Number(level),
|
||||||
|
};
|
||||||
|
cornerstone.setViewport(enabledElement, viewport);
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const definitions = {
|
const definitions = {
|
||||||
@@ -334,30 +342,28 @@ const commandsModule = ({ servicesManager }) => {
|
|||||||
storeContexts: ['viewports'],
|
storeContexts: ['viewports'],
|
||||||
options: {},
|
options: {},
|
||||||
},
|
},
|
||||||
// TODO: First/Last image
|
|
||||||
// Next/Previous series/DisplaySet
|
|
||||||
nextViewportDisplaySet: {
|
|
||||||
commandFn: actions.updateViewportDisplaySet,
|
|
||||||
storeContexts: [],
|
|
||||||
options: { direction: 1 },
|
|
||||||
},
|
|
||||||
previousViewportDisplaySet: {
|
|
||||||
commandFn: actions.updateViewportDisplaySet,
|
|
||||||
storeContexts: [],
|
|
||||||
options: { direction: -1 },
|
|
||||||
},
|
|
||||||
// TOOLS
|
// TOOLS
|
||||||
setToolActive: {
|
setToolActive: {
|
||||||
commandFn: actions.setToolActive,
|
commandFn: actions.setToolActive,
|
||||||
storeContexts: [],
|
storeContexts: [],
|
||||||
options: {},
|
options: {},
|
||||||
},
|
},
|
||||||
|
setZoomTool: {
|
||||||
|
commandFn: actions.setToolActive,
|
||||||
|
storeContexts: [],
|
||||||
|
options: { toolName: 'Zoom' },
|
||||||
|
},
|
||||||
setCornerstoneLayout: {
|
setCornerstoneLayout: {
|
||||||
commandFn: actions.setCornerstoneLayout,
|
commandFn: actions.setCornerstoneLayout,
|
||||||
storeContexts: [],
|
storeContexts: [],
|
||||||
options: {},
|
options: {},
|
||||||
context: 'VIEWER',
|
context: 'VIEWER',
|
||||||
},
|
},
|
||||||
|
setWindowLevel: {
|
||||||
|
commandFn: actions.setWindowLevel,
|
||||||
|
storeContexts: ['viewports'],
|
||||||
|
options: {},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -3,6 +3,38 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.2.22](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.2.21...@ohif/extension-vtk@1.2.22) (2020-03-06)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-vtk
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.2.21](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.2.20...@ohif/extension-vtk@1.2.21) (2020-02-29)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-vtk
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.2.20](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.2.19...@ohif/extension-vtk@1.2.20) (2020-02-21)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-vtk
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.2.19](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.2.18...@ohif/extension-vtk@1.2.19) (2020-02-20)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-vtk
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [1.2.18](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.2.17...@ohif/extension-vtk@1.2.18) (2020-02-12)
|
## [1.2.18](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.2.17...@ohif/extension-vtk@1.2.18) (2020-02-12)
|
||||||
|
|
||||||
**Note:** Version bump only for package @ohif/extension-vtk
|
**Note:** Version bump only for package @ohif/extension-vtk
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ohif/extension-vtk",
|
"name": "@ohif/extension-vtk",
|
||||||
"version": "1.2.18",
|
"version": "1.2.22",
|
||||||
"description": "OHIF extension for VTK.js",
|
"description": "OHIF extension for VTK.js",
|
||||||
"author": "OHIF",
|
"author": "OHIF",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -52,8 +52,8 @@
|
|||||||
"react-vtkjs-viewport": "^0.8.3"
|
"react-vtkjs-viewport": "^0.8.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ohif/core": "^2.4.1",
|
"@ohif/core": "^2.5.2",
|
||||||
"@ohif/ui": "^1.2.1",
|
"@ohif/ui": "^1.3.1",
|
||||||
"cornerstone-tools": "^4.12.0",
|
"cornerstone-tools": "^4.12.0",
|
||||||
"cornerstone-wado-image-loader": "^3.0.0",
|
"cornerstone-wado-image-loader": "^3.0.0",
|
||||||
"dicom-parser": "^1.8.3",
|
"dicom-parser": "^1.8.3",
|
||||||
|
|||||||
@@ -3,6 +3,36 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [2.5.2](https://github.com/OHIF/Viewers/compare/@ohif/core@2.5.1...@ohif/core@2.5.2) (2020-03-06)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/core
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [2.5.1](https://github.com/OHIF/Viewers/compare/@ohif/core@2.5.0...@ohif/core@2.5.1) (2020-02-21)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 💡 Update log to warn ([#1454](https://github.com/OHIF/Viewers/issues/1454)) ([509a7b7](https://github.com/OHIF/Viewers/commit/509a7b7e57834a0653add98cc320b2a5dbefd51d)), closes [#1451](https://github.com/OHIF/Viewers/issues/1451)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [2.5.0](https://github.com/OHIF/Viewers/compare/@ohif/core@2.4.1...@ohif/core@2.5.0) (2020-02-20)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* [#1342](https://github.com/OHIF/Viewers/issues/1342) - Window level tab ([#1429](https://github.com/OHIF/Viewers/issues/1429)) ([ebc01a8](https://github.com/OHIF/Viewers/commit/ebc01a8ca238d5a3437b44d81f75aa8a5e8d0574))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.4.1](https://github.com/OHIF/Viewers/compare/@ohif/core@2.4.0...@ohif/core@2.4.1) (2020-02-12)
|
## [2.4.1](https://github.com/OHIF/Viewers/compare/@ohif/core@2.4.0...@ohif/core@2.4.1) (2020-02-12)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ohif/core",
|
"name": "@ohif/core",
|
||||||
"version": "2.4.1",
|
"version": "2.5.2",
|
||||||
"description": "Generic business logic for web-based medical imaging applications",
|
"description": "Generic business logic for web-based medical imaging applications",
|
||||||
"author": "OHIF Core Team",
|
"author": "OHIF Core Team",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
SET_VIEWPORT_ACTIVE,
|
SET_VIEWPORT_ACTIVE,
|
||||||
SET_VIEWPORT_LAYOUT,
|
SET_VIEWPORT_LAYOUT,
|
||||||
SET_VIEWPORT_LAYOUT_AND_DATA,
|
SET_VIEWPORT_LAYOUT_AND_DATA,
|
||||||
|
SET_USER_PREFERENCES,
|
||||||
} from './constants/ActionTypes.js';
|
} from './constants/ActionTypes.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -89,7 +90,7 @@ export const clearStudyLoadingProgress = progressId => ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const setUserPreferences = state => ({
|
export const setUserPreferences = state => ({
|
||||||
type: 'SET_USER_PREFERENCES',
|
type: SET_USER_PREFERENCES,
|
||||||
state,
|
state,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -20,3 +20,8 @@ export const SET_SERVERS = 'SET_SERVERS';
|
|||||||
* EXTENSIONS
|
* EXTENSIONS
|
||||||
*/
|
*/
|
||||||
export const SET_EXTENSION_DATA = 'SET_EXTENSION_DATA';
|
export const SET_EXTENSION_DATA = 'SET_EXTENSION_DATA';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PREFERENCES
|
||||||
|
* */
|
||||||
|
export const SET_USER_PREFERENCES = 'SET_USER_PREFERENCES';
|
||||||
@@ -1,25 +1,30 @@
|
|||||||
import cloneDeep from 'lodash.clonedeep';
|
|
||||||
|
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
windowLevelData: {
|
windowLevelData: {
|
||||||
// order, description, window (int), level (int)
|
1: { description: 'Soft tissue', window: '550', level: '40' },
|
||||||
// 0: { description: 'Soft tissue', window: '', level: '' },
|
2: { description: 'Lung', window: '150', level: '-600' },
|
||||||
|
3: { description: 'Liver', window: '150', level: '90' },
|
||||||
|
4: { description: 'Bone', window: '2500', level: '480' },
|
||||||
|
5: { description: 'Brain', window: '80', level: '40' },
|
||||||
|
6: { description: 'Trest', window: '1', level: '1' },
|
||||||
|
7: { description: '', window: '', level: '' },
|
||||||
|
8: { description: '', window: '', level: '' },
|
||||||
|
9: { description: '', window: '', level: '' },
|
||||||
|
10: { description: '', window: '', level: '' },
|
||||||
},
|
},
|
||||||
generalPreferences: {
|
generalPreferences: {
|
||||||
// language: 'en-US'
|
// language: 'en-US'
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const preferences = (state, action) => {
|
const preferences = (state = defaultState, action) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case 'SET_USER_PREFERENCES': {
|
case 'SET_USER_PREFERENCES': {
|
||||||
const newState = action.state || cloneDeep(defaultState);
|
return Object.assign({}, state, action.state);
|
||||||
|
|
||||||
return Object.assign({}, state, newState);
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return cloneDeep(state) || cloneDeep(defaultState);
|
return state;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { defaultState };
|
||||||
export default preferences;
|
export default preferences;
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { Reducer } from 'redux-testkit';
|
||||||
|
|
||||||
|
import reducer, { defaultState } from './preferences';
|
||||||
|
import { SET_USER_PREFERENCES } from './../constants/ActionTypes.js';
|
||||||
|
|
||||||
|
describe('preferences reducer', () => {
|
||||||
|
it('should return the initial state', () => {
|
||||||
|
expect(reducer(undefined, {})).toEqual(defaultState);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set user preferences state and properly merge with current state', () => {
|
||||||
|
const initialState = defaultState;
|
||||||
|
|
||||||
|
const action = {
|
||||||
|
type: SET_USER_PREFERENCES,
|
||||||
|
state: { generalPreferences: { language: 'es' } },
|
||||||
|
};
|
||||||
|
|
||||||
|
const expectedState = {
|
||||||
|
windowLevelData: defaultState.windowLevelData,
|
||||||
|
generalPreferences: {
|
||||||
|
language: 'es',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
Reducer(reducer)
|
||||||
|
.withState(initialState)
|
||||||
|
.expect(action)
|
||||||
|
.toReturnState(expectedState);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -271,7 +271,7 @@ class MeasurementService {
|
|||||||
/* Assign measurement source instance */
|
/* Assign measurement source instance */
|
||||||
measurement.source = source;
|
measurement.source = source;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error(`Failed to map '${sourceInfo}' measurement for definition ${definition}:`, error.message);
|
log.warn(`Failed to map '${sourceInfo}' measurement for definition ${definition}:`, error.message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ describe('MeasurementService.js', () => {
|
|||||||
|
|
||||||
source.addOrUpdate(definition, measurement);
|
source.addOrUpdate(definition, measurement);
|
||||||
|
|
||||||
expect(log.error.mock.calls.length).toBe(1);
|
expect(log.warn.mock.calls.length).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('adds new measurement with custom id', () => {
|
it('adds new measurement with custom id', () => {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import RetrieveMetadataLoaderAsync from './retrieveMetadataLoaderAsync';
|
|||||||
*/
|
*/
|
||||||
async function RetrieveMetadata(server, studyInstanceUid, filters = {}) {
|
async function RetrieveMetadata(server, studyInstanceUid, filters = {}) {
|
||||||
const RetrieveMetadataLoader =
|
const RetrieveMetadataLoader =
|
||||||
server.enableStudyLazyLoad !== false
|
server.enableStudyLazyLoad != false
|
||||||
? RetrieveMetadataLoaderAsync
|
? RetrieveMetadataLoaderAsync
|
||||||
: RetrieveMetadataLoaderSync;
|
: RetrieveMetadataLoaderSync;
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,28 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.3.1](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.3.0...@ohif/ui@1.3.1) (2020-02-29)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* prevent the native context menu from appearing when right-clicking on a measurement or angle (https://github.com/OHIF/Viewers/issues/1406) ([#1469](https://github.com/OHIF/Viewers/issues/1469)) ([9b3be9b](https://github.com/OHIF/Viewers/commit/9b3be9b0c082c9a5b62f2a40f42e59381860fe73))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [1.3.0](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.2.1...@ohif/ui@1.3.0) (2020-02-20)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* [#1342](https://github.com/OHIF/Viewers/issues/1342) - Window level tab ([#1429](https://github.com/OHIF/Viewers/issues/1429)) ([ebc01a8](https://github.com/OHIF/Viewers/commit/ebc01a8ca238d5a3437b44d81f75aa8a5e8d0574))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [1.2.1](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.2.0...@ohif/ui@1.2.1) (2020-02-12)
|
## [1.2.1](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.2.0...@ohif/ui@1.2.1) (2020-02-12)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ohif/ui",
|
"name": "@ohif/ui",
|
||||||
"version": "1.2.1",
|
"version": "1.3.1",
|
||||||
"description": "A set of React components for Medical Imaging Viewers",
|
"description": "A set of React components for Medical Imaging Viewers",
|
||||||
"author": "OHIF Contributors",
|
"author": "OHIF Contributors",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import React from 'react';
|
||||||
import './ContextMenu.css';
|
import './ContextMenu.css';
|
||||||
|
|
||||||
const ContextMenu = ({ items, onClick }) => {
|
const ContextMenu = ({ items, onClick }) => {
|
||||||
return (
|
return (
|
||||||
<div className="ContextMenu">
|
<div className="ContextMenu" onContextMenu={e => e.preventDefault()}>
|
||||||
<ul>
|
<ul>
|
||||||
{items.map((item, index) => (
|
{items.map((item, index) => (
|
||||||
<li key={index}>
|
<li key={index}>
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ function TabComponents({ tabs, customProps = {} }) {
|
|||||||
<div className="dialog-separator-after">
|
<div className="dialog-separator-after">
|
||||||
<ul className="nav nav-tabs">
|
<ul className="nav nav-tabs">
|
||||||
{tabs.map((tab, index) => {
|
{tabs.map((tab, index) => {
|
||||||
const { name, hidden } = tab;
|
const { name, hidden = false } = tab;
|
||||||
return (
|
return (
|
||||||
!hidden && (
|
!hidden && (
|
||||||
<li
|
<li
|
||||||
@@ -70,7 +70,11 @@ function TabComponents({ tabs, customProps = {} }) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{tabs.map((tab, index) => {
|
{tabs.map((tab, index) => {
|
||||||
const { Component, customProps: tabCustomProps, hidden } = tab;
|
const {
|
||||||
|
Component,
|
||||||
|
customProps: tabCustomProps,
|
||||||
|
hidden = false,
|
||||||
|
} = tab;
|
||||||
return (
|
return (
|
||||||
!hidden && (
|
!hidden && (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -3,6 +3,82 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [3.7.6](https://github.com/OHIF/Viewers/compare/@ohif/viewer@3.7.5...@ohif/viewer@3.7.6) (2020-03-06)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [3.7.5](https://github.com/OHIF/Viewers/compare/@ohif/viewer@3.7.4...@ohif/viewer@3.7.5) (2020-03-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [3.7.4](https://github.com/OHIF/Viewers/compare/@ohif/viewer@3.7.3...@ohif/viewer@3.7.4) (2020-03-03)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [3.7.3](https://github.com/OHIF/Viewers/compare/@ohif/viewer@3.7.2...@ohif/viewer@3.7.3) (2020-03-02)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* GCloud dataset picker dialog broken ([#1453](https://github.com/OHIF/Viewers/issues/1453)) ([64dfbea](https://github.com/OHIF/Viewers/commit/64dfbeab7af98277efefadd334df14db79e32a4f))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [3.7.2](https://github.com/OHIF/Viewers/compare/@ohif/viewer@3.7.1...@ohif/viewer@3.7.2) (2020-02-29)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* prevent the native context menu from appearing when right-clicking on a measurement or angle (https://github.com/OHIF/Viewers/issues/1406) ([#1469](https://github.com/OHIF/Viewers/issues/1469)) ([9b3be9b](https://github.com/OHIF/Viewers/commit/9b3be9b0c082c9a5b62f2a40f42e59381860fe73))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [3.7.1](https://github.com/OHIF/Viewers/compare/@ohif/viewer@3.7.0...@ohif/viewer@3.7.1) (2020-02-21)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [3.7.0](https://github.com/OHIF/Viewers/compare/@ohif/viewer@3.6.3...@ohif/viewer@3.7.0) (2020-02-20)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* [#1342](https://github.com/OHIF/Viewers/issues/1342) - Window level tab ([#1429](https://github.com/OHIF/Viewers/issues/1429)) ([ebc01a8](https://github.com/OHIF/Viewers/commit/ebc01a8ca238d5a3437b44d81f75aa8a5e8d0574))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [3.6.3](https://github.com/OHIF/Viewers/compare/@ohif/viewer@3.6.2...@ohif/viewer@3.6.3) (2020-02-14)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Creating 2 commands to activate zoom tool and also to move between displaySets ([#1446](https://github.com/OHIF/Viewers/issues/1446)) ([06a4af0](https://github.com/OHIF/Viewers/commit/06a4af06faaecf6fa06ccd90cdfa879ee8d53053))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [3.6.2](https://github.com/OHIF/Viewers/compare/@ohif/viewer@3.6.1...@ohif/viewer@3.6.2) (2020-02-12)
|
## [3.6.2](https://github.com/OHIF/Viewers/compare/@ohif/viewer@3.6.1...@ohif/viewer@3.6.2) (2020-02-12)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -419,7 +419,7 @@ describe('OHIF User Preferences', () => {
|
|||||||
cy.get('.HotkeysPreferences').within(() => {
|
cy.get('.HotkeysPreferences').within(() => {
|
||||||
cy.contains('Rotate Right') // label we're looking for
|
cy.contains('Rotate Right') // label we're looking for
|
||||||
.parent()
|
.parent()
|
||||||
.find('.errorMessage')
|
.find('.preferencesInputErrorMessage')
|
||||||
.as('errorMsg')
|
.as('errorMsg')
|
||||||
.should('have.text', '"Invert" is already using the "i" shortcut.');
|
.should('have.text', '"Invert" is already using the "i" shortcut.');
|
||||||
});
|
});
|
||||||
@@ -440,7 +440,7 @@ describe('OHIF User Preferences', () => {
|
|||||||
cy.get('.HotkeysPreferences').within(() => {
|
cy.get('.HotkeysPreferences').within(() => {
|
||||||
cy.contains('Rotate Right') // label we're looking for
|
cy.contains('Rotate Right') // label we're looking for
|
||||||
.parent()
|
.parent()
|
||||||
.find('.errorMessage')
|
.find('.preferencesInputErrorMessage')
|
||||||
.as('errorMsg')
|
.as('errorMsg')
|
||||||
.should('have.text', '"ctrl+z" shortcut combination is not allowed');
|
.should('have.text', '"ctrl+z" shortcut combination is not allowed');
|
||||||
});
|
});
|
||||||
@@ -461,7 +461,7 @@ describe('OHIF User Preferences', () => {
|
|||||||
cy.get('.HotkeysPreferences').within(() => {
|
cy.get('.HotkeysPreferences').within(() => {
|
||||||
cy.contains('Zoom Out') // label we're looking for
|
cy.contains('Zoom Out') // label we're looking for
|
||||||
.parent()
|
.parent()
|
||||||
.find('.errorMessage')
|
.find('.preferencesInputErrorMessage')
|
||||||
.as('errorMsg')
|
.as('errorMsg')
|
||||||
.should(
|
.should(
|
||||||
'have.text',
|
'have.text',
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ohif/viewer",
|
"name": "@ohif/viewer",
|
||||||
"version": "3.6.2",
|
"version": "3.7.6",
|
||||||
"description": "OHIF Viewer",
|
"description": "OHIF Viewer",
|
||||||
"author": "OHIF Contributors",
|
"author": "OHIF Contributors",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -47,15 +47,15 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.5.5",
|
"@babel/runtime": "^7.5.5",
|
||||||
"@ohif/core": "^2.4.1",
|
"@ohif/core": "^2.5.2",
|
||||||
"@ohif/extension-cornerstone": "^2.3.0",
|
"@ohif/extension-cornerstone": "^2.4.1",
|
||||||
"@ohif/extension-dicom-html": "^1.1.0",
|
"@ohif/extension-dicom-html": "^1.1.0",
|
||||||
"@ohif/extension-dicom-microscopy": "^0.50.6",
|
"@ohif/extension-dicom-microscopy": "^0.50.6",
|
||||||
"@ohif/extension-dicom-pdf": "^1.0.1",
|
"@ohif/extension-dicom-pdf": "^1.0.1",
|
||||||
"@ohif/extension-lesion-tracker": "^0.2.0",
|
"@ohif/extension-lesion-tracker": "^0.2.0",
|
||||||
"@ohif/extension-vtk": "^1.2.18",
|
"@ohif/extension-vtk": "^1.2.22",
|
||||||
"@ohif/i18n": "^0.52.6",
|
"@ohif/i18n": "^0.52.6",
|
||||||
"@ohif/ui": "^1.2.1",
|
"@ohif/ui": "^1.3.1",
|
||||||
"@tanem/react-nprogress": "^1.1.25",
|
"@tanem/react-nprogress": "^1.1.25",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"core-js": "^3.2.1",
|
"core-js": "^3.2.1",
|
||||||
|
|||||||
@@ -58,17 +58,63 @@ window.config = {
|
|||||||
// firstImage
|
// firstImage
|
||||||
// lastImage
|
// lastImage
|
||||||
{
|
{
|
||||||
commandName: 'nextViewportDisplaySet',
|
commandName: 'previousViewportDisplaySet',
|
||||||
label: 'Previous Series',
|
label: 'Previous Series',
|
||||||
keys: ['pagedown'],
|
keys: ['pagedown'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
commandName: 'previousViewportDisplaySet',
|
commandName: 'nextViewportDisplaySet',
|
||||||
label: 'Next Series',
|
label: 'Next Series',
|
||||||
keys: ['pageup'],
|
keys: ['pageup'],
|
||||||
},
|
},
|
||||||
// ~ Cornerstone Tools
|
// ~ Cornerstone Tools
|
||||||
{ commandName: 'setZoomTool', label: 'Zoom', keys: ['z'] },
|
{ commandName: 'setZoomTool', label: 'Zoom', keys: ['z'] },
|
||||||
|
// ~ Window level presets
|
||||||
|
{
|
||||||
|
commandName: 'windowLevelPreset1',
|
||||||
|
label: 'W/L Preset 1',
|
||||||
|
keys: ['1'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
commandName: 'windowLevelPreset2',
|
||||||
|
label: 'W/L Preset 2',
|
||||||
|
keys: ['2'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
commandName: 'windowLevelPreset3',
|
||||||
|
label: 'W/L Preset 3',
|
||||||
|
keys: ['3'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
commandName: 'windowLevelPreset4',
|
||||||
|
label: 'W/L Preset 4',
|
||||||
|
keys: ['4'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
commandName: 'windowLevelPreset5',
|
||||||
|
label: 'W/L Preset 5',
|
||||||
|
keys: ['5'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
commandName: 'windowLevelPreset6',
|
||||||
|
label: 'W/L Preset 6',
|
||||||
|
keys: ['6'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
commandName: 'windowLevelPreset7',
|
||||||
|
label: 'W/L Preset 7',
|
||||||
|
keys: ['7'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
commandName: 'windowLevelPreset8',
|
||||||
|
label: 'W/L Preset 8',
|
||||||
|
keys: ['8'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
commandName: 'windowLevelPreset9',
|
||||||
|
label: 'W/L Preset 9',
|
||||||
|
keys: ['9'],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
cornerstoneExtensionConfig: {},
|
cornerstoneExtensionConfig: {},
|
||||||
};
|
};
|
||||||
@@ -48,16 +48,62 @@ window.config = {
|
|||||||
{ commandName: 'nextImage', label: 'Next Image', keys: ['down'] },
|
{ commandName: 'nextImage', label: 'Next Image', keys: ['down'] },
|
||||||
{ commandName: 'previousImage', label: 'Previous Image', keys: ['up'] },
|
{ commandName: 'previousImage', label: 'Previous Image', keys: ['up'] },
|
||||||
{
|
{
|
||||||
commandName: 'nextViewportDisplaySet',
|
commandName: 'previousViewportDisplaySet',
|
||||||
label: 'Previous Series',
|
label: 'Previous Series',
|
||||||
keys: ['pagedown'],
|
keys: ['pagedown'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
commandName: 'previousViewportDisplaySet',
|
commandName: 'nextViewportDisplaySet',
|
||||||
label: 'Next Series',
|
label: 'Next Series',
|
||||||
keys: ['pageup'],
|
keys: ['pageup'],
|
||||||
},
|
},
|
||||||
{ commandName: 'setZoomTool', label: 'Zoom', keys: ['z'] },
|
{ commandName: 'setZoomTool', label: 'Zoom', keys: ['z'] },
|
||||||
|
// ~ Window level presets
|
||||||
|
{
|
||||||
|
commandName: 'windowLevelPreset1',
|
||||||
|
label: 'W/L Preset 1',
|
||||||
|
keys: ['1'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
commandName: 'windowLevelPreset2',
|
||||||
|
label: 'W/L Preset 2',
|
||||||
|
keys: ['2'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
commandName: 'windowLevelPreset3',
|
||||||
|
label: 'W/L Preset 3',
|
||||||
|
keys: ['3'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
commandName: 'windowLevelPreset4',
|
||||||
|
label: 'W/L Preset 4',
|
||||||
|
keys: ['4'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
commandName: 'windowLevelPreset5',
|
||||||
|
label: 'W/L Preset 5',
|
||||||
|
keys: ['5'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
commandName: 'windowLevelPreset6',
|
||||||
|
label: 'W/L Preset 6',
|
||||||
|
keys: ['6'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
commandName: 'windowLevelPreset7',
|
||||||
|
label: 'W/L Preset 7',
|
||||||
|
keys: ['7'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
commandName: 'windowLevelPreset8',
|
||||||
|
label: 'W/L Preset 8',
|
||||||
|
keys: ['8'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
commandName: 'windowLevelPreset9',
|
||||||
|
label: 'W/L Preset 9',
|
||||||
|
keys: ['9'],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
i18n: {
|
i18n: {
|
||||||
LOCIZE_PROJECTID: 'a8da3f9a-e467-4dd6-af33-474d582a0294',
|
LOCIZE_PROJECTID: 'a8da3f9a-e467-4dd6-af33-474d582a0294',
|
||||||
|
|||||||
@@ -53,17 +53,63 @@ window.config = {
|
|||||||
// firstImage
|
// firstImage
|
||||||
// lastImage
|
// lastImage
|
||||||
{
|
{
|
||||||
commandName: 'nextViewportDisplaySet',
|
commandName: 'previousViewportDisplaySet',
|
||||||
label: 'Previous Series',
|
label: 'Previous Series',
|
||||||
keys: ['pagedown'],
|
keys: ['pagedown'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
commandName: 'previousViewportDisplaySet',
|
commandName: 'nextViewportDisplaySet',
|
||||||
label: 'Next Series',
|
label: 'Next Series',
|
||||||
keys: ['pageup'],
|
keys: ['pageup'],
|
||||||
},
|
},
|
||||||
// ~ Cornerstone Tools
|
// ~ Cornerstone Tools
|
||||||
{ commandName: 'setZoomTool', label: 'Zoom', keys: ['z'] },
|
{ commandName: 'setZoomTool', label: 'Zoom', keys: ['z'] },
|
||||||
|
// ~ Window level presets
|
||||||
|
{
|
||||||
|
commandName: 'windowLevelPreset1',
|
||||||
|
label: 'W/L Preset 1',
|
||||||
|
keys: ['1'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
commandName: 'windowLevelPreset2',
|
||||||
|
label: 'W/L Preset 2',
|
||||||
|
keys: ['2'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
commandName: 'windowLevelPreset3',
|
||||||
|
label: 'W/L Preset 3',
|
||||||
|
keys: ['3'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
commandName: 'windowLevelPreset4',
|
||||||
|
label: 'W/L Preset 4',
|
||||||
|
keys: ['4'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
commandName: 'windowLevelPreset5',
|
||||||
|
label: 'W/L Preset 5',
|
||||||
|
keys: ['5'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
commandName: 'windowLevelPreset6',
|
||||||
|
label: 'W/L Preset 6',
|
||||||
|
keys: ['6'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
commandName: 'windowLevelPreset7',
|
||||||
|
label: 'W/L Preset 7',
|
||||||
|
keys: ['7'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
commandName: 'windowLevelPreset8',
|
||||||
|
label: 'W/L Preset 8',
|
||||||
|
keys: ['8'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
commandName: 'windowLevelPreset9',
|
||||||
|
label: 'W/L Preset 9',
|
||||||
|
keys: ['9'],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
i18n: {
|
i18n: {
|
||||||
LOCIZE_PROJECTID: 'a8da3f9a-e467-4dd6-af33-474d582a0294',
|
LOCIZE_PROJECTID: 'a8da3f9a-e467-4dd6-af33-474d582a0294',
|
||||||
|
|||||||
@@ -1,39 +1,140 @@
|
|||||||
import { redux } from "@ohif/core";
|
import { redux } from '@ohif/core';
|
||||||
import store from "./../../store";
|
import store from './../../store';
|
||||||
const { setViewportActive } = redux.actions;
|
|
||||||
|
|
||||||
const actions = {
|
const commandsModule = ({ commandsManager }) => {
|
||||||
updateViewportDisplaySet: ({ direction }) => {
|
const { setViewportActive, setActiveViewportSpecificData } = redux.actions;
|
||||||
// TODO
|
|
||||||
// console.warn('updateDisplaySet: ', direction);
|
|
||||||
},
|
|
||||||
updateActiveViewport: ({ viewports, direction }) => {
|
|
||||||
const { viewportSpecificData, activeViewportIndex } = viewports;
|
|
||||||
const maxIndex = Object.keys(viewportSpecificData).length - 1;
|
|
||||||
|
|
||||||
let newIndex = activeViewportIndex + direction;
|
const actions = {
|
||||||
newIndex = newIndex > maxIndex ? 0 : newIndex;
|
updateActiveViewport: ({ viewports, direction }) => {
|
||||||
newIndex = newIndex < 0 ? maxIndex : newIndex;
|
const { viewportSpecificData, activeViewportIndex } = viewports;
|
||||||
|
const maxIndex = Object.keys(viewportSpecificData).length - 1;
|
||||||
|
|
||||||
store.dispatch(setViewportActive(newIndex));
|
let newIndex = activeViewportIndex + direction;
|
||||||
}
|
newIndex = newIndex > maxIndex ? 0 : newIndex;
|
||||||
|
newIndex = newIndex < 0 ? maxIndex : newIndex;
|
||||||
|
|
||||||
|
store.dispatch(setViewportActive(newIndex));
|
||||||
|
},
|
||||||
|
setWindowLevelPreset: ({ viewports, preset }) => {
|
||||||
|
const state = store.getState();
|
||||||
|
const { preferences = {} } = state;
|
||||||
|
const { window, level } =
|
||||||
|
preferences.windowLevelData && preferences.windowLevelData[preset];
|
||||||
|
|
||||||
|
if (window && level) {
|
||||||
|
commandsManager.runCommand('setWindowLevel', {
|
||||||
|
viewports,
|
||||||
|
window,
|
||||||
|
level,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updateViewportDisplaySet: ({ viewports, direction }) => {
|
||||||
|
const viewportSpecificData = { ...viewports.viewportSpecificData };
|
||||||
|
const activeViewport =
|
||||||
|
viewportSpecificData[viewports.activeViewportIndex];
|
||||||
|
const studyMetadata = utils.studyMetadataManager.get(
|
||||||
|
activeViewport.studyInstanceUid
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!studyMetadata) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const allDisplaySets = studyMetadata.getDisplaySets();
|
||||||
|
const currentDisplaySetIndex = allDisplaySets.findIndex(
|
||||||
|
displaySet =>
|
||||||
|
displaySet.displaySetInstanceUid ===
|
||||||
|
activeViewport.displaySetInstanceUid
|
||||||
|
);
|
||||||
|
if (currentDisplaySetIndex < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newDisplaySetIndex = currentDisplaySetIndex + direction;
|
||||||
|
const newDisplaySetData = allDisplaySets[newDisplaySetIndex];
|
||||||
|
if (!newDisplaySetData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
store.dispatch(setActiveViewportSpecificData(newDisplaySetData));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const definitions = {
|
||||||
|
// Next/Previous active viewport
|
||||||
|
incrementActiveViewport: {
|
||||||
|
commandFn: actions.updateActiveViewport,
|
||||||
|
storeContexts: ['viewports'],
|
||||||
|
options: { direction: 1 },
|
||||||
|
},
|
||||||
|
decrementActiveViewport: {
|
||||||
|
commandFn: actions.updateActiveViewport,
|
||||||
|
storeContexts: ['viewports'],
|
||||||
|
options: { direction: -1 },
|
||||||
|
},
|
||||||
|
// Window level Presets
|
||||||
|
windowLevelPreset1: {
|
||||||
|
commandFn: actions.setWindowLevelPreset,
|
||||||
|
storeContexts: ['viewports'],
|
||||||
|
options: { preset: 1 },
|
||||||
|
},
|
||||||
|
windowLevelPreset2: {
|
||||||
|
commandFn: actions.setWindowLevelPreset,
|
||||||
|
storeContexts: ['viewports'],
|
||||||
|
options: { preset: 2 },
|
||||||
|
},
|
||||||
|
windowLevelPreset3: {
|
||||||
|
commandFn: actions.setWindowLevelPreset,
|
||||||
|
storeContexts: ['viewports'],
|
||||||
|
options: { preset: 3 },
|
||||||
|
},
|
||||||
|
windowLevelPreset4: {
|
||||||
|
commandFn: actions.setWindowLevelPreset,
|
||||||
|
storeContexts: ['viewports'],
|
||||||
|
options: { preset: 4 },
|
||||||
|
},
|
||||||
|
windowLevelPreset5: {
|
||||||
|
commandFn: actions.setWindowLevelPreset,
|
||||||
|
storeContexts: ['viewports'],
|
||||||
|
options: { preset: 5 },
|
||||||
|
},
|
||||||
|
windowLevelPreset6: {
|
||||||
|
commandFn: actions.setWindowLevelPreset,
|
||||||
|
storeContexts: ['viewports'],
|
||||||
|
options: { preset: 6 },
|
||||||
|
},
|
||||||
|
windowLevelPreset7: {
|
||||||
|
commandFn: actions.setWindowLevelPreset,
|
||||||
|
storeContexts: ['viewports'],
|
||||||
|
options: { preset: 7 },
|
||||||
|
},
|
||||||
|
windowLevelPreset8: {
|
||||||
|
commandFn: actions.setWindowLevelPreset,
|
||||||
|
storeContexts: ['viewports'],
|
||||||
|
options: { preset: 8 },
|
||||||
|
},
|
||||||
|
windowLevelPreset9: {
|
||||||
|
commandFn: actions.setWindowLevelPreset,
|
||||||
|
storeContexts: ['viewports'],
|
||||||
|
options: { preset: 9 },
|
||||||
|
},
|
||||||
|
nextViewportDisplaySet: {
|
||||||
|
commandFn: actions.updateViewportDisplaySet,
|
||||||
|
storeContexts: ['viewports'],
|
||||||
|
options: { direction: 1 },
|
||||||
|
},
|
||||||
|
previousViewportDisplaySet: {
|
||||||
|
commandFn: actions.updateViewportDisplaySet,
|
||||||
|
storeContexts: ['viewports'],
|
||||||
|
options: { direction: -1 },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
definitions,
|
||||||
|
defaultContext: 'VIEWER',
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const definitions = {
|
export default commandsModule;
|
||||||
// Next/Previous active viewport
|
|
||||||
incrementActiveViewport: {
|
|
||||||
commandFn: actions.updateActiveViewport,
|
|
||||||
storeContexts: ["viewports"],
|
|
||||||
options: { direction: 1 }
|
|
||||||
},
|
|
||||||
decrementActiveViewport: {
|
|
||||||
commandFn: actions.updateActiveViewport,
|
|
||||||
storeContexts: ["viewports"],
|
|
||||||
options: { direction: -1 }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default {
|
|
||||||
definitions,
|
|
||||||
defaultContext: "VIEWER"
|
|
||||||
};
|
|
||||||
@@ -2,7 +2,7 @@ import commandsModule from './commandsModule.js';
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
id: 'generic-viewer-commands',
|
id: 'generic-viewer-commands',
|
||||||
getCommandsModule() {
|
getCommandsModule({ commandsManager }) {
|
||||||
return commandsModule;
|
return commandsModule({ commandsManager });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -168,9 +168,11 @@ function HotkeysPreferences({ onClose }) {
|
|||||||
keys={keys}
|
keys={keys}
|
||||||
modifier_keys={MODIFIER_KEYS}
|
modifier_keys={MODIFIER_KEYS}
|
||||||
handleChange={handleChange}
|
handleChange={handleChange}
|
||||||
classNames={'hotkeyInput'}
|
classNames={'preferencesInput'}
|
||||||
></HotkeyField>
|
></HotkeyField>
|
||||||
<span className="errorMessage">{errorMessage}</span>
|
<span className="preferencesInputErrorMessage">
|
||||||
|
{errorMessage}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,11 +2,6 @@
|
|||||||
display: flex
|
display: flex
|
||||||
padding: 20px
|
padding: 20px
|
||||||
|
|
||||||
.errorMessage
|
|
||||||
color: var(--state-error-text)
|
|
||||||
font-size: 10px
|
|
||||||
text-transform: uppercase
|
|
||||||
|
|
||||||
.hotkeyTable
|
.hotkeyTable
|
||||||
display: flex
|
display: flex
|
||||||
flex-direction: row
|
flex-direction: row
|
||||||
@@ -40,28 +35,6 @@
|
|||||||
flex-basis: 0
|
flex-basis: 0
|
||||||
flex-grow: 1.5
|
flex-grow: 1.5
|
||||||
|
|
||||||
.hotkeyInput
|
|
||||||
font-weight: 400
|
|
||||||
cursor: pointer
|
|
||||||
transition: background-color .3s ease,border-color .3s ease
|
|
||||||
background-color: var(--ui-gray)
|
|
||||||
color: var(--text-primary-color)
|
|
||||||
border-color: var(--ui-border-coolor)
|
|
||||||
border: 0
|
|
||||||
border-radius: 2px
|
|
||||||
font-size: 14px
|
|
||||||
height: 30px
|
|
||||||
width: 100%
|
|
||||||
line-height: 16px
|
|
||||||
padding: 8px 9px 6px
|
|
||||||
text-align: center
|
|
||||||
|
|
||||||
.hotkeyInput:focus
|
|
||||||
border-color: var(--active-color)
|
|
||||||
background-color: var(--ui-gray-dark)
|
|
||||||
box-shadow: 0 0 0 2px var(--active-color) !important
|
|
||||||
outline: 0
|
|
||||||
|
|
||||||
.hotkeyLabel
|
.hotkeyLabel
|
||||||
padding: 5px 15px 5px 0
|
padding: 5px 15px 5px 0
|
||||||
text-align: right
|
text-align: right
|
||||||
@@ -69,5 +42,5 @@
|
|||||||
flex-grow: 1.5
|
flex-grow: 1.5
|
||||||
|
|
||||||
.stateError
|
.stateError
|
||||||
.hotkeyInput
|
.preferencesInput
|
||||||
background-color: var(--state-error)
|
background-color: var(--state-error)
|
||||||
@@ -8,24 +8,23 @@ import { HotkeysPreferences } from './HotkeysPreferences';
|
|||||||
import { WindowLevelPreferences } from './WindowLevelPreferences';
|
import { WindowLevelPreferences } from './WindowLevelPreferences';
|
||||||
import { GeneralPreferences } from './GeneralPreferences';
|
import { GeneralPreferences } from './GeneralPreferences';
|
||||||
|
|
||||||
|
import './UserPreferences.styl';
|
||||||
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
{
|
{
|
||||||
name: 'Hotkeys',
|
name: 'Hotkeys',
|
||||||
Component: HotkeysPreferences,
|
Component: HotkeysPreferences,
|
||||||
customProps: {},
|
customProps: {},
|
||||||
hidden: false,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'General',
|
name: 'General',
|
||||||
Component: GeneralPreferences,
|
Component: GeneralPreferences,
|
||||||
customProps: {},
|
customProps: {},
|
||||||
hidden: false,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Window Level',
|
name: 'Window Level',
|
||||||
Component: WindowLevelPreferences,
|
Component: WindowLevelPreferences,
|
||||||
customProps: {},
|
customProps: {},
|
||||||
hidden: true,
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
.preferencesInputErrorMessage
|
||||||
|
color: var(--state-error-text)
|
||||||
|
font-size: 10px
|
||||||
|
text-transform: uppercase
|
||||||
|
|
||||||
|
.preferencesInput
|
||||||
|
font-weight: 400
|
||||||
|
cursor: pointer
|
||||||
|
transition: background-color .3s ease,border-color .3s ease
|
||||||
|
background-color: var(--ui-gray)
|
||||||
|
color: var(--text-primary-color)
|
||||||
|
border-color: var(--ui-border-coolor)
|
||||||
|
border: 0
|
||||||
|
border-radius: 2px
|
||||||
|
font-size: 14px
|
||||||
|
height: 30px
|
||||||
|
width: 100%
|
||||||
|
line-height: 16px
|
||||||
|
padding: 8px 9px 6px
|
||||||
|
text-align: center
|
||||||
|
|
||||||
|
.preferencesInput:focus
|
||||||
|
border-color: var(--active-color)
|
||||||
|
background-color: var(--ui-gray-dark)
|
||||||
|
box-shadow: 0 0 0 2px var(--active-color) !important
|
||||||
|
outline: 0
|
||||||
@@ -1,19 +1,115 @@
|
|||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import { useSelector, useDispatch } from 'react-redux';
|
||||||
|
import { redux } from '@ohif/core';
|
||||||
|
|
||||||
import { TabFooter } from '@ohif/ui';
|
import { TabFooter, useSnackbarContext } from '@ohif/ui';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
const { actions } = redux;
|
||||||
|
|
||||||
|
import './WindowLevelPreferences.styl';
|
||||||
|
|
||||||
function WindowLevelPreferences({ onClose }) {
|
function WindowLevelPreferences({ onClose }) {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
const windowLevelData = useSelector(state => {
|
||||||
|
const { preferences = {} } = state;
|
||||||
|
const { windowLevelData } = preferences;
|
||||||
|
|
||||||
|
return windowLevelData;
|
||||||
|
});
|
||||||
|
|
||||||
|
const [state, setState] = useState({
|
||||||
|
values: { ...windowLevelData },
|
||||||
|
});
|
||||||
|
|
||||||
const { t } = useTranslation('UserPreferencesModal');
|
const { t } = useTranslation('UserPreferencesModal');
|
||||||
const onResetPreferences = () => {};
|
const onResetPreferences = () => {};
|
||||||
const onSave = () => {};
|
|
||||||
const hasErrors = false;
|
const hasErrors = false;
|
||||||
|
const onSave = () => {
|
||||||
|
dispatch(actions.setUserPreferences({ windowLevelData: state.values }));
|
||||||
|
|
||||||
|
onClose();
|
||||||
|
|
||||||
|
snackbar.show({
|
||||||
|
message: t('SaveMessage'),
|
||||||
|
type: 'success',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const snackbar = useSnackbarContext();
|
||||||
|
|
||||||
|
const handleInputChange = event => {
|
||||||
|
const $target = event.target;
|
||||||
|
const { key, inputname } = $target.dataset;
|
||||||
|
const inputValue = $target.value;
|
||||||
|
|
||||||
|
if (!state.values[key] || !state.values[key][inputname]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(prevState => ({
|
||||||
|
...prevState,
|
||||||
|
values: {
|
||||||
|
...prevState.values,
|
||||||
|
[key]: {
|
||||||
|
...prevState.values[key],
|
||||||
|
[inputname]: inputValue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<div className="">Component content: {name}</div>
|
<div className="WindowLevelPreferences">
|
||||||
<div className="">TDB!</div>
|
<div className="wlColumn">
|
||||||
|
<div className="wlRow header">
|
||||||
|
<div className="wlColumn preset">Preset</div>
|
||||||
|
<div className="wlColumn description">Description</div>
|
||||||
|
<div className="wlColumn window">Window</div>
|
||||||
|
<div className="wlColumn level">Level</div>
|
||||||
|
</div>
|
||||||
|
{Object.keys(state.values).map((key, index) => {
|
||||||
|
return (
|
||||||
|
<div className="wlRow" key={key}>
|
||||||
|
<div className="wlColumn preset">{key}</div>
|
||||||
|
<div className="wlColumn description">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="preferencesInput"
|
||||||
|
value={state.values[key].description}
|
||||||
|
data-key={key}
|
||||||
|
data-inputname="description"
|
||||||
|
onChange={handleInputChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="wlColumn window">
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
className="preferencesInput"
|
||||||
|
value={state.values[key].window}
|
||||||
|
data-key={key}
|
||||||
|
data-inputname="window"
|
||||||
|
onChange={handleInputChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="wlColumn level">
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
className="preferencesInput"
|
||||||
|
value={state.values[key].level}
|
||||||
|
data-key={key}
|
||||||
|
data-inputname="level"
|
||||||
|
onChange={handleInputChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<TabFooter
|
<TabFooter
|
||||||
onResetPreferences={onResetPreferences}
|
onResetPreferences={onResetPreferences}
|
||||||
onSave={onSave}
|
onSave={onSave}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
.WindowLevelPreferences
|
||||||
|
display: flex
|
||||||
|
padding: 20px 0
|
||||||
|
text-align: center
|
||||||
|
|
||||||
|
.wlColumn
|
||||||
|
display: flex
|
||||||
|
flex-direction: column
|
||||||
|
flex-basis: 0
|
||||||
|
flex-grow: 1.5
|
||||||
|
margin: 0 5px
|
||||||
|
|
||||||
|
.wlRow
|
||||||
|
display: flex
|
||||||
|
flex-direction: row
|
||||||
|
margin: 5px 0
|
||||||
|
|
||||||
|
.header
|
||||||
|
|
||||||
|
.preset
|
||||||
|
flex-grow: 0.5
|
||||||
|
|
||||||
|
.window,
|
||||||
|
.level
|
||||||
|
flex-grow: 1
|
||||||
|
|
||||||
|
.description
|
||||||
|
flex-grow: 2
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { commandsManager } from './../App.js';
|
|
||||||
|
|
||||||
import { ContextMenu } from '@ohif/ui';
|
import { ContextMenu } from '@ohif/ui';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React from 'react';
|
||||||
|
import { commandsManager } from './../App.js';
|
||||||
|
|
||||||
const toolTypes = [
|
const toolTypes = [
|
||||||
'Angle',
|
'Angle',
|
||||||
@@ -94,7 +93,7 @@ const ToolContextMenu = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ToolContextMenu">
|
<div className="ToolContextMenu">
|
||||||
<ContextMenu items={dropdownItems} onClick={onClickHandler} />;
|
<ContextMenu items={dropdownItems} onClick={onClickHandler} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -25,9 +25,17 @@ class ToolbarRow extends Component {
|
|||||||
isRightSidePanelOpen: PropTypes.bool.isRequired,
|
isRightSidePanelOpen: PropTypes.bool.isRequired,
|
||||||
selectedLeftSidePanel: PropTypes.string.isRequired,
|
selectedLeftSidePanel: PropTypes.string.isRequired,
|
||||||
selectedRightSidePanel: PropTypes.string.isRequired,
|
selectedRightSidePanel: PropTypes.string.isRequired,
|
||||||
handleSidePanelChange: PropTypes.func,
|
handleSidePanelChange: PropTypes.func.isRequired,
|
||||||
activeContexts: PropTypes.arrayOf(PropTypes.string).isRequired,
|
activeContexts: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||||
studies: PropTypes.array,
|
studies: PropTypes.array,
|
||||||
|
t: PropTypes.func.isRequired,
|
||||||
|
// NOTE: withDialog, withModal HOCs
|
||||||
|
dialog: PropTypes.any,
|
||||||
|
modal: PropTypes.any,
|
||||||
|
};
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
studies: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -50,30 +58,30 @@ class ToolbarRow extends Component {
|
|||||||
this._handleBuiltIn = _handleBuiltIn.bind(this);
|
this._handleBuiltIn = _handleBuiltIn.bind(this);
|
||||||
|
|
||||||
const panelModules = extensionManager.modules[MODULE_TYPES.PANEL];
|
const panelModules = extensionManager.modules[MODULE_TYPES.PANEL];
|
||||||
|
|
||||||
this.buttonGroups = {
|
this.buttonGroups = {
|
||||||
left: [
|
left: [],
|
||||||
// TODO: This should come from extensions, instead of being baked in
|
|
||||||
{
|
|
||||||
value: 'studies',
|
|
||||||
icon: 'th-large',
|
|
||||||
bottomLabel: this.props.t('Series'),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
right: [],
|
right: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ~ FIND MENU OPTIONS
|
||||||
panelModules.forEach(panelExtension => {
|
panelModules.forEach(panelExtension => {
|
||||||
const panelModule = panelExtension.module;
|
const panelModule = panelExtension.module;
|
||||||
const defaultContexts = Array.from(panelModule.defaultContext);
|
const defaultContexts = Array.from(panelModule.defaultContext);
|
||||||
|
|
||||||
// MENU OPTIONS
|
|
||||||
panelModule.menuOptions.forEach(menuOption => {
|
panelModule.menuOptions.forEach(menuOption => {
|
||||||
const contexts = Array.from(menuOption.context || defaultContexts);
|
const contexts = Array.from(menuOption.context || defaultContexts);
|
||||||
|
const hasActiveContext = this.props.activeContexts.some(actx =>
|
||||||
const activeContextIncludesAnyPanelContexts = this.props.activeContexts.some(
|
contexts.includes(actx)
|
||||||
actx => contexts.includes(actx)
|
|
||||||
);
|
);
|
||||||
if (activeContextIncludesAnyPanelContexts) {
|
|
||||||
|
// It's a bit beefy to pass studies; probably only need to be reactive on `studyInstanceUIDs` and activeViewport?
|
||||||
|
// Note: This does not cleanly handle `studies` prop updating with panel open
|
||||||
|
const isDisabled =
|
||||||
|
typeof menuOption.isDisabled === 'function' &&
|
||||||
|
menuOption.isDisabled(this.props.studies);
|
||||||
|
|
||||||
|
if (hasActiveContext && !isDisabled) {
|
||||||
const menuOptionEntry = {
|
const menuOptionEntry = {
|
||||||
value: menuOption.target,
|
value: menuOption.target,
|
||||||
icon: menuOption.icon,
|
icon: menuOption.icon,
|
||||||
@@ -85,6 +93,13 @@ class ToolbarRow extends Component {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO: This should come from extensions, instead of being baked in
|
||||||
|
this.buttonGroups.left.unshift({
|
||||||
|
value: 'studies',
|
||||||
|
icon: 'th-large',
|
||||||
|
bottomLabel: this.props.t('Series'),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
@@ -222,6 +237,10 @@ function _getButtonComponents(toolbarButtons, activeButtons) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* TODO: DEPRECATE
|
||||||
|
* This is used exclusively in `extensions/cornerstone/src`
|
||||||
|
* We have better ways with new UI Services to trigger "builtin" behaviors
|
||||||
|
*
|
||||||
* A handy way for us to handle different button types. IE. firing commands for
|
* A handy way for us to handle different button types. IE. firing commands for
|
||||||
* buttons, or initiation built in behavior.
|
* buttons, or initiation built in behavior.
|
||||||
*
|
*
|
||||||
@@ -273,7 +292,7 @@ function _getVisibleToolbarButtons() {
|
|||||||
|
|
||||||
function _handleBuiltIn(button) {
|
function _handleBuiltIn(button) {
|
||||||
/* TODO: Keep cine button active until its unselected. */
|
/* TODO: Keep cine button active until its unselected. */
|
||||||
const { dialog, modal, t } = this.props;
|
const { dialog, t } = this.props;
|
||||||
const { dialogId } = this.state;
|
const { dialogId } = this.state;
|
||||||
const { id, options } = button;
|
const { id, options } = button;
|
||||||
|
|
||||||
|
|||||||
@@ -18,45 +18,30 @@ import WhiteLabellingContext from '../context/WhiteLabellingContext.js';
|
|||||||
import UserManagerContext from '../context/UserManagerContext';
|
import UserManagerContext from '../context/UserManagerContext';
|
||||||
|
|
||||||
import './Viewer.css';
|
import './Viewer.css';
|
||||||
/**
|
|
||||||
* Inits OHIF Hanging Protocol's onReady.
|
|
||||||
* It waits for OHIF Hanging Protocol to be ready to instantiate the ProtocolEngine
|
|
||||||
* Hanging Protocol will use OHIF LayoutManager to render viewports properly
|
|
||||||
*/
|
|
||||||
/*const initHangingProtocol = () => {
|
|
||||||
// When Hanging Protocol is ready
|
|
||||||
HP.ProtocolStore.onReady(() => {
|
|
||||||
|
|
||||||
// Gets all StudyMetadata objects: necessary for Hanging Protocol to access study metadata
|
|
||||||
const studyMetadataList = OHIF.viewer.StudyMetadataList.all();
|
|
||||||
|
|
||||||
// Instantiate StudyMetadataSource: necessary for Hanging Protocol to get study metadata
|
|
||||||
const studyMetadataSource = new OHIF.studies.classes.OHIFStudyMetadataSource();
|
|
||||||
|
|
||||||
// Get prior studies map
|
|
||||||
const studyPriorsMap = OHIF.studylist.functions.getStudyPriorsMap(studyMetadataList);
|
|
||||||
|
|
||||||
// Creates Protocol Engine object with required arguments
|
|
||||||
const ProtocolEngine = new HP.ProtocolEngine(layoutManager, studyMetadataList, studyPriorsMap, studyMetadataSource);
|
|
||||||
|
|
||||||
// Sets up Hanging Protocol engine
|
|
||||||
HP.setEngine(ProtocolEngine);
|
|
||||||
});
|
|
||||||
};*/
|
|
||||||
|
|
||||||
/*const viewportUtils = OHIF.viewerbase.viewportUtils;
|
|
||||||
|
|
||||||
OHIF.viewer.functionList = {
|
|
||||||
toggleCineDialog: viewportUtils.toggleCineDialog,
|
|
||||||
toggleCinePlay: viewportUtils.toggleCinePlay,
|
|
||||||
clearTools: viewportUtils.clearTools,
|
|
||||||
resetViewport: viewportUtils.resetViewport,
|
|
||||||
invert: viewportUtils.invert
|
|
||||||
};*/
|
|
||||||
|
|
||||||
class Viewer extends Component {
|
class Viewer extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
studies: PropTypes.array,
|
studies: PropTypes.arrayOf(
|
||||||
|
PropTypes.shape({
|
||||||
|
studyInstanceUid: PropTypes.string.isRequired,
|
||||||
|
studyDate: PropTypes.string,
|
||||||
|
displaySets: PropTypes.arrayOf(
|
||||||
|
PropTypes.shape({
|
||||||
|
displaySetInstanceUid: PropTypes.string.isRequired,
|
||||||
|
seriesDescription: PropTypes.string,
|
||||||
|
seriesNumber: PropTypes.number,
|
||||||
|
instanceNumber: PropTypes.number,
|
||||||
|
numImageFrames: PropTypes.number,
|
||||||
|
modality: PropTypes.string.isRequired,
|
||||||
|
images: PropTypes.arrayOf(
|
||||||
|
PropTypes.shape({
|
||||||
|
getImageId: PropTypes.func.isRequired,
|
||||||
|
})
|
||||||
|
),
|
||||||
|
})
|
||||||
|
),
|
||||||
|
})
|
||||||
|
),
|
||||||
studyInstanceUids: PropTypes.array,
|
studyInstanceUids: PropTypes.array,
|
||||||
activeServer: PropTypes.shape({
|
activeServer: PropTypes.shape({
|
||||||
type: PropTypes.string,
|
type: PropTypes.string,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export default class DatasetPicker extends Component {
|
|||||||
error: null,
|
error: null,
|
||||||
loading: true,
|
loading: true,
|
||||||
datasets: [],
|
datasets: [],
|
||||||
filterStr: ""
|
filterStr: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
@@ -42,22 +42,23 @@ export default class DatasetPicker extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { datasets, loading, error, filterStr } = this.state;
|
const { datasets, loading, error, filterStr } = this.state;
|
||||||
const { onSelect } = this.props;
|
const { onSelect } = this.props;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<input class="form-control gcp-input"
|
<input
|
||||||
type="text"
|
className="form-control gcp-input"
|
||||||
value={ filterStr }
|
type="text"
|
||||||
onChange={ e => this.setState({ filterStr: e.target.value }) }
|
value={filterStr}
|
||||||
|
onChange={e => this.setState({ filterStr: e.target.value })}
|
||||||
|
/>
|
||||||
|
<DatasetsList
|
||||||
|
datasets={datasets}
|
||||||
|
loading={loading}
|
||||||
|
error={error}
|
||||||
|
filter={filterStr}
|
||||||
|
onSelect={onSelect}
|
||||||
/>
|
/>
|
||||||
<DatasetsList
|
|
||||||
datasets={datasets}
|
|
||||||
loading={loading}
|
|
||||||
error={error}
|
|
||||||
filter={filterStr}
|
|
||||||
onSelect={onSelect}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,10 +122,7 @@ class DatasetSelector extends Component {
|
|||||||
<>
|
<>
|
||||||
{projectBreadcrumbs}
|
{projectBreadcrumbs}
|
||||||
{!project && (
|
{!project && (
|
||||||
<ProjectPicker
|
<ProjectPicker accessToken={accessToken} onSelect={onProjectSelect} />
|
||||||
accessToken={accessToken}
|
|
||||||
onSelect={onProjectSelect}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{project && !location && (
|
{project && !location && (
|
||||||
|
|||||||
@@ -10,13 +10,13 @@ export default class DicomStorePicker extends Component {
|
|||||||
loading: true,
|
loading: true,
|
||||||
stores: [],
|
stores: [],
|
||||||
locations: [],
|
locations: [],
|
||||||
filterStr: ""
|
filterStr: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
dataset: PropTypes.object,
|
dataset: PropTypes.object,
|
||||||
onSelect: PropTypes.func,
|
onSelect: PropTypes.func,
|
||||||
accessToken: PropTypes.string.isRequired
|
accessToken: PropTypes.string.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
@@ -44,10 +44,11 @@ export default class DicomStorePicker extends Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<input class="form-control gcp-input"
|
<input
|
||||||
type="text"
|
className="form-control gcp-input"
|
||||||
value={ filterStr }
|
type="text"
|
||||||
onChange={ e => this.setState({ filterStr: e.target.value }) }
|
value={filterStr}
|
||||||
|
onChange={e => this.setState({ filterStr: e.target.value })}
|
||||||
/>
|
/>
|
||||||
<DicomStoreList
|
<DicomStoreList
|
||||||
stores={stores}
|
stores={stores}
|
||||||
|
|||||||
@@ -1,57 +1,56 @@
|
|||||||
import React, { Component } from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import Modal from 'react-bootstrap-modal';
|
|
||||||
import DatasetSelector from './DatasetSelector';
|
import DatasetSelector from './DatasetSelector';
|
||||||
import './googleCloud.css';
|
import './googleCloud.css';
|
||||||
import { withTranslation } from 'react-i18next';
|
import { withTranslation } from 'react-i18next';
|
||||||
import * as GoogleCloudUtilServers from './utils/getServers';
|
import * as GoogleCloudUtilServers from './utils/getServers';
|
||||||
|
|
||||||
class DicomStorePickerModal extends Component {
|
import { servicesManager } from './../App.js';
|
||||||
static propTypes = {
|
|
||||||
url: PropTypes.string,
|
function DicomStorePickerModal({
|
||||||
user: PropTypes.object.isRequired,
|
isOpen = false,
|
||||||
setServers: PropTypes.func.isRequired,
|
setServers,
|
||||||
isOpen: PropTypes.bool.isRequired,
|
onClose,
|
||||||
onClose: PropTypes.func,
|
user,
|
||||||
|
url,
|
||||||
|
t,
|
||||||
|
}) {
|
||||||
|
const { UIModalService } = servicesManager.services;
|
||||||
|
|
||||||
|
const showDicomStorePickerModal = () => {
|
||||||
|
const handleEvent = data => {
|
||||||
|
const servers = GoogleCloudUtilServers.getServers(data, data.dicomstore);
|
||||||
|
setServers(servers);
|
||||||
|
|
||||||
|
// Force auto close
|
||||||
|
UIModalService.hide();
|
||||||
|
onClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (UIModalService) {
|
||||||
|
UIModalService.show({
|
||||||
|
content: DatasetSelector,
|
||||||
|
title: t('Google Cloud Healthcare API'),
|
||||||
|
contentProps: {
|
||||||
|
setServers: handleEvent,
|
||||||
|
user,
|
||||||
|
url,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
return (
|
||||||
isOpen: false,
|
<React.Fragment>{isOpen && showDicomStorePickerModal()}</React.Fragment>
|
||||||
};
|
);
|
||||||
|
|
||||||
handleEvent = data => {
|
|
||||||
const servers = GoogleCloudUtilServers.getServers(data, data.dicomstore);
|
|
||||||
this.props.setServers(servers);
|
|
||||||
// Force auto close
|
|
||||||
this.props.onClose();
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<Modal
|
|
||||||
show={this.props.isOpen}
|
|
||||||
onHide={this.props.onClose}
|
|
||||||
aria-labelledby="ModalHeader"
|
|
||||||
className="modal fade themed in"
|
|
||||||
backdrop={false}
|
|
||||||
size={'md'}
|
|
||||||
keyboard={true}
|
|
||||||
>
|
|
||||||
<Modal.Header closeButton>
|
|
||||||
<Modal.Title>
|
|
||||||
{this.props.t('Google Cloud Healthcare API')}
|
|
||||||
</Modal.Title>
|
|
||||||
</Modal.Header>
|
|
||||||
<Modal.Body>
|
|
||||||
<DatasetSelector
|
|
||||||
setServers={this.handleEvent}
|
|
||||||
user={this.props.user}
|
|
||||||
url={this.props.url}
|
|
||||||
/>
|
|
||||||
</Modal.Body>
|
|
||||||
</Modal>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DicomStorePickerModal.propTypes = {
|
||||||
|
isOpen: PropTypes.bool.isRequired,
|
||||||
|
setServers: PropTypes.func.isRequired,
|
||||||
|
onClose: PropTypes.func,
|
||||||
|
user: PropTypes.object.isRequired,
|
||||||
|
url: PropTypes.string,
|
||||||
|
};
|
||||||
|
|
||||||
export default withTranslation('Common')(DicomStorePickerModal);
|
export default withTranslation('Common')(DicomStorePickerModal);
|
||||||
@@ -9,7 +9,7 @@ export default class LocationPicker extends Component {
|
|||||||
error: null,
|
error: null,
|
||||||
loading: true,
|
loading: true,
|
||||||
locations: [],
|
locations: [],
|
||||||
filterStr: "",
|
filterStr: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
@@ -42,10 +42,11 @@ export default class LocationPicker extends Component {
|
|||||||
const { onSelect } = this.props;
|
const { onSelect } = this.props;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<input class="form-control gcp-input"
|
<input
|
||||||
type="text"
|
className="form-control gcp-input"
|
||||||
value={ filterStr }
|
type="text"
|
||||||
onChange={ e => this.setState({ filterStr: e.target.value }) }
|
value={filterStr}
|
||||||
|
onChange={e => this.setState({ filterStr: e.target.value })}
|
||||||
/>
|
/>
|
||||||
<LocationsList
|
<LocationsList
|
||||||
locations={locations}
|
locations={locations}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export default class ProjectPicker extends Component {
|
|||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
projects: response.data.projects || [],
|
projects: response.data.projects || [],
|
||||||
filterStr: "",
|
filterStr: '',
|
||||||
loading: false,
|
loading: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -40,10 +40,11 @@ export default class ProjectPicker extends Component {
|
|||||||
const { onSelect } = this.props;
|
const { onSelect } = this.props;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<input class="form-control gcp-input"
|
<input
|
||||||
type="text"
|
className="form-control gcp-input"
|
||||||
value={ filterStr }
|
type="text"
|
||||||
onChange={ e => this.setState({ filterStr: e.target.value }) }
|
value={filterStr}
|
||||||
|
onChange={e => this.setState({ filterStr: e.target.value })}
|
||||||
/>
|
/>
|
||||||
<ProjectsList
|
<ProjectsList
|
||||||
projects={projects}
|
projects={projects}
|
||||||
|
|||||||
@@ -15202,10 +15202,10 @@ react-codemirror2@^6.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/react-codemirror2/-/react-codemirror2-6.0.0.tgz#180065df57a64026026cde569a9708fdf7656525"
|
resolved "https://registry.yarnpkg.com/react-codemirror2/-/react-codemirror2-6.0.0.tgz#180065df57a64026026cde569a9708fdf7656525"
|
||||||
integrity sha512-D7y9qZ05FbUh9blqECaJMdDwKluQiO3A9xB+fssd5jKM7YAXucRuEOlX32mJQumUvHUkHRHqXIPBjm6g0FW0Ag==
|
integrity sha512-D7y9qZ05FbUh9blqECaJMdDwKluQiO3A9xB+fssd5jKM7YAXucRuEOlX32mJQumUvHUkHRHqXIPBjm6g0FW0Ag==
|
||||||
|
|
||||||
react-cornerstone-viewport@2.x.x:
|
react-cornerstone-viewport@^2.3.6:
|
||||||
version "2.1.0"
|
version "2.3.6"
|
||||||
resolved "https://registry.yarnpkg.com/react-cornerstone-viewport/-/react-cornerstone-viewport-2.1.0.tgz#1f353e3b0a57c45add70e5040b819290d9f55f4b"
|
resolved "https://registry.yarnpkg.com/react-cornerstone-viewport/-/react-cornerstone-viewport-2.3.6.tgz#1c76bd37c95284254767296952845bacd3b810a4"
|
||||||
integrity sha512-HahonGn2ZSud/yMSClWL3YDlh74hE46OMyTeTI7i80EWYPXO1eKeHajwyFvfl2wWXycuotpyhUlwIfQY1h4jRw==
|
integrity sha512-MBs1Mgl0g0YswkhgoaYlaPoPDVs/HZQ3Z89thHxVytvJsgnQvhc3YrR48iRaUfQj0eYoazh7AL/lLCfd8veFKA==
|
||||||
dependencies:
|
dependencies:
|
||||||
classnames "^2.2.6"
|
classnames "^2.2.6"
|
||||||
date-fns "^2.2.1"
|
date-fns "^2.2.1"
|
||||||
|
|||||||
Reference in new issue
Block a user