Skip to content

Commit

Permalink
Feat/combine gwas workflow attrition table styling and setup (#1129)
Browse files Browse the repository at this point in the history
* Feat/combine gwas workflow progress bar (#1125)

* Update node js and fix failing unit tests (#1119)

* fixed unhandled promise rejection

...which fixes locally failing jest test

* fix failing unit test for UserProfile

* udpate node js and npm for CI tests

* make test a bit more specific

* set node js to 16.x

* update node js to 16.x and npm to 8.15 in Dockerfile

* revert npm version change

* feat(CombineGWASWorkflowProgressBar): Initial commit

* feat(CombineGWASWorkflowProgressBar): created partially working prototype

* feat(CombineGWASWorkflowProgressBar): added logic for displaying select or edit for each step

* feat(CombineGWASWorkflowProgressBar): created CSS style sheet for new component and began overriding AntD styles to match design

* feat(CombineGWASWorkflowProgressBar): fixed colors to match design for numeric icons

* feat(CombineGWASWorkflowProgressBar): set width to container to 100%

* feat(CombineGWASWorkflowProgressBar): added animation

* feat(CombineGWASWorkflowProgressBar): added styles for Get Started button

* feat(CombineGWASWorkflowProgressBar): positioned get started button

* feat(CombineGWASWorkflowProgressBar): removed inline styles from ProgressBar.jsx

* feat(CombineGWASWorkflowProgressBar): formatted GWASContainer.jsx

* feat(CombineGWASWorkflowProgressBar): changed class name to progress-bar

* feat(CombineGWASWorkflowProgressBar): began authoring JEST test

* feat(CombineGWASWorkflowProgressBar): Added clarifying comment to jest test

* feat(CombineGWASWorkflowProgressBar): Formatted test code

* feat(CombineGWASWorkflowProgressBar): Added Story Book for ProgressBar

* feat(CombineGWASWorkflowProgressBar): ran eslint on ProgressBar.test.jsx

* feat(CombineGWASWorkflowProgressBar): ran autoformatters eslint and stylelint

* feat(CombineGWASWorkflowProgressBar): Resolved style lint error in ProgressBar.css

* feat(CombineGWASWorkflowProgressBar): Resolved remaining style lint errors in ProgressBar.css

* feat(CombineGWASWorkflowProgressBar): reverted unintentionally changed file

* feat(CombineGWASWorkflowProgressBar): reverted unintentionally changed file

* feat(CombineGWASWorkflowProgressBar): reverted unintentionally changed file

* feat(CombineGWASWorkflowProgressBar): reverted unintentionally changed file Dockerfile

* feat(CombineGWASWorkflowProgressBar): reverted unintentionally changed file Submission/MapDataModel.jsx

* feat(CombineGWASWorkflowProgressBar): reverted unintentionally changed file UserProfile/UserProfile.test.jsx

* feat(CombineGWASWorkflowProgressBar): reverted unintentionally changed file again  UserProfile/UserProfile.test.jsx

* feat(CombineGWASWorkflowProgressBar): Ran ESLINT fix

* feat(CombineGWASWorkflowProgressBar): Refactored code to use a constants file to make code more DRY

* feat(CombineGWASWorkflowProgressBar): Ran ESLINT on recently updated files

* feat(CombineGWASWorkflowProgressBar): Ran ESLINT on recently updated files

* feat(CombineGWASWorkflowProgressBar): Added media query so that button will not overlap progress bar on smaller screens

* feat(CombineGWASWorkflowProgressBar): Formatted CSS with line break

* feat(CombineGWASWorkflowProgressBar): Updated JEST test to use for loops

* feat(CombineGWASWorkflowProgressBar): Updated GWASContainer.jsx to use nextButtonEnabled boolean for disabling or enabling next button

* feat(CombineGWASWorkflowProgressBar): Ran eslint on  GWASContainer.jsx

Co-authored-by: pieterlukasse <pieterlukasse@gmail.com>

* feat(CombineGWASWorkflowAttritionTable): Initial Commit, not working yet

* feat(CombineGWASWorkflowAttritionTable): Added eslint-new command to this branch

* feat(CombineGWASWorkflowProgressBar): Updated file references in AttritionTable imports

* feat(CombineGWASWorkflowProgressBar): Created partially working prototype (shows some data, no headers, has js errors)

* feat(CombineGWASWorkflowAttritionTable): Added table header obj to constants.js

* feat(CombineGWASWorkflowAttritionTable): Added table headerDataSource obj to constants and ran eslint-new

* feat(CombineGWASWorkflowAttritionTable): updated tableHeader in GWASContainer.jsx

* feat(CombineGWASWorkflowAttritionTable): began styling table

* feat(CombineGWASWorkflowAttritionTable): made alternating table rows different colors

* feat(CombineGWASWorkflowAttritionTable): added table borders

* feat(CombineGWASWorkflowAttritionTable): ran stylelint

* feat(CombineGWASWorkflowAttritionTable): created ChartIcons directory and refactored to use more semantic HTML

* feat(CombineGWASWorkflowAttritionTable): added SVG icons

* feat(CombineGWASWorkflowAttritionTable): Updated dropdown icon styling

* feat(CombineGWASWorkflowAttritionTable): Removed unneeded files and updated padding on table

* feat(CombineGWASWorkflowAttritionTable): Reset files unrelated to this ticket

* feat(CombineGWASWorkflowAttritionTable): Updated dropdown button styles

* feat(CombineGWASWorkflowAttritionTable): Updated attrition table logic, styles and storybook to not use antD list component, to avoid injection of non-tabular elements in table element

* feat(CombineGWASWorkflowAttritionTable): Converted inline styles to class names

* feat(CombineGWASWorkflowAttritionTable): Updated padding left class to 26px

* feat(CombineGWASWorkflowAttritionTable): Ran eslint-new on branch and fixed errors

* feat(CombineGWASWorkflowAttritionTable): Ran stylelint on branch and fixed errors

* feat(CombineGWASWorkflowAttritionTable): Reverted unintentionally changed ProgressBar.test.jsx file

* feat(CombineGWASWorkflowsAttritionTable): Made SVG more accessible

* feat(CombineGWASWorkflowAttritionTable): Changed title elements to desc to avoid hover effect in browser - additional accessible text will be added once chart fires modal

* feat(CombineGWASWorkflowAttritionTable): Removed inline comments in AttritionTableRow.jsx, they've been logged in a ticket instead

* feat(CombineGWASWorkflowAttritionTable): Clarified comment in AttritionTableRow.jsx

* feat(CombineGWASWorkflowAttritionTable): Made CSS consistent for colors in AttritionTable.css

* feat(CombineGWASWorkflowAttritionTable): Created new CSS rule to make stylesheet more DRY

* feat(CombineGWASWorkflowsAttritionTable): Cleaned up JS formating in AttritionTable.jsx

Co-authored-by: pieterlukasse <pieterlukasse@gmail.com>
  • Loading branch information
jarvisraymond-uchicago and pieterlukasse authored Oct 28, 2022
1 parent a0e397e commit 278e0d3
Show file tree
Hide file tree
Showing 9 changed files with 597 additions and 22 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@
"schema": "node ./data/getSchema",
"params": "node ./data/getTexts > src/params.js",
"eslint": "./node_modules/.bin/eslint --ext js --ext jsx --ext ts --ext tsx --ignore-pattern '**/__generated__/**' --ignore-pattern '**/*.min.js' --ignore-pattern '**/setupJest.js' --ignore-pattern '**/gqlHelper.js' --ignore-pattern '**/formHooks.jsx' --ignore-pattern '**/*.stories.jsx' --fix src data",
"eslint-new": "./node_modules/.bin/eslint --ext js --ext jsx --ext ts --ext tsx --ignore-pattern '**/__generated__/**' --ignore-pattern '**/*.min.js' --ignore-pattern '**/setupJest.js' --ignore-pattern '**/gqlHelper.js' --ignore-pattern '**/formHooks.jsx' --ignore-pattern '**/*.json' --ignore-pattern '**/Dockerfile' --ignore-pattern '**/*.png' --ignore-pattern '**/*.ico' --ignore-pattern '**/*.stories.jsx' --ignore-pattern '**/*.md' --ignore-pattern '**/*.yml' --quiet --fix $(git diff --name-only master | xargs)",
"eslint-new": "./node_modules/.bin/eslint --ext js --ext jsx --ext ts --ext tsx --ignore-pattern '**/__generated__/**' --ignore-pattern '**/*.min.js' --ignore-pattern '**/setupJest.js' --ignore-pattern '**/gqlHelper.js' --ignore-pattern '**/formHooks.jsx' --ignore-pattern '**/*.json' --ignore-pattern '**/Dockerfile' --ignore-pattern '**/*.png' --ignore-pattern '**/*.ico' --ignore-pattern '**/*.stories.jsx' --ignore-pattern '**/*.css' --ignore-pattern '**/*.md' --ignore-pattern '**/*.yml' --quiet --fix $(git diff --name-only master | xargs)",
"elint": "./node_modules/.bin/eslint --ext js --ext jsx --ext ts --ext tsx --ignore-pattern '**/__generated__/**' --ignore-pattern '**/*.min.js' --ignore-pattern '**/setupJest.js'",
"storybook": "start-storybook -p 6006 -s .storybook/public",
"stylelint": "stylelint 'src/**/*.less' 'src/**/*.css' --config .stylelintrc.js --fix",
Expand Down
29 changes: 29 additions & 0 deletions src/Analysis/GWASV2/GWASContainer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,22 @@ import React, { useState } from 'react';
import { Space, Button, Popconfirm } from 'antd';
import SelectStudyPopulation from './SelectStudyPopulation/SelectStudyPopulation';
import ProgressBar from './Shared/ProgressBar/ProgressBar';
import AttritionTable from './Shared/AttritionTable/AttritionTable';
import { useSourceFetch } from './Shared/wizardEndpoints/cohortMiddlewareApi';
import { gwasV2Steps } from './Shared/constants';
import './GWASV2.css';

const GWASContainer = () => {
const { loading, sourceId } = useSourceFetch();
const [current, setCurrent] = useState(0);
const [
selectedStudyPopulationCohort,
setSelectedStudyPopulationCohort,
] = useState({});
const [selectedControlCohort] = useState(undefined);
const [selectedCaseCohort] = useState(undefined);
const [selectedCovariates] = useState([]);
const [selectedDichotomousCovariates] = useState([]);

const generateStep = () => {
// steps 2 & 3 very similar
Expand Down Expand Up @@ -50,6 +57,28 @@ const GWASContainer = () => {
return (
<React.Fragment>
<ProgressBar current={current} />
{!loading && sourceId && (
<React.Fragment>
<AttritionTable
sourceId={sourceId}
selectedCohort={selectedStudyPopulationCohort}
otherSelectedCohort={selectedControlCohort}
// outcome={outcome}
selectedCovariates={selectedCovariates}
selectedDichotomousCovariates={selectedDichotomousCovariates}
tableHeader={'Case Cohort Attrition Table'}
/>
<AttritionTable
sourceId={sourceId}
selectedCohort={selectedControlCohort}
otherSelectedCohort={selectedCaseCohort}
// outcome={outcome}
selectedCovariates={selectedCovariates}
selectedDichotomousCovariates={selectedDichotomousCovariates}
tableHeader={'Control Cohort Attrition Table'}
/>
</React.Fragment>
)}
{/* Inline style block needed so centering rule doesn't impact other workflows */}
<style>
{'.analysis-app__actions > div:nth-child(1) { width: 100%; }'}
Expand Down
90 changes: 90 additions & 0 deletions src/Analysis/GWASV2/Shared/AttritionTable/AttritionTable.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
.gwasv2-attrition-table .ant-collapse-header {
background: #cfdbe6;
}

.gwasv2-attrition-table .ant-collapse-content-box {
padding: 0;
}

.gwasv2-attrition-table .ant-collapse-expand-icon svg {
display: none;
}

.gwasv2-attrition-table .ant-collapse-expand-icon {
background: #2e77b8;
border-radius: 16px;
color: white;
height: 18px;
width: 18px;
margin: 3px 10px 0;
text-align: center;
}

.gwasv2-attrition-table
.ant-collapse-header
.ant-collapse-expand-icon:before {
content: "\2303";
display: block;
font-size: 16px;
transition: all 0.1s ease-in-out;
margin-top: -1px;
}

.gwasv2-attrition-table
.ant-collapse-header[aria-expanded="true"]
.ant-collapse-expand-icon:before {
margin-top: -1px;
}

.gwasv2-attrition-table
.ant-collapse-header[aria-expanded="false"]
.ant-collapse-expand-icon:before {
transform: rotate(180deg);
transform-origin: 7px 9px;
margin: 1px 2px;
}

.gwasv2-attrition-table table tr {
border-top: 1px solid #e2e2e3;
height: 32px;
}

.gwasv2-attrition-table table
tr:nth-child(2n) {
background-color: #fafafb;
}

.gwasv2-attrition-table table {
width: 100%;
padding: 0 16px;
}

.gwasv2-attrition-table table th,
.gwasv2-attrition-table table td {
text-align: left;
padding: 0 16px;
}

.gwasv2-attrition-table table thead {
background-color: #e9eef2;
height: 40px;
}

.gwasv2-attrition-table table .gwasv2-attrition-table--leftpad {
padding-left: 26px;
}
.gwasv2-attrition-table table .gwasv2-attrition-table--chart {
text-align: center;
}
.gwasv2-attrition-table table .gwasv2-attrition-table--rightborder {
border-right: 2px solid #e2e2e3;
padding-right: 32px;
}

.gwasv2-attrition-table--w5 {
width: 5%;
}

.gwasv2-attrition-table--w15 {
width: 15%;
}
117 changes: 117 additions & 0 deletions src/Analysis/GWASV2/Shared/AttritionTable/AttritionTable.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { Collapse } from 'antd';
import AttritionTableRow from './AttritionTableRow';
import '../../../GWASUIApp/GWASUIApp.css';
import './AttritionTable.css';

const { Panel } = Collapse;

const AttritionTable = ({
selectedCohort,
otherSelectedCohort,
outcome,
selectedCovariates,
selectedDichotomousCovariates,
sourceId,
tableHeader,
}) => {
const [covariateSubsets, setCovariateSubsets] = useState([]);
const getCovariateRow = (selectedCovs = [], selectedCustomdichotomousCovs = []) => {
const subsets = [];
// todo: handle case of deselecting/selecting existing covariates (100% missing?) after adding custom dichotomous
const allCovariates = [...selectedCovs, ...selectedCustomdichotomousCovs];
allCovariates
.slice()
.reverse()
.forEach((covariate, i) => {
subsets.push(
allCovariates
.slice()
.reverse()
.slice(allCovariates.length - i - 1),
);
});
return subsets;
};

useEffect(() => {
setCovariateSubsets(getCovariateRow(selectedCovariates, selectedDichotomousCovariates));
}, [selectedCovariates, selectedDichotomousCovariates]);

return (
<div className='gwasv2-attrition-table'>
<Collapse onClick={(event) => event.stopPropagation()}>
<Panel header={tableHeader} key='2'>
<table>
<thead>
<tr>
<th className='gwasv2-attrition-table--leftpad gwasv2-attrition-table--w15'>
Type
</th>
<th className='gwasv2-attrition-table--w5'>Chart</th>
<th className='gwasv2-attrition-table--w15'>Name</th>
<th className='gwasv2-attrition-table--rightborder
gwasv2-attrition-table--w5'
>Size
</th>
<th className='gwasv2-attrition-table--w15
gwasv2-attrition-table--leftpad'
>Non-Hispanic Black
</th>
<th className='gwasv2-attrition-table--w15'>Non-Hispanic Asian</th>
<th className='gwasv2-attrition-table--w15'>Non-Hispanic White</th>
<th className='gwasv2-attrition-table--w15'>Hispanic</th>
</tr>
</thead>
<tbody>
{selectedCohort?.cohort_definition_id && (
<React.Fragment>
<AttritionTableRow
cohortDefinitionId={selectedCohort.cohort_definition_id}
otherCohortDefinitionId={otherSelectedCohort ? otherSelectedCohort.cohort_definition_id : undefined}
rowType='Cohort'
rowName={selectedCohort.cohort_name}
covariateSubset={[]}
sourceId={sourceId}
/>
</React.Fragment>
)}
{selectedCohort?.cohort_definition_id && covariateSubsets.length > 0 ? (
covariateSubsets.map((item) => (
<AttritionTableRow
key={item}
cohortDefinitionId={selectedCohort.cohort_definition_id}
otherCohortDefinitionId={otherSelectedCohort ? otherSelectedCohort.cohort_definition_id : undefined}
rowType={outcome && outcome.concept_id === item[0].concept_id ? 'Outcome Phenotype' : 'Covariate'}
rowName={item[0].concept_name ? item[0].concept_name : item[0].provided_name}
covariateSubset={item}
sourceId={sourceId}
/>
))
) : null}
</tbody>
</table>
</Panel>
</Collapse>
</div>
);
};

AttritionTable.propTypes = {
selectedCohort: PropTypes.object,
otherSelectedCohort: PropTypes.object,
outcome: PropTypes.object,
selectedCovariates: PropTypes.array.isRequired,
selectedDichotomousCovariates: PropTypes.array.isRequired,
sourceId: PropTypes.number.isRequired,
tableHeader: PropTypes.string.isRequired,
};

AttritionTable.defaultProps = {
selectedCohort: undefined,
otherSelectedCohort: undefined,
outcome: undefined,
};

export default AttritionTable;
Loading

0 comments on commit 278e0d3

Please sign in to comment.