Compare commits

...
Author SHA1 Message Date
ohif-bot 78344c2c66 chore(release): publish [skip ci]
- @ohif/extension-vtk@0.52.17
 - @ohif/core@1.5.0
 - @ohif/viewer@1.12.0
2019-10-25 13:17:26 +00:00
James Petts b451ce4407 fix: 🐛 Fix crosshairs location when using MIP (#1080) 2019-10-25 15:07:35 +02:00
ladeirarodolfo 21b586b08f feat: 🎸 Allow routes to load Google Cloud DICOM Stores in the Study List (#1069) 2019-10-25 14:49:48 +02:00
ohif-bot 3bbeb1c521 chore(release): publish [skip ci]
- @ohif/viewer@1.11.5
2019-10-24 20:23:16 +00:00
Danny Brown 7668b69f20 test: percy snapshot workaround (#1085)
* Try workaround for percy snapshot

* Return our modified document
2019-10-24 16:09:59 -04:00
Danny Brown 3a12138134 test: Try workaround for percy snapshot (#1084) 2019-10-24 15:54:06 -04:00
Danny Brown 97786b808c ci: revert flags 2019-10-23 12:55:39 -04:00
Danny Brown cd1baa1b36 ci: force flag 2019-10-23 12:41:44 -04:00
Danny Brown 3ae3bee452 ci: test recursive removal 2019-10-23 12:24:56 -04:00
21 changed files with 278 additions and 57 deletions

No files matched your search

+11
View File
@@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.52.17](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.52.16...@ohif/extension-vtk@0.52.17) (2019-10-25)
### Bug Fixes
* 🐛 Fix crosshairs location when using MIP ([#1080](https://github.com/OHIF/Viewers/issues/1080)) ([b451ce4](https://github.com/OHIF/Viewers/commit/b451ce440796f13b0891739d2130e8ee71993d3d))
## [0.52.16](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.52.15...@ohif/extension-vtk@0.52.16) (2019-10-23)
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-vtk",
"version": "0.52.16",
"version": "0.52.17",
"description": "OHIF extension for VTK.js",
"author": "OHIF",
"license": "MIT",
@@ -49,10 +49,10 @@
"dependencies": {
"@babel/runtime": "^7.5.5",
"lodash.throttle": "^4.1.1",
"react-vtkjs-viewport": "^0.3.5"
"react-vtkjs-viewport": "^0.3.6"
},
"devDependencies": {
"@ohif/core": "^1.4.0",
"@ohif/core": "^1.5.0",
"@ohif/ui": "^0.56.0",
"cornerstone-tools": "^4.0.9",
"cornerstone-wado-image-loader": "^3.0.0",
+11
View File
@@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [1.5.0](https://github.com/OHIF/Viewers/compare/@ohif/core@1.4.0...@ohif/core@1.5.0) (2019-10-25)
### Features
* 🎸 Allow routes to load Google Cloud DICOM Stores in the Study List ([#1069](https://github.com/OHIF/Viewers/issues/1069)) ([21b586b](https://github.com/OHIF/Viewers/commit/21b586b08f3dde6613859712a9e0577dece564db))
# [1.4.0](https://github.com/OHIF/Viewers/compare/@ohif/core@1.3.2...@ohif/core@1.4.0) (2019-10-15)
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/core",
"version": "1.4.0",
"version": "1.5.0",
"description": "Generic business logic for web-based medical imaging applications",
"author": "OHIF Core Team",
"license": "MIT",
+10 -4
View File
@@ -6,7 +6,7 @@ const PARAM_PATTERN_IDENTIFIER = ':';
function toLowerCaseFirstLetter(word) {
return word[0].toLowerCase() + word.slice(1);
}
const getFilters = (location = {}) => {
const getQueryFilters = (location = {}) => {
const { search } = location;
if (!search) {
@@ -55,13 +55,19 @@ const replaceParam = (path = '', paramKey, paramValue) => {
return path;
};
const isValidPath = path => {
const paramPatternPiece = `/${PARAM_PATTERN_IDENTIFIER}`;
return path.indexOf(paramPatternPiece) < 0;
};
const queryString = {
getQueryFilters: getFilters,
getQueryFilters,
};
const paramString = {
parseParam: parseParam,
replaceParam: replaceParam,
isValidPath,
parseParam,
replaceParam,
};
export { parse, queryString, paramString };
+15 -4
View File
@@ -3,6 +3,21 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [1.12.0](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.11.5...@ohif/viewer@1.12.0) (2019-10-25)
### Features
* 🎸 Allow routes to load Google Cloud DICOM Stores in the Study List ([#1069](https://github.com/OHIF/Viewers/issues/1069)) ([21b586b](https://github.com/OHIF/Viewers/commit/21b586b08f3dde6613859712a9e0577dece564db))
## [1.11.5](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.11.4...@ohif/viewer@1.11.5) (2019-10-24)
**Note:** Version bump only for package @ohif/viewer
## [1.11.4](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.11.3...@ohif/viewer@1.11.4) (2019-10-23)
@@ -10,10 +25,6 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
* Revert "Revert "fix: MPR initialization"" ([#1065](https://github.com/OHIF/Viewers/issues/1065)) ([c680720](https://github.com/OHIF/Viewers/commit/c680720ce5ead58fdb399e3a356edac18093f5c0)), closes [#1062](https://github.com/OHIF/Viewers/issues/1062) [#1064](https://github.com/OHIF/Viewers/issues/1064)
## [1.11.3](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.11.2...@ohif/viewer@1.11.3) (2019-10-23)
@@ -5,7 +5,7 @@ describe('OHIFStandaloneViewer', () => {
it('loads route with at least 2 rows', () => {
cy.screenshot();
cy.percySnapshot();
cy.percyCanvasSnapshot('Study List');
cy.get('#studyListData tr')
.its('length')
@@ -12,7 +12,7 @@ describe('OHIF Study Viewer Page', () => {
it('checks if series thumbnails are being displayed', () => {
cy.screenshot();
cy.percySnapshot();
cy.percyCanvasSnapshot('Series Thumbnails');
cy.get('[data-cy="thumbnail-list"]')
.its('length')
@@ -22,6 +22,6 @@ describe('OHIF Microscopy Extension', () => {
cy.wait(3000); //Waiting for image to render before taking the snapshot
cy.screenshot();
cy.percySnapshot();
cy.percyCanvasSnapshot('Microscopy Extension');
});
});
@@ -21,6 +21,6 @@ describe('OHIF PDF Extension', () => {
.should('be.eq', 1);
cy.screenshot();
cy.percySnapshot();
cy.percyCanvasSnapshot('PDF Extension');
});
});
@@ -29,7 +29,7 @@ describe('OHIF VTK Extension', () => {
it('checks if VTK buttons are displayed on the toolbar', () => {
cy.screenshot();
cy.percySnapshot();
cy.percyCanvasSnapshot('VTK Extension');
cy.get('@crosshairsBtn')
.should('be.visible')
@@ -306,3 +306,34 @@ Cypress.Commands.add('isInViewport', element => {
}
});
});
/**
* Percy.io Canvas screenshot workaround
*
*/
Cypress.Commands.add('percyCanvasSnapshot', (name, options = {}) => {
function convertCanvas(documentClone) {
documentClone
.querySelectorAll('canvas')
.forEach(selector => canvasToImage(selector));
return documentClone;
}
function canvasToImage(selectorOrEl) {
let canvas =
typeof selectorOrEl === 'object'
? selectorOrEl
: document.querySelector(selectorOrEl);
let image = document.createElement('img');
let canvasImageBase64 = canvas.toDataURL();
image.src = canvasImageBase64;
image.style = 'max-width: 100%';
canvas.setAttribute('data-percy-modified', true);
canvas.parentElement.appendChild(image);
canvas.style = 'display: none';
}
cy.percySnapshot(name, { ...options, domTransformation: convertCanvas });
});
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/viewer",
"version": "1.11.4",
"version": "1.12.0",
"description": "OHIF Viewer",
"author": "OHIF Contributors",
"license": "MIT",
@@ -45,12 +45,12 @@
},
"dependencies": {
"@babel/runtime": "^7.5.5",
"@ohif/core": "^1.4.0",
"@ohif/core": "^1.5.0",
"@ohif/extension-cornerstone": "^2.0.0",
"@ohif/extension-dicom-html": "^1.0.0",
"@ohif/extension-dicom-microscopy": "^0.50.6",
"@ohif/extension-dicom-pdf": "^1.0.0",
"@ohif/extension-vtk": "^0.52.16",
"@ohif/extension-vtk": "^0.52.17",
"@ohif/i18n": "^0.51.0",
"@ohif/ui": "^0.56.0",
"@tanem/react-nprogress": "^1.1.25",
@@ -0,0 +1,9 @@
import React, { useEffect, useRef } from 'react';
export default function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
}, [value]);
return ref.current;
}
+72 -15
View File
@@ -1,8 +1,10 @@
import React, { useContext } from 'react';
import GoogleCloudApi from '../googleCloud/api/GoogleCloudApi';
import usePrevious from './usePrevious';
import * as GoogleCloudUtilServers from '../googleCloud/utils/getServers';
import { useSelector, useDispatch } from 'react-redux';
import isEqual from 'lodash.isequal';
// Contexts
import AppContext from '../context/AppContext';
@@ -32,28 +34,68 @@ const getServers = (appConfig, project, location, dataset, dicomStore) => {
wadoRoot: pathUrl,
};
servers = GoogleCloudUtilServers.getServers(data, dicomStore);
if (!isValidServer(servers[0], appConfig)) {
return;
}
}
return servers;
};
const updateServer = (
const isValidServer = (server, appConfig) => {
if (appConfig.enableGoogleCloudAdapter) {
return GoogleCloudUtilServers.isValidServer(server);
}
return !!server;
};
const setServers = (dispatch, servers) => {
const action = {
type: 'SET_SERVERS',
servers,
};
dispatch(action);
};
const useServerFromUrl = (
servers = [],
previousServers,
activeServer,
urlBasedServers,
appConfig,
dispatch,
project,
location,
dataset,
dicomStore
) => {
const servers = getServers(appConfig, project, location, dataset, dicomStore);
if (servers && servers.length) {
const action = {
type: 'SET_SERVERS',
servers,
};
dispatch(action);
// update state from url available only when gcloud on
if (!appConfig.enableGoogleCloudAdapter) {
return false;
}
const serverHasChanged = previousServers !== servers && previousServers;
// do not update from url. use state instead.
if (serverHasChanged) {
return false;
}
// if no valid urlbased servers
if (!urlBasedServers || !urlBasedServers.length) {
return false;
} else if (!servers.length || !activeServer) {
// no current valid server
return true;
}
const newServer = urlBasedServers[0];
let exists = servers.some(
GoogleCloudUtilServers.isEqualServer.bind(undefined, newServer)
);
return !exists;
};
export default function useServer({
@@ -64,14 +106,29 @@ export default function useServer({
} = {}) {
// Hooks
const servers = useSelector(state => state && state.servers);
const previousServers = usePrevious(servers);
const dispatch = useDispatch();
const { appConfig = {} } = useContext(AppContext);
const server = getActiveServer(servers);
const activeServer = getActiveServer(servers);
const urlBasedServers =
getServers(appConfig, project, location, dataset, dicomStore) || [];
const shouldUpdateServer = useServerFromUrl(
servers.servers,
previousServers,
activeServer,
urlBasedServers,
appConfig,
project,
location,
dataset,
dicomStore
);
if (!server) {
updateServer(appConfig, dispatch, project, location, dataset, dicomStore);
} else {
return server;
if (shouldUpdateServer) {
setServers(dispatch, urlBasedServers);
} else if (isValidServer(activeServer, appConfig)) {
return activeServer;
}
}
@@ -29,6 +29,10 @@ class GoogleCloudApi {
);
}
getUrlPath(project, location, dataset, dicomStore) {
`/projects/${project}/locations/${location}/datasets/${dataset}/dicomStores/${dicomStore}`;
}
async doRequest(urlStr, config = {}, params = {}) {
const url = new URL(urlStr);
let data = null;
@@ -29,4 +29,31 @@ const getServers = (data, name) => {
];
};
export { getServers };
const isValidServer = server => {
return (
server &&
!!server.dataset &&
!!server.dicomStore &&
!!server.location &&
!!server.project
);
};
const isEqualServer = (server = {}, toCompare = {}) => {
const serverLength = Object.keys(server).length;
const toCompareLength = Object.keys(toCompare).length;
if (!serverLength || !toCompareLength) {
return false;
}
return (
server.dataset === toCompare.dataset &&
server.dataset === toCompare.dataset &&
server.dicomStore === toCompare.dicomStore &&
server.location === toCompare.location &&
server.project === toCompare.project
);
};
export { getServers, isValidServer, isEqualServer };
+35 -12
View File
@@ -65,6 +65,19 @@ const ROUTES_DEF = {
return !!appConfig.enableGoogleCloudAdapter;
},
},
list: {
path:
'/projects/:project/locations/:location/datasets/:dataset/dicomStores/:dicomStore',
component: StudyListRouting,
condition: appConfig => {
const showList =
appConfig.showStudyList !== undefined
? appConfig.showStudyList
: true;
return showList && !!appConfig.enableGoogleCloudAdapter;
},
},
},
};
@@ -92,23 +105,33 @@ const getRoutes = appConfig => {
return routes;
};
const parsePath = (path, server, params) => {
let _path = path;
const _paramsCopy = Object.assign({}, server, params);
for (let key in _paramsCopy) {
_path = UrlUtil.paramString.replaceParam(_path, key, _paramsCopy[key]);
}
return _path;
};
const parseViewerPath = (appConfig = {}, server = {}, params) => {
let viewerPath = ROUTES_DEF.default.viewer.path;
if (appConfig.enableGoogleCloudAdapter) {
viewerPath = ROUTES_DEF.gcloud.viewer.path;
}
const _paramsCopy = Object.assign({}, server, params);
for (let key in _paramsCopy) {
viewerPath = UrlUtil.paramString.replaceParam(
viewerPath,
key,
_paramsCopy[key]
);
}
return viewerPath;
return parsePath(viewerPath, server, params);
};
export { getRoutes, parseViewerPath, reload };
const parseStudyListPath = (appConfig = {}, server = {}, params) => {
let studyListPath = ROUTES_DEF.default.list.path;
if (appConfig.enableGoogleCloudAdapter) {
studyListPath = ROUTES_DEF.gcloud.list.path || studyListPath;
}
return parsePath(studyListPath, server, params);
};
export { getRoutes, parseViewerPath, parseStudyListPath, reload };
@@ -2,17 +2,26 @@ import React, { useContext } from 'react';
import PropTypes from 'prop-types';
import { withRouter } from 'react-router-dom';
import ConnectedStudyList from './ConnectedStudyList';
import useServer from '../customHooks/useServer';
import OHIF from '@ohif/core';
const { urlUtil: UrlUtil } = OHIF.utils;
// Contexts
import AppContext from '../context/AppContext';
function StudyListRouting({ location }) {
function StudyListRouting({ match: routeMatch, location: routeLocation }) {
const {
project,
location,
dataset,
dicomStore,
studyInstanceUids,
seriesInstanceUids,
} = routeMatch.params;
const server = useServer({ project, location, dataset, dicomStore });
const { appConfig = {} } = useContext(AppContext);
const filters = UrlUtil.queryString.getQueryFilters(location);
const filters = UrlUtil.queryString.getQueryFilters(routeLocation);
let studyListFunctionsEnabled = false;
if (appConfig.studyListFunctionsEnabled) {
@@ -13,6 +13,7 @@ import ConnectedDicomFilesUploader from '../googleCloud/ConnectedDicomFilesUploa
import ConnectedDicomStorePicker from '../googleCloud/ConnectedDicomStorePicker';
import filesToStudies from '../lib/filesToStudies.js';
const { urlUtil: UrlUtil } = OHIF.utils;
// Contexts
import UserManagerContext from '../context/UserManagerContext';
import WhiteLabellingContext from '../context/WhiteLabellingContext';
@@ -202,9 +203,27 @@ class StudyListWithData extends Component {
const viewerPath = RoutesUtil.parseViewerPath(appConfig, server, {
studyInstanceUids: studyInstanceUID,
});
this.props.history.push(viewerPath);
if (UrlUtil.paramString.isValidPath(viewerPath)) {
this.props.history.push(viewerPath);
}
};
updateURL(modalOpened) {
if (!modalOpened) {
const { appConfig = {} } = this.context;
const { server } = this.props;
const listPath = RoutesUtil.parseStudyListPath(appConfig, server);
if (UrlUtil.paramString.isValidPath(listPath)) {
const { location = {} } = this.props.history;
if (location.pathname !== listPath) {
this.props.history.replace(listPath);
}
}
}
}
onSearch = searchData => {
this.searchForStudies(searchData);
};
@@ -235,9 +254,12 @@ class StudyListWithData extends Component {
let healthCareApiWindows = null;
if (appConfig.enableGoogleCloudAdapter) {
const modalOpened = this.state.modalComponentId === 'DicomStorePicker';
this.updateURL(modalOpened);
healthCareApiWindows = (
<ConnectedDicomStorePicker
isOpen={this.state.modalComponentId === 'DicomStorePicker'}
isOpen={modalOpened}
onClose={this.closeModals}
/>
);
+4 -4
View File
@@ -15526,10 +15526,10 @@ react-transition-group@^4.1.1:
loose-envify "^1.4.0"
prop-types "^15.6.2"
react-vtkjs-viewport@^0.3.5:
version "0.3.5"
resolved "https://registry.yarnpkg.com/react-vtkjs-viewport/-/react-vtkjs-viewport-0.3.5.tgz#772a5e51e1a8f7e9ca170e9044bee28debf04002"
integrity sha512-JeSrS0oaV5fcHTN8VOGzP4ayM0K4PNoPrEYpyw9CGHbBFivshEiQnbyDqpPxkbHJrLCf2dNKTqbI3A5cL4iTZQ==
react-vtkjs-viewport@^0.3.6:
version "0.3.6"
resolved "https://registry.yarnpkg.com/react-vtkjs-viewport/-/react-vtkjs-viewport-0.3.6.tgz#69df6c5c8808a64dc005d77e8058f9a99eaaca02"
integrity sha512-tK6thFTiStFhfYuKBf6xEPRUYf+iZVcujzDElbMFqggRC5PgzcLfYZFAI/bI+9ju7VVyuVazhADu2KHJZYsuEg==
dependencies:
date-fns "^2.2.1"
gl-matrix "^3.1.0"