Skip to content

Commit

Permalink
Merge pull request #103 from KPMP/develop
Browse files Browse the repository at this point in the history
Release v1.3
  • Loading branch information
rlreamy authored Mar 26, 2024
2 parents 5cfcfbe + 10441ed commit d8507a0
Show file tree
Hide file tree
Showing 15 changed files with 252 additions and 165 deletions.
3 changes: 2 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
REACT_APP_SEARCH_KEY=
REACT_APP_SEARCH_ENDPOINT="/spatial-viewer/search"
REACT_APP_SEARCH_ENDPOINT="/spatial-viewer/search"
REACT_APP_FILE_ENDPOINT=
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hydra-web",
"version": "1.0.0",
"version": "1.3.0",
"private": true,
"homepage": "/repository",
"baseURL": "/repository",
Expand All @@ -25,7 +25,7 @@
"history": "5.1.0",
"immutability-helper": "3.1.1",
"isomorphic-unfetch": "3.1.0",
"kpmp-common-components": "1.2.12",
"kpmp-common-components": "1.2.13",
"kpmp-common-styles": "1.0.13",
"npm-run-all": "4.1.5",
"pretty-bytes": "6.0.0",
Expand Down
14 changes: 12 additions & 2 deletions src/actions/Experimental/experimentalDatasetAction.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import actionNames from '../actionNames'
import {fetchParticipantExperimentCounts} from "../../helpers/Api";
import {fetchParticipantExperimentStrategyFileCounts} from "../../helpers/Api";


export const setSelectedParticipant = (participant_id) => {
return {
type: actionNames.SET_SELECTED_PARTICIPANT,
payload: participant_id
}
}

export const fetchAndSetExperimentalDataCounts = (participant_id) => {
return async (dispatch) => {
let experimentalDataCounts = await fetchParticipantExperimentCounts(participant_id);
let experimentalDataCounts = await fetchParticipantExperimentStrategyFileCounts(participant_id);
dispatch(setExperimentalDataCounts(experimentalDataCounts));
}
}
Expand All @@ -13,5 +21,7 @@ export const setExperimentalDataCounts = (experimentalDataCounts) => {
type: actionNames.SET_EXPERIMENTAL_DATASETS,
payload: experimentalDataCounts
}


}

3 changes: 2 additions & 1 deletion src/actions/actionNames.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ const actionNames = {
SET_CLINICAL_DATASETS: 'SET_CLINICAL_DATASETS',
SET_EXPERIMENTAL_DATASETS: 'SET_EXPERIMENTAL_DATASETS',
SET_DATA_TYPE_COUNTS: 'SET_DATA_TYPE_COUNTS',
SET_TOTAL_FILE_COUNT: 'SET_TOTAL_FILE_COUNT'
SET_TOTAL_FILE_COUNT: 'SET_TOTAL_FILE_COUNT',
SET_SELECTED_PARTICIPANT: 'SET_SELECTED_PARTICIPANT'
};

export default actionNames;
80 changes: 80 additions & 0 deletions src/components/ReportCard/FilesByExperimentType.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import React, {Component} from 'react';
import { Grid, TableFixedColumns, TableHeaderRow, Table} from '@devexpress/dx-react-grid-bootstrap4';
import { Row, Col } from 'reactstrap';

class FilesByExperimentType extends Component {

constructor(props) {
super(props);
this.getColumns = this.getColumns.bind(this);
}

handleEmptyCounts(count, row){
return count === 0 ? "0" : this.formatDataTypeValueCell(count, row)
}

handleDataTypeValueClick(row) {
let linkType = row.linkInformation.linkType;
let linkValue = row.linkInformation.linkValue.replace('&', '%26');
let mapping = `/repository/?size=n_20_n&filters[0][field]=redcap_id&filters[0][values][0]=${this.props.participantId}&filters[0][type]=any&filters[1][field]=${linkType}&filters[1][values][0]=${linkValue}&filters[1][type]=any`;
if(linkType && linkValue){
return encodeURI(mapping).replace('%2526', '%26');
} else {
this.props.history.push('/oops');
throw new Error('Datatype not found', row.dataType)
}
}

formatDataTypeValueCell(value, row) {
return (
<a href={`${this.handleDataTypeValueClick(row)}`}>
<span className="buttonhref">
{value}
</span>
</a>
);
}


getColumnExtensions() {

return [
{ columnName: 'dataType', width: 'auto'},
{ columnName: 'count', width: 'auto', align: 'center'},
]
}

getColumns() {
return [
{
title: <span className="table-header omics data-type-table-header">Experimental Strategies</span>,
name: 'dataType',
getCellValue: row => <div className='data-type-table-content' style={{'flex': '250 0 auto'}} role='gridcell'>{row.dataType}</div>

},
{
title: <span className="data-type-table-header">Files</span>,
name: 'count',
getCellValue: row => <div className='rt-td data-type-table-content' style={{'flex': '250 0 auto','textAlign': 'center'}} role='gridcell'>{this.handleEmptyCounts(row.count, row)}</div>
}
]
}

render() {
return (
<article id='summary-plot'>
<Row className='mt-4'>
<Col xs='12'>
<Grid rows={this.props.experimentalDataCounts} columns={this.getColumns()}>
<Table columnExtensions={this.getColumnExtensions()}/>
<TableHeaderRow/>
<TableFixedColumns/>
</Grid>
</Col>
</Row>
</article>
);
}
}

export default FilesByExperimentType;
202 changes: 80 additions & 122 deletions src/components/ReportCard/ReportCard.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { Component } from 'react';
import { Col, Container, Row } from "reactstrap";
import '@devexpress/dx-react-grid-bootstrap4/dist/dx-react-grid-bootstrap4.css';
import { Grid, Table, TableColumnResizing, TableHeaderRow } from '@devexpress/dx-react-grid-bootstrap4';
import { Grid, Table, TableColumnResizing } from '@devexpress/dx-react-grid-bootstrap4';
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faFile } from '@fortawesome/free-regular-svg-icons';
import { dataToTableConverter, experimentalDataConverter, fileCountsToTableConverter, mapClinicalKeysToPresentationStyle } from '../../helpers/dataHelper';
import { dataToTableConverter, fileCountsToTableConverter, mapClinicalKeysToPresentationStyle } from '../../helpers/dataHelper';
import { handleGoogleAnalyticsEvent } from '../../helpers/googleAnalyticsHelper';
import FilesByExperimentType from './FilesByExperimentType';

class ReportCard extends Component {
constructor(props) {
Expand All @@ -30,6 +31,7 @@ class ReportCard extends Component {
dataTypeFileCounts: sessionStorage['dataTypeFileCounts']['repositoryDataTypes'],
clinicalDataset: (sessionStorage['clinicalDatasets']['clinicalData']) ? JSON.parse(sessionStorage['clinicalDatasets']['clinicalData']) : {},
totalFileCount: sessionStorage['totalFileCount'],
participantId: sessionStorage['selectedParticipant'],
isLoaded: true
})
handleGoogleAnalyticsEvent("Repository", "Navigation", "Participant Information");
Expand Down Expand Up @@ -72,131 +74,87 @@ class ReportCard extends Component {
];
};

formatLinkableCellKey = (row) => {
let key = row['key'];
return( key )
}

formatLinkableCellValue = (row) => {
let link = '/'
if (row.tool === 'spatial-viewer') {
link = '/' + row.tool + '?filters[0][field]=datatype&filters[0][values][0]=' + row.key + '&filters[0][type]=any&filters[1][field]=redcapid&filters[1][values][0]=' + this.state.summaryDataset['Participant ID'] + '&filters[1][type]=any'
} else if (row.tool === 'explorer') {
link += row.tool;
if (row.key.includes('Single-cell')) {
link += '/dataViz?dataType=sc';
} else if (row.key.includes('Single-nuc')) {
link += '/dataViz?dataType=sn';
} else if (row.key.includes('Regional transcriptomics')) {
link +='/regionalviz?dataType=rt';
} else if (row.key.includes('Regional proteomics')) {
link +='/regionalpro?dataType=rp';
}
}

return (row['value'] > 0 ? <a className="p-0" href={link}>{row['value']}</a> : <span>{row['value']}</span>)
}

getExperimentalLinkableColumns = () => {
return [
{
name: 'Experimental Strategies',
sortable: false,
hideable: false,
defaultHidden: false,
getCellValue: row => this.formatLinkableCellKey(row)
},
{
name: 'Files',
sortable: false,
hideable: false,
defaultHidden: false,
getCellValue: row => <div style={{ textAlign: 'right' }}>{this.formatLinkableCellValue(row)}</div>
}
];
};

getRowSets = (dataset) => {
return experimentalDataConverter(dataset)
}

getRows = (dataset) => {
return dataToTableConverter(dataset)
}

render() {
return (
<div className='report-card ms-5 me-5'>
<Row className='pt-2'>
<Col className='report-col col-sm-12 col-md-8 col-lg-10'>
<Container className='container-max landing mb-4 rounded border p-3 pt-2 shadow-sm'>
<div className='report-header mb-3'>
Participant Summary
</div>
<Grid rows={this.getRows(this.state.summaryDataset)} columns={this.getColumns()}>
<Table />
<TableColumnResizing defaultColumnWidths={this.getDefaultColumnWidths()} />
</Grid>
</Container>
</Col>
<Col className='report-col col-sm-12 col-md-4 col-lg-2'>
<Container className='container-max landing mb-4 rounded border px-3 pt-2 shadow-sm'>
<Row>
<Col className=''>
Files
<div id='file-count'>
<a href={this.getTotalFileCountLink()}>{this.state.totalFileCount['count']}</a>
</div>
</Col>
<Col className='text-end align-bottom' id='file-icon'>
<FontAwesomeIcon
className="fas fa-file fa-light" icon={faFile} />
</Col>
</Row>
</Container>
</Col>
</Row>
<Row className=''>
<Col className='report-col col-sm-12 col-md-12 col-lg-6'>
<Container className='container-max landing mb-4 rounded border p-3 pt-2 shadow-sm' style={{ height: 'fit-content' }}>
<div className='report-header'>
File Counts by Data Type
</div>
<Grid rows={fileCountsToTableConverter(this.state.dataTypeFileCounts, this.state.summaryDataset['Participant ID'])} columns={this.getColumns()}>
<Table />
</Grid>
</Container>
</Col>
<Col className='report-col col-sm-12 col-md-12 col-lg-6'>
<Container className='container-max landing mb-4 rounded border p-3 pt-2 shadow-sm' style={{ height: 'fit-content' }}>
<div className='report-header'>
File Counts by Experimental Strategy
</div>
<Grid rows={this.getRowSets(this.state.experimentalDataCounts)} columns={this.getExperimentalLinkableColumns()}>
<Table columnExtensions={[{ columnName: 'Files', align: 'right' }]} />
<TableHeaderRow />
</Grid>
</Container>
</Col>
</Row>
<Row className=''>
<Col className='report-col col-12'>
<Container className='container-max landing mb-4 rounded border p-3 pt-2 shadow-sm' style={{ height: 'fit-content' }}>
<div className='report-header'>
Clinical
</div>
<Grid rows={this.getRows(mapClinicalKeysToPresentationStyle(this.state.clinicalDataset))} columns={this.getColumns()}>
<Table />
<TableColumnResizing defaultColumnWidths={[
{ columnName: 'key', width: 350 },
{ columnName: 'value', width: 500 },
]} />
</Grid>
</Container>
</Col>
</Row>
</div>
)
if (this.state.isLoaded) {
return (

<div className='report-card ms-5 me-5'>
<Row className='pt-2'>
<Col className='report-col col-sm-12 col-md-8 col-lg-10'>
<Container className='container-max landing mb-4 rounded border p-3 pt-2 shadow-sm'>
<div className='report-header mb-3'>
Participant Summary
</div>
<Grid rows={this.getRows(this.state.summaryDataset)} columns={this.getColumns()}>
<Table />
<TableColumnResizing defaultColumnWidths={this.getDefaultColumnWidths()} />
</Grid>
</Container>
</Col>
<Col className='report-col col-sm-12 col-md-4 col-lg-2'>
<Container className='container-max landing mb-4 rounded border px-3 pt-2 shadow-sm'>
<Row>
<Col className=''>
Files
<div id='file-count'>
<a href={this.getTotalFileCountLink()}>{this.state.totalFileCount['count']}</a>
</div>
</Col>
<Col className='text-end align-bottom' id='file-icon'>
<FontAwesomeIcon
className="fas fa-file fa-light" icon={faFile} />
</Col>
</Row>
</Container>
</Col>
</Row>
<Row className=''>
<Col className='report-col col-sm-12 col-md-12 col-lg-6'>
<Container className='container-max landing mb-4 rounded border p-3 pt-2 shadow-sm' style={{ height: 'fit-content' }}>
<div className='report-header'>
File Counts by Data Type
</div>
<Grid rows={fileCountsToTableConverter(this.state.dataTypeFileCounts, this.state.summaryDataset['Participant ID'])} columns={this.getColumns()}>
<Table />
</Grid>
</Container>
</Col>
<Col className='report-col col-sm-12 col-md-12 col-lg-6'>
<Container className='container-max landing mb-4 rounded border p-3 pt-2 shadow-sm' style={{ height: 'fit-content' }}>
<div className='report-header'>
File Counts by Experimental Strategy
</div>
<FilesByExperimentType experimentalDataCounts={this.state.experimentalDataCounts} participantId={this.state.participantId}/>
</Container>
</Col>
</Row>
<Row className=''>
<Col className='report-col col-12'>
<Container className='container-max landing mb-4 rounded border p-3 pt-2 shadow-sm' style={{ height: 'fit-content' }}>
<div className='report-header'>
Clinical
</div>
<Grid rows={this.getRows(mapClinicalKeysToPresentationStyle(this.state.clinicalDataset))} columns={this.getColumns()}>
<Table />
<TableColumnResizing defaultColumnWidths={[
{ columnName: 'key', width: 350 },
{ columnName: 'value', width: 500 },
]} />
</Grid>
</Container>
</Col>
</Row>
</div>
)

}
else {
return "Loading";
}
}
}

Expand Down
Loading

0 comments on commit d8507a0

Please sign in to comment.