Skip to content

Commit 6c251ef

Browse files
committed
1 parent a3676b5 commit 6c251ef

File tree

4 files changed

+68
-1
lines changed

4 files changed

+68
-1
lines changed

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

Lines changed: 36 additions & 1 deletion
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';
@@ -38,7 +39,38 @@ export const TAB_THEMES = {
3839
export default class TabsItemsLoader extends Component {
3940
constructor(props) {
4041
super(props);
41-
this.state = { tabIndex: props.selected };
42+
this.state = {
43+
tabIndex: props.selected || 0,
44+
};
45+
46+
this.updatePageUrl.bind(this);
47+
}
48+
49+
componentDidMount() {
50+
const q = getQuery();
51+
const { tabId } = this.props;
52+
const { tabIndex } = this.state;
53+
if (q.tabs && q.tabs[tabId] && Number(q.tabs[tabId]) !== tabIndex) {
54+
this.setState({ tabIndex: Number(q.tabs[tabId]) });
55+
} else {
56+
this.updatePageUrl();
57+
}
58+
}
59+
60+
componentDidUpdate() {
61+
this.updatePageUrl();
62+
}
63+
64+
updatePageUrl() {
65+
const q = getQuery();
66+
const { tabId } = this.props;
67+
const { tabIndex } = this.state;
68+
updateQuery({
69+
tabs: {
70+
...q.tabs,
71+
[tabId]: tabIndex || 0,
72+
},
73+
});
4274
}
4375

4476
render() {
@@ -48,6 +80,7 @@ export default class TabsItemsLoader extends Component {
4880
spaceName,
4981
environment,
5082
theme,
83+
tabId,
5184
} = this.props;
5285
const { tabIndex } = this.state;
5386

@@ -127,6 +160,7 @@ export default class TabsItemsLoader extends Component {
127160
environment={environment}
128161
selected={fields.selected}
129162
theme={TAB_THEMES[fields.theme || 'Default']}
163+
tabId={tabId}
130164
/>
131165
);
132166
}
@@ -171,4 +205,5 @@ TabsItemsLoader.propTypes = {
171205
environment: PT.string,
172206
selected: PT.number,
173207
theme: PT.shape().isRequired,
208+
tabId: PT.string.isRequired,
174209
};

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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 11 additions & 0 deletions
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

Lines changed: 20 additions & 0 deletions
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)