Pull config values into dataset overview drawer (#1814)

This PR adds multiple data to the dataset overview drawer provided by the config endpoint and formats them accordingly.  The appearance of this new data is contingent on `dataPortalProps.corpora_schema_version === "1.0.0"`

For QA launch cellxgene with a remixed dataset and click on the button in the upper left-hand corner or the updated button in the info menu.


![image](https://user-images.githubusercontent.com/8716829/92670435-de966280-f2c8-11ea-87f1-8591c959a586.png)


~~Review opening is blocked by merge of #1805~~

---

Closes #1319
This commit is contained in:
Severiano Badajoz
2020-09-10 16:41:05 -07:00
committed by GitHub
parent 89b68723cc
commit 5583e91392
5 changed files with 219 additions and 59 deletions
+1
View File
@@ -39,6 +39,7 @@ module.exports = {
},
},
rules: {
"react/jsx-no-target-blank": "off",
"eslint-comments/require-description": ["error"],
"no-magic-numbers": "off",
"no-nested-ternary": "off",
+22 -56
View File
@@ -1,7 +1,9 @@
import React, { PureComponent } from "react";
import { connect, shallowEqual } from "react-redux";
import { Drawer, H3, H1, UL, Classes } from "@blueprintjs/core";
import { Drawer } from "@blueprintjs/core";
import Async from "react-async";
import InfoFormat from "./infoFormat";
import {
selectableCategoryNames,
createCategorySummaryFromDfCol,
@@ -14,6 +16,7 @@ import {
datasetTitle: state.config?.displayNames?.dataset ?? "",
aboutURL: state.config?.links?.["about-dataset"],
isOpen: state.controls.datasetDrawer,
dataPortalProps: state.config?.["corpora_props"] ?? {},
};
})
class InfoDrawer extends PureComponent {
@@ -60,7 +63,14 @@ class InfoDrawer extends PureComponent {
};
render() {
const { position, aboutURL, datasetTitle, schema, isOpen } = this.props;
const {
position,
aboutURL,
datasetTitle,
schema,
isOpen,
dataPortalProps,
} = this.props;
return (
<Drawer
@@ -74,7 +84,10 @@ class InfoDrawer extends PureComponent {
watchProps={{ schema }}
>
<Async.Pending>
<InfoFormat skeleton {...{ datasetTitle, aboutURL }} />
<InfoFormat
skeleton
{...{ datasetTitle, aboutURL, dataPortalProps }}
/>
</Async.Pending>
<Async.Rejected>
{(error) => {
@@ -87,7 +100,12 @@ class InfoDrawer extends PureComponent {
const { singleValueCategories } = asyncProps;
return (
<InfoFormat
{...{ datasetTitle, aboutURL, singleValueCategories }}
{...{
datasetTitle,
aboutURL,
singleValueCategories,
dataPortalProps,
}}
/>
);
}}
@@ -97,56 +115,4 @@ class InfoDrawer extends PureComponent {
);
}
}
const NUM_CATEGORIES = 8;
const singleValueCategoriesPlaceholder = Array.from(Array(NUM_CATEGORIES)).map(
(_, index) => {
return [index, index];
}
);
const InfoFormat = ({
datasetTitle,
singleValueCategories = new Map(singleValueCategoriesPlaceholder),
aboutURL = "thisisabouthtelengthofaurl",
skeleton = false,
}) => {
return (
<div style={{ margin: 24 }}>
<H1 className={skeleton ? Classes.SKELETON : null}>{datasetTitle}</H1>
{singleValueCategories.size > 0 && (
<>
<H3 className={skeleton ? Classes.SKELETON : null}>
Dataset Metadata
</H3>
<UL>
{Array.from(singleValueCategories).map((pair) => {
if (!pair[1] || pair[1] === "") return null;
return (
<li
className={skeleton ? Classes.SKELETON : null}
key={pair[0]}
>{`${pair[0]}: ${pair[1]}`}</li>
);
})}
</UL>
</>
)}
{aboutURL && (
<>
<H3 className={skeleton ? Classes.SKELETON : null}>More Info</H3>
<a
className={skeleton ? Classes.SKELETON : null}
href={aboutURL}
target="_blank"
rel="noopener noreferrer"
>
{aboutURL}
</a>
</>
)}
</div>
);
};
export default InfoDrawer;
@@ -0,0 +1,194 @@
import { H3, H1, UL, Classes } from "@blueprintjs/core";
import React from "react";
const renderContributors = (contributors, affiliations, skeleton) => {
// eslint-disable-next-line no-constant-condition -- Temp removed contributor section to avoid publishing PII
if (contributors?.length === 0 && true) return null;
return (
<>
<H3 className={skeleton ? Classes.SKELETON : null}>Contributors</H3>
<p className={skeleton ? Classes.SKELETON : null}>
{contributors.map((contributor) => {
const { email, name, institution } = contributor;
return (
<span key={name}>
{name}
{email && `(${email})`}
<sup>{affiliations.indexOf(institution) + 1}</sup>
</span>
);
})}
</p>
{renderAffiliations(affiliations, skeleton)}
</>
);
};
const buildAffiliations = (contributors = []) => {
const affiliations = [];
contributors.forEach((contributor) => {
const { institution } = contributor;
if (affiliations.indexOf(institution) === -1) {
affiliations.push(institution);
}
});
return affiliations;
};
const renderAffiliations = (affiliations, skeleton) => {
if (affiliations.length === 0) return null;
return (
<>
<H3 className={skeleton ? Classes.SKELETON : null}>Affiliations</H3>
<UL>
{affiliations.map((item, index) => (
<div
id={`#afil${index}`}
key={item}
className={skeleton ? Classes.SKELETON : null}
>
<sup>{index + 1}</sup>
{" "}
{item}
</div>
))}
</UL>
</>
);
};
const renderDOILink = (type, doi, skeleton) => {
if (!doi) return null;
return (
doi && (
<>
<H3 className={skeleton ? Classes.SKELETON : null}>{type}</H3>
<p className={skeleton ? Classes.SKELETON : null}>
<a href={doi} target="_blank" rel="noopener">
{doi}
</a>
</p>
</>
)
);
};
const renderOrganism = (organism, skeleton) => {
if (!organism) return null;
return (
<>
<H3 className={skeleton ? Classes.SKELETON : null}>Organism</H3>
<p className={skeleton ? Classes.SKELETON : null}>{organism}</p>
</>
);
};
const renderSingleValueCategories = (singleValueCategories, skeleton) => {
if (singleValueCategories.size === 0) return null;
return (
<>
<H3 className={skeleton ? Classes.SKELETON : null}>Dataset Metadata</H3>
<UL>
{Array.from(singleValueCategories).map((pair) => {
if (!pair[1] || pair[1] === "") return null;
return (
<li
className={skeleton ? Classes.SKELETON : null}
key={pair[0]}
>{`${pair[0]}: ${pair[1]}`}</li>
);
})}
</UL>
</>
);
};
const renderLinks = (projectLinks, aboutURL, skeleton) => {
if (!projectLinks && !aboutURL) return null;
if (projectLinks)
return (
<>
<H3 className={skeleton ? Classes.SKELETON : null}>Project Links</H3>
<UL>
{projectLinks.map((link) => {
if (link.link_type === "SUMMARY") return null;
return (
<li
key={link.link_name}
className={skeleton ? Classes.SKELETON : null}
>
<a href={link.link_url} target="_blank" rel="noopener">
{link.link_name}
</a>
</li>
);
})}
</UL>
</>
);
return (
<>
<H3 className={skeleton ? Classes.SKELETON : null}>More Info</H3>
<p>
<a
className={skeleton ? Classes.SKELETON : null}
href={aboutURL}
target="_blank"
rel="noopener"
>
{aboutURL}
</a>
</p>
</>
);
};
const NUM_CATEGORIES = 8;
const singleValueCategoriesPlaceholder = Array.from(Array(NUM_CATEGORIES)).map(
(_, index) => {
return [index, index];
}
);
const InfoFormat = React.memo(
({
datasetTitle,
singleValueCategories = new Map(singleValueCategoriesPlaceholder),
aboutURL = "thisisabouthtelengthofaurl",
dataPortalProps = {},
skeleton = false,
}) => {
if (dataPortalProps.corpora_schema_version === "1.0.0") {
dataPortalProps = {};
}
const {
title,
publication_doi: doi,
preprint_doi: preprintDOI,
organism,
contributors,
project_links: projectLinks,
} = dataPortalProps;
const affiliations = buildAffiliations(contributors);
return (
<div style={{ margin: 24, overflow: "auto" }}>
<H1 className={skeleton ? Classes.SKELETON : null}>
{title ?? datasetTitle}
</H1>
{renderContributors(contributors, affiliations, skeleton)}
{renderDOILink("DOI", doi, skeleton)}
{renderDOILink("Preprint DOI", preprintDOI, skeleton)}
{renderOrganism(organism, skeleton)}
{renderSingleValueCategories(singleValueCategories, skeleton)}
{renderLinks(projectLinks, aboutURL, skeleton)}
</div>
);
}
);
export default InfoFormat;
+2 -2
View File
@@ -84,7 +84,7 @@ class TermsPrompt extends React.PureComponent {
}}
href={tosURL}
target="_blank"
rel="noopener noreferrer"
rel="noopener"
>
terms of service
</a>
@@ -106,7 +106,7 @@ class TermsPrompt extends React.PureComponent {
}}
href={privacyURL}
target="_blank"
rel="noopener noreferrer"
rel="noopener"
>
privacy policy
</a>
-1
View File
@@ -21,7 +21,6 @@ const Controls = (
scatterplotYYaccessor: null,
graphRenderCounter: 0 /* integer as <Component key={graphRenderCounter} - a change in key forces a remount */,
singletonHover: false,
datasetDrawer: false,
},
action