Skip to content

Commit 807fd0c

Browse files
committed
Merge branch 'feature-contentful-tabs-urls'
2 parents 86a2263 + 876f5b8 commit 807fd0c

File tree

5 files changed

+69
-1
lines changed

5 files changed

+69
-1
lines changed

.circleci/config.yml

+1
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ workflows:
253253
branches:
254254
only:
255255
- develop
256+
- feature-contentful
256257
# This is stage env for production QA releases
257258
- "build-prod-staging":
258259
context : org-global

src/shared/components/Contentful/Tabs/Tabs.jsx

+36-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
TabPanel,
1818
} from 'react-tabs';
1919
import { fixStyle } from 'utils/contentful';
20+
import { getQuery, updateQuery } from 'utils/url';
2021
import defaultTheme from './themes/style.scss';
2122
import zurichTheme from './themes/zurich.scss';
2223
import tabsGroup from './themes/tabsGroup.scss';
@@ -40,7 +41,38 @@ export const TAB_THEMES = {
4041
export default class TabsItemsLoader extends Component {
4142
constructor(props) {
4243
super(props);
43-
this.state = { tabIndex: props.selected };
44+
this.state = {
45+
tabIndex: props.selected || 0,
46+
};
47+
48+
this.updatePageUrl.bind(this);
49+
}
50+
51+
componentDidMount() {
52+
const q = getQuery();
53+
const { tabId } = this.props;
54+
const { tabIndex } = this.state;
55+
if (q.tabs && q.tabs[tabId] && Number(q.tabs[tabId]) !== tabIndex) {
56+
this.setState({ tabIndex: Number(q.tabs[tabId]) });
57+
} else {
58+
this.updatePageUrl();
59+
}
60+
}
61+
62+
componentDidUpdate() {
63+
this.updatePageUrl();
64+
}
65+
66+
updatePageUrl() {
67+
const q = getQuery();
68+
const { tabId } = this.props;
69+
const { tabIndex } = this.state;
70+
updateQuery({
71+
tabs: {
72+
...q.tabs,
73+
[tabId]: tabIndex || 0,
74+
},
75+
});
4476
}
4577

4678
render() {
@@ -50,6 +82,7 @@ export default class TabsItemsLoader extends Component {
5082
spaceName,
5183
environment,
5284
theme,
85+
tabId,
5386
} = this.props;
5487
const { tabIndex } = this.state;
5588

@@ -129,6 +162,7 @@ export default class TabsItemsLoader extends Component {
129162
environment={environment}
130163
selected={fields.selected}
131164
theme={TAB_THEMES[fields.theme || 'Default']}
165+
tabId={tabId}
132166
/>
133167
);
134168
}
@@ -173,4 +207,5 @@ TabsItemsLoader.propTypes = {
173207
environment: PT.string,
174208
selected: PT.number,
175209
theme: PT.shape().isRequired,
210+
tabId: PT.string.isRequired,
176211
};

src/shared/components/Contentful/Tabs/index.jsx

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ function ContentfulTabs(props) {
3434
environment={environment}
3535
selected={fields.selected}
3636
theme={TAB_THEMES[fields.theme || 'Default']}
37+
tabId={fields.urlQueryName || id}
3738
/>
3839
);
3940
}}

src/shared/components/Contentful/Viewport/Viewport.jsx

+11
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import PT from 'prop-types';
55
import React from 'react';
66
import { themr } from 'react-css-super-themr';
7+
import { getHash } from 'utils/url';
8+
79

810
/* Loads viewport content assets. */
911
const Viewport = ({
@@ -13,6 +15,15 @@ const Viewport = ({
1315
viewportId,
1416
animation,
1517
}) => {
18+
const hash = getHash();
19+
if (hash && hash.vid && hash.vid === viewportId) {
20+
setTimeout(() => {
21+
requestAnimationFrame(() => {
22+
const section = document.getElementById(viewportId);
23+
if (section) section.scrollIntoView({ behavior: 'smooth', block: 'start' });
24+
});
25+
});
26+
}
1627
// Animated on scroll viewport?
1728
if (animation.animateOnScroll) {
1829
return (

src/shared/utils/url.js

+20
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,22 @@ import _ from 'lodash';
88
import qs from 'qs';
99
import { isomorphy } from 'topcoder-react-utils';
1010

11+
/**
12+
* Get current URL hash parameters as object
13+
*/
14+
export function getHash() {
15+
if (isomorphy.isServerSide()) return null;
16+
return qs.parse(window.location.hash.slice(1));
17+
}
18+
19+
/**
20+
* Get current URL query parameters as object
21+
*/
22+
export function getQuery() {
23+
if (isomorphy.isServerSide()) return {};
24+
return qs.parse(window.location.search.slice(1));
25+
}
26+
1127
/**
1228
* If executed client-side (determined in this case by the presence of global
1329
* window object), this function updates query section of URL; otherwise does
@@ -22,6 +38,7 @@ export function updateQuery(update) {
2238
if (isomorphy.isServerSide()) return;
2339

2440
let query = qs.parse(window.location.search.slice(1));
41+
const { hash } = window.location;
2542

2643
/* _.merge won't work here, because it just ignores the fields explicitely
2744
* set as undefined in the objects to be merged, rather than deleting such
@@ -31,6 +48,9 @@ export function updateQuery(update) {
3148
else query[key] = value;
3249
});
3350
query = `?${qs.stringify(query, { encodeValuesOnly: true })}`;
51+
if (hash) {
52+
query += hash;
53+
}
3454
window.history.replaceState(window.history.state, '', query);
3555
}
3656

0 commit comments

Comments
 (0)