Skip to content

Commit

Permalink
Merge pull request #2045 from kids-first/dev
Browse files Browse the repository at this point in the history
Prepare Release v2.8.0
  • Loading branch information
Jeremy Costanza authored Aug 28, 2019
2 parents 65a03b1 + 5d133e4 commit 3484128
Show file tree
Hide file tree
Showing 10 changed files with 187 additions and 166 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ yarn-error.log*
yarn.lock

.vscode/launch.json
.vscode/extensions.json

.cache/

Expand Down
10 changes: 10 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ Data fix, introduced 2019-08-08

## 2019-08-05 kf-portal-ui 2.7.0

This release introduces bug fixes.

### Bug fixes

- [#2020](https://github.com/kids-first/kf-portal-ui/issues/2020) Cohort Builder: MONDO link doesn't appear in the table view on the cohort builder
- [#1961](https://github.com/kids-first/kf-portal-ui/issues/1961) Open access files should be accessible for everyone
- [#2025](https://github.com/kids-first/kf-portal-ui/issues/2025) Participant entity page: Don't display the sequencing data table if empty

## 2019-08-05 kf-portal-ui 2.7.0

This release concentrates on renaming the studies and adding the participant entity page, including family and phenotype data. The format of family and phenotype data has been corrected in the ETL as part of that effort.

It also introduces improvements and bug fixes.
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "kf-portal-ui",
"version": "2.7.0",
"version": "2.8.0",
"private": true,
"dependencies": {
"@kfarranger/admin-ui": "~1.3.1",
Expand Down Expand Up @@ -186,4 +186,4 @@
"eslintConfig": {
"extends": "react-app"
}
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import { compose, withState } from 'recompose';
import { css } from 'emotion';
import { withTheme } from 'emotion-theming';

import FileIcon from 'icons/FileIcon';
import ControlledDataTable from 'uikit/DataTable/ControlledDataTable';
import { Link } from 'uikit/Core';
import {
Expand All @@ -17,29 +14,27 @@ import ColumnFilter from 'uikit/DataTable/ToolbarButtons/ColumnFilter';
import Export from 'uikit/DataTable/ToolbarButtons/Export';
import { trackUserInteraction } from 'services/analyticsTracking';
import { configureCols } from 'uikit/DataTable/utils/columns';
// import RemoveFromCohortButton from './RemoveFromCohortButton';

import DownloadButton from 'components/FileRepo/DownloadButton';
import { arrangerProjectId } from 'common/injectGlobals';
import { SORTABLE_FIELDS_MAPPING } from './queries';
import { css } from 'emotion';
import FileIcon from 'icons/FileIcon';
import { union, compact } from 'lodash';
import {MONDOLink} from '../../Utils/DiagnosisAndPhenotypeLinks'
import { MONDOLink } from '../../Utils/DiagnosisAndPhenotypeLinks';

const SelectionCell = ({ value: checked, onCellSelected, row }) => {
if (row === undefined) {
// header row
return (
<input
type="checkbox"
checked={!!checked}
onChange={evt => {
onCellSelected(evt.currentTarget.checked);
}}
/>
);
}
return (
<input type="checkbox" checked={!!checked} onChange={() => onCellSelected(!checked, row)} />
<input
type="checkbox"
checked={!!checked}
onChange={
row
? () => onCellSelected(!checked, row)
: evt => {
onCellSelected(evt.currentTarget.checked);
}
}
/>
);
};

Expand All @@ -50,50 +45,51 @@ const rowCss = css({
alignContent: 'stretch',
});

const isMondo = datum => typeof datum === 'string' && datum.includes('MONDO');

const enhance = compose(withState('collapsed', 'setCollapsed', true));

const CollapsibleMultiLineCell = enhance(({ value: data, collapsed, setCollapsed }) => {
// Display one row when there is exactly more than one row.
// Collapsing a single don't save any space.
const sortedData = union(data);
const cleanedData = compact(data);
const displayedRowCount = collapsed ? 1 : cleanedData.length;
const displayMoreButton = compact(sortedData).length > 1;
let isMondo = false
if(typeof(sortedData[0])==="string"){
isMondo =sortedData[0].includes("MONDO")
}
const cleanedUniquifiedData = compact(union(data));

const sizeOfCleanData = cleanedUniquifiedData.length;

const displayedRowCount = collapsed ? 1 : sizeOfCleanData;
const displayMoreButton = sizeOfCleanData > 1;
const hasManyValues = sizeOfCleanData > 1;

return (
<div className={`${rowCss}`}>
<div style={{ flex: '4' }}>
{compact(sortedData).length <= 1
? compact(sortedData)
.slice(0, displayedRowCount)
.map((datum, index) => (
isMondo ? <MONDOLink mondo={datum}/> :
<div key={index}>
{datum === null
? '\u00A0' /* unbreakable space to avoid empty rows from collapsing in height */
: datum}
</div>
))
: cleanedData
.slice(0, displayedRowCount)
.map((datum, index) => (
isMondo ? <MONDOLink mondo={datum}/> : <div key={index}>&#8226; {datum === null ? '\u00A0' : datum}</div>
))}
<div style={{ display: 'flex', flexDirection: 'column', flex: '4' }}>
{cleanedUniquifiedData.slice(0, displayedRowCount).map((datum, index) => {
if (isMondo(datum)) {
return <MONDOLink key={index} mondo={datum} />;
} else {
return (
<div key={index}>
{hasManyValues && '\u2022'}
{datum === null
? '\u00A0' /* unbreakable space to avoid empty rows from collapsing in height */
: datum}
</div>
);
}
})}
</div>
{displayMoreButton ? (
{displayMoreButton && (
<div
style={{ flex: '1', marginTop: '-8px ' }}
onClick={() => {
setCollapsed(!collapsed);
}}
>
<div className={`showMore-wrapper ${collapsed ? 'more' : 'less'}`}>
{collapsed ? `${cleanedData.length - displayedRowCount} ` : ''}
{collapsed ? `${sizeOfCleanData - displayedRowCount} ` : ''}
</div>
</div>
) : null}
)}
</div>
);
});
Expand Down Expand Up @@ -136,12 +132,8 @@ const NbFilesCell = compose(
);

const ParticipantIdLink = compose(
withTheme(({ value: idParticipant, row, theme }) => {
return (
<Link to={`/participant/${idParticipant}#summary`}>
{`${idParticipant}`}
</Link>
);
withTheme(({ value: idParticipant }) => {
return <Link to={`/participant/${idParticipant}#summary`}>{`${idParticipant}`}</Link>;
}),
);

Expand All @@ -156,17 +148,21 @@ const participantsTableViewColumns = (onRowSelected, onAllRowsSelected, dirtyHac
/>
);
},
Cell: props => <SelectionCell {...props} onCellSelected={onRowSelected} />,
Cell: props => {
return <SelectionCell value={props.value} row={props.row} onCellSelected={onRowSelected} />;
},
accessor: 'selected',
filterable: false,
sortable: false,
skipExport: true,
resizable: false,
minWidth: 33,
},
{ Header: 'Participant ID',
{
Header: 'Participant ID',
accessor: 'participantId',
Cell: props => <ParticipantIdLink {...props}/>},
Cell: props => <ParticipantIdLink value={props.value} />,
},
{
Header: 'Study Name',
accessor: 'studyName',
Expand All @@ -177,22 +173,40 @@ const participantsTableViewColumns = (onRowSelected, onAllRowsSelected, dirtyHac
{
Header: 'Diagnosis Category',
accessor: 'diagnosisCategories',
Cell: props => <CollapsibleMultiLineCell {...props} />,
Cell: props => (
<CollapsibleMultiLineCell
value={props.value}
collapsed={props.collapsed}
setCollapsed={props.setCollapsed}
/>
),
field: 'diagnoses.diagnosis_category',
sortable: false,
},
{
Header: 'Diagnosis (Mondo)',
accessor: 'diagnosisMondo',
Cell: props => <CollapsibleMultiLineCell {...props} />,
Cell: props => (
<CollapsibleMultiLineCell
value={props.value}
collapsed={props.collapsed}
setCollapsed={props.setCollapsed}
/>
),
field: 'diagnoses.mondo_id_diagnosis',
minWidth: 175,
sortable: false,
},
{
Header: 'Age at Diagnosis (days)',
accessor: 'ageAtDiagnosis',
Cell: props => <CollapsibleMultiLineCell {...props} />,
Cell: props => (
<CollapsibleMultiLineCell
value={props.value}
collapsed={props.collapsed}
setCollapsed={props.setCollapsed}
/>
),
field: 'diagnoses.age_at_event_days',
sortable: false,
},
Expand All @@ -201,14 +215,20 @@ const participantsTableViewColumns = (onRowSelected, onAllRowsSelected, dirtyHac
{
Header: 'Family Composition',
accessor: 'familyCompositions',
Cell: props => <CollapsibleMultiLineCell {...props} />,
Cell: props => (
<CollapsibleMultiLineCell
value={props.value}
collapsed={props.collapsed}
setCollapsed={props.setCollapsed}
/>
),
field: 'family.family_compositions',
sortable: false,
},
{
Header: 'Files',
accessor: 'filesCount',
Cell: props => <NbFilesCell {...props} />,
Cell: props => <NbFilesCell value={props.value} row={props.row} />,
field: 'files',
sortable: false,
},
Expand Down
43 changes: 30 additions & 13 deletions src/components/EntityPage/Participant/ParticipantSummary.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,16 @@ function specimenSummaryTableData(specimen) {

const ParticipantSummary = ({ participant }) => {
const specimens = get(participant, 'biospecimens.hits.edges', []);
const hasFile = get(participant, 'files.hits.edges', [] ).length === 0 ? false : true
let wrongTypes = ['Aligned Reads', 'gVCF', 'Unaligned Reads', 'Variant Calls'];

let hasSequencingData = false
for(const i in get(participant, 'files.hits.edges', [] )){
if(wrongTypes.includes(get(participant, 'files.hits.edges', [] )[i].node.data_type)){
hasSequencingData =true
break
}
}

return (
<React.Fragment>
Expand Down Expand Up @@ -186,19 +196,26 @@ const ParticipantSummary = ({ participant }) => {
</div>
}

<EntityContentDivider />
<EntityContentSection title="Available Data Files" size={'big'}>
<EntityContentSection title="Sequencing Data" size={'small'}>
<SequencingDataTable
files={get(participant, 'files.hits.edges', [])}
participantID={participant.kf_id}
/>
</EntityContentSection>
<OtherDataTypesSummaryTable
files={get(participant, 'files.hits.edges', [])}
participantID={participant.kf_id}
/>
</EntityContentSection>

{
hasFile ?
<div>
<EntityContentDivider />
<EntityContentSection title="Available Data Files" size={'big'}>
{
hasSequencingData ?
<EntityContentSection title="Sequencing Data" size={'small'}>
<SequencingDataTable files={get(participant, 'files.hits.edges', [])} participantID={participant.kf_id}/>
</EntityContentSection> : ""
}
<OtherDataTypesSummaryTable
files={get(participant, 'files.hits.edges', [])}
participantID={participant.kf_id}
hasSequencingData = {hasSequencingData}
/>
</EntityContentSection>
</div>: ""
}
</React.Fragment>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as React from 'react';
import { EntityContentSection } from '../../index';
import sanitizeURL from './sanitizeURL';

const OtherDataTypesSummaryTable = ({ files, participantID }) => {
const OtherDataTypesSummaryTable = ({ files, participantID , hasSequencingData}) => {
//"Other" being "not sequencing data"...
let wrongTypes = new Set(['Aligned Reads', 'gVCF', 'Unaligned Reads', 'Variant Calls']);

Expand All @@ -13,7 +13,6 @@ const OtherDataTypesSummaryTable = ({ files, participantID }) => {
//for every file
const file = fileTemp.node;
const type = file.data_type;

if (!wrongTypes.has(type)) {
//if they're the right type
let row = arr.find(ele => ele.title === type); //find its row to increment the number of files
Expand Down Expand Up @@ -61,7 +60,7 @@ const OtherDataTypesSummaryTable = ({ files, participantID }) => {
return arr.length === 0 ? (
''
) : (
<EntityContentSection title="Other Data Types" size={'small'}>
<EntityContentSection title={hasSequencingData ? "Other Data Types" : "Data Types"} size={'small'}>
<div style={{display: "flex", flexWrap: "wrap", justifyContent: "space-between"}}>
{arr.map( (thing, i) => {
return (
Expand Down
2 changes: 1 addition & 1 deletion src/components/FileRepo/CustomColumns/ActionsColumn.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ const ActionsColumn = ({ value, api, theme, fenceAcls }) => (
const file = get(data, 'file.hits.edges[0].node', {});
const acl = file.acl || [];
const repository = file.repository;
const hasAccess = intersection(fenceAcls, acl).length > 0;
const hasAccess = acl.includes('*') || intersection(fenceAcls, acl).length > 0;
return (
<Row center height={'100%'}>
{loadingQuery ? (
Expand Down
Loading

0 comments on commit 3484128

Please sign in to comment.