BrowserBar.tsx 7.74 KB
Newer Older
1
import React, { FunctionComponent, useState, useEffect } from 'react';
2
import { connect } from 'react-redux';
Andrey Azov's avatar
Andrey Azov committed
3
import classNames from 'classnames';
4

Andrey Azov's avatar
Andrey Azov committed
5
import { browserInfoConfig, BrowserInfoItem } from '../browserConfig';
6 7
import { TrackType } from '../track-panel/trackPanelConfig';

8
import { toggleBrowserNav, toggleGenomeSelector } from '../browserActions';
Andrey Azov's avatar
Andrey Azov committed
9
import { ChrLocation } from '../browserState';
10 11 12
import {
  getBrowserNavOpened,
  getChrLocation,
13
  getBrowserActivated,
14
  getDefaultChrLocation,
15 16
  getGenomeSelectorActive,
  getBrowserActiveGenomeId,
Andrey Azov's avatar
Andrey Azov committed
17
  getBrowserActiveEnsObject
18
} from '../browserSelectors';
19
import { getIsDrawerOpened } from '../drawer/drawerSelectors';
20
import {
21
  getSelectedBrowserTab,
22 23
  getTrackPanelModalOpened,
  getTrackPanelOpened
24
} from '../track-panel/trackPanelSelectors';
25
import { selectBrowserTabAndSave } from '../track-panel/trackPanelActions';
26
import { toggleDrawer } from '../drawer/drawerActions';
Andrey Azov's avatar
Andrey Azov committed
27
import { RootState } from 'src/store';
28
import { EnsObject } from 'src/ens-object/ensObjectTypes';
29

Imran Salam's avatar
Imran Salam committed
30
import BrowserReset from '../browser-reset/BrowserReset';
31
import BrowserGenomeSelector from '../browser-genome-selector/BrowserGenomeSelector';
32
import BrowserTabs from '../browser-tabs/BrowserTabs';
33 34

import styles from './BrowserBar.scss';
35

36
type StateProps = {
37
  activeGenomeId: string | null;
38
  browserActivated: boolean;
39
  browserNavOpened: boolean;
Andrey Azov's avatar
Andrey Azov committed
40 41
  chrLocation: ChrLocation | null;
  defaultChrLocation: ChrLocation | null;
42
  isDrawerOpened: boolean;
43
  genomeSelectorActive: boolean;
Andrey Azov's avatar
Andrey Azov committed
44
  ensObject: EnsObject | null;
45
  selectedBrowserTab: TrackType;
46
  trackPanelModalOpened: boolean;
47
  trackPanelOpened: boolean;
48 49 50
};

type DispatchProps = {
51
  selectBrowserTabAndSave: (selectedBrowserTab: TrackType) => void;
52
  toggleBrowserNav: () => void;
53
  toggleDrawer: (isDrawerOpened: boolean) => void;
54
  toggleGenomeSelector: (genomeSelectorActive: boolean) => void;
55 56
};

Imran Salam's avatar
Imran Salam committed
57
type OwnProps = {
Andrey Azov's avatar
Andrey Azov committed
58
  dispatchBrowserLocation: (genomeId: string, chrLocation: ChrLocation) => void;
Imran Salam's avatar
Imran Salam committed
59
};
60 61 62

type BrowserBarProps = StateProps & DispatchProps & OwnProps;

Andrey Azov's avatar
Andrey Azov committed
63
type BrowserInfoProps = {
Andrey Azov's avatar
Andrey Azov committed
64
  ensObject: EnsObject;
Andrey Azov's avatar
Andrey Azov committed
65 66 67 68 69 70 71 72
};

type BrowserNavigatorButtonProps = {
  toggleNavigator: () => void;
  navigator: BrowserInfoItem;
  icon: string; // TODO: use inline SVG
};

Imran Salam's avatar
Imran Salam committed
73 74 75
export const BrowserBar: FunctionComponent<BrowserBarProps> = (
  props: BrowserBarProps
) => {
76
  const { isDrawerOpened } = props;
77

Andrey Azov's avatar
Andrey Azov committed
78
  const shouldShowBrowserInfo = () => {
Andrey Azov's avatar
Andrey Azov committed
79 80
    const { defaultChrLocation } = props;
    const isLocationOfWholeChromosome = !defaultChrLocation;
81

Andrey Azov's avatar
Andrey Azov committed
82
    return !(props.genomeSelectorActive || isLocationOfWholeChromosome);
83 84
  };

85
  const { navigator } = browserInfoConfig;
Andrey Azov's avatar
Andrey Azov committed
86 87 88
  const [showBrowserInfo, toggleShowBrowserInfo] = useState(
    shouldShowBrowserInfo()
  );
89

Andrey Azov's avatar
Andrey Azov committed
90 91 92 93
  const setBrowserInfoVisibility = () => {
    const shouldToggleVisibility = showBrowserInfo !== shouldShowBrowserInfo();
    if (shouldToggleVisibility) {
      toggleShowBrowserInfo(!showBrowserInfo);
94 95 96
    }
  };

Andrey Azov's avatar
Andrey Azov committed
97 98 99 100
  useEffect(() => {
    setBrowserInfoVisibility();
  }, [props.defaultChrLocation, props.genomeSelectorActive]);

101
  const getBrowserNavIcon = () => {
102
    if (isDrawerOpened) {
Andrey Azov's avatar
Andrey Azov committed
103
      return navigator.icon.grey as string;
Andrey Azov's avatar
Andrey Azov committed
104
    } else if (props.browserNavOpened) {
Andrey Azov's avatar
Andrey Azov committed
105
      return navigator.icon.selected as string;
106 107 108 109 110
    } else {
      return navigator.icon.default;
    }
  };

111
  const toggleNavigator = () => {
112
    if (isDrawerOpened) {
113 114 115 116 117 118
      return;
    }

    props.toggleBrowserNav();
  };

Andrey Azov's avatar
Andrey Azov committed
119 120
  const className = classNames(styles.browserInfo, {
    [styles.browserInfoExpanded]: !props.trackPanelOpened,
121
    [styles.browserInfoGreyed]: isDrawerOpened
Andrey Azov's avatar
Andrey Azov committed
122 123
  });

Andrey Azov's avatar
Andrey Azov committed
124 125 126 127
  if (!(props.chrLocation && props.ensObject)) {
    return <div className={styles.browserBar} />;
  }

Imran Salam's avatar
Imran Salam committed
128 129
  return (
    <div className={styles.browserBar}>
Andrey Azov's avatar
Andrey Azov committed
130
      <div className={className}>
Imran Salam's avatar
Imran Salam committed
131
        <dl className={styles.browserInfoLeft}>
132
          <BrowserReset
133
            activeGenomeId={props.activeGenomeId}
134
            dispatchBrowserLocation={props.dispatchBrowserLocation}
135 136
            chrLocation={props.chrLocation}
            defaultChrLocation={props.defaultChrLocation}
137
            isDrawerOpened={isDrawerOpened}
138
          />
Andrey Azov's avatar
Andrey Azov committed
139
          {showBrowserInfo && <BrowserInfo ensObject={props.ensObject} />}
Imran Salam's avatar
Imran Salam committed
140 141
        </dl>
        <dl className={styles.browserInfoRight}>
142
          <BrowserGenomeSelector
143
            activeGenomeId={props.activeGenomeId}
144
            browserActivated={props.browserActivated}
145
            dispatchBrowserLocation={props.dispatchBrowserLocation}
146
            chrLocation={props.chrLocation}
147
            isDrawerOpened={isDrawerOpened}
148 149
            genomeSelectorActive={props.genomeSelectorActive}
            toggleGenomeSelector={props.toggleGenomeSelector}
150
          />
Andrey Azov's avatar
Andrey Azov committed
151
          {!props.genomeSelectorActive && props.ensObject.genome_id && (
Andrey Azov's avatar
Andrey Azov committed
152 153 154 155 156
            <BrowserNavigatorButton
              navigator={navigator}
              toggleNavigator={toggleNavigator}
              icon={getBrowserNavIcon()}
            />
157
          )}
158 159
        </dl>
      </div>
Andrey Azov's avatar
Andrey Azov committed
160
      {props.trackPanelOpened && props.activeGenomeId && (
161
        <BrowserTabs
Andrey Azov's avatar
Andrey Azov committed
162
          ensObject={props.ensObject}
163
          isDrawerOpened={props.isDrawerOpened}
164
          genomeSelectorActive={props.genomeSelectorActive}
165
          selectBrowserTabAndSave={props.selectBrowserTabAndSave}
166 167 168 169
          selectedBrowserTab={props.selectedBrowserTab}
          toggleDrawer={props.toggleDrawer}
          trackPanelModalOpened={props.trackPanelModalOpened}
        />
Andrey Azov's avatar
Andrey Azov committed
170
      )}
Imran Salam's avatar
Imran Salam committed
171 172 173
    </div>
  );
};
174

Andrey Azov's avatar
Andrey Azov committed
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
export const BrowserInfo = ({ ensObject }: BrowserInfoProps) => {
  return (
    <>
      {ensObject.object_type === 'gene' && (
        <>
          <dd className={styles.ensObjectLabel}>
            <label>{ensObject.object_type}</label>
            <span className={styles.value}>{ensObject.label}</span>
          </dd>
          <dd>
            <label>Stable ID</label>
            <span className={styles.value}>{ensObject.stable_id}</span>
          </dd>
          <dd className="show-for-large">
            <label>Spliced mRNA length</label>
            <span className={styles.value}>{ensObject.spliced_length}</span>
            <label>bp</label>
          </dd>
          <dd className={`show-for-large ${styles.nonLabelValue}`}>
            {ensObject.bio_type}
          </dd>
          <dd className={`show-for-large ${styles.nonLabelValue}`}>
            {ensObject.strand} strand
          </dd>
        </>
      )}

      {ensObject.object_type === 'region' && (
        <>
          <dd className={styles.ensObjectLabel}>
            <label>Region: </label>
            <span className={styles.value}>
              {`${ensObject.location.chromosome}:${ensObject.location.start}:${ensObject.location.end}`}
            </span>
          </dd>
        </>
      )}
    </>
  );
};
Andrey Azov's avatar
Andrey Azov committed
215 216 217 218 219 220 221 222 223

export const BrowserNavigatorButton = (props: BrowserNavigatorButtonProps) => (
  <dd className={styles.navigator}>
    <button title={props.navigator.description} onClick={props.toggleNavigator}>
      <img src={props.icon} alt={props.navigator.description} />
    </button>
  </dd>
);

224
const mapStateToProps = (state: RootState): StateProps => ({
225
  activeGenomeId: getBrowserActiveGenomeId(state),
226
  browserActivated: getBrowserActivated(state),
227
  browserNavOpened: getBrowserNavOpened(state),
228
  chrLocation: getChrLocation(state),
229
  defaultChrLocation: getDefaultChrLocation(state),
230
  isDrawerOpened: getIsDrawerOpened(state),
Andrey Azov's avatar
Andrey Azov committed
231
  ensObject: getBrowserActiveEnsObject(state),
232
  genomeSelectorActive: getGenomeSelectorActive(state),
233
  selectedBrowserTab: getSelectedBrowserTab(state),
234 235
  trackPanelModalOpened: getTrackPanelModalOpened(state),
  trackPanelOpened: getTrackPanelOpened(state)
236 237 238
});

const mapDispatchToProps: DispatchProps = {
239
  selectBrowserTabAndSave,
240
  toggleBrowserNav,
241
  toggleDrawer,
242
  toggleGenomeSelector
243 244 245 246 247 248
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(BrowserBar);