refactor(GoogleCloud): Clean up some of the Healthcare API Adapter components (#641)
This commit is contained in:
parent
4a09f33446
commit
091cab49e0
@ -1,5 +1,5 @@
|
||||
import { connect } from 'react-redux';
|
||||
import DicomFileUploader from './DicomFileUploader.js';
|
||||
import DicomFileUploaderModal from './DicomFileUploaderModal.js';
|
||||
|
||||
const isActive = a => a.active === true;
|
||||
|
||||
@ -17,6 +17,6 @@ const mapStateToProps = state => {
|
||||
const ConnectedDicomFileUploader = connect(
|
||||
mapStateToProps,
|
||||
null
|
||||
)(DicomFileUploader);
|
||||
)(DicomFileUploaderModal);
|
||||
|
||||
export default ConnectedDicomFileUploader;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { connect } from 'react-redux';
|
||||
import DicomStorePickerWindow from './DicomStorePickerWindow.js';
|
||||
import DicomStorePickerModal from './DicomStorePickerModal.js';
|
||||
|
||||
const isActive = a => a.active === true;
|
||||
|
||||
@ -29,6 +29,6 @@ const mapDispatchToProps = dispatch => {
|
||||
const ConnectedDicomStorePicker = connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(DicomStorePickerWindow);
|
||||
)(DicomStorePickerModal);
|
||||
|
||||
export default ConnectedDicomStorePicker;
|
||||
|
||||
@ -5,14 +5,11 @@ import DatasetsList from './DatasetsList';
|
||||
import './googleCloud.css';
|
||||
|
||||
export default class DatasetPicker extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
error: null,
|
||||
loading: false,
|
||||
datasets: [],
|
||||
};
|
||||
}
|
||||
state = {
|
||||
error: null,
|
||||
loading: true,
|
||||
datasets: [],
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
project: PropTypes.object,
|
||||
@ -20,7 +17,6 @@ export default class DatasetPicker extends Component {
|
||||
onSelect: PropTypes.func,
|
||||
oidcKey: PropTypes.string,
|
||||
};
|
||||
static defaultProps = {};
|
||||
|
||||
async componentDidMount() {
|
||||
api.setOidcStorageKey(this.props.oidcKey);
|
||||
@ -29,12 +25,19 @@ export default class DatasetPicker extends Component {
|
||||
this.props.project.projectId,
|
||||
this.props.location.locationId
|
||||
);
|
||||
this.loading = false;
|
||||
|
||||
if (response.isError) {
|
||||
this.error = response.message;
|
||||
this.setState({
|
||||
error: response.message,
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
this.setState({ datasets: response.data.datasets || [] });
|
||||
|
||||
this.setState({
|
||||
datasets: response.data.datasets || [],
|
||||
loading: false,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -46,7 +49,7 @@ export default class DatasetPicker extends Component {
|
||||
loading={loading}
|
||||
error={error}
|
||||
onSelect={onSelect}
|
||||
></DatasetsList>
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import DicomStorePicker from './DicomStorePicker';
|
||||
import DatasetPicker from './DatasetPicker';
|
||||
import ProjectPicker from './ProjectPicker';
|
||||
@ -7,16 +8,13 @@ import LocationPicker from './LocationPicker';
|
||||
import GoogleCloudApi from './api/GoogleCloudApi';
|
||||
import './googleCloud.css';
|
||||
|
||||
export default class DatasetSelector extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
project: null,
|
||||
location: null,
|
||||
dataset: null,
|
||||
unloading: false,
|
||||
};
|
||||
}
|
||||
class DatasetSelector extends Component {
|
||||
state = {
|
||||
project: null,
|
||||
location: null,
|
||||
dataset: null,
|
||||
unloading: false,
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
id: PropTypes.string,
|
||||
@ -25,23 +23,22 @@ export default class DatasetSelector extends Component {
|
||||
canClose: PropTypes.string,
|
||||
setServers: PropTypes.func.isRequired,
|
||||
};
|
||||
static defaultProps = {};
|
||||
|
||||
onProjectSelect = project => {
|
||||
this.setState({
|
||||
project: project,
|
||||
project,
|
||||
});
|
||||
};
|
||||
|
||||
onLocationSelect = location => {
|
||||
this.setState({
|
||||
location: location,
|
||||
location,
|
||||
});
|
||||
};
|
||||
|
||||
onDatasetSelect = dataset => {
|
||||
this.setState({
|
||||
dataset: dataset,
|
||||
dataset,
|
||||
});
|
||||
};
|
||||
|
||||
@ -92,65 +89,68 @@ export default class DatasetSelector extends Component {
|
||||
onDatasetSelect,
|
||||
onDicomStoreSelect,
|
||||
} = this;
|
||||
|
||||
let projectBreadcrumbs = (
|
||||
<div className="gcp-picker--path">
|
||||
<span>{this.props.t('Select a Project')}</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
if (project) {
|
||||
projectBreadcrumbs = (
|
||||
<div className="gcp-picker--path">
|
||||
<span onClick={onProjectClick}>{project.name}</span>
|
||||
{project && location && (
|
||||
<span onClick={onLocationClick}>
|
||||
{' '}
|
||||
-> {location.name.split('/')[3]}
|
||||
</span>
|
||||
)}
|
||||
{project && location && dataset && (
|
||||
<span onClick={onDatasetClick}>
|
||||
{' '}
|
||||
-> {dataset.name.split('/')[5]}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<span className="gcp-picker--title">Google Cloud Healthcare API</span>
|
||||
{project && (
|
||||
<div className="gcp-picker--path">
|
||||
<span onClick={onProjectClick}>{project.name}</span>
|
||||
{project && location && (
|
||||
<>
|
||||
<span onClick={onLocationClick}>
|
||||
{' '}
|
||||
-> {location.name.split('/')[3]}
|
||||
</span>
|
||||
{project && location && dataset && (
|
||||
<span onClick={onDatasetClick}>
|
||||
{' '}
|
||||
-> {dataset.name.split('/')[5]}
|
||||
</span>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{projectBreadcrumbs}
|
||||
{!project && (
|
||||
<ProjectPicker
|
||||
oidcKey={this.props.oidcKey}
|
||||
onSelect={onProjectSelect}
|
||||
></ProjectPicker>
|
||||
/>
|
||||
)}
|
||||
|
||||
{project && !location && (
|
||||
<>
|
||||
<LocationPicker
|
||||
oidcKey={this.props.oidcKey}
|
||||
project={project}
|
||||
onSelect={onLocationSelect}
|
||||
></LocationPicker>
|
||||
</>
|
||||
<LocationPicker
|
||||
oidcKey={this.props.oidcKey}
|
||||
project={project}
|
||||
onSelect={onLocationSelect}
|
||||
/>
|
||||
)}
|
||||
{project && location && !dataset && (
|
||||
<>
|
||||
<DatasetPicker
|
||||
oidcKey={this.props.oidcKey}
|
||||
project={project}
|
||||
location={location}
|
||||
onSelect={onDatasetSelect}
|
||||
></DatasetPicker>
|
||||
</>
|
||||
<DatasetPicker
|
||||
oidcKey={this.props.oidcKey}
|
||||
project={project}
|
||||
location={location}
|
||||
onSelect={onDatasetSelect}
|
||||
/>
|
||||
)}
|
||||
{project && location && dataset && (
|
||||
<>
|
||||
<DicomStorePicker
|
||||
oidcKey={this.props.oidcKey}
|
||||
dataset={dataset}
|
||||
onSelect={onDicomStoreSelect}
|
||||
></DicomStorePicker>
|
||||
</>
|
||||
<DicomStorePicker
|
||||
oidcKey={this.props.oidcKey}
|
||||
dataset={dataset}
|
||||
onSelect={onDicomStoreSelect}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withTranslation('Common')(DatasetSelector);
|
||||
|
||||
@ -1,14 +1,13 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import './googleCloud.css';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import { Icon } from 'react-viewerbase';
|
||||
|
||||
export default class DatasetsList extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
search: '',
|
||||
};
|
||||
}
|
||||
class DatasetsList extends Component {
|
||||
state = {
|
||||
search: '',
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
datasets: PropTypes.array,
|
||||
@ -16,16 +15,19 @@ export default class DatasetsList extends Component {
|
||||
error: PropTypes.string,
|
||||
onSelect: PropTypes.func,
|
||||
};
|
||||
static defaultProps = {};
|
||||
|
||||
renderTableRow(dataset) {
|
||||
static defaultProps = {
|
||||
loading: true,
|
||||
};
|
||||
|
||||
renderTableRow = dataset => {
|
||||
return (
|
||||
<tr
|
||||
key={dataset.name}
|
||||
className={
|
||||
this.state.highlightedItem === dataset.name
|
||||
? 'studylistStudy noselect active'
|
||||
: 'studylistStudy noselect'
|
||||
? 'noselect active'
|
||||
: 'noselect'
|
||||
}
|
||||
onMouseEnter={() => {
|
||||
this.onHighlightItem(dataset.name);
|
||||
@ -37,21 +39,42 @@ export default class DatasetsList extends Component {
|
||||
<td>{dataset.name.split('/')[5]}</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
onHighlightItem(dataset) {
|
||||
this.setState({ highlightedItem: dataset });
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.props.error) {
|
||||
return <p>{this.props.error}</p>;
|
||||
}
|
||||
|
||||
const loadingIcon = (
|
||||
<Icon name="circle-notch" className="loading-icon-spin loading-icon" />
|
||||
);
|
||||
|
||||
if (this.props.loading) {
|
||||
return loadingIcon;
|
||||
}
|
||||
|
||||
const body = (
|
||||
<tbody id="DatasetList">
|
||||
{this.props.datasets.map(this.renderTableRow)}
|
||||
</tbody>
|
||||
);
|
||||
|
||||
return (
|
||||
<table id="tblDatasetList" className="studyListToolbar table noselect">
|
||||
<tbody id="DatasetList">
|
||||
{this.props.datasets.map(dataset => {
|
||||
return this.renderTableRow(dataset);
|
||||
})}
|
||||
</tbody>
|
||||
<table id="tblDatasetList" className="gcp-table table noselect">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{this.props.t('Dataset')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{this.props.datasets && body}
|
||||
</table>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withTranslation('Common')(DatasetsList);
|
||||
|
||||
@ -1,38 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import DicomUploader from './DicomUploader';
|
||||
|
||||
class DicomFileUploader extends Component {
|
||||
static propTypes = {
|
||||
url: PropTypes.string,
|
||||
oidcStorageKey: PropTypes.string.isRequired,
|
||||
onClose: PropTypes.func,
|
||||
};
|
||||
state = {
|
||||
uploaded: false,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.element = React.createRef();
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.props.url != null) {
|
||||
return (
|
||||
<div className="gcp-window">
|
||||
<DicomUploader
|
||||
url={this.props.url}
|
||||
oidcKey={this.props.oidcStorageKey}
|
||||
></DicomUploader>
|
||||
<button className="btn btn-primary" onClick={this.props.onClose}>
|
||||
close
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return <></>;
|
||||
}
|
||||
}
|
||||
|
||||
export default DicomFileUploader;
|
||||
49
src/googleCloud/DicomFileUploaderModal.js
Normal file
49
src/googleCloud/DicomFileUploaderModal.js
Normal file
@ -0,0 +1,49 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Modal from 'react-bootstrap-modal';
|
||||
import DicomUploader from './DicomUploader';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
|
||||
class DicomFileUploaderModal extends Component {
|
||||
static propTypes = {
|
||||
url: PropTypes.string,
|
||||
oidcStorageKey: PropTypes.string.isRequired,
|
||||
onClose: PropTypes.func,
|
||||
};
|
||||
|
||||
state = {
|
||||
uploaded: false,
|
||||
};
|
||||
|
||||
render() {
|
||||
if (!this.props.url) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
show={this.props.isOpen}
|
||||
onHide={this.props.onClose}
|
||||
aria-labelledby="ModalHeader"
|
||||
className="modal fade themed in"
|
||||
backdrop={false}
|
||||
size={'md'}
|
||||
keyboard={true}
|
||||
>
|
||||
<Modal.Header closeButton>
|
||||
<Modal.Title>
|
||||
{this.props.t('Google Cloud Healthcare API - DICOM Upload')}
|
||||
</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
<DicomUploader
|
||||
url={this.props.url}
|
||||
oidcKey={this.props.oidcStorageKey}
|
||||
/>
|
||||
</Modal.Body>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withTranslation('Common')(DicomFileUploaderModal);
|
||||
@ -1,31 +1,33 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import './googleCloud.css';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import { Icon } from 'react-viewerbase';
|
||||
|
||||
export default class DicomStoreList extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
search: '',
|
||||
};
|
||||
}
|
||||
class DicomStoreList extends Component {
|
||||
state = {
|
||||
search: '',
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
stores: PropTypes.array,
|
||||
loading: PropTypes.bool,
|
||||
loading: PropTypes.bool.isRequired,
|
||||
error: PropTypes.string,
|
||||
onSelect: PropTypes.func,
|
||||
};
|
||||
static defaultProps = {};
|
||||
|
||||
renderTableRow(store) {
|
||||
static defaultProps = {
|
||||
loading: true,
|
||||
};
|
||||
|
||||
renderTableRow = store => {
|
||||
return (
|
||||
<tr
|
||||
key={store.name}
|
||||
className={
|
||||
this.state.highlightedItem === store.name
|
||||
? 'studylistStudy noselect active'
|
||||
: 'studylistStudy noselect'
|
||||
? 'noselect active'
|
||||
: 'noselect'
|
||||
}
|
||||
onMouseEnter={() => {
|
||||
this.onHighlightItem(store.name);
|
||||
@ -37,21 +39,40 @@ export default class DicomStoreList extends Component {
|
||||
<td className="project">{store.name.split('/')[7]}</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
onHighlightItem(store) {
|
||||
this.setState({ highlightedItem: store });
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.props.error) {
|
||||
return <p>{this.props.error}</p>;
|
||||
}
|
||||
|
||||
const loadingIcon = (
|
||||
<Icon name="circle-notch" className="loading-icon-spin loading-icon" />
|
||||
);
|
||||
|
||||
if (this.props.loading) {
|
||||
return loadingIcon;
|
||||
}
|
||||
|
||||
const body = (
|
||||
<tbody id="StoreList">{this.props.stores.map(this.renderTableRow)}</tbody>
|
||||
);
|
||||
|
||||
return (
|
||||
<table id="tblStoreList" className="studyListToolbar table noselect">
|
||||
<tbody id="StoreList">
|
||||
{this.props.stores.map(store => {
|
||||
return this.renderTableRow(store);
|
||||
})}
|
||||
</tbody>
|
||||
<table id="tblStoreList" className="gcp-table table noselect">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{this.props.t('DICOM Store')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{this.props.stores && body}
|
||||
</table>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withTranslation('Common')(DicomStoreList);
|
||||
|
||||
@ -5,33 +5,36 @@ import DicomStoreList from './DicomStoreList';
|
||||
import './googleCloud.css';
|
||||
|
||||
export default class DicomStorePicker extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
error: null,
|
||||
loading: false,
|
||||
stores: [],
|
||||
locations: [],
|
||||
};
|
||||
}
|
||||
state = {
|
||||
error: null,
|
||||
loading: true,
|
||||
stores: [],
|
||||
locations: [],
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
dataset: PropTypes.object,
|
||||
onSelect: PropTypes.func,
|
||||
};
|
||||
static defaultProps = {};
|
||||
|
||||
async componentDidMount() {
|
||||
const { authority, client_id } = window.config.oidc[0];
|
||||
const oidcStorageKey = `oidc.user:${authority}:${client_id}`;
|
||||
api.setOidcStorageKey(oidcStorageKey);
|
||||
const response = await api.loadDicomStores(this.props.dataset.name);
|
||||
this.loading = false;
|
||||
|
||||
if (response.isError) {
|
||||
this.error = response.message;
|
||||
this.setState({
|
||||
error: response.message,
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
this.setState({ stores: response.data.dicomStores || [] });
|
||||
|
||||
this.setState({
|
||||
stores: response.data.dicomStores || [],
|
||||
loading: false,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -44,7 +47,7 @@ export default class DicomStorePicker extends Component {
|
||||
loading={loading}
|
||||
error={error}
|
||||
onSelect={onSelect}
|
||||
></DicomStoreList>
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
67
src/googleCloud/DicomStorePickerModal.js
Normal file
67
src/googleCloud/DicomStorePickerModal.js
Normal file
@ -0,0 +1,67 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Modal from 'react-bootstrap-modal';
|
||||
import DatasetSelector from './DatasetSelector';
|
||||
import './googleCloud.css';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
|
||||
class DicomStorePickerModal extends Component {
|
||||
static propTypes = {
|
||||
url: PropTypes.string,
|
||||
oidcStorageKey: PropTypes.string.isRequired,
|
||||
setServers: PropTypes.func.isRequired,
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
onClose: PropTypes.func,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
isOpen: false,
|
||||
};
|
||||
|
||||
handleEvent = data => {
|
||||
const servers = [
|
||||
{
|
||||
name: data.dicomStore,
|
||||
imageRendering: 'wadors',
|
||||
thumbnailRendering: 'wadors',
|
||||
qidoSupportsIncludeField: false,
|
||||
type: 'dicomWeb',
|
||||
qidoRoot: data.qidoRoot,
|
||||
wadoRoot: data.wadoRoot,
|
||||
wadoUriRoot: data.wadoUriRoot,
|
||||
active: true,
|
||||
},
|
||||
];
|
||||
|
||||
this.props.setServers(servers);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Modal
|
||||
show={this.props.isOpen}
|
||||
onHide={this.props.onClose}
|
||||
aria-labelledby="ModalHeader"
|
||||
className="modal fade themed in"
|
||||
backdrop={false}
|
||||
size={'md'}
|
||||
keyboard={true}
|
||||
>
|
||||
<Modal.Header closeButton>
|
||||
<Modal.Title>
|
||||
{this.props.t('Google Cloud Healthcare API')}
|
||||
</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
<DatasetSelector
|
||||
setServers={this.handleEvent}
|
||||
oidcKey={this.props.oidcStorageKey}
|
||||
url={this.props.url}
|
||||
/>
|
||||
</Modal.Body>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withTranslation('Common')(DicomStorePickerModal);
|
||||
@ -1,57 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import DatasetSelector from './DatasetSelector';
|
||||
import './googleCloud.css';
|
||||
|
||||
class DicomStorePickerWindow extends Component {
|
||||
static propTypes = {
|
||||
url: PropTypes.string,
|
||||
oidcStorageKey: PropTypes.string.isRequired,
|
||||
setServers: PropTypes.func.isRequired,
|
||||
onClose: PropTypes.func,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.element = React.createRef();
|
||||
this.handleEvent = this.handleEvent.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {}
|
||||
|
||||
handleEvent(data) {
|
||||
const servers = [
|
||||
{
|
||||
name: data.dicomStore,
|
||||
imageRendering: 'wadors',
|
||||
thumbnailRendering: 'wadors',
|
||||
qidoSupportsIncludeField: false,
|
||||
requestOptions: { requestFromBrowser: true },
|
||||
type: 'dicomWeb',
|
||||
qidoRoot: data.qidoRoot,
|
||||
wadoRoot: data.wadoRoot,
|
||||
wadoUriRoot: data.wadoUriRoot,
|
||||
active: true,
|
||||
},
|
||||
];
|
||||
|
||||
this.props.setServers(servers);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="gcp-window">
|
||||
<DatasetSelector
|
||||
setServers={this.handleEvent}
|
||||
oidcKey={this.props.oidcStorageKey}
|
||||
url={this.props.url}
|
||||
></DatasetSelector>
|
||||
<button className="btn btn-primary" onClick={this.props.onClose}>
|
||||
close
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default DicomStorePickerWindow;
|
||||
@ -6,25 +6,21 @@ import dicomUploader from './api/DicomUploadService';
|
||||
import './googleCloud.css';
|
||||
|
||||
export default class DicomUploader extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
status: 'Upload',
|
||||
isCancelled: false,
|
||||
errorsCount: 0,
|
||||
files: null,
|
||||
uploadedVolume: null,
|
||||
wholeVolumeStr: null,
|
||||
isFilesListHidden: true,
|
||||
timeLeft: null,
|
||||
uploadedList: null,
|
||||
totalCount: 0,
|
||||
successfullyUploadedCount: 0,
|
||||
lastFile: '',
|
||||
uploadContext: null, // this is probably not needed, but we use this variable to destinguish between different downloads
|
||||
};
|
||||
this.uploadFiles = this.uploadFiles.bind(this);
|
||||
}
|
||||
state = {
|
||||
status: 'Upload',
|
||||
isCancelled: false,
|
||||
errorsCount: 0,
|
||||
files: null,
|
||||
uploadedVolume: null,
|
||||
wholeVolumeStr: null,
|
||||
isFilesListHidden: true,
|
||||
timeLeft: null,
|
||||
uploadedList: null,
|
||||
totalCount: 0,
|
||||
successfullyUploadedCount: 0,
|
||||
lastFile: '',
|
||||
uploadContext: null, // this is probably not needed, but we use this variable to distinguish between different downloads
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
id: PropTypes.string,
|
||||
@ -32,7 +28,6 @@ export default class DicomUploader extends Component {
|
||||
url: PropTypes.string,
|
||||
oidcKey: PropTypes.string,
|
||||
};
|
||||
static defaultProps = {};
|
||||
|
||||
filesLeft() {
|
||||
return (
|
||||
@ -66,7 +61,7 @@ export default class DicomUploader extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
uploadFiles(files) {
|
||||
uploadFiles = files => {
|
||||
const filesArray = Array.from(files.target.files);
|
||||
const filesDict = {};
|
||||
filesArray.forEach((file, i) => {
|
||||
@ -107,14 +102,14 @@ export default class DicomUploader extends Component {
|
||||
uploadCallback,
|
||||
cancellationToken
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
uploadCallback(fileId, error) {
|
||||
const file = this.state.files[fileId];
|
||||
file.processed = true;
|
||||
if (!error) {
|
||||
let uploadedVolume = this.state.uploadedVolume + file.size;
|
||||
this.setState({ uploadedVolume: uploadedVolume });
|
||||
this.setState({ uploadedVolume });
|
||||
} else {
|
||||
file.error = error;
|
||||
this.setState({ errorsCount: this.state.errorsCount + 1 });
|
||||
@ -122,17 +117,13 @@ export default class DicomUploader extends Component {
|
||||
this.setState({ lastFile: file.name });
|
||||
let uploadedList = this.state.uploadedList;
|
||||
uploadedList.push(file);
|
||||
this.setState({ uploadedList: uploadedList });
|
||||
this.setState({ uploadedList });
|
||||
}
|
||||
|
||||
renderTableRow(file) {
|
||||
let error = <></>;
|
||||
if (file.error != null) {
|
||||
error = (
|
||||
<>
|
||||
<font color="red">{file.error}</font>
|
||||
</>
|
||||
);
|
||||
renderTableRow = file => {
|
||||
let error = null;
|
||||
if (file.error !== null) {
|
||||
error = <p style={{ color: 'red' }}>{file.error}</p>;
|
||||
}
|
||||
return (
|
||||
<tr key={file.id}>
|
||||
@ -141,10 +132,10 @@ export default class DicomUploader extends Component {
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
if (this.state.files == null) {
|
||||
if (this.state.files === null) {
|
||||
return (
|
||||
<div className="gcp-dicom-uploader">
|
||||
<div className="button">
|
||||
@ -177,28 +168,21 @@ export default class DicomUploader extends Component {
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<>
|
||||
<table
|
||||
id="tblProjectList"
|
||||
className="studyListToolbar table noselect"
|
||||
>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="gcp-picker--path">
|
||||
{this.percents()}% {this.filesLeft()}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="ProjectList">
|
||||
{this.state.uploadedList.map(file => {
|
||||
return this.renderTableRow(file);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<table id="tblProjectList" className="table noselect">
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="gcp-picker--path">
|
||||
{this.percents()}% {this.filesLeft()}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="ProjectList">
|
||||
{this.state.uploadedList.map(this.renderTableRow)}
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,14 +5,11 @@ import LocationsList from './LocationsList';
|
||||
import './googleCloud.css';
|
||||
|
||||
export default class LocationPicker extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
error: null,
|
||||
loading: false,
|
||||
locations: [],
|
||||
};
|
||||
}
|
||||
state = {
|
||||
error: null,
|
||||
loading: true,
|
||||
locations: [],
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
project: PropTypes.object,
|
||||
@ -25,15 +22,19 @@ export default class LocationPicker extends Component {
|
||||
|
||||
const response = await api.loadLocations(this.props.project.projectId);
|
||||
|
||||
this.loading = false;
|
||||
if (response.isError) {
|
||||
this.error = response.message;
|
||||
this.setState({
|
||||
error: response.message,
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
this.setState({ locations: response.data.locations || [] });
|
||||
}
|
||||
|
||||
static defaultProps = {};
|
||||
this.setState({
|
||||
locations: response.data.locations || [],
|
||||
loading: false,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { locations, loading, error } = this.state;
|
||||
@ -44,7 +45,7 @@ export default class LocationPicker extends Component {
|
||||
loading={loading}
|
||||
error={error}
|
||||
onSelect={onSelect}
|
||||
></LocationsList>
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,30 +1,33 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import './googleCloud.css';
|
||||
export default class LocationsList extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
search: '',
|
||||
};
|
||||
}
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import { Icon } from 'react-viewerbase';
|
||||
|
||||
class LocationsList extends Component {
|
||||
state = {
|
||||
search: '',
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
locations: PropTypes.array,
|
||||
loading: PropTypes.bool,
|
||||
loading: PropTypes.bool.isRequired,
|
||||
error: PropTypes.string,
|
||||
onSelect: PropTypes.func,
|
||||
};
|
||||
static defaultProps = {};
|
||||
|
||||
renderTableRow(location) {
|
||||
static defaultProps = {
|
||||
loading: true,
|
||||
};
|
||||
|
||||
renderTableRow = location => {
|
||||
return (
|
||||
<tr
|
||||
key={location.locationId}
|
||||
className={
|
||||
this.state.highlightedItem === location.locationId
|
||||
? 'studylistStudy noselect active'
|
||||
: 'studylistStudy noselect'
|
||||
? 'noselect active'
|
||||
: 'noselect'
|
||||
}
|
||||
onMouseEnter={() => {
|
||||
this.onHighlightItem(location.locationId);
|
||||
@ -36,21 +39,42 @@ export default class LocationsList extends Component {
|
||||
<td>{location.name.split('/')[3]}</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
onHighlightItem(locationId) {
|
||||
this.setState({ highlightedItem: locationId });
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.props.error) {
|
||||
return <p>{this.props.error}</p>;
|
||||
}
|
||||
|
||||
const loadingIcon = (
|
||||
<Icon name="circle-notch" className="loading-icon-spin loading-icon" />
|
||||
);
|
||||
|
||||
if (this.props.loading) {
|
||||
return loadingIcon;
|
||||
}
|
||||
|
||||
const body = (
|
||||
<tbody id="LocationList">
|
||||
{this.props.locations.map(this.renderTableRow)}
|
||||
</tbody>
|
||||
);
|
||||
|
||||
return (
|
||||
<table id="tblLocationList" className="studyListToolbar table noselect">
|
||||
<tbody id="LocationList">
|
||||
{this.props.locations.map(project => {
|
||||
return this.renderTableRow(project);
|
||||
})}
|
||||
</tbody>
|
||||
<table id="tblLocationList" className="gcp-table table noselect">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{this.props.t('Location')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{this.props.locations && body}
|
||||
</table>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withTranslation('Common')(LocationsList);
|
||||
|
||||
@ -5,30 +5,33 @@ import ProjectsList from './ProjectsList';
|
||||
import './googleCloud.css';
|
||||
|
||||
export default class ProjectPicker extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
error: null,
|
||||
loading: false,
|
||||
projects: [],
|
||||
};
|
||||
}
|
||||
state = {
|
||||
error: null,
|
||||
loading: true,
|
||||
projects: [],
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
onSelect: PropTypes.func,
|
||||
oidcKey: PropTypes.string,
|
||||
};
|
||||
static defaultProps = {};
|
||||
|
||||
async componentDidMount() {
|
||||
api.setOidcStorageKey(this.props.oidcKey);
|
||||
const response = await api.loadProjects();
|
||||
this.loading = false;
|
||||
|
||||
if (response.isError) {
|
||||
this.error = response.message;
|
||||
this.setState({
|
||||
error: response.message,
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
this.setState({ projects: response.data.projects || [] });
|
||||
|
||||
this.setState({
|
||||
projects: response.data.projects || [],
|
||||
loading: false,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -40,7 +43,7 @@ export default class ProjectPicker extends Component {
|
||||
loading={loading}
|
||||
error={error}
|
||||
onSelect={onSelect}
|
||||
></ProjectsList>
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,32 +1,35 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import './googleCloud.css';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import { Icon } from 'react-viewerbase';
|
||||
|
||||
export default class ProjectsList extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
search: '',
|
||||
highlightedItem: null,
|
||||
};
|
||||
}
|
||||
class ProjectsList extends Component {
|
||||
state = {
|
||||
search: '',
|
||||
highlightedItem: null,
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
projects: PropTypes.array,
|
||||
loading: PropTypes.bool,
|
||||
loading: PropTypes.bool.isRequired,
|
||||
error: PropTypes.string,
|
||||
onSelect: PropTypes.func.isRequired,
|
||||
t: PropTypes.func,
|
||||
};
|
||||
static defaultProps = {};
|
||||
|
||||
renderTableRow(project) {
|
||||
static defaultProps = {
|
||||
loading: true,
|
||||
};
|
||||
|
||||
renderTableRow = project => {
|
||||
return (
|
||||
<tr
|
||||
key={project.projectId}
|
||||
className={
|
||||
this.state.highlightedItem === project.projectId
|
||||
? 'studylistStudy noselect active'
|
||||
: 'studylistStudy noselect'
|
||||
? 'noselect active'
|
||||
: 'noselect'
|
||||
}
|
||||
onMouseEnter={() => {
|
||||
this.onHighlightItem(project.projectId);
|
||||
@ -37,23 +40,46 @@ export default class ProjectsList extends Component {
|
||||
}}
|
||||
>
|
||||
<td>{project.name}</td>
|
||||
<td>{project.projectId}</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
onHighlightItem(project) {
|
||||
this.setState({ highlightedItem: project });
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.props.error) {
|
||||
return <p>{this.props.error}</p>;
|
||||
}
|
||||
|
||||
const loadingIcon = (
|
||||
<Icon name="circle-notch" className="loading-icon-spin loading-icon" />
|
||||
);
|
||||
|
||||
if (this.props.loading) {
|
||||
return loadingIcon;
|
||||
}
|
||||
|
||||
const body = (
|
||||
<tbody id="ProjectList">
|
||||
{this.props.projects.map(this.renderTableRow)}
|
||||
</tbody>
|
||||
);
|
||||
|
||||
return (
|
||||
<table id="tblProjectList" className="studyListToolbar table noselect">
|
||||
<tbody id="ProjectList">
|
||||
{this.props.projects.map(project => {
|
||||
return this.renderTableRow(project);
|
||||
})}
|
||||
</tbody>
|
||||
<table id="tblProjectList" className="gcp-table table noselect">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{this.props.t('Project')}</th>
|
||||
<th>{this.props.t('ID')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{this.props.projects && body}
|
||||
</table>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withTranslation('Common')(ProjectsList);
|
||||
|
||||
@ -62,8 +62,8 @@ class DicomUploadService {
|
||||
}
|
||||
|
||||
readFile(file) {
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
var reader = new FileReader();
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = () => {
|
||||
resolve({
|
||||
name: file.name,
|
||||
@ -75,7 +75,6 @@ class DicomUploadService {
|
||||
reader.onerror = error => reject(error);
|
||||
reader.readAsArrayBuffer(file);
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
|
||||
getClient(url) {
|
||||
|
||||
@ -27,7 +27,7 @@ class GoogleCloudApi {
|
||||
}
|
||||
|
||||
async doRequest(urlStr, config = {}, params = {}) {
|
||||
var url = new URL(urlStr);
|
||||
const url = new URL(urlStr);
|
||||
let data = null;
|
||||
url.search = new URLSearchParams(params);
|
||||
|
||||
@ -40,7 +40,7 @@ class GoogleCloudApi {
|
||||
if (data.nextPageToken != null) {
|
||||
params.pageToken = data.nextPageToken;
|
||||
let subPage = await this.doRequest(urlStr, config, params);
|
||||
for (var key in data) {
|
||||
for (let key in data) {
|
||||
if (data.hasOwnProperty(key)) {
|
||||
data[key] = data[key].concat(subPage.data[key]);
|
||||
}
|
||||
@ -49,7 +49,7 @@ class GoogleCloudApi {
|
||||
return {
|
||||
isError: false,
|
||||
status: response.status,
|
||||
data: data,
|
||||
data,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
@ -81,17 +81,17 @@ class GoogleCloudApi {
|
||||
}
|
||||
|
||||
async loadLocations(projectId) {
|
||||
return this.doRequest(this.urlBaseProject + `/${projectId}/locations`);
|
||||
return this.doRequest(`${this.urlBaseProject}/${projectId}/locations`);
|
||||
}
|
||||
|
||||
async loadDatasets(projectId, locationId) {
|
||||
return this.doRequest(
|
||||
this.urlBaseProject + `/${projectId}/locations/${locationId}/datasets`
|
||||
`${this.urlBaseProject}/${projectId}/locations/${locationId}/datasets`
|
||||
);
|
||||
}
|
||||
|
||||
async loadDicomStores(dataset) {
|
||||
return this.doRequest(this.urlBase + `/${dataset}/dicomStores`);
|
||||
return this.doRequest(`${this.urlBase}/${dataset}/dicomStores`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,76 @@
|
||||
.loading-icon-spin {
|
||||
animation: spin 2s linear infinite;
|
||||
}
|
||||
|
||||
.loading-icon {
|
||||
font-size: 30px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.gcp-table {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
margin-bottom: 20px;
|
||||
border-spacing: 0;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
.gcp-table > tr {
|
||||
height: 20px;
|
||||
}
|
||||
.gcp-table > thead {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.gcp-table > thead tr th {
|
||||
padding: 0;
|
||||
border-bottom: 1px solid var(--ui-border-color-active);
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
border-top: 0;
|
||||
}
|
||||
.gcp-table > tbody tr {
|
||||
padding: 5px;
|
||||
background-color: var(--ui-gray-darker);
|
||||
}
|
||||
.gcp-table > tbody tr:nth-child(even) {
|
||||
background-color: var(--ui-gray-dark);
|
||||
}
|
||||
|
||||
.gcp-table > tbody tr td {
|
||||
padding: 8px;
|
||||
height: $body-cell-height;
|
||||
line-height: $body-cell-height;
|
||||
color: var(--table-text-primary-color);
|
||||
font-weight: 300;
|
||||
border-top: 1px solid var(--ui-gray-lighter);
|
||||
border-bottom: 1px solid var(--ui-gray-lighter);
|
||||
white-space: nowrap;
|
||||
}
|
||||
.gcp-table > tbody tr td.emptyCell {
|
||||
color: #516873;
|
||||
}
|
||||
.gcp-table > tbody tr td.emptyValue {
|
||||
color: var(--ui-gray-light);
|
||||
}
|
||||
.gcp-table > tbody tr:hover,
|
||||
.gcp-table > tbody tr:active,
|
||||
.gcp-table > tbody tr.active {
|
||||
background-color: var(--table-hover-color);
|
||||
color: var(--text-primary-color);
|
||||
}
|
||||
.gcp-table > tbody tr:hover td,
|
||||
.gcp-table > tbody tr:active td,
|
||||
.gcp-table > tbody tr.active td {
|
||||
border-top: 1px solid var(--ui-gray-lighter);
|
||||
border-bottom: 1px solid var(--ui-gray-lighter);
|
||||
background-color: var(--table-hover-color);
|
||||
}
|
||||
|
||||
.gcp-files-selector {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@ -32,10 +105,37 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
.gcp-picker {
|
||||
box-sizing: border-box;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
width: 650px;
|
||||
height: 600px;
|
||||
background-color: #161a1f;
|
||||
padding: 20px 30px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.gcp-dicom-picker__exit {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
right: 30px;
|
||||
width: 14px !important;
|
||||
height: 14px !important;
|
||||
filter: opacity(0.5);
|
||||
}
|
||||
|
||||
.gcp-dicom-picker__exit:hover {
|
||||
filter: opacity(1);
|
||||
}
|
||||
|
||||
.gcp-picker--btn {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.gcp-picker--title {
|
||||
color: #ffffff;
|
||||
font-size: 24px;
|
||||
font-weight: 28px;
|
||||
text-align: center;
|
||||
margin: 20px auto;
|
||||
}
|
||||
@ -44,6 +144,11 @@
|
||||
color: #ffffff;
|
||||
font-size: 16px;
|
||||
font-weight: 28px;
|
||||
text-align: leaft;
|
||||
text-align: left;
|
||||
margin: 20px auto;
|
||||
}
|
||||
|
||||
.gcp-dicom-uploader .button {
|
||||
float: left;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import OHIF from 'ohif-core';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import { StudyList } from 'react-viewerbase';
|
||||
import ConnectedHeader from '../connectedComponents/ConnectedHeader.js';
|
||||
import moment from 'moment';
|
||||
@ -14,7 +15,6 @@ class StudyListWithData extends Component {
|
||||
studies: [],
|
||||
error: null,
|
||||
modalComponentId: null,
|
||||
showStudyList: true,
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
@ -47,7 +47,6 @@ class StudyListWithData extends Component {
|
||||
if (!this.props.server && window.config.enableGoogleCloudAdapter) {
|
||||
this.setState({
|
||||
modalComponentId: 'DicomStorePicker',
|
||||
showStudyList: false,
|
||||
});
|
||||
} else {
|
||||
this.searchForStudies({
|
||||
@ -64,7 +63,6 @@ class StudyListWithData extends Component {
|
||||
if (this.props.server !== prevProps.server) {
|
||||
this.setState({
|
||||
modalComponentId: null,
|
||||
showStudyList: true,
|
||||
searchData: null,
|
||||
studies: null,
|
||||
});
|
||||
@ -151,7 +149,6 @@ class StudyListWithData extends Component {
|
||||
openModal = modalComponentId => {
|
||||
this.setState({
|
||||
modalComponentId,
|
||||
showStudyList: false,
|
||||
});
|
||||
};
|
||||
|
||||
@ -167,10 +164,9 @@ class StudyListWithData extends Component {
|
||||
this.searchForStudies(searchData);
|
||||
};
|
||||
|
||||
update = () => {
|
||||
closeModals = () => {
|
||||
this.setState({
|
||||
modalComponentId: null,
|
||||
showStudyList: true,
|
||||
});
|
||||
};
|
||||
|
||||
@ -181,49 +177,47 @@ class StudyListWithData extends Component {
|
||||
return <div>Loading...</div>;
|
||||
}
|
||||
|
||||
let healthCareApiButtons = '';
|
||||
let healthCareApiWindows = '';
|
||||
let healthCareApiButtons = null;
|
||||
let healthCareApiWindows = null;
|
||||
|
||||
// TODO: This should probably be a prop
|
||||
if (window.config.enableGoogleCloudAdapter) {
|
||||
if (this.state.modalComponentId) {
|
||||
if (this.state.modalComponentId === 'DicomStorePicker') {
|
||||
healthCareApiWindows = (
|
||||
<ConnectedDicomStorePicker onClose={this.update} />
|
||||
);
|
||||
} else if (this.state.modalComponentId === 'DicomFilesUploader') {
|
||||
healthCareApiWindows = (
|
||||
<ConnectedDicomFilesUploader onClose={this.update} />
|
||||
);
|
||||
}
|
||||
healthCareApiWindows = (
|
||||
<>
|
||||
<div className="col-md-4 col-md-offset-2 layoutChooser pagination-area">
|
||||
{healthCareApiWindows}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
healthCareApiButtons = (
|
||||
healthCareApiWindows = (
|
||||
<>
|
||||
<div className="form-inline form-group pull-right">
|
||||
<button
|
||||
className="btn btn-primary "
|
||||
onClick={() => this.openModal('DicomStorePicker')}
|
||||
>
|
||||
Change Dicom Store
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-primary"
|
||||
onClick={() => this.openModal('DicomFilesUploader')}
|
||||
>
|
||||
Upload Studies
|
||||
</button>
|
||||
</div>
|
||||
<ConnectedDicomStorePicker
|
||||
isOpen={this.state.modalComponentId === 'DicomStorePicker'}
|
||||
onClose={this.closeModals}
|
||||
/>
|
||||
<ConnectedDicomFilesUploader
|
||||
isOpen={this.state.modalComponentId === 'DicomFilesUploader'}
|
||||
onClose={this.closeModals}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
healthCareApiButtons = (
|
||||
<div
|
||||
className="form-inline btn-group pull-right"
|
||||
style={{ padding: '20px' }}
|
||||
>
|
||||
<button
|
||||
className="btn btn-primary"
|
||||
onClick={() => this.openModal('DicomStorePicker')}
|
||||
>
|
||||
{this.props.t('Change DICOM Store')}
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-primary"
|
||||
onClick={() => this.openModal('DicomFilesUploader')}
|
||||
>
|
||||
{this.props.t('Upload Studies')}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
let studyList = <></>;
|
||||
studyList = (
|
||||
<div name="paginationArea">
|
||||
|
||||
const studyList = (
|
||||
<div className="paginationArea">
|
||||
<StudyList
|
||||
studies={this.state.studies}
|
||||
studyListFunctionsEnabled={false}
|
||||
@ -250,4 +244,4 @@ class StudyListWithData extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default withRouter(StudyListWithData);
|
||||
export default withRouter(withTranslation('Common')(StudyListWithData));
|
||||
|
||||
46
yarn.lock
46
yarn.lock
@ -4313,7 +4313,7 @@ debug@3.2.6, debug@^3.1.0, debug@^3.2.5, debug@^3.2.6:
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
debuglog@*, debuglog@^1.0.1:
|
||||
debuglog@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492"
|
||||
integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=
|
||||
@ -6958,7 +6958,7 @@ import-local@^2.0.0:
|
||||
pkg-dir "^3.0.0"
|
||||
resolve-cwd "^2.0.0"
|
||||
|
||||
imurmurhash@*, imurmurhash@^0.1.4:
|
||||
imurmurhash@^0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
||||
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
|
||||
@ -8602,7 +8602,7 @@ libnpm@^2.0.1:
|
||||
read-package-json "^2.0.13"
|
||||
stringify-package "^1.0.0"
|
||||
|
||||
libnpmaccess@*, libnpmaccess@^3.0.1:
|
||||
libnpmaccess@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/libnpmaccess/-/libnpmaccess-3.0.1.tgz#5b3a9de621f293d425191aa2e779102f84167fa8"
|
||||
integrity sha512-RlZ7PNarCBt+XbnP7R6PoVgOq9t+kou5rvhaInoNibhPO7eMlRfS0B8yjatgn2yaHIwWNyoJDolC/6Lc5L/IQA==
|
||||
@ -8631,7 +8631,7 @@ libnpmhook@^5.0.2:
|
||||
get-stream "^4.0.0"
|
||||
npm-registry-fetch "^3.8.0"
|
||||
|
||||
libnpmorg@*, libnpmorg@^1.0.0:
|
||||
libnpmorg@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/libnpmorg/-/libnpmorg-1.0.0.tgz#979b868c48ba28c5820e3bb9d9e73c883c16a232"
|
||||
integrity sha512-o+4eVJBoDGMgRwh2lJY0a8pRV2c/tQM/SxlqXezjcAg26Qe9jigYVs+Xk0vvlYDWCDhP0g74J8UwWeAgsB7gGw==
|
||||
@ -8656,7 +8656,7 @@ libnpmpublish@^1.1.0:
|
||||
semver "^5.5.1"
|
||||
ssri "^6.0.1"
|
||||
|
||||
libnpmsearch@*, libnpmsearch@^2.0.0:
|
||||
libnpmsearch@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/libnpmsearch/-/libnpmsearch-2.0.1.tgz#eccc73a8fbf267d765d18082b85daa2512501f96"
|
||||
integrity sha512-K0yXyut9MHHCAH+DOiglQCpmBKPZXSUu76+BE2maSEfQN15OwNaA/Aiioe9lRFlVFOr7WcuJCY+VSl+gLi9NTA==
|
||||
@ -8665,7 +8665,7 @@ libnpmsearch@*, libnpmsearch@^2.0.0:
|
||||
get-stream "^4.0.0"
|
||||
npm-registry-fetch "^3.8.0"
|
||||
|
||||
libnpmteam@*, libnpmteam@^1.0.1:
|
||||
libnpmteam@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/libnpmteam/-/libnpmteam-1.0.1.tgz#ff704b1b6c06ea674b3b1101ac3e305f5114f213"
|
||||
integrity sha512-gDdrflKFCX7TNwOMX1snWojCoDE5LoRWcfOC0C/fqF7mBq8Uz9zWAX4B2RllYETNO7pBupBaSyBDkTAC15cAMg==
|
||||
@ -8923,11 +8923,6 @@ lodash-es@^4.17.11:
|
||||
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.11.tgz#145ab4a7ac5c5e52a3531fb4f310255a152b4be0"
|
||||
integrity sha512-DHb1ub+rMjjrxqlB3H56/6MXtm1lSksDp2rA2cNWjG8mlDUYFhUj3Di2Zn5IwSU87xLv8tNIQ7sSwE/YOX/D/Q==
|
||||
|
||||
lodash._baseindexof@*:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz#fe52b53a1c6761e42618d654e4a25789ed61822c"
|
||||
integrity sha1-/lK1OhxnYeQmGNZU5KJXie1hgiw=
|
||||
|
||||
lodash._baseuniq@~4.6.0:
|
||||
version "4.6.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8"
|
||||
@ -8936,33 +8931,11 @@ lodash._baseuniq@~4.6.0:
|
||||
lodash._createset "~4.0.0"
|
||||
lodash._root "~3.0.0"
|
||||
|
||||
lodash._bindcallback@*:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e"
|
||||
integrity sha1-5THCdkTPi1epnhftlbNcdIeJOS4=
|
||||
|
||||
lodash._cacheindexof@*:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz#3dc69ac82498d2ee5e3ce56091bafd2adc7bde92"
|
||||
integrity sha1-PcaayCSY0u5ePOVgkbr9Ktx73pI=
|
||||
|
||||
lodash._createcache@*:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash._createcache/-/lodash._createcache-3.1.2.tgz#56d6a064017625e79ebca6b8018e17440bdcf093"
|
||||
integrity sha1-VtagZAF2JeeevKa4AY4XRAvc8JM=
|
||||
dependencies:
|
||||
lodash._getnative "^3.0.0"
|
||||
|
||||
lodash._createset@~4.0.0:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26"
|
||||
integrity sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY=
|
||||
|
||||
lodash._getnative@*, lodash._getnative@^3.0.0:
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"
|
||||
integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=
|
||||
|
||||
lodash._reinterpolate@~3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
|
||||
@ -9038,11 +9011,6 @@ lodash.once@^4.1.1:
|
||||
resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
|
||||
integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=
|
||||
|
||||
lodash.restparam@*:
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805"
|
||||
integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=
|
||||
|
||||
lodash.set@^4.3.2:
|
||||
version "4.3.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23"
|
||||
@ -10125,7 +10093,7 @@ npm-pick-manifest@^2.2.3:
|
||||
npm-package-arg "^6.0.0"
|
||||
semver "^5.4.1"
|
||||
|
||||
npm-profile@*, npm-profile@^4.0.1:
|
||||
npm-profile@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/npm-profile/-/npm-profile-4.0.1.tgz#d350f7a5e6b60691c7168fbb8392c3603583f5aa"
|
||||
integrity sha512-NQ1I/1Q7YRtHZXkcuU1/IyHeLy6pd+ScKg4+DQHdfsm769TGq6HPrkbuNJVJS4zwE+0mvvmeULzQdWn2L2EsVA==
|
||||
|
||||
Loading…
Reference in New Issue
Block a user