Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[preview 1] Move panel toggles to control headers #1707

22 changes: 0 additions & 22 deletions src/components/controls/annotatedHeader.js

This file was deleted.

32 changes: 32 additions & 0 deletions src/components/controls/annotatedHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from "react";
import { FaInfoCircle } from "react-icons/fa";
import {StyledTooltip, HeaderIconContainer, HeaderContainer, HeaderTitle} from "./styles";

type Props = {
toggle?: JSX.Element
title: string
tooltip: JSX.Element
mobile: boolean
}

export const AnnotatedHeader = ({toggle=undefined, title, tooltip, mobile}: Props) => {
return (
<HeaderContainer>
<div>
<HeaderTitle>{title}</HeaderTitle>
{tooltip && !mobile && (
<>
<HeaderIconContainer data-tip data-for={title}>
<FaInfoCircle />
</HeaderIconContainer>
<StyledTooltip place="bottom" type="dark" effect="solid" id={title}>
{tooltip}
</StyledTooltip>
</>
)}
</div>
{toggle !== undefined && toggle}
</HeaderContainer>
);
};

84 changes: 73 additions & 11 deletions src/components/controls/controls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,37 @@ import GeoResolution from "./geo-resolution";
import TransmissionLines from './transmission-lines';
import NormalizeFrequencies from "./frequency-normalization";
import AnimationOptions from "./animation-options";
import PanelToggles from "./panel-toggles";
import PanelToggle from "./panel-toggle";
import ToggleTangle from "./toggle-tangle";
import Language from "./language";
import { ControlsContainer } from "./styles";
import FilterData, {FilterInfo} from "./filter";
import {TreeOptionsInfo, MapOptionsInfo, AnimationOptionsInfo, PanelOptionsInfo,
ExplodeTreeInfo, FrequencyInfo, MeasurementsOptionsInfo} from "./miscInfoText";
import {TreeInfo, MapInfo, AnimationOptionsInfo, PanelLayoutInfo,
ExplodeTreeInfo, FrequencyInfo, MeasurementsInfo} from "./miscInfoText";
import { AnnotatedHeader } from "./annotatedHeader";
import MeasurementsOptions from "./measurementsOptions";
import { useSelector } from "react-redux";

// Interface to represent the entire Redux store.
// Since most of the codebase is not typed yet, add types manually¹ for now.
// TODO: Move this to src/store.
// ¹ https://react-redux.js.org/using-react-redux/usage-with-typescript#typing-hooks-manually
interface RootState {
controls: {
panelsAvailable: string[]
panelsToDisplay: string[]
showTreeToo: boolean
canTogglePanelLayout: boolean

// This allows arbitrary prop names while TypeScript adoption is incomplete.
// TODO: add all other props explicitly and remove this.
[propName: string]: any;
}

// This allows arbitrary prop names while TypeScript adoption is incomplete.
// TODO: add all other props explicitly and remove this.
[propName: string]: any;
}

type Props = {
treeOn: boolean
Expand All @@ -37,6 +59,10 @@ type Props = {
function Controls({ treeOn, mapOn, frequenciesOn, measurementsOn, mobileDisplay }: Props) {
const { t } = useTranslation();

const panelsAvailable = useSelector((state: RootState) => state.controls.panelsAvailable);
const showTreeToo = useSelector((state: RootState) => state.controls.showTreeToo);
const canTogglePanelLayout = useSelector((state: RootState) => state.controls.canTogglePanelLayout);

return (
<ControlsContainer>
<ChooseDataset />
Expand All @@ -51,9 +77,25 @@ function Controls({ treeOn, mapOn, frequenciesOn, measurementsOn, mobileDisplay
<AnnotatedHeader title={t("sidebar:Filter Data")} tooltip={FilterInfo} mobile={mobileDisplay}/>
<FilterData measurementsOn={measurementsOn} />

{canTogglePanelLayout &&
<>
<span style={{ paddingTop: "10px" }} />
{/* FIXME: update translations */}
<AnnotatedHeader title={t("sidebar:Layout")} tooltip={PanelLayoutInfo} mobile={mobileDisplay} />
<PanelLayout />
</>
}

{panelsAvailable.includes("tree") &&
<AnnotatedHeader
toggle={<PanelToggle panel="tree" on={treeOn} />}
title={t("sidebar:Tree")}
tooltip={TreeInfo}
mobile={mobileDisplay}
/>
}
{treeOn &&
<span>
<AnnotatedHeader title={t("sidebar:Tree Options")} tooltip={TreeOptionsInfo} mobile={mobileDisplay}/>
<ChooseLayout />
<ChooseMetric />
<ChooseBranchLabelling />
Expand All @@ -64,24 +106,48 @@ function Controls({ treeOn, mapOn, frequenciesOn, measurementsOn, mobileDisplay
</span>
}

{panelsAvailable.includes("measurements") &&
<AnnotatedHeader
toggle={<PanelToggle panel="measurements" on={measurementsOn} />}
title={t("sidebar:Measurements")}
tooltip={MeasurementsInfo}
mobile={mobileDisplay}
/>
}
{measurementsOn &&
<span style={{ marginTop: "10px" }}>
<AnnotatedHeader title={t("sidebar:Measurements Options")} tooltip={MeasurementsOptionsInfo} mobile={mobileDisplay}/>
<MeasurementsOptions />
</span>
}

{/* Prevent the map from being toggled on when a second tree is visible.
It is hidden by logic elsewhere.
*/}
{panelsAvailable.includes("map") && !showTreeToo &&
<AnnotatedHeader
toggle={<PanelToggle panel="map" on={mapOn} />}
title={t("sidebar:Map")}
tooltip={MapInfo}
mobile={mobileDisplay}
/>
}
{mapOn &&
<span style={{ marginTop: "10px" }}>
<AnnotatedHeader title={t("sidebar:Map Options")} tooltip={MapOptionsInfo} mobile={mobileDisplay}/>
<GeoResolution />
<TransmissionLines />
</span>
}

{panelsAvailable.includes("frequencies") &&
<AnnotatedHeader
toggle={<PanelToggle panel="frequencies" on={frequenciesOn} />}
title={t("sidebar:Frequency")}
tooltip={FrequencyInfo}
mobile={mobileDisplay}
/>
}
{frequenciesOn &&
<span style={{ marginTop: "10px" }}>
<AnnotatedHeader title={t("sidebar:Frequency Options")} tooltip={FrequencyInfo} mobile={mobileDisplay}/>
<NormalizeFrequencies />
</span>
}
Expand All @@ -91,10 +157,6 @@ function Controls({ treeOn, mapOn, frequenciesOn, measurementsOn, mobileDisplay
<AnimationOptions />
</span>

<span style={{ paddingTop: "10px" }} />
<AnnotatedHeader title={t("sidebar:Panel Options")} tooltip={PanelOptionsInfo} mobile={mobileDisplay}/>
<PanelLayout />
<PanelToggles />
<Language />
</ControlsContainer>
);
Expand Down
12 changes: 5 additions & 7 deletions src/components/controls/miscInfoText.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";


export const TreeOptionsInfo = (
export const TreeInfo = (
<>
Change various options relating to how the tree is displayed.
The exact options available depend on the dataset and specific analysis performed.
Expand All @@ -12,7 +12,7 @@ export const TreeOptionsInfo = (
);


export const MapOptionsInfo = (
export const MapInfo = (
<>
Change various options relating to how the map is displayed.
<br/>
Expand All @@ -27,11 +27,9 @@ export const AnimationOptionsInfo = (
</>
);

export const PanelOptionsInfo = (
export const PanelLayoutInfo = (
<>
Control which panels are being displayed and whether to show the tree and the map side-by-side (<em>grid</em>) or expanded (<em>full</em>).
<br/>
Note that what options are available here are dataset specific!
Control whether to show the tree and the map side-by-side (<em>grid</em>) or expanded (<em>full</em>).
</>
);

Expand All @@ -42,7 +40,7 @@ export const FrequencyInfo = (
</>
);

export const MeasurementsOptionsInfo = (
export const MeasurementsInfo = (
<>
Change collection of measurements and various display options for the collection.
</>
Expand Down
6 changes: 1 addition & 5 deletions src/components/controls/panel-layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,12 @@ const PanelsGridIcon = withTheme(icons.PanelsGrid);
@connect((state) => {
return {
panelLayout: state.controls.panelLayout,
canTogglePanelLayout: state.controls.canTogglePanelLayout
};
})
class PanelLayouts extends React.Component {
render() {
const { t } = this.props;
// const mapAndTree = this.props.panels !== undefined && this.props.panels.indexOf("map") !== -1 && this.props.panels.indexOf("tree") !== -1;
if (!this.props.canTogglePanelLayout) {
return null;
}

return (
<div style={{marginTop: 0, marginBottom: 10}}>
<PanelsFullIcon width={22} selected={this.props.panelLayout === "full"}/>
Expand Down
31 changes: 31 additions & 0 deletions src/components/controls/panel-toggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// A slider toggle to adjust the state of a panel via dispatch.

import React from "react";
import { useDispatch } from "react-redux";

import Toggle from "./toggle";
import { togglePanelDisplay } from "../../actions/panelDisplay";

type Props = {
panel: string
on: boolean
}

const PanelToggle = ({ panel, on }: Props) => {
const dispatch = useDispatch();

// There is no slider label since the title in the annotated header acts as a
// visual label.
// FIXME: Add a hidden label?

return (
<Toggle
display={true}
on={on}
callback={() => dispatch(togglePanelDisplay(panel))}
label=""
/>
);
};

export default PanelToggle;
35 changes: 0 additions & 35 deletions src/components/controls/panel-toggles.js

This file was deleted.

12 changes: 8 additions & 4 deletions src/components/controls/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,23 @@ export const ControlsContainer = styled.div`
export const HeaderContainer = styled.div`
display: flex;
justify-content: space-between;
font-family: ${(props) => props.theme["font-family"]};
font-size: 16px;
line-height: 28px;
min-height: 28px; /* needed for safari, else the div height is 0 */
margin-top: 15px;
margin-bottom: 5px;
border-top: 1px solid #d3d3d3;
padding-top: 9px;
`;

export const HeaderTitle = styled.span`
font-family: ${(props) => props.theme["font-family"]};
font-size: 16px;
font-weight: 500;
color: ${(props) => props.theme.color};
`;

export const HeaderIconContainer = styled.span`
padding-top: 4px;
padding-right: 3px;
padding-left: 6px;
cursor: help;
color: #888;
`;
Expand Down
8 changes: 3 additions & 5 deletions src/locales/ar/sidebar.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"Dataset": "مجموعة بيانات",
"Date Range": "النطاق الزمني",
"Color By": "اللون حسب",
"Tree Options": "خيارات الشجرة",
"Layout": "التخطيط",
"rectangular": "مستطيل",
"radial": "شعاعي",
Expand All @@ -15,15 +14,14 @@
"Branch Labels": "تسميات الفروع",
"Search Strains": "البحث على السلالات",
"Second Tree": "الشجرة الثانية",
"Map Options": "خيارات الخريطة",
"Geographic resolution": "دقة الخريطة",
"Animation Speed": "سرعة الحركة",
"Loop animation": "حركة متكررة",
"Animate cumulative history": "تحريك التاريخ التراكمي",
"Panel Options": "خيارات اللوحة",
"Show tree": "اظهار الشجرة",
"Show map": "اظهار الخريطة",
"Show entropy": "اظهار الانتروبيا",
"Tree": "الشجرة",
"Map": "الخريطة",
"Entropy": "الانتروبيا",
"Language": "اللغة",
"Slow": "بطيئة",
"Medium": "متوسطة",
Expand Down
Loading
Loading