Skip to content

Commit 9611beb

Browse files
committed
UN-129 - improve universal-nav ssr placeholder
1 parent a7c3e22 commit 9611beb

File tree

5 files changed

+77
-71
lines changed

5 files changed

+77
-71
lines changed

package-lock.json

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@
168168
"topcoder-react-ui-kit": "2.0.1",
169169
"topcoder-react-utils": "0.7.8",
170170
"turndown": "^4.0.2",
171+
"uninav-react": "git+https://github.com/topcoder-platform/uninav-react.git#0.0.1",
171172
"url-parse": "^1.4.1",
172173
"uuid": "^3.3.2",
173174
"valid-url": "^1.0.9",
Lines changed: 60 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,51 @@
1-
/* global tcUniNav */
2-
import React, { useEffect, useMemo, useRef } from 'react';
1+
import React, { useMemo } from 'react';
2+
import PT from 'prop-types';
33
import { connect } from 'react-redux';
4+
import { withRouter } from 'react-router-dom';
45
import { config } from 'topcoder-react-utils';
56
import LoadingIndicator from 'components/LoadingIndicator';
7+
import _ from 'lodash';
8+
import { MarketingNavigation, ToolNavigation } from 'uninav-react';
69
import { getSubPageConfiguration } from '../../utils/url';
7-
import { SSRPlaceholder } from '../../utils/SSR';
810
import './styles.scss';
911

10-
let counter = 0;
11-
const headerElIdTmpl = 'uninav-headerNav';
12-
13-
const TopcoderHeader = () => {
14-
const uniNavInitialized = useRef(false);
12+
const TopcoderHeader = ({ auth, location }) => {
13+
const user = _.get(auth, 'profile') || {};
14+
const authToken = _.get(auth, 'tokenV3');
15+
const isAuthenticated = !!authToken;
1516
const authURLs = config.HEADER_AUTH_URLS;
16-
const headerRef = useRef();
17-
const headerElId = useRef(`${headerElIdTmpl}-${counter}`);
18-
19-
const navType = useMemo(() => {
20-
if (typeof window === 'undefined') {
21-
return '';
22-
}
23-
24-
let { type } = getSubPageConfiguration();
25-
26-
// if there's a stored nav type in session storage, retrieve it and overwrite type
27-
const sessionNavType = sessionStorage.getItem('uni-nav[navType]');
28-
const url = new URL(window.location.href);
29-
30-
// Only use the set sessionStorage value for navType on the /thrive paths, for now.
31-
// Probably will change in the future...
32-
if (window.location.href.indexOf('/thrive') > -1 && sessionNavType && (sessionNavType === 'tool' || sessionNavType === 'marketing')) {
33-
type = sessionNavType;
17+
const pageCfg = useMemo(() => getSubPageConfiguration(location), [location]);
18+
const isSSR = typeof window === 'undefined';
19+
20+
const NavComponent = useMemo(() => {
21+
let { type } = pageCfg;
22+
23+
if (!isSSR) {
24+
// if there's a stored nav type in session storage, retrieve it and overwrite type
25+
const sessionNavType = sessionStorage.getItem('uni-nav[navType]');
26+
if (location.pathname.includes() && sessionNavType && (sessionNavType === 'tool' || sessionNavType === 'marketing')) {
27+
type = sessionNavType;
28+
}
3429
}
3530

3631
// If url contains navTool url parameter. Overwrite settings with parameter.
37-
const urlParams = new URLSearchParams(url.search);
38-
if (urlParams.get('navTool')) {
39-
type = urlParams.get('navTool');
32+
const navTool = (location.search.match(/navTool=(tool|marketing)/) || [])[1];
33+
if (navTool) {
34+
type = navTool;
4035
}
4136

42-
// store nav type for current session
43-
sessionStorage.setItem('uni-nav[navType]', type);
44-
return type;
45-
}, []);
46-
47-
useEffect(() => {
48-
if (uniNavInitialized.current) {
49-
return;
37+
if (!isSSR) {
38+
// store nav type for current session
39+
sessionStorage.setItem('uni-nav[navType]', type);
5040
}
51-
headerRef.current.id = headerElId.current;
41+
return type === 'marketing' ? MarketingNavigation : ToolNavigation;
42+
}, [pageCfg, location]);
5243

53-
uniNavInitialized.current = true;
54-
counter += 1;
44+
const { signOut, signIn, signUp } = useMemo(() => {
45+
const regSource = (location.pathname || '').split('/')[1];
46+
const retUrl = encodeURIComponent(isSSR ? location.href : window.location.href);
5547

56-
const regSource = window.location.pathname.split('/')[1];
57-
const retUrl = encodeURIComponent(window.location.href);
58-
59-
tcUniNav('init', headerElId.current, {
60-
type: navType,
61-
toolName: getSubPageConfiguration().toolName,
62-
toolRoot: getSubPageConfiguration().toolRoot,
63-
user: 'auto',
48+
return {
6449
signOut: () => {
6550
window.location = `${config.URL.BASE}/logout?ref=nav`;
6651
},
@@ -70,27 +55,39 @@ const TopcoderHeader = () => {
7055
signUp: () => {
7156
window.location = `${authURLs.location.replace('%S', retUrl).replace('member?', '#!/member?')}&mode=signUp&regSource=${regSource}`;
7257
},
73-
});
74-
}, [navType]);
58+
};
59+
}, [location]);
7560

7661
return (
77-
<div styleName="header-container" id={headerElId.current} ref={headerRef} />
62+
<div styleName="header-container">
63+
<NavComponent
64+
toolName={pageCfg.toolName}
65+
toolRoot={pageCfg.toolRoot}
66+
user={isAuthenticated ? user : undefined}
67+
signIn={signIn}
68+
signOut={signOut}
69+
signUp={signUp}
70+
currentLocation={location.pathname}
71+
>
72+
<div styleName="loader">
73+
<LoadingIndicator />
74+
</div>
75+
</NavComponent>
76+
</div>
7877
);
7978
};
79+
TopcoderHeader.defaultProps = {
80+
auth: {},
81+
location: typeof window === 'undefined' ? {} : window.location,
82+
};
83+
84+
TopcoderHeader.propTypes = {
85+
auth: PT.shape(),
86+
location: PT.shape(), // sent from withRouter
87+
};
8088

8189
const mapStateToProps = state => ({
8290
auth: state.auth,
8391
});
8492

85-
const TopcoderHeaderConnect = connect(mapStateToProps, null)(TopcoderHeader);
86-
87-
const TopcoderHeaderPlaceholder = () => (
88-
<div styleName="header-container header-container-placeholder">
89-
<LoadingIndicator />
90-
</div>
91-
);
92-
93-
export default SSRPlaceholder()(
94-
TopcoderHeaderConnect,
95-
TopcoderHeaderPlaceholder,
96-
);
93+
export default connect(mapStateToProps, null)(withRouter(TopcoderHeader));
Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1-
@import '~styles/mixins';
2-
31
.header-container {
4-
min-height: 60px;
5-
background-color: #0c0c0c;
2+
position: relative;
63
}
74

8-
.header-container-placeholder {
9-
height: 60px;
5+
.loader {
6+
position: absolute;
7+
top: 0;
8+
left: 0;
9+
right: 0;
10+
bottom: 0;
11+
12+
display: flex;
13+
align-items: center;
14+
justify-content: center;
1015
}

src/shared/utils/url.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,14 +164,14 @@ export function getInitials(firstName = '', lastName = '') {
164164

165165
export const DEFAULT_AVATAR_URL = 'https://images.ctfassets.net/b5f1djy59z3a/4PTwZVSf3W7qgs9WssqbVa/4c51312671a4b9acbdfd7f5e22320b62/default_avatar.svg';
166166

167-
export const getSubPageConfiguration = () => {
167+
export const getSubPageConfiguration = (location) => {
168168
let toolName = 'Community';
169169
let toolRoot = '/';
170170
let loginRedirect = '/';
171171
let type = 'marketing';
172172
let fullFooter = true;
173173

174-
const url = window.location.pathname;
174+
const url = (location || window.location).pathname;
175175

176176
if (url.includes('/gigs')) {
177177
toolName = 'Gigs';

0 commit comments

Comments
 (0)