Browser.tsx 5.22 KB
Newer Older
1
2
3
4
import React, {
  FunctionComponent,
  useCallback,
  useRef,
5
6
7
  useEffect,
  useState,
  Fragment
8
9
} from 'react';
import { withRouter, RouteComponentProps } from 'react-router-dom';
10
import { connect } from 'react-redux';
11
import { replace, Replace } from 'connected-react-router';
12

13
14
15
16
17
import BrowserBar from './browser-bar/BrowserBar';
import BrowserImage from './browser-image/BrowserImage';
import BrowserNavBar from './browser-nav/BrowserNavBar';
import TrackPanel from './track-panel/TrackPanel';
import Drawer from './drawer/Drawer';
18

Andrey Azov's avatar
Andrey Azov committed
19
import { RootState } from 'src/store';
20
21
22
23
24
25
import {
  BrowserOpenState,
  BrowserNavStates,
  ChrLocation
} from './browserState';
import {
26
  changeBrowserLocation,
27
  fetchExampleObjectsData,
28
  fetchObjectData,
29
30
31
  toggleDrawer,
  updateChrLocation,
  updateBrowserNavStates,
32
  updateBrowserActivated
33
} from './browserActions';
34
35
36
import {
  getBrowserOpenState,
  getDrawerOpened,
37
  getBrowserNavOpened,
38
  getChrLocation,
Dan Sheppard's avatar
Dan Sheppard committed
39
  getGenomeSelectorActive,
40
  getBrowserActivated,
41
  getExampleObjects
42
} from './browserSelectors';
43

44
import styles from './Browser.scss';
45

46
import 'static/browser/browser.js';
47
import { getChrLocationFromStr, getChrLocationStr } from './browserHelper';
48
49

type StateProps = {
50
  browserActivated: boolean;
51
  browserNavOpened: boolean;
52
  browserOpenState: BrowserOpenState;
53
  chrLocation: ChrLocation;
54
  drawerOpened: boolean;
55
  exampleObjects: {};
56
  genomeSelectorActive: boolean;
57
58
59
};

type DispatchProps = {
60
61
62
63
  changeBrowserLocation: (
    chrLocation: ChrLocation,
    browserEl: HTMLDivElement
  ) => void;
64
  fetchExampleObjectsData: () => void;
65
  fetchObjectData: (stableId: string) => void;
66
  replace: Replace;
67
  toggleDrawer: (drawerOpened: boolean) => void;
68
69
70
  updateBrowserActivated: (browserActivated: boolean) => void;
  updateBrowserNavStates: (browserNavStates: BrowserNavStates) => void;
  updateChrLocation: (chrLocation: ChrLocation) => void;
71
};
72

73
74
type OwnProps = {};

75
type MatchParams = {
76
  location: string;
77
  stableId: string;
78
79
80
81
82
83
84
  species: string;
};

type BrowserProps = RouteComponentProps<MatchParams> &
  StateProps &
  DispatchProps &
  OwnProps;
85

86
87
88
export const Browser: FunctionComponent<BrowserProps> = (
  props: BrowserProps
) => {
89
  const browserRef: React.RefObject<HTMLDivElement> = useRef(null);
90
  const [showBrowser, toggleShowBrowser] = useState(true);
91

92
  const dispatchBrowserLocation = (chrLocation: ChrLocation) => {
93
    if (browserRef.current) {
94
      props.changeBrowserLocation(chrLocation, browserRef.current);
95
96
97
    }
  };

98
  useEffect(() => {
99
100
101
102
103
    if (Object.values(props.exampleObjects).length > 0) {
      toggleShowBrowser(true);
    } else {
      props.fetchExampleObjectsData();
      toggleShowBrowser(false);
104
    }
105
  }, [props.exampleObjects]);
106

107
  useEffect(() => {
108
    const { stableId } = props.match.params;
109
    const location = props.location.search;
110
    const chrLocation = getChrLocationFromStr(location);
111

112
    dispatchBrowserLocation(chrLocation);
113

114
115
    props.fetchObjectData(stableId);
  }, [props.match.params.stableId]);
116

Dan Sheppard's avatar
Dan Sheppard committed
117
  useEffect(() => {
118
119
120
121
    const [, chrStart, chrEnd] = props.chrLocation;

    if (props.browserActivated && chrStart > 0 && chrEnd > 0) {
      dispatchBrowserLocation(props.chrLocation);
Dan Sheppard's avatar
Dan Sheppard committed
122
    }
123
  }, [props.browserActivated]);
Dan Sheppard's avatar
Dan Sheppard committed
124

125
  useEffect(() => {
126
    const { params } = props.match;
127
    const newChrLocationStr = getChrLocationStr(props.chrLocation);
128
129
130
    const newUrl = `/app/browser/${params.species}/${
      params.stableId
    }?region=${newChrLocationStr}`;
131

132
    props.replace(newUrl);
133
  }, [props.chrLocation, props.location.search]);
134

135
  const closeTrack = useCallback(() => {
136
    if (props.drawerOpened === false) {
137
138
139
      return;
    }

140
    props.toggleDrawer(false);
141
  }, [props.drawerOpened]);
142

143
144
  return (
    <section className={styles.browser}>
145
146
147
148
149
      {showBrowser ? (
        <Fragment>
          <BrowserBar dispatchBrowserLocation={dispatchBrowserLocation} />
          {props.genomeSelectorActive ? (
            <div className={styles.browserOverlay} />
150
          ) : null}
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
          <div className={styles.browserInnerWrapper}>
            <div
              className={`${styles.browserImageWrapper} ${
                styles[props.browserOpenState]
              }`}
              onClick={closeTrack}
            >
              {props.browserNavOpened && !props.drawerOpened ? (
                <BrowserNavBar browserRef={browserRef} />
              ) : null}
              <BrowserImage browserRef={browserRef} />
            </div>
            <TrackPanel browserRef={browserRef} />
            {props.drawerOpened && <Drawer />}
          </div>
        </Fragment>
      ) : null}
168
169
170
    </section>
  );
};
171

172
const mapStateToProps = (state: RootState): StateProps => ({
173
  browserActivated: getBrowserActivated(state),
174
175
  browserNavOpened: getBrowserNavOpened(state),
  browserOpenState: getBrowserOpenState(state),
176
  chrLocation: getChrLocation(state),
177
  drawerOpened: getDrawerOpened(state),
178
  exampleObjects: getExampleObjects(state),
179
  genomeSelectorActive: getGenomeSelectorActive(state)
180
181
});

182
const mapDispatchToProps: DispatchProps = {
183
  changeBrowserLocation,
184
  fetchExampleObjectsData,
185
  fetchObjectData,
186
  replace,
187
188
189
  toggleDrawer,
  updateBrowserActivated,
  updateBrowserNavStates,
190
  updateChrLocation
191
192
};

193
194
195
196
197
198
export default withRouter(
  connect(
    mapStateToProps,
    mapDispatchToProps
  )(Browser)
);