diff --git a/src/AnalysisPage/GeneCentricViewRat/geneCentricViewPage.jsx b/src/AnalysisPage/GeneCentricViewRat/geneCentricViewPage.jsx index 4d85a468..de596b9a 100644 --- a/src/AnalysisPage/GeneCentricViewRat/geneCentricViewPage.jsx +++ b/src/AnalysisPage/GeneCentricViewRat/geneCentricViewPage.jsx @@ -11,6 +11,7 @@ import GeneCentricTrainingResultsTable from './geneCentricTrainingResultsTable'; import GeneCentricSearchResultFilters from './geneCentricSearchResultFilters'; import AnimatedLoadingIcon from '../../lib/ui/loading'; import { genes } from '../../data/genes'; +import { trackEvent } from '../../GoogleAnalytics/googleAnalytics'; function GeneCentricView({ geneSearchResults, @@ -22,6 +23,7 @@ function GeneCentricView({ geneSearchChangeFilter, scope, hasResultFilters, + profile, }) { const [multiSelections, setMultiSelections] = useState([]); const inputRef = useRef(null); @@ -140,7 +142,18 @@ function GeneCentricView({ handleGeneCentricSearch( geneSearchParams, formatSearchInput(), - 'all' + 'all', + ); + // track event in Google Analytics 4 + trackEvent( + 'Gene-centric View Search', + 'keyword_search', + profile && profile.userid + ? profile.userid.substring( + profile.userid.indexOf('|') + 1, + ) + : 'anonymous', + formatSearchInput(), ); }} > @@ -254,6 +267,10 @@ GeneCentricView.propTypes = { assay: PropTypes.object, tissue: PropTypes.object, }), + profile: PropTypes.shape({ + userid: PropTypes.string, + user_metadata: PropTypes.object, + }), }; GeneCentricView.defaultProps = { @@ -263,16 +280,18 @@ GeneCentricView.defaultProps = { geneSearchParams: { ...defaultGeneSearchParams }, scope: 'all', hasResultFilters: {}, + profile: {}, }; const mapStateToProps = (state) => ({ ...state.analysis, + ...state.auth, }); const mapDispatchToProps = (dispatch) => ({ handleGeneCentricSearch: (params, geneInputValue, scope) => dispatch( - AnalysisActions.handleGeneCentricSearch(params, geneInputValue, scope) + AnalysisActions.handleGeneCentricSearch(params, geneInputValue, scope), ), geneSearchReset: (scope) => dispatch(AnalysisActions.geneSearchReset(scope)), geneSearchChangeFilter: (field, value) => diff --git a/src/App/App.jsx b/src/App/App.jsx index 6595fe22..4c1f9bed 100644 --- a/src/App/App.jsx +++ b/src/App/App.jsx @@ -95,6 +95,12 @@ function App({ history = History }) { /> + ', () => { }); test('It should contain fifteen children', () => { - expect(component.find('Route').length).toBe(21); + expect(component.find('Route').length).toBe(22); }); test('It should contain four children', () => { diff --git a/src/BrowseDataPage/browseDataActions.js b/src/BrowseDataPage/browseDataActions.js index f7a08c7f..ab4feab8 100644 --- a/src/BrowseDataPage/browseDataActions.js +++ b/src/BrowseDataPage/browseDataActions.js @@ -18,6 +18,9 @@ const DATA_FETCH_REQUESTED = 'DATA_FETCH_REQUESTED'; const DATA_FETCH_SUCCESS = 'DATA_FETCH_SUCCESS'; const DATA_FETCH_FAILURE = 'DATA_FETCH_FAILURE'; const RESET_BROWSE_STATE = 'RESET_BROWSE_STATE'; +const SELECT_PASS1B_06_DATA = 'SELECT_PASS1B_06_DATA'; +const SELECT_PASS1A_06_DATA = 'SELECT_PASS1A_06_DATA'; +const SELECT_HUMAN_PRECOVID_SED_ADU_DATA = 'SELECT_HUMAN_PRECOVID_SED_ADU_DATA'; export const types = { CHANGE_FILTER, @@ -37,6 +40,9 @@ export const types = { DATA_FETCH_SUCCESS, DATA_FETCH_FAILURE, RESET_BROWSE_STATE, + SELECT_PASS1B_06_DATA, + SELECT_PASS1A_06_DATA, + SELECT_HUMAN_PRECOVID_SED_ADU_DATA, }; function changeFilter(category, filter) { @@ -154,6 +160,24 @@ function resetBrowseState() { }; } +function selectPass1B06Data() { + return { + type: SELECT_PASS1B_06_DATA, + }; +} + +function selectPass1A06Data() { + return { + type: SELECT_PASS1A_06_DATA, + }; +} + +function selectHumanPreCovidSedAduData() { + return { + type: SELECT_HUMAN_PRECOVID_SED_ADU_DATA, + }; +} + // Mock Async Getting List const files = []; @@ -330,6 +354,9 @@ const actions = { handleDownloadRequest, handleDataFetch, resetBrowseState, + selectPass1B06Data, + selectPass1A06Data, + selectHumanPreCovidSedAduData, }; export default actions; diff --git a/src/BrowseDataPage/browseDataFilter.jsx b/src/BrowseDataPage/browseDataFilter.jsx index 53cb0780..bb202729 100644 --- a/src/BrowseDataPage/browseDataFilter.jsx +++ b/src/BrowseDataPage/browseDataFilter.jsx @@ -1,27 +1,53 @@ import React from 'react'; import PropTypes from 'prop-types'; -import browseDataFilters, { tissueList } from '../lib/browseDataFilters'; +import { useSelector } from 'react-redux'; +import browseDataFilters, { tissues, omes } from '../lib/browseDataFilters'; +import assayList from '../lib/assayList'; -// build list of PASS1B-06 tissues -const pass1bTissues = tissueList.filter((item) => item !== 'Aorta'); +function BrowseDataFilter({ activeFilters, onChangeFilter, onResetFilters }) { + const dataDownload = useSelector((state) => state.browseData); -function BrowseDataFilter({ - activeFilters, - onChangeFilter, - onResetFilters, - userType, -}) { const fileFilters = [...browseDataFilters]; - if (!userType || (userType && userType !== 'internal')) { - fileFilters.forEach((item) => { - if (item.keyName === 'study') { - item.filters = ['Endurance Training']; + // Remove phenotype filter if human-precovid-sed-adu data tab is selected + if (dataDownload.humanPrecovidSedAduDataSelected) { + fileFilters.splice(4, 1); + } + + fileFilters.forEach((item) => { + if (item.keyName === 'tissue_name') { + if (dataDownload.pass1b06DataSelected) { + item.filters = tissues.pass1b_06; } - if (item.keyName === 'tissue_name') { - item.filters = pass1bTissues; + if (dataDownload.pass1a06DataSelected) { + item.filters = tissues.pass1a_06; } - }); - } + if (dataDownload.humanPrecovidSedAduDataSelected) { + item.filters = tissues.human_sed_adu; + } + } + if (item.keyName === 'omics') { + if (dataDownload.pass1b06DataSelected) { + item.filters = omes.pass1b_06; + } + if (dataDownload.pass1a06DataSelected) { + item.filters = omes.pass1a_06; + } + if (dataDownload.humanPrecovidSedAduDataSelected) { + item.filters = omes.human_sed_adu; + } + } + if (item.keyName === 'assay') { + if (dataDownload.pass1b06DataSelected) { + item.filters = assayList.pass1b_06; + } + if (dataDownload.pass1a06DataSelected) { + item.filters = assayList.pass1a_06; + } + if (dataDownload.humanPrecovidSedAduDataSelected) { + item.filters = assayList.human_sed_adu; + } + } + }); const filters = fileFilters.map((item) => (
@@ -52,15 +78,9 @@ function BrowseDataFilter({ key={filter} type="button" className={`btn filterBtn ${ - isActiveFilter || - (filter === 'Endurance Training' && userType !== 'internal') - ? 'activeFilter' - : '' + isActiveFilter ? 'activeFilter' : '' }`} onClick={() => onChangeFilter(item.keyName, filter)} - disabled={ - filter === 'Endurance Training' && userType !== 'internal' - } > {filter} @@ -95,7 +115,6 @@ BrowseDataFilter.propTypes = { }), onChangeFilter: PropTypes.func.isRequired, onResetFilters: PropTypes.func.isRequired, - userType: PropTypes.string, }; BrowseDataFilter.defaultProps = { activeFilters: { @@ -104,7 +123,6 @@ BrowseDataFilter.defaultProps = { tissue_name: [], category: [], }, - userType: null, }; export default BrowseDataFilter; diff --git a/src/BrowseDataPage/browseDataPage.jsx b/src/BrowseDataPage/browseDataPage.jsx index 04de8ed3..9ea399ef 100644 --- a/src/BrowseDataPage/browseDataPage.jsx +++ b/src/BrowseDataPage/browseDataPage.jsx @@ -1,17 +1,12 @@ import React, { useEffect } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; -import { Link } from 'react-router-dom'; import { Helmet } from 'react-helmet'; -import PageTitle from '../lib/ui/pageTitle'; -import BrowseDataTable from './browseDataTable'; import actions from './browseDataActions'; import BrowseDataFilter from './browseDataFilter'; -import BootstrapSpinner from '../lib/ui/spinner'; -import OpenAccessBrowseDataSummary from './components/openAccessSummary'; -import AuthAccessBrowseDataSummary from './components/authAccessSummary'; import dataDownloadStructuredData from '../lib/searchStructuredData/dataDownload'; import UserSurveyModal from '../UserSurvey/userSurveyModal'; +import DataDownloadsMain from './components/dataDownloadsMain'; export function BrowseDataPage({ profile, @@ -25,10 +20,9 @@ export function BrowseDataPage({ waitingForResponse, showUserSurveyModal, surveyId, + surveySubmitted, + downloadedData, }) { - // anonymous user or authenticated user - const userType = profile.user_metadata && profile.user_metadata.userType; - useEffect(() => { if (showUserSurveyModal) { const userSurveyModalRef = document.querySelector('body'); @@ -45,58 +39,25 @@ export function BrowseDataPage({ {JSON.stringify(dataDownloadStructuredData)} - + - {!userType || (userType && userType === 'external') ? ( - - ) : null} - {userType && userType === 'internal' ? ( - - ) : null} -
- - {fetching && ( -
- -
- )} - {!fetching && !filteredFiles.length && ( -
-

- - No matches found for the selected filters. Please refer to the{' '} - Summary Table for data that are - available. - -

-
- )} - {!fetching && filteredFiles.length && ( - - )} - -
); } @@ -120,12 +81,16 @@ BrowseDataPage.propTypes = { waitingForResponse: PropTypes.bool.isRequired, showUserSurveyModal: PropTypes.bool, surveyId: PropTypes.string, + surveySubmitted: PropTypes.bool, + downloadedData: PropTypes.bool, }; BrowseDataPage.defaultProps = { profile: {}, showUserSurveyModal: false, surveyId: '', + surveySubmitted: false, + downloadedData: false, }; const mapStateToProps = (state) => ({ @@ -133,6 +98,8 @@ const mapStateToProps = (state) => ({ profile: state.auth.profile, showUserSurveyModal: state.userSurvey.showUserSurveyModal, surveyId: state.userSurvey.surveyId, + surveySubmitted: state.userSurvey.surveySubmitted, + downloadedData: state.userSurvey.downloadedData, }); const mapDispatchToProps = (dispatch) => ({ diff --git a/src/BrowseDataPage/browseDataReducer.js b/src/BrowseDataPage/browseDataReducer.js index 6bdb975c..9857956d 100644 --- a/src/BrowseDataPage/browseDataReducer.js +++ b/src/BrowseDataPage/browseDataReducer.js @@ -20,6 +20,9 @@ export const defaultBrowseDataState = { waitingForResponse: false, fetching: false, error: '', + pass1b06DataSelected: false, + pass1a06DataSelected: false, + humanPrecovidSedAduDataSelected: false, }; function createSorter(sortBy) { @@ -266,6 +269,27 @@ function browseDataReducer(state = defaultBrowseDataState, action) { error: '', }; } + case types.SELECT_PASS1B_06_DATA: + return { + ...state, + pass1b06DataSelected: true, + pass1a06DataSelected: false, + humanPrecovidSedAduDataSelected: false, + }; + case types.SELECT_PASS1A_06_DATA: + return { + ...state, + pass1b06DataSelected: false, + pass1a06DataSelected: true, + humanPrecovidSedAduDataSelected: false, + }; + case types.SELECT_HUMAN_PRECOVID_SED_ADU_DATA: + return { + ...state, + pass1b06DataSelected: false, + pass1a06DataSelected: false, + humanPrecovidSedAduDataSelected: true, + }; case types.RESET_BROWSE_STATE: return defaultBrowseDataState; default: diff --git a/src/BrowseDataPage/browseDataTable.jsx b/src/BrowseDataPage/browseDataTable.jsx index 87a20a8f..02738f49 100644 --- a/src/BrowseDataPage/browseDataTable.jsx +++ b/src/BrowseDataPage/browseDataTable.jsx @@ -156,21 +156,6 @@ function DataTable({ .fill(start) .map((x, y) => x + y * step); - // anonymous user or authenticated user - const userType = profile.user_metadata && profile.user_metadata.userType; - const hasAccess = profile.user_metadata && profile.user_metadata.hasAccess; - - function handleDownloadClickEvent(selectedFiles) { - if (userType && hasAccess) { - handleDownloadRequest( - profile.user_metadata.email, - profile.user_metadata.name, - profile.userid, - selectedFiles, - ); - } - } - // Render the UI for your table // react-table doesn't have UI, it's headless. We just need to put the react-table // props from the Hooks, and it will do its magic automatically @@ -188,28 +173,18 @@ function DataTable({ className="btn btn-primary d-flex align-items-center" disabled={Object.keys(selectedRowIds).length === 0} data-toggle="modal" - data-target=".data-download-modal" - onClick={() => { - handleDownloadClickEvent(selectedFlatRows); - }} + data-target="#dataDownloadModal" > file_download Download selected files - {Object.keys(selectedRowIds).length > 0 && userType && hasAccess ? ( - - ) : null} - {Object.keys(selectedRowIds).length > 0 && !userType ? ( - - ) : null} +
diff --git a/src/BrowseDataPage/components/authAccessModal.jsx b/src/BrowseDataPage/components/authAccessModal.jsx index 93a1d496..a7e59bdc 100644 --- a/src/BrowseDataPage/components/authAccessModal.jsx +++ b/src/BrowseDataPage/components/authAccessModal.jsx @@ -68,7 +68,7 @@ function AuthAccessFileDownloadModal({
); } @@ -95,7 +87,7 @@ function BundleDownloadButton({ handleFileDownload(file, e)} > @@ -109,7 +101,7 @@ function BundleDownloadButton({ return ( ); } @@ -164,6 +158,7 @@ function BundleDownloadButton({ BundleDownloadButton.propTypes = { bundlefile: PropTypes.string.isRequired, + bundlefileSize: PropTypes.string.isRequired, profile: PropTypes.shape({ userid: PropTypes.string, user_metadata: PropTypes.shape({ @@ -172,12 +167,10 @@ BundleDownloadButton.propTypes = { name: PropTypes.string, }), }), - handleUserSurveyOpenOnBundledDownload: PropTypes.func, }; BundleDownloadButton.defaultProps = { profile: {}, - handleUserSurveyOpenOnBundledDownload: null, }; export default BundleDownloadButton; diff --git a/src/BrowseDataPage/components/dataDownloadsMain.jsx b/src/BrowseDataPage/components/dataDownloadsMain.jsx new file mode 100644 index 00000000..3fdb2219 --- /dev/null +++ b/src/BrowseDataPage/components/dataDownloadsMain.jsx @@ -0,0 +1,324 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Link, useLocation } from 'react-router-dom'; +import { useDispatch } from 'react-redux'; +import PageTitle from '../../lib/ui/pageTitle'; +import BrowseDataFilter from '../browseDataFilter'; +import DataTypeInfo from './dataTypeInfo'; +import BundleDatasets from './bundleDatasets'; +import BundleDataTypes from './bundleDataTypes'; +import actions from '../browseDataActions'; +import SelectiveDataDownloads from './selectiveDataDownloads'; +import SelectiveDataDownloadsCard from './selectiveDataDownloadsCard'; + +function DataDownloadsMain({ + profile, + filteredFiles, + fetching, + activeFilters, + onChangeFilter, + onResetFilters, + handleDownloadRequest, + downloadRequestResponse, + waitingForResponse, + surveySubmitted, + downloadedData, +}) { + const dispatch = useDispatch(); + const location = useLocation(); + + // anonymous user or authenticated user + const userType = profile.user_metadata && profile.user_metadata.userType; + + if (location.pathname === '/data-download/file-browser') { + return ( + + ); + } + + return ( +
+ +
+
+

+ Explore and download the MoTrPAC multi-omics datasets, which + includes quantitative results and analyses of molecular changes from + exercise across tissues. Currently, the complete young rat endurance + training dataset is publicly available. + {' '} + {userType && userType === 'internal' + ? 'The young rat acute exercise and human precovid sedentary adult datasets are currently available to consortium members only in the early preview phase. ' + : null} + For a summary of all the ongoing studies in MoTrPAC (data available + soon), please visit our + {' '} + Project Overview + . +

+
+
+
+

Study Data

+

+ Browse and find the data of your interest by tissue, ome, or assay + types. +

+
+ dispatch(actions.selectPass1B06Data())} + selectedData="pass1b-06" + cssSelector={ + !userType || (userType && userType === 'external') + ? 'external-access' + : '' + } + > +

+ Endurance Training +

+
    +
  • Male and female animals
  • +
  • 20 tissues
  • +
  • 29 assays across different omes
  • +
  • 5 time points
  • +
+
+ {/* pass1a/1c-06 data set */} + {userType && userType === 'internal' && ( + dispatch(actions.selectPass1A06Data())} + selectedData="pass1a-06" + > +

Acute Exercise

+
    +
  • Male and female animals
  • +
  • 21 tissues
  • +
  • 30 assays across different omes
  • +
  • 7 time points
  • +
+
+ )} + {/* human-precovid-sed-adu data set */} + {userType && userType === 'internal' && ( + + dispatch(actions.selectHumanPreCovidSedAduData()) + } + selectedData="human-precovid-sed-adu" + > +

+ Pre-COVID Sedentary +

+
    +
  • Adult participants
  • +
  • 4 tissues
  • +
  • 22 assays across different omes
  • +
  • Acute exercise
  • +
+
+ )} +
+
+ {/* Pre-bundled data sets */} +
+

Pre-bundled Data Sets

+ {/* nav tabs */} +
+ {/* tab panes */} +
+
+ +
+ {userType && userType === 'internal' && ( +
+ +
+ )} + {userType && userType === 'internal' && ( +
+ +
+ )} +
+
+ {/* Additional data information */} + {userType && userType === 'internal' ? ( +
+
+

Additional Information

+

+ The currently available young adult rats experimental data for + acute exercise and endurance training include all tissues and + assays from the very last consortium data release, as well as + additional tissues and assays made available afterwards. The + phenotypic data sets have also been updated since then. +

+

+ Please refer to this + {' '} + + README + + description + + + {' '} + document for the data included in the very last consortium + data release. +

+
+
+ ) : null} +
+
+ ); +} + +DataDownloadsMain.propTypes = { + filteredFiles: PropTypes.arrayOf(PropTypes.shape({})).isRequired, + fetching: PropTypes.bool.isRequired, + profile: PropTypes.shape({ + user_metadata: PropTypes.shape({ + userType: PropTypes.string, + email: PropTypes.string, + name: PropTypes.string, + userid: PropTypes.string, + }), + }), + activeFilters: BrowseDataFilter.propTypes.activeFilters.isRequired, + onChangeFilter: PropTypes.func.isRequired, + onResetFilters: PropTypes.func.isRequired, + handleDownloadRequest: PropTypes.func.isRequired, + downloadRequestResponse: PropTypes.string.isRequired, + waitingForResponse: PropTypes.bool.isRequired, + surveySubmitted: PropTypes.bool.isRequired, + downloadedData: PropTypes.bool.isRequired, +}; + +DataDownloadsMain.defaultProps = { + profile: {}, +}; + +export default DataDownloadsMain; diff --git a/src/BrowseDataPage/components/dataTypeInfo.jsx b/src/BrowseDataPage/components/dataTypeInfo.jsx index 4cafaf3b..50f65fd3 100644 --- a/src/BrowseDataPage/components/dataTypeInfo.jsx +++ b/src/BrowseDataPage/components/dataTypeInfo.jsx @@ -1,7 +1,6 @@ import React, { useState } from 'react'; import PropTypes from 'prop-types'; import { Link } from 'react-router-dom'; -import EmailLink from '../../lib/ui/emailLink'; function DataTypeInfo({ grid }) { const [showMoreInfo, setShowMoreInfo] = useState(false); @@ -15,35 +14,8 @@ function DataTypeInfo({ grid }) { return (
-

Data Types

-
    -
  • - Assay-specific differential analysis and - normalized data -
  • -
  • - Assay-specific quantitative results, experiment metadata, and QA/QC - reports -
  • -
  • - Cross-platform merged metabolomics data tables for named metabolites -
  • -
  • Phenotypic data
  • -
-
-

- Note: Raw files are not - currently available for direct download through the Data Hub portal. - Please submit your requests to{' '} - {' '} - and specify the relevant tissues/assays if you would like to get - access to the raw files. -

-
-
+
+

Data Types

+
    +
  • + Assay-specific + {' '} + differential analysis + , normalized data, quantitative results, experiment metadata + and QA/QC reports +
  • +
  • + Cross-platform merged metabolomics data tables for named metabolites +
  • +
  • Phenotypic data
  • +
+
+

+ Note: Raw files are not + currently available for direct download through the Data Hub portal. + Please{' '} + submit your requests to our helpdesk and + specify the relevant tissues/assays if you would like to get access + to the raw files. +

+
); diff --git a/src/BrowseDataPage/components/openAccessModal.jsx b/src/BrowseDataPage/components/openAccessModal.jsx index 8c9c2a34..a063da44 100644 --- a/src/BrowseDataPage/components/openAccessModal.jsx +++ b/src/BrowseDataPage/components/openAccessModal.jsx @@ -9,10 +9,19 @@ function OpenAccessFileDownloadModal({ waitingForResponse, handleDownloadRequest, selectedFiles, + profile, }) { const [submitted, setSubmitted] = useState(false); - const [name, setName] = useState(''); - const [email, setEmail] = useState(''); + const [name, setName] = useState( + profile && profile.user_metadata && profile.user_metadata.name + ? profile.user_metadata.name + : '', + ); + const [email, setEmail] = useState( + profile && profile.user_metadata && profile.user_metadata.email + ? profile.user_metadata.email + : '', + ); const dispatch = useDispatch(); // get states from redux store @@ -36,7 +45,12 @@ function OpenAccessFileDownloadModal({ return false; } // submit download request - handleDownloadRequest(email, name, '', selectedFiles); + handleDownloadRequest( + email, + name, + profile && profile.userid ? profile.userid : '', + selectedFiles, + ); // set user survey id in redux store dispatch(surveyModdalActions.setUserSurveyId(email)); // update store to show that user has downloaded data @@ -50,8 +64,17 @@ function OpenAccessFileDownloadModal({ return (

- Please provide your email address and name. We will notify you when - the the download is ready. + {profile && profile.user_metadata && profile.user_metadata.email ? ( + + Please submit your request upon verifying your email address and + name. We will notify you when the the download is ready. + + ) : ( + + Please submit your request upon providing your email address and + name. We will notify you when the the download is ready. + + )}

@@ -59,6 +82,7 @@ function OpenAccessFileDownloadModal({ type="email" className="form-control w-100 mt-1" id="requester-email" + value={email} onChange={(e) => { e.preventDefault(); setEmail(e.target.value); @@ -71,6 +95,7 @@ function OpenAccessFileDownloadModal({ type="text" className="form-control w-100 mt-1" id="requester-name" + value={name} onChange={(e) => { e.preventDefault(); setName(e.target.value); @@ -80,8 +105,8 @@ function OpenAccessFileDownloadModal({
@@ -90,7 +115,7 @@ function OpenAccessFileDownloadModal({ ); } - // reset state and close modal if user has not submitted download request + // reset state and close modal function handleModalClose() { setName(''); setEmail(''); @@ -134,8 +159,8 @@ function OpenAccessFileDownloadModal({ className="close" data-dismiss="modal" aria-label="Close" - onClick={ - submitted ? handleModalCloseAfterRequest : handleModalClose + onClick={() => + submitted ? handleModalCloseAfterRequest() : handleModalClose() } > @@ -164,9 +189,9 @@ function OpenAccessFileDownloadModal({
@@ -183,6 +208,18 @@ OpenAccessFileDownloadModal.propTypes = { downloadRequestResponse: PropTypes.string.isRequired, handleDownloadRequest: PropTypes.func.isRequired, selectedFiles: PropTypes.arrayOf(PropTypes.shape({})).isRequired, + profile: PropTypes.shape({ + userid: PropTypes.string, + user_metadata: PropTypes.shape({ + userType: PropTypes.string, + email: PropTypes.string, + name: PropTypes.string, + }), + }), +}; + +OpenAccessFileDownloadModal.defaultProps = { + profile: {}, }; export default OpenAccessFileDownloadModal; diff --git a/src/BrowseDataPage/components/selectiveDataDownloadFileBrowser.jsx b/src/BrowseDataPage/components/selectiveDataDownloadFileBrowser.jsx new file mode 100644 index 00000000..478d11c2 --- /dev/null +++ b/src/BrowseDataPage/components/selectiveDataDownloadFileBrowser.jsx @@ -0,0 +1,77 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Link } from 'react-router-dom'; +import BrowseDataTable from '../browseDataTable'; +import BrowseDataFilter from '../browseDataFilter'; +import BootstrapSpinner from '../../lib/ui/spinner'; + +function SelectiveDataDownloadFileBrowser({ + profile, + filteredFiles, + fetching, + activeFilters, + onChangeFilter, + onResetFilters, + handleDownloadRequest, + downloadRequestResponse, + waitingForResponse, +}) { + return ( +
+ + {fetching && ( +
+ +
+ )} + {!fetching && !filteredFiles.length && ( +
+

+ + No matches found for the selected filters. Please refer to the{' '} + Summary Table for data that are + available. + +

+
+ )} + {!fetching && filteredFiles.length && ( + + )} +
+ ); +} + +SelectiveDataDownloadFileBrowser.propTypes = { + profile: PropTypes.shape({ + user_metadata: PropTypes.shape({ + userType: PropTypes.string, + email: PropTypes.string, + name: PropTypes.string, + }), + }), + filteredFiles: PropTypes.arrayOf(PropTypes.shape({})).isRequired, + fetching: PropTypes.bool.isRequired, + activeFilters: BrowseDataFilter.propTypes.activeFilters.isRequired, + onChangeFilter: PropTypes.func.isRequired, + onResetFilters: PropTypes.func.isRequired, + handleDownloadRequest: PropTypes.func.isRequired, + downloadRequestResponse: PropTypes.string.isRequired, + waitingForResponse: PropTypes.bool.isRequired, +}; + +SelectiveDataDownloadFileBrowser.defaultProps = { + profile: {}, +}; + +export default SelectiveDataDownloadFileBrowser; diff --git a/src/BrowseDataPage/components/selectiveDataDownloadFileBrowserTab.jsx b/src/BrowseDataPage/components/selectiveDataDownloadFileBrowserTab.jsx new file mode 100644 index 00000000..1a584721 --- /dev/null +++ b/src/BrowseDataPage/components/selectiveDataDownloadFileBrowserTab.jsx @@ -0,0 +1,47 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +function SelectiveDataDownloadFileBrowserTab({ + className, + id, + href, + ariaControls, + tabTitle, + tabSelectHandler, + onResetFilters, +}) { + function handleTabSelect(e) { + e.preventDefault(); + tabSelectHandler(); + onResetFilters(); + } + + return ( +
  • + handleTabSelect(e)} + > + {tabTitle} + +
  • + ); +} + +SelectiveDataDownloadFileBrowserTab.propTypes = { + className: PropTypes.string.isRequired, + id: PropTypes.string.isRequired, + href: PropTypes.string.isRequired, + ariaControls: PropTypes.string.isRequired, + tabTitle: PropTypes.string.isRequired, + tabSelectHandler: PropTypes.func.isRequired, + onResetFilters: PropTypes.func.isRequired, +}; + +export default SelectiveDataDownloadFileBrowserTab; diff --git a/src/BrowseDataPage/components/selectiveDataDownloads.jsx b/src/BrowseDataPage/components/selectiveDataDownloads.jsx new file mode 100644 index 00000000..9649bce9 --- /dev/null +++ b/src/BrowseDataPage/components/selectiveDataDownloads.jsx @@ -0,0 +1,128 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { useSelector } from 'react-redux'; +import { Link } from 'react-router-dom'; +import PageTitle from '../../lib/ui/pageTitle'; +import BrowseDataFilter from '../browseDataFilter'; +import SelectiveDataDownloadFileBrowser from './selectiveDataDownloadFileBrowser'; + +function SelectiveDataDownloads({ + profile, + filteredFiles, + fetching, + activeFilters, + onChangeFilter, + onResetFilters, + handleDownloadRequest, + downloadRequestResponse, + waitingForResponse, +}) { + const dataDownload = useSelector((state) => state.browseData); + + // set page title based on selected data + function renderPageTitle() { + let titleStr = 'Data Download'; + if (dataDownload.pass1b06DataSelected) { + titleStr = 'Data Download - Endurance Training Rats'; + } + if (dataDownload.pass1a06DataSelected) { + titleStr = 'Data Download - Acute Exercise Rats'; + } + if (dataDownload.humanPrecovidSedAduDataSelected) { + titleStr = 'Data Download - Human Sedentary Adults'; + } + + return titleStr; + } + + // set page summary based on selected data + function renderStudySummary() { + let summary = ''; + if (dataDownload.pass1b06DataSelected) { + summary = + 'Experimental data from endurance trained (1 week, 2 weeks, 4 weeks or 8 weeks) compared to untrained young adult rats (6 months old).'; + } + if (dataDownload.pass1a06DataSelected) { + summary = + 'Experimental data from acute exercise study on young adult rats for a comprehensive analysis of the physiological responses following a single exercise session in 6-month-old F344 rats.'; + } + if (dataDownload.humanPrecovidSedAduDataSelected) { + summary = + 'Differential analysis results data for differences in changes during the acute bout, comparing the change from pre-exercise baseline at any given timepoint during the acute bout as compared to resting control.'; + } + + return summary; + } + + // set data file list based on selected data + let dataFiles = []; + if (dataDownload.pass1b06DataSelected) { + dataFiles = filteredFiles.filter((item) => item.phase === 'PASS1B-06'); + } + if (dataDownload.pass1a06DataSelected) { + dataFiles = filteredFiles.filter((item) => item.phase === 'PASS1A-06'); + } + if (dataDownload.humanPrecovidSedAduDataSelected) { + dataFiles = filteredFiles.filter( + (item) => item.phase === 'HUMAN-PRECOVID-SED-ADU', + ); + } + + return ( +
    +
    + + arrow_back + Back + +
    + +

    {renderStudySummary()}

    +
    +
    + +
    +
    +
    + ); +} + +SelectiveDataDownloads.propTypes = { + filteredFiles: PropTypes.arrayOf(PropTypes.shape({})), + fetching: PropTypes.bool.isRequired, + profile: PropTypes.shape({ + user_metadata: PropTypes.shape({ + userType: PropTypes.string, + email: PropTypes.string, + name: PropTypes.string, + userid: PropTypes.string, + }), + }), + activeFilters: BrowseDataFilter.propTypes.activeFilters.isRequired, + onChangeFilter: PropTypes.func.isRequired, + onResetFilters: PropTypes.func.isRequired, + handleDownloadRequest: PropTypes.func.isRequired, + downloadRequestResponse: PropTypes.string.isRequired, + waitingForResponse: PropTypes.bool.isRequired, +}; + +SelectiveDataDownloads.defaultProps = { + profile: {}, + filteredFiles: [], +}; + +export default SelectiveDataDownloads; diff --git a/src/BrowseDataPage/components/selectiveDataDownloadsCard.jsx b/src/BrowseDataPage/components/selectiveDataDownloadsCard.jsx new file mode 100644 index 00000000..8214e9a0 --- /dev/null +++ b/src/BrowseDataPage/components/selectiveDataDownloadsCard.jsx @@ -0,0 +1,60 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { useHistory } from 'react-router-dom'; + +function SelectiveDataDownloadsCard({ + cardIcon, + cardTitle, + dataSelectHandler, + selectedData, + cssSelector, + children, +}) { + const history = useHistory(); + + function handleDataSelect(e) { + e.preventDefault(); + dataSelectHandler(); + history.push('/data-download/file-browser', { + state: { selectedData }, + }); + } + + return ( +
    +
    +

    + {cardIcon} + {cardTitle} +

    +
    +
    + {children} + +
    +
    + ); +} + +SelectiveDataDownloadsCard.propTypes = { + cardIcon: PropTypes.string.isRequired, + cardTitle: PropTypes.string.isRequired, + dataSelectHandler: PropTypes.func.isRequired, + selectedData: PropTypes.string, + cssSelector: PropTypes.string, +}; + +SelectiveDataDownloadsCard.defaultProps = { + selectedData: '', + cssSelector: '', +}; + +export default SelectiveDataDownloadsCard; diff --git a/src/BrowseDataPage/helper.jsx b/src/BrowseDataPage/helper.jsx index cfb731a7..30204653 100644 --- a/src/BrowseDataPage/helper.jsx +++ b/src/BrowseDataPage/helper.jsx @@ -251,6 +251,57 @@ export const transformData = (arr) => { item.assay = newMetabAssayVal; } } + if ( + item.assay !== null && + item.assay !== undefined && + item.omics === 'Metabolomics Targeted' + ) { + let newMetabAssayVal = item.assay; + if ( + newMetabAssayVal.indexOf('Acylcarnitines') !== -1 && + newMetabAssayVal.indexOf('Oxylipins') !== -1 + ) { + newMetabAssayVal = 'Merged'; + item.assay = newMetabAssayVal; + } + } + if (item.tissue_name !== null && item.tissue_name !== undefined) { + let newTissueVal = item.tissue_name; + if ( + newTissueVal.indexOf('Human PBMC') !== -1 || + newTissueVal.indexOf('Human EDTA Packed Cells') !== -1 || + newTissueVal.indexOf('Human PAXgene RNA') !== -1 + ) { + newTissueVal = 'Blood'; + item.tissue_name = newTissueVal; + } + if ( + newTissueVal.indexOf('Human Adipose') !== -1 || + newTissueVal.indexOf('Human Adipose Powder') !== -1 + ) { + newTissueVal = 'Adipose'; + item.tissue_name = newTissueVal; + } + if ( + newTissueVal.indexOf('Human Muscle') !== -1 || + newTissueVal.indexOf('Human Muscle Powder') !== -1 + ) { + newTissueVal = 'Muscle'; + item.tissue_name = newTissueVal; + } + if (newTissueVal.indexOf('Human EDTA Plasma') !== -1) { + newTissueVal = 'Plasma'; + item.tissue_name = newTissueVal; + } + if ( + newTissueVal.indexOf('EDTA Plasma') !== -1 && + item.omics.indexOf('Metabolomics') !== -1 && + item.study.indexOf('Acute Exercise') !== -1 + ) { + newTissueVal = 'Plasma'; + item.tissue_name = newTissueVal; + } + } }); return tranformArray; }; diff --git a/src/LandingPage/landingPage.jsx b/src/LandingPage/landingPage.jsx index c57f6a75..6542e7cd 100644 --- a/src/LandingPage/landingPage.jsx +++ b/src/LandingPage/landingPage.jsx @@ -214,18 +214,9 @@ export function LandingPage({ isAuthenticated, profile }) {

    Exercise

    - - Molecular Transducers of Physical Activity Consortium - (MoTrPAC) - {' '} - is a national research consortium. Its goal is to{' '} - - study the molecular changes that occur in response to - exercise, - {' '} - and ultimately to advance the understanding of how physical - activity improves and preserves health. We aim to generate a - molecular map of the effects of exercise. + Welcome to the data repository for the Molecular Transducers of Physical + Activity Consortium; a national research initiative that aims to generate + a molecular map of the effects of exercise and training.

    diff --git a/src/MultiOmicsWorkingGroups/bicUpdates.jsx b/src/MultiOmicsWorkingGroups/bicUpdates.jsx new file mode 100644 index 00000000..87b5a26a --- /dev/null +++ b/src/MultiOmicsWorkingGroups/bicUpdates.jsx @@ -0,0 +1,39 @@ +import React from 'react'; + +function BicUpdates() { + return ( +
    +

    BIC Updates

    +

    + The Bioinformatics Center is committed to keeping our community informed + and up-to-date with the latest developments in bioinformatics resources, + tools, and data. To this end, we provide{' '} + + monthly BIC Updates + {' '} + that encapsulate all recent advancements, new resources, and crucial + data updates facilitated by our center.{' '} + + The archive of all the monthly BIC Updates is available here + + . +

    +

    + Note: BIC Updates are disseminated monthly through email by Jane Lu. To + be added to the distribution list, please contact Jane at{' '} + motrpac-acc@aging.ufl.edu + . +

    +
    + ); +} + +export default BicUpdates; diff --git a/src/MultiOmicsWorkingGroups/dawgPAC.jsx b/src/MultiOmicsWorkingGroups/dawgPAC.jsx new file mode 100644 index 00000000..ecef3adf --- /dev/null +++ b/src/MultiOmicsWorkingGroups/dawgPAC.jsx @@ -0,0 +1,268 @@ +import React, { useState } from 'react'; +import PropTypes from 'prop-types'; +import HtmlReportModal from './htmlReportModal'; + +const proteomicsReportsDA = [ + 't55-gastrocnemius_prot-ph_DEA_report.html', + 't55-gastrocnemius_prot-pr_DEA_report.html', + 't58-heart_prot-ac_DEA_report.html', + 't58-heart_prot-ph_DEA_report.html', + 't58-heart_prot-pr_DEA_report.html', + 't59-kidney_prot-ph_DEA_report.html', + 't59-kidney_prot-pr_DEA_report.html', + 't66-lung_prot-ph_DEA_report.html', + 't66-lung_prot-pr_DEA_report.html', + 't68-liver_prot-ac_DEA_report.html', + 't68-liver_prot-ph_DEA_report.html', + 't68-liver_prot-pr_DEA_report.html', + 't70-white-adipose_prot-ph_DEA_report.html', + 't70-white-adipose_prot-pr_DEA_report.html', +]; + +const proteomicsReportsQCNorm = [ + 't55-gastrocnemius_prot-ph_qc-norm_report.html', + 't55-gastrocnemius_prot-pr_qc-norm_report.html', + 't58-heart_prot-ac_qc-norm_report.html', + 't58-heart_prot-ph_qc-norm_report.html', + 't58-heart_prot-pr_qc-norm_report.html', + 't59-kidney_prot-ph_qc-norm_report.html', + 't59-kidney_prot-pr_qc-norm_report.html', + 't66-lung_prot-ph_qc-norm_report.html', + 't66-lung_prot-pr_qc-norm_report.html', + 't68-liver_prot-ac_qc-norm_report.html', + 't68-liver_prot-ph_qc-norm_report.html', + 't68-liver_prot-pr_qc-norm_report.html', + 't70-white-adipose_prot-ph_qc-norm_report.html', + 't70-white-adipose_prot-pr_qc-norm_report.html', +]; + +const proteomics1A1CIndependentAnalyses = [ + 't55-gastrocnemius_prot-ph_1A1C-independent-analyses_report.html', + 't55-gastrocnemius_prot-pr_1A1C-independent-analyses_report.html', + 't58-heart_prot-ac_1A1C-independent-analyses_report.html', + 't58-heart_prot-ph_1A1C-independent-analyses_report.html', + 't58-heart_prot-pr_1A1C-independent-analyses_report.html', + 't59-kidney_prot-ph_1A1C-independent-analyses_report.html', + 't59-kidney_prot-pr_1A1C-independent-analyses_report.html', + 't66-lung_prot-ph_1A1C-independent-analyses_report.html', + 't66-lung_prot-pr_1A1C-independent-analyses_report.html', + 't68-liver_prot-ac_1A1C-independent-analyses_report.html', + 't68-liver_prot-ph_1A1C-independent-analyses_report.html', + 't68-liver_prot-pr_1A1C-independent-analyses_report.html', + 't70-white-adipose_prot-ph_1A1C-independent-analyses_report.html', + 't70-white-adipose_prot-pr_1A1C-independent-analyses_report.html', +]; + +function DawgPAC({ profile }) { + const [selectedReport, setSelectedReport] = useState(null); + const [selectedReportLabel, setSelectedReportLabel] = useState(null); + + const handleClickReport = (report, reportLabel) => { + setSelectedReport(report); + setSelectedReportLabel(reportLabel); + }; + + return ( +
    +

    + DAWG-PAC: Data Analysis Working Group - PASS1A/1C +

    +
    PASS1A/1C: Acute exercise on young adult rats
    +

    + The goal of the acute exercise study on young adult rats (designated as + PASS1A-06) is to conduct a comprehensive analysis of the physiological + responses following a single exercise session in 6-month-old F344 rats. + The primary aim was to collect a wide range of tissue samples + post-exercise for high-quality analysis at chemical analysis sites. +

    + +
    + ); +} + +DawgPAC.propTypes = { + profile: PropTypes.shape({ + userid: PropTypes.string, + user_metadata: PropTypes.object, + }), +}; + +DawgPAC.defaultProps = { + profile: {}, +}; + +export default DawgPAC; diff --git a/src/MultiOmicsWorkingGroups/htmlReportModal.jsx b/src/MultiOmicsWorkingGroups/htmlReportModal.jsx index 475951cc..6e6caa1c 100644 --- a/src/MultiOmicsWorkingGroups/htmlReportModal.jsx +++ b/src/MultiOmicsWorkingGroups/htmlReportModal.jsx @@ -1,7 +1,8 @@ import React, { useState, useRef } from 'react'; import PropTypes from 'prop-types'; +import { trackEvent } from '../GoogleAnalytics/googleAnalytics'; -function HtmlReportModal({ selectedReport, selectedReportLabel }) { +function HtmlReportModal({ selectedReport, selectedReportLabel, profile }) { const iframeRef = useRef(null); const [iframeLoaded, setIframeLoaded] = useState(false); @@ -29,6 +30,19 @@ function HtmlReportModal({ selectedReport, selectedReportLabel }) { className="btn btn-primary btn-report-download ml-3" href={`/static-assets/dawg-pac/${selectedReport}`} download + onClick={(e) => { + // track event in Google Analytics 4 + trackEvent( + 'Multi-omics Working Groups', + 'html_report_download', + profile && profile.userid + ? profile.userid.substring( + profile.userid.indexOf('|') + 1, + ) + : 'anonymous', + selectedReport, + ); + }} > Download Report @@ -71,11 +85,16 @@ function HtmlReportModal({ selectedReport, selectedReportLabel }) { HtmlReportModal.propTypes = { selectedReport: PropTypes.string, selectedReportLabel: PropTypes.string, + profile: PropTypes.shape({ + userid: PropTypes.string, + user_metadata: PropTypes.object, + }), }; HtmlReportModal.defaultProps = { selectedReport: null, selectedReportLabel: null, + profile: {}, }; export default HtmlReportModal; diff --git a/src/MultiOmicsWorkingGroups/multiOmicsWorkingGroups.jsx b/src/MultiOmicsWorkingGroups/multiOmicsWorkingGroups.jsx index 2237d76d..7d0e0f4e 100644 --- a/src/MultiOmicsWorkingGroups/multiOmicsWorkingGroups.jsx +++ b/src/MultiOmicsWorkingGroups/multiOmicsWorkingGroups.jsx @@ -1,70 +1,13 @@ -import React, { useState } from 'react'; +import React from 'react'; import { useSelector } from 'react-redux'; import { Redirect } from 'react-router-dom'; import { Helmet } from 'react-helmet'; import PageTitle from '../lib/ui/pageTitle'; -import HtmlReportModal from './htmlReportModal'; - -const proteomicsReportsDA = [ - 't55-gastrocnemius_prot-ph_DEA_report.html', - 't55-gastrocnemius_prot-pr_DEA_report.html', - 't58-heart_prot-ac_DEA_report.html', - 't58-heart_prot-ph_DEA_report.html', - 't58-heart_prot-pr_DEA_report.html', - 't59-kidney_prot-ph_DEA_report.html', - 't59-kidney_prot-pr_DEA_report.html', - 't66-lung_prot-ph_DEA_report.html', - 't66-lung_prot-pr_DEA_report.html', - 't68-liver_prot-ac_DEA_report.html', - 't68-liver_prot-ph_DEA_report.html', - 't68-liver_prot-pr_DEA_report.html', - 't70-white-adipose_prot-ph_DEA_report.html', - 't70-white-adipose_prot-pr_DEA_report.html', -]; - -const proteomicsReportsQCNorm = [ - 't55-gastrocnemius_prot-ph_qc-norm_report.html', - 't55-gastrocnemius_prot-pr_qc-norm_report.html', - 't58-heart_prot-ac_qc-norm_report.html', - 't58-heart_prot-ph_qc-norm_report.html', - 't58-heart_prot-pr_qc-norm_report.html', - 't59-kidney_prot-ph_qc-norm_report.html', - 't59-kidney_prot-pr_qc-norm_report.html', - 't66-lung_prot-ph_qc-norm_report.html', - 't66-lung_prot-pr_qc-norm_report.html', - 't68-liver_prot-ac_qc-norm_report.html', - 't68-liver_prot-ph_qc-norm_report.html', - 't68-liver_prot-pr_qc-norm_report.html', - 't70-white-adipose_prot-ph_qc-norm_report.html', - 't70-white-adipose_prot-pr_qc-norm_report.html', -]; - -const proteomics1A1CIndependentAnalyses = [ - 't55-gastrocnemius_prot-ph_1A1C-independent-analyses_report.html', - 't55-gastrocnemius_prot-pr_1A1C-independent-analyses_report.html', - 't58-heart_prot-ac_1A1C-independent-analyses_report.html', - 't58-heart_prot-ph_1A1C-independent-analyses_report.html', - 't58-heart_prot-pr_1A1C-independent-analyses_report.html', - 't59-kidney_prot-ph_1A1C-independent-analyses_report.html', - 't59-kidney_prot-pr_1A1C-independent-analyses_report.html', - 't66-lung_prot-ph_1A1C-independent-analyses_report.html', - 't66-lung_prot-pr_1A1C-independent-analyses_report.html', - 't68-liver_prot-ac_1A1C-independent-analyses_report.html', - 't68-liver_prot-ph_1A1C-independent-analyses_report.html', - 't68-liver_prot-pr_1A1C-independent-analyses_report.html', - 't70-white-adipose_prot-ph_1A1C-independent-analyses_report.html', - 't70-white-adipose_prot-pr_1A1C-independent-analyses_report.html', -]; +import BicUpdates from './bicUpdates'; +import PreCAWG from './preCAWG'; +import DawgPAC from './dawgPAC'; function MultiOmicsWorkingGroups() { - const [selectedReport, setSelectedReport] = useState(null); - const [selectedReportLabel, setSelectedReportLabel] = useState(null); - - const handleClickReport = (report, reportLabel) => { - setSelectedReport(report); - setSelectedReportLabel(reportLabel); - }; - // get states from redux store const userProfile = useSelector((state) => state.auth.profile); @@ -83,277 +26,54 @@ function MultiOmicsWorkingGroups() {
    -
    -

    BIC Updates

    -

    - The Bioinformatics Center is committed to keeping our community - informed and up-to-date with the latest developments in - bioinformatics resources, tools, and data. To this end, we provide{' '} + + {/* nav tabs */} +

    -
    -

    - PRE-CAWG: PRE-COVID Analysis Working Group -

    -

    - Processed PreCAWG data are set for internal dissemination of the - first freeze. -

    -
      -
    • - Internal freeze notes for full details on the internal freeze and - steps for onboarding to work with the PreCAWG are available{' '} - - this Google Doc - -
    • -
    • - Source code is available in{' '} - - this GitHub repository - -
    • -
    • - Data processing methods are available in{' '} - - this Google Drive folder - -
    • -
    • - Raw clinical data is available in the motrpac-data-hub bucket:{' '} - gs://motrpac-data-hub/human-precovid/phenotype/raw/ -
    • -
    -
    -
    -

    - DAWG-PAC: Data Analysis Working Group - PASS1A/1C -

    -
    PASS1A/1C: Acute exercise on young adult rats
    -

    - The goal of the acute exercise study on young adult rats (designated - as PASS1A-06) is to conduct a comprehensive analysis of the - physiological responses following a single exercise session in - 6-month-old F344 rats. The primary aim was to collect a wide range - of tissue samples post-exercise for high-quality analysis at - chemical analysis sites. -

    - + + + {/* tab panes */} +
    +
    + +
    +
    + +
    diff --git a/src/MultiOmicsWorkingGroups/preCAWG.jsx b/src/MultiOmicsWorkingGroups/preCAWG.jsx new file mode 100644 index 00000000..7a050090 --- /dev/null +++ b/src/MultiOmicsWorkingGroups/preCAWG.jsx @@ -0,0 +1,786 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import IconSet from '../lib/iconSet'; + +function PreCAWG() { + return ( +
    +

    PRE-CAWG: PRE-COVID Analysis Working Group

    +
    MoTrPAC Data Package: human-precovid-sed-adu
    + +
    + START HERE FOR ONBOARDING →{' '} + + Analysis Collaboration: Getting started step-by-step + +
    +
    2024APR01 Freeze 1.1 Release Notes
    + + + + + + + +
    +
    +
    Data package nickname:
    +
    human-precovid-sed-adu
    +
    Type:
    +
    Freeze
    +
    Distribution date:
    +
    04/01/2024 (Release)
    +
    Organism:
    +
    Human
    +
    Internal Batch:
    +
    Precovid
    +
    Baseline activity level:
    +
    Sedentary
    +
    +
    +
    +
    Age:
    +
    Adults
    +
    Modality:
    +
    resistance and endurance
    +
    Exercise duration:
    +
    acute and chronic
    +
    Freeze version:
    +
    1.1
    +
    DMAQC CRF Version:
    +
    1.06
    +
    +
    +
    Data Access
    +
    Programmatic Access via Google Cloud
    +

    + With this release, internal data access is preferred via the beta + version of a custom R package created by Christopher Jin called{' '} + + MotrpacHumanPreSuspension + + . Using this approach ensures seamless updates for any backend changes + to the data. Please review the README associated with GitHub repo to get + started and ask for help from Christopher Jin or Dan Katz (best contact + via the help desk at{' '} + + motrpac-helpdesk@lists.stanford.edu + + ) if needed. +

    +
    + As before, data can also be accessed in the following ways + programmatically: +
      +
    • + From the command line using the{' '} + + Google Cloud Command Line + {' '} + Interface +
    • +
    • + From a BIC approved download function for R such as{' '} + load_adu_norm_data (currently available only in the + functions library of the precovid-analyses GitHub repo) or{' '} + MotrpacBicQC::dl_read_gcp (package{' '} + + here + + ). +
    • +
    +
    +

    All options still require Google Cloud Command Line Interface.

    +
    Download access
    +

    + Data will be available in early April 2024 for direct download from + MoTrPAC Data Hub. +

    +
    Data Changes
    +
    Versioning
    +

    + Prior file names may have ended in “v1.txt” instead of the BIC standard + "v1.0.txt". This has been fixed. All files remain v1.0 as the underlying + standard methodology has not changed. +

    +
    QC-normalized data
    +

    + Metabolomics: during the soft release, data was scaled to{' '} + mean = 0, and sd = 1. To allow more + flexibility for analysts, this has been undone. The new version of the + data follows the following format example: +
    + + human-precovid-sed-adu_t11-adipose_metab-t-ka_qc-norm_log2_v1.0.txt + + which replaces: + + human-precovid-sed-adu_t11-adipose_metab-t-ka_qc-norm_log2-scaled_v1.txt + +

    +
    Differential analysis results
    +

    + With the release of Freeze 1, there are now differential analysis + results available. Data are for differences in changes during the acute + bout, comparing the change from pre-exercise baseline at any given + timepoint during the acute bout as compared to resting control. Results + are adjusted for age, sex, BMI, clinical site, and technical covariates. + Models are processed by variancePartition::dream to allow + for random effects models accounting for random effects of individuals. + Analytical details and methods are forthcoming. Note that files + containing these results have names annotated with “dream” to indicate + this model selection. +

    +

    + DA data location:{' '} + + gs://motrpac-data-hub/analysis/human-precovid-sed-adu/[ome]/da[ome] + {' '} + represents one of epigenomics, proteomics, metabolomics-targeted, + metabolomics-untargeted, or transcriptomics. +

    +
    Guidance
    +

    + Note that methyl-capture DA and QC-normalized data continues to be in + "beta" status. Consortium members may incorporate the data into analysis + pipelines, but please be aware that some results may change. +

    +
    2024FEB05 Soft Release
    + + + + + + + +
    +
    +
    Type:
    +
    Initial freeze
    +
    Distribution date:
    +
    02/05/2024 (Soft Release)
    +
    Organism:
    +
    Human
    +
    Internal Batch:
    +
    Precovid
    +
    Baseline activity level:
    +
    Sedentary
    +
    Age:
    +
    Adults
    +
    +
    +
    +
    Modality:
    +
    resistance and endurance
    +
    Exercise duration:
    +
    acute and chronic
    +
    Data package nickname:
    +
    human-precovid-sed-adu
    +
    Freeze version:
    +
    1.0
    +
    DMAQC CRF Version:
    +
    1.06
    +
    +
    +
    Data Notes
    +
      +
    • + The methyl capture pipeline has been developed collaboratively + BIC and the GET, and while data and metadata have been shared, the BIC + is in the final stages of validating the pipeline. Users can begin + working with the qc-normalized data, and we anticipate finalizing the + results, which might come with minor updates, in the coming weeks. +
    • +
    • + Individual level genomic data, per the genomic data sharing + plan, is considered high-risk data. As such, this data requires + additional permission to access. If you would like to work with whole + genome sequence data, please contact the BIC. +
    • +
    • + The curated biospecimens file is intended for analysts to be a + replacement for the EQC file. It has a many-to-one and one-to-many + relationship as needed between labelID, BID, pid, and vialLabel, + though any labelID-vialLabel pair should be unique. Users should be + aware that biospecimen data in this file is pertinent to the collected + sample, which is identified by the labelID. Some vialLabels, which go + off to chemical analysis, are sometimes made up of multiple combined + labelIDs. Thus, if using the biospecimens file to flag vialLabel + samples that might not meet the user's criteria, be aware only one of + the multiple labelIDs that are mixed into a vialLabel may violate a + specific biospecimen criterion. No samples have been removed from the + data package based on data from this table. Rather we have relied on + outlier analysis as described in the methods. +
    • +
    • All data sets are tab-separated .txt files.
    • +
    • + It is highly recommended that data is downloaded from Google Cloud in + one of two ways: +
        +
      • + From the command line using the{' '} + + Google Cloud Command Line + {' '} + Interface +
      • +
      • + From a BIC approved download function for R such as{' '} + load_adu_norm_data (currently available only in the + functions library of the precovid-analyses GitHub repo) or{' '} + MotrpacBicQC::dl_read_gcp (package{' '} + + here + + ). Both options still require Google Cloud Command Line Interface. +
      • +
      +
    • +
    +
    Data
    +
    Omics
    +

    + Omics data are available in both raw and QC-normalized format. The + QC-normalized data is preferred for analysis, as these data are the + result of consortium consensus imputation, normalization, batch + correction, and outlier removal decisions.{' '} + + Please note + {' '} + that in regard to raw and analyzed data “human precovid” means slightly + different things, as the precovid phase of clinical participation and + multi-omic measurement did include PED and HA participants, but these + are excluded from this analytical freeze.{' '} + Any reanalysis of the raw data must exclude these participants. +

    +

    + Raw results data location:{' '} + gs://motrpac-data-hub/human-precovid/results/ +

    +

    + QC-normalized data location:{' '} + + gs://motrpac-data-hub/analysis/human-precovid-sed-adu/[ome]/qc-norm*[ome] + {' '} + represents one of epigenomics, proteomics, metabolomics-targeted, + metabolomics-untargeted, or transcriptomics +

    +
    Clinical
    +

    + Clinical data for sedentary adults are available in the complete case + report form (CRF) data, as transferred by the DMAQC. It includes the + Actigraph minute-level analytical data processed by DMAQC. The only BIC + processing to the above files is redaction of PHI and de-identification.{' '} + A critical data table is the "Key" data set, which includes + critical demographics and the randomized group for each participant. In + these files, ds indicates the data set, while dd indicates the data + dictionary. Missing data files contain lists of missing forms and + visits, with a reason provided where applicable, and identified by + participant. +

    +

    + CRF data location:{' '} + + gs://motrpac-data-hub/human-precovid/phenotype/human-precovid-sed-adu/raw + +

    +

    + Key data set:{' '} + + gs://motrpac-data-hub/human-precovid/phenotype/human-precovid-sed-adu/raw/data_sets/human-precovid-sed-adu_clinical_key_ds_crf-redacted_v1.txt + +

    +
    + The freeze also includes a set of “curated” tables, created by the BIC + and designed to facilitate analysis. These include: +
      +
    1. + A table of vital signs and height/weight/BMI as recorded at each + visit +
    2. +
    3. + Baseline and follow up exercise parameters (CPET, 1RM, grip + strength) +
    4. +
    5. + Acute bout exercise parameters and "dose" metrics (EE and RE + separately) +
    6. +
    7. + A table of biospecimen-level data (primary key: labelID-vialLabel + pairs). This table contains data about biospecimens that might + affect multi-omic data quality. It is recommended that analysts use + this file rather than the EQC file to map samples to participants + and other metadata. +
    8. +
    9. + A table of derived variables at baseline from the Actigraph + minute-level analytical data +
    10. +
    +
    +

    + Curated clinical data location:{' '} + + gs://motrpac-data-hub/human-precovid/phenotype/human-precovid-sed-adu/curated + +

    +
    Metadata
    +
    QC reports
    +

    + These html reports show numerous quality checks of the raw data, and any + steps or graphic visualizations that were utilized in decision making + for processing raw data to the QC normalized data. +

    +

    + QC report location:{' '} + + gs://motrpac-data-hub/analysis/human-precovid-sed-adu/[ome]/metadata/*qc-report* + +

    +
    Removed samples
    +

    + These tables show lists of samples that have been removed from + qc-normalized tables for either quality reasons, or because they are + outliers. +

    +

    + Removed samples location:{' '} + + gs://motrpac-data-hub/analysis/human-precovid-sed-adu/[ome]/metadata/*removed-samples* + +

    +
    Sample metadata
    +

    + These include sample-level metadata that are ome/assay specific. This + does not include any biospecimen data or demographic data that is found + elsewhere. An example would be percent missing features for a given + sample.{' '} + + NOTE: + {' '} + it is not recommended to use these files as a source of biospecimen or + participant metadata, though the files may include such data. Rely on + centralized biospecimen and Key files. +

    +

    + Sample metadata location:{' '} + + gs://motrpac-data-hub/analysis/human-precovid-sed-adu/[ome]/metadata/*metadata_samples* + +

    +
    Feature metadata
    +

    + These tables include feature-level metadata that are ome/assay specific. + This does not include gene mapping, which is provided from a single + source. +

    +

    + Feature metadata location:{' '} + + gs://motrpac-data-hub/analysis/human-precovid-sed-adu/[ome]/metadata/*metadata_features* + +

    +
    Code
    +

    + All code for generating the data and metadata above is available at:{' '} + + https://github.com/MoTrPAC/precovid-analyses + + . The README.md describes how to interact with the data + functionally. Access can be granted by{' '} + + jzhen@stanford.edu + {' '} + or{' '} + + dankatz@stanford.edu + + . If you'd like to run or manipulate the code, please do not work from + the main repo, instead create a branch from the main using your name. + Use of other branches on the repo is not recommended. +

    +
    Methods
    +

    + The methodological description of data processing for each ome is + available on Google Drive:{' '} + + MoTrPAC MAWG Teamdrive > Pre-COVID > Writing Methods + +

    +
    + Analysis Collaboration: Getting started step-by-step +
    +
    + If you are interested in working with the PreCAWG on integrative + analysis on these data, complete the steps below: +
      +
    1. + Ensure you are listed on the required IRB for your institution. +
    2. +
    3. + Become listed as a MoTrPAC member on the main site with your + institutional email: Reach out to{' '} + + janelu@ufl.edu + +
    4. +
    5. + Obtain a Google Account using your institutional email address; + Gmail accounts are not permitted. See how{' '} + + here + + . All institutional emails are eligible to be linked to a Google + Account. +
    6. +
    7. + Obtain a Slack account through your institution/institutional email + (if your institution does not use Slack, wait for the invite - see + below). +
    8. +
    9. + Download and install the{' '} + + Google Command Line Tools + {' '} + on your preferred work computer. +
    10. +
    11. + Set up a{' '} + + GitHub account + + , and familiarize yourself with Git, GitHub, and GitHub Desktop. We + recommend GitHub desktop.{' '} + + Here is a video tutorial + + . +
    12. +
    13. + Install R and RStudio and the following MoTrPAC specific packages: +
        +
      1. + + MotrpacBicQC + {' '} + (everyone) +
      2. +
      3. + + MotrpacRatTraining6mo + {' '} + and{' '} + + MotrpacRatTraining6moData + {' '} + (for chronic exercise in 6mo rats) +
      4. +
      5. + We also recommend{' '} + + tidyverse packages + {' '} + and{' '} + + Bioconductor + +
      6. +
      +
    14. +
    15. + Email{' '} + + motrpac-helpdesk@lists.stanford.edu + + ,{' '} + + davidjm@stanford.edu + + ,{' '} + + dankatz@stanford.edu + + ,{' '} + + jzhen@stanford.edu + {' '} + and your local site PI with a written request for the + following access permissions: +
        +
      1. MoTrPAC Data Hub
      2. +
      3. Slack #precovid channel
      4. +
      5. + + MoTrPAC MAWG Teamdrive + +
      6. +
      7. + The following Google Cloud Platform Buckets:{' '} + gs://pre-cawg (read and write) and{' '} + gs://motrpac-data-hub (read only) +
      8. +
      9. + + The MoTrPAC GitHub + {' '} + with the ability to commit to{' '} + + MoTrPAC/precovid-analyses + + (assuming you want to collaborate) and access to + + MoTrPAC/MotrpacHumanPreSuspension + +
      10. +
      +
    16. +
    17. + Clone the following two GitHub repositories once you are granted + access: +
        +
      1. + + https://github.com/MoTrPAC/precovid-analyses + +
      2. +
      3. + + https://github.com/MoTrPAC/motrpac-bic-norm-qc + +
      4. +
      +
    18. +
    19. + Install the{' '} + + MoTrPAC/MotrpacHumanPreSuspension + {' '} + package - this package gives you programmatic access to the PreCAWG + data. Also review the README.md +
    20. +
    21. + Read the{' '} + + MoTrPAC/precovid-analyses + {' '} + README.md - this repo is where novel analysis code must + be stored +
    22. +
    23. + Set up your motrpac_config.json configuration file +
    24. +
    25. + Open Rstudio and attempt to run{' '} + + human-precovid-sed-adu_t07-adipose_prot-ph_metadata_qc-report_v1.Rmd + {' '} + (after pointing to your motrpac_config.json file. +
    26. +
    27. + Then ensure that{' '} + MotrpacHumanPreSuspension::load_differential_analysis{' '} + runs for you. +
    28. +
    29. If #13 and #15 are running, you are ready to go!
    30. +
    +
    +
    + ); +} + +export default PreCAWG; diff --git a/src/Navbar/navbar.jsx b/src/Navbar/navbar.jsx index e27179b6..d24aeba7 100644 --- a/src/Navbar/navbar.jsx +++ b/src/Navbar/navbar.jsx @@ -256,7 +256,9 @@ export function Navbar({ className="dropdown-item" onClick={handleDataObjectFetch} > - Endurance Training Data + {isAuthenticated && hasAccess && userType === 'internal' + ? 'Rat and Human Data' + : 'Endurance Training Data'} + + + Publications - MoTrPAC Data Hub +
    {renderPublications()}
    diff --git a/src/Search/deaSearchResultFilters.jsx b/src/Search/deaSearchResultFilters.jsx index c539a092..4a6c423a 100644 --- a/src/Search/deaSearchResultFilters.jsx +++ b/src/Search/deaSearchResultFilters.jsx @@ -7,6 +7,7 @@ import { assayList, } from '../lib/searchFilters'; import { searchParamsPropType } from './sharedlib'; +import { trackEvent } from '../GoogleAnalytics/googleAnalytics'; function SearchResultFilters({ searchParams, @@ -14,6 +15,7 @@ function SearchResultFilters({ handleSearch, resetSearch, hasResultFilters, + profile, }) { const [inputError, setInputError] = useState(false); // FIXME - this is a hack to get the search filters such as tissue and assay @@ -164,6 +166,15 @@ function SearchResultFilters({ onClick={(e) => { e.preventDefault(); handleSearch(searchParams, searchParams.keys, 'filters'); + // track event in Google Analytics 4 + trackEvent( + 'Differential Abundance Search', + 'search_filters', + profile && profile.userid + ? profile.userid.substring(profile.userid.indexOf('|') + 1) + : 'anonymous', + searchParams.keys, + ); }} disabled={inputError} > @@ -200,10 +211,15 @@ SearchResultFilters.propTypes = { sex: PropTypes.object, tissue: PropTypes.object, }), + profile: PropTypes.shape({ + userid: PropTypes.string, + user_metadata: PropTypes.object, + }), }; SearchResultFilters.defaultProps = { hasResultFilters: {}, + profile: {}, }; export default SearchResultFilters; diff --git a/src/Search/searchPage.jsx b/src/Search/searchPage.jsx index 8317bf84..959612e4 100644 --- a/src/Search/searchPage.jsx +++ b/src/Search/searchPage.jsx @@ -248,7 +248,21 @@ export function SearchPage({ (inputEl && inputEl.value && inputEl.value.length) ? formatSearchInput() : searchParams.keys, - 'all' + 'all', + ); + // track event in Google Analytics 4 + trackEvent( + 'Differential Abundance Search', + 'keyword_search', + profile && profile.userid + ? profile.userid.substring( + profile.userid.indexOf('|') + 1, + ) + : 'anonymous', + (multiSelections && multiSelections.length) || + (inputEl && inputEl.value && inputEl.value.length) + ? formatSearchInput() + : searchParams.keys, ); }} > @@ -296,6 +310,7 @@ export function SearchPage({ handleSearch={handleSearch} resetSearch={resetSearch} hasResultFilters={hasResultFilters} + profile={profile} />
    diff --git a/src/assets/icons/github.svg b/src/assets/icons/github.svg new file mode 100644 index 00000000..ccdc8f44 --- /dev/null +++ b/src/assets/icons/github.svg @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/src/assets/icons/google-cloud.svg b/src/assets/icons/google-cloud.svg new file mode 100644 index 00000000..3921c81e --- /dev/null +++ b/src/assets/icons/google-cloud.svg @@ -0,0 +1,30 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/icons/google-drive.svg b/src/assets/icons/google-drive.svg new file mode 100644 index 00000000..c361c154 --- /dev/null +++ b/src/assets/icons/google-drive.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/lib/assayList.js b/src/lib/assayList.js index 1dea4711..d6a77c1e 100644 --- a/src/lib/assayList.js +++ b/src/lib/assayList.js @@ -1,37 +1,86 @@ -const assays = [ - 'RNA-seq', - 'RRBS', - 'ATAC-seq', - 'Immunoassay', - 'Targeted 3-Hydroxyisobutyric Acid (3-HIB)', - 'Targeted Acyl-CoA', - 'Targeted Acylcarnitines', - 'Targeted Amines', - 'Targeted Amino Acids', - 'Targeted Beta-Aminoisobutyric Acid', - 'Targeted Ceramide', - 'Targeted Conventional', - 'Targeted Ethanolamides', - 'Targeted Keto Acids', - 'Targeted Nucleotides', - 'Targeted Organic Acids', - 'Targeted Oxylipins', - 'Targeted Sphingomyelin', - 'Targeted Tricarboxylic Acid Cycle', - 'Untargeted HILIC-Positive', - 'Untargeted Ion-Pair Negative', - 'Untargeted Lipidomics Reversed-Phase Negative', - 'Untargeted Lipidomics Reversed-Phase Positive', - 'Untargeted Reversed-Phase Negative', - 'Untargeted Reversed-Phase Positive', - 'Global Proteomics', - 'Phosphoproteomics', - 'Acetyl Proteomics', - 'Protein Ubiquitination', -]; - -const assayList = assays.sort((a, b) => - a.toLowerCase().localeCompare(b.toLowerCase()) -); +const assayList = { + pass1b_06: [ + 'Acetyl Proteomics', + 'ATAC-seq', + 'Global Proteomics', + 'Immunoassay', + 'Phosphoproteomics', + 'Protein Ubiquitination', + 'RNA-seq', + 'RRBS', + 'Targeted 3-Hydroxyisobutyric Acid (3-HIB)', + 'Targeted Acyl-CoA', + 'Targeted Acylcarnitines', + 'Targeted Amines', + 'Targeted Amino Acids', + 'Targeted Beta-Aminoisobutyric Acid', + 'Targeted Ceramide', + 'Targeted Conventional', + 'Targeted Ethanolamides', + 'Targeted Keto Acids', + 'Targeted Nucleotides', + 'Targeted Organic Acids', + 'Targeted Oxylipins', + 'Targeted Sphingomyelin', + 'Targeted Tricarboxylic Acid Cycle', + 'Untargeted HILIC-Positive', + 'Untargeted Ion-Pair Negative', + 'Untargeted Lipidomics Reversed-Phase Negative', + 'Untargeted Lipidomics Reversed-Phase Positive', + 'Untargeted Reversed-Phase Negative', + 'Untargeted Reversed-Phase Positive', + ], + pass1a_06: [ + 'Acetyl Proteomics', + 'ATAC-seq', + 'Global Proteomics', + 'Phosphoproteomics', + 'Protein Ubiquitination', + 'RNA-seq', + 'RRBS', + 'Targeted 3-Hydroxyisobutyric Acid (3-HIB)', + 'Targeted Acyl-CoA', + 'Targeted Acylcarnitines', + 'Targeted Amino Acids', + 'Targeted Beta-Aminoisobutyric Acid', + 'Targeted Ceramide', + 'Targeted Conventional', + 'Targeted Keto Acids', + 'Targeted Nucleotides', + 'Targeted Organic Acids', + 'Targeted Oxylipins', + 'Targeted Sphingomyelin', + 'Untargeted HILIC-Positive', + 'Untargeted Ion-Pair Negative', + 'Untargeted Lipidomics Reversed-Phase Negative', + 'Untargeted Lipidomics Reversed-Phase Positive', + 'Untargeted Reversed-Phase Negative', + 'Untargeted Reversed-Phase Positive', + ], + human_sed_adu: [ + 'ATAC-seq', + 'Global Proteomics', + 'Immunoassay for corticosteroids', + 'Immunoassay for glucagon and related metabolic hormones', + 'Immunoassay for insulin and related metabolic hormones', + 'MethylCap-seq', + 'Phosphoproteomics', + 'Proteomics Olink', + 'RNA-seq', + 'Targeted Acyl-CoA', + 'Targeted Amines', + 'Targeted Conventional', + 'Targeted Keto Acids', + 'Targeted Nucleotides', + 'Targeted Oxylipins', + 'Targeted Tricarboxylic Acid Cycle', + 'Untargeted HILIC-Positive', + 'Untargeted Ion-Pair Negative', + 'Untargeted Lipidomics Reversed-Phase Negative', + 'Untargeted Lipidomics Reversed-Phase Positive', + 'Untargeted Reversed-Phase Negative', + 'Untargeted Reversed-Phase Positive', + ], +}; export default assayList; diff --git a/src/lib/browseDataFilters.jsx b/src/lib/browseDataFilters.jsx index b49947be..20d4dfd2 100644 --- a/src/lib/browseDataFilters.jsx +++ b/src/lib/browseDataFilters.jsx @@ -1,43 +1,84 @@ import assayList from './assayList'; -const tissues = [ - 'Adrenal', - 'Aorta', - 'Blood RNA', - 'Brown Adipose', - 'Colon', - 'Cortex', - 'Gastrocnemius', - 'Heart', - 'Hippocampus', - 'Hypothalamus', - 'Kidney', - 'Liver', - 'Lung', - 'Ovaries', - 'Plasma', - 'Small Intestine', - 'Spleen', - 'Testes', - 'Vastus Lateralis', - 'Vena Cava', - 'White Adipose', -]; +export const tissues = { + pass1b_06: [ + 'Adrenal', + 'Blood RNA', + 'Brown Adipose', + 'Colon', + 'Cortex', + 'Gastrocnemius', + 'Heart', + 'Hippocampus', + 'Hypothalamus', + 'Kidney', + 'Liver', + 'Lung', + 'Ovaries', + 'Plasma', + 'Small Intestine', + 'Spleen', + 'Testes', + 'Vastus Lateralis', + 'Vena Cava', + 'White Adipose', + ], + pass1a_06: [ + 'Adrenal', + 'Aorta', + 'Blood RNA', + 'Brown Adipose', + 'Colon', + 'Cortex', + 'Gastrocnemius', + 'Heart', + 'Hippocampus', + 'Hypothalamus', + 'Kidney', + 'Liver', + 'Lung', + 'Ovaries', + 'Plasma', + 'Small Intestine', + 'Spleen', + 'Testes', + 'Tibia', + 'Vastus Lateralis', + 'White Adipose', + ], + human_sed_adu: ['Adipose', 'Blood', 'Muscle', 'Plasma'], +}; -export const tissueList = tissues.sort((a, b) => - a.toLowerCase().localeCompare(b.toLowerCase()) -); +export const omes = { + pass1b_06: [ + 'Epigenomics', + 'Metabolomics Targeted', + 'Metabolomics Untargeted', + 'Proteomics Targeted', + 'Proteomics Untargeted', + 'Transcriptomics', + ], + pass1a_06: [ + 'Epigenomics', + 'Metabolomics Targeted', + 'Metabolomics Untargeted', + 'Proteomics Untargeted', + 'Transcriptomics', + ], + human_sed_adu: [ + 'Epigenomics', + 'Metabolomics Targeted', + 'Metabolomics Untargeted', + 'Proteomics', + 'Transcriptomics', + ], +}; const browseDataFilters = [ - { - keyName: 'study', - name: 'Intervention', - filters: ['Acute Exercise', 'Endurance Training'], - }, { keyName: 'tissue_name', name: 'Tissue', - filters: tissueList, + filters: tissues, }, { keyName: 'omics', diff --git a/src/lib/iconSet.js b/src/lib/iconSet.js index 3a3e64c0..70321835 100644 --- a/src/lib/iconSet.js +++ b/src/lib/iconSet.js @@ -15,6 +15,9 @@ import Archive from '../assets/icons/archive.png'; import InternalDataRelease from '../assets/icons/data-release-internal.png'; import ArrowRightAnimated from '../assets/icons/arrow-right-animated.svg'; import ArrowDownAnimated from '../assets/icons/arrow-down-animated.svg'; +import GitHub from '../assets/icons/github.svg'; +import GoogleCloud from '../assets/icons/google-cloud.svg'; +import GoogleDrive from '../assets/icons/google-drive.svg'; const IconSet = { Clinic, @@ -34,6 +37,9 @@ const IconSet = { InternalDataRelease, ArrowRightAnimated, ArrowDownAnimated, + GitHub, + GoogleCloud, + GoogleDrive, }; export default IconSet; diff --git a/src/sass/_landingPage.scss b/src/sass/_landingPage.scss index ba6444c7..7d439a35 100644 --- a/src/sass/_landingPage.scss +++ b/src/sass/_landingPage.scss @@ -85,6 +85,7 @@ } p.hero { + font-weight: 400; margin-top: 1.75rem; a { @@ -93,10 +94,6 @@ line-height: 1.5; text-decoration: none; text-shadow: 0 0 0.1em rgba(0, 0, 0, 0.75); - - .about-motrpac-emphasis { - color: $accent-yellow; - } } } diff --git a/src/sass/_multiOmicsWorkingGroups.scss b/src/sass/_multiOmicsWorkingGroups.scss new file mode 100644 index 00000000..89c4f0ac --- /dev/null +++ b/src/sass/_multiOmicsWorkingGroups.scss @@ -0,0 +1,37 @@ +.multiOmicsWorkingGroupsPage { + .multi-omics-wg-tab-content { + .pre-cawg { + .resources-table { + th { + text-align: center; + width: 33.33%; + } + + td { + text-align: center; + vertical-align: top; + + img { + width: 6.0em; + } + } + } + + .release-notes-table { + td { + dl { + dt { + float: left; + clear: left; + margin-right: 0.5rem; + } + } + } + } + + .nested-order-list { + list-style-type: lower-alpha; + } + } + } +} \ No newline at end of file diff --git a/src/sass/browseData/_browseData.scss b/src/sass/browseData/_browseData.scss index 539561ee..40b11aae 100644 --- a/src/sass/browseData/_browseData.scss +++ b/src/sass/browseData/_browseData.scss @@ -17,6 +17,13 @@ text-decoration: none; } } + + .bd-callout-info { + ul { + padding-left: 1.0rem; + + } + } } .inline-link-with-icon .material-icons { @@ -30,6 +37,68 @@ font-size: 5.0rem; } } + + .bundle-datasets-item { + .card { + .bundle-dataset-tags { + .badge.badge-pill.badge-purple { + background-color: #6f42c1; + color: #fff; + } + } + + .card-footer { + background-color: #fff; + border-top: none; + + .ready-to-download-link { + background-color: #343a40; + border-color: #343a40; + border-radius: 0.25rem; + color: #fff; + font-size: 1rem; + font-weight: 600; + line-height: 1.5; + padding: 0.465rem 0.75rem; + text-align: center; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + + &:hover, &:focus, &:active { + background-color: #23272b; + border-color: #23272b; + text-decoration: none; + } + } + } + } + } + } + + .selective-data-downloads-card { + .card-header { + .material-icons { + font-size: 1.85rem; + } + } + + &.external-access { + max-width: 22rem; + } + } + + .data-download-selective-files { + /* tab UI temporary removed + .nav.nav-tabs { + margin-left: 15px; + margin-right: 15px; + } + */ + .link-back { + a { + text-decoration: none; + width: fit-content; + } + } } label { diff --git a/src/sass/main.scss b/src/sass/main.scss index 4c1cac94..56a3c12d 100644 --- a/src/sass/main.scss +++ b/src/sass/main.scss @@ -37,3 +37,4 @@ @import 'codeRepo/all'; @import 'mainStudy/all'; @import 'publications'; +@import 'multiOmicsWorkingGroups'; diff --git a/yarn.lock b/yarn.lock index 517c4f29..f986753f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2032,9 +2032,9 @@ ts-dedent "^2.0.0" "@storybook/csf@^0.1.2", "@storybook/csf@^0.1.4": - version "0.1.6" - resolved "https://registry.yarnpkg.com/@storybook/csf/-/csf-0.1.6.tgz#247bdf6c371b83af5c4f0bc6654954eaabdb7595" - integrity sha512-JjWnBptVhBYJ14yq+cHs66BXjykRUWQ5TlD1RhPxMOtavynYyV/Q+QR98/N+XB+mcPtFMm5I2DvNkpj0/Dk8Mw== + version "0.1.7" + resolved "https://registry.yarnpkg.com/@storybook/csf/-/csf-0.1.7.tgz#dcc6c16a353bc09c8c619ba1a23ba93b2aab0b9d" + integrity sha512-53JeLZBibjQxi0Ep+/AJTfxlofJlxy1jXcSKENlnKxHjWEYyHQCumMP5yTFjf7vhNnMjEpV3zx6t23ssFiGRyw== dependencies: type-fest "^2.19.0" @@ -2580,16 +2580,16 @@ "@types/node" "*" "@types/node@*": - version "20.12.8" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.8.tgz#35897bf2bfe3469847ab04634636de09552e8256" - integrity sha512-NU0rJLJnshZWdE/097cdCBbyW1h4hEg0xpovcoAQYHl8dnEyp/NAOiE45pvc+Bd1Dt+2r94v2eGFpQJ4R7g+2w== + version "20.12.10" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.10.tgz#8f0c3f12b0f075eee1fe20c1afb417e9765bef76" + integrity sha512-Eem5pH9pmWBHoGAT8Dr5fdc5rYA+4NAovdM4EktRPVAAiJhmWWfQrA0cFhAbOsQdSfIHjAud6YdkbL69+zSKjw== dependencies: undici-types "~5.26.4" "@types/node@^18.0.0": - version "18.19.31" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.31.tgz#b7d4a00f7cb826b60a543cebdbda5d189aaecdcd" - integrity sha512-ArgCD39YpyyrtFKIqMDvjz79jto5fcI/SVUs2HwB+f0dAzq68yqOdyaSivLiLugSziTpNXLQrVb7RZFmdZzbhA== + version "18.19.32" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.32.tgz#96e4c80dca0ccf48505add2a399f36465955e0be" + integrity sha512-2bkg93YBSDKk8DLmmHnmj/Rwr18TLx7/n+I23BigFwgexUJoMHZOd8X1OFxuF/W3NN0S2W2E5sVabI5CPinNvA== dependencies: undici-types "~5.26.4" @@ -5042,9 +5042,9 @@ ejs@^3.1.6: jake "^10.8.5" electron-to-chromium@^1.4.668: - version "1.4.756" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.756.tgz#7b872ed8c8c5bee571be771730225d6d2a37fe45" - integrity sha512-RJKZ9+vEBMeiPAvKNWyZjuYyUqMndcP1f335oHqn3BEQbs2NFtVrnK5+6Xg5wSM9TknNNpWghGDUCKGYF+xWXw== + version "1.4.758" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.758.tgz#f39e530cae2ca4329a0f0e1840629d8d1da73156" + integrity sha512-/o9x6TCdrYZBMdGeTifAP3wlF/gVT+TtWJe3BSmtNh92Mw81U9hrYwW9OAGUh+sEOX/yz5e34sksqRruZbjYrw== emittery@^0.10.2: version "0.10.2" @@ -5077,9 +5077,9 @@ encodeurl@~1.0.2: integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== enhanced-resolve@^5.16.0: - version "5.16.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz#65ec88778083056cb32487faa9aef82ed0864787" - integrity sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA== + version "5.16.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.16.1.tgz#e8bc63d51b826d6f1cbc0a150ecb5a8b0c62e567" + integrity sha512-4U5pNsuDl0EhuZpq46M5xPslstkviJuhrdobaRDBk2Jy2KO37FDAJl4lb2KlNabxT0m4MTK2UHNrsAcphE8nyw== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" @@ -7873,13 +7873,6 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - magic-string@^0.25.0, magic-string@^0.25.7: version "0.25.9" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c" @@ -10126,11 +10119,9 @@ semver@^6.0.0, semver@^6.3.0, semver@^6.3.1: integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== semver@^7.3.2, semver@^7.3.5, semver@^7.3.7, semver@^7.5.3, semver@^7.5.4: - version "7.6.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" - integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== - dependencies: - lru-cache "^6.0.0" + version "7.6.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.1.tgz#60bfe090bf907a25aa8119a72b9f90ef7ca281b2" + integrity sha512-f/vbBsu+fOiYt+lmwZV0rVwJScl46HppnOA1ZvIuBWKOTlllpyJ3bfVax76/OrhCH38dyxoDIA8K7uB963IYgA== send@0.18.0: version "0.18.0" @@ -10929,9 +10920,9 @@ to-regex-range@^5.0.1: is-number "^7.0.0" tocbot@^4.25.0: - version "4.27.19" - resolved "https://registry.yarnpkg.com/tocbot/-/tocbot-4.27.19.tgz#e288dc2a81332e05cdeb68438d5aa859733f3dbd" - integrity sha512-0yu8k0L3gCQ1OVNZnKqpbZp+kLd6qtlNEBxsb+e0G/bS0EXMl2tWqWi1Oy9knRX8rTPYfOxd/sI/OzAj3JowGg== + version "4.27.20" + resolved "https://registry.yarnpkg.com/tocbot/-/tocbot-4.27.20.tgz#c7ba627585894fa306d65b08f53f624949becf19" + integrity sha512-6M78FT20+FA5edtx7KowLvhG3gbZ6GRcEkL/0b2TcPbn6Ba+1ayI3SEVxe25zjkWGs0jd04InImaO81Hd8Hukw== toidentifier@1.0.1: version "1.0.1" @@ -12192,11 +12183,6 @@ yallist@^3.0.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2: version "1.10.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"