Merge branch 'master' into dannyrb/ci/visual-test

This commit is contained in:
Danny Brown 2019-12-10 23:08:09 -05:00 committed by GitHub
commit 17e3b49b06
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 250 additions and 186 deletions

View File

@ -43,7 +43,7 @@ translate to in practice?
```js
// In the application
const UINotificationService = createUINotificationService();
import UINotificationService from '@ohif/core';
const servicesManager = new ServicesManager();
servicesManager.registerService(UINotificationService);

View File

@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.0.2](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.0.1...@ohif/extension-vtk@1.0.2) (2019-12-11)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.0.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.0.0...@ohif/extension-vtk@1.0.1) (2019-12-09)
**Note:** Version bump only for package @ohif/extension-vtk

View File

@ -1,6 +1,6 @@
{
"name": "@ohif/extension-vtk",
"version": "1.0.1",
"version": "1.0.2",
"description": "OHIF extension for VTK.js",
"author": "OHIF",
"license": "MIT",
@ -52,7 +52,7 @@
"react-vtkjs-viewport": "^0.3.9"
},
"devDependencies": {
"@ohif/core": "^2.0.1",
"@ohif/core": "^2.0.2",
"@ohif/ui": "^1.0.1",
"cornerstone-tools": "^4.8.0",
"cornerstone-wado-image-loader": "^3.0.0",

View File

@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.0.2](https://github.com/OHIF/Viewers/compare/@ohif/core@2.0.1...@ohif/core@2.0.2) (2019-12-11)
**Note:** Version bump only for package @ohif/core
## [2.0.1](https://github.com/OHIF/Viewers/compare/@ohif/core@2.0.0...@ohif/core@2.0.1) (2019-12-09)
**Note:** Version bump only for package @ohif/core

View File

@ -1,6 +1,6 @@
{
"name": "@ohif/core",
"version": "2.0.1",
"version": "2.0.2",
"description": "Generic business logic for web-based medical imaging applications",
"author": "OHIF Core Team",
"license": "MIT",

View File

@ -20,11 +20,11 @@ import user from './user.js';
import utils from './utils/';
import {
createUINotificationService,
createUIModalService,
createUIDialogService,
createUIContextMenuService,
createUILabellingFlowService,
UINotificationService,
UIModalService,
UIDialogService,
UIContextMenuService,
UILabellingFlowService,
} from './services';
const OHIF = {
@ -52,11 +52,11 @@ const OHIF = {
measurements,
hangingProtocols,
//
createUINotificationService,
createUIModalService,
createUIDialogService,
createUIContextMenuService,
createUILabellingFlowService,
UINotificationService,
UIModalService,
UIDialogService,
UIContextMenuService,
UILabellingFlowService,
};
export {
@ -83,11 +83,11 @@ export {
measurements,
hangingProtocols,
//
createUINotificationService,
createUIModalService,
createUIDialogService,
createUIContextMenuService,
createUILabellingFlowService,
UINotificationService,
UIModalService,
UIDialogService,
UIContextMenuService,
UILabellingFlowService,
};
export { OHIF };

View File

@ -10,11 +10,11 @@ describe('Top level exports', () => {
'HotkeysManager',
'ServicesManager',
//
'createUINotificationService',
'createUIModalService',
'createUIDialogService',
'createUIContextMenuService',
'createUILabellingFlowService',
'UINotificationService',
'UIModalService',
'UIDialogService',
'UIContextMenuService',
'UILabellingFlowService',
//
'utils',
'studies',

View File

@ -7,10 +7,12 @@ export default class ServicesManager {
}
/**
* Registers a new service.
*
* @param {Object} service
* @param {Object} configuration
*/
registerService(service) {
registerService(service, configuration = {}) {
if (!service) {
log.warn(
'Attempting to register a null/undefined service. Exiting early.'
@ -18,32 +20,45 @@ export default class ServicesManager {
return;
}
let serviceName = service.name;
if (!serviceName) {
if (!service.name) {
log.warn(`Service name not set. Exiting early.`);
return;
}
if (this.registeredServiceNames.includes(serviceName)) {
if (this.registeredServiceNames.includes(service.name)) {
log.warn(
`Extension name ${serviceName} has already been registered. Exiting before duplicating services.`
`Service name ${service.name} has already been registered. Exiting before duplicating services.`
);
return;
}
this.services[service.name] = service;
if (service.create) {
this.services[service.name] = service.create({ configuration });
} else {
log.warn(`Service create factory function not defined. Exiting early.`);
return;
}
// Track service registration
this.registeredServiceNames.push(serviceName);
/* Track service registration */
this.registeredServiceNames.push(service.name);
}
/**
* An array of services.
* An array of services, or an array of arrays that contains service
* configuration pairs.
*
* @param {Object[]} services - Array of services
*/
registerServices(services) {
services.forEach(service => this.registerService(service));
services.forEach(service => {
const hasConfiguration = Array.isArray(service);
if (hasConfiguration) {
const [ohifService, configuration] = service;
this.registerService(ohifService, configuration);
} else {
this.registerService(service);
}
});
}
}

View File

@ -16,18 +16,32 @@ describe('ServicesManager.js', () => {
it('calls registerService() for each service', () => {
servicesManager.registerService = jest.fn();
const fakeServices = [
{ name: 'UINotificationTestService', hide: jest.fn() },
{ name: 'UIModalTestService', hide: jest.fn() },
];
servicesManager.registerServices(fakeServices);
servicesManager.registerServices([
{ name: 'UINotificationTestService', create: jest.fn() },
{ name: 'UIModalTestService', create: jest.fn() },
]);
expect(servicesManager.registerService.mock.calls.length).toBe(2);
});
it('calls registerService() for each service passing its configuration if tuple', () => {
servicesManager.registerService = jest.fn();
const fakeConfiguration = { testing: true };
servicesManager.registerServices([
{ name: 'UINotificationTestService', create: jest.fn() },
[{ name: 'UIModalTestService', create: jest.fn() }, fakeConfiguration],
]);
expect(servicesManager.registerService.mock.calls[1]).toContain(
fakeConfiguration
);
});
});
describe('registerService()', () => {
const fakeService = { name: 'UINotificationService', create: jest.fn() };
it('logs a warning if the service is null or undefined', () => {
const undefinedService = undefined;
const nullService = null;
@ -39,8 +53,8 @@ describe('ServicesManager.js', () => {
});
it('logs a warning if the service does not have a name', () => {
const serviceWithEmptyName = { name: '', hide: jest.fn() };
const serviceWithoutName = { hide: jest.fn() };
const serviceWithEmptyName = { name: '', create: jest.fn() };
const serviceWithoutName = { create: jest.fn() };
servicesManager.registerService(serviceWithEmptyName);
servicesManager.registerService(serviceWithoutName);
@ -48,23 +62,37 @@ describe('ServicesManager.js', () => {
expect(log.warn.mock.calls.length).toBe(2);
});
it('tracks which services have been registered', () => {
const service = {
name: 'UINotificationService',
};
it('logs a warning if the service does not have a create factory function', () => {
const serviceWithoutCreate = { name: 'UINotificationService' };
servicesManager.registerService(service);
expect(servicesManager.registeredServiceNames).toContain(service.name);
});
it('logs a warning if the service has an name that has already been registered', () => {
const service = { name: 'UINotificationService' };
servicesManager.registerService(service);
servicesManager.registerService(service);
servicesManager.registerService(serviceWithoutCreate);
expect(log.warn.mock.calls.length).toBe(1);
});
it('tracks which services have been registered', () => {
servicesManager.registerService(fakeService);
expect(servicesManager.registeredServiceNames).toContain(
fakeService.name
);
});
it('logs a warning if the service has an name that has already been registered', () => {
servicesManager.registerService(fakeService);
servicesManager.registerService(fakeService);
expect(log.warn.mock.calls.length).toBe(1);
});
it('pass configuration to service create factory function', () => {
const configuration = { config: 'Some configuration' };
servicesManager.registerService(fakeService, configuration);
expect(fakeService.create.mock.calls[0][0]).toEqual({
configuration,
});
});
});
});

View File

@ -5,29 +5,27 @@
* @property {Event} event The event with tool information.
*/
const uiContextMenuServicePublicAPI = {
name: 'UIContextMenuService',
hide,
show,
const name = 'UIContextMenuService';
const publicAPI = {
name,
hide: _hide,
show: _show,
setServiceImplementation,
};
const uiContextMenuServiceImplementation = {
const serviceImplementation = {
_show: () => console.warn('show() NOT IMPLEMENTED'),
_hide: () => console.warn('hide() NOT IMPLEMENTED'),
};
function createUIContextMenuService() {
return uiContextMenuServicePublicAPI;
}
/**
* Show a new UI ContextMenu dialog;
*
* @param {ContextMenuProps} props { event }
*/
function show({ event }) {
return uiContextMenuServiceImplementation._show({
function _show({ event }) {
return serviceImplementation._show({
event,
});
}
@ -36,8 +34,8 @@ function show({ event }) {
* Hide a UI ContextMenu dialog;
*
*/
function hide() {
return uiContextMenuServiceImplementation._hide();
function _hide() {
return serviceImplementation._hide();
}
/**
@ -53,11 +51,16 @@ function setServiceImplementation({
hide: hideImplementation,
}) {
if (showImplementation) {
uiContextMenuServiceImplementation._show = showImplementation;
serviceImplementation._show = showImplementation;
}
if (hideImplementation) {
uiContextMenuServiceImplementation._hide = hideImplementation;
serviceImplementation._hide = hideImplementation;
}
}
export default createUIContextMenuService;
export default {
name,
create: ({ configuration = {} }) => {
return publicAPI;
},
};

View File

@ -25,30 +25,28 @@
* @property {Function} onDrag Called while dragging.
*/
const uiDialogServicePublicAPI = {
name: 'UIDialogService',
dismiss,
dismissAll,
create,
const name = 'UIDialogService';
const publicAPI = {
name,
dismiss: _dismiss,
dismissAll: _dismissAll,
create: _create,
setServiceImplementation,
};
const uiDialogServiceImplementation = {
const serviceImplementation = {
_dismiss: () => console.warn('dismiss() NOT IMPLEMENTED'),
_dismissAll: () => console.warn('dismissAll() NOT IMPLEMENTED'),
_create: () => console.warn('create() NOT IMPLEMENTED'),
};
function createUIDialogService() {
return uiDialogServicePublicAPI;
}
/**
* Show a new UI dialog;
*
* @param {DialogProps} props { id, content, contentProps, onStart, onDrag, onStop, centralize, isDraggable, showOverlay, preservePosition, defaultPosition }
*/
function create({
function _create({
id,
content,
contentProps,
@ -61,7 +59,7 @@ function create({
showOverlay = false,
defaultPosition,
}) {
return uiDialogServiceImplementation._create({
return serviceImplementation._create({
id,
content,
contentProps,
@ -81,8 +79,8 @@ function create({
*
* @returns void
*/
function dismissAll() {
return uiDialogServiceImplementation._dismissAll();
function _dismissAll() {
return serviceImplementation._dismissAll();
}
/**
@ -90,8 +88,8 @@ function dismissAll() {
*
* @returns void
*/
function dismiss({ id }) {
return uiDialogServiceImplementation._dismiss({ id });
function _dismiss({ id }) {
return serviceImplementation._dismiss({ id });
}
/**
@ -109,14 +107,19 @@ function setServiceImplementation({
create: createImplementation,
}) {
if (dismissImplementation) {
uiDialogServiceImplementation._dismiss = dismissImplementation;
serviceImplementation._dismiss = dismissImplementation;
}
if (dismissAllImplementation) {
uiDialogServiceImplementation._dismissAll = dismissAllImplementation;
serviceImplementation._dismissAll = dismissAllImplementation;
}
if (createImplementation) {
uiDialogServiceImplementation._create = createImplementation;
serviceImplementation._create = createImplementation;
}
}
export default createUIDialogService;
export default {
name,
create: ({ configuration = {} }) => {
return publicAPI;
},
};

View File

@ -8,28 +8,26 @@
*
*/
const uiLabellingFlowServicePublicAPI = {
name: 'UILabellingFlowService',
show,
hide,
const name = 'UILabellingFlowService';
const publicAPI = {
name,
show: _show,
hide: _hide,
setServiceImplementation,
};
const uiLabellingFlowServiceImplementation = {
const serviceImplementation = {
_show: () => console.warn('show() NOT IMPLEMENTED'),
_hide: () => console.warn('hide() NOT IMPLEMENTED'),
};
function createUILabellingFlowService() {
return uiLabellingFlowServicePublicAPI;
}
/**
* Hide a UI LabellingFlow dialog;
*
*/
function hide() {
return uiLabellingFlowServiceImplementation._hide();
function _hide() {
return serviceImplementation._hide();
}
/**
@ -37,8 +35,8 @@ function hide() {
*
* @param {LabellingFlowProps} props { defaultPosition, centralize, props }
*/
function show({ defaultPosition, centralize, props }) {
return uiLabellingFlowServiceImplementation._show({
function _show({ defaultPosition, centralize, props }) {
return serviceImplementation._show({
defaultPosition,
centralize,
props,
@ -58,11 +56,16 @@ function setServiceImplementation({
hide: hideImplementation,
}) {
if (showImplementation) {
uiLabellingFlowServiceImplementation._show = showImplementation;
serviceImplementation._show = showImplementation;
}
if (hideImplementation) {
uiLabellingFlowServiceImplementation._hide = hideImplementation;
serviceImplementation._hide = hideImplementation;
}
}
export default createUILabellingFlowService;
export default {
name,
create: ({ configuration = {} }) => {
return publicAPI;
},
};

View File

@ -11,28 +11,26 @@
* @property {string} [customClassName=null] The custom class to style the modal.
*/
const uiModalServicePublicAPI = {
name: 'UIModalService',
hide,
show,
const name = 'UIModalService';
const publicAPI = {
name,
hide: _hide,
show: _show,
setServiceImplementation,
};
const uiModalServiceImplementation = {
const serviceImplementation = {
_hide: () => console.warn('hide() NOT IMPLEMENTED'),
_show: () => console.warn('show() NOT IMPLEMENTED'),
};
function createUIModalService() {
return uiModalServicePublicAPI;
}
/**
* Show a new UI modal;
*
* @param {ModalProps} props { content, contentProps, shouldCloseOnEsc, isOpen, closeButton, title, customClassName }
*/
function show({
function _show({
content = null,
contentProps = null,
shouldCloseOnEsc = false,
@ -41,7 +39,7 @@ function show({
title = null,
customClassName = null,
}) {
return uiModalServiceImplementation._show({
return serviceImplementation._show({
content,
contentProps,
shouldCloseOnEsc,
@ -57,8 +55,8 @@ function show({
*
* @returns void
*/
function hide() {
return uiModalServiceImplementation._hide();
function _hide() {
return serviceImplementation._hide();
}
/**
@ -74,11 +72,16 @@ function setServiceImplementation({
show: showImplementation,
}) {
if (hideImplementation) {
uiModalServiceImplementation._hide = hideImplementation;
serviceImplementation._hide = hideImplementation;
}
if (showImplementation) {
uiModalServiceImplementation._show = showImplementation;
serviceImplementation._show = showImplementation;
}
}
export default createUIModalService;
export default {
name,
create: ({ configuration = {} }) => {
return publicAPI;
},
};

View File

@ -10,22 +10,20 @@
* @property {boolean} [autoClose=true]
*/
const uiNotificationServicePublicAPI = {
name: 'UINotificationService',
hide,
show,
const name = 'UINotificationService';
const publicAPI = {
name,
hide: _hide,
show: _show,
setServiceImplementation,
};
const uiNotificationServiceImplementation = {
const serviceImplementation = {
_hide: () => console.warn('hide() NOT IMPLEMENTED'),
_show: () => console.warn('show() NOT IMPLEMENTED'),
};
function createUINotificationService() {
return uiNotificationServicePublicAPI;
}
/**
* Create and show a new UI notification; returns the
* ID of the created notification.
@ -33,7 +31,7 @@ function createUINotificationService() {
* @param {Notification} notification { title, message, duration, position, type, autoClose}
* @returns {number} id
*/
function show({
function _show({
title,
message,
duration = 5000,
@ -41,7 +39,7 @@ function show({
type = 'info',
autoClose = true,
}) {
return uiNotificationServiceImplementation._show({
return serviceImplementation._show({
title,
message,
duration,
@ -57,8 +55,8 @@ function show({
* @param {number} id - id of the notification to hide/dismiss
* @returns undefined
*/
function hide(id) {
return uiNotificationServiceImplementation._hide({ id });
function _hide(id) {
return serviceImplementation._hide({ id });
}
/**
@ -74,11 +72,16 @@ function setServiceImplementation({
show: showImplementation,
}) {
if (hideImplementation) {
uiNotificationServiceImplementation._hide = hideImplementation;
serviceImplementation._hide = hideImplementation;
}
if (showImplementation) {
uiNotificationServiceImplementation._show = showImplementation;
serviceImplementation._show = showImplementation;
}
}
export default createUINotificationService;
export default {
name,
create: ({ configuration = {} }) => {
return publicAPI;
},
};

View File

@ -1,15 +1,15 @@
import ServicesManager from './ServicesManager.js';
import createUINotificationService from './UINotificationService';
import createUIModalService from './UIModalService';
import createUIDialogService from './UIDialogService';
import createUIContextMenuService from './UIContextMenuService';
import createUILabellingFlowService from './UILabellingFlowService';
import UINotificationService from './UINotificationService';
import UIModalService from './UIModalService';
import UIDialogService from './UIDialogService';
import UIContextMenuService from './UIContextMenuService';
import UILabellingFlowService from './UILabellingFlowService';
export {
createUINotificationService,
createUIModalService,
createUIDialogService,
createUIContextMenuService,
createUILabellingFlowService,
UINotificationService,
UIModalService,
UIDialogService,
UIContextMenuService,
UILabellingFlowService,
ServicesManager,
};

View File

@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.0.2](https://github.com/OHIF/Viewers/compare/@ohif/viewer@3.0.1...@ohif/viewer@3.0.2) (2019-12-11)
**Note:** Version bump only for package @ohif/viewer
## [3.0.1](https://github.com/OHIF/Viewers/compare/@ohif/viewer@3.0.0...@ohif/viewer@3.0.1) (2019-12-09)
**Note:** Version bump only for package @ohif/viewer

View File

@ -1,6 +1,6 @@
{
"name": "@ohif/viewer",
"version": "3.0.1",
"version": "3.0.2",
"description": "OHIF Viewer",
"author": "OHIF Contributors",
"license": "MIT",
@ -45,12 +45,12 @@
},
"dependencies": {
"@babel/runtime": "^7.5.5",
"@ohif/core": "^2.0.1",
"@ohif/core": "^2.0.2",
"@ohif/extension-cornerstone": "^2.0.1",
"@ohif/extension-dicom-html": "^1.0.2",
"@ohif/extension-dicom-microscopy": "^0.50.6",
"@ohif/extension-dicom-pdf": "^1.0.0",
"@ohif/extension-vtk": "^1.0.1",
"@ohif/extension-vtk": "^1.0.2",
"@ohif/i18n": "^0.52.2",
"@ohif/ui": "^1.0.1",
"@tanem/react-nprogress": "^1.1.25",

View File

@ -28,11 +28,11 @@ import {
ExtensionManager,
ServicesManager,
HotkeysManager,
createUINotificationService,
createUIModalService,
createUIDialogService,
createUIContextMenuService,
createUILabellingFlowService,
UINotificationService,
UIModalService,
UIDialogService,
UIContextMenuService,
UILabellingFlowService,
utils,
redux as reduxOHIF,
} from '@ohif/core';
@ -70,13 +70,6 @@ const commandsManagerConfig = {
getActiveContexts: () => getActiveContexts(store.getState()),
};
/** Services */
const UINotificationService = createUINotificationService();
const UIModalService = createUIModalService();
const UIDialogService = createUIDialogService();
const UIContextMenuService = createUIContextMenuService();
const UILabellingFlowService = createUILabellingFlowService();
/** Managers */
const commandsManager = new CommandsManager(commandsManagerConfig);
const hotkeysManager = new HotkeysManager(commandsManager);
@ -165,6 +158,14 @@ class App extends Component {
render() {
const { whiteLabelling, routerBasename } = this._appConfig;
const {
UINotificationService,
UIDialogService,
UILabellingFlowService,
UIModalService,
UIContextMenuService,
} = servicesManager.services;
if (this._userManager) {
return (
<AppContext.Provider value={{ appConfig: this._appConfig }}>

View File

@ -2654,16 +2654,6 @@
dependencies:
"@types/node" "^12.11.1"
"@ohif/extension-cornerstone@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@ohif/extension-cornerstone/-/extension-cornerstone-2.0.0.tgz#b4ee3b594212502192cdd311a100354857280548"
integrity sha512-hvJ3t2GRcu906NiYpUWaJIB9ja/M/MKEYLy19t4XBFpqf4VqoezR2KJpZelmZjQscXGaDQeZgvr3DJO5Nva8Uw==
dependencies:
"@babel/runtime" "^7.5.5"
classnames "^2.2.6"
lodash.throttle "^4.1.1"
react-cornerstone-viewport "0.1.30"
"@ohif/i18n@^0.2.3":
version "0.2.5"
resolved "https://registry.yarnpkg.com/@ohif/i18n/-/i18n-0.2.5.tgz#2b92a78109823ce0f50dd590201d980a5fd64974"
@ -13103,7 +13093,7 @@ modify-values@^1.0.0:
resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022"
integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==
moment@2.24.0, moment@>=1.6.0, moment@^2.23.0, moment@^2.24.0:
moment@2.24.0, moment@>=1.6.0, moment@^2.24.0:
version "2.24.0"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==
@ -15839,15 +15829,6 @@ react-codemirror2@^6.0.0:
resolved "https://registry.yarnpkg.com/react-codemirror2/-/react-codemirror2-6.0.0.tgz#180065df57a64026026cde569a9708fdf7656525"
integrity sha512-D7y9qZ05FbUh9blqECaJMdDwKluQiO3A9xB+fssd5jKM7YAXucRuEOlX32mJQumUvHUkHRHqXIPBjm6g0FW0Ag==
react-cornerstone-viewport@0.1.30:
version "0.1.30"
resolved "https://registry.yarnpkg.com/react-cornerstone-viewport/-/react-cornerstone-viewport-0.1.30.tgz#3546a5164feef5f1f3b45ade10fd9a66f82fd101"
integrity sha512-DGxdpS7FJvWi57NhpKhKMdaW3go/Fs/zfWJFtaEzGVHq2zQnEEV5G1pamC4ttRhKMfzy7T7y4h14xUVzE7IqPA==
dependencies:
lodash.debounce "^4.0.8"
moment "^2.23.0"
stylus "^0.54.5"
react-cornerstone-viewport@2.x.x:
version "2.1.0"
resolved "https://registry.yarnpkg.com/react-cornerstone-viewport/-/react-cornerstone-viewport-2.1.0.tgz#1f353e3b0a57c45add70e5040b819290d9f55f4b"