diff --git a/index.html b/index.html
index 3908f05f7..1be3025f4 100644
--- a/index.html
+++ b/index.html
@@ -14,6 +14,10 @@
})(window, document, "script", "dataLayer", "GTM-KB579ZN7");
+
+
Timelapse Feature Explorer
diff --git a/src/Viewer.tsx b/src/Viewer.tsx
index a18f0601c..742014100 100644
--- a/src/Viewer.tsx
+++ b/src/Viewer.tsx
@@ -34,7 +34,7 @@ import { useConstructor, useDebounce, useRecentCollections } from "./colorizer/u
import * as urlUtils from "./colorizer/utils/url_utils";
import { SCATTERPLOT_TIME_FEATURE } from "./components/Tabs/scatter_plot_data_utils";
import { DEFAULT_PLAYBACK_FPS } from "./constants";
-import { FlexRowAlignCenter } from "./styles/utils";
+import { FlexRow, FlexRowAlignCenter } from "./styles/utils";
import { LocationState } from "./types";
import Collection from "./colorizer/Collection";
@@ -51,6 +51,7 @@ import ColorRampDropdown from "./components/Dropdowns/ColorRampDropdown";
import HelpDropdown from "./components/Dropdowns/HelpDropdown";
import SelectionDropdown from "./components/Dropdowns/SelectionDropdown";
import Export from "./components/Export";
+import GlossaryPanel from "./components/GlossaryPanel";
import Header from "./components/Header";
import HoverTooltip from "./components/HoverTooltip";
import IconButton from "./components/IconButton";
@@ -834,19 +835,37 @@ function Viewer(): ReactElement {
items={collection?.getDatasetKeys() || []}
onChange={handleDatasetChange}
/>
- {
- if (value !== featureKey && dataset) {
- replaceFeature(dataset, value);
- resetColorRampRangeToDefaults(dataset, value);
- reportFeatureSelected(dataset, value);
- }
- }}
- />
+
+
+ //
+ // {featureKey && dataset?.getFeatureNameWithUnits(featureKey)}
+ //
+ //
+ // {dataset?.getFeatureData(featureKey)?.description}
+ //
+ //
+ // ) : (
+ // dataset?.getFeatureNameWithUnits(featureKey)
+ // )
+ selected={featureKey}
+ items={getFeatureDropdownData()}
+ onChange={(value) => {
+ if (value !== featureKey && dataset) {
+ replaceFeature(dataset, value);
+ resetColorRampRangeToDefaults(dataset, value);
+ reportFeatureSelected(dataset, value);
+ }
+ }}
+ />
+
+
({ modalContain
/** Applies theme as CSS variables that affect the rest of the document. */
const CssContainer = styled.div`
- @import url("https://fonts.googleapis.com/css2?family=Lato&display=swap");
-
@font-face {
font-family: LatoExtended;
font-style: normal;
diff --git a/src/components/GlossaryPanel.tsx b/src/components/GlossaryPanel.tsx
new file mode 100644
index 000000000..e55d1d24b
--- /dev/null
+++ b/src/components/GlossaryPanel.tsx
@@ -0,0 +1,113 @@
+import { ReadOutlined } from "@ant-design/icons";
+import { Divider, Drawer, Radio, RadioChangeEvent, Tooltip } from "antd";
+import React, { ReactElement, useContext, useMemo, useState } from "react";
+import styled from "styled-components";
+
+import { Dataset } from "../colorizer";
+import { FlexColumn, FlexRowAlignCenter } from "../styles/utils";
+
+import { AppThemeContext } from "./AppStyle";
+import IconButton from "./IconButton";
+
+type GlossaryPanelProps = {
+ dataset: Dataset | null;
+};
+
+const StyledDrawer = styled(Drawer)`
+ .ant-drawer-body {
+ padding-top: 16px;
+ }
+
+ .ant-drawer-header-title {
+ // Move the close button to the right corner of the header
+ display: flex;
+ flex-direction: row-reverse;
+ }
+
+ p {
+ margin: 0;
+ }
+`;
+
+export default function GlossaryPanel(props: GlossaryPanelProps): ReactElement {
+ const [showPanel, setShowPanel] = useState(false);
+ const [alphabetizeFeatures, setAlphabetizeFeatures] = useState(false);
+
+ const theme = useContext(AppThemeContext);
+
+ const drawerContent = useMemo(() => {
+ const dataset = props.dataset;
+ if (dataset === null) {
+ return null;
+ }
+ const allFeatureData = dataset.featureKeys.map((featureKey) => dataset.getFeatureData(featureKey)!);
+ if (alphabetizeFeatures) {
+ allFeatureData.sort((a, b) => a.name.localeCompare(b.name));
+ }
+
+ return (
+
+ {allFeatureData.map((featureData) => {
+ const hasDescription = featureData.description && featureData.description !== "";
+ const key = featureData.key;
+ return (
+
+
+ {dataset.getFeatureNameWithUnits(key)}
+
+
+ {featureData.description}
+
+ );
+ })}
+
+ );
+ }, [props.dataset, alphabetizeFeatures]);
+
+ return (
+ <>
+
+ {
+ setShowPanel(true);
+ }}
+ disabled={!props.dataset}
+ >
+
+
+
+ {
+ setShowPanel(false);
+ }}
+ title={Feature glossary}
+ open={showPanel}
+ size="large"
+ style={{ color: theme.color.text.primary }}
+ >
+
+
+
+ Sort by
+
+ setAlphabetizeFeatures(e.target.value)}
+ >
+ Feature order
+ Alphabetical
+
+
+
+ {drawerContent}
+
+
+ >
+ );
+}
diff --git a/src/routes/LandingPage.tsx b/src/routes/LandingPage.tsx
index d464a7d8e..52678a12d 100644
--- a/src/routes/LandingPage.tsx
+++ b/src/routes/LandingPage.tsx
@@ -1,5 +1,3 @@
-import { faUpRightFromSquare } from "@fortawesome/free-solid-svg-icons";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Button, Divider, Tooltip } from "antd";
import React, { lazy, ReactElement, Suspense } from "react";
import { Link, useNavigate } from "react-router-dom";
@@ -7,7 +5,7 @@ import styled from "styled-components";
import { Dataset } from "../colorizer";
import { paramsToUrlQueryString } from "../colorizer/utils/url_utils";
-import { FlexColumn, FlexColumnAlignCenter, FlexRowAlignCenter, VisuallyHidden } from "../styles/utils";
+import { ExternalLink, FlexColumn, FlexColumnAlignCenter, FlexRowAlignCenter, VisuallyHidden } from "../styles/utils";
import { DatasetEntry, LocationState, ProjectEntry } from "../types";
import { PageRoutes } from "./index";
@@ -92,7 +90,7 @@ const FeatureHighlightsItem = styled(FlexColumn)`
grid-row: span 2;
& > h3 {
- font-weight: 600;
+ font-weight: bold;
}
`;
@@ -127,7 +125,7 @@ const ProjectCard = styled.li`
gap: 0px;
& h3 {
- font-weight: 600;
+ font-weight: bold;
}
& p,
@@ -188,7 +186,7 @@ const InReviewFlag = styled(FlexRowAlignCenter)`
& > p {
color: var(--color-flag-text);
font-size: 10px;
- font-weight: 700;
+ font-weight: bold;
white-space: nowrap;
}
`;
@@ -253,12 +251,7 @@ export default function LandingPage(): ReactElement {
const publicationElement = project.publicationLink ? (
Related publication:{" "}
-
- {project.publicationName}
- {/* Icon offset slightly to align with text */}
-
- (opens in new tab)
-
+ {project.publicationName}
) : null;
diff --git a/src/styles/utils.tsx b/src/styles/utils.tsx
index 6249e280e..114dd65ab 100644
--- a/src/styles/utils.tsx
+++ b/src/styles/utils.tsx
@@ -82,6 +82,7 @@ export function ExternalLink(props: { href: string; children: React.ReactNode })
{props.children}
+ (opens in new tab)
);
}