BrowserBar.tsx 7.78 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
19
20
} from '../browserSelectors';
import { getDrawerOpened } from '../drawer/drawerSelectors';
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 = {
Andrey Azov's avatar
Andrey Azov committed
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
  drawerOpened: boolean;
43
  genomeSelectorActive: boolean;
Andrey Azov's avatar
Andrey Azov committed
44
  ensObject: EnsObject | null;
45
  selectedBrowserTab: { [genomeId: string]: TrackType };
46
  trackPanelModalOpened: boolean;
47
  trackPanelOpened: boolean;
48
49
50
};

type DispatchProps = {
51
  selectBrowserTabAndSave: (selectedBrowserTab: TrackType) => void;
52
  toggleBrowserNav: () => void;
53
  toggleDrawer: (drawerOpened: 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
) => {
Andrey Azov's avatar
Andrey Azov committed
76
  const shouldShowBrowserInfo = () => {
Andrey Azov's avatar
Andrey Azov committed
77
78
    const { defaultChrLocation } = props;
    const isLocationOfWholeChromosome = !defaultChrLocation;
79

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

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

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

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

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

109
  const toggleNavigator = () => {
Andrey Azov's avatar
Andrey Azov committed
110
    if (props.drawerOpened) {
111
112
113
114
115
116
      return;
    }

    props.toggleBrowserNav();
  };

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

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

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

Andrey Azov's avatar
Andrey Azov committed
174
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
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
214
215
216
217
218
219
220
221
222

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

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

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

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