Unverified Commit 87353a13 authored by Imran Salam's avatar Imran Salam Committed by GitHub
Browse files

Fix drawer state (#118)

* make drawer state unique to species instance

* fix drawer not closing when clicked on browser tab and browser image

* make selectors return the genome specific values for drawer and some browser specific state properties

* fix thunk type in drawer actions

* refactor drawer state returned in reducer

* fix wrong drawer open check in 4b8ec1b5

* make more changes as suggested in code review

* fix wrong thunk dispatch type in track panel actions

* fix wrong value returned for selectedBrowserTab

* remove unnecessary calc method

* fix wrong value returned for selectedBrowserTab

* fix correct track not being highlighted on selection

* fix undefined returned by drawer selector

* change drawerViewForGenome to drawerView to be more relevant

* use calc for getting the browser width rather than 41px (needs to be in the same format as other width values)

* fix broken test cases

* add a comment that tells about the need for the calc format for browser animation

* use the ChrLocations replacing the genome ChrLocation object type

* use classname to append class names instead of manually doing it

* create closeDrawer action as it is used in many places within the browser

* batch multiple dispatches in drawer actions

* fix key type of TrackItemColour enum
parent 9cee8550
Pipeline #27334 passed with stages
in 4 minutes and 3 seconds
......@@ -15,7 +15,7 @@ import TrackPanel from './track-panel/TrackPanel';
import AppBar from 'src/shared/app-bar/AppBar';
import { RootState } from 'src/store';
import { ChrLocation } from './browserState';
import { ChrLocation, ChrLocations } from './browserState';
import {
changeBrowserLocation,
setDataFromUrlAndSave,
......@@ -33,16 +33,20 @@ import {
getAllChrLocations
} from './browserSelectors';
import { getLaunchbarExpanded } from 'src/header/headerSelectors';
import { getTrackPanelOpened } from './track-panel/trackPanelSelectors';
import { getIsTrackPanelOpened } from './track-panel/trackPanelSelectors';
import { getChrLocationFromStr, getChrLocationStr } from './browserHelper';
import { getDrawerOpened } from './drawer/drawerSelectors';
import { getIsDrawerOpened } from './drawer/drawerSelectors';
import { getEnabledCommittedSpecies } from 'src/content/app/species-selector/state/speciesSelectorSelectors';
import { CommittedItem } from 'src/content/app/species-selector/types/species-search';
import { getExampleEnsObjects } from 'src/ens-object/ensObjectSelectors';
import { EnsObject } from 'src/ens-object/ensObjectTypes';
import { fetchGenomeData } from 'src/genome/genomeActions';
import { toggleDrawer } from './drawer/drawerActions';
import {
changeDrawerView,
closeDrawer,
toggleDrawer
} from './drawer/drawerActions';
import browserStorageService from './browser-storage-service';
import { TrackStates } from './track-panel/trackPanelConfig';
......@@ -58,14 +62,14 @@ type StateProps = {
activeGenomeId: string | null;
activeEnsObjectId: string | null;
allActiveEnsObjectIds: { [genomeId: string]: string };
allChrLocations: ChrLocations;
browserActivated: boolean;
browserNavOpened: boolean;
browserQueryParams: { [key: string]: string };
chrLocation: ChrLocation | null;
allChrLocations: { [genomeId: string]: ChrLocation };
drawerOpened: boolean;
genomeSelectorActive: boolean;
trackPanelOpened: boolean;
isDrawerOpened: boolean;
isTrackPanelOpened: boolean;
launchbarExpanded: boolean;
exampleEnsObjects: EnsObject[];
committedSpecies: CommittedItem[];
......@@ -73,9 +77,11 @@ type StateProps = {
type DispatchProps = {
changeBrowserLocation: (genomeId: string, chrLocation: ChrLocation) => void;
changeDrawerView: (drawerView: string) => void;
closeDrawer: () => void;
fetchGenomeData: (genomeId: string) => void;
replace: Replace;
toggleDrawer: (drawerOpened: boolean) => void;
toggleDrawer: (isDrawerOpened: boolean) => void;
setDataFromUrlAndSave: (payload: ParsedUrlPayload) => void;
};
......@@ -99,6 +105,8 @@ export const Browser: FunctionComponent<BrowserProps> = (
>({});
const lastGenomeIdRef = useRef(props.activeGenomeId);
const { isDrawerOpened, closeDrawer } = props;
const setDataFromUrl = () => {
const { genomeId = null } = props.match.params;
const { focus = null, location = null } = props.browserQueryParams;
......@@ -212,10 +220,11 @@ export const Browser: FunctionComponent<BrowserProps> = (
}, [props.browserActivated]);
const closeTrack = () => {
if (props.drawerOpened === false) {
if (!isDrawerOpened) {
return;
}
props.toggleDrawer(false);
closeDrawer();
};
const [trackAnimation, setTrackAnimation] = useSpring(() => ({
......@@ -225,10 +234,10 @@ export const Browser: FunctionComponent<BrowserProps> = (
}));
const getBrowserWidth = (): string => {
if (props.drawerOpened) {
return 'calc(41px + 0vw)';
if (isDrawerOpened) {
return 'calc(41px + 0vw)'; // this format must be used for the react-spring animation to function properly
}
return props.trackPanelOpened
return props.isTrackPanelOpened
? 'calc(-356px + 100vw)'
: 'calc(-36px + 100vw)';
};
......@@ -237,12 +246,16 @@ export const Browser: FunctionComponent<BrowserProps> = (
setTrackAnimation({
width: getBrowserWidth()
});
}, [props.drawerOpened, props.trackPanelOpened]);
}, [isDrawerOpened, props.isTrackPanelOpened]);
const getHeightClass = (launchbarExpanded: boolean): string => {
return launchbarExpanded ? styles.shorter : styles.taller;
};
const BrowserBarNode = (
<BrowserBar dispatchBrowserLocation={dispatchBrowserLocation} />
);
return props.activeGenomeId ? (
<>
<AppBar
......@@ -253,13 +266,13 @@ export const Browser: FunctionComponent<BrowserProps> = (
{!props.browserQueryParams.focus && (
<section className={styles.browser}>
<BrowserBar dispatchBrowserLocation={dispatchBrowserLocation} />
{BrowserBarNode}
<ExampleObjectLinks {...props} />
</section>
)}
{props.browserQueryParams.focus && (
<section className={styles.browser}>
<BrowserBar dispatchBrowserLocation={dispatchBrowserLocation} />
{BrowserBarNode}
{props.genomeSelectorActive && (
<div className={styles.browserOverlay} />
)}
......@@ -271,7 +284,7 @@ export const Browser: FunctionComponent<BrowserProps> = (
<animated.div style={trackAnimation}>
<div className={styles.browserImageWrapper} onClick={closeTrack}>
{props.browserNavOpened &&
!props.drawerOpened &&
!isDrawerOpened &&
browserRef.current ? (
<BrowserNavBar />
) : null}
......@@ -321,14 +334,14 @@ const mapStateToProps = (state: RootState): StateProps => ({
activeGenomeId: getBrowserActiveGenomeId(state),
activeEnsObjectId: getBrowserActiveEnsObjectId(state),
allActiveEnsObjectIds: getBrowserActiveEnsObjectIds(state),
allChrLocations: getAllChrLocations(state),
browserActivated: getBrowserActivated(state),
browserNavOpened: getBrowserNavOpened(state),
browserQueryParams: getBrowserQueryParams(state),
chrLocation: getChrLocation(state),
allChrLocations: getAllChrLocations(state),
drawerOpened: getDrawerOpened(state),
genomeSelectorActive: getGenomeSelectorActive(state),
trackPanelOpened: getTrackPanelOpened(state),
isDrawerOpened: getIsDrawerOpened(state),
isTrackPanelOpened: getIsTrackPanelOpened(state),
launchbarExpanded: getLaunchbarExpanded(state),
exampleEnsObjects: getExampleEnsObjects(state),
committedSpecies: getEnabledCommittedSpecies(state)
......@@ -336,6 +349,8 @@ const mapStateToProps = (state: RootState): StateProps => ({
const mapDispatchToProps: DispatchProps = {
changeBrowserLocation,
changeDrawerView,
closeDrawer,
fetchGenomeData,
replace,
toggleDrawer,
......
......@@ -139,7 +139,7 @@ describe('<BrowserBar />', () => {
test('shows BrowserTabs if TrackPanel is open', () => {
const renderedBrowserBar = mount(
renderBrowserBar({ trackPanelOpened: true })
renderBrowserBar({ isTrackPanelOpened: true })
);
expect(renderedBrowserBar.find(BrowserTabs).length).toBe(1);
});
......
......@@ -17,14 +17,14 @@ import {
getBrowserActiveGenomeId,
getBrowserActiveEnsObject
} from '../browserSelectors';
import { getDrawerOpened } from '../drawer/drawerSelectors';
import { getIsDrawerOpened } from '../drawer/drawerSelectors';
import {
getSelectedBrowserTab,
getTrackPanelModalOpened,
getTrackPanelOpened
getIsTrackPanelModalOpened,
getIsTrackPanelOpened
} from '../track-panel/trackPanelSelectors';
import { selectBrowserTabAndSave } from '../track-panel/trackPanelActions';
import { toggleDrawer } from '../drawer/drawerActions';
import { closeDrawer, toggleDrawer } from '../drawer/drawerActions';
import { RootState } from 'src/store';
import { EnsObject } from 'src/ens-object/ensObjectTypes';
......@@ -41,18 +41,19 @@ type StateProps = {
chrLocation: ChrLocation | null;
actualChrLocation: ChrLocation | null;
defaultChrLocation: ChrLocation | null;
drawerOpened: boolean;
isDrawerOpened: boolean;
isTrackPanelModalOpened: boolean;
isTrackPanelOpened: boolean;
genomeSelectorActive: boolean;
ensObject: EnsObject | null;
selectedBrowserTab: { [genomeId: string]: TrackType };
trackPanelModalOpened: boolean;
trackPanelOpened: boolean;
selectedBrowserTab: TrackType;
};
type DispatchProps = {
closeDrawer: () => void;
selectBrowserTabAndSave: (selectedBrowserTab: TrackType) => void;
toggleBrowserNav: () => void;
toggleDrawer: (drawerOpened: boolean) => void;
toggleDrawer: (isDrawerOpened: boolean) => void;
toggleGenomeSelector: (genomeSelectorActive: boolean) => void;
};
......@@ -75,6 +76,8 @@ type BrowserNavigatorButtonProps = {
export const BrowserBar: FunctionComponent<BrowserBarProps> = (
props: BrowserBarProps
) => {
const { isDrawerOpened } = props;
const shouldShowBrowserInfo = () => {
const { defaultChrLocation } = props;
const isLocationOfWholeChromosome = !defaultChrLocation;
......@@ -99,7 +102,7 @@ export const BrowserBar: FunctionComponent<BrowserBarProps> = (
}, [props.defaultChrLocation, props.genomeSelectorActive]);
const getBrowserNavIcon = () => {
if (props.drawerOpened) {
if (isDrawerOpened) {
return navigator.icon.grey as string;
} else if (props.browserNavOpened) {
return navigator.icon.selected as string;
......@@ -109,7 +112,7 @@ export const BrowserBar: FunctionComponent<BrowserBarProps> = (
};
const toggleNavigator = () => {
if (props.drawerOpened) {
if (isDrawerOpened) {
return;
}
......@@ -117,8 +120,8 @@ export const BrowserBar: FunctionComponent<BrowserBarProps> = (
};
const className = classNames(styles.browserInfo, {
[styles.browserInfoExpanded]: !props.trackPanelOpened,
[styles.browserInfoGreyed]: props.drawerOpened
[styles.browserInfoExpanded]: !props.isTrackPanelOpened,
[styles.browserInfoGreyed]: isDrawerOpened
});
if (!(props.chrLocation && props.actualChrLocation && props.ensObject)) {
......@@ -134,7 +137,7 @@ export const BrowserBar: FunctionComponent<BrowserBarProps> = (
dispatchBrowserLocation={props.dispatchBrowserLocation}
chrLocation={props.chrLocation}
defaultChrLocation={props.defaultChrLocation}
drawerOpened={props.drawerOpened}
isDrawerOpened={isDrawerOpened}
/>
{showBrowserInfo && <BrowserInfo ensObject={props.ensObject} />}
</dl>
......@@ -144,7 +147,7 @@ export const BrowserBar: FunctionComponent<BrowserBarProps> = (
browserActivated={props.browserActivated}
dispatchBrowserLocation={props.dispatchBrowserLocation}
chrLocation={props.actualChrLocation}
drawerOpened={props.drawerOpened}
isDrawerOpened={isDrawerOpened}
genomeSelectorActive={props.genomeSelectorActive}
toggleGenomeSelector={props.toggleGenomeSelector}
/>
......@@ -157,16 +160,15 @@ export const BrowserBar: FunctionComponent<BrowserBarProps> = (
)}
</dl>
</div>
{props.trackPanelOpened && props.activeGenomeId && (
{props.isTrackPanelOpened && props.activeGenomeId && (
<BrowserTabs
activeGenomeId={props.activeGenomeId}
closeDrawer={props.closeDrawer}
ensObject={props.ensObject}
drawerOpened={props.drawerOpened}
isDrawerOpened={props.isDrawerOpened}
genomeSelectorActive={props.genomeSelectorActive}
selectBrowserTabAndSave={props.selectBrowserTabAndSave}
selectedBrowserTab={props.selectedBrowserTab}
toggleDrawer={props.toggleDrawer}
trackPanelModalOpened={props.trackPanelModalOpened}
isTrackPanelModalOpened={props.isTrackPanelModalOpened}
/>
)}
</div>
......@@ -229,15 +231,16 @@ const mapStateToProps = (state: RootState): StateProps => ({
chrLocation: getChrLocation(state),
actualChrLocation: getActualChrLocation(state),
defaultChrLocation: getDefaultChrLocation(state),
drawerOpened: getDrawerOpened(state),
ensObject: getBrowserActiveEnsObject(state),
genomeSelectorActive: getGenomeSelectorActive(state),
selectedBrowserTab: getSelectedBrowserTab(state),
trackPanelModalOpened: getTrackPanelModalOpened(state),
trackPanelOpened: getTrackPanelOpened(state)
isDrawerOpened: getIsDrawerOpened(state),
isTrackPanelModalOpened: getIsTrackPanelModalOpened(state),
isTrackPanelOpened: getIsTrackPanelOpened(state),
selectedBrowserTab: getSelectedBrowserTab(state)
});
const mapDispatchToProps: DispatchProps = {
closeDrawer,
selectBrowserTabAndSave,
toggleBrowserNav,
toggleDrawer,
......
......@@ -5,6 +5,7 @@ import React, {
FormEvent,
useEffect
} from 'react';
import classNames from 'classnames';
import { ChrLocation } from '../browserState';
......@@ -19,7 +20,7 @@ type BrowserGenomeSelectorProps = {
browserActivated: boolean;
chrLocation: ChrLocation;
dispatchBrowserLocation: (genomeId: string, chrLocation: ChrLocation) => void;
drawerOpened: boolean;
isDrawerOpened: boolean;
genomeSelectorActive: boolean;
toggleGenomeSelector: (genomeSelectorActive: boolean) => void;
};
......@@ -27,7 +28,7 @@ type BrowserGenomeSelectorProps = {
const BrowserGenomeSelector: FunctionComponent<BrowserGenomeSelectorProps> = (
props: BrowserGenomeSelectorProps
) => {
const { activeGenomeId, chrLocation } = props;
const { activeGenomeId, chrLocation, isDrawerOpened } = props;
const chrLocationStr = getChrLocationStr(chrLocation);
const [chrLocationPlaceholder, setChrLocationPlaceholder] = useState('');
......@@ -40,18 +41,8 @@ const BrowserGenomeSelector: FunctionComponent<BrowserGenomeSelectorProps> = (
setChrLocationPlaceholder(chrLocationStr);
}, []);
const getGenomeSelectorClasses = () => {
let classNames = styles.browserGenomeSelector;
if (props.drawerOpened === true) {
classNames += ` ${styles.browserGenomeSelectorDisabled}`;
}
return classNames;
};
const activateForm = () => {
if (props.drawerOpened === true) {
if (isDrawerOpened) {
return;
}
......@@ -99,8 +90,12 @@ const BrowserGenomeSelector: FunctionComponent<BrowserGenomeSelectorProps> = (
}
};
const className = classNames(styles.browserGenomeSelector, {
[styles.browserGenomeSelectorDisabled]: isDrawerOpened
});
return props.browserActivated ? (
<dd className={getGenomeSelectorClasses()}>
<dd className={className}>
<label className="show-for-large">Chromosome</label>
{props.genomeSelectorActive ? (
<form onSubmit={handleSubmit}>
......
......@@ -17,8 +17,7 @@ import {
getTrackConfigLabel,
getBrowserCogTrackList,
getBrowserNavOpened,
getBrowserActivated,
getBrowserActiveGenomeId
getBrowserActivated
} from '../browserSelectors';
import {
activateBrowser,
......@@ -38,7 +37,6 @@ import { TrackStates } from '../track-panel/trackPanelConfig';
import { BROWSER_CONTAINER_ID } from '../browser-constants';
type StateProps = {
activeGenomeId: string | null;
browserCogTrackList: CogList;
browserNavOpened: boolean;
trackConfigNames: any;
......@@ -194,7 +192,6 @@ function getBrowserImageClasses(browserNavOpened: boolean): string {
}
const mapStateToProps = (state: RootState): StateProps => ({
activeGenomeId: getBrowserActiveGenomeId(state),
browserCogTrackList: getBrowserCogTrackList(state),
browserNavOpened: getBrowserNavOpened(state),
trackConfigLabel: getTrackConfigLabel(state),
......
......@@ -15,7 +15,7 @@ describe('<BrowserNavBar />', () => {
shallow(
<BrowserNavBar
browserNavStates={browserStates as BrowserNavStates}
trackPanelOpened={true}
isTrackPanelOpened={true}
/>
).hasClass(styles.browserNavBarExpanded)
).toBe(false);
......@@ -24,7 +24,7 @@ describe('<BrowserNavBar />', () => {
shallow(
<BrowserNavBar
browserNavStates={browserStates as BrowserNavStates}
trackPanelOpened={false}
isTrackPanelOpened={false}
/>
).hasClass(styles.browserNavBarExpanded)
).toBe(true);
......
......@@ -6,7 +6,7 @@ import { browserNavConfig, BrowserNavItem } from '../browserConfig';
import { RootState } from 'src/store';
import { getBrowserNavStates } from '../browserSelectors';
import { getTrackPanelOpened } from '../track-panel/trackPanelSelectors';
import { getIsTrackPanelOpened } from '../track-panel/trackPanelSelectors';
import { BrowserNavStates } from '../browserState';
import BrowserNavIcon from './BrowserNavIcon';
......@@ -15,7 +15,7 @@ import styles from './BrowserNavBar.scss';
type StateProps = {
browserNavStates: BrowserNavStates;
trackPanelOpened: boolean;
isTrackPanelOpened: boolean;
};
type BrowserNavBarProps = StateProps;
......@@ -24,7 +24,7 @@ export const BrowserNavBar: FunctionComponent<BrowserNavBarProps> = (
props: BrowserNavBarProps
) => {
const className = classNames(styles.browserNavBar, {
[styles.browserNavBarExpanded]: !props.trackPanelOpened
[styles.browserNavBarExpanded]: !props.isTrackPanelOpened
});
return (
......@@ -44,7 +44,7 @@ export const BrowserNavBar: FunctionComponent<BrowserNavBarProps> = (
const mapStateToProps = (state: RootState): StateProps => ({
browserNavStates: getBrowserNavStates(state),
trackPanelOpened: getTrackPanelOpened(state)
isTrackPanelOpened: getIsTrackPanelOpened(state)
});
export default connect(mapStateToProps)(BrowserNavBar);
......@@ -14,7 +14,7 @@ type BrowserResetProps = {
chrLocation: ChrLocation | null;
defaultChrLocation: ChrLocation | null;
dispatchBrowserLocation: (genomeId: string, chrLocation: ChrLocation) => void;
drawerOpened: boolean;
isDrawerOpened: boolean;
};
export const BrowserReset: FunctionComponent<BrowserResetProps> = (
......@@ -24,7 +24,7 @@ export const BrowserReset: FunctionComponent<BrowserResetProps> = (
activeGenomeId,
chrLocation,
defaultChrLocation,
drawerOpened
isDrawerOpened
} = props;
const getResetIconStatus = (): ImageButtonStatus => {
......@@ -35,7 +35,7 @@ export const BrowserReset: FunctionComponent<BrowserResetProps> = (
const chrLocationStr = getChrLocationStr(chrLocation);
const defaultChrLocationStr = getChrLocationStr(defaultChrLocation);
if (chrLocationStr === defaultChrLocationStr || drawerOpened === true) {
if (chrLocationStr === defaultChrLocationStr || isDrawerOpened) {
return ImageButtonStatus.DISABLED;
}
......@@ -43,7 +43,7 @@ export const BrowserReset: FunctionComponent<BrowserResetProps> = (
};
const resetBrowser = () => {
if (drawerOpened === true) {
if (isDrawerOpened) {
return;
}
......
......@@ -166,7 +166,7 @@ describe('BrowserStorageService', () => {
);
const result = browserStorageService.getSelectedBrowserTab();
expect(result).toEqual(TrackType.GENOMIC);
expect(result).toEqual({});
mockStorageService.get.mockRestore();
});
......
......@@ -7,7 +7,6 @@ import {
TrackToggleStates
} from './track-panel/trackPanelConfig';
import { ChrLocations } from './browserState';
import { ImageButtonStatus } from 'src/shared/image-button/ImageButton';
export enum StorageKeys {
ACTIVE_GENOME_ID = 'browser.activeGenomeId',
......@@ -77,10 +76,7 @@ export class BrowserStorageService {
}
public getSelectedBrowserTab() {
return (
this.storageService.get(StorageKeys.SELECTED_BROWSER_TAB) ||
TrackType.GENOMIC
);
return this.storageService.get(StorageKeys.SELECTED_BROWSER_TAB) || {};
}
public updateSelectedBrowserTab(selectedBrowserTabForGenome: {
......
......@@ -5,14 +5,13 @@ import { EnsObject } from 'src/ens-object/ensObjectTypes';
import styles from './BrowserTabs.scss';
type BrowserTabsProps = {
activeGenomeId: string;
closeDrawer: () => void;
ensObject: EnsObject;
drawerOpened: boolean;
isDrawerOpened: boolean;
genomeSelectorActive: boolean;
selectBrowserTabAndSave: (selectedBrowserTab: TrackType) => void;
selectedBrowserTab: { [genomeId: string]: TrackType };
toggleDrawer: (drawerOpened: boolean) => void;
trackPanelModalOpened: boolean;
selectedBrowserTab: TrackType;
isTrackPanelModalOpened: boolean;
};
const BrowserTabs: FunctionComponent<BrowserTabsProps> = (
......@@ -23,24 +22,26 @@ const BrowserTabs: FunctionComponent<BrowserTabsProps> = (
return;
}
if (props.drawerOpened) {
props.toggleDrawer(false);
if (props.isDrawerOpened) {
props.closeDrawer();
}
props.selectBrowserTabAndSave(value);
};
const getBrowserTabClasses = (trackType: TrackType) => {
const { activeGenomeId, drawerOpened, trackPanelModalOpened } = props;
const selectedBrowserTab =
props.selectedBrowserTab[activeGenomeId] || TrackType.GENOMIC;
const {
isDrawerOpened,
selectedBrowserTab,
isTrackPanelModalOpened
} = props;
let classNames = styles.browserTab;
if (
props.ensObject.genome_id &&
selectedBrowserTab === trackType &&
drawerOpened === false &&
trackPanelModalOpened === false
!isDrawerOpened &&
!isTrackPanelModalOpened
) {
classNames += ` ${styles.browserTabActive} ${styles.browserTabArrow}`;
} else if (!props.ensObject.genome_id) {
......
......@@ -35,7 +35,7 @@ export function browserInfo(
? BrowserOpenState.SEMI_EXPANDED
: BrowserOpenState.EXPANDED
};
case getType(drawerActions.toggleDrawer):
case getType(drawerActions.toggleDrawerForGenome):
return {
...state,
browserOpenState: action.payload
......