diff --git a/src/googleCloud/ConnectedDicomFilesUploader.js b/src/googleCloud/ConnectedDicomFilesUploader.js
index 15a818fd8..1edf639f0 100644
--- a/src/googleCloud/ConnectedDicomFilesUploader.js
+++ b/src/googleCloud/ConnectedDicomFilesUploader.js
@@ -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;
diff --git a/src/googleCloud/ConnectedDicomStorePicker.js b/src/googleCloud/ConnectedDicomStorePicker.js
index e6dcd6e88..4572af90f 100644
--- a/src/googleCloud/ConnectedDicomStorePicker.js
+++ b/src/googleCloud/ConnectedDicomStorePicker.js
@@ -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;
diff --git a/src/googleCloud/DatasetPicker.js b/src/googleCloud/DatasetPicker.js
index a7a62a30d..581dd2be0 100644
--- a/src/googleCloud/DatasetPicker.js
+++ b/src/googleCloud/DatasetPicker.js
@@ -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}
- >
+ />
);
}
}
diff --git a/src/googleCloud/DatasetSelector.js b/src/googleCloud/DatasetSelector.js
index 85119fb59..f347226f1 100644
--- a/src/googleCloud/DatasetSelector.js
+++ b/src/googleCloud/DatasetSelector.js
@@ -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 = (
+
+ {this.props.t('Select a Project')}
+
+ );
+
+ if (project) {
+ projectBreadcrumbs = (
+
+ {project.name}
+ {project && location && (
+
+ {' '}
+ -> {location.name.split('/')[3]}
+
+ )}
+ {project && location && dataset && (
+
+ {' '}
+ -> {dataset.name.split('/')[5]}
+
+ )}
+
+ );
+ }
+
return (
<>
- Google Cloud Healthcare API
- {project && (
-
- {project.name}
- {project && location && (
- <>
-
- {' '}
- -> {location.name.split('/')[3]}
-
- {project && location && dataset && (
-
- {' '}
- -> {dataset.name.split('/')[5]}
-
- )}
- >
- )}
-
- )}
-
+ {projectBreadcrumbs}
{!project && (
+ />
)}
{project && !location && (
- <>
-
- >
+
)}
{project && location && !dataset && (
- <>
-
- >
+
)}
{project && location && dataset && (
- <>
-
- >
+
)}
>
);
}
}
+
+export default withTranslation('Common')(DatasetSelector);
diff --git a/src/googleCloud/DatasetsList.js b/src/googleCloud/DatasetsList.js
index af1d038b0..cdcc103d1 100644
--- a/src/googleCloud/DatasetsList.js
+++ b/src/googleCloud/DatasetsList.js
@@ -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 (
{
this.onHighlightItem(dataset.name);
@@ -37,21 +39,42 @@ export default class DatasetsList extends Component {
| {dataset.name.split('/')[5]} |
);
- }
+ };
onHighlightItem(dataset) {
this.setState({ highlightedItem: dataset });
}
render() {
+ if (this.props.error) {
+ return {this.props.error}
;
+ }
+
+ const loadingIcon = (
+
+ );
+
+ if (this.props.loading) {
+ return loadingIcon;
+ }
+
+ const body = (
+
+ {this.props.datasets.map(this.renderTableRow)}
+
+ );
+
return (
-
-
- {this.props.datasets.map(dataset => {
- return this.renderTableRow(dataset);
- })}
-
+
+
+
+ | {this.props.t('Dataset')} |
+
+
+ {this.props.datasets && body}
);
}
}
+
+export default withTranslation('Common')(DatasetsList);
diff --git a/src/googleCloud/DicomFileUploader.js b/src/googleCloud/DicomFileUploader.js
deleted file mode 100644
index 9e7fe0b76..000000000
--- a/src/googleCloud/DicomFileUploader.js
+++ /dev/null
@@ -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 (
-
-
-
-
- );
- }
- return <>>;
- }
-}
-
-export default DicomFileUploader;
diff --git a/src/googleCloud/DicomFileUploaderModal.js b/src/googleCloud/DicomFileUploaderModal.js
new file mode 100644
index 000000000..f0e38fe4a
--- /dev/null
+++ b/src/googleCloud/DicomFileUploaderModal.js
@@ -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 (
+
+
+
+ {this.props.t('Google Cloud Healthcare API - DICOM Upload')}
+
+
+
+
+
+
+ );
+ }
+}
+
+export default withTranslation('Common')(DicomFileUploaderModal);
diff --git a/src/googleCloud/DicomStoreList.js b/src/googleCloud/DicomStoreList.js
index ba5a16ca6..aac4b3f85 100644
--- a/src/googleCloud/DicomStoreList.js
+++ b/src/googleCloud/DicomStoreList.js
@@ -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 (
{
this.onHighlightItem(store.name);
@@ -37,21 +39,40 @@ export default class DicomStoreList extends Component {
| {store.name.split('/')[7]} |
);
- }
+ };
onHighlightItem(store) {
this.setState({ highlightedItem: store });
}
render() {
+ if (this.props.error) {
+ return {this.props.error}
;
+ }
+
+ const loadingIcon = (
+
+ );
+
+ if (this.props.loading) {
+ return loadingIcon;
+ }
+
+ const body = (
+ {this.props.stores.map(this.renderTableRow)}
+ );
+
return (
-
-
- {this.props.stores.map(store => {
- return this.renderTableRow(store);
- })}
-
+
+
+
+ | {this.props.t('DICOM Store')} |
+
+
+ {this.props.stores && body}
);
}
}
+
+export default withTranslation('Common')(DicomStoreList);
diff --git a/src/googleCloud/DicomStorePicker.js b/src/googleCloud/DicomStorePicker.js
index f4a44182b..7437bb9a2 100644
--- a/src/googleCloud/DicomStorePicker.js
+++ b/src/googleCloud/DicomStorePicker.js
@@ -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}
- >
+ />
);
}
}
diff --git a/src/googleCloud/DicomStorePickerModal.js b/src/googleCloud/DicomStorePickerModal.js
new file mode 100644
index 000000000..5de69f531
--- /dev/null
+++ b/src/googleCloud/DicomStorePickerModal.js
@@ -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 (
+
+
+
+ {this.props.t('Google Cloud Healthcare API')}
+
+
+
+
+
+
+ );
+ }
+}
+
+export default withTranslation('Common')(DicomStorePickerModal);
diff --git a/src/googleCloud/DicomStorePickerWindow.js b/src/googleCloud/DicomStorePickerWindow.js
deleted file mode 100644
index 8b080f91e..000000000
--- a/src/googleCloud/DicomStorePickerWindow.js
+++ /dev/null
@@ -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 (
-
-
-
-
- );
- }
-}
-
-export default DicomStorePickerWindow;
diff --git a/src/googleCloud/DicomUploader.js b/src/googleCloud/DicomUploader.js
index 423c51fb5..1f03dd06a 100644
--- a/src/googleCloud/DicomUploader.js
+++ b/src/googleCloud/DicomUploader.js
@@ -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 = (
- <>
- {file.error}
- >
- );
+ renderTableRow = file => {
+ let error = null;
+ if (file.error !== null) {
+ error = {file.error}
;
}
return (
@@ -141,10 +132,10 @@ export default class DicomUploader extends Component {
);
- }
+ };
render() {
- if (this.state.files == null) {
+ if (this.state.files === null) {
return (
@@ -177,28 +168,21 @@ export default class DicomUploader extends Component {
);
- } else {
- return (
- <>
-
-
-
- |
- {this.percents()}% {this.filesLeft()}
- |
-
-
-
- {this.state.uploadedList.map(file => {
- return this.renderTableRow(file);
- })}
-
-
- >
- );
}
+
+ return (
+
+
+
+ |
+ {this.percents()}% {this.filesLeft()}
+ |
+
+
+
+ {this.state.uploadedList.map(this.renderTableRow)}
+
+
+ );
}
}
diff --git a/src/googleCloud/LocationPicker.js b/src/googleCloud/LocationPicker.js
index f15782dc2..423d194c5 100644
--- a/src/googleCloud/LocationPicker.js
+++ b/src/googleCloud/LocationPicker.js
@@ -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}
- >
+ />
);
}
}
diff --git a/src/googleCloud/LocationsList.js b/src/googleCloud/LocationsList.js
index a1ad230a7..cab67e08e 100644
--- a/src/googleCloud/LocationsList.js
+++ b/src/googleCloud/LocationsList.js
@@ -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 (
{
this.onHighlightItem(location.locationId);
@@ -36,21 +39,42 @@ export default class LocationsList extends Component {
| {location.name.split('/')[3]} |
);
- }
+ };
onHighlightItem(locationId) {
this.setState({ highlightedItem: locationId });
}
render() {
+ if (this.props.error) {
+ return {this.props.error}
;
+ }
+
+ const loadingIcon = (
+
+ );
+
+ if (this.props.loading) {
+ return loadingIcon;
+ }
+
+ const body = (
+
+ {this.props.locations.map(this.renderTableRow)}
+
+ );
+
return (
-
-
- {this.props.locations.map(project => {
- return this.renderTableRow(project);
- })}
-
+
+
+
+ | {this.props.t('Location')} |
+
+
+ {this.props.locations && body}
);
}
}
+
+export default withTranslation('Common')(LocationsList);
diff --git a/src/googleCloud/ProjectPicker.js b/src/googleCloud/ProjectPicker.js
index d9ba1f8c7..4455f211b 100644
--- a/src/googleCloud/ProjectPicker.js
+++ b/src/googleCloud/ProjectPicker.js
@@ -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}
- >
+ />
);
}
}
diff --git a/src/googleCloud/ProjectsList.js b/src/googleCloud/ProjectsList.js
index 98974d8a5..22b731039 100644
--- a/src/googleCloud/ProjectsList.js
+++ b/src/googleCloud/ProjectsList.js
@@ -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 (
{
this.onHighlightItem(project.projectId);
@@ -37,23 +40,46 @@ export default class ProjectsList extends Component {
}}
>
| {project.name} |
+ {project.projectId} |
);
- }
+ };
onHighlightItem(project) {
this.setState({ highlightedItem: project });
}
render() {
+ if (this.props.error) {
+ return {this.props.error}
;
+ }
+
+ const loadingIcon = (
+
+ );
+
+ if (this.props.loading) {
+ return loadingIcon;
+ }
+
+ const body = (
+
+ {this.props.projects.map(this.renderTableRow)}
+
+ );
+
return (
-
-
- {this.props.projects.map(project => {
- return this.renderTableRow(project);
- })}
-
+
+
+
+ | {this.props.t('Project')} |
+ {this.props.t('ID')} |
+
+
+ {this.props.projects && body}
);
}
}
+
+export default withTranslation('Common')(ProjectsList);
diff --git a/src/googleCloud/api/DicomUploadService.js b/src/googleCloud/api/DicomUploadService.js
index 4ad30ce40..07250ab72 100644
--- a/src/googleCloud/api/DicomUploadService.js
+++ b/src/googleCloud/api/DicomUploadService.js
@@ -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) {
diff --git a/src/googleCloud/api/GoogleCloudApi.js b/src/googleCloud/api/GoogleCloudApi.js
index 616ae8259..d3a4cf5d2 100644
--- a/src/googleCloud/api/GoogleCloudApi.js
+++ b/src/googleCloud/api/GoogleCloudApi.js
@@ -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`);
}
}
diff --git a/src/googleCloud/googleCloud.css b/src/googleCloud/googleCloud.css
index 466483d93..b83d718cd 100644
--- a/src/googleCloud/googleCloud.css
+++ b/src/googleCloud/googleCloud.css
@@ -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;
+}
diff --git a/src/studylist/StudyListWithData.js b/src/studylist/StudyListWithData.js
index c6bf3d4c4..3f97015cf 100644
--- a/src/studylist/StudyListWithData.js
+++ b/src/studylist/StudyListWithData.js
@@ -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 Loading...
;
}
- 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 = (
-
- );
- } else if (this.state.modalComponentId === 'DicomFilesUploader') {
- healthCareApiWindows = (
-
- );
- }
- healthCareApiWindows = (
- <>
-
- {healthCareApiWindows}
-
- >
- );
- }
- healthCareApiButtons = (
+ healthCareApiWindows = (
<>
-
-
-
-
+
+
>
);
+
+ healthCareApiButtons = (
+
+
+
+
+ );
}
- let studyList = <>>;
- studyList = (
-
+
+ const studyList = (
+