diff --git a/client/__tests__/e2e/__snapshots__/e2e.test.js.snap b/client/__tests__/e2e/__snapshots__/e2e.test.js.snap index fce4a085..e7207fb7 100644 --- a/client/__tests__/e2e/__snapshots__/e2e.test.js.snap +++ b/client/__tests__/e2e/__snapshots__/e2e.test.js.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`did launch page launched 1`] = `"pbmc3kc3k"`; +exports[`did launch page launched 1`] = `"pbmc3kc3k"`; exports[`metadata loads categories and values from dataset appear 1`] = `"
louvainvain
tint
"`; diff --git a/client/src/components/categorical/category/index.js b/client/src/components/categorical/category/index.js index 90999deb..6fc628f1 100644 --- a/client/src/components/categorical/category/index.js +++ b/client/src/components/categorical/category/index.js @@ -491,19 +491,7 @@ const CategoryRender = React.memo( /* Entire category has a single value, special case. */ - const theOneValue = categorySummary.categoryValues[0]; - return ( -
- - - {metadataField} - - - - {`: ${theOneValue}`} - -
- ); + return null; } /* diff --git a/client/src/components/infoDrawer/infoDrawer.js b/client/src/components/infoDrawer/infoDrawer.js new file mode 100644 index 00000000..047e5017 --- /dev/null +++ b/client/src/components/infoDrawer/infoDrawer.js @@ -0,0 +1,152 @@ +import React, { PureComponent } from "react"; +import { connect, shallowEqual } from "react-redux"; +import { Drawer, H3, H1, UL, Classes } from "@blueprintjs/core"; +import Async from "react-async"; +import { + selectableCategoryNames, + createCategorySummaryFromDfCol, +} from "../../util/stateManager/controlsHelpers"; + +@connect((state) => { + return { + annoMatrix: state.annoMatrix, + schema: state.annoMatrix.schema, + datasetTitle: state.config?.displayNames?.dataset ?? "", + aboutURL: state.config?.links?.["about-dataset"], + isOpen: state.controls.datasetDrawer, + }; +}) +class InfoDrawer extends PureComponent { + static watchAsync(props, prevProps) { + return !shallowEqual(props.watchProps, prevProps.watchProps); + } + + fetchAsyncProps = async (props) => { + const { schema } = props.watchProps; + const { annoMatrix } = this.props; + + const allCategoryNames = selectableCategoryNames(schema).sort(); + + const nonUserAnnoCategories = allCategoryNames.map((catName) => { + const isUserAnno = schema?.annotations?.obsByName[catName]?.writable; + if (!isUserAnno) return annoMatrix.fetch("obs", catName); + return null; + }); + const singleValueCategories = ( + await Promise.all(nonUserAnnoCategories) + ).reduce((acc, categoryData, i) => { + const catName = allCategoryNames[i]; + + const column = categoryData.icol(0); + const colSchema = schema.annotations.obsByName[catName]; + + const categorySummary = createCategorySummaryFromDfCol(column, colSchema); + + const { numCategoryValues } = categorySummary; + // Add to the array if the category has only one value + if (numCategoryValues === 1) { + acc.set(catName, categorySummary.allCategoryValues[0]); + } + return acc; + }, new Map()); + + return { singleValueCategories }; + }; + + handleClose = () => { + const { dispatch } = this.props; + + dispatch({ type: "toggle dataset drawer" }); + }; + + render() { + const { position, aboutURL, datasetTitle, schema, isOpen } = this.props; + + return ( + + + + + + + {(error) => { + console.error(error); + return Failed to load info; + }} + + + {(asyncProps) => { + const { singleValueCategories } = asyncProps; + return ( + + ); + }} + + + + ); + } +} + +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 ( +
+

{datasetTitle}

+ {singleValueCategories.size > 0 && ( + <> +

+ Dataset Metadata +

+ + + )} + {aboutURL && ( + <> +

More Info

+ + {aboutURL} + + + )} +
+ ); +}; +export default InfoDrawer; diff --git a/client/src/components/leftSidebar/topLeftLogoAndTitle.js b/client/src/components/leftSidebar/topLeftLogoAndTitle.js index ee274b6f..f2346593 100644 --- a/client/src/components/leftSidebar/topLeftLogoAndTitle.js +++ b/client/src/components/leftSidebar/topLeftLogoAndTitle.js @@ -1,22 +1,27 @@ // jshint esversion: 6 import React from "react"; import { connect } from "react-redux"; +import { Button } from "@blueprintjs/core"; +import { IconNames } from "@blueprintjs/icons"; + import * as globals from "../../globals"; import Logo from "../framework/logo"; import Truncate from "../util/truncate"; +import InfoDrawer from "../infoDrawer/infoDrawer"; -const DATASET_TITLE_WIDTH = 190; const DATASET_TITLE_FONT_SIZE = 14; @connect((state) => ({ datasetTitle: state.config?.displayNames?.dataset ?? "", - aboutURL: state.config?.links?.["about-dataset"], - scatterplotXXaccessor: state.controls.scatterplotXXaccessor, - scatterplotYYaccessor: state.controls.scatterplotYYaccessor, })) class LeftSideBar extends React.Component { + handleClick = () => { + const { dispatch } = this.props; + dispatch({ type: "toggle dataset drawer" }); + }; + render() { - const { datasetTitle, aboutURL } = this.props; + const { datasetTitle } = this.props; return (
gene -
- {aboutURL ? ( - - - {datasetTitle} - - - ) : ( - - - {datasetTitle} - - - )} -
+ + + {datasetTitle} + + + +
); } diff --git a/client/src/components/menubar/index.js b/client/src/components/menubar/index.js index c06ece70..3fd840c0 100644 --- a/client/src/components/menubar/index.js +++ b/client/src/components/menubar/index.js @@ -250,10 +250,7 @@ class MenuBar extends React.PureComponent { > { + dispatch({ type: "toggle dataset drawer" }); +}; + const InformationMenu = React.memo((props) => { - const { libraryVersions, aboutLink, tosURL, privacyURL } = props; + const { libraryVersions, tosURL, privacyURL, dispatch } = props; return (
- {aboutLink ? ( - - ) : ( - "" - )} + handleClick(dispatch)} + icon={IconNames.BOOK} + text="Dataset Overview" + /> { @@ -162,6 +165,12 @@ const Controls = ( scatterplotYYaccessor: null, }; + /************************** + Dataset Drawer + **************************/ + case "toggle dataset drawer": + return { ...state, datasetDrawer: !state.datasetDrawer }; + default: return state; }