BrowserBar.tsx 6.82 KB
Newer Older
1
import React, { FunctionComponent, Fragment, 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';
9
import { ChrLocation } from '../browserState';
10
11
12
import {
  getBrowserNavOpened,
  getChrLocation,
13
  getBrowserActivated,
14
  getDefaultChrLocation,
15
16
17
18
19
  getGenomeSelectorActive
} from '../browserSelectors';
import { getDrawerOpened } from '../drawer/drawerSelectors';
import { getEnsObjectInfo } from 'src/ens-object/ensObjectSelectors';
import {
20
  getSelectedBrowserTab,
21
22
  getTrackPanelModalOpened,
  getTrackPanelOpened
23
24
25
} from '../track-panel/trackPanelSelectors';
import { selectBrowserTab } from '../track-panel/trackPanelActions';
import { toggleDrawer } from '../drawer/drawerActions';
Andrey Azov's avatar
Andrey Azov committed
26
import { RootState } from 'src/store';
27

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

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

34
type StateProps = {
35
  browserActivated: boolean;
36
  browserNavOpened: boolean;
37
  chrLocation: ChrLocation;
38
  defaultChrLocation: ChrLocation;
39
  drawerOpened: boolean;
40
  genomeSelectorActive: boolean;
41
  ensObjectInfo: any;
42
  selectedBrowserTab: TrackType;
43
  trackPanelModalOpened: boolean;
44
  trackPanelOpened: boolean;
45
46
47
};

type DispatchProps = {
48
  selectBrowserTab: (selectedBrowserTab: TrackType) => void;
49
  toggleBrowserNav: () => void;
50
  toggleDrawer: (drawerOpened: boolean) => void;
51
  toggleGenomeSelector: (genomeSelectorActive: boolean) => void;
52
53
};

Imran Salam's avatar
Imran Salam committed
54
type OwnProps = {
55
  dispatchBrowserLocation: (chrLocation: ChrLocation) => void;
Imran Salam's avatar
Imran Salam committed
56
};
57
58
59

type BrowserBarProps = StateProps & DispatchProps & OwnProps;

Andrey Azov's avatar
Andrey Azov committed
60
61
62
63
64
65
66
67
68
69
type BrowserInfoProps = {
  ensObjectInfo: any;
};

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

Imran Salam's avatar
Imran Salam committed
70
71
72
export const BrowserBar: FunctionComponent<BrowserBarProps> = (
  props: BrowserBarProps
) => {
Andrey Azov's avatar
Andrey Azov committed
73
  const shouldShowBrowserInfo = () => {
74
    const [, chrStart, chrEnd] = props.defaultChrLocation;
Andrey Azov's avatar
Andrey Azov committed
75
    const isLocationOfWholeChromosome = chrStart === 0 && chrEnd === 0;
76

Andrey Azov's avatar
Andrey Azov committed
77
    return !(props.genomeSelectorActive || isLocationOfWholeChromosome);
78
79
  };

Andrey Azov's avatar
Andrey Azov committed
80
81
82
83
  const { navigator, reset } = browserInfoConfig;
  const [showBrowserInfo, toggleShowBrowserInfo] = useState(
    shouldShowBrowserInfo()
  );
84

Andrey Azov's avatar
Andrey Azov committed
85
86
87
88
  const setBrowserInfoVisibility = () => {
    const shouldToggleVisibility = showBrowserInfo !== shouldShowBrowserInfo();
    if (shouldToggleVisibility) {
      toggleShowBrowserInfo(!showBrowserInfo);
89
90
91
    }
  };

Andrey Azov's avatar
Andrey Azov committed
92
93
94
95
  useEffect(() => {
    setBrowserInfoVisibility();
  }, [props.defaultChrLocation, props.genomeSelectorActive]);

96
  const getBrowserNavIcon = () => {
97
    if (props.drawerOpened === true) {
Andrey Azov's avatar
Andrey Azov committed
98
      return navigator.icon.grey as string;
99
    } else if (props.browserNavOpened === true) {
Andrey Azov's avatar
Andrey Azov committed
100
      return navigator.icon.selected as string;
101
102
103
104
105
    } else {
      return navigator.icon.default;
    }
  };

106
107
108
109
110
111
112
113
  const toggleNavigator = () => {
    if (props.drawerOpened === true) {
      return;
    }

    props.toggleBrowserNav();
  };

Andrey Azov's avatar
Andrey Azov committed
114
115
116
117
118
  const className = classNames(styles.browserInfo, {
    [styles.browserInfoExpanded]: !props.trackPanelOpened,
    [styles.browserInfoGreyed]: props.drawerOpened
  });

Imran Salam's avatar
Imran Salam committed
119
120
  return (
    <div className={styles.browserBar}>
Andrey Azov's avatar
Andrey Azov committed
121
      <div className={className}>
Imran Salam's avatar
Imran Salam committed
122
        <dl className={styles.browserInfoLeft}>
123
          <BrowserReset
124
            dispatchBrowserLocation={props.dispatchBrowserLocation}
125
126
            chrLocation={props.chrLocation}
            defaultChrLocation={props.defaultChrLocation}
127
128
            details={reset}
            drawerOpened={props.drawerOpened}
129
          />
Andrey Azov's avatar
Andrey Azov committed
130
131
132
          {showBrowserInfo && (
            <BrowserInfo ensObjectInfo={props.ensObjectInfo} />
          )}
Imran Salam's avatar
Imran Salam committed
133
134
        </dl>
        <dl className={styles.browserInfoRight}>
135
136
          <BrowserGenomeSelector
            browserActivated={props.browserActivated}
137
            dispatchBrowserLocation={props.dispatchBrowserLocation}
138
            chrLocation={props.chrLocation}
139
            drawerOpened={props.drawerOpened}
140
141
            genomeSelectorActive={props.genomeSelectorActive}
            toggleGenomeSelector={props.toggleGenomeSelector}
142
          />
Andrey Azov's avatar
Andrey Azov committed
143
144
145
146
147
148
          {!props.genomeSelectorActive && (
            <BrowserNavigatorButton
              navigator={navigator}
              toggleNavigator={toggleNavigator}
              icon={getBrowserNavIcon()}
            />
149
          )}
150
151
        </dl>
      </div>
Andrey Azov's avatar
Andrey Azov committed
152
      {props.trackPanelOpened && (
153
154
155
156
157
158
159
160
        <BrowserTabs
          drawerOpened={props.drawerOpened}
          genomeSelectorActive={props.genomeSelectorActive}
          selectBrowserTab={props.selectBrowserTab}
          selectedBrowserTab={props.selectedBrowserTab}
          toggleDrawer={props.toggleDrawer}
          trackPanelModalOpened={props.trackPanelModalOpened}
        />
Andrey Azov's avatar
Andrey Azov committed
161
      )}
Imran Salam's avatar
Imran Salam committed
162
163
164
    </div>
  );
};
165

Andrey Azov's avatar
Andrey Azov committed
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
export const BrowserInfo = ({ ensObjectInfo }: BrowserInfoProps) => (
  <Fragment>
    <dd className={styles.geneSymbol}>
      <label>Gene</label>
      <span className={styles.value}>{ensObjectInfo.obj_symbol}</span>
    </dd>
    <dd>
      <label>Stable ID</label>
      <span className={styles.value}>{ensObjectInfo.stable_id}</span>
    </dd>
    <dd className="show-for-large">
      <label>Spliced mRNA length</label>
      <span className={styles.value}>{ensObjectInfo.spliced_length}</span>
      <label>bp</label>
    </dd>
    <dd className={`show-for-large ${styles.nonLabelValue}`}>
      {ensObjectInfo.bio_type}
    </dd>
    <dd className={`show-for-large ${styles.nonLabelValue}`}>
      {ensObjectInfo.strand} strand
    </dd>
  </Fragment>
);

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>
);

198
const mapStateToProps = (state: RootState): StateProps => ({
199
  browserActivated: getBrowserActivated(state),
200
  browserNavOpened: getBrowserNavOpened(state),
201
  chrLocation: getChrLocation(state),
202
  defaultChrLocation: getDefaultChrLocation(state),
203
  drawerOpened: getDrawerOpened(state),
204
  ensObjectInfo: getEnsObjectInfo(state),
205
  genomeSelectorActive: getGenomeSelectorActive(state),
206
  selectedBrowserTab: getSelectedBrowserTab(state),
207
208
  trackPanelModalOpened: getTrackPanelModalOpened(state),
  trackPanelOpened: getTrackPanelOpened(state)
209
210
211
});

const mapDispatchToProps: DispatchProps = {
212
  selectBrowserTab,
213
  toggleBrowserNav,
214
  toggleDrawer,
215
  toggleGenomeSelector
216
217
218
219
220
221
};

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