Compare commits
30
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3296ffaa07 | ||
|
|
0456d92462 | ||
|
|
db3b15e537 | ||
|
|
6e723ebced | ||
|
|
a6a231c81e | ||
|
|
7c2bd9b76a | ||
|
|
5dfa8d465d | ||
|
|
fc5301e904 | ||
|
|
88e5a7e54a | ||
|
|
5d24bb4b73 | ||
|
|
03a4056179 | ||
|
|
ec76bc3b0b | ||
|
|
b1070acaca | ||
|
|
7b5beb8f98 | ||
|
|
97410e12b9 | ||
|
|
bdecbfeee3 | ||
|
|
5a970056ae | ||
|
|
8581405352 | ||
|
|
df8c4db2ed | ||
|
|
ea62bdaddf | ||
|
|
e983b02677 | ||
|
|
1e4b78d78d | ||
|
|
ee6131f98e | ||
|
|
a56bdd035b | ||
|
|
04901c296e | ||
|
|
59cadad98c | ||
|
|
14d6454eaf | ||
|
|
64f87d2c93 | ||
|
|
cfd66e5ef7 | ||
|
|
6480389778 |
No files matched your search
@@ -248,9 +248,6 @@ To acknowledge the OHIF Viewer in an academic publication, please cite
|
|||||||
>
|
>
|
||||||
> _Cancer Research_, November 1 2017 (77) (21) e119-e122 DOI:
|
> _Cancer Research_, November 1 2017 (77) (21) e119-e122 DOI:
|
||||||
> [10.1158/0008-5472.CAN-17-0334](https://www.doi.org/10.1158/0008-5472.CAN-17-0334)
|
> [10.1158/0008-5472.CAN-17-0334](https://www.doi.org/10.1158/0008-5472.CAN-17-0334)
|
||||||
>
|
|
||||||
> NCI Imaging Data Commons: contract number 19X037Q from Leidos Biomedical
|
|
||||||
> Research under Task Order HHSN26100071 from NCI.
|
|
||||||
|
|
||||||
**Note:** If you use or find this repository helpful, please take the time to
|
**Note:** If you use or find this repository helpful, please take the time to
|
||||||
star this repository on Github. This is an easy way for us to assess adoption
|
star this repository on Github. This is an easy way for us to assess adoption
|
||||||
@@ -261,6 +258,22 @@ Cancer Institute, Informatics Technology for Cancer Research (ITCR) program,
|
|||||||
under a
|
under a
|
||||||
[grant to Dr. Gordon Harris at Massachusetts General Hospital (U24 CA199460)](https://projectreporter.nih.gov/project_info_description.cfm?aid=8971104).
|
[grant to Dr. Gordon Harris at Massachusetts General Hospital (U24 CA199460)](https://projectreporter.nih.gov/project_info_description.cfm?aid=8971104).
|
||||||
|
|
||||||
|
## Projects that contributed to OHIF Viewer
|
||||||
|
|
||||||
|
The following is a (partial) list of projects that contributed resources towards
|
||||||
|
development of OHIF Viewer:
|
||||||
|
|
||||||
|
- [NCI Imaging Data Commons (IDC) project](https://imaging.datacommons.cancer.gov/)
|
||||||
|
supported development of new features and bug fixes marked with
|
||||||
|
["IDC:priority"](https://github.com/OHIF/Viewers/issues?q=is%3Aissue+is%3Aopen+label%3AIDC%3Apriority),
|
||||||
|
["IDC:candidate"](https://github.com/OHIF/Viewers/issues?q=is%3Aissue+is%3Aopen+label%3AIDC%3Acandidate)
|
||||||
|
or
|
||||||
|
["IDC:collaboration"](https://github.com/OHIF/Viewers/issues?q=is%3Aissue+is%3Aopen+label%3AIDC%3Acollaboration).
|
||||||
|
NCI Imaging Data Commons is supported by the contract number 19X037Q from
|
||||||
|
Leidos Biomedical Research under Task Order HHSN26100071 from NCI.
|
||||||
|
[IDC Viewer](https://learn.canceridc.dev/portal/visualization) is a customized
|
||||||
|
version of the OHIF Viewer.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT © [OHIF](https://github.com/OHIF)
|
MIT © [OHIF](https://github.com/OHIF)
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|
||||||
|
## [2.10.5](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.10.4...@ohif/extension-cornerstone@2.10.5) (2021-03-15)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [2.10.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.10.3...@ohif/extension-cornerstone@2.10.4) (2021-03-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [2.10.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.10.2...@ohif/extension-cornerstone@2.10.3) (2021-03-03)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [2.10.2](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.10.1...@ohif/extension-cornerstone@2.10.2) (2021-02-25)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.10.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.10.0...@ohif/extension-cornerstone@2.10.1) (2021-02-05)
|
## [2.10.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.10.0...@ohif/extension-cornerstone@2.10.1) (2021-02-05)
|
||||||
|
|
||||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ohif/extension-cornerstone",
|
"name": "@ohif/extension-cornerstone",
|
||||||
"version": "2.10.1",
|
"version": "2.10.5",
|
||||||
"description": "OHIF extension for Cornerstone",
|
"description": "OHIF extension for Cornerstone",
|
||||||
"author": "OHIF",
|
"author": "OHIF",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
"cornerstone-math": "^0.1.8",
|
"cornerstone-math": "^0.1.8",
|
||||||
"cornerstone-tools": "^4.20.1",
|
"cornerstone-tools": "^4.20.1",
|
||||||
"cornerstone-wado-image-loader": "^3.1.0",
|
"cornerstone-wado-image-loader": "^3.1.0",
|
||||||
"dcmjs": "0.17.2",
|
"dcmjs": "0.18.3",
|
||||||
"dicom-parser": "^1.8.3",
|
"dicom-parser": "^1.8.3",
|
||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
@@ -51,6 +51,6 @@
|
|||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"lodash.merge": "^4.6.2",
|
"lodash.merge": "^4.6.2",
|
||||||
"lodash.throttle": "^4.1.1",
|
"lodash.throttle": "^4.1.1",
|
||||||
"react-cornerstone-viewport": "4.0.4"
|
"react-cornerstone-viewport": "4.0.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,25 @@
|
|||||||
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.
|
||||||
|
|
||||||
|
## [0.2.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-debugging@0.2.0...@ohif/extension-debugging@0.2.1) (2021-03-19)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-debugging
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [0.2.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-debugging@0.1.6...@ohif/extension-debugging@0.2.0) (2021-03-04)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **log:** add new log service ([14d6454](https://github.com/OHIF/Viewers/commit/14d6454eafaa2ccb50e133c2945c9558052ea27e))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [0.1.6](https://github.com/OHIF/Viewers/compare/@ohif/extension-debugging@0.1.5...@ohif/extension-debugging@0.1.6) (2020-10-06)
|
## [0.1.6](https://github.com/OHIF/Viewers/compare/@ohif/extension-debugging@0.1.5...@ohif/extension-debugging@0.1.6) (2020-10-06)
|
||||||
|
|
||||||
**Note:** Version bump only for package @ohif/extension-debugging
|
**Note:** Version bump only for package @ohif/extension-debugging
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ohif/extension-debugging",
|
"name": "@ohif/extension-debugging",
|
||||||
"version": "0.1.6",
|
"version": "0.2.1",
|
||||||
"description": "OHIF extension for debugging.",
|
"description": "OHIF extension for debugging.",
|
||||||
"author": "OHIF",
|
"author": "OHIF",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -12,3 +12,15 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.debug-report-modal-container .errors {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.debug-report-modal-container .errors-container {
|
||||||
|
border: 1px solid var(--active-color);
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 10px;
|
||||||
|
overflow: scroll;
|
||||||
|
max-height: 300px;
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@ const DubugReportModal = ({
|
|||||||
extensionManager,
|
extensionManager,
|
||||||
mailTo,
|
mailTo,
|
||||||
debugModalMessage,
|
debugModalMessage,
|
||||||
|
errors = [],
|
||||||
}) => {
|
}) => {
|
||||||
const copyDebugDataToClipboard = () => {
|
const copyDebugDataToClipboard = () => {
|
||||||
const body = getEmailBody();
|
const body = getEmailBody();
|
||||||
@@ -131,6 +132,19 @@ const DubugReportModal = ({
|
|||||||
{getLayout(viewports)}
|
{getLayout(viewports)}
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="errors">
|
||||||
|
<h3>Errors ({errors.length})</h3>
|
||||||
|
<div className="errors-container">
|
||||||
|
{errors.map(error => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<pre>Message: {error.message}</pre>
|
||||||
|
{error.error && <pre>Stack: {error.error.stack}</pre>}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import OHIF from '@ohif/core';
|
import OHIF from '@ohif/core';
|
||||||
|
import { useLogger } from '@ohif/ui';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
save,
|
save,
|
||||||
upload,
|
upload,
|
||||||
@@ -95,6 +97,7 @@ export function getCommands(context, servicesManager, extensionManager) {
|
|||||||
const { UIModalService } = servicesManager.services;
|
const { UIModalService } = servicesManager.services;
|
||||||
|
|
||||||
const WrappedDebugReportModal = function() {
|
const WrappedDebugReportModal = function() {
|
||||||
|
const { state: loggerState } = useLogger();
|
||||||
return (
|
return (
|
||||||
<DebugReportModal
|
<DebugReportModal
|
||||||
viewports={viewports}
|
viewports={viewports}
|
||||||
@@ -103,6 +106,7 @@ export function getCommands(context, servicesManager, extensionManager) {
|
|||||||
extensionManager={extensionManager}
|
extensionManager={extensionManager}
|
||||||
mailTo={state.mailTo}
|
mailTo={state.mailTo}
|
||||||
debugModalMessage={state.debugModalMessage}
|
debugModalMessage={state.debugModalMessage}
|
||||||
|
errors={loggerState.errors}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
const state = { mailTo: undefined, message: undefined };
|
const state = { mailTo: undefined, debugModalMessage: undefined };
|
||||||
|
|
||||||
export default state;
|
export default state;
|
||||||
@@ -3,6 +3,30 @@
|
|||||||
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.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.3...@ohif/extension-dicom-html@1.3.4) (2021-03-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-dicom-html
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.3.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.2...@ohif/extension-dicom-html@1.3.3) (2021-03-03)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-dicom-html
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.3.2](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.1...@ohif/extension-dicom-html@1.3.2) (2021-02-25)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-dicom-html
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [1.3.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.0...@ohif/extension-dicom-html@1.3.1) (2021-02-05)
|
## [1.3.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.0...@ohif/extension-dicom-html@1.3.1) (2021-02-05)
|
||||||
|
|
||||||
**Note:** Version bump only for package @ohif/extension-dicom-html
|
**Note:** Version bump only for package @ohif/extension-dicom-html
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ohif/extension-dicom-html",
|
"name": "@ohif/extension-dicom-html",
|
||||||
"version": "1.3.1",
|
"version": "1.3.4",
|
||||||
"description": "OHIF extension for rendering structured reports to HTML",
|
"description": "OHIF extension for rendering structured reports to HTML",
|
||||||
"author": "OHIF",
|
"author": "OHIF",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@ohif/core": "^0.50.0",
|
"@ohif/core": "^0.50.0",
|
||||||
"dcmjs": "0.17.2",
|
"dcmjs": "0.18.3",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^16.8.6",
|
"react": "^16.8.6",
|
||||||
"react-dom": "^16.8.6"
|
"react-dom": "^16.8.6"
|
||||||
|
|||||||
@@ -3,6 +3,17 @@
|
|||||||
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.
|
||||||
|
|
||||||
|
# [0.52.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-microscopy@0.51.4...@ohif/extension-dicom-microscopy@0.52.0) (2021-03-04)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **log:** add new log service ([14d6454](https://github.com/OHIF/Viewers/commit/14d6454eafaa2ccb50e133c2945c9558052ea27e))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [0.51.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-microscopy@0.51.3...@ohif/extension-dicom-microscopy@0.51.4) (2021-01-21)
|
## [0.51.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-microscopy@0.51.3...@ohif/extension-dicom-microscopy@0.51.4) (2021-01-21)
|
||||||
|
|
||||||
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
|
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ohif/extension-dicom-microscopy",
|
"name": "@ohif/extension-dicom-microscopy",
|
||||||
"version": "0.51.4",
|
"version": "0.52.0",
|
||||||
"description": "OHIF extension for Dicom Microscopy",
|
"description": "OHIF extension for Dicom Microscopy",
|
||||||
"author": "OHIF",
|
"author": "OHIF",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -70,12 +70,18 @@ class DicomMicroscopyViewport extends Component {
|
|||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[Microscopy Viewer] Failed to load:', error);
|
console.error('[Microscopy Viewer] Failed to load:', error);
|
||||||
const { UINotificationService } = this.props.servicesManager.services;
|
const {
|
||||||
|
UINotificationService,
|
||||||
|
LoggerService,
|
||||||
|
} = this.props.servicesManager.services;
|
||||||
if (UINotificationService) {
|
if (UINotificationService) {
|
||||||
|
const message =
|
||||||
|
'Failed to load viewport. Please check that you have hardware acceleration enabled.';
|
||||||
|
LoggerService.error({ error, message });
|
||||||
UINotificationService.show({
|
UINotificationService.show({
|
||||||
|
autoClose: false,
|
||||||
title: 'Microscopy Viewport',
|
title: 'Microscopy Viewport',
|
||||||
message:
|
message,
|
||||||
'Failed to load viewport. Please check that you have hardware acceleration enabled.',
|
|
||||||
type: 'error',
|
type: 'error',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,30 @@
|
|||||||
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.
|
||||||
|
|
||||||
|
## [0.6.7](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.6.6...@ohif/extension-dicom-rt@0.6.7) (2021-03-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-dicom-rt
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.6.6](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.6.5...@ohif/extension-dicom-rt@0.6.6) (2021-03-03)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-dicom-rt
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.6.5](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.6.4...@ohif/extension-dicom-rt@0.6.5) (2021-02-25)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-dicom-rt
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [0.6.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.6.3...@ohif/extension-dicom-rt@0.6.4) (2021-02-05)
|
## [0.6.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.6.3...@ohif/extension-dicom-rt@0.6.4) (2021-02-05)
|
||||||
|
|
||||||
**Note:** Version bump only for package @ohif/extension-dicom-rt
|
**Note:** Version bump only for package @ohif/extension-dicom-rt
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ohif/extension-dicom-rt",
|
"name": "@ohif/extension-dicom-rt",
|
||||||
"version": "0.6.4",
|
"version": "0.6.7",
|
||||||
"description": "OHIF extension for rendering DICOM RTSTRUCTs on top of cornerstone images.",
|
"description": "OHIF extension for rendering DICOM RTSTRUCTs on top of cornerstone images.",
|
||||||
"author": "OHIF",
|
"author": "OHIF",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
"@ohif/core": "^0.50.0",
|
"@ohif/core": "^0.50.0",
|
||||||
"cornerstone-core": "^2.2.8",
|
"cornerstone-core": "^2.2.8",
|
||||||
"cornerstone-tools": "^4.20.1",
|
"cornerstone-tools": "^4.20.1",
|
||||||
"dcmjs": "0.17.2",
|
"dcmjs": "0.18.3",
|
||||||
"gl-matrix": "^3.3.0",
|
"gl-matrix": "^3.3.0",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^16.8.6",
|
"react": "^16.8.6",
|
||||||
|
|||||||
@@ -3,6 +3,41 @@
|
|||||||
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.
|
||||||
|
|
||||||
|
## [0.6.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.6.0...@ohif/extension-dicom-segmentation@0.6.1) (2021-03-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [0.6.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.5.4...@ohif/extension-dicom-segmentation@0.6.0) (2021-03-04)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **log:** add new log service ([14d6454](https://github.com/OHIF/Viewers/commit/14d6454eafaa2ccb50e133c2945c9558052ea27e))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.5.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.5.3...@ohif/extension-dicom-segmentation@0.5.4) (2021-03-03)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.5.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.5.2...@ohif/extension-dicom-segmentation@0.5.3) (2021-02-25)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [0.5.2](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.5.1...@ohif/extension-dicom-segmentation@0.5.2) (2021-02-05)
|
## [0.5.2](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.5.1...@ohif/extension-dicom-segmentation@0.5.2) (2021-02-05)
|
||||||
|
|
||||||
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
|
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ohif/extension-dicom-segmentation",
|
"name": "@ohif/extension-dicom-segmentation",
|
||||||
"version": "0.5.2",
|
"version": "0.6.1",
|
||||||
"description": "OHIF extension for viewing segmentations in the 2D MPR view",
|
"description": "OHIF extension for viewing segmentations in the 2D MPR view",
|
||||||
"author": "OHIF",
|
"author": "OHIF",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
"@ohif/core": "^0.50.0",
|
"@ohif/core": "^0.50.0",
|
||||||
"cornerstone-core": "^2.2.8",
|
"cornerstone-core": "^2.2.8",
|
||||||
"cornerstone-tools": "^4.20.1",
|
"cornerstone-tools": "^4.20.1",
|
||||||
"dcmjs": "0.17.2",
|
"dcmjs": "0.18.3",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^16.8.6",
|
"react": "^16.8.6",
|
||||||
"react-dom": "^16.8.6"
|
"react-dom": "^16.8.6"
|
||||||
|
|||||||
@@ -25,12 +25,13 @@ export default {
|
|||||||
return toolbarModule;
|
return toolbarModule;
|
||||||
},
|
},
|
||||||
getPanelModule({ commandsManager, api, servicesManager }) {
|
getPanelModule({ commandsManager, api, servicesManager }) {
|
||||||
const { UINotificationService } = servicesManager.services;
|
const { UINotificationService, LoggerService } = servicesManager.services;
|
||||||
|
|
||||||
const ExtendedSegmentationPanel = props => {
|
const ExtendedSegmentationPanel = props => {
|
||||||
const { activeContexts } = api.hooks.useAppContext();
|
const { activeContexts } = api.hooks.useAppContext();
|
||||||
|
|
||||||
const onDisplaySetLoadFailureHandler = error => {
|
const onDisplaySetLoadFailureHandler = error => {
|
||||||
|
LoggerService.error({ error, message: error.message });
|
||||||
UINotificationService.show({
|
UINotificationService.show({
|
||||||
title: 'DICOM Segmentation Loader',
|
title: 'DICOM Segmentation Loader',
|
||||||
message: error.message,
|
message: error.message,
|
||||||
|
|||||||
@@ -3,6 +3,30 @@
|
|||||||
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.
|
||||||
|
|
||||||
|
## [0.2.5](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.4...@ohif/extension-dicom-tag-browser@0.2.5) (2021-03-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.2.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.3...@ohif/extension-dicom-tag-browser@0.2.4) (2021-03-03)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.2.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.2...@ohif/extension-dicom-tag-browser@0.2.3) (2021-02-25)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [0.2.2](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.1...@ohif/extension-dicom-tag-browser@0.2.2) (2021-02-05)
|
## [0.2.2](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.1...@ohif/extension-dicom-tag-browser@0.2.2) (2021-02-05)
|
||||||
|
|
||||||
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
|
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ohif/extension-dicom-tag-browser",
|
"name": "@ohif/extension-dicom-tag-browser",
|
||||||
"version": "0.2.2",
|
"version": "0.2.5",
|
||||||
"description": "OHIF extension for checking DICOM headers.",
|
"description": "OHIF extension for checking DICOM headers.",
|
||||||
"author": "OHIF",
|
"author": "OHIF",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@ohif/core": "^2.6.0",
|
"@ohif/core": "^2.6.0",
|
||||||
"dcmjs": "0.17.2",
|
"dcmjs": "0.18.3",
|
||||||
"react": "^16.8.6"
|
"react": "^16.8.6"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -3,6 +3,65 @@
|
|||||||
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.11.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.11.3...@ohif/extension-vtk@1.11.4) (2021-03-26)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-vtk
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.11.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.11.2...@ohif/extension-vtk@1.11.3) (2021-03-25)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-vtk
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.11.2](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.11.1...@ohif/extension-vtk@1.11.2) (2021-03-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-vtk
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.11.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.11.0...@ohif/extension-vtk@1.11.1) (2021-03-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-vtk
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [1.11.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.10.6...@ohif/extension-vtk@1.11.0) (2021-03-04)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **log:** add new log service ([14d6454](https://github.com/OHIF/Viewers/commit/14d6454eafaa2ccb50e133c2945c9558052ea27e))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.10.6](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.10.5...@ohif/extension-vtk@1.10.6) (2021-03-03)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-vtk
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.10.5](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.10.4...@ohif/extension-vtk@1.10.5) (2021-02-25)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-vtk
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [1.10.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.10.3...@ohif/extension-vtk@1.10.4) (2021-02-05)
|
## [1.10.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.10.3...@ohif/extension-vtk@1.10.4) (2021-02-05)
|
||||||
|
|
||||||
**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.10.4",
|
"version": "1.11.4",
|
||||||
"description": "OHIF extension for VTK.js",
|
"description": "OHIF extension for VTK.js",
|
||||||
"author": "OHIF",
|
"author": "OHIF",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
"cornerstone-core": "^2.2.8",
|
"cornerstone-core": "^2.2.8",
|
||||||
"cornerstone-tools": "^4.20.1",
|
"cornerstone-tools": "^4.20.1",
|
||||||
"cornerstone-wado-image-loader": "^3.1.0",
|
"cornerstone-wado-image-loader": "^3.1.0",
|
||||||
"dcmjs": "0.17.2",
|
"dcmjs": "0.18.3",
|
||||||
"dicom-parser": "^1.8.3",
|
"dicom-parser": "^1.8.3",
|
||||||
"i18next": "^17.0.3",
|
"i18next": "^17.0.3",
|
||||||
"i18next-browser-languagedetector": "^3.0.1",
|
"i18next-browser-languagedetector": "^3.0.1",
|
||||||
@@ -53,8 +53,8 @@
|
|||||||
"react-vtkjs-viewport": "^0.14.2"
|
"react-vtkjs-viewport": "^0.14.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ohif/core": "^2.12.3",
|
"@ohif/core": "^2.13.3",
|
||||||
"@ohif/ui": "^1.8.2",
|
"@ohif/ui": "^1.9.1",
|
||||||
"cornerstone-tools": "^4.20.1",
|
"cornerstone-tools": "^4.20.1",
|
||||||
"cornerstone-wado-image-loader": "^3.1.0",
|
"cornerstone-wado-image-loader": "^3.1.0",
|
||||||
"dicom-parser": "^1.8.3",
|
"dicom-parser": "^1.8.3",
|
||||||
|
|||||||
@@ -360,12 +360,15 @@ class OHIFVTKViewport extends Component {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
const errorTitle = 'Failed to load 2D MPR';
|
const errorTitle = 'Failed to load 2D MPR';
|
||||||
console.error(errorTitle, error);
|
console.error(errorTitle, error);
|
||||||
const { UINotificationService } = this.props.servicesManager.services;
|
const {
|
||||||
|
UINotificationService,
|
||||||
|
LoggerService,
|
||||||
|
} = this.props.servicesManager.services;
|
||||||
if (this.props.viewportIndex === 0) {
|
if (this.props.viewportIndex === 0) {
|
||||||
const message = error.message.includes('buffer')
|
const message = error.message.includes('buffer')
|
||||||
? 'Dataset is too big to display in MPR'
|
? 'Dataset is too big to display in MPR'
|
||||||
: error.message;
|
: error.message;
|
||||||
console.error(errorTitle, error);
|
LoggerService.error({ error, message });
|
||||||
UINotificationService.show({
|
UINotificationService.show({
|
||||||
title: errorTitle,
|
title: errorTitle,
|
||||||
message,
|
message,
|
||||||
@@ -428,11 +431,15 @@ class OHIFVTKViewport extends Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onPixelDataInsertedErrorCallback = error => {
|
const onPixelDataInsertedErrorCallback = error => {
|
||||||
const { UINotificationService } = this.props.servicesManager.services;
|
const {
|
||||||
|
UINotificationService,
|
||||||
|
LoggerService,
|
||||||
|
} = this.props.servicesManager.services;
|
||||||
|
|
||||||
if (!this.hasError) {
|
if (!this.hasError) {
|
||||||
if (this.props.viewportIndex === 0) {
|
if (this.props.viewportIndex === 0) {
|
||||||
// Only show the notification from one viewport 1 in MPR2D.
|
// Only show the notification from one viewport 1 in MPR2D.
|
||||||
|
LoggerService.error({ error, message: error.message });
|
||||||
UINotificationService.show({
|
UINotificationService.show({
|
||||||
title: 'MPR Load Error',
|
title: 'MPR Load Error',
|
||||||
message: error.message,
|
message: error.message,
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ import OHIFVTKViewport from './OHIFVTKViewport';
|
|||||||
|
|
||||||
const { BlendMode } = Constants;
|
const { BlendMode } = Constants;
|
||||||
|
|
||||||
const commandsModule = ({ commandsManager, UINotificationService }) => {
|
const commandsModule = ({ commandsManager, servicesManager }) => {
|
||||||
|
const { UINotificationService, LoggerService } = servicesManager.services;
|
||||||
|
|
||||||
// TODO: Put this somewhere else
|
// TODO: Put this somewhere else
|
||||||
let apis = {};
|
let apis = {};
|
||||||
let defaultVOI;
|
let defaultVOI;
|
||||||
@@ -175,7 +177,7 @@ const commandsModule = ({ commandsManager, UINotificationService }) => {
|
|||||||
segmentNumber,
|
segmentNumber,
|
||||||
frameIndex,
|
frameIndex,
|
||||||
frame,
|
frame,
|
||||||
done = () => { },
|
done = () => {},
|
||||||
}) => {
|
}) => {
|
||||||
let api = apis[viewports.activeViewportIndex];
|
let api = apis[viewports.activeViewportIndex];
|
||||||
|
|
||||||
@@ -473,10 +475,12 @@ const commandsModule = ({ commandsManager, UINotificationService }) => {
|
|||||||
const volumeLength = dimensions[0] * dimensions[1] * dimensions[2];
|
const volumeLength = dimensions[0] * dimensions[1] * dimensions[2];
|
||||||
|
|
||||||
if (volumeLength > maxBufferLengthFloat32) {
|
if (volumeLength > maxBufferLengthFloat32) {
|
||||||
|
const message =
|
||||||
|
'This volume is too large to fit in WebGL 1 textures and will display incorrectly. Please use a different browser to view this data';
|
||||||
|
LoggerService.error({ message });
|
||||||
UINotificationService.show({
|
UINotificationService.show({
|
||||||
title: 'Browser does not support WebGL 2',
|
title: 'Browser does not support WebGL 2',
|
||||||
message:
|
message,
|
||||||
'This volume is too large to fit in WebGL 1 textures and will display incorrectly. Please use a different browser to view this data',
|
|
||||||
type: 'error',
|
type: 'error',
|
||||||
autoClose: false,
|
autoClose: false,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -35,8 +35,7 @@ const vtkExtension = {
|
|||||||
return toolbarModule;
|
return toolbarModule;
|
||||||
},
|
},
|
||||||
getCommandsModule({ commandsManager, servicesManager }) {
|
getCommandsModule({ commandsManager, servicesManager }) {
|
||||||
const { UINotificationService } = servicesManager.services;
|
return commandsModule({ commandsManager, servicesManager });
|
||||||
return commandsModule({ commandsManager, UINotificationService });
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -31,63 +31,7 @@ const _isDisplaySetReconstructable = (viewportSpecificData = {}, activeViewportI
|
|||||||
|
|
||||||
if (!displaySet) {
|
if (!displaySet) {
|
||||||
return false;
|
return false;
|
||||||
}
|
};
|
||||||
|
|
||||||
// 2D MPR is not currently available for 4D datasets.
|
|
||||||
|
|
||||||
// Assuming that slices at different time have the same position, here we just check if
|
|
||||||
// there are multiple slices for the same ImagePositionPatient and disable MPR.
|
|
||||||
|
|
||||||
// A better heuristic would be checking 4D tags, e.g. the presence of multiple TemporalPositionIdentifier values.
|
|
||||||
// However, some studies (e.g. https://github.com/OHIF/Viewers/issues/2113) do not have such tags.
|
|
||||||
|
|
||||||
for (let ii = 0; ii < displaySet.numImageFrames; ++ii) {
|
|
||||||
const image = displaySet.images[ii];
|
|
||||||
if (!image) continue;
|
|
||||||
|
|
||||||
const imageIdControl = image.getImageId()
|
|
||||||
const instanceMetadataControl = cornerstone.metaData.get('instance', imageIdControl)
|
|
||||||
|
|
||||||
if (!instanceMetadataControl ||
|
|
||||||
instanceMetadataControl === undefined ||
|
|
||||||
!instanceMetadataControl.ImagePositionPatient ||
|
|
||||||
instanceMetadataControl.ImagePositionPatient === undefined) {
|
|
||||||
// if ImagePositionPatient is missing, skip the 4D datasets check.
|
|
||||||
// do not return false, because it could be a 3D dataset.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let xImagePositionPatientControl = instanceMetadataControl.ImagePositionPatient[0];
|
|
||||||
let yImagePositionPatientControl = instanceMetadataControl.ImagePositionPatient[1];
|
|
||||||
let zImagePositionPatientControl = instanceMetadataControl.ImagePositionPatient[2];
|
|
||||||
|
|
||||||
for (let jj = ii + 1; jj < displaySet.numImageFrames; ++jj) {
|
|
||||||
const image = displaySet.images[jj];
|
|
||||||
if (!image) continue;
|
|
||||||
|
|
||||||
const imageId = image.getImageId()
|
|
||||||
const instanceMetadata = cornerstone.metaData.get('instance', imageId)
|
|
||||||
|
|
||||||
if (!instanceMetadata ||
|
|
||||||
instanceMetadata === undefined ||
|
|
||||||
!instanceMetadata.ImagePositionPatient ||
|
|
||||||
instanceMetadata.ImagePositionPatient === undefined) {
|
|
||||||
// if ImagePositionPatient is missing, skip the 4D datasets check.
|
|
||||||
// do not return false, because it could be a 3D dataset.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let xImagePositionPatient = instanceMetadata.ImagePositionPatient[0];
|
|
||||||
let yImagePositionPatient = instanceMetadata.ImagePositionPatient[1];
|
|
||||||
let zImagePositionPatient = instanceMetadata.ImagePositionPatient[2];
|
|
||||||
|
|
||||||
if (xImagePositionPatientControl === xImagePositionPatient &&
|
|
||||||
yImagePositionPatientControl === yImagePositionPatient &&
|
|
||||||
zImagePositionPatientControl === zImagePositionPatient) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return displaySet.isReconstructable;
|
return displaySet.isReconstructable;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,6 +3,60 @@
|
|||||||
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.13.3](https://github.com/OHIF/Viewers/compare/@ohif/core@2.13.2...@ohif/core@2.13.3) (2021-03-26)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/core
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [2.13.2](https://github.com/OHIF/Viewers/compare/@ohif/core@2.13.1...@ohif/core@2.13.2) (2021-03-25)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* IDC-2288: Update toolbar tabs after derived displayset loaded ([#2307](https://github.com/OHIF/Viewers/issues/2307)) ([6e723eb](https://github.com/OHIF/Viewers/commit/6e723ebced58852007ca553792c740976cfc4201))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [2.13.1](https://github.com/OHIF/Viewers/compare/@ohif/core@2.13.0...@ohif/core@2.13.1) (2021-03-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/core
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [2.13.0](https://github.com/OHIF/Viewers/compare/@ohif/core@2.12.5...@ohif/core@2.13.0) (2021-03-04)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **log:** add new log service ([14d6454](https://github.com/OHIF/Viewers/commit/14d6454eafaa2ccb50e133c2945c9558052ea27e))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [2.12.5](https://github.com/OHIF/Viewers/compare/@ohif/core@2.12.4...@ohif/core@2.12.5) (2021-03-03)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/core
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [2.12.4](https://github.com/OHIF/Viewers/compare/@ohif/core@2.12.3...@ohif/core@2.12.4) (2021-02-25)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/core
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.12.3](https://github.com/OHIF/Viewers/compare/@ohif/core@2.12.2...@ohif/core@2.12.3) (2021-02-05)
|
## [2.12.3](https://github.com/OHIF/Viewers/compare/@ohif/core@2.12.2...@ohif/core@2.12.3) (2021-02-05)
|
||||||
|
|
||||||
**Note:** Version bump only for package @ohif/core
|
**Note:** Version bump only for package @ohif/core
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ohif/core",
|
"name": "@ohif/core",
|
||||||
"version": "2.12.3",
|
"version": "2.13.3",
|
||||||
"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",
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.5.5",
|
"@babel/runtime": "^7.5.5",
|
||||||
"ajv": "^6.10.0",
|
"ajv": "^6.10.0",
|
||||||
"dcmjs": "0.17.2",
|
"dcmjs": "0.18.3",
|
||||||
"dicomweb-client": "^0.6.0",
|
"dicomweb-client": "^0.6.0",
|
||||||
"immer": "6.0.2",
|
"immer": "6.0.2",
|
||||||
"isomorphic-base64": "^1.0.2",
|
"isomorphic-base64": "^1.0.2",
|
||||||
|
|||||||
@@ -63,10 +63,15 @@ export class HotkeysManager {
|
|||||||
|
|
||||||
definitions.forEach(definition => this.registerHotkeys(definition));
|
definitions.forEach(definition => this.registerHotkeys(definition));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const { UINotificationService } = this._servicesManager.services;
|
const {
|
||||||
|
UINotificationService,
|
||||||
|
LoggerService,
|
||||||
|
} = this._servicesManager.services;
|
||||||
|
const message = 'Erro while setting hotkeys';
|
||||||
|
LoggerService.error({ error, message });
|
||||||
UINotificationService.show({
|
UINotificationService.show({
|
||||||
title: 'Hotkeys Manager',
|
title: 'Hotkeys Manager',
|
||||||
message: 'Erro while setting hotkeys',
|
message,
|
||||||
type: 'error',
|
type: 'error',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -767,6 +767,16 @@ const isMultiFrame = instance => {
|
|||||||
return instance.getTagValue('NumberOfFrames') > 1;
|
return instance.getTagValue('NumberOfFrames') > 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a display set for a series.
|
||||||
|
* Checks if a series is reconstructable to a 3D volume.
|
||||||
|
* If reconstructable, the frames are sorted.
|
||||||
|
*
|
||||||
|
* @param {SeriesMetadata} series The series metadata object from which the display sets will be created
|
||||||
|
* @param {Object[]} instances An array of `OHIFInstanceMetadata` objects.
|
||||||
|
*
|
||||||
|
* @returns {Object} imageSet.
|
||||||
|
*/
|
||||||
const makeDisplaySet = (series, instances) => {
|
const makeDisplaySet = (series, instances) => {
|
||||||
const instance = instances[0];
|
const instance = instances[0];
|
||||||
const imageSet = new ImageSet(instances);
|
const imageSet = new ImageSet(instances);
|
||||||
@@ -804,18 +814,22 @@ const makeDisplaySet = (series, instances) => {
|
|||||||
imageSet.getImage(0).getTagValue('InstanceNumber')
|
imageSet.getImage(0).getTagValue('InstanceNumber')
|
||||||
);
|
);
|
||||||
|
|
||||||
const isReconstructable = isDisplaySetReconstructable(instances);
|
const displayReconstructableInfo = isDisplaySetReconstructable(instances);
|
||||||
|
imageSet.isReconstructable = displayReconstructableInfo.value;
|
||||||
imageSet.isReconstructable = isReconstructable.value;
|
|
||||||
|
|
||||||
if (shallSort && imageSet.isReconstructable) {
|
if (shallSort && imageSet.isReconstructable) {
|
||||||
imageSet.sortByImagePositionPatient();
|
imageSet.sortByImagePositionPatient();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isReconstructable.missingFrames) {
|
if (displayReconstructableInfo.missingFrames) {
|
||||||
// TODO -> This is currently unused, but may be used for reconstructing
|
// TODO -> This is currently unused, but may be used for reconstructing
|
||||||
// Volumes with gaps later on.
|
// Volumes with gaps later on.
|
||||||
imageSet.missingFrames = isReconstructable.missingFrames;
|
imageSet.missingFrames = displayReconstructableInfo.missingFrames;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!imageSet.displayReconstructableInfo) {
|
||||||
|
// It is not reconstrabale Save type of warning
|
||||||
|
imageSet.warningIssues = displayReconstructableInfo.warningIssues;
|
||||||
}
|
}
|
||||||
|
|
||||||
return imageSet;
|
return imageSet;
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
const ReconstructionIssues = {
|
||||||
|
DATASET_4D: 'datasetis4D',
|
||||||
|
VARYING_IMAGESDIMENSIONS: 'imagesdimensionsvarying',
|
||||||
|
VARYING_IMAGESCOMPONENTS: 'imagescomponentsvarying',
|
||||||
|
VARYING_IMAGESORIENTATION: 'imagesorientationvarying',
|
||||||
|
MISSING_FRAMES: 'missingframes',
|
||||||
|
IRREGULAR_SPACING: 'irregularspacing',
|
||||||
|
MULTIFFRAMES: 'multiframe',
|
||||||
|
};
|
||||||
|
|
||||||
|
export {ReconstructionIssues};
|
||||||
@@ -26,6 +26,7 @@ import {
|
|||||||
UIModalService,
|
UIModalService,
|
||||||
UIDialogService,
|
UIDialogService,
|
||||||
MeasurementService,
|
MeasurementService,
|
||||||
|
LoggerService,
|
||||||
} from './services';
|
} from './services';
|
||||||
|
|
||||||
const OHIF = {
|
const OHIF = {
|
||||||
@@ -60,6 +61,7 @@ const OHIF = {
|
|||||||
UIModalService,
|
UIModalService,
|
||||||
UIDialogService,
|
UIDialogService,
|
||||||
MeasurementService,
|
MeasurementService,
|
||||||
|
LoggerService,
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@@ -93,6 +95,7 @@ export {
|
|||||||
UIModalService,
|
UIModalService,
|
||||||
UIDialogService,
|
UIDialogService,
|
||||||
MeasurementService,
|
MeasurementService,
|
||||||
|
LoggerService,
|
||||||
};
|
};
|
||||||
|
|
||||||
export { OHIF };
|
export { OHIF };
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ describe('Top level exports', () => {
|
|||||||
'UIModalService',
|
'UIModalService',
|
||||||
'UIDialogService',
|
'UIDialogService',
|
||||||
'MeasurementService',
|
'MeasurementService',
|
||||||
|
'LoggerService',
|
||||||
//
|
//
|
||||||
'utils',
|
'utils',
|
||||||
'hotkeys',
|
'hotkeys',
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
const name = 'LoggerService';
|
||||||
|
|
||||||
|
const publicAPI = {
|
||||||
|
name,
|
||||||
|
info: _info,
|
||||||
|
error: _error,
|
||||||
|
setServiceImplementation,
|
||||||
|
};
|
||||||
|
|
||||||
|
const serviceImplementation = {
|
||||||
|
_info: () => console.warn('info() NOT IMPLEMENTED'),
|
||||||
|
_error: () => console.warn('error() NOT IMPLEMENTED'),
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs an info
|
||||||
|
*
|
||||||
|
* @param {object} props { message, displayOnConsole }
|
||||||
|
*/
|
||||||
|
function _info({ message, displayOnConsole }) {
|
||||||
|
return serviceImplementation._info({
|
||||||
|
message,
|
||||||
|
displayOnConsole,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs an error
|
||||||
|
*
|
||||||
|
* @param {object} props { error, stack, message, displayOnConsole }
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
function _error({ error, stack, message, displayOnConsole }) {
|
||||||
|
return serviceImplementation._error({
|
||||||
|
error,
|
||||||
|
stack,
|
||||||
|
message,
|
||||||
|
displayOnConsole,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param {*} {
|
||||||
|
* info: infoImplementation,
|
||||||
|
* error: errorImplementation,
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
function setServiceImplementation({
|
||||||
|
info: infoImplementation,
|
||||||
|
error: errorImplementation,
|
||||||
|
}) {
|
||||||
|
if (infoImplementation) {
|
||||||
|
serviceImplementation._info = infoImplementation;
|
||||||
|
}
|
||||||
|
if (errorImplementation) {
|
||||||
|
serviceImplementation._error = errorImplementation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name,
|
||||||
|
create: ({ configuration = {} }) => {
|
||||||
|
return publicAPI;
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -3,6 +3,7 @@ import UINotificationService from './UINotificationService';
|
|||||||
import UIModalService from './UIModalService';
|
import UIModalService from './UIModalService';
|
||||||
import UIDialogService from './UIDialogService';
|
import UIDialogService from './UIDialogService';
|
||||||
import MeasurementService from './MeasurementService';
|
import MeasurementService from './MeasurementService';
|
||||||
|
import LoggerService from './LoggerService';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
UINotificationService,
|
UINotificationService,
|
||||||
@@ -10,4 +11,5 @@ export {
|
|||||||
UIDialogService,
|
UIDialogService,
|
||||||
ServicesManager,
|
ServicesManager,
|
||||||
MeasurementService,
|
MeasurementService,
|
||||||
|
LoggerService,
|
||||||
};
|
};
|
||||||
@@ -1,7 +1,12 @@
|
|||||||
|
import { ReconstructionIssues } from './../enums.js';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if a series is reconstructable to a 3D volume.
|
* Checks if a series is reconstructable to a 3D volume.
|
||||||
*
|
*
|
||||||
* @param {Object[]} instances An array of `OHIFInstanceMetadata` objects.
|
* @param {Object[]} instances An array of `OHIFInstanceMetadata` objects.
|
||||||
|
*
|
||||||
|
* @returns {Object} reconstructable value, missingFrames and warningIssues.
|
||||||
*/
|
*/
|
||||||
export default function isDisplaySetReconstructable(instances) {
|
export default function isDisplaySetReconstructable(instances) {
|
||||||
if (!instances.length) {
|
if (!instances.length) {
|
||||||
@@ -29,12 +34,28 @@ export default function isDisplaySetReconstructable(instances) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process reconstructable multiframes checks
|
||||||
|
* TODO: deal with multriframe checks! return false for now as can't reconstruct.
|
||||||
|
*
|
||||||
|
* @param {Object} instanceof `OHIFInstanceMetadata` objects. Currently not used.
|
||||||
|
*
|
||||||
|
* @returns {Object} reconstructable value and warningIssues.
|
||||||
|
*/
|
||||||
function processMultiframe(instance) {
|
function processMultiframe(instance) {
|
||||||
//TODO: deal with multriframe checks! return false for now as can't reconstruct.
|
const warningIssues = [ReconstructionIssues.MULTIFRAMES];
|
||||||
return { value: false };
|
return { value: false, warningIssues };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process reconstructable single frame checks
|
||||||
|
*
|
||||||
|
* @param {Object[]} instances An array of `OHIFInstanceMetadata` objects.
|
||||||
|
*
|
||||||
|
* @returns {Object} reconstructable value, missingFrames and warningIssues.
|
||||||
|
*/
|
||||||
function processSingleframe(instances) {
|
function processSingleframe(instances) {
|
||||||
|
const n = instances.length;
|
||||||
const firstImage = instances[0].getData().metadata;
|
const firstImage = instances[0].getData().metadata;
|
||||||
const firstImageRows = firstImage.Rows;
|
const firstImageRows = firstImage.Rows;
|
||||||
const firstImageColumns = firstImage.Columns;
|
const firstImageColumns = firstImage.Columns;
|
||||||
@@ -42,12 +63,13 @@ function processSingleframe(instances) {
|
|||||||
const firstImageOrientationPatient = firstImage.ImageOrientationPatient;
|
const firstImageOrientationPatient = firstImage.ImageOrientationPatient;
|
||||||
const firstImagePositionPatient = firstImage.ImagePositionPatient;
|
const firstImagePositionPatient = firstImage.ImagePositionPatient;
|
||||||
|
|
||||||
|
const warningIssues = [];
|
||||||
// Can't reconstruct if we:
|
// Can't reconstruct if we:
|
||||||
// -- Have a different dimensions within a displaySet.
|
// -- Have a different dimensions within a displaySet.
|
||||||
// -- Have a different number of components within a displaySet.
|
// -- Have a different number of components within a displaySet.
|
||||||
// -- Have different orientations within a displaySet.
|
// -- Have different orientations within a displaySet.
|
||||||
for (let i = 1; i < instances.length; i++) {
|
for (let ii = 1; ii < n; ++ii) {
|
||||||
const instance = instances[i].getData().metadata;
|
const instance = instances[ii].getData().metadata;
|
||||||
const {
|
const {
|
||||||
Rows,
|
Rows,
|
||||||
Columns,
|
Columns,
|
||||||
@@ -55,13 +77,16 @@ function processSingleframe(instances) {
|
|||||||
ImageOrientationPatient,
|
ImageOrientationPatient,
|
||||||
} = instance;
|
} = instance;
|
||||||
|
|
||||||
if (
|
if (Rows !== firstImageRows || Columns !== firstImageColumns) {
|
||||||
Rows !== firstImageRows ||
|
warningIssues.push(ReconstructionIssues.VARYING_IMAGESDIMENSIONS);
|
||||||
Columns !== firstImageColumns ||
|
} else if (SamplesPerPixel !== firstImageSamplesPerPixel) {
|
||||||
SamplesPerPixel !== firstImageSamplesPerPixel ||
|
warningIssues.push(ReconstructionIssues.VARYING_IMAGESCOMPONENTS);
|
||||||
!_isSameOrientation(ImageOrientationPatient, firstImageOrientationPatient)
|
} else if (!_isSameArray(ImageOrientationPatient, firstImageOrientationPatient)) {
|
||||||
) {
|
warningIssues.push(ReconstructionIssues.VARYING_IMAGESORIENTATION);
|
||||||
return { value: false };
|
}
|
||||||
|
|
||||||
|
if (warningIssues.length !== 0) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,52 +95,101 @@ function processSingleframe(instances) {
|
|||||||
// Check if frame spacing is approximately equal within a spacingTolerance.
|
// Check if frame spacing is approximately equal within a spacingTolerance.
|
||||||
// If spacing is on a uniform grid but we are missing frames,
|
// If spacing is on a uniform grid but we are missing frames,
|
||||||
// Allow reconstruction, but pass back the number of missing frames.
|
// Allow reconstruction, but pass back the number of missing frames.
|
||||||
if (instances.length > 2) {
|
if (n > 2) {
|
||||||
const lastIpp = instances[instances.length - 1].getData().metadata
|
const lastIpp = instances[n - 1].getData().metadata
|
||||||
.ImagePositionPatient;
|
.ImagePositionPatient;
|
||||||
|
|
||||||
// We can't reconstruct if we are missing ImagePositionPatient values
|
// We can't reconstruct if we are missing ImagePositionPatient values
|
||||||
if (!firstImagePositionPatient || !lastIpp) {
|
if (firstImagePositionPatient && lastIpp) {
|
||||||
return { value: false };
|
const averageSpacingBetweenFrames =
|
||||||
}
|
_getPerpendicularDistance(firstImagePositionPatient, lastIpp) /
|
||||||
|
(n - 1);
|
||||||
|
|
||||||
const averageSpacingBetweenFrames =
|
let previousImagePositionPatient = firstImagePositionPatient;
|
||||||
_getPerpendicularDistance(firstImagePositionPatient, lastIpp) /
|
|
||||||
(instances.length - 1);
|
|
||||||
|
|
||||||
let previousImagePositionPatient = firstImagePositionPatient;
|
for (let ii = 1; ii < n; ++ii) {
|
||||||
|
const instance = instances[ii].getData().metadata;
|
||||||
|
const { ImagePositionPatient } = instance;
|
||||||
|
|
||||||
for (let i = 1; i < instances.length; i++) {
|
const spacingBetweenFrames = _getPerpendicularDistance(
|
||||||
const instance = instances[i].getData().metadata;
|
ImagePositionPatient,
|
||||||
const { ImagePositionPatient } = instance;
|
previousImagePositionPatient
|
||||||
|
);
|
||||||
|
const spacingIssue = _getSpacingIssue(
|
||||||
|
spacingBetweenFrames,
|
||||||
|
averageSpacingBetweenFrames
|
||||||
|
);
|
||||||
|
|
||||||
const spacingBetweenFrames = _getPerpendicularDistance(
|
if (spacingIssue) {
|
||||||
ImagePositionPatient,
|
const issue = spacingIssue.issue;
|
||||||
previousImagePositionPatient
|
|
||||||
);
|
|
||||||
const spacingIssue = _getSpacingIssue(
|
|
||||||
spacingBetweenFrames,
|
|
||||||
averageSpacingBetweenFrames
|
|
||||||
);
|
|
||||||
|
|
||||||
if (spacingIssue) {
|
if (issue === ReconstructionIssues.MISSING_FRAMES) {
|
||||||
const issue = spacingIssue.issue;
|
missingFrames += spacingIssue.missingFrames;
|
||||||
|
} else if (issue === ReconstructionIssues.IRREGULAR_SPACING) {
|
||||||
if (issue === reconstructionIssues.MISSING_FRAMES) {
|
warningIssues.push(issue);
|
||||||
missingFrames += spacingIssue.missingFrames;
|
break;
|
||||||
} else if (issue === reconstructionIssues.IRREGULAR_SPACING) {
|
}
|
||||||
return { value: false };
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
previousImagePositionPatient = ImagePositionPatient;
|
previousImagePositionPatient = ImagePositionPatient;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { value: true, missingFrames };
|
// check if dataset is 4D
|
||||||
|
if (_isDataset4D(instances)) {
|
||||||
|
warningIssues.push(ReconstructionIssues.DATASET_4D);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { value: warningIssues.length === 0 ? true : false, missingFrames, warningIssues };
|
||||||
}
|
}
|
||||||
|
|
||||||
function _isSameOrientation(iop1, iop2) {
|
/**
|
||||||
|
* Check if 4D dataset.
|
||||||
|
*
|
||||||
|
* Assuming that slices at different time have the same position, here we just check if
|
||||||
|
* there are multiple slices for the same ImagePositionPatient and disable MPR.
|
||||||
|
*
|
||||||
|
* A better heuristic would be checking 4D tags, e.g. the presence of multiple TemporalPositionIdentifier values.
|
||||||
|
* However, some studies (e.g. https://github.com/OHIF/Viewers/issues/2113) do not have such tags.
|
||||||
|
*
|
||||||
|
* @param {Object[]} instances An array of `OHIFInstanceMetadata` objects.
|
||||||
|
*
|
||||||
|
* @returns {boolean} reconstructable value.
|
||||||
|
*/
|
||||||
|
function _isDataset4D(instances) {
|
||||||
|
const n = instances.length;
|
||||||
|
for (let ii = 0; ii < n; ++ii) {
|
||||||
|
const instanceMetadataControl = instances[ii].getData().metadata;
|
||||||
|
if (
|
||||||
|
!instanceMetadataControl ||
|
||||||
|
instanceMetadataControl === undefined ||
|
||||||
|
!instanceMetadataControl.ImagePositionPatient ||
|
||||||
|
instanceMetadataControl.ImagePositionPatient === undefined
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (let jj = ii + 1; jj < n; ++jj) {
|
||||||
|
const instanceMetadata = instances[jj].getData().metadata;
|
||||||
|
if (
|
||||||
|
!instanceMetadata ||
|
||||||
|
instanceMetadata === undefined ||
|
||||||
|
!instanceMetadata.ImagePositionPatient ||
|
||||||
|
instanceMetadata.ImagePositionPatient === undefined
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_isSameArray(instanceMetadataControl.ImagePositionPatient, instanceMetadata.ImagePositionPatient)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _isSameArray(iop1, iop2) {
|
||||||
if (iop1 === undefined || !iop2 === undefined) {
|
if (iop1 === undefined || !iop2 === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -156,12 +230,12 @@ function _getSpacingIssue(spacing, averageSpacing) {
|
|||||||
|
|
||||||
if (errorForEachSpacing < spacingTolerance * averageSpacing) {
|
if (errorForEachSpacing < spacingTolerance * averageSpacing) {
|
||||||
return {
|
return {
|
||||||
issue: reconstructionIssues.MISSING_FRAMES,
|
issue: ReconstructionIssues.MISSING_FRAMES,
|
||||||
missingFrames: numberOfSpacings - 1,
|
missingFrames: numberOfSpacings - 1,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return { issue: reconstructionIssues.IRREGULAR_SPACING };
|
return { issue: ReconstructionIssues.IRREGULAR_SPACING };
|
||||||
}
|
}
|
||||||
|
|
||||||
function _getPerpendicularDistance(a, b) {
|
function _getPerpendicularDistance(a, b) {
|
||||||
@@ -173,7 +247,3 @@ function _getPerpendicularDistance(a, b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const constructableModalities = ['MR', 'CT', 'PT', 'NM'];
|
const constructableModalities = ['MR', 'CT', 'PT', 'NM'];
|
||||||
const reconstructionIssues = {
|
|
||||||
MISSING_FRAMES: 'missingframes',
|
|
||||||
IRREGULAR_SPACING: 'irregularspacing',
|
|
||||||
};
|
|
||||||
@@ -49,9 +49,7 @@ import studyMetadataManager from './studyMetadataManager';
|
|||||||
*/
|
*/
|
||||||
const loadAndCacheDerivedDisplaySets = (referencedDisplaySet, studies) => {
|
const loadAndCacheDerivedDisplaySets = (referencedDisplaySet, studies) => {
|
||||||
const { StudyInstanceUID, SeriesInstanceUID } = referencedDisplaySet;
|
const { StudyInstanceUID, SeriesInstanceUID } = referencedDisplaySet;
|
||||||
|
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
|
||||||
const studyMetadata = studyMetadataManager.get(StudyInstanceUID);
|
const studyMetadata = studyMetadataManager.get(StudyInstanceUID);
|
||||||
|
|
||||||
if (!studyMetadata) {
|
if (!studyMetadata) {
|
||||||
@@ -112,6 +110,16 @@ const loadAndCacheDerivedDisplaySets = (referencedDisplaySet, studies) => {
|
|||||||
promises.push(recentDisplaySet.load(referencedDisplaySet, studies));
|
promises.push(recentDisplaySet.load(referencedDisplaySet, studies));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Promise.all(promises).then(() => {
|
||||||
|
/*
|
||||||
|
* TODO: Improve the way we notify parts of the app
|
||||||
|
* that depends on derived display sets to be loaded.
|
||||||
|
* (Implement pubsub for better tracking of derived display sets)
|
||||||
|
*/
|
||||||
|
const event = new CustomEvent('deriveddisplaysetsloadedandcached');
|
||||||
|
document.dispatchEvent(event);
|
||||||
|
});
|
||||||
|
|
||||||
return promises;
|
return promises;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,25 @@
|
|||||||
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.9.1](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.9.0...@ohif/ui@1.9.1) (2021-03-26)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/ui
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [1.9.0](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.8.2...@ohif/ui@1.9.0) (2021-03-04)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **log:** add new log service ([14d6454](https://github.com/OHIF/Viewers/commit/14d6454eafaa2ccb50e133c2945c9558052ea27e))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [1.8.2](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.8.1...@ohif/ui@1.8.2) (2021-02-05)
|
## [1.8.2](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.8.1...@ohif/ui@1.8.2) (2021-02-05)
|
||||||
|
|
||||||
**Note:** Version bump only for package @ohif/ui
|
**Note:** Version bump only for package @ohif/ui
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ohif/ui",
|
"name": "@ohif/ui",
|
||||||
"version": "1.8.2",
|
"version": "1.9.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",
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ function StudyBrowser(props) {
|
|||||||
SeriesDescription,
|
SeriesDescription,
|
||||||
SeriesNumber,
|
SeriesNumber,
|
||||||
stackPercentComplete,
|
stackPercentComplete,
|
||||||
|
hasWarnings,
|
||||||
} = thumb;
|
} = thumb;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -50,6 +51,7 @@ function StudyBrowser(props) {
|
|||||||
numImageFrames={numImageFrames}
|
numImageFrames={numImageFrames}
|
||||||
SeriesDescription={SeriesDescription}
|
SeriesDescription={SeriesDescription}
|
||||||
SeriesNumber={SeriesNumber}
|
SeriesNumber={SeriesNumber}
|
||||||
|
hasWarnings={hasWarnings}
|
||||||
stackPercentComplete={stackPercentComplete}
|
stackPercentComplete={stackPercentComplete}
|
||||||
// Events
|
// Events
|
||||||
onClick={onThumbnailClick.bind(
|
onClick={onThumbnailClick.bind(
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
import React from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useDrag } from 'react-dnd';
|
import { useDrag } from 'react-dnd';
|
||||||
import ImageThumbnail from './ImageThumbnail';
|
import ImageThumbnail from './ImageThumbnail';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { Icon } from './../../elements/Icon';
|
||||||
|
import { Tooltip } from './../tooltip';
|
||||||
|
import { OverlayTrigger } from './../overlayTrigger';
|
||||||
|
|
||||||
import './Thumbnail.styl';
|
import './Thumbnail.styl';
|
||||||
|
|
||||||
@@ -11,7 +14,22 @@ function ThumbnailFooter({
|
|||||||
SeriesNumber,
|
SeriesNumber,
|
||||||
InstanceNumber,
|
InstanceNumber,
|
||||||
numImageFrames,
|
numImageFrames,
|
||||||
|
hasWarnings
|
||||||
}) {
|
}) {
|
||||||
|
const [warningList, warningListSet] = useState([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let unmounted = false
|
||||||
|
hasWarnings.then(response => {
|
||||||
|
if (!unmounted) {
|
||||||
|
warningListSet(response)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return () => {
|
||||||
|
unmounted = true
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
const infoOnly = !SeriesDescription;
|
const infoOnly = !SeriesDescription;
|
||||||
|
|
||||||
const getInfo = (value, icon, className = '') => {
|
const getInfo = (value, icon, className = '') => {
|
||||||
@@ -22,28 +40,73 @@ function ThumbnailFooter({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getWarningContent = (warningList) => {
|
||||||
|
if (Array.isArray(warningList)) {
|
||||||
|
const listedWarnings = warningList.map((warn, index) => {
|
||||||
|
return <li key={index}>{warn}</li>;
|
||||||
|
});
|
||||||
|
|
||||||
|
return <ol>{listedWarnings}</ol>;
|
||||||
|
} else {
|
||||||
|
return <React.Fragment>{warningList}</React.Fragment>;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getWarningInfo = (SeriesNumber, warningList) => {
|
||||||
|
return(
|
||||||
|
<React.Fragment>
|
||||||
|
{warningList.length != 0 ? (
|
||||||
|
<OverlayTrigger
|
||||||
|
key={SeriesNumber}
|
||||||
|
placement="left"
|
||||||
|
overlay={
|
||||||
|
<Tooltip
|
||||||
|
placement="left"
|
||||||
|
className="in tooltip-warning"
|
||||||
|
id="tooltip-left"
|
||||||
|
>
|
||||||
|
<div className="warningTitle">Series Inconsistencies</div>
|
||||||
|
<div className="warningContent">{getWarningContent(warningList)}</div>
|
||||||
|
</Tooltip>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className={classNames('warning')}>
|
||||||
|
<span className="warning-icon">
|
||||||
|
<Icon name="exclamation-triangle" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</OverlayTrigger>
|
||||||
|
) : (
|
||||||
|
<React.Fragment></React.Fragment>
|
||||||
|
)}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
};
|
||||||
const getSeriesInformation = (
|
const getSeriesInformation = (
|
||||||
SeriesNumber,
|
SeriesNumber,
|
||||||
InstanceNumber,
|
InstanceNumber,
|
||||||
numImageFrames
|
numImageFrames,
|
||||||
|
warningList
|
||||||
) => {
|
) => {
|
||||||
if (!SeriesNumber && !InstanceNumber && !numImageFrames) {
|
if (!SeriesNumber && !InstanceNumber && !numImageFrames) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const seriesInformation =
|
||||||
return (
|
|
||||||
<div className="series-information">
|
<div className="series-information">
|
||||||
{getInfo(SeriesNumber, 'S:')}
|
{getInfo(SeriesNumber, 'S:')}
|
||||||
{getInfo(InstanceNumber, 'I:')}
|
{getInfo(InstanceNumber, 'I:')}
|
||||||
{getInfo(numImageFrames, '', 'image-frames')}
|
{getInfo(numImageFrames, '', 'image-frames')}
|
||||||
|
{getWarningInfo(SeriesNumber, warningList)}
|
||||||
</div>
|
</div>
|
||||||
);
|
|
||||||
|
return (seriesInformation);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames('series-details', { 'info-only': infoOnly })}>
|
<div className={classNames('series-details', { 'info-only': infoOnly })}>
|
||||||
<div className="series-description">{SeriesDescription}</div>
|
<div className="series-description">{SeriesDescription}</div>
|
||||||
{getSeriesInformation(SeriesNumber, InstanceNumber, numImageFrames)}
|
{getSeriesInformation(SeriesNumber, InstanceNumber, numImageFrames, warningList)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -60,6 +123,7 @@ function Thumbnail(props) {
|
|||||||
numImageFrames,
|
numImageFrames,
|
||||||
SeriesDescription,
|
SeriesDescription,
|
||||||
SeriesNumber,
|
SeriesNumber,
|
||||||
|
hasWarnings,
|
||||||
stackPercentComplete,
|
stackPercentComplete,
|
||||||
StudyInstanceUID,
|
StudyInstanceUID,
|
||||||
onClick,
|
onClick,
|
||||||
@@ -126,13 +190,14 @@ Thumbnail.propTypes = {
|
|||||||
stackPercentComplete: PropTypes.number,
|
stackPercentComplete: PropTypes.number,
|
||||||
/**
|
/**
|
||||||
altImageText will be used when no imageId or imageSrc is provided.
|
altImageText will be used when no imageId or imageSrc is provided.
|
||||||
It will be displayed inside the <div>. This is useful when it is difficult
|
It will be displayed inside the <div>. This is useful when it is difficult
|
||||||
to make a preview for a type of DICOM series (e.g. DICOM-SR)
|
to make a preview for a type of DICOM series (e.g. DICOM-SR)
|
||||||
*/
|
*/
|
||||||
altImageText: PropTypes.string,
|
altImageText: PropTypes.string,
|
||||||
SeriesDescription: PropTypes.string,
|
SeriesDescription: PropTypes.string,
|
||||||
SeriesNumber: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
SeriesNumber: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
InstanceNumber: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
InstanceNumber: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
|
hasWarnings: PropTypes.instanceOf(Promise),
|
||||||
numImageFrames: PropTypes.number,
|
numImageFrames: PropTypes.number,
|
||||||
onDoubleClick: PropTypes.func,
|
onDoubleClick: PropTypes.func,
|
||||||
onClick: PropTypes.func,
|
onClick: PropTypes.func,
|
||||||
|
|||||||
@@ -78,6 +78,17 @@
|
|||||||
height: 11px
|
height: 11px
|
||||||
width: 11px
|
width: 11px
|
||||||
|
|
||||||
|
.warning
|
||||||
|
margin: auto 0;
|
||||||
|
opacity: 1
|
||||||
|
color: #e29e4a;
|
||||||
|
|
||||||
|
svg
|
||||||
|
width: 16px;
|
||||||
|
height: 14px;
|
||||||
|
pointer-events: inherit;
|
||||||
|
|
||||||
|
|
||||||
.value
|
.value
|
||||||
color: var(--text-secondary-color);
|
color: var(--text-secondary-color);
|
||||||
display: inline-block
|
display: inline-block
|
||||||
|
|||||||
@@ -0,0 +1,104 @@
|
|||||||
|
import React, { useState, createContext, useContext, useEffect } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
const LoggerContext = createContext(null);
|
||||||
|
const { Provider } = LoggerContext;
|
||||||
|
|
||||||
|
export const useLogger = () => useContext(LoggerContext);
|
||||||
|
|
||||||
|
const LoggerProvider = ({ children, service }) => {
|
||||||
|
const [state, setState] = useState({
|
||||||
|
errors: [],
|
||||||
|
infos: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const onErrorHandler = ({ error: errorObject, message }) => {
|
||||||
|
error({ error: errorObject, message });
|
||||||
|
};
|
||||||
|
window.addEventListener('error', onErrorHandler);
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('error', onErrorHandler);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs an error
|
||||||
|
*
|
||||||
|
* @param {object} props { error, stack, message, displayOnConsole }
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
const error = ({
|
||||||
|
error = {},
|
||||||
|
stack = '',
|
||||||
|
message = '',
|
||||||
|
displayOnConsole = true,
|
||||||
|
}) => {
|
||||||
|
const errorObject = { error, stack, message, displayOnConsole };
|
||||||
|
setState(state => ({ ...state, errors: [...state.errors, errorObject] }));
|
||||||
|
|
||||||
|
if (displayOnConsole) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs an info
|
||||||
|
*
|
||||||
|
* @param {object} props { message, displayOnConsole }
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
const info = ({ message = '', displayOnConsole = true }) => {
|
||||||
|
setState(state => ({
|
||||||
|
...state,
|
||||||
|
infos: state.infos.push({ message, displayOnConsole }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (displayOnConsole) {
|
||||||
|
console.info(message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the implementation of a log service that can be used by extensions
|
||||||
|
*
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
useEffect(() => {
|
||||||
|
if (service) {
|
||||||
|
service.setServiceImplementation({ error, info });
|
||||||
|
}
|
||||||
|
}, [error, service, info]);
|
||||||
|
|
||||||
|
return <Provider value={{ info, error, state }}>{children}</Provider>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Higher Order Component to use the log methods through a Class Component
|
||||||
|
*
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const withLogger = Component => {
|
||||||
|
return function WrappedComponent(props) {
|
||||||
|
const { error, info, state } = useLogger();
|
||||||
|
return <Component {...props} logger={{ error, info, state }} />;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
LoggerProvider.defaultProps = {
|
||||||
|
service: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
LoggerProvider.propTypes = {
|
||||||
|
children: PropTypes.oneOfType([
|
||||||
|
PropTypes.arrayOf(PropTypes.node),
|
||||||
|
PropTypes.node,
|
||||||
|
]).isRequired,
|
||||||
|
service: PropTypes.shape({
|
||||||
|
setServiceImplementation: PropTypes.func,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LoggerProvider;
|
||||||
|
|
||||||
|
export const LogConsumer = LoggerContext.Consumer;
|
||||||
@@ -18,3 +18,8 @@ export {
|
|||||||
withDialog,
|
withDialog,
|
||||||
useDialog,
|
useDialog,
|
||||||
} from './DialogProvider.js';
|
} from './DialogProvider.js';
|
||||||
|
export {
|
||||||
|
default as LoggerProvider,
|
||||||
|
withLogger,
|
||||||
|
useLogger,
|
||||||
|
} from './LoggerProvider.js';
|
||||||
@@ -30,7 +30,7 @@ import {
|
|||||||
AboutContent,
|
AboutContent,
|
||||||
OHIFModal,
|
OHIFModal,
|
||||||
ErrorBoundary,
|
ErrorBoundary,
|
||||||
ErrorPage
|
ErrorPage,
|
||||||
} from './components';
|
} from './components';
|
||||||
import { useDebounce, useMedia } from './hooks';
|
import { useDebounce, useMedia } from './hooks';
|
||||||
|
|
||||||
@@ -66,6 +66,9 @@ import {
|
|||||||
ModalConsumer,
|
ModalConsumer,
|
||||||
useModal,
|
useModal,
|
||||||
withModal,
|
withModal,
|
||||||
|
LoggerProvider,
|
||||||
|
withLogger,
|
||||||
|
useLogger,
|
||||||
} from './contextProviders';
|
} from './contextProviders';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@@ -127,11 +130,14 @@ export {
|
|||||||
useDialog,
|
useDialog,
|
||||||
ErrorBoundary,
|
ErrorBoundary,
|
||||||
ErrorPage,
|
ErrorPage,
|
||||||
|
LoggerProvider,
|
||||||
|
withLogger,
|
||||||
|
useLogger,
|
||||||
// Hooks
|
// Hooks
|
||||||
useDebounce,
|
useDebounce,
|
||||||
useMedia,
|
useMedia,
|
||||||
// Utils
|
// Utils
|
||||||
ViewerbaseDragDropContext,
|
ViewerbaseDragDropContext,
|
||||||
asyncComponent,
|
asyncComponent,
|
||||||
retryImport
|
retryImport,
|
||||||
};
|
};
|
||||||
@@ -3,6 +3,84 @@
|
|||||||
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.
|
||||||
|
|
||||||
|
## [4.9.6](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.9.5...@ohif/viewer@4.9.6) (2021-03-26)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [4.9.5](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.9.4...@ohif/viewer@4.9.5) (2021-03-25)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* IDC-2288: Update toolbar tabs after derived displayset loaded ([#2307](https://github.com/OHIF/Viewers/issues/2307)) ([6e723eb](https://github.com/OHIF/Viewers/commit/6e723ebced58852007ca553792c740976cfc4201))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [4.9.4](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.9.3...@ohif/viewer@4.9.4) (2021-03-19)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [4.9.3](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.9.2...@ohif/viewer@4.9.3) (2021-03-15)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [4.9.2](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.9.1...@ohif/viewer@4.9.2) (2021-03-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [4.9.1](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.9.0...@ohif/viewer@4.9.1) (2021-03-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [4.9.0](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.8.12...@ohif/viewer@4.9.0) (2021-03-04)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **log:** add new log service ([14d6454](https://github.com/OHIF/Viewers/commit/14d6454eafaa2ccb50e133c2945c9558052ea27e))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [4.8.12](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.8.11...@ohif/viewer@4.8.12) (2021-03-03)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [4.8.11](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.8.10...@ohif/viewer@4.8.11) (2021-02-25)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [4.8.10](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.8.9...@ohif/viewer@4.8.10) (2021-02-08)
|
## [4.8.10](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.8.9...@ohif/viewer@4.8.10) (2021-02-08)
|
||||||
|
|
||||||
**Note:** Version bump only for package @ohif/viewer
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ohif/viewer",
|
"name": "@ohif/viewer",
|
||||||
"version": "4.8.10",
|
"version": "4.9.6",
|
||||||
"description": "OHIF Viewer",
|
"description": "OHIF Viewer",
|
||||||
"author": "OHIF Contributors",
|
"author": "OHIF Contributors",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -49,18 +49,18 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.5.5",
|
"@babel/runtime": "^7.5.5",
|
||||||
"@ohif/core": "^2.12.3",
|
"@ohif/core": "^2.13.3",
|
||||||
"@ohif/extension-cornerstone": "^2.10.1",
|
"@ohif/extension-cornerstone": "^2.10.5",
|
||||||
"@ohif/extension-debugging": "^0.1.6",
|
"@ohif/extension-debugging": "^0.2.1",
|
||||||
"@ohif/extension-dicom-html": "^1.3.1",
|
"@ohif/extension-dicom-html": "^1.3.4",
|
||||||
"@ohif/extension-dicom-microscopy": "^0.51.4",
|
"@ohif/extension-dicom-microscopy": "^0.52.0",
|
||||||
"@ohif/extension-dicom-pdf": "^1.0.6",
|
"@ohif/extension-dicom-pdf": "^1.0.6",
|
||||||
"@ohif/extension-dicom-rt": "^0.6.4",
|
"@ohif/extension-dicom-rt": "^0.6.7",
|
||||||
"@ohif/extension-dicom-segmentation": "^0.5.2",
|
"@ohif/extension-dicom-segmentation": "^0.6.1",
|
||||||
"@ohif/extension-lesion-tracker": "^0.2.1",
|
"@ohif/extension-lesion-tracker": "^0.2.1",
|
||||||
"@ohif/extension-vtk": "^1.10.4",
|
"@ohif/extension-vtk": "^1.11.4",
|
||||||
"@ohif/i18n": "^0.53.0",
|
"@ohif/i18n": "^0.53.0",
|
||||||
"@ohif/ui": "^1.8.2",
|
"@ohif/ui": "^1.9.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",
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
"cornerstone-math": "^0.1.8",
|
"cornerstone-math": "^0.1.8",
|
||||||
"cornerstone-tools": "^4.20.1",
|
"cornerstone-tools": "^4.20.1",
|
||||||
"cornerstone-wado-image-loader": "^3.1.0",
|
"cornerstone-wado-image-loader": "^3.1.0",
|
||||||
"dcmjs": "0.17.2",
|
"dcmjs": "0.18.3",
|
||||||
"dicom-parser": "^1.8.3",
|
"dicom-parser": "^1.8.3",
|
||||||
"dicomweb-client": "^0.4.4",
|
"dicomweb-client": "^0.4.4",
|
||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
|
|||||||
+30
-19
@@ -13,6 +13,7 @@ import {
|
|||||||
ModalProvider,
|
ModalProvider,
|
||||||
DialogProvider,
|
DialogProvider,
|
||||||
OHIFModal,
|
OHIFModal,
|
||||||
|
LoggerProvider,
|
||||||
ErrorBoundary,
|
ErrorBoundary,
|
||||||
} from '@ohif/ui';
|
} from '@ohif/ui';
|
||||||
|
|
||||||
@@ -24,6 +25,7 @@ import {
|
|||||||
UINotificationService,
|
UINotificationService,
|
||||||
UIModalService,
|
UIModalService,
|
||||||
UIDialogService,
|
UIDialogService,
|
||||||
|
LoggerService,
|
||||||
MeasurementService,
|
MeasurementService,
|
||||||
utils,
|
utils,
|
||||||
redux as reduxOHIF,
|
redux as reduxOHIF,
|
||||||
@@ -141,6 +143,7 @@ class App extends Component {
|
|||||||
UIModalService,
|
UIModalService,
|
||||||
UIDialogService,
|
UIDialogService,
|
||||||
MeasurementService,
|
MeasurementService,
|
||||||
|
LoggerService,
|
||||||
]);
|
]);
|
||||||
_initExtensions(
|
_initExtensions(
|
||||||
[...defaultExtensions, ...extensions],
|
[...defaultExtensions, ...extensions],
|
||||||
@@ -164,6 +167,7 @@ class App extends Component {
|
|||||||
UIDialogService,
|
UIDialogService,
|
||||||
UIModalService,
|
UIModalService,
|
||||||
MeasurementService,
|
MeasurementService,
|
||||||
|
LoggerService,
|
||||||
} = servicesManager.services;
|
} = servicesManager.services;
|
||||||
|
|
||||||
if (this._userManager) {
|
if (this._userManager) {
|
||||||
@@ -176,18 +180,20 @@ class App extends Component {
|
|||||||
<UserManagerContext.Provider value={this._userManager}>
|
<UserManagerContext.Provider value={this._userManager}>
|
||||||
<Router basename={routerBasename}>
|
<Router basename={routerBasename}>
|
||||||
<WhiteLabelingContext.Provider value={whiteLabeling}>
|
<WhiteLabelingContext.Provider value={whiteLabeling}>
|
||||||
<SnackbarProvider service={UINotificationService}>
|
<LoggerProvider service={LoggerService}>
|
||||||
<DialogProvider service={UIDialogService}>
|
<SnackbarProvider service={UINotificationService}>
|
||||||
<ModalProvider
|
<DialogProvider service={UIDialogService}>
|
||||||
modal={OHIFModal}
|
<ModalProvider
|
||||||
service={UIModalService}
|
modal={OHIFModal}
|
||||||
>
|
service={UIModalService}
|
||||||
<OHIFStandaloneViewer
|
>
|
||||||
userManager={this._userManager}
|
<OHIFStandaloneViewer
|
||||||
/>
|
userManager={this._userManager}
|
||||||
</ModalProvider>
|
/>
|
||||||
</DialogProvider>
|
</ModalProvider>
|
||||||
</SnackbarProvider>
|
</DialogProvider>
|
||||||
|
</SnackbarProvider>
|
||||||
|
</LoggerProvider>
|
||||||
</WhiteLabelingContext.Provider>
|
</WhiteLabelingContext.Provider>
|
||||||
</Router>
|
</Router>
|
||||||
</UserManagerContext.Provider>
|
</UserManagerContext.Provider>
|
||||||
@@ -206,13 +212,18 @@ class App extends Component {
|
|||||||
<I18nextProvider i18n={i18n}>
|
<I18nextProvider i18n={i18n}>
|
||||||
<Router basename={routerBasename}>
|
<Router basename={routerBasename}>
|
||||||
<WhiteLabelingContext.Provider value={whiteLabeling}>
|
<WhiteLabelingContext.Provider value={whiteLabeling}>
|
||||||
<SnackbarProvider service={UINotificationService}>
|
<LoggerProvider service={LoggerService}>
|
||||||
<DialogProvider service={UIDialogService}>
|
<SnackbarProvider service={UINotificationService}>
|
||||||
<ModalProvider modal={OHIFModal} service={UIModalService}>
|
<DialogProvider service={UIDialogService}>
|
||||||
<OHIFStandaloneViewer />
|
<ModalProvider
|
||||||
</ModalProvider>
|
modal={OHIFModal}
|
||||||
</DialogProvider>
|
service={UIModalService}
|
||||||
</SnackbarProvider>
|
>
|
||||||
|
<OHIFStandaloneViewer />
|
||||||
|
</ModalProvider>
|
||||||
|
</DialogProvider>
|
||||||
|
</SnackbarProvider>
|
||||||
|
</LoggerProvider>
|
||||||
</WhiteLabelingContext.Provider>
|
</WhiteLabelingContext.Provider>
|
||||||
</Router>
|
</Router>
|
||||||
</I18nextProvider>
|
</I18nextProvider>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import React, { useEffect } from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { utils } from '@ohif/core';
|
import { utils } from '@ohif/core';
|
||||||
import { useSnackbarContext } from '@ohif/ui';
|
import { useSnackbarContext, useLogger } from '@ohif/ui';
|
||||||
//
|
//
|
||||||
import ViewportPane from './ViewportPane.js';
|
import ViewportPane from './ViewportPane.js';
|
||||||
import DefaultViewport from './DefaultViewport.js';
|
import DefaultViewport from './DefaultViewport.js';
|
||||||
@@ -12,7 +12,7 @@ import EmptyViewport from './EmptyViewport.js';
|
|||||||
|
|
||||||
const { loadAndCacheDerivedDisplaySets } = utils;
|
const { loadAndCacheDerivedDisplaySets } = utils;
|
||||||
|
|
||||||
const ViewportGrid = function (props) {
|
const ViewportGrid = function(props) {
|
||||||
const {
|
const {
|
||||||
activeViewportIndex,
|
activeViewportIndex,
|
||||||
availablePlugins,
|
availablePlugins,
|
||||||
@@ -36,14 +36,15 @@ const ViewportGrid = function (props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const snackbar = useSnackbarContext();
|
const snackbar = useSnackbarContext();
|
||||||
|
const logger = useLogger();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isStudyLoaded) {
|
if (isStudyLoaded) {
|
||||||
viewportData.forEach(displaySet => {
|
viewportData.forEach(displaySet => {
|
||||||
const promises = loadAndCacheDerivedDisplaySets(displaySet, studies);
|
const promises = loadAndCacheDerivedDisplaySets(displaySet, studies);
|
||||||
|
|
||||||
promises.forEach(promise => {
|
promises.forEach(promise => {
|
||||||
promise.catch(error => {
|
promise.catch(error => {
|
||||||
|
logger.error({ error, message: error.message });
|
||||||
snackbar.show({
|
snackbar.show({
|
||||||
title: 'Error loading derived display set:',
|
title: 'Error loading derived display set:',
|
||||||
message: error.message,
|
message: error.message,
|
||||||
|
|||||||
@@ -59,6 +59,9 @@ class ToolbarRow extends Component {
|
|||||||
this.seriesPerStudyCount = [];
|
this.seriesPerStudyCount = [];
|
||||||
|
|
||||||
this._handleBuiltIn = _handleBuiltIn.bind(this);
|
this._handleBuiltIn = _handleBuiltIn.bind(this);
|
||||||
|
this._onDerivedDisplaySetsLoadedAndCached = this._onDerivedDisplaySetsLoadedAndCached.bind(
|
||||||
|
this
|
||||||
|
);
|
||||||
|
|
||||||
this.updateButtonGroups();
|
this.updateButtonGroups();
|
||||||
}
|
}
|
||||||
@@ -109,6 +112,32 @@ class ToolbarRow extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
/*
|
||||||
|
* TODO: Improve the way we notify parts of the app
|
||||||
|
* that depends on derived display sets to be loaded.
|
||||||
|
* (Implement pubsub for better tracking of derived display sets)
|
||||||
|
*/
|
||||||
|
document.addEventListener(
|
||||||
|
'deriveddisplaysetsloadedandcached',
|
||||||
|
this._onDerivedDisplaySetsLoadedAndCached
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
document.removeEventListener(
|
||||||
|
'deriveddisplaysetsloadedandcached',
|
||||||
|
this._onDerivedDisplaySetsLoadedAndCached
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_onDerivedDisplaySetsLoadedAndCached() {
|
||||||
|
this.updateButtonGroups();
|
||||||
|
this.setState({
|
||||||
|
toolbarButtons: _getVisibleToolbarButtons.call(this),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
const activeContextsChanged =
|
const activeContextsChanged =
|
||||||
prevProps.activeContexts !== this.props.activeContexts;
|
prevProps.activeContexts !== this.props.activeContexts;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import ConnectedViewerMain from './ConnectedViewerMain.js';
|
|||||||
import SidePanel from './../components/SidePanel.js';
|
import SidePanel from './../components/SidePanel.js';
|
||||||
import ErrorBoundaryDialog from './../components/ErrorBoundaryDialog';
|
import ErrorBoundaryDialog from './../components/ErrorBoundaryDialog';
|
||||||
import { extensionManager } from './../App.js';
|
import { extensionManager } from './../App.js';
|
||||||
|
import { ReconstructionIssues } from './../../../core/src/enums.js';
|
||||||
|
|
||||||
// Contexts
|
// Contexts
|
||||||
import WhiteLabelingContext from '../context/WhiteLabelingContext.js';
|
import WhiteLabelingContext from '../context/WhiteLabelingContext.js';
|
||||||
@@ -271,6 +272,7 @@ class Viewer extends Component {
|
|||||||
activeViewport={
|
activeViewport={
|
||||||
this.props.viewports[this.props.activeViewportIndex]
|
this.props.viewports[this.props.activeViewportIndex]
|
||||||
}
|
}
|
||||||
|
isDerivedDisplaySetsLoaded={this.props.isDerivedDisplaySetsLoaded}
|
||||||
isLeftSidePanelOpen={this.state.isLeftSidePanelOpen}
|
isLeftSidePanelOpen={this.state.isLeftSidePanelOpen}
|
||||||
isRightSidePanelOpen={this.state.isRightSidePanelOpen}
|
isRightSidePanelOpen={this.state.isRightSidePanelOpen}
|
||||||
selectedLeftSidePanel={
|
selectedLeftSidePanel={
|
||||||
@@ -366,6 +368,62 @@ class Viewer extends Component {
|
|||||||
|
|
||||||
export default withDialog(Viewer);
|
export default withDialog(Viewer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Async function to check if there are any inconsistences in the series
|
||||||
|
* (i.e. reconstructable to a 3D volume). If not reconstructable MPR is disabled.
|
||||||
|
* The actual computations are done in isDisplaySetReconstructable.
|
||||||
|
*
|
||||||
|
* 1) Is series multiframe?
|
||||||
|
* 2) Do the frames have different dimensions/numer of components/orientations?
|
||||||
|
* 3) Has the series any missing frames or irregular spacing?
|
||||||
|
* 4) Is the series 4D?
|
||||||
|
*
|
||||||
|
* @param {*object} displaySet
|
||||||
|
* @returns {[string]} an array of strings containing the warnings
|
||||||
|
*/
|
||||||
|
const _checkForSeriesInconsistencesWarnings = async function (displaySet) {
|
||||||
|
// NOTE: at the moment this function is async even if it does not perfom any heavy calculation.
|
||||||
|
// We may add or move here some of the computations
|
||||||
|
// done when creating the displaySet (see makeDisplaySet and isDisplaySetReconstructable).
|
||||||
|
// the thumbnail footnotes warning react element is already set up to handle a promise.
|
||||||
|
const warningsList = [];
|
||||||
|
if (displaySet.warningIssues && displaySet.warningIssues.length !== 0) {
|
||||||
|
displaySet.warningIssues.forEach(warning => {
|
||||||
|
switch (warning) {
|
||||||
|
case ReconstructionIssues.DATASET_4D:
|
||||||
|
warningsList.push("The dataset is 4D.");
|
||||||
|
break;
|
||||||
|
case ReconstructionIssues.VARYING_IMAGESDIMENSIONS:
|
||||||
|
warningsList.push("The dataset frames have different dimensions (rows, columns).");
|
||||||
|
break;
|
||||||
|
case ReconstructionIssues.VARYING_IMAGESCOMPONENTS:
|
||||||
|
warningsList.push("The dataset frames have different components (Sample per pixel).");
|
||||||
|
break;
|
||||||
|
case ReconstructionIssues.VARYING_IMAGESORIENTATION:
|
||||||
|
warningsList.push("The dataset frames have different orientation.");
|
||||||
|
break;
|
||||||
|
case ReconstructionIssues.IRREGULAR_SPACING:
|
||||||
|
warningsList.push("The dataset frames have different pixel spacing.");
|
||||||
|
break;
|
||||||
|
case ReconstructionIssues.MULTIFFRAMES:
|
||||||
|
warningsList.push("The dataset is a multiframes.");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
warningsList.push('The datasets is not a reconstructable 3D volume. MPR mode is not available.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (displaySet.missingFrames &&
|
||||||
|
(!displaySet.warningIssues ||
|
||||||
|
(displaySet.warningIssues && !displaySet.warningIssues.find(warn => warn === ReconstructionIssues.DATASET_4D)))) {
|
||||||
|
warningsList.push('The datasets is missing frames: ' + displaySet.missingFrames + '.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return warningsList
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* What types are these? Why do we have "mapping" dropped in here instead of in
|
* What types are these? Why do we have "mapping" dropped in here instead of in
|
||||||
* a mapping layer?
|
* a mapping layer?
|
||||||
@@ -405,6 +463,8 @@ const _mapStudiesToThumbnails = function(studies) {
|
|||||||
altImageText = displaySet.Modality ? displaySet.Modality : 'UN';
|
altImageText = displaySet.Modality ? displaySet.Modality : 'UN';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const hasWarnings = _checkForSeriesInconsistencesWarnings(displaySet)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
imageId,
|
imageId,
|
||||||
altImageText,
|
altImageText,
|
||||||
@@ -413,6 +473,7 @@ const _mapStudiesToThumbnails = function(studies) {
|
|||||||
InstanceNumber,
|
InstanceNumber,
|
||||||
numImageFrames,
|
numImageFrames,
|
||||||
SeriesNumber,
|
SeriesNumber,
|
||||||
|
hasWarnings,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ let config = {};
|
|||||||
|
|
||||||
if (window) {
|
if (window) {
|
||||||
config = window.config || {};
|
config = window.config || {};
|
||||||
|
|
||||||
window.version = version;
|
window.version = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6619,10 +6619,10 @@ dateformat@^3.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
|
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
|
||||||
integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==
|
integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==
|
||||||
|
|
||||||
dcmjs@0.17.2:
|
dcmjs@0.18.3:
|
||||||
version "0.17.2"
|
version "0.18.3"
|
||||||
resolved "https://registry.yarnpkg.com/dcmjs/-/dcmjs-0.17.2.tgz#81d6e696119c25afbd26967a6250a32c25f06535"
|
resolved "https://registry.yarnpkg.com/dcmjs/-/dcmjs-0.18.3.tgz#17d5a23d96b63264b8a1a859e4cb000b3e20495b"
|
||||||
integrity sha512-wM9AUWt9vM2S+owI/4UjoBCSV9Mfi/m5rykHH5WTDZVxQZUrL/ehOC/l7d7gkcMaOSD0C0r9X56Nn/562Jt1/Q==
|
integrity sha512-nmG6wEBcIMnadXAZOTcXwacBv+lrh8bqPwIKZwdy7AkdihLEwI6/OnyP+PYjzcdltuPu9wOQcKZionvXuCteag==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/polyfill" "^7.8.3"
|
"@babel/polyfill" "^7.8.3"
|
||||||
"@babel/runtime" "^7.8.4"
|
"@babel/runtime" "^7.8.4"
|
||||||
@@ -15698,10 +15698,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@4.0.4:
|
react-cornerstone-viewport@4.0.5:
|
||||||
version "4.0.4"
|
version "4.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/react-cornerstone-viewport/-/react-cornerstone-viewport-4.0.4.tgz#0e4291d9b0fe55c003e275175b0902ced61b0c80"
|
resolved "https://registry.yarnpkg.com/react-cornerstone-viewport/-/react-cornerstone-viewport-4.0.5.tgz#3de83cdd3643980e0330f3743f631dbbb24d98a7"
|
||||||
integrity sha512-RjCqOtQep04dRoHtsju0USlxN/vGUI2WnEt1aN84iYU7eZ+AXnwJo1nAd0RMX2obcXaGCIqMDtMRkE/zm3oZHw==
|
integrity sha512-uamDtFljWWEHe26kOBJJ1Bu//6hAgEra7BDVykOvtMC/W7kW34Q2fFX3ZwkL6TDdCQ94O6K98IXPS9HbrEJWYg==
|
||||||
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