From 95249928a832a34f652988a452a0dd07e0c2315b Mon Sep 17 00:00:00 2001 From: dannyrb Date: Thu, 4 Jun 2020 11:28:10 -0400 Subject: [PATCH] Replace measurementsPanel w/ a format that reduces nesting --- extensions/default/src/ActionButtons.jsx | 37 ++++ extensions/default/src/MeasurementTable.js | 73 -------- .../default/src/PanelMeasurementTable.js | 55 ++++++ extensions/default/src/getPanelModule.js | 4 +- .../lesion-tracker/.webpack/webpack.dev.js | 8 - .../lesion-tracker/.webpack/webpack.prod.js | 38 ---- extensions/lesion-tracker/CHANGELOG.md | 22 --- extensions/lesion-tracker/LICENSE | 21 --- extensions/lesion-tracker/README.md | 38 ---- extensions/lesion-tracker/package.json | 39 ---- .../components/MeasurementComparisonTable.css | 60 ------ .../components/MeasurementComparisonTable.js | 151 --------------- extensions/lesion-tracker/src/index.js | 52 ----- .../ActionButtons.jsx | 37 ++++ .../PanelMeasurementTableTracking/index.js | 177 +++++++++--------- package.json | 2 - platform/ui/index.js | 2 +- .../MeasurementsPanel/MeasurementsPanel.jsx | 65 ------- .../MeasurementsPanel/MeasurementsPanel.mdx | 101 ---------- .../src/components/MeasurementsPanel/index.js | 2 - .../components/StudySummary/StudySummary.jsx | 26 +++ .../components/StudySummary/StudySummary.mdx | 0 .../ui/src/components/StudySummary/index.js | 3 + platform/ui/src/components/index.js | 8 +- platform/ui/src/views/Viewer/Viewer.mdx | 25 ++- platform/viewer/package.json | 2 - 26 files changed, 276 insertions(+), 772 deletions(-) create mode 100644 extensions/default/src/ActionButtons.jsx delete mode 100644 extensions/default/src/MeasurementTable.js create mode 100644 extensions/default/src/PanelMeasurementTable.js delete mode 100644 extensions/lesion-tracker/.webpack/webpack.dev.js delete mode 100644 extensions/lesion-tracker/.webpack/webpack.prod.js delete mode 100644 extensions/lesion-tracker/CHANGELOG.md delete mode 100644 extensions/lesion-tracker/LICENSE delete mode 100644 extensions/lesion-tracker/README.md delete mode 100644 extensions/lesion-tracker/package.json delete mode 100644 extensions/lesion-tracker/src/components/MeasurementComparisonTable.css delete mode 100644 extensions/lesion-tracker/src/components/MeasurementComparisonTable.js delete mode 100644 extensions/lesion-tracker/src/index.js create mode 100644 extensions/measurement-tracking/src/panels/PanelMeasurementTableTracking/ActionButtons.jsx delete mode 100644 platform/ui/src/components/MeasurementsPanel/MeasurementsPanel.jsx delete mode 100644 platform/ui/src/components/MeasurementsPanel/MeasurementsPanel.mdx delete mode 100644 platform/ui/src/components/MeasurementsPanel/index.js create mode 100644 platform/ui/src/components/StudySummary/StudySummary.jsx create mode 100644 platform/ui/src/components/StudySummary/StudySummary.mdx create mode 100644 platform/ui/src/components/StudySummary/index.js diff --git a/extensions/default/src/ActionButtons.jsx b/extensions/default/src/ActionButtons.jsx new file mode 100644 index 000000000..0e3e8a3b6 --- /dev/null +++ b/extensions/default/src/ActionButtons.jsx @@ -0,0 +1,37 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Button, ButtonGroup, Icon, IconButton } from '@ohif/ui'; + +function ActionButtons() { + return ( + + alert('Export')}> + + + + + + + + ); +} + +export default ActionButtons; diff --git a/extensions/default/src/MeasurementTable.js b/extensions/default/src/MeasurementTable.js deleted file mode 100644 index 7ba1e010e..000000000 --- a/extensions/default/src/MeasurementTable.js +++ /dev/null @@ -1,73 +0,0 @@ -import React from 'react'; -import { - MeasurementsPanel, - Button, - ButtonGroup, - Icon, - IconButton, -} from '@ohif/ui'; - -export default function MeasurementTable({ servicesManager, commandsManager }) { - const { MeasurementService } = servicesManager.services; - - console.log('MeasurementTable rendering!!!!!!!!!!!!!'); - - const actionButtons = ( - - alert('Export')}> - - - - - - - - ); - - const descriptionData = { - date: '07-Sep-2010', - modality: 'CT', - description: 'CHEST/ABD/PELVIS W CONTRAST', - }; - - const activeMeasurementItem = 0; - - const measurementTableData = { - title: 'Measurements', - amount: 10, - data: new Array(10).fill({}).map((el, i) => ({ - id: i + 1, - label: 'Label short description', - displayText: '24.0 x 24.0 mm (S:4, I:22)', - isActive: activeMeasurementItem === i + 1, - })), - onClick: id => setActiveMeasurementItem(s => (s === id ? null : id)), - onEdit: id => alert(`Edit: ${id}`), - }; - - return ( - - ); -} diff --git a/extensions/default/src/PanelMeasurementTable.js b/extensions/default/src/PanelMeasurementTable.js new file mode 100644 index 000000000..6da4696fd --- /dev/null +++ b/extensions/default/src/PanelMeasurementTable.js @@ -0,0 +1,55 @@ +import React from 'react'; +import { StudySummary, MeasurementTable } from '@ohif/ui'; +import ActionButtons from './ActionButtons.jsx'; + +export default function PanelMeasurementTable({ + servicesManager, + commandsManager, +}) { + const { MeasurementService } = servicesManager.services; + + console.log('MeasurementTable rendering!!!!!!!!!!!!!'); + + const descriptionData = { + date: '07-Sep-2010', + modality: 'CT', + description: 'CHEST/ABD/PELVIS W CONTRAST', + }; + + const activeMeasurementItem = 0; + + const measurementTableData = { + title: 'Measurements', + amount: 10, + data: new Array(10).fill({}).map((el, i) => ({ + id: i + 1, + label: 'Label short description', + displayText: '24.0 x 24.0 mm (S:4, I:22)', + isActive: activeMeasurementItem === i + 1, + })), + onClick: id => setActiveMeasurementItem(s => (s === id ? null : id)), + onEdit: id => alert(`Edit: ${id}`), + }; + + return ( + <> +
+ + {}} + onEdit={id => alert(`Edit: ${id}`)} + /> +
+
+ +
+ + ); +} diff --git a/extensions/default/src/getPanelModule.js b/extensions/default/src/getPanelModule.js index 1cffbdb86..54f91a20c 100644 --- a/extensions/default/src/getPanelModule.js +++ b/extensions/default/src/getPanelModule.js @@ -1,7 +1,7 @@ import React from 'react'; import { WrappedPanelStudyBrowser } from './Panels'; -import MeasurementTable from './MeasurementTable.js'; +import PanelMeasurementTable from './PanelMeasurementTable.js'; // TODO: // - No loading UI exists yet @@ -15,7 +15,7 @@ function getPanelModule({ }) { const wrappedMeasurementPanel = () => { return ( - diff --git a/extensions/lesion-tracker/.webpack/webpack.dev.js b/extensions/lesion-tracker/.webpack/webpack.dev.js deleted file mode 100644 index 1ae308448..000000000 --- a/extensions/lesion-tracker/.webpack/webpack.dev.js +++ /dev/null @@ -1,8 +0,0 @@ -const path = require('path'); -const webpackCommon = require('./../../../.webpack/webpack.commonjs.js'); -const SRC_DIR = path.join(__dirname, '../src'); -const DIST_DIR = path.join(__dirname, '../dist'); - -module.exports = (env, argv) => { - return webpackCommon(env, argv, { SRC_DIR, DIST_DIR }); -}; diff --git a/extensions/lesion-tracker/.webpack/webpack.prod.js b/extensions/lesion-tracker/.webpack/webpack.prod.js deleted file mode 100644 index 55f80827c..000000000 --- a/extensions/lesion-tracker/.webpack/webpack.prod.js +++ /dev/null @@ -1,38 +0,0 @@ -const merge = require('webpack-merge'); -const path = require('path'); -const webpackCommon = require('./../../../.webpack/webpack.commonjs.js'); -const pkg = require('./../package.json'); - -const ROOT_DIR = path.join(__dirname, './..'); -const SRC_DIR = path.join(__dirname, '../src'); -const DIST_DIR = path.join(__dirname, '../dist'); - -module.exports = (env, argv) => { - const commonConfig = webpackCommon(env, argv, { SRC_DIR, DIST_DIR }); - - return merge(commonConfig, { - devtool: 'source-map', - stats: { - colors: true, - hash: true, - timings: true, - assets: true, - chunks: false, - chunkModules: false, - modules: false, - children: false, - warnings: true, - }, - optimization: { - minimize: true, - sideEffects: true, - }, - output: { - path: ROOT_DIR, - library: 'OHIFExtLesionTracker', - libraryTarget: 'umd', - libraryExport: 'default', - filename: pkg.main, - }, - }); -}; diff --git a/extensions/lesion-tracker/CHANGELOG.md b/extensions/lesion-tracker/CHANGELOG.md deleted file mode 100644 index 7d23c9be6..000000000 --- a/extensions/lesion-tracker/CHANGELOG.md +++ /dev/null @@ -1,22 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -# [0.2.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-lesion-tracker@0.1.0...@ohif/extension-lesion-tracker@0.2.0) (2020-02-10) - - -### Features - -* Lesion tracker right panel ([#1428](https://github.com/OHIF/Viewers/issues/1428)) ([98a649b](https://github.com/OHIF/Viewers/commit/98a649b455ffc712938fc5035cdef40695e58440)) - - - - - -# 0.1.0 (2020-02-06) - - -### Features - -* lesion-tracker extension ([#1420](https://github.com/OHIF/Viewers/issues/1420)) ([73e4409](https://github.com/OHIF/Viewers/commit/73e440968ce4699d081a9c9f2d21dd68095b3056)) diff --git a/extensions/lesion-tracker/LICENSE b/extensions/lesion-tracker/LICENSE deleted file mode 100644 index 19e20dd35..000000000 --- a/extensions/lesion-tracker/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2018 Open Health Imaging Foundation - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/extensions/lesion-tracker/README.md b/extensions/lesion-tracker/README.md deleted file mode 100644 index 6c9c9bbfe..000000000 --- a/extensions/lesion-tracker/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# @ohif/extension-lesion-tracker - -This project is an OHIF extension that can be used with the Core OHIF Platform, -either at runtime, or as an ES6 dependency, to create a medical image viewing -application similar to that of the [legacy Lesion -Tracker][legacy-lesion-tracker] viewer. - -## About - -... - -## Scope - -... - -### Configuration - -... - -### Extensions - -... - -## Build & Deploy - -... - -## Funding/Support - -... - - - - -[legacy-lesion-tracker]: http://lesiontracker.ohif.org/studylist - diff --git a/extensions/lesion-tracker/package.json b/extensions/lesion-tracker/package.json deleted file mode 100644 index 07d2c0877..000000000 --- a/extensions/lesion-tracker/package.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "name": "@ohif/extension-lesion-tracker", - "version": "0.2.0", - "description": "OHIF extension for Lesion Tracker", - "author": "OHIF", - "license": "MIT", - "repository": "OHIF/Viewers", - "main": "dist/index.umd.js", - "module": "src/index.js", - "publishConfig": { - "access": "public" - }, - "engines": { - "node": ">=10", - "npm": ">=6", - "yarn": ">=1.16.0" - }, - "files": [ - "dist", - "README.md" - ], - "scripts": { - "dev": "cross-env NODE_ENV=development webpack --config .webpack/webpack.dev.js --watch --debug --output-pathinfo", - "dev:lesion-tracker": "yarn run dev", - "build": "cross-env NODE_ENV=production webpack --config .webpack/webpack.prod.js", - "build:package": "yarn run build", - "start": "yarn run dev" - }, - "peerDependencies": { - "@ohif/core": "^0.50.0", - "prop-types": "^15.6.2", - "react": "^16.11.0", - "react-dom": "^16.11.0" - }, - "dependencies": { - "@babel/runtime": "7.7.6", - "classnames": "^2.2.6" - } -} diff --git a/extensions/lesion-tracker/src/components/MeasurementComparisonTable.css b/extensions/lesion-tracker/src/components/MeasurementComparisonTable.css deleted file mode 100644 index 2148a2ee2..000000000 --- a/extensions/lesion-tracker/src/components/MeasurementComparisonTable.css +++ /dev/null @@ -1,60 +0,0 @@ -.MeasurementComparisonTable { - height: 100%; - display: flex; - flex-direction: column; -} - -.MeasurementComparisonTable .displayTexts { - display: flex; -} - -.MeasurementComparisonTable .displayTexts .measurementDisplayText { - flex: 1; -} - -.MeasurementComparisonTable .measurementTableHeader { - display: flex; - position: relative; - padding-left: 38px; -} - -.MeasurementComparisonTable .measurementTableHeader .warning-status { - left: 0; - top: 3px; - cursor: pointer; - width: 40px; - height: 100%; - display: flex; - align-items: center; -} - -.MeasurementComparisonTable .measurementTableHeader .warning-status .warning-border { - padding: 2px 3px; - width: 30px; - height: 30px; -} - -.MeasurementComparisonTable .measurementTableHeader .warning-status svg { - width: 20px; - height: 18px; -} - -.MeasurementComparisonTable .measurementTableHeader .measurementTableHeaderItem { - position: relative; - flex: 1; -} - -.MeasurementComparisonTable .generate-report { - background-color: #151a1f; - margin-top: 2px; - padding: 10px 0; - display: flex; - justify-content: center; - align-items: center; -} - -.MeasurementComparisonTable .generate-report button { - font-size: 12px; - color: black; - background-color: var(--active-color); -} diff --git a/extensions/lesion-tracker/src/components/MeasurementComparisonTable.js b/extensions/lesion-tracker/src/components/MeasurementComparisonTable.js deleted file mode 100644 index 2118895da..000000000 --- a/extensions/lesion-tracker/src/components/MeasurementComparisonTable.js +++ /dev/null @@ -1,151 +0,0 @@ -import React from 'react'; - -import { MeasurementTable } from '@ohif/ui'; - -import './MeasurementComparisonTable.css'; - -const overallWarnings = { - warningList: [ - 'All measurements should have a location', - 'Nodal lesions must be >= 15mm short axis AND >= double the acquisition slice thickness by CT and MR', - ], -}; - -const measurements = [ - { - measurementId: '125', - measurementNumber: '125', - itemNumber: 1, - label: '(No description)', - data: [{ displayText: '12.5 x 4.6' }], - }, - { - measurementId: '124', - measurementNumber: '124', - itemNumber: 2, - label: '(No description)', - data: [{ displayText: '32.5 x 1.6' }], - }, - { - measurementId: '123', - measurementNumber: '123', - itemNumber: 3, - hasWarnings: true, - warningList: [ - 'All measurements should have a location', - 'Nodal lesions must be >= 15mm short axis AND >= double the acquisition slice thickness by CT and MR', - ], - label: '(No description)', - data: [{ displayText: '5.5 x 9.2' }], - }, -]; - -const additionalFindings = [ - { - measurementId: '122', - measurementNumber: '122', - itemNumber: 1, - hasWarnings: true, - warningList: [ - 'All measurements should have a location', - 'Nodal lesions must be >= 15mm short axis AND >= double the acquisition slice thickness by CT and MR', - ], - label: '(No description)', - data: [{ displayText: '23.5 x 9.2' }], - }, - { - measurementId: '121', - measurementNumber: '121', - itemNumber: 2, - hasWarnings: true, - warningList: [ - 'All measurements should have a location', - 'Nodal lesions must be >= 15mm short axis AND >= double the acquisition slice thickness by CT and MR', - ], - label: '(No description)', - data: [{ displayText: '11.2 x 9.2' }], - }, - { - measurementId: '120', - measurementNumber: '120', - itemNumber: 3, - label: '(No description)', - data: [{ displayText: '2.9 x 9.2' }], - }, -]; - -const currentCollections = [ - { - selectorAction: () => {}, - maxMeasurements: 3, - groupName: 'Measurements', - measurements: measurements, - }, - { - selectorAction: () => {}, - groupName: 'Additional Findings', - measurements: additionalFindings, - }, -]; - -const comparisonColletions = [ - { - selectorAction: () => {}, - maxMeasurements: 3, - groupName: 'Measurements', - measurements: measurements, - }, - { - selectorAction: () => {}, - groupName: 'Additional Findings', - measurements: additionalFindings, - }, -]; - -const comparisonCollections = currentCollections.map((group, index) => { - return { - ...group, - measurements: group.measurements.map((measurement, measurementIndex) => { - const comparisonCollection = comparisonColletions[index].measurements; - if (measurementIndex < comparisonCollection.length) { - return { - ...measurement, - data: [ - ...measurement.data, - ...comparisonCollection[measurementIndex].data, - ], - }; - } - }), - }; -}); - -const comparisonTimepoints = [ - { - key: 'Current', - date: '10-Apr-18', - }, - { - key: 'Comparison', - date: '15-Jun-18', - }, -]; - -const MeasurementComparisonTable = () => { - return ( -
- {}} - onEditDescriptionClick={() => {}} - /> -
- -
-
- ); -}; - -export default MeasurementComparisonTable; diff --git a/extensions/lesion-tracker/src/index.js b/extensions/lesion-tracker/src/index.js deleted file mode 100644 index d664070aa..000000000 --- a/extensions/lesion-tracker/src/index.js +++ /dev/null @@ -1,52 +0,0 @@ -import MeasurementComparisonTable from './components/MeasurementComparisonTable'; - -export default { - /** - * Only required property. Should be a unique value across all extensions. - */ - id: 'lesion-tracker', - - /** - * @param {object} params - * @param {ServicesManager} params.servicesManager - * @param {CommandsManager} params.commandsManager - */ - getPanelModule({ servicesManager, commandsManager }) { - return { - menuOptions: [ - { - icon: 'th-list', - label: 'Measurements', - target: 'lesion-tracker-panel', - }, - ], - components: [ - { - id: 'lesion-tracker-panel', - component: MeasurementComparisonTable, - }, - ], - defaultContext: ['VIEWER'], - }; - }, - - /** - * @param {object} params - * @param {ServicesManager} params.servicesManager - * @param {CommandsManager} params.commandsManager - * @returns Object - */ - getToolbarModule() { - return null; - }, - - /** - * @param {object} params - * @param {ServicesManager} params.servicesManager - * @param {CommandsManager} params.commandsManager - * @returns Object - */ - getCommandsModule() { - return null; - }, -}; diff --git a/extensions/measurement-tracking/src/panels/PanelMeasurementTableTracking/ActionButtons.jsx b/extensions/measurement-tracking/src/panels/PanelMeasurementTableTracking/ActionButtons.jsx new file mode 100644 index 000000000..0e3e8a3b6 --- /dev/null +++ b/extensions/measurement-tracking/src/panels/PanelMeasurementTableTracking/ActionButtons.jsx @@ -0,0 +1,37 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Button, ButtonGroup, Icon, IconButton } from '@ohif/ui'; + +function ActionButtons() { + return ( + + alert('Export')}> + + + + + + + + ); +} + +export default ActionButtons; diff --git a/extensions/measurement-tracking/src/panels/PanelMeasurementTableTracking/index.js b/extensions/measurement-tracking/src/panels/PanelMeasurementTableTracking/index.js index dfc5dc1bc..868d38250 100644 --- a/extensions/measurement-tracking/src/panels/PanelMeasurementTableTracking/index.js +++ b/extensions/measurement-tracking/src/panels/PanelMeasurementTableTracking/index.js @@ -1,12 +1,8 @@ import React, { useEffect, useState } from 'react'; import PropTypes from 'prop-types'; -import { - MeasurementsPanel, - Button, - ButtonGroup, - Icon, - IconButton, -} from '@ohif/ui'; +import { StudySummary, MeasurementTable } from '@ohif/ui'; +import { DicomMetadataStore } from '@ohif/core'; +import ActionButtons from './ActionButtons'; import { useTrackedMeasurements } from '../../getContextModule'; function PanelMeasurementTableTracking({ servicesManager, commandsManager }) { @@ -15,6 +11,11 @@ function PanelMeasurementTableTracking({ servicesManager, commandsManager }) { trackedMeasurements, sendTrackedMeasurementsEvent, ] = useTrackedMeasurements(); + const [displayStudySummary, setDisplayStudySummary] = useState({ + date: '', // '07-Sep-2010', + modality: '', // 'CT', + description: '', // 'CHEST/ABD/PELVIS W CONTRAST', + }); const [displayMeasurements, setDisplayMeasurements] = useState([]); // TODO: initial measurements + initial tracked? @@ -24,8 +25,8 @@ function PanelMeasurementTableTracking({ servicesManager, commandsManager }) { // Initial? useEffect(() => { const measurements = MeasurementService.getMeasurements(); - const mappedMeasurements = measurements.map(m => - _mapMeasurementToDisplay(m) + const mappedMeasurements = measurements.map((m, index) => + _mapMeasurementToDisplay(m, index) ); setDisplayMeasurements(mappedMeasurements); // eslint-ignore-next-line @@ -51,93 +52,101 @@ function PanelMeasurementTableTracking({ servicesManager, commandsManager }) { // return unsubscribe; }, [MeasurementService, sendTrackedMeasurementsEvent]); - console.log('MeasurementTable rendering!!!!!!!!!!!!!'); - - const actionButtons = ( - - alert('Export')}> - - - - - - - - ); - - const descriptionData = { - date: '07-Sep-2010', - modality: 'CT', - description: 'CHEST/ABD/PELVIS W CONTRAST', - }; - const activeMeasurementItem = 0; - const measurementTableData = { - title: 'Measurements', - amount: displayMeasurements.length, - data: displayMeasurements, - // new Array(10).fill({}).map((el, i) => ({ - // id: i + 1, - // label: 'Label short description', - // displayText: '24.0 x 24.0 mm (S:4, I:22)', - // isActive: activeMeasurementItem === i + 1, - // })), - // onClick: id => setActiveMeasurementItem(s => (s === id ? null : id)), - onClick: () => {}, - onEdit: id => alert(`Edit: ${id}`), - }; - return ( - + <> +
+ + {}} + onEdit={id => alert(`Edit: ${id}`)} + /> +
+
+ +
+ ); } PanelMeasurementTableTracking.propTypes = {}; -// 'id', -// 'SOPInstanceUID', -// 'FrameOfReferenceUID', -// 'referenceStudyUID', -// 'referenceSeriesUID', -// 'label', -// 'description', -// 'type', -// 'unit', -// 'area', // TODO: Add concept names instead (descriptor) -// 'points', -// 'source', -function _mapMeasurementToDisplay(measurement) { - const { id, label, description: displayText } = measurement; - return { +// TODO: This could be a MeasurementService mapper +function _mapMeasurementToDisplay(measurement, index) { + const { id, - label, // 'Label short description', - displayText, // '24.0 x 24.0 mm (S:4, I:22)', + label, + description, + // Reference IDs + referenceStudyUID, + referenceSeriesUID, + SOPInstanceUID, + } = measurement; + const instance = DicomMetadataStore.getInstance( + referenceStudyUID, + referenceSeriesUID, + SOPInstanceUID + ); + const { PixelSpacing, SeriesNumber, InstanceNumber } = instance; + + console.log('mapping....', measurement); + console.log(instance); + + return { + id: index + 1, + label: '(empty)', // 'Label short description', + displayText: _getDisplayText( + measurement.points, + PixelSpacing, + SeriesNumber, + InstanceNumber + ), // TODO: handle one layer down isActive: false, // activeMeasurementItem === i + 1, }; } +/** + * + * @param {*} points + * @param {*} pixelSpacing + */ +function _getDisplayText(points, pixelSpacing, seriesNumber, instanceNumber) { + // TODO: determination of shape influences text + // Length: 'xx.x unit (S:x, I:x)' + // Rectangle: 'xx.x x xx.x unit (S:x, I:x)', + // Ellipse? + // Bidirectional? + // Freehand? + + const hasPixelSpacing = + pixelSpacing !== undefined && + Array.isArray(pixelSpacing) && + pixelSpacing.length === 2; + const [rowPixelSpacing, colPixelSpacing] = hasPixelSpacing + ? pixelSpacing + : [1, 1]; + const unit = hasPixelSpacing ? 'mm' : 'px'; + + const { x: x1, y: y1 } = points[0]; + const { x: x2, y: y2 } = points[1]; + const dx = x2 - x1 * colPixelSpacing; + const dy = y2 - y1 * rowPixelSpacing; + const length = _round(Math.sqrt(dx * dx + dy * dy), 1); + + return `${length} ${unit} (S:${seriesNumber}, I:${instanceNumber})`; +} + +function _round(value, decimals) { + return Number(Math.round(value + 'e' + decimals) + 'e-' + decimals); +} + export default PanelMeasurementTableTracking; diff --git a/package.json b/package.json index 23b7e5097..6f4176432 100644 --- a/package.json +++ b/package.json @@ -16,14 +16,12 @@ "scripts": { "cm": "npx git-cz", "build": "lerna run build:viewer --stream", - "build:lt": "lerna run build:viewer:lesion-tracker --stream", "build:ci": "lerna run build:viewer:ci --stream", "build:ui:deploy-preview": "lerna run build:ui:deploy-preview --stream", "build:demo": "lerna run build:viewer:demo --stream", "build:package": "lerna run build:viewer:package --stream", "build:package-all": "lerna run build:package --parallel --stream", "dev": "lerna run dev:viewer --stream", - "dev:lt": "lerna run dev:viewer:lesion-tracker --stream", "dev:project": ".scripts/dev.sh", "dev:orthanc": "lerna run dev:orthanc --stream", "orthanc:up": "docker-compose -f .docker/Nginx-Orthanc/docker-compose.yml up", diff --git a/platform/ui/index.js b/platform/ui/index.js index 4dd7ddb85..94ff8071c 100644 --- a/platform/ui/index.js +++ b/platform/ui/index.js @@ -41,7 +41,6 @@ export { InputMultiSelect, InputText, Label, - MeasurementsPanel, MeasurementTable, Modal, NavBar, @@ -56,6 +55,7 @@ export { StudyListPagination, StudyListTable, StudyListTableRow, + StudySummary, Svg, Table, TableBody, diff --git a/platform/ui/src/components/MeasurementsPanel/MeasurementsPanel.jsx b/platform/ui/src/components/MeasurementsPanel/MeasurementsPanel.jsx deleted file mode 100644 index f8b48122e..000000000 --- a/platform/ui/src/components/MeasurementsPanel/MeasurementsPanel.jsx +++ /dev/null @@ -1,65 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { MeasurementTable } from '@ohif/ui'; - -const MeasurementsPanel = ({ - descriptionData, - measurementTableData, - actionButtons, -}) => { - const { date, modality, description } = descriptionData; - return ( - <> -
-
-
- {date} - - {modality} - -
-
- {description} -
-
- -
-
{actionButtons}
- - ); -}; - -MeasurementsPanel.defaultProps = { - actionButtons: null, -}; - -MeasurementsPanel.propTypes = { - descriptionData: PropTypes.shape({ - date: PropTypes.string, - modality: PropTypes.string, - description: PropTypes.string, - }).isRequired, - measurementTableData: PropTypes.shape({ - title: PropTypes.string, - amount: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - data: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - label: PropTypes.string, - displayText: PropTypes.string, - isActive: PropTypes.bool, - }) - ), - onClick: PropTypes.func, - onEdit: PropTypes.func, - }).isRequired, - actionButtons: PropTypes.node, -}; - -export default MeasurementsPanel; diff --git a/platform/ui/src/components/MeasurementsPanel/MeasurementsPanel.mdx b/platform/ui/src/components/MeasurementsPanel/MeasurementsPanel.mdx deleted file mode 100644 index 0089064cc..000000000 --- a/platform/ui/src/components/MeasurementsPanel/MeasurementsPanel.mdx +++ /dev/null @@ -1,101 +0,0 @@ ---- -name: Measurements Panel -menu: Data Display -route: components/measurementsPanel ---- - -import { useState } from 'react'; -import { Playground, Props } from 'docz'; -import { - SidePanel, - MeasurementsPanel, - ButtonGroup, - Button, - IconButton, - Icon, -} from '@ohif/ui'; - -# Measurements Panel - -## Import - -```javascript -import { MeasurementsPanel } from '@ohif/ui'; -``` - -## Basic usage - - - {() => { - const [activeMeasurementItem, setActiveMeasurementItem] = useState(null); - const descriptionData = { - date: '07-Sep-2010', - modality: 'CT', - description: 'CHEST/ABD/PELVIS W CONTRAST', - }; - const measurementTableData = { - title: 'Measurements', - amount: 10, - data: new Array(10).fill({}).map((el, i) => ({ - id: i + 1, - label: 'Label short description', - displayText: '24.0 x 24.0 mm (S:4, I:22)', - isActive: activeMeasurementItem === i + 1, - })), - onClick: (id) => setActiveMeasurementItem((s) => (s === id ? null : id)), - onEdit: (id) => alert(`Edit: ${id}`), - }; - return ( -
-
- CONTENT -
- - - alert('Export')}> - - - - - - - - } - /> - -
- ); - }} -
- -## Properties - - diff --git a/platform/ui/src/components/MeasurementsPanel/index.js b/platform/ui/src/components/MeasurementsPanel/index.js deleted file mode 100644 index 530242b4f..000000000 --- a/platform/ui/src/components/MeasurementsPanel/index.js +++ /dev/null @@ -1,2 +0,0 @@ -import MeasurementsPanel from './MeasurementsPanel'; -export default MeasurementsPanel; diff --git a/platform/ui/src/components/StudySummary/StudySummary.jsx b/platform/ui/src/components/StudySummary/StudySummary.jsx new file mode 100644 index 000000000..9726ac25c --- /dev/null +++ b/platform/ui/src/components/StudySummary/StudySummary.jsx @@ -0,0 +1,26 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +const StudySummary = ({ date, modality, description }) => { + return ( +
+
+ {date} + + {modality} + +
+
+ {description} +
+
+ ); +}; + +StudySummary.propTypes = { + date: PropTypes.string.isRequired, + modality: PropTypes.string.isRequired, + description: PropTypes.string.isRequired, +}; + +export default StudySummary; diff --git a/platform/ui/src/components/StudySummary/StudySummary.mdx b/platform/ui/src/components/StudySummary/StudySummary.mdx new file mode 100644 index 000000000..e69de29bb diff --git a/platform/ui/src/components/StudySummary/index.js b/platform/ui/src/components/StudySummary/index.js new file mode 100644 index 000000000..e9d71324f --- /dev/null +++ b/platform/ui/src/components/StudySummary/index.js @@ -0,0 +1,3 @@ +import StudySummary from './StudySummary.jsx'; + +export default StudySummary; diff --git a/platform/ui/src/components/index.js b/platform/ui/src/components/index.js index cc224c2bd..39c42d01f 100644 --- a/platform/ui/src/components/index.js +++ b/platform/ui/src/components/index.js @@ -12,7 +12,6 @@ import InputLabelWrapper from './InputLabelWrapper'; import InputMultiSelect from './InputMultiSelect'; import InputText from './InputText'; import Label from './Label'; -import MeasurementsPanel from './MeasurementsPanel'; import MeasurementTable from './MeasurementTable'; import Modal from './Modal'; import NavBar from './NavBar'; @@ -21,12 +20,13 @@ import Select from './Select'; import SegmentationTable from './SegmentationTable'; import SidePanel from './SidePanel'; import StudyBrowser from './StudyBrowser'; +import StudyItem from './StudyItem'; import StudyListExpandedRow from './StudyListExpandedRow'; +import StudyListFilter from './StudyListFilter'; import StudyListPagination from './StudyListPagination'; import { StudyListTable, StudyListTableRow } from './StudyListTable'; +import StudySummary from './StudySummary'; import Svg from './Svg'; -import StudyItem from './StudyItem'; -import StudyListFilter from './StudyListFilter'; import Table from './Table'; import TableBody from './TableBody'; import TableCell from './TableCell'; @@ -61,7 +61,6 @@ export { InputMultiSelect, InputText, Label, - MeasurementsPanel, MeasurementTable, Modal, NavBar, @@ -76,6 +75,7 @@ export { StudyListPagination, StudyListTable, StudyListTableRow, + StudySummary, Svg, Table, TableBody, diff --git a/platform/ui/src/views/Viewer/Viewer.mdx b/platform/ui/src/views/Viewer/Viewer.mdx index 987089eae..3fe5ea9a1 100644 --- a/platform/ui/src/views/Viewer/Viewer.mdx +++ b/platform/ui/src/views/Viewer/Viewer.mdx @@ -10,7 +10,6 @@ import { NavBar, SidePanel, Svg, - MeasurementsPanel, SegmentationTable, ButtonGroup, Button, @@ -125,10 +124,22 @@ import { tabs } from './studyBrowserMockData'; label: 'Measurements', name: 'measurements', content: ( - +
+ + {}} + onEdit={id => alert(`Edit: ${id}`)} + /> +
+
alert('Export')}>
+ ) }} /> diff --git a/platform/viewer/package.json b/platform/viewer/package.json index 4c22092c5..bfe7ead46 100644 --- a/platform/viewer/package.json +++ b/platform/viewer/package.json @@ -19,14 +19,12 @@ "scripts": { "build:package": "cross-env NODE_ENV=production node --max_old_space_size=4096 ./../../node_modules/webpack/bin/webpack.js --config .webpack/webpack.commonjs.js --progress", "build:viewer": "cross-env NODE_ENV=production node --max_old_space_size=4096 ./../../node_modules/webpack/bin/webpack.js --config .webpack/webpack.pwa.js --progress", - "build:viewer:lesion-tracker": "cross-env ENTRY_TARGET=index-lesion-tracker.js NODE_ENV=production node --max_old_space_size=4096 ./../../node_modules/webpack/bin/webpack.js --config .webpack/webpack.pwa.js --progress", "build:viewer:ci": "cross-env NODE_ENV=production PUBLIC_URL=/pwa/ APP_CONFIG=config/netlify.js QUICK_BUILD=true node --max_old_space_size=4096 ./../../node_modules/webpack/bin/webpack.js --config .webpack/webpack.pwa.js", "build:viewer:demo": "cross-env NODE_ENV=production APP_CONFIG=config/demo.js HTML_TEMPLATE=rollbar.html QUICK_BUILD=true node --max_old_space_size=4096 ./../../node_modules/webpack/bin/webpack.js --progress --config .webpack/webpack.pwa.js", "build:viewer:package": "yarn run build:package", "dev": "cross-env NODE_ENV=development webpack-dev-server --config .webpack/webpack.pwa.js --watch", "dev:orthanc": "cross-env NODE_ENV=development PROXY_TARGET=/dicom-web PROXY_DOMAIN=http://localhost:8042 APP_CONFIG=config/docker_nginx-orthanc.js webpack-dev-server --config .webpack/webpack.pwa.js --watch", "dev:viewer": "yarn run dev", - "dev:viewer:lesion-tracker": "cross-env ENTRY_TARGET=index-lesion-tracker.js NODE_ENV=development webpack-dev-server --config .webpack/webpack.pwa.js --watch", "start": "yarn run dev", "test:e2e": "cypress open", "test:e2e:ci": "percy exec -- cypress run --config video=false --record --browser chrome --spec 'cypress/integration/visual-regression/**/*'",