diff --git a/.eslintrc.js b/.eslintrc.js
index f760b896..a6a6b90d 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -1,41 +1,16 @@
module.exports = {
- "extends": [
- "airbnb",
- "plugin:prettier/recommended"
- ],
- "plugins": [
- "react-hooks",
- "prettier"
- ],
- "rules": {
- "jsx-a11y/label-has-for": 0,
- "jsx-a11y/label-has-associated-control": 0,
- "jsx-a11y/no-noninteractive-tabindex": 0,
- "jsx-a11y/control-has-associated-label": 0,
- "react-hooks/rules-of-hooks": "error",
- "react-hooks/exhaustive-deps": "warn",
- "import/no-extraneous-dependencies": [
- "error",
- {"devDependencies": true}
- ],
- "no-use-before-define": 0,
- "no-param-reassign": 0,
- "no-console": 0,
- "func-names": 0,
- "prefer-template": 0,
- "consistent-return": 0,
- "react/jsx-filename-extension": 0,
- "react/jsx-props-no-spreading": 0,
- "react/jsx-one-expression-per-line": 0,
- "react/prop-types": 0,
- "react/forbid-prop-types": 0,
- "react/no-unescaped-entities": 0,
- "react/destructuring-assignment": 0,
- "react/no-this-in-sfc": 0,
- "prettier/prettier": 0
- },
- "env": {
- "browser": true,
- "jest": true
- }
+ extends: ['airbnb', 'plugin:prettier/recommended'],
+ plugins: ['react-hooks', 'prettier'],
+ rules: {
+ 'jsx-a11y/label-has-for': 0,
+ 'jsx-a11y/label-has-associated-control': 0,
+ 'react-hooks/rules-of-hooks': 'error',
+ 'react-hooks/exhaustive-deps': 'warn',
+ 'import/no-extraneous-dependencies': ['error', { devDependencies: true }],
+ 'react/jsx-props-no-spreading': 0,
+ },
+ env: {
+ browser: true,
+ jest: true,
+ },
};
diff --git a/package.json b/package.json
index 5f389263..77a36f56 100644
--- a/package.json
+++ b/package.json
@@ -3,12 +3,13 @@
"version": "0.1.0",
"private": true,
"dependencies": {
- "auth0-js": "9.14.3",
+ "auth0-js": "9.15.0",
"axios": "^0.21.1",
"bootstrap": "4.6.0",
"chart.js": "^2.9.3",
"d3": "^5.14.2",
"dayjs": "1.8.25",
+ "ga-gtag": "^1.0.1",
"history": "4.10.1",
"jquery": "^3.5.1",
"lodash": "^4.17.11",
@@ -18,12 +19,11 @@
"react": "17.0.1",
"react-chartjs-2": "^2.8.0",
"react-dom": "17.0.1",
- "react-ga": "^3.1.2",
"react-google-recaptcha": "^2.1.0",
"react-particles-js": "3.4.1",
"react-redux": "^7.2.1",
"react-router-dom": "^5.1.2",
- "react-scripts": "4.0.2",
+ "react-scripts": "4.0.3",
"react-spring": "^8.0.20",
"redux": "^4.0.1",
"redux-thunk": "^2.3.0",
@@ -49,17 +49,17 @@
"not op_mini all"
],
"devDependencies": {
- "@storybook/addon-actions": "6.1.18",
- "@storybook/addon-links": "6.1.18",
- "@storybook/addon-storyshots": "6.1.18",
- "@storybook/addons": "6.1.18",
+ "@storybook/addon-actions": "6.1.21",
+ "@storybook/addon-links": "6.1.21",
+ "@storybook/addon-storyshots": "6.1.21",
+ "@storybook/addons": "6.1.21",
"@storybook/preset-create-react-app": "^3.1.4",
- "@storybook/react": "6.1.18",
- "@wojtekmaj/enzyme-adapter-react-17": "^0.4.1",
+ "@storybook/react": "6.1.21",
+ "@wojtekmaj/enzyme-adapter-react-17": "0.6.0",
"enzyme": "3.11.0",
"enzyme-adapter-react-16": "1.15.6",
"eslint-config-airbnb": "^18.2.0",
- "eslint-config-prettier": "7.2.0",
+ "eslint-config-prettier": "8.1.0",
"eslint-plugin-prettier": "^3.1.4",
"eslint-plugin-react-hooks": "^4.0.8",
"jest-canvas-mock": "^2.2.0",
@@ -67,6 +67,6 @@
"sass": "1.32.8",
"storybook-react-router": "1.0.8",
"stylelint": "^13.2.0",
- "stylelint-config-recommended": "^3.0.0"
+ "stylelint-config-recommended": "4.0.0"
}
}
diff --git a/src/AnalysisPage/humanDataAnalysis.jsx b/src/AnalysisPage/humanDataAnalysis.jsx
deleted file mode 100644
index ad958723..00000000
--- a/src/AnalysisPage/humanDataAnalysis.jsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import HumanGeneMetaAnalysis from './humanGeneMetaAnalysis';
-
-export default function HumanDataAnalysis({ analysis, subAnalysis }) {
- if (analysis === 'META_ANALYSIS') {
- switch (subAnalysis) {
- case 'META_ANALYSIS_PUBLIC_DATA':
- return ;
- default:
- return null;
- }
- }
-}
-
-HumanDataAnalysis.propTypes = {
- analysis: PropTypes.string.isRequired,
- subAnalysis: PropTypes.string.isRequired,
-};
diff --git a/src/AnalysisPage/humanGeneMetaAnalysis.jsx b/src/AnalysisPage/humanGeneMetaAnalysis.jsx
deleted file mode 100644
index dd54de73..00000000
--- a/src/AnalysisPage/humanGeneMetaAnalysis.jsx
+++ /dev/null
@@ -1,197 +0,0 @@
-import React, { useState } from 'react';
-import HumanMetaAnalysisAcuteMuscleGenes from '../data/humanMetaAnalysisAcuteMuscleGenes';
-
-import PlotFOXO1 from '../assets/plots/analysis/meta-analysis/human/acute-muscle/FOXO1.png';
-import PlotID1 from '../assets/plots/analysis/meta-analysis/human/acute-muscle/ID1.png';
-import PlotPPARGC1A from '../assets/plots/analysis/meta-analysis/human/acute-muscle/PPARGC1A.png';
-import PlotSMAD3 from '../assets/plots/analysis/meta-analysis/human/acute-muscle/SMAD3.png';
-import PlotVEGFA from '../assets/plots/analysis/meta-analysis/human/acute-muscle/VEGFA.png';
-
-const plotMapping = {
- FOXO1: PlotFOXO1,
- ID1: PlotID1,
- PPARGC1A: PlotPPARGC1A,
- SMAD3: PlotSMAD3,
- VEGFA: PlotVEGFA,
-};
-
-const humanMetaAnalysisAcuteMuscleGeneStats = require('../data/human_meta_analysis_acute_muscle_gene_stats');
-
-/**
- * Functional component to render human meta-analysis acute muscle data visualization
- * It uses internal states not shared by other components
- *
- * @return {Object} JSX representation of the meta analysis data visualization
- */
-function HumanGeneMetaAnalysis() {
- // Local states
- const [inputValue, setInputValue] = useState('');
- const [gene, setGene] = useState('');
-
- /**
- * Simple Math.round method
- * alternative #1 - Math.round(num * 10) / 10; //*** returns 1 decimal
- * alternative #2 - Math.round((num + 0.00001) * 100) / 100; //*** returns 2 decimals
- */
- const classificationMathRound = (number, decimals) => {
- return Number(Math.round(number + ('e' + decimals)) + ('e-' + decimals));
- };
-
- const geneObj = humanMetaAnalysisAcuteMuscleGeneStats
- .find(item => item.Symbol === gene.toUpperCase());
-
- // Renders found gene stats info in the gene search panel
- const renderGeneInfo = () => {
- if (geneObj && Object.keys(geneObj).length) {
- const geneObjClone = { ...geneObj };
- delete geneObjClone.Summary;
-
- return (
-
-
-
- {Object.entries(geneObjClone).map(([key, value]) => {
- return (
-
- {`${key}:`}
- {!Number.isNaN(classificationMathRound(Number(value), 2)) ? classificationMathRound(Number(value), 2) : value}
-
- );
- })}
-
-
- Summary:
- {geneObj.Summary}
-
-
-
-
-
- );
- }
-
- return No matching gene found.
;
- };
-
- const geneAanlysisDataArray = HumanMetaAnalysisAcuteMuscleGenes[gene.toUpperCase()]
- ? HumanMetaAnalysisAcuteMuscleGenes[gene.toUpperCase()] : null;
-
- // Renders table head of gene meta-analysis
- const renderMetaAnalysisTableHead = () => {
- return (
-
- Cohort ID
- Geo ID
- Training
- Avg Age
- Age SD
- SDD
-
- );
- };
-
- // Renders individual rows of gene meta-analysis data
- const renderMetaAnalysisTableRows = (data) => {
- const rows = data.map(item => (
-
- {item.V1}
- {item.gse}
- {item.training}
- {classificationMathRound(Number(item.avg_age), 2)}
- {classificationMathRound(Number(item.age_sd), 2)}
- {classificationMathRound(Number(item.sdd), 2)}
-
- ));
-
- return rows;
- };
-
- // Renders meta-analysis of a gene for acute muscle
- const renderMetaAnalysisData = () => {
- if (geneAanlysisDataArray && geneAanlysisDataArray.length) {
- return (
-
-
-
-
-
- {renderMetaAnalysisTableHead()}
-
-
- {renderMetaAnalysisTableRows(geneAanlysisDataArray)}
-
-
-
-
- info
- A cohort can have more than a single data point in a time window.
-
-
-
-
-
-
- );
- }
-
- return null;
- };
-
- return (
-
-
- info
-
- The following analyses use existing published data sets. They
- do not represent the complete meta-analysis data set. Only
- 5 genes (FOXO1, ID1, PPARGC1A, SMAD3, VEGFA) are available for
- searching in this release.
-
-
- ×
-
-
-
- {/* gene search */}
-
-
-
Select a gene:
-
- {renderGeneInfo()}
-
-
- {/* meta-analysis acute muscle data */}
-
-
{`Meta-Analysis${geneObj && geneObj.Symbol ? ` of ${geneObj.Symbol.toUpperCase()}` : ''} for Acute Muscle`}
- {renderMetaAnalysisData()}
-
-
-
- );
-}
-
-export default HumanGeneMetaAnalysis;
diff --git a/src/AnnouncementsPage/announcementsPage.jsx b/src/AnnouncementsPage/announcementsPage.jsx
index eb6cde67..8502eacf 100644
--- a/src/AnnouncementsPage/announcementsPage.jsx
+++ b/src/AnnouncementsPage/announcementsPage.jsx
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import dayjs from 'dayjs';
-import { TrackEvent } from '../GoogleAnalytics/googleAnalytics';
+import { trackEvent } from '../GoogleAnalytics/googleAnalytics';
import AuthContentContainer from '../lib/ui/authContentContainer';
const announcementData = require('./announcements');
@@ -77,7 +77,7 @@ function AnnouncementEntry({ entry }) {
className="inline-link-with-icon"
target="_blank"
rel="noopener noreferrer"
- onClick={TrackEvent.bind(
+ onClick={trackEvent.bind(
this,
link.gaEventCategory,
link.gaEventAction,
diff --git a/src/App/__test__/App.test.jsx b/src/App/__test__/App.test.jsx
index e51fd948..614ac833 100644
--- a/src/App/__test__/App.test.jsx
+++ b/src/App/__test__/App.test.jsx
@@ -5,8 +5,8 @@ import App from '../App';
const testUser = require('../../testData/testUser');
-// Mocking ReactGA for Google Analytics
-jest.mock('react-ga');
+// Mocking Google Analytics
+jest.mock('ga-gtag');
describe(' ', () => {
let component;
diff --git a/src/GoogleAnalytics/googleAnalytics.jsx b/src/GoogleAnalytics/googleAnalytics.jsx
index c2fab877..492e70d5 100644
--- a/src/GoogleAnalytics/googleAnalytics.jsx
+++ b/src/GoogleAnalytics/googleAnalytics.jsx
@@ -1,7 +1,7 @@
import React, { useEffect } from 'react';
-import ReactGA from 'react-ga';
+import gtag from 'ga-gtag';
-export const initializeReactGA = () => {
+const trackingId = () => {
// available tracking Ids for motrpac apps
const trackers = {
'dev.motrpac-data.org': 'UA-137588878-5',
@@ -35,21 +35,12 @@ export const initializeReactGA = () => {
// use correct tracking Id based on hostname
const tracker = trackers[analyticsTrackerHostname];
- ReactGA.initialize(tracker, {
- gaOptions: {
- cookieDomain: 'none',
- siteSpeedSampleRate: 100,
- },
- });
+ return tracker;
};
-export const withTracker = (WrappedComponent, options = {}) => {
+export const withTracker = (WrappedComponent) => {
const trackPage = (page) => {
- ReactGA.set({
- page,
- ...options,
- });
- ReactGA.pageview(page);
+ gtag('config', trackingId(), {'page_path': page, 'site_speed_sample_rate' : 100});
};
const HOC = (props) => {
@@ -64,16 +55,11 @@ export const withTracker = (WrappedComponent, options = {}) => {
return HOC;
};
-/**
- * TrackEvent - Add custom tracking event.
- * @param {string} category
- * @param {string} action
- * @param {string} label
- */
-export const TrackEvent = (category, action, label) => {
- ReactGA.event({
- category,
- action,
- label,
+export const trackEvent = (category, action, label) => {
+ gtag('event', action, {
+ event_category: category,
+ event_label: label,
});
};
+
+export default trackingId;
diff --git a/src/LandingPage/landingPage.jsx b/src/LandingPage/landingPage.jsx
index c5d10404..7d277f20 100644
--- a/src/LandingPage/landingPage.jsx
+++ b/src/LandingPage/landingPage.jsx
@@ -4,7 +4,7 @@ import { connect } from 'react-redux';
import { Redirect } from 'react-router-dom';
import Particles from 'react-particles-js';
import { useSpring, animated } from 'react-spring';
-import { TrackEvent } from '../GoogleAnalytics/googleAnalytics';
+import { trackEvent } from '../GoogleAnalytics/googleAnalytics';
import LogoAnimation from '../assets/LandingPageGraphics/LogoAnimation_03082019-yellow_pipelineball_left.gif';
import LayerRunner from '../assets/LandingPageGraphics/Data_Layer_Runner.png';
import HealthyHeart from '../assets/LandingPageGraphics/Infographic_Healthy_Heart.png';
@@ -97,7 +97,7 @@ export function LandingPage({ isAuthenticated, profile }) {
className="inline-link-with-icon"
target="_blank"
rel="noopener noreferrer"
- onClick={TrackEvent.bind(
+ onClick={trackEvent.bind(
this,
'MoTrPAC Marker Paper',
'Cell Publication',
@@ -118,7 +118,7 @@ export function LandingPage({ isAuthenticated, profile }) {
className="inline-link-with-icon"
target="_blank"
rel="noopener noreferrer"
- onClick={TrackEvent.bind(
+ onClick={trackEvent.bind(
this,
'MoTrPAC Marker Paper',
'NIH Press Release',
diff --git a/src/ReleasePage/releaseEntry.jsx b/src/ReleasePage/releaseEntry.jsx
index 70c30a34..edcedc47 100644
--- a/src/ReleasePage/releaseEntry.jsx
+++ b/src/ReleasePage/releaseEntry.jsx
@@ -1,7 +1,7 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import axios from 'axios';
-import { TrackEvent } from '../GoogleAnalytics/googleAnalytics';
+import { trackEvent } from '../GoogleAnalytics/googleAnalytics';
import IconSet from '../lib/iconSet';
import ToolTip from '../lib/ui/tooltip';
import ExternalLink from '../lib/ui/externalLink';
@@ -38,6 +38,7 @@ function ReleaseEntry({ profile, currentView }) {
status: null,
file: null,
message: '',
+ releaseVersion: null,
});
const [visibleReleases, setVisibleReleases] = useState(2);
@@ -113,7 +114,7 @@ function ReleaseEntry({ profile, currentView }) {
}
// Fetch file url from Google Storage API
- function fetchFile(bucket, filename) {
+ function fetchFile(bucket, filename, version) {
return axios.get(`https://data-link-access.motrpac-data.org/${bucket}/${filename}`)
.then((response) => {
setFileUrl(response.data.url);
@@ -121,6 +122,7 @@ function ReleaseEntry({ profile, currentView }) {
status: 'success',
file: filename,
message: 'Click this link to download the requested file.',
+ releaseVersion: version,
});
setFetching(false);
}).catch((err) => {
@@ -130,31 +132,39 @@ function ReleaseEntry({ profile, currentView }) {
status: 'error',
file: filename,
message: 'Error occurred. Please close the dialog box and try again.',
+ releaseVersion: version,
});
setFetching(false);
});
}
- // Handle modal download button click event
- function handleGAEvent(releaseVersion) {
- TrackEvent(`Release ${releaseVersion} Downloads (${currentView})`, modalStatus.file, profile.user_metadata.name);
- }
-
// Render modal message
- function renderModalMessage(releaseVersion) {
+ function renderModalMessage() {
if (modalStatus.status !== 'success') {
return {modalStatus.message} ;
}
return (
- {modalStatus.message}
+
+ {modalStatus.message}
+
);
}
// Render modal
- function renderModal(releaseVersion) {
+ function renderModal() {
return (
@@ -167,7 +177,7 @@ function ReleaseEntry({ profile, currentView }) {
{!fetching
- ? renderModalMessage(releaseVersion) :
}
+ ? renderModalMessage() :
}
Close
@@ -217,7 +227,7 @@ function ReleaseEntry({ profile, currentView }) {
className="btn-data-download"
data-toggle="modal"
data-target=".data-download-modal"
- onClick={fetchFile.bind(this, bucket, item.object_zipfile)}
+ onClick={fetchFile.bind(this, bucket, item.object_zipfile, version)}
>
save_alt
@@ -305,7 +315,7 @@ function ReleaseEntry({ profile, currentView }) {
renderDataTypeRow={renderDataTypeRow}
/>
) : null}
- {renderModal(release.version)}
+ {renderModal()}
{currentView === 'internal' && release.raw_files
diff --git a/src/assets/plots/analysis/meta-analysis/human/acute-muscle/FOXO1.png b/src/assets/plots/analysis/meta-analysis/human/acute-muscle/FOXO1.png
deleted file mode 100644
index e776506e..00000000
Binary files a/src/assets/plots/analysis/meta-analysis/human/acute-muscle/FOXO1.png and /dev/null differ
diff --git a/src/assets/plots/analysis/meta-analysis/human/acute-muscle/ID1.png b/src/assets/plots/analysis/meta-analysis/human/acute-muscle/ID1.png
deleted file mode 100644
index e776506e..00000000
Binary files a/src/assets/plots/analysis/meta-analysis/human/acute-muscle/ID1.png and /dev/null differ
diff --git a/src/assets/plots/analysis/meta-analysis/human/acute-muscle/PPARGC1A.png b/src/assets/plots/analysis/meta-analysis/human/acute-muscle/PPARGC1A.png
deleted file mode 100644
index e776506e..00000000
Binary files a/src/assets/plots/analysis/meta-analysis/human/acute-muscle/PPARGC1A.png and /dev/null differ
diff --git a/src/assets/plots/analysis/meta-analysis/human/acute-muscle/SMAD3.png b/src/assets/plots/analysis/meta-analysis/human/acute-muscle/SMAD3.png
deleted file mode 100644
index e776506e..00000000
Binary files a/src/assets/plots/analysis/meta-analysis/human/acute-muscle/SMAD3.png and /dev/null differ
diff --git a/src/assets/plots/analysis/meta-analysis/human/acute-muscle/VEGFA.png b/src/assets/plots/analysis/meta-analysis/human/acute-muscle/VEGFA.png
deleted file mode 100644
index e776506e..00000000
Binary files a/src/assets/plots/analysis/meta-analysis/human/acute-muscle/VEGFA.png and /dev/null differ
diff --git a/src/data/humanMetaAnalysisAcuteMuscleGenes.js b/src/data/humanMetaAnalysisAcuteMuscleGenes.js
deleted file mode 100644
index d9a1275d..00000000
--- a/src/data/humanMetaAnalysisAcuteMuscleGenes.js
+++ /dev/null
@@ -1,15 +0,0 @@
-const FOXO1 = require('./human_acute_muscle_genes/FOXO1');
-const ID1 = require('./human_acute_muscle_genes/ID1');
-const PPARGC1A = require('./human_acute_muscle_genes/PPARGC1A');
-const SMAD3 = require('./human_acute_muscle_genes/SMAD3');
-const VEGFA = require('./human_acute_muscle_genes/VEGFA');
-
-const HumanMetaAnalysisAcuteMuscleGenes = {
- FOXO1,
- ID1,
- PPARGC1A,
- SMAD3,
- VEGFA,
-};
-
-export default HumanMetaAnalysisAcuteMuscleGenes;
diff --git a/src/data/human_acute_muscle_genes/FOXO1.json b/src/data/human_acute_muscle_genes/FOXO1.json
deleted file mode 100644
index 710e9394..00000000
--- a/src/data/human_acute_muscle_genes/FOXO1.json
+++ /dev/null
@@ -1,6 +0,0 @@
-[
- {
- "tissue": "muscle",
- "training": "endurance"
- }
-]
diff --git a/src/data/human_acute_muscle_genes/ID1.json b/src/data/human_acute_muscle_genes/ID1.json
deleted file mode 100644
index 710e9394..00000000
--- a/src/data/human_acute_muscle_genes/ID1.json
+++ /dev/null
@@ -1,6 +0,0 @@
-[
- {
- "tissue": "muscle",
- "training": "endurance"
- }
-]
diff --git a/src/data/human_acute_muscle_genes/PPARGC1A.json b/src/data/human_acute_muscle_genes/PPARGC1A.json
deleted file mode 100644
index 710e9394..00000000
--- a/src/data/human_acute_muscle_genes/PPARGC1A.json
+++ /dev/null
@@ -1,6 +0,0 @@
-[
- {
- "tissue": "muscle",
- "training": "endurance"
- }
-]
diff --git a/src/data/human_acute_muscle_genes/SMAD3.json b/src/data/human_acute_muscle_genes/SMAD3.json
deleted file mode 100644
index 710e9394..00000000
--- a/src/data/human_acute_muscle_genes/SMAD3.json
+++ /dev/null
@@ -1,6 +0,0 @@
-[
- {
- "tissue": "muscle",
- "training": "endurance"
- }
-]
diff --git a/src/data/human_acute_muscle_genes/VEGFA.json b/src/data/human_acute_muscle_genes/VEGFA.json
deleted file mode 100644
index 710e9394..00000000
--- a/src/data/human_acute_muscle_genes/VEGFA.json
+++ /dev/null
@@ -1,6 +0,0 @@
-[
- {
- "tissue": "muscle",
- "training": "endurance"
- }
-]
diff --git a/src/data/human_meta_analysis_acute_muscle_gene_stats.json b/src/data/human_meta_analysis_acute_muscle_gene_stats.json
deleted file mode 100644
index 39d5161f..00000000
--- a/src/data/human_meta_analysis_acute_muscle_gene_stats.json
+++ /dev/null
@@ -1,8 +0,0 @@
-[
- {
- "Symbol": "PCMTD2",
- "Entrez": "55251",
- "SelectedModel": "training",
- "Selected": "FALSE"
- }
-]
diff --git a/src/index.js b/src/index.js
index 7f330630..55e25025 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,12 +1,12 @@
import React from 'react';
import { render } from 'react-dom';
-import { initializeReactGA } from './GoogleAnalytics/googleAnalytics';
+import { install } from 'ga-gtag';
+import trackingId from './GoogleAnalytics/googleAnalytics';
import App from './App/App';
import * as serviceWorker from './serviceWorker';
import './main.css';
-// Initialize Google Analytics
-initializeReactGA();
+install(trackingId());
render( , document.getElementById('root'));