Skip to content

Commit 0281b4a

Browse files
committed
Loading indicator
1 parent 052786b commit 0281b4a

File tree

7 files changed

+81
-166
lines changed

7 files changed

+81
-166
lines changed

__tests__/shared/components/__snapshots__/TopcoderFooter.jsx.snap

+22-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,26 @@
22

33
exports[`Matches shallow shapshot 1`] = `
44
<div
5-
id="uninav-footerNav-0"
6-
/>
5+
className="src-shared-components-TopcoderFooter-___style__footer-container-placeholder___2RQLw"
6+
>
7+
<svg
8+
className="src-shared-components-LoadingIndicator-styles___container___V7JxFl"
9+
viewBox="0 0 64 64"
10+
>
11+
<circle
12+
className="src-shared-components-LoadingIndicator-styles___circle1___hEgvYX"
13+
cx="32"
14+
cy="32"
15+
id="loading-indicator-circle1"
16+
r="28"
17+
/>
18+
<circle
19+
className="src-shared-components-LoadingIndicator-styles___circle2___2-o58I"
20+
cx="32"
21+
cy="32"
22+
id="loading-indicator-circle2"
23+
r="6"
24+
/>
25+
</svg>
26+
</div>
727
`;
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,13 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

33
exports[`Matches shallow snapshot 1`] = `
4-
<TopcoderHeader
5-
auth={
6-
Object {
7-
"profile": Object {},
8-
}
9-
}
10-
dispatch={[Function]}
4+
<TopcoderHeaderPlaceholder
115
store={
126
Object {
137
"dispatch": [Function],
148
"getState": [Function],
159
"subscribe": [Function],
1610
}
1711
}
18-
storeSubscription={
19-
Subscription {
20-
"listeners": Object {
21-
"notify": [Function],
22-
},
23-
"onStateChange": [Function],
24-
"parentSub": undefined,
25-
"store": Object {
26-
"dispatch": [Function],
27-
"getState": [Function],
28-
"subscribe": [Function],
29-
},
30-
"unsubscribe": null,
31-
}
32-
}
3312
/>
3413
`;

src/shared/components/TopcoderFooter/index.jsx

+15-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
/* global tcUniNav */
22
import React, { useEffect, useMemo, useRef } from 'react';
3+
import LoadingIndicator from 'components/LoadingIndicator';
4+
import { SSRPlaceholder } from '../../utils/SSR';
35
import { getSubPageConfiguration } from '../../utils/url';
6+
import './style.scss';
47

58
let counter = 0;
69
const footerElIdTmpl = 'uninav-footerNav';
710

8-
export default function TopcoderFooter() {
11+
function TopcoderFooter() {
912
const footerRef = useRef();
1013
const footerInitialized = useRef(false);
1114
const footerElId = useRef(`${footerElIdTmpl}-${counter}`);
@@ -48,3 +51,14 @@ export default function TopcoderFooter() {
4851

4952
return <div id={footerElId.current} ref={footerRef} />;
5053
}
54+
55+
const TopcoderFooterPlaceholder = () => (
56+
<div styleName="footer-container-placeholder">
57+
<LoadingIndicator />
58+
</div>
59+
);
60+
61+
export default SSRPlaceholder()(
62+
TopcoderFooter,
63+
TopcoderFooterPlaceholder,
64+
);
Original file line numberDiff line numberDiff line change
@@ -1,140 +1,6 @@
11
@import '~styles/mixins';
22

3-
.mobile-only {
4-
@include md-to-xl {
5-
display: none;
6-
}
7-
}
8-
9-
.link a {
10-
color: #e9e9e9 !important;
11-
}
12-
13-
.sep-line {
14-
height: 2px;
15-
background-color: #555;
16-
border-radius: 1px;
17-
width: 100%;
18-
19-
@include xs-to-sm {
20-
display: none;
21-
}
22-
}
23-
24-
.social-icons {
25-
margin-top: 15px;
26-
27-
@include xs-to-sm {
28-
display: flex;
29-
justify-content: center;
30-
}
31-
32-
a {
33-
margin-right: 5px;
34-
35-
&:last-child {
36-
margin-right: 0;
37-
}
38-
}
39-
}
40-
41-
.mobile-navi {
42-
display: flex;
43-
justify-content: center;
44-
45-
@include md-to-xl {
46-
display: none;
47-
}
48-
49-
.mobile-navi-col {
50-
display: flex;
51-
flex-direction: column;
52-
margin-right: 43px;
53-
54-
&:last-child {
55-
margin-right: 0;
56-
}
57-
58-
a {
59-
color: #e9e9e9;
60-
font-size: 12px;
61-
font-weight: 500;
62-
line-height: 21px;
63-
}
64-
}
65-
}
66-
67-
.footer {
68-
background-color: #2a2a2a;
69-
padding: 30px 80px 21px 80px;
70-
font-family: Roboto, sans-serif;
71-
font-size: 14px;
72-
font-weight: 400;
73-
line-height: 21px;
74-
position: relative;
75-
z-index: 0;
76-
77-
@include xs-to-sm {
78-
padding: 30px 30px 21px 30px;
79-
}
80-
81-
.footer-wrap {
82-
max-width: $screen-lg;
83-
margin: auto;
84-
85-
.logo-wrap {
86-
display: flex;
87-
justify-content: center;
88-
margin-bottom: 30px;
89-
}
90-
}
91-
92-
.navi-links {
93-
margin-bottom: 39px;
94-
display: grid;
95-
grid-template-columns: repeat(6, 1fr);
96-
gap: 20px;
97-
98-
@include xs-to-sm {
99-
display: none;
100-
}
101-
102-
.navi-col {
103-
.navi-col-title {
104-
color: white;
105-
font-family: Roboto, sans-serif;
106-
font-size: 14px;
107-
font-weight: 500;
108-
line-height: 21px;
109-
margin-bottom: 1px;
110-
}
111-
112-
.navi-col-links {
113-
margin-top: 7px;
114-
}
115-
}
116-
}
117-
118-
.bottom {
119-
display: flex;
120-
justify-content: space-between;
121-
padding-top: 22px;
122-
123-
.copyright-notice {
124-
color: #aaa;
125-
126-
@include xs-to-sm {
127-
font-size: 11px;
128-
line-height: 21px;
129-
130-
a {
131-
text-decoration: underline;
132-
}
133-
}
134-
135-
a {
136-
margin-left: 20px;
137-
}
138-
}
139-
}
3+
.footer-container-placeholder {
4+
height: 60px;
5+
background-color: #0c0c0c;
1406
}

src/shared/containers/TopcoderHeader.jsx renamed to src/shared/containers/TopcoderHeader/index.jsx

+19-4
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ import React, { useEffect, useMemo, useRef } from 'react';
33
import PT from 'prop-types';
44
import { connect } from 'react-redux';
55
import { config } from 'topcoder-react-utils';
6+
import LoadingIndicator from 'components/LoadingIndicator';
67
import _ from 'lodash';
7-
import { getInitials, getSubPageConfiguration } from '../utils/url';
8+
import { getInitials, getSubPageConfiguration } from '../../utils/url';
9+
import { SSRPlaceholder } from '../../utils/SSR';
10+
import './styles.scss';
811

912
let counter = 0;
1013
const headerElIdTmpl = 'uninav-headerNav';
@@ -81,9 +84,10 @@ const TopcoderHeader = ({ auth }) => {
8184
});
8285
}, [isAuthenticated, navigationUserInfo]);
8386

84-
return <div id={headerElId.current} ref={headerRef} />;
87+
return (
88+
<div styleName="header-container" id={headerElId.current} ref={headerRef} />
89+
);
8590
};
86-
8791
TopcoderHeader.defaultProps = {
8892
auth: {},
8993
};
@@ -96,4 +100,15 @@ const mapStateToProps = state => ({
96100
auth: state.auth,
97101
});
98102

99-
export default connect(mapStateToProps, null)(TopcoderHeader);
103+
const TopcoderHeaderConnect = connect(mapStateToProps, null)(TopcoderHeader);
104+
105+
const TopcoderHeaderPlaceholder = () => (
106+
<div styleName="header-container header-container-placeholder">
107+
<LoadingIndicator />
108+
</div>
109+
);
110+
111+
export default SSRPlaceholder()(
112+
TopcoderHeaderConnect,
113+
TopcoderHeaderPlaceholder,
114+
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
@import '~styles/mixins';
2+
3+
.header-container {
4+
min-height: 60px;
5+
background-color: #0c0c0c;
6+
}
7+
8+
.header-container-placeholder {
9+
height: 60px;
10+
}

src/shared/utils/SSR.jsx

+11
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,14 @@ export default function SSR(checkStore, updateStore) {
7171
return <Wrapper />;
7272
};
7373
}
74+
75+
/**
76+
* Creates a decorator function for a component that benefits from server-side
77+
* rendering.
78+
*/
79+
export function SSRPlaceholder() {
80+
return (Component, ComponentPlaceholder) => (props) => {
81+
if (isomorphy.isClientSide()) return <Component {...props} />;
82+
return <ComponentPlaceholder {...props} />;
83+
};
84+
}

0 commit comments

Comments
 (0)