Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hiding DICOM Viewer button for the imaging studies that doesn't have one #1174

Merged
merged 12 commits into from
Dec 16, 2022
110 changes: 75 additions & 35 deletions src/GuppyDataExplorer/ExplorerTable/index.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import _ from 'lodash';
import _, { isEqual } from 'lodash';
import pluralize from 'pluralize';
import ReactTable from 'react-table';
import { Switch } from 'antd';
Expand All @@ -21,42 +21,13 @@ class ExplorerTable extends React.Component {
pageSize: props.defaultPageSize,
currentPage: 0,
showEmptyColumns: false,
tableData: this.props.rawData,
};
}

getWidthForColumn = (field, columnName) => {
if (this.props.tableConfig.linkFields.includes(field)) {
return 80;
}

// some magic numbers that work fine for table columns width
const minWidth = 100;
const maxWidth = 400;
const letterWidth = 8;
const spacing = 20;
if (!this.props.rawData || this.props.rawData.length === 0) {
return minWidth;
}
let maxLetterLen = columnName.length;
const fieldStringsArray = field.split('.');
this.props.rawData.forEach((d) => {
if (d[fieldStringsArray[0]] === null || typeof d[fieldStringsArray[0]] === 'undefined') {
return;
}
// the calculation logic here is a bit wild if it is a nested array field
// it would convert the whole array to string and calculate
// which in most cases would exceed the maxWidth so just use maxWidth
const str = d[fieldStringsArray[0]].toString && d[fieldStringsArray[0]].toString();
const len = str ? str.length : 0;
maxLetterLen = len > maxLetterLen ? len : maxLetterLen;
});
const resWidth = Math.min((maxLetterLen * letterWidth) + spacing, maxWidth);
return resWidth;
}

/**
* Build column configs for each table according to their locations and fields
* @param field: the full field name, if it is a nested field, it would contains at least 1 '.'
* @param field: the full field name, if it is a nested field, it would contain at least 1 '.'
* @param isNestedTableColumn: control flag to determine if it is building column config for
* the root table or inner nested tables
* @param isDetailedColumn: control flag to determine if it is building column config for inner
Expand All @@ -65,7 +36,7 @@ class ExplorerTable extends React.Component {
*/
buildColumnConfig = (field, isNestedTableColumn, isDetailedColumn) => {
const fieldMappingEntry = this.props.guppyConfig.fieldMapping
&& this.props.guppyConfig.fieldMapping.find((i) => i.field === field);
&& this.props.guppyConfig.fieldMapping.find((i) => i.field === field);
const overrideName = fieldMappingEntry ? fieldMappingEntry.name : undefined;
const fieldStringsArray = field.split('.');
// for nested table, we only display the children names in column header
Expand Down Expand Up @@ -130,7 +101,10 @@ class ExplorerTable extends React.Component {

// if this field is the `dicomViewerId`, convert the value to a link to the DICOM viewer
if (this.props.tableConfig.dicomViewerId && this.props.tableConfig.dicomViewerId === field && valueStr) {
const dicomViewerLink = `${hostname}dicom-viewer/viewer/${valueStr}`;
let dicomViewerLink = `${hostname}dicom-viewer/viewer/${valueStr}`;
if (row.original.has_dicom_images !== undefined && !row.original.has_dicom_images) {
dicomViewerLink = undefined;
}
if (this.props.tableConfig.linkFields.includes(field)) { // link button
valueStr = dicomViewerLink;
} else { // direct link
Expand Down Expand Up @@ -248,10 +222,76 @@ class ExplorerTable extends React.Component {
this.setState({ showEmptyColumns: checked });
};

/**
* processes the table data if this is a dicom table. This will determine if the table row
* has image data and will then esure that the lick icon is shown
*/
augmentData = () => {
const haveField = this.props.rawData.filter((x) => Object.keys(x).includes(this.props.tableConfig.dicomViewerId));
if (haveField.length === this.props.rawData.length) {
this.setState({ loading: true });
// eslint-disable-next-line array-callback-return
Promise.all(this.props.rawData.map((x) => {
const dicomServerLink = `${hostname}dicom-server/dicom-web/studies/${x[this.props.tableConfig.dicomViewerId]}/series`;
return fetch(dicomServerLink, {
method: 'GET',
})
.then((resp) => ({ ...x, has_dicom_images: resp.headers.get('content-length') !== '22' }),
);
})).then((data) => {
this.setState({ tableData: data });
this.setState({ loading: false });
});
}
}

/**
* Used to process the table data when needed.
* THis is used primarily to check for the existence
* of a Dicom images to show the link icon to the dicom viewer
* @param prevProps
*/
componentDidUpdate(prevProps) {
if (this.props.tableConfig.dicomViewerId && !isEqual(this.props.rawData, prevProps.rawData)) {
this.augmentData();
} else if (this.props.rawData !== prevProps.rawData) this.setState({ tableData: this.props.rawData });
}

getWidthForColumn = (field, columnName) => {
if (this.props.tableConfig.linkFields.includes(field)) {
return 80;
}

// some magic numbers that work fine for table columns width
const minWidth = 100;
const maxWidth = 400;
const letterWidth = 8;
const spacing = 20;
if (!this.props.rawData || this.props.rawData.length === 0) {
return minWidth;
}
let maxLetterLen = columnName.length;
const fieldStringsArray = field.split('.');
this.props.rawData.forEach((d) => {
if (d[fieldStringsArray[0]] === null || typeof d[fieldStringsArray[0]] === 'undefined') {
return;
}
// the calculation logic here is a bit wild if it is a nested array field
// it would convert the whole array to string and calculate
// which in most cases would exceed the maxWidth so just use maxWidth
const str = d[fieldStringsArray[0]].toString && d[fieldStringsArray[0]].toString();
const len = str ? str.length : 0;
maxLetterLen = len > maxLetterLen ? len : maxLetterLen;
});
const resWidth = Math.min((maxLetterLen * letterWidth) + spacing, maxWidth);
return resWidth;
}

render() {
if (!this.props.tableConfig.fields || this.props.tableConfig.fields.length === 0) {
return null;
}

// build column configs for root table first
const rootColumnsConfig = this.props.tableConfig.fields.map((field) => {
const tempColumnConfig = this.buildColumnConfig(field, false, false);
Expand Down Expand Up @@ -368,7 +408,7 @@ class ExplorerTable extends React.Component {
<ReactTable
columns={rootColumnsConfig}
manual
data={(this.props.isLocked || !this.props.rawData) ? [] : this.props.rawData}
data={(this.props.isLocked || !this.state.tableData) ? [] : this.state.tableData}
showPageSizeOptions={!this.props.isLocked}
pages={(this.props.isLocked) ? 0 : visiblePages} // Total number of pages, don't show 10000+ records in table
loading={this.state.loading}
Expand Down
1 change: 1 addition & 0 deletions src/GuppyDataExplorer/ExplorerVisualization/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { checkForAnySelectedUnaccessibleField } from '../GuppyDataExplorerHelper
import './ExplorerVisualization.css';
import { labelToPlural } from '../utils';


class ExplorerVisualization extends React.Component {
constructor(props) {
super(props);
Expand Down