diff --git a/.circleci/config.yml b/.circleci/config.yml index e751e36073..080146f76e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -180,10 +180,8 @@ workflows: context : org-global filters: branches: - only: - - hot-fixes - - legacy-tco - - general-features + only: + - legacy-tco # This is beta env for production soft releases - "build-prod-beta": context : org-global diff --git a/README.md b/README.md index c1706ba0ea..cf28314b2e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ ![Dev Build Status](https://img.shields.io/circleci/project/github/topcoder-platform/community-app/develop.svg?label=develop) ![Master Build Status](https://img.shields.io/circleci/project/github/topcoder-platform/community-app/master.svg?label=master) +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=topcoder-platform_community-app&metric=alert_status)](https://sonarcloud.io/dashboard?id=topcoder-platform_community-app) +[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=topcoder-platform_community-app&metric=security_rating)](https://sonarcloud.io/dashboard?id=topcoder-platform_community-app) +[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=topcoder-platform_community-app&metric=vulnerabilities)](https://sonarcloud.io/dashboard?id=topcoder-platform_community-app) # Topcoder Community App New version of Topcoder Community website. diff --git a/src/assets/themes/tco18-01/TCO01.svg b/src/assets/themes/tco18-01/TCO01.svg new file mode 100644 index 0000000000..1d398a46c5 --- /dev/null +++ b/src/assets/themes/tco18-01/TCO01.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/themes/tco18-01/TCO02.png b/src/assets/themes/tco18-01/TCO02.png new file mode 100644 index 0000000000..40b9c39a92 Binary files /dev/null and b/src/assets/themes/tco18-01/TCO02.png differ diff --git a/src/assets/themes/tco18-01/TCO03.png b/src/assets/themes/tco18-01/TCO03.png new file mode 100644 index 0000000000..0966377755 Binary files /dev/null and b/src/assets/themes/tco18-01/TCO03.png differ diff --git a/src/assets/themes/tco18-01/TCO04.png b/src/assets/themes/tco18-01/TCO04.png new file mode 100644 index 0000000000..89f37fdfda Binary files /dev/null and b/src/assets/themes/tco18-01/TCO04.png differ diff --git a/src/assets/themes/tco18-01/TCO05.png b/src/assets/themes/tco18-01/TCO05.png new file mode 100644 index 0000000000..82a79d9bde Binary files /dev/null and b/src/assets/themes/tco18-01/TCO05.png differ diff --git a/src/assets/themes/tco18-01/TCO06.png b/src/assets/themes/tco18-01/TCO06.png new file mode 100644 index 0000000000..1de8303d7c Binary files /dev/null and b/src/assets/themes/tco18-01/TCO06.png differ diff --git a/src/assets/themes/tco18-01/TCO07.png b/src/assets/themes/tco18-01/TCO07.png new file mode 100644 index 0000000000..20bc154cc4 Binary files /dev/null and b/src/assets/themes/tco18-01/TCO07.png differ diff --git a/src/assets/themes/tco18-01/TCO08.png b/src/assets/themes/tco18-01/TCO08.png new file mode 100644 index 0000000000..9236de62d7 Binary files /dev/null and b/src/assets/themes/tco18-01/TCO08.png differ diff --git a/src/assets/themes/tco18-01/TCO09.png b/src/assets/themes/tco18-01/TCO09.png new file mode 100644 index 0000000000..38cc88a5c3 Binary files /dev/null and b/src/assets/themes/tco18-01/TCO09.png differ diff --git a/src/assets/themes/tco18-01/TCO10.png b/src/assets/themes/tco18-01/TCO10.png new file mode 100644 index 0000000000..93315a78b0 Binary files /dev/null and b/src/assets/themes/tco18-01/TCO10.png differ diff --git a/src/assets/themes/tco18-01/TCO11.png b/src/assets/themes/tco18-01/TCO11.png new file mode 100644 index 0000000000..d3eddfc629 Binary files /dev/null and b/src/assets/themes/tco18-01/TCO11.png differ diff --git a/src/assets/themes/tco18-01/TCO12.svg b/src/assets/themes/tco18-01/TCO12.svg new file mode 100644 index 0000000000..c04ace2d77 --- /dev/null +++ b/src/assets/themes/tco18-01/TCO12.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/assets/themes/tco18-01/TCO13.svg b/src/assets/themes/tco18-01/TCO13.svg new file mode 100644 index 0000000000..71acd34eab --- /dev/null +++ b/src/assets/themes/tco18-01/TCO13.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/themes/tco18-01/TCO14.svg b/src/assets/themes/tco18-01/TCO14.svg new file mode 100644 index 0000000000..8b56609a0d --- /dev/null +++ b/src/assets/themes/tco18-01/TCO14.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/themes/tco18-01/TCO15.svg b/src/assets/themes/tco18-01/TCO15.svg new file mode 100644 index 0000000000..eb6c6287d7 --- /dev/null +++ b/src/assets/themes/tco18-01/TCO15.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/themes/tco18-01/TCO16.svg b/src/assets/themes/tco18-01/TCO16.svg new file mode 100644 index 0000000000..8fd81e127f --- /dev/null +++ b/src/assets/themes/tco18-01/TCO16.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/assets/themes/tco17/TCO17.svg b/src/assets/themes/tco18-01/TCO17.svg similarity index 100% rename from src/assets/themes/tco17/TCO17.svg rename to src/assets/themes/tco18-01/TCO17.svg diff --git a/src/assets/themes/tco18/TCO18.svg b/src/assets/themes/tco18-01/TCO18.svg similarity index 100% rename from src/assets/themes/tco18/TCO18.svg rename to src/assets/themes/tco18-01/TCO18.svg diff --git a/src/server/tc-communities/tco01/metadata.json b/src/server/tc-communities/tco01/metadata.json new file mode 100644 index 0000000000..4d06b51b57 --- /dev/null +++ b/src/server/tc-communities/tco01/metadata.json @@ -0,0 +1,14 @@ +{ + "communityId": "tco01", + "hidden": true, + "communityName": "TCO01", + "groupIds": [], + "hideSearch": true, + "logos": [{ + "img": "/community-app-assets/themes/tco18-01/TCO01.svg", + "url": "https://tco01.topcoder.com" + }], + "newsFeed": "http://www.topcoder.com/feed", + "subdomains": ["tco01"], + "description": "2001 Topcoder Open. The Ultimate Programming & Design Tournament" +} diff --git a/src/server/tc-communities/tco02/metadata.json b/src/server/tc-communities/tco02/metadata.json new file mode 100644 index 0000000000..2e3f4fe263 --- /dev/null +++ b/src/server/tc-communities/tco02/metadata.json @@ -0,0 +1,14 @@ +{ + "communityId": "tco02", + "hidden": true, + "communityName": "TCO02", + "groupIds": [], + "hideSearch": true, + "logos": [{ + "img": "/community-app-assets/themes/tco18-01/TCO02.png", + "url": "https://tco02.topcoder.com" + }], + "newsFeed": "http://www.topcoder.com/feed", + "subdomains": ["tco02"], + "description": "2002 Topcoder Open. The Ultimate Programming & Design Tournament" +} diff --git a/src/server/tc-communities/tco03/metadata.json b/src/server/tc-communities/tco03/metadata.json new file mode 100644 index 0000000000..a7ed9c0287 --- /dev/null +++ b/src/server/tc-communities/tco03/metadata.json @@ -0,0 +1,17 @@ +{ + "communityId": "tco03", + "hidden": true, + "communityName": "TCO03", + "groupIds": [], + "hideSearch": true, + "logos": [{ + "img": "/community-app-assets/themes/tco18-01/TCO03.png", + "url": "https://tco03.topcoder.com" + }], + "menuItems": [{ + "navigationMenu": "1NTh1Tcgf31hGo5OSUXSTA" + }], + "newsFeed": "http://www.topcoder.com/feed", + "subdomains": ["tco03"], + "description": "2003 Topcoder Open. The Ultimate Programming & Design Tournament" +} diff --git a/src/server/tc-communities/tco04/metadata.json b/src/server/tc-communities/tco04/metadata.json new file mode 100644 index 0000000000..5c81ed7c9a --- /dev/null +++ b/src/server/tc-communities/tco04/metadata.json @@ -0,0 +1,17 @@ +{ + "communityId": "tco04", + "hidden": true, + "communityName": "TCO04", + "groupIds": [], + "hideSearch": true, + "logos": [{ + "img": "/community-app-assets/themes/tco18-01/TCO04.png", + "url": "https://tco04.topcoder.com" + }], + "menuItems": [{ + "navigationMenu": "7FFCD13ZeWgLUhgC2FS86M" + }], + "newsFeed": "http://www.topcoder.com/feed", + "subdomains": ["tco04"], + "description": "2004 Topcoder Open. The Ultimate Programming & Design Tournament" +} diff --git a/src/server/tc-communities/tco05/metadata.json b/src/server/tc-communities/tco05/metadata.json new file mode 100644 index 0000000000..cdbc4cad14 --- /dev/null +++ b/src/server/tc-communities/tco05/metadata.json @@ -0,0 +1,17 @@ +{ + "communityId": "tco05", + "hidden": true, + "communityName": "TCO05", + "groupIds": [], + "hideSearch": true, + "logos": [{ + "img": "/community-app-assets/themes/tco18-01/TCO05.png", + "url": "https://tco05.topcoder.com" + }], + "menuItems": [{ + "navigationMenu": "5ckaJfIYOf7juZczKSwjyB" + }], + "newsFeed": "http://www.topcoder.com/feed", + "subdomains": ["tco05"], + "description": "2005 Topcoder Open. The Ultimate Programming & Design Tournament" +} diff --git a/src/server/tc-communities/tco06/metadata.json b/src/server/tc-communities/tco06/metadata.json new file mode 100644 index 0000000000..212c1414f9 --- /dev/null +++ b/src/server/tc-communities/tco06/metadata.json @@ -0,0 +1,17 @@ +{ + "communityId": "tco06", + "hidden": true, + "communityName": "TCO06", + "groupIds": [], + "hideSearch": true, + "logos": [{ + "img": "/community-app-assets/themes/tco18-01/TCO06.png", + "url": "https://tco06.topcoder.com" + }], + "menuItems": [{ + "navigationMenu": "TTGuQGYZ7Q5TFm3m6hyua" + }], + "newsFeed": "http://www.topcoder.com/feed", + "subdomains": ["tco06"], + "description": "2006 Topcoder Open. The Ultimate Programming & Design Tournament" +} diff --git a/src/server/tc-communities/tco07/metadata.json b/src/server/tc-communities/tco07/metadata.json new file mode 100644 index 0000000000..2045a22acc --- /dev/null +++ b/src/server/tc-communities/tco07/metadata.json @@ -0,0 +1,17 @@ +{ + "communityId": "tco07", + "hidden": true, + "communityName": "TCO07", + "groupIds": [], + "hideSearch": true, + "logos": [{ + "img": "/community-app-assets/themes/tco18-01/TCO07.png", + "url": "https://tco07.topcoder.com" + }], + "menuItems": [{ + "navigationMenu": "3fVSY5EbFPFAykNujEsvv8" + }], + "newsFeed": "http://www.topcoder.com/feed", + "subdomains": ["tco07"], + "description": "2007 Topcoder Open. The Ultimate Programming & Design Tournament" +} diff --git a/src/server/tc-communities/tco08/metadata.json b/src/server/tc-communities/tco08/metadata.json new file mode 100644 index 0000000000..2240217b85 --- /dev/null +++ b/src/server/tc-communities/tco08/metadata.json @@ -0,0 +1,17 @@ +{ + "communityId": "tco08", + "hidden": true, + "communityName": "TCO08", + "groupIds": [], + "hideSearch": true, + "logos": [{ + "img": "/community-app-assets/themes/tco18-01/TCO08.png", + "url": "https://tco08.topcoder.com" + }], + "menuItems": [{ + "navigationMenu": "4rYnxNIsLi0zVAvDsTK9JK" + }], + "newsFeed": "http://www.topcoder.com/feed", + "subdomains": ["tco08"], + "description": "2008 Topcoder Open. The Ultimate Programming & Design Tournament" +} diff --git a/src/server/tc-communities/tco09/metadata.json b/src/server/tc-communities/tco09/metadata.json new file mode 100644 index 0000000000..76ae2f6822 --- /dev/null +++ b/src/server/tc-communities/tco09/metadata.json @@ -0,0 +1,17 @@ +{ + "communityId": "tco09", + "hidden": true, + "communityName": "TCO09", + "groupIds": [], + "hideSearch": true, + "logos": [{ + "img": "/community-app-assets/themes/tco18-01/TCO09.png", + "url": "https://tco09.topcoder.com" + }], + "menuItems": [{ + "navigationMenu": "4NcwpDu5Fzx1BE36PRoySk" + }], + "newsFeed": "http://www.topcoder.com/feed", + "subdomains": ["tco09"], + "description": "2009 Topcoder Open. The Ultimate Programming & Design Tournament" +} diff --git a/src/server/tc-communities/tco10/metadata.json b/src/server/tc-communities/tco10/metadata.json new file mode 100644 index 0000000000..0aea6f74b8 --- /dev/null +++ b/src/server/tc-communities/tco10/metadata.json @@ -0,0 +1,17 @@ +{ + "communityId": "tco10", + "hidden": true, + "communityName": "TCO10", + "groupIds": [], + "hideSearch": true, + "logos": [{ + "img": "/community-app-assets/themes/tco18-01/TCO10.png", + "url": "https://tco10.topcoder.com" + }], + "menuItems": [{ + "navigationMenu": "NEG4INIrZGWnVQXbsxzbq" + }], + "newsFeed": "http://www.topcoder.com/feed", + "subdomains": ["tco10"], + "description": "2010 Topcoder Open. The Ultimate Programming & Design Tournament" +} diff --git a/src/server/tc-communities/tco11/metadata.json b/src/server/tc-communities/tco11/metadata.json new file mode 100644 index 0000000000..1fe51ed2eb --- /dev/null +++ b/src/server/tc-communities/tco11/metadata.json @@ -0,0 +1,17 @@ +{ + "communityId": "tco11", + "hidden": true, + "communityName": "TCO11", + "groupIds": [], + "hideSearch": true, + "logos": [{ + "img": "/community-app-assets/themes/tco18-01/TCO11.png", + "url": "https://tco11.topcoder.com" + }], + "menuItems": [{ + "navigationMenu": "7tudOHlGLUOTzsPVPrV7gm" + }], + "newsFeed": "http://www.topcoder.com/feed", + "subdomains": ["tco11"], + "description": "2011 Topcoder Open. The Ultimate Programming & Design Tournament" +} diff --git a/src/server/tc-communities/tco12/metadata.json b/src/server/tc-communities/tco12/metadata.json new file mode 100644 index 0000000000..0115bee5c7 --- /dev/null +++ b/src/server/tc-communities/tco12/metadata.json @@ -0,0 +1,17 @@ +{ + "communityId": "tco12", + "hidden": true, + "communityName": "TCO12", + "groupIds": [], + "hideSearch": true, + "logos": [{ + "img": "/community-app-assets/themes/tco18-01/TCO12.svg", + "url": "https://tco12.topcoder.com" + }], + "menuItems": [{ + "navigationMenu": "1EOuUA49hvEfR12P1h6o4J" + }], + "newsFeed": "http://www.topcoder.com/feed", + "subdomains": ["tco12"], + "description": "2012 Topcoder Open. The Ultimate Programming & Design Tournament" +} diff --git a/src/server/tc-communities/tco13/metadata.json b/src/server/tc-communities/tco13/metadata.json new file mode 100644 index 0000000000..baab2f6b92 --- /dev/null +++ b/src/server/tc-communities/tco13/metadata.json @@ -0,0 +1,17 @@ +{ + "communityId": "tco13", + "hidden": true, + "communityName": "TCO13", + "groupIds": [], + "hideSearch": true, + "logos": [{ + "img": "/community-app-assets/themes/tco18-01/TCO13.svg", + "url": "https://tco13.topcoder.com" + }], + "menuItems": [{ + "navigationMenu": "4kGaSRZWN8Hb9kqWrfqexL" + }], + "newsFeed": "http://www.topcoder.com/feed", + "subdomains": ["tco13"], + "description": "2013 Topcoder Open. The Ultimate Programming & Design Tournament" +} diff --git a/src/server/tc-communities/tco14/metadata.json b/src/server/tc-communities/tco14/metadata.json new file mode 100644 index 0000000000..1ce4036127 --- /dev/null +++ b/src/server/tc-communities/tco14/metadata.json @@ -0,0 +1,17 @@ +{ + "communityId": "tco14", + "hidden": true, + "communityName": "TCO14", + "groupIds": [], + "hideSearch": true, + "logos": [{ + "img": "/community-app-assets/themes/tco18-01/TCO14.svg", + "url": "https://tco14.topcoder.com" + }], + "menuItems": [{ + "navigationMenu": "6rXdWUciLO5dathvpOmPRc" + }], + "newsFeed": "http://www.topcoder.com/feed", + "subdomains": ["tco14"], + "description": "2014 Topcoder Open. The Ultimate Programming & Design Tournament" +} diff --git a/src/server/tc-communities/tco15/metadata.json b/src/server/tc-communities/tco15/metadata.json new file mode 100644 index 0000000000..a0d1a5057e --- /dev/null +++ b/src/server/tc-communities/tco15/metadata.json @@ -0,0 +1,17 @@ +{ + "communityId": "tco15", + "hidden": true, + "communityName": "TCO15", + "groupIds": [], + "hideSearch": true, + "logos": [{ + "img": "/community-app-assets/themes/tco18-01/TCO15.svg", + "url": "https://tco15.topcoder.com" + }], + "menuItems": [{ + "navigationMenu": "2YbWIaEZGghDDiFtb0pYGz" + }], + "newsFeed": "http://www.topcoder.com/feed", + "subdomains": ["tco15"], + "description": "2015 Topcoder Open. The Ultimate Programming & Design Tournament" +} diff --git a/src/server/tc-communities/tco16/metadata.json b/src/server/tc-communities/tco16/metadata.json new file mode 100644 index 0000000000..f89055db0c --- /dev/null +++ b/src/server/tc-communities/tco16/metadata.json @@ -0,0 +1,17 @@ +{ + "communityId": "tco16", + "hidden": true, + "communityName": "TCO16", + "groupIds": [], + "hideSearch": true, + "logos": [{ + "img": "/community-app-assets/themes/tco18-01/TCO16.svg", + "url": "https://tco16.topcoder.com" + }], + "menuItems": [{ + "navigationMenu": "2CnO5xaWYA4XoB3musqcku" + }], + "newsFeed": "http://www.topcoder.com/feed", + "subdomains": ["tco16"], + "description": "2016 Topcoder Open. The Ultimate Programming & Design Tournament" +} diff --git a/src/server/tc-communities/tco17/metadata.json b/src/server/tc-communities/tco17/metadata.json index 14f7f07d93..f08876d8e9 100644 --- a/src/server/tc-communities/tco17/metadata.json +++ b/src/server/tc-communities/tco17/metadata.json @@ -5,7 +5,7 @@ "groupIds": [], "hideSearch": true, "logos": [{ - "img": "/community-app-assets/themes/tco17/TCO17.svg", + "img": "/community-app-assets/themes/tco18-01/TCO17.svg", "url": "https://tco17.topcoder.com" }], "menuItems": [{ diff --git a/src/server/tc-communities/tco18/metadata.json b/src/server/tc-communities/tco18/metadata.json index 80382d76fc..2f66559f70 100644 --- a/src/server/tc-communities/tco18/metadata.json +++ b/src/server/tc-communities/tco18/metadata.json @@ -5,7 +5,7 @@ "groupIds": [], "hideSearch": true, "logos": [{ - "img": "/community-app-assets/themes/tco18/TCO18.svg", + "img": "/community-app-assets/themes/tco18-01/TCO18.svg", "url": "https://tco18.topcoder.com" }], "menuItems": [{ diff --git a/src/server/tc-communities/tco19/metadata.json b/src/server/tc-communities/tco19/metadata.json index c39622d0c9..ed501a0c34 100644 --- a/src/server/tc-communities/tco19/metadata.json +++ b/src/server/tc-communities/tco19/metadata.json @@ -14,7 +14,7 @@ "url": "https://tco19.topcoder.com" }], "menuItems": [{ - "navigationMenu": "2Q7PFVzaoEGK0SciSceoew" + "navigationMenu": "3QcKcut8TFtBwXk0Dkk0AZ" }], "newsFeed": "http://www.topcoder.com/feed", "subdomains": ["tco19"], diff --git a/src/shared/components/Contentful/Menu/Menu.jsx b/src/shared/components/Contentful/Menu/Menu.jsx index 0f8c8b524e..86a249aff5 100644 --- a/src/shared/components/Contentful/Menu/Menu.jsx +++ b/src/shared/components/Contentful/Menu/Menu.jsx @@ -3,21 +3,27 @@ * */ /* global window */ +import _ from 'lodash'; import React from 'react'; import PT from 'prop-types'; -import { isomorphy } from 'topcoder-react-utils'; -import { removeTrailingSlash } from 'utils/url'; import Dropdown from 'components/tc-communities/Dropdown'; +import { isomorphy } from 'topcoder-react-utils'; +import { isActive, linkText, target } from 'utils/contentful'; import MenuItem from './MenuItem'; export default function Menu(props) { const { - menuItems, theme, baseUrl, parentItems, activeParentItem, + menuItems, theme, baseUrl, parentBaseUrl, parentItems, activeParentItem, } = props; - let pathname = ''; + if (isomorphy.isClientSide()) { - pathname = removeTrailingSlash(window.location.pathname); + if (baseUrl && baseUrl === parentBaseUrl && baseUrl !== _.trimEnd(window.location.pathname, '/')) { + return null; + } + } else { + // TODO: should probably get the current URL from the web framework + // and apply the check ot current location path } return ( @@ -27,11 +33,11 @@ export default function Menu(props) {
({ - label: pI.fields.linkText, - value: pI.fields.slug, - url: `${baseUrl}/../${pI.fields.slug}`, + label: linkText(pI), + value: pI.sys.id, + url: target(parentBaseUrl, pI), }))} - value={activeParentItem.fields.slug} + value={activeParentItem.sys.id} onChange={(option) => { window.location.href = option.url; }} />
@@ -43,10 +49,7 @@ export default function Menu(props) { @@ -72,6 +75,7 @@ Menu.propTypes = { }), menuItems: PT.arrayOf(PT.shape()), baseUrl: PT.string.isRequired, + parentBaseUrl: PT.string.isRequired, parentItems: PT.arrayOf(PT.shape()).isRequired, activeParentItem: PT.shape().isRequired, }; diff --git a/src/shared/components/Contentful/Menu/MenuItem.jsx b/src/shared/components/Contentful/Menu/MenuItem.jsx index 794723b077..b5c8e3f221 100644 --- a/src/shared/components/Contentful/Menu/MenuItem.jsx +++ b/src/shared/components/Contentful/Menu/MenuItem.jsx @@ -4,26 +4,14 @@ import React from 'react'; import PT from 'prop-types'; import { NavLink } from 'topcoder-react-utils'; +import { linkText, target } from 'utils/contentful'; export default function MenuItem(props) { const { item, theme, isActive, baseUrl, } = props; - // use/prefer url if available - let to = ''; - if (item.fields.url) { - to = item.fields.url.startsWith('http') ? item.fields.url : `${baseUrl}${item.fields.url}`; - } else if (item.fields.viewport) { - // for viewports use - // menu item slug to build the url - to = `${baseUrl}/${item.fields.slug}`; - } else { - // case when nor url either viewport - // of item are specified. Bad link!? - to = '#'; - } - return ( + return item.fields.excludeFromNavigationMenus !== true ? (
  • isActive} - to={to} + to={target(baseUrl, item)} openNewTab={item.fields.inNewTab} > - {item.fields.linkText || item.fields.name} + {linkText(item)}
  • - ); + ) : null; } diff --git a/src/shared/components/Contentful/Menu/index.jsx b/src/shared/components/Contentful/Menu/index.jsx index f2184ec7b5..620c668314 100644 --- a/src/shared/components/Contentful/Menu/index.jsx +++ b/src/shared/components/Contentful/Menu/index.jsx @@ -4,10 +4,11 @@ /* global window */ import _ from 'lodash'; import ContentfulLoader from 'containers/ContentfulLoader'; +import LoadingIndicator from 'components/LoadingIndicator'; import PT from 'prop-types'; import React from 'react'; -import { isomorphy } from 'topcoder-react-utils'; import { removeTrailingSlash } from 'utils/url'; +import { isActive, target } from 'utils/contentful'; import NavMenu from './Menu'; @@ -27,34 +28,53 @@ function MenuItemsLoader(props) { title, themeName, theme, + parentBaseUrl, parentItems, activeParentItem, level, + spaceName, + environment, } = props; const themeToUse = theme || THEMES[themeName]; let { baseUrl } = props; - let pathname = ''; // remove trail slash from baseUrl baseUrl = removeTrailingSlash(baseUrl); - // check current path - if (isomorphy.isClientSide()) { - pathname = removeTrailingSlash(window.location.pathname); - } + return ( { const submenu = _.compact(_.values(data.entries.items).map((menuItem) => { - if (menuItem.fields.submenu - && (pathname.indexOf(menuItem.fields.slug) !== -1 || (pathname === baseUrl && menuItem.fields.url === '/'))) { + if (menuItem.fields.submenu && isActive(baseUrl, menuItem, 'submenu')) { return (
    +
    + ); + } + if (menuItem.fields.childRoutes && menuItem.fields.excludeFromNavigationMenus !== true && isActive(baseUrl, menuItem, 'childRoutes')) { + return ( +
    + @@ -87,6 +108,7 @@ function MenuItemsLoader(props) { key={menuId} theme={themeToUse} baseUrl={baseUrl} + parentBaseUrl={parentBaseUrl} parentItems={parentItems} activeParentItem={activeParentItem} /> @@ -98,6 +120,7 @@ function MenuItemsLoader(props) {
    ); }} + renderPlaceholder={LoadingIndicator} /> ); } @@ -105,16 +128,21 @@ function MenuItemsLoader(props) { MenuItemsLoader.defaultProps = { title: '', theme: null, + spaceName: null, + environment: null, }; MenuItemsLoader.propTypes = { menuId: PT.string.isRequired, ids: PT.arrayOf(PT.string).isRequired, preview: PT.bool.isRequired, + spaceName: PT.string, + environment: PT.string, title: PT.string, themeName: PT.string.isRequired, baseUrl: PT.string.isRequired, theme: PT.shape(), + parentBaseUrl: PT.string.isRequired, parentItems: PT.arrayOf(PT.shape()).isRequired, activeParentItem: PT.shape().isRequired, level: PT.number.isRequired, @@ -126,15 +154,20 @@ export default function ContentfulMenu(props) { preview, baseUrl, theme, + parentBaseUrl, parentItems, activeParentItem, level, + spaceName, + environment, } = props; return ( { const { fields } = Object.values(data.entries.items)[0]; if (!fields) return null; @@ -143,24 +176,31 @@ export default function ContentfulMenu(props) { menuId={id} ids={_.map(fields.items, 'sys.id')} preview={preview} + spaceName={spaceName} + environment={environment} themeName={fields.theme} theme={theme} title={fields.title} baseUrl={fields.baseUrl || baseUrl} + parentBaseUrl={parentBaseUrl} parentItems={parentItems} activeParentItem={activeParentItem} level={level} /> ); }} + renderPlaceholder={LoadingIndicator} /> ); } ContentfulMenu.defaultProps = { preview: false, + spaceName: null, + environment: null, baseUrl: '', theme: null, + parentBaseUrl: '', parentItems: [], activeParentItem: {}, level: 0, @@ -171,7 +211,10 @@ ContentfulMenu.propTypes = { preview: PT.bool, baseUrl: PT.string, theme: PT.shape(), + parentBaseUrl: PT.string, parentItems: PT.arrayOf(PT.shape()), activeParentItem: PT.shape(), level: PT.number, + spaceName: PT.string, + environment: PT.string, }; diff --git a/src/shared/components/Contentful/Menu/themes/default.scss b/src/shared/components/Contentful/Menu/themes/default.scss index 9b7535fc99..17d71a3b58 100644 --- a/src/shared/components/Contentful/Menu/themes/default.scss +++ b/src/shared/components/Contentful/Menu/themes/default.scss @@ -48,10 +48,10 @@ line-height: 30px; a { - color: #aaaaab; + color: #aaaaab !important; &:hover { - color: darken($color: #aaaaab, $amount: 10); + color: darken($color: #aaaaab, $amount: 10) !important; } } @@ -59,7 +59,7 @@ color: #404041; &:hover { - color: darken($color: #404041, $amount: 20); + color: darken($color: #404041, $amount: 20) !important; } } @@ -107,11 +107,11 @@ .menuItemLevel { a { - color: #a3a3ad; + color: #a3a3ad !important; font-weight: 400; &:hover { - color: $tc-white; + color: $tc-white !important; } } @@ -120,7 +120,7 @@ } .menuItemLinkActive::after { - background-color: $tc-white; + background-color: $tc-white !important; } } @@ -167,7 +167,7 @@ font-size: 13px; font-weight: 700; line-height: 25px; - color: $tc-white; + color: $tc-white !important; text-transform: uppercase; :global { @@ -184,7 +184,7 @@ font-weight: 400; line-height: 30px; text-transform: uppercase; - color: #47474f; + color: #47474f !important; padding-left: 10px; padding-right: 20px; diff --git a/src/shared/components/Contentful/Route.jsx b/src/shared/components/Contentful/Route.jsx index d18c502586..204a44064c 100644 --- a/src/shared/components/Contentful/Route.jsx +++ b/src/shared/components/Contentful/Route.jsx @@ -58,6 +58,7 @@ function ChildRoutesLoader(props) { preview={preview} spaceName={spaceName} environment={environment} + baseUrl={url} /> ) : } diff --git a/src/shared/components/tc-communities/communities/tco19/Home/index.jsx b/src/shared/components/tc-communities/communities/tco19/Home/index.jsx deleted file mode 100644 index 9fb4d0d109..0000000000 --- a/src/shared/components/tc-communities/communities/tco19/Home/index.jsx +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; -import Viewport from 'components/Contentful/Viewport'; - -export default function Home() { - return ( - - ); -} diff --git a/src/shared/components/tc-communities/communities/tco19/Home/style.scss b/src/shared/components/tc-communities/communities/tco19/Home/style.scss deleted file mode 100644 index e4bd7a5666..0000000000 --- a/src/shared/components/tc-communities/communities/tco19/Home/style.scss +++ /dev/null @@ -1,57 +0,0 @@ -@import '~styles/mixins'; - -.statsContainer { - padding: 0; -} - -.statsContent { - border-bottom: 1px solid #ddd; - padding: 43px 38px 50px; - - @include xs-to-sm { - display: flex; - justify-content: space-around; - padding: 30px 12px 32px; - } -} - -.resourcesContainer { - background-color: #fafafa; - padding: 70px 0; - - @include xs-to-sm { - padding: 40px 0; - } -} - -.linksContainer { - padding: 24px 0 60px; - - @include xs-to-sm { - padding: 0; - } -} - -.introContainer { - background: $tc-gray-neutral-light; - color: #787d81; - padding-bottom: 48px; - margin-bottom: 24px; - - @include xs-to-sm { - padding-left: 24px; - padding-right: 24px; - } - - h1 { - color: #394146; - font: 600 36px 'Open Sans', sans-serif; - margin-bottom: 12px; - } - - p { - color: #787d81; - font: 15px/22px 'Open Sans', sans-serif; - padding: 6px 0; - } -} diff --git a/src/shared/containers/tc-communities/tco19/Home.jsx b/src/shared/containers/tc-communities/tco19/Home.jsx deleted file mode 100644 index 4973462ce3..0000000000 --- a/src/shared/containers/tc-communities/tco19/Home.jsx +++ /dev/null @@ -1,11 +0,0 @@ -import _ from 'lodash'; -import Home from 'components/tc-communities/communities/tco19/Home'; -import { connect } from 'react-redux'; - -function mapStateToProps(state) { - return { - userGroups: _.get(state.auth.profile, 'groups'), - }; -} - -export default connect(mapStateToProps)(Home); diff --git a/src/shared/routes/Communities/Routes.jsx b/src/shared/routes/Communities/Routes.jsx index 8fda8c85b2..2c3e3dfddd 100644 --- a/src/shared/routes/Communities/Routes.jsx +++ b/src/shared/routes/Communities/Routes.jsx @@ -17,18 +17,55 @@ import Veterans from './Veterans'; import Wipro from './Wipro'; import Cognitive from './Cognitive'; import IoT from './iot'; -import TCO17 from './TCO17'; -import TCO18 from './TCO18'; -import TCO19 from './TCO19'; +import tco01 from './TCO01'; +import tco02 from './TCO02'; +import tco03 from './TCO03'; +import tco04 from './TCO04'; +import tco05 from './TCO05'; +import tco06 from './TCO06'; +import tco07 from './TCO07'; +import tco08 from './TCO08'; +import tco09 from './TCO09'; +import tco10 from './TCO10'; +import tco11 from './TCO11'; +import tco12 from './TCO12'; +import tco13 from './TCO13'; +import tco14 from './TCO14'; +import tco15 from './TCO15'; +import tco16 from './TCO16'; +import tco17 from './TCO17'; +import tco18 from './TCO18'; +import tco19 from './TCO19'; import Mobile from './Mobile'; import Zurich from './Zurich'; +const TCOs = { + tco01, + tco02, + tco03, + tco04, + tco05, + tco06, + tco07, + tco08, + tco09, + tco10, + tco11, + tco12, + tco13, + tco14, + tco15, + tco16, + tco17, + tco18, + tco19, +}; + export default function Communities({ base, communityId, member, meta, }) { switch (communityId) { - case 'blockchain': - return ; + case 'blockchain': return ; case 'community-2': return ; case 'cs': return ; case 'zurich': return ; @@ -37,16 +74,18 @@ export default function Communities({ case 'srmx': return ; case 'taskforce': return ; case 'tc-prod-dev': return ; - case 'veterans': - return ; + case 'veterans': return ; case 'wipro': return ; case 'cognitive': return ; case 'iot': return ; - case 'tco17': return ; - case 'tco18': return ; - case 'tco19': return ; case 'mobile': return ; - default: throw new Error('Unknown community ID!'); + default: + // to avoid listing all TCOs we use defaut switch with a check + if (TCOs[communityId]) { + const TCOCommunity = TCOs[communityId]; + return ; + } + throw new Error('Unknown community ID!'); } } diff --git a/src/shared/routes/Communities/TCO01/Routes.jsx b/src/shared/routes/Communities/TCO01/Routes.jsx new file mode 100644 index 0000000000..31b00fba55 --- /dev/null +++ b/src/shared/routes/Communities/TCO01/Routes.jsx @@ -0,0 +1,48 @@ +/** + * Routing of TCO01 Community. + */ + +import ContentfulRoute from 'components/Contentful/Route'; +import Error404 from 'components/Error404'; +import Header from 'containers/tc-communities/Header'; +import PT from 'prop-types'; +import React from 'react'; +import { Route, Switch } from 'react-router-dom'; + +import headerTheme from 'components/tc-communities/communities/tco/themes/header.scss'; + +export default function TCO01({ base }) { + return ( + ( +
    +
    + + } + id="1fX3oi25s40qzhFlzeWaoc" + /> + + +
    + )} + path={`${base}/:pageId?`} + /> + ); +} + +TCO01.defaultProps = { + base: '', +}; + +TCO01.propTypes = { + base: PT.string, +}; diff --git a/src/shared/routes/Communities/TCO01/index.jsx b/src/shared/routes/Communities/TCO01/index.jsx new file mode 100644 index 0000000000..ca7c6cfbf2 --- /dev/null +++ b/src/shared/routes/Communities/TCO01/index.jsx @@ -0,0 +1,32 @@ +/** + * Loader for the community's code chunks. + */ + +import LoadingIndicator from 'components/LoadingIndicator'; +import path from 'path'; +import PT from 'prop-types'; +import React from 'react'; +import { AppChunk, webpack } from 'topcoder-react-utils'; + +export default function ChunkLoader({ base, meta }) { + return ( + import(/* webpackChunkName: "tco01-community/chunk" */ './Routes') + .then(({ default: Routes }) => ( + + )) + } + renderPlaceholder={() => } + renderServer={() => { + const Routes = webpack.requireWeak(path.resolve(__dirname, './Routes')); + return ; + }} + /> + ); +} + +ChunkLoader.propTypes = { + base: PT.string.isRequired, + meta: PT.shape().isRequired, +}; diff --git a/src/shared/routes/Communities/TCO02/Routes.jsx b/src/shared/routes/Communities/TCO02/Routes.jsx new file mode 100644 index 0000000000..53a3e5aa05 --- /dev/null +++ b/src/shared/routes/Communities/TCO02/Routes.jsx @@ -0,0 +1,48 @@ +/** + * Routing of TCO02 Community. + */ + +import ContentfulRoute from 'components/Contentful/Route'; +import Error404 from 'components/Error404'; +import Header from 'containers/tc-communities/Header'; +import PT from 'prop-types'; +import React from 'react'; +import { Route, Switch } from 'react-router-dom'; + +import headerTheme from 'components/tc-communities/communities/tco/themes/header.scss'; + +export default function TCO02({ base }) { + return ( + ( +
    +
    + + } + id="2FYBo8o2bOOCbqSWuYcX1u" + /> + + +
    + )} + path={`${base}/:pageId?`} + /> + ); +} + +TCO02.defaultProps = { + base: '', +}; + +TCO02.propTypes = { + base: PT.string, +}; diff --git a/src/shared/routes/Communities/TCO02/index.jsx b/src/shared/routes/Communities/TCO02/index.jsx new file mode 100644 index 0000000000..76141a292a --- /dev/null +++ b/src/shared/routes/Communities/TCO02/index.jsx @@ -0,0 +1,32 @@ +/** + * Loader for the community's code chunks. + */ + +import LoadingIndicator from 'components/LoadingIndicator'; +import path from 'path'; +import PT from 'prop-types'; +import React from 'react'; +import { AppChunk, webpack } from 'topcoder-react-utils'; + +export default function ChunkLoader({ base, meta }) { + return ( + import(/* webpackChunkName: "tco02-community/chunk" */ './Routes') + .then(({ default: Routes }) => ( + + )) + } + renderPlaceholder={() => } + renderServer={() => { + const Routes = webpack.requireWeak(path.resolve(__dirname, './Routes')); + return ; + }} + /> + ); +} + +ChunkLoader.propTypes = { + base: PT.string.isRequired, + meta: PT.shape().isRequired, +}; diff --git a/src/shared/routes/Communities/TCO03/Routes.jsx b/src/shared/routes/Communities/TCO03/Routes.jsx new file mode 100644 index 0000000000..c31dc5b5d7 --- /dev/null +++ b/src/shared/routes/Communities/TCO03/Routes.jsx @@ -0,0 +1,48 @@ +/** + * Routing of TCO03 Community. + */ + +import ContentfulRoute from 'components/Contentful/Route'; +import Error404 from 'components/Error404'; +import Header from 'containers/tc-communities/Header'; +import PT from 'prop-types'; +import React from 'react'; +import { Route, Switch } from 'react-router-dom'; + +import headerTheme from 'components/tc-communities/communities/tco/themes/header.scss'; + +export default function TCO03({ base }) { + return ( + ( +
    +
    + + } + id="4mKZxfgAi6Us6dRS4Hy2Ab" + /> + + +
    + )} + path={`${base}/:pageId?`} + /> + ); +} + +TCO03.defaultProps = { + base: '', +}; + +TCO03.propTypes = { + base: PT.string, +}; diff --git a/src/shared/routes/Communities/TCO03/index.jsx b/src/shared/routes/Communities/TCO03/index.jsx new file mode 100644 index 0000000000..67757632d6 --- /dev/null +++ b/src/shared/routes/Communities/TCO03/index.jsx @@ -0,0 +1,32 @@ +/** + * Loader for the community's code chunks. + */ + +import LoadingIndicator from 'components/LoadingIndicator'; +import path from 'path'; +import PT from 'prop-types'; +import React from 'react'; +import { AppChunk, webpack } from 'topcoder-react-utils'; + +export default function ChunkLoader({ base, meta }) { + return ( + import(/* webpackChunkName: "tco03-community/chunk" */ './Routes') + .then(({ default: Routes }) => ( + + )) + } + renderPlaceholder={() => } + renderServer={() => { + const Routes = webpack.requireWeak(path.resolve(__dirname, './Routes')); + return ; + }} + /> + ); +} + +ChunkLoader.propTypes = { + base: PT.string.isRequired, + meta: PT.shape().isRequired, +}; diff --git a/src/shared/routes/Communities/TCO04/Routes.jsx b/src/shared/routes/Communities/TCO04/Routes.jsx new file mode 100644 index 0000000000..304c885a62 --- /dev/null +++ b/src/shared/routes/Communities/TCO04/Routes.jsx @@ -0,0 +1,48 @@ +/** + * Routing of TCO04 Community. + */ + +import ContentfulRoute from 'components/Contentful/Route'; +import Error404 from 'components/Error404'; +import Header from 'containers/tc-communities/Header'; +import PT from 'prop-types'; +import React from 'react'; +import { Route, Switch } from 'react-router-dom'; + +import headerTheme from 'components/tc-communities/communities/tco/themes/header.scss'; + +export default function TCO04({ base }) { + return ( + ( +
    +
    + + } + id="3Qua3zCM6DjLVmwlH8LSMA" + /> + + +
    + )} + path={`${base}/:pageId?`} + /> + ); +} + +TCO04.defaultProps = { + base: '', +}; + +TCO04.propTypes = { + base: PT.string, +}; diff --git a/src/shared/routes/Communities/TCO04/index.jsx b/src/shared/routes/Communities/TCO04/index.jsx new file mode 100644 index 0000000000..73d386667c --- /dev/null +++ b/src/shared/routes/Communities/TCO04/index.jsx @@ -0,0 +1,32 @@ +/** + * Loader for the community's code chunks. + */ + +import LoadingIndicator from 'components/LoadingIndicator'; +import path from 'path'; +import PT from 'prop-types'; +import React from 'react'; +import { AppChunk, webpack } from 'topcoder-react-utils'; + +export default function ChunkLoader({ base, meta }) { + return ( + import(/* webpackChunkName: "tco04-community/chunk" */ './Routes') + .then(({ default: Routes }) => ( + + )) + } + renderPlaceholder={() => } + renderServer={() => { + const Routes = webpack.requireWeak(path.resolve(__dirname, './Routes')); + return ; + }} + /> + ); +} + +ChunkLoader.propTypes = { + base: PT.string.isRequired, + meta: PT.shape().isRequired, +}; diff --git a/src/shared/routes/Communities/TCO05/Routes.jsx b/src/shared/routes/Communities/TCO05/Routes.jsx new file mode 100644 index 0000000000..c4ff510be5 --- /dev/null +++ b/src/shared/routes/Communities/TCO05/Routes.jsx @@ -0,0 +1,48 @@ +/** + * Routing of TCO05 Community. + */ + +import ContentfulRoute from 'components/Contentful/Route'; +import Error404 from 'components/Error404'; +import Header from 'containers/tc-communities/Header'; +import PT from 'prop-types'; +import React from 'react'; +import { Route, Switch } from 'react-router-dom'; + +import headerTheme from 'components/tc-communities/communities/tco/themes/header.scss'; + +export default function TCO05({ base }) { + return ( + ( +
    +
    + + } + id="kvig81sweT2PYI4iIwP7B" + /> + + +
    + )} + path={`${base}/:pageId?`} + /> + ); +} + +TCO05.defaultProps = { + base: '', +}; + +TCO05.propTypes = { + base: PT.string, +}; diff --git a/src/shared/routes/Communities/TCO05/index.jsx b/src/shared/routes/Communities/TCO05/index.jsx new file mode 100644 index 0000000000..318d7d8788 --- /dev/null +++ b/src/shared/routes/Communities/TCO05/index.jsx @@ -0,0 +1,32 @@ +/** + * Loader for the community's code chunks. + */ + +import LoadingIndicator from 'components/LoadingIndicator'; +import path from 'path'; +import PT from 'prop-types'; +import React from 'react'; +import { AppChunk, webpack } from 'topcoder-react-utils'; + +export default function ChunkLoader({ base, meta }) { + return ( + import(/* webpackChunkName: "tco05-community/chunk" */ './Routes') + .then(({ default: Routes }) => ( + + )) + } + renderPlaceholder={() => } + renderServer={() => { + const Routes = webpack.requireWeak(path.resolve(__dirname, './Routes')); + return ; + }} + /> + ); +} + +ChunkLoader.propTypes = { + base: PT.string.isRequired, + meta: PT.shape().isRequired, +}; diff --git a/src/shared/routes/Communities/TCO06/Routes.jsx b/src/shared/routes/Communities/TCO06/Routes.jsx new file mode 100644 index 0000000000..528f49e61c --- /dev/null +++ b/src/shared/routes/Communities/TCO06/Routes.jsx @@ -0,0 +1,48 @@ +/** + * Routing of TCO06 Community. + */ + +import ContentfulRoute from 'components/Contentful/Route'; +import Error404 from 'components/Error404'; +import Header from 'containers/tc-communities/Header'; +import PT from 'prop-types'; +import React from 'react'; +import { Route, Switch } from 'react-router-dom'; + +import headerTheme from 'components/tc-communities/communities/tco/themes/header.scss'; + +export default function TCO06({ base }) { + return ( + ( +
    +
    + + } + id="4VDa1nH6C3aNAlhqXI6tBe" + /> + + +
    + )} + path={`${base}/:pageId?`} + /> + ); +} + +TCO06.defaultProps = { + base: '', +}; + +TCO06.propTypes = { + base: PT.string, +}; diff --git a/src/shared/routes/Communities/TCO06/index.jsx b/src/shared/routes/Communities/TCO06/index.jsx new file mode 100644 index 0000000000..0fc5164e76 --- /dev/null +++ b/src/shared/routes/Communities/TCO06/index.jsx @@ -0,0 +1,32 @@ +/** + * Loader for the community's code chunks. + */ + +import LoadingIndicator from 'components/LoadingIndicator'; +import path from 'path'; +import PT from 'prop-types'; +import React from 'react'; +import { AppChunk, webpack } from 'topcoder-react-utils'; + +export default function ChunkLoader({ base, meta }) { + return ( + import(/* webpackChunkName: "tco06-community/chunk" */ './Routes') + .then(({ default: Routes }) => ( + + )) + } + renderPlaceholder={() => } + renderServer={() => { + const Routes = webpack.requireWeak(path.resolve(__dirname, './Routes')); + return ; + }} + /> + ); +} + +ChunkLoader.propTypes = { + base: PT.string.isRequired, + meta: PT.shape().isRequired, +}; diff --git a/src/shared/routes/Communities/TCO07/Routes.jsx b/src/shared/routes/Communities/TCO07/Routes.jsx new file mode 100644 index 0000000000..6636d64233 --- /dev/null +++ b/src/shared/routes/Communities/TCO07/Routes.jsx @@ -0,0 +1,48 @@ +/** + * Routing of TCO07 Community. + */ + +import ContentfulRoute from 'components/Contentful/Route'; +import Error404 from 'components/Error404'; +import Header from 'containers/tc-communities/Header'; +import PT from 'prop-types'; +import React from 'react'; +import { Route, Switch } from 'react-router-dom'; + +import headerTheme from 'components/tc-communities/communities/tco/themes/header.scss'; + +export default function TCO07({ base }) { + return ( + ( +
    +
    + + } + id="2XWcxVALvInOlAOfROErKS" + /> + + +
    + )} + path={`${base}/:pageId?`} + /> + ); +} + +TCO07.defaultProps = { + base: '', +}; + +TCO07.propTypes = { + base: PT.string, +}; diff --git a/src/shared/routes/Communities/TCO07/index.jsx b/src/shared/routes/Communities/TCO07/index.jsx new file mode 100644 index 0000000000..403fe9c8fb --- /dev/null +++ b/src/shared/routes/Communities/TCO07/index.jsx @@ -0,0 +1,32 @@ +/** + * Loader for the community's code chunks. + */ + +import LoadingIndicator from 'components/LoadingIndicator'; +import path from 'path'; +import PT from 'prop-types'; +import React from 'react'; +import { AppChunk, webpack } from 'topcoder-react-utils'; + +export default function ChunkLoader({ base, meta }) { + return ( + import(/* webpackChunkName: "tco07-community/chunk" */ './Routes') + .then(({ default: Routes }) => ( + + )) + } + renderPlaceholder={() => } + renderServer={() => { + const Routes = webpack.requireWeak(path.resolve(__dirname, './Routes')); + return ; + }} + /> + ); +} + +ChunkLoader.propTypes = { + base: PT.string.isRequired, + meta: PT.shape().isRequired, +}; diff --git a/src/shared/routes/Communities/TCO08/Routes.jsx b/src/shared/routes/Communities/TCO08/Routes.jsx new file mode 100644 index 0000000000..4571266274 --- /dev/null +++ b/src/shared/routes/Communities/TCO08/Routes.jsx @@ -0,0 +1,48 @@ +/** + * Routing of TCO08 Community. + */ + +import ContentfulRoute from 'components/Contentful/Route'; +import Error404 from 'components/Error404'; +import Header from 'containers/tc-communities/Header'; +import PT from 'prop-types'; +import React from 'react'; +import { Route, Switch } from 'react-router-dom'; + +import headerTheme from 'components/tc-communities/communities/tco/themes/header.scss'; + +export default function TCO08({ base }) { + return ( + ( +
    +
    + + } + id="6e1kgev8X8GSHEcDDiKrVD" + /> + + +
    + )} + path={`${base}/:pageId?`} + /> + ); +} + +TCO08.defaultProps = { + base: '', +}; + +TCO08.propTypes = { + base: PT.string, +}; diff --git a/src/shared/routes/Communities/TCO08/index.jsx b/src/shared/routes/Communities/TCO08/index.jsx new file mode 100644 index 0000000000..783d779240 --- /dev/null +++ b/src/shared/routes/Communities/TCO08/index.jsx @@ -0,0 +1,32 @@ +/** + * Loader for the community's code chunks. + */ + +import LoadingIndicator from 'components/LoadingIndicator'; +import path from 'path'; +import PT from 'prop-types'; +import React from 'react'; +import { AppChunk, webpack } from 'topcoder-react-utils'; + +export default function ChunkLoader({ base, meta }) { + return ( + import(/* webpackChunkName: "tco08-community/chunk" */ './Routes') + .then(({ default: Routes }) => ( + + )) + } + renderPlaceholder={() => } + renderServer={() => { + const Routes = webpack.requireWeak(path.resolve(__dirname, './Routes')); + return ; + }} + /> + ); +} + +ChunkLoader.propTypes = { + base: PT.string.isRequired, + meta: PT.shape().isRequired, +}; diff --git a/src/shared/routes/Communities/TCO09/Routes.jsx b/src/shared/routes/Communities/TCO09/Routes.jsx new file mode 100644 index 0000000000..c4b9392a2c --- /dev/null +++ b/src/shared/routes/Communities/TCO09/Routes.jsx @@ -0,0 +1,48 @@ +/** + * Routing of TCO09 Community. + */ + +import ContentfulRoute from 'components/Contentful/Route'; +import Error404 from 'components/Error404'; +import Header from 'containers/tc-communities/Header'; +import PT from 'prop-types'; +import React from 'react'; +import { Route, Switch } from 'react-router-dom'; + +import headerTheme from 'components/tc-communities/communities/tco/themes/header.scss'; + +export default function TCO09({ base }) { + return ( + ( +
    +
    + + } + id="1w99R7k46hAh3SwkRuFQiI" + /> + + +
    + )} + path={`${base}/:pageId?`} + /> + ); +} + +TCO09.defaultProps = { + base: '', +}; + +TCO09.propTypes = { + base: PT.string, +}; diff --git a/src/shared/routes/Communities/TCO09/index.jsx b/src/shared/routes/Communities/TCO09/index.jsx new file mode 100644 index 0000000000..767a64c576 --- /dev/null +++ b/src/shared/routes/Communities/TCO09/index.jsx @@ -0,0 +1,32 @@ +/** + * Loader for the community's code chunks. + */ + +import LoadingIndicator from 'components/LoadingIndicator'; +import path from 'path'; +import PT from 'prop-types'; +import React from 'react'; +import { AppChunk, webpack } from 'topcoder-react-utils'; + +export default function ChunkLoader({ base, meta }) { + return ( + import(/* webpackChunkName: "tco09-community/chunk" */ './Routes') + .then(({ default: Routes }) => ( + + )) + } + renderPlaceholder={() => } + renderServer={() => { + const Routes = webpack.requireWeak(path.resolve(__dirname, './Routes')); + return ; + }} + /> + ); +} + +ChunkLoader.propTypes = { + base: PT.string.isRequired, + meta: PT.shape().isRequired, +}; diff --git a/src/shared/routes/Communities/TCO10/Routes.jsx b/src/shared/routes/Communities/TCO10/Routes.jsx new file mode 100644 index 0000000000..d339b8e989 --- /dev/null +++ b/src/shared/routes/Communities/TCO10/Routes.jsx @@ -0,0 +1,48 @@ +/** + * Routing of TCO10 Community. + */ + +import ContentfulRoute from 'components/Contentful/Route'; +import Error404 from 'components/Error404'; +import Header from 'containers/tc-communities/Header'; +import PT from 'prop-types'; +import React from 'react'; +import { Route, Switch } from 'react-router-dom'; + +import headerTheme from 'components/tc-communities/communities/tco/themes/header.scss'; + +export default function TCO10({ base }) { + return ( + ( +
    +
    + + } + id="2br5Pgqe2mPx5HG2DwmKhJ" + /> + + +
    + )} + path={`${base}/:pageId?`} + /> + ); +} + +TCO10.defaultProps = { + base: '', +}; + +TCO10.propTypes = { + base: PT.string, +}; diff --git a/src/shared/routes/Communities/TCO10/index.jsx b/src/shared/routes/Communities/TCO10/index.jsx new file mode 100644 index 0000000000..73001685d9 --- /dev/null +++ b/src/shared/routes/Communities/TCO10/index.jsx @@ -0,0 +1,32 @@ +/** + * Loader for the community's code chunks. + */ + +import LoadingIndicator from 'components/LoadingIndicator'; +import path from 'path'; +import PT from 'prop-types'; +import React from 'react'; +import { AppChunk, webpack } from 'topcoder-react-utils'; + +export default function ChunkLoader({ base, meta }) { + return ( + import(/* webpackChunkName: "tco10-community/chunk" */ './Routes') + .then(({ default: Routes }) => ( + + )) + } + renderPlaceholder={() => } + renderServer={() => { + const Routes = webpack.requireWeak(path.resolve(__dirname, './Routes')); + return ; + }} + /> + ); +} + +ChunkLoader.propTypes = { + base: PT.string.isRequired, + meta: PT.shape().isRequired, +}; diff --git a/src/shared/routes/Communities/TCO11/Routes.jsx b/src/shared/routes/Communities/TCO11/Routes.jsx new file mode 100644 index 0000000000..67d36218a9 --- /dev/null +++ b/src/shared/routes/Communities/TCO11/Routes.jsx @@ -0,0 +1,48 @@ +/** + * Routing of TCO11 Community. + */ + +import ContentfulRoute from 'components/Contentful/Route'; +import Error404 from 'components/Error404'; +import Header from 'containers/tc-communities/Header'; +import PT from 'prop-types'; +import React from 'react'; +import { Route, Switch } from 'react-router-dom'; + +import headerTheme from 'components/tc-communities/communities/tco/themes/header.scss'; + +export default function TCO11({ base }) { + return ( + ( +
    +
    + + } + id="3Inhu3CrJhVNnzNHsmevps" + /> + + +
    + )} + path={`${base}/:pageId?`} + /> + ); +} + +TCO11.defaultProps = { + base: '', +}; + +TCO11.propTypes = { + base: PT.string, +}; diff --git a/src/shared/routes/Communities/TCO11/index.jsx b/src/shared/routes/Communities/TCO11/index.jsx new file mode 100644 index 0000000000..cd102bd1b5 --- /dev/null +++ b/src/shared/routes/Communities/TCO11/index.jsx @@ -0,0 +1,32 @@ +/** + * Loader for the community's code chunks. + */ + +import LoadingIndicator from 'components/LoadingIndicator'; +import path from 'path'; +import PT from 'prop-types'; +import React from 'react'; +import { AppChunk, webpack } from 'topcoder-react-utils'; + +export default function ChunkLoader({ base, meta }) { + return ( + import(/* webpackChunkName: "tco11-community/chunk" */ './Routes') + .then(({ default: Routes }) => ( + + )) + } + renderPlaceholder={() => } + renderServer={() => { + const Routes = webpack.requireWeak(path.resolve(__dirname, './Routes')); + return ; + }} + /> + ); +} + +ChunkLoader.propTypes = { + base: PT.string.isRequired, + meta: PT.shape().isRequired, +}; diff --git a/src/shared/routes/Communities/TCO12/Routes.jsx b/src/shared/routes/Communities/TCO12/Routes.jsx new file mode 100644 index 0000000000..7f676a8569 --- /dev/null +++ b/src/shared/routes/Communities/TCO12/Routes.jsx @@ -0,0 +1,48 @@ +/** + * Routing of TCO12 Community. + */ + +import ContentfulRoute from 'components/Contentful/Route'; +import Error404 from 'components/Error404'; +import Header from 'containers/tc-communities/Header'; +import PT from 'prop-types'; +import React from 'react'; +import { Route, Switch } from 'react-router-dom'; + +import headerTheme from 'components/tc-communities/communities/tco/themes/header.scss'; + +export default function TCO12({ base }) { + return ( + ( +
    +
    + + } + id="ajoVqIOPhPSSXfCA7kt3N" + /> + + +
    + )} + path={`${base}/:pageId?`} + /> + ); +} + +TCO12.defaultProps = { + base: '', +}; + +TCO12.propTypes = { + base: PT.string, +}; diff --git a/src/shared/routes/Communities/TCO12/index.jsx b/src/shared/routes/Communities/TCO12/index.jsx new file mode 100644 index 0000000000..83dfed1509 --- /dev/null +++ b/src/shared/routes/Communities/TCO12/index.jsx @@ -0,0 +1,32 @@ +/** + * Loader for the community's code chunks. + */ + +import LoadingIndicator from 'components/LoadingIndicator'; +import path from 'path'; +import PT from 'prop-types'; +import React from 'react'; +import { AppChunk, webpack } from 'topcoder-react-utils'; + +export default function ChunkLoader({ base, meta }) { + return ( + import(/* webpackChunkName: "tco12-community/chunk" */ './Routes') + .then(({ default: Routes }) => ( + + )) + } + renderPlaceholder={() => } + renderServer={() => { + const Routes = webpack.requireWeak(path.resolve(__dirname, './Routes')); + return ; + }} + /> + ); +} + +ChunkLoader.propTypes = { + base: PT.string.isRequired, + meta: PT.shape().isRequired, +}; diff --git a/src/shared/routes/Communities/TCO13/Routes.jsx b/src/shared/routes/Communities/TCO13/Routes.jsx new file mode 100644 index 0000000000..ee13fbd710 --- /dev/null +++ b/src/shared/routes/Communities/TCO13/Routes.jsx @@ -0,0 +1,48 @@ +/** + * Routing of TCO13 Community. + */ + +import ContentfulRoute from 'components/Contentful/Route'; +import Error404 from 'components/Error404'; +import Header from 'containers/tc-communities/Header'; +import PT from 'prop-types'; +import React from 'react'; +import { Route, Switch } from 'react-router-dom'; + +import headerTheme from 'components/tc-communities/communities/tco/themes/header.scss'; + +export default function TCO13({ base }) { + return ( + ( +
    +
    + + } + id="2O131soNK7FqORBFRMfcqu" + /> + + +
    + )} + path={`${base}/:pageId?`} + /> + ); +} + +TCO13.defaultProps = { + base: '', +}; + +TCO13.propTypes = { + base: PT.string, +}; diff --git a/src/shared/routes/Communities/TCO13/index.jsx b/src/shared/routes/Communities/TCO13/index.jsx new file mode 100644 index 0000000000..f8d1d5cea8 --- /dev/null +++ b/src/shared/routes/Communities/TCO13/index.jsx @@ -0,0 +1,32 @@ +/** + * Loader for the community's code chunks. + */ + +import LoadingIndicator from 'components/LoadingIndicator'; +import path from 'path'; +import PT from 'prop-types'; +import React from 'react'; +import { AppChunk, webpack } from 'topcoder-react-utils'; + +export default function ChunkLoader({ base, meta }) { + return ( + import(/* webpackChunkName: "tco13-community/chunk" */ './Routes') + .then(({ default: Routes }) => ( + + )) + } + renderPlaceholder={() => } + renderServer={() => { + const Routes = webpack.requireWeak(path.resolve(__dirname, './Routes')); + return ; + }} + /> + ); +} + +ChunkLoader.propTypes = { + base: PT.string.isRequired, + meta: PT.shape().isRequired, +}; diff --git a/src/shared/routes/Communities/TCO14/Routes.jsx b/src/shared/routes/Communities/TCO14/Routes.jsx new file mode 100644 index 0000000000..b55721221e --- /dev/null +++ b/src/shared/routes/Communities/TCO14/Routes.jsx @@ -0,0 +1,48 @@ +/** + * Routing of TCO14 Community. + */ + +import ContentfulRoute from 'components/Contentful/Route'; +import Error404 from 'components/Error404'; +import Header from 'containers/tc-communities/Header'; +import PT from 'prop-types'; +import React from 'react'; +import { Route, Switch } from 'react-router-dom'; + +import headerTheme from 'components/tc-communities/communities/tco/themes/header.scss'; + +export default function TCO14({ base }) { + return ( + ( +
    +
    + + } + id="4H8E3xUu9egGuEWAp0mj7Q" + /> + + +
    + )} + path={`${base}/:pageId?`} + /> + ); +} + +TCO14.defaultProps = { + base: '', +}; + +TCO14.propTypes = { + base: PT.string, +}; diff --git a/src/shared/routes/Communities/TCO14/index.jsx b/src/shared/routes/Communities/TCO14/index.jsx new file mode 100644 index 0000000000..5270617e6d --- /dev/null +++ b/src/shared/routes/Communities/TCO14/index.jsx @@ -0,0 +1,32 @@ +/** + * Loader for the community's code chunks. + */ + +import LoadingIndicator from 'components/LoadingIndicator'; +import path from 'path'; +import PT from 'prop-types'; +import React from 'react'; +import { AppChunk, webpack } from 'topcoder-react-utils'; + +export default function ChunkLoader({ base, meta }) { + return ( + import(/* webpackChunkName: "tco14-community/chunk" */ './Routes') + .then(({ default: Routes }) => ( + + )) + } + renderPlaceholder={() => } + renderServer={() => { + const Routes = webpack.requireWeak(path.resolve(__dirname, './Routes')); + return ; + }} + /> + ); +} + +ChunkLoader.propTypes = { + base: PT.string.isRequired, + meta: PT.shape().isRequired, +}; diff --git a/src/shared/routes/Communities/TCO15/Routes.jsx b/src/shared/routes/Communities/TCO15/Routes.jsx new file mode 100644 index 0000000000..7ec8acc9d0 --- /dev/null +++ b/src/shared/routes/Communities/TCO15/Routes.jsx @@ -0,0 +1,48 @@ +/** + * Routing of TCO15 Community. + */ + +import ContentfulRoute from 'components/Contentful/Route'; +import Error404 from 'components/Error404'; +import Header from 'containers/tc-communities/Header'; +import PT from 'prop-types'; +import React from 'react'; +import { Route, Switch } from 'react-router-dom'; + +import headerTheme from 'components/tc-communities/communities/tco/themes/header.scss'; + +export default function TCO15({ base }) { + return ( + ( +
    +
    + + } + id="1wjcHvy0CC9B4N4KeLsDJ0" + /> + + +
    + )} + path={`${base}/:pageId?`} + /> + ); +} + +TCO15.defaultProps = { + base: '', +}; + +TCO15.propTypes = { + base: PT.string, +}; diff --git a/src/shared/routes/Communities/TCO15/index.jsx b/src/shared/routes/Communities/TCO15/index.jsx new file mode 100644 index 0000000000..ad4e04191e --- /dev/null +++ b/src/shared/routes/Communities/TCO15/index.jsx @@ -0,0 +1,32 @@ +/** + * Loader for the community's code chunks. + */ + +import LoadingIndicator from 'components/LoadingIndicator'; +import path from 'path'; +import PT from 'prop-types'; +import React from 'react'; +import { AppChunk, webpack } from 'topcoder-react-utils'; + +export default function ChunkLoader({ base, meta }) { + return ( + import(/* webpackChunkName: "tco15-community/chunk" */ './Routes') + .then(({ default: Routes }) => ( + + )) + } + renderPlaceholder={() => } + renderServer={() => { + const Routes = webpack.requireWeak(path.resolve(__dirname, './Routes')); + return ; + }} + /> + ); +} + +ChunkLoader.propTypes = { + base: PT.string.isRequired, + meta: PT.shape().isRequired, +}; diff --git a/src/shared/routes/Communities/TCO16/Routes.jsx b/src/shared/routes/Communities/TCO16/Routes.jsx new file mode 100644 index 0000000000..039fbbea06 --- /dev/null +++ b/src/shared/routes/Communities/TCO16/Routes.jsx @@ -0,0 +1,48 @@ +/** + * Routing of TCO16 Community. + */ + +import ContentfulRoute from 'components/Contentful/Route'; +import Error404 from 'components/Error404'; +import Header from 'containers/tc-communities/Header'; +import PT from 'prop-types'; +import React from 'react'; +import { Route, Switch } from 'react-router-dom'; + +import headerTheme from 'components/tc-communities/communities/tco/themes/header.scss'; + +export default function TCO16({ base }) { + return ( + ( +
    +
    + + } + id="6jQnnCtlJUr7p6lOzaHwNg" + /> + + +
    + )} + path={`${base}/:pageId?`} + /> + ); +} + +TCO16.defaultProps = { + base: '', +}; + +TCO16.propTypes = { + base: PT.string, +}; diff --git a/src/shared/routes/Communities/TCO16/index.jsx b/src/shared/routes/Communities/TCO16/index.jsx new file mode 100644 index 0000000000..edb8b59591 --- /dev/null +++ b/src/shared/routes/Communities/TCO16/index.jsx @@ -0,0 +1,32 @@ +/** + * Loader for the community's code chunks. + */ + +import LoadingIndicator from 'components/LoadingIndicator'; +import path from 'path'; +import PT from 'prop-types'; +import React from 'react'; +import { AppChunk, webpack } from 'topcoder-react-utils'; + +export default function ChunkLoader({ base, meta }) { + return ( + import(/* webpackChunkName: "tco16-community/chunk" */ './Routes') + .then(({ default: Routes }) => ( + + )) + } + renderPlaceholder={() => } + renderServer={() => { + const Routes = webpack.requireWeak(path.resolve(__dirname, './Routes')); + return ; + }} + /> + ); +} + +ChunkLoader.propTypes = { + base: PT.string.isRequired, + meta: PT.shape().isRequired, +}; diff --git a/src/shared/routes/Communities/TCO19/Routes.jsx b/src/shared/routes/Communities/TCO19/Routes.jsx index 70acff60f6..df59b48930 100644 --- a/src/shared/routes/Communities/TCO19/Routes.jsx +++ b/src/shared/routes/Communities/TCO19/Routes.jsx @@ -5,7 +5,6 @@ import _ from 'lodash'; import Error404 from 'components/Error404'; import Header from 'containers/tc-communities/Header'; -import Home from 'containers/tc-communities/tco19/Home'; import PT from 'prop-types'; import React from 'react'; import { Route, Switch } from 'react-router-dom'; @@ -13,6 +12,7 @@ import Viewport from 'components/Contentful/Viewport'; import ContentfulLoader from 'containers/ContentfulLoader'; import Blog from 'components/Contentful/Blog'; import { HeroImageLoader } from 'components/Contentful/BlogPost'; +import ContentfulRoute from 'components/Contentful/Route'; import headerTheme from 'components/tc-communities/communities/tco19/themes/header.scss'; @@ -67,38 +67,10 @@ export default function TCO19({ base }) { ); }} /> - { - const mId = p.match.params.menuItems.split('/'); - const query = { - content_type: 'navigationMenuItem', - 'fields.slug': mId[mId.length - 1], - }; - return ( - { - const menuItem = _.values(data.entries.items)[0]; - if (!menuItem) return Error404(); - - return ( - - ); - }} - /> - ); - }} - path={`${base}/:menuItems+`} - /> - } - exact - path={`${base}`} - /> - } - exact - path={`${base}/home`} + } + id="6kF6iiWGmhM6EHH8j7Kee7" /> _.camelCase(key)) : undefined; } +// Concatenates a base and segment and handles optional trailing slashes +const buildUrl = (base, segment) => `${_.trimEnd(base, '/')}/${_.trim(segment, '/')}`; + +/** + * Checks if URL is absolute + * @param {String} url + */ +function isAbsolute(url) { + return url.startsWith('http:') || url.startsWith('https:'); +} + +/** + * Builds target url for menu link + * @param {String} baseUrl + * @param {String} item + */ +export function target(baseUrl, item) { + // use/prefer url if available + let to = ''; + if (item.fields.url) { + // for Routes or NavigationMenuItem entries with a non-empty url field + to = isAbsolute(item.fields.url) ? item.fields.url : buildUrl(baseUrl, item.fields.url); + } else if (item.fields.slug) { + // for NavigationMenuItem entries without an URL field + // menu item slug to build the url + to = buildUrl(baseUrl, item.fields.slug); + } else { + // for Routes with no url + to = baseUrl; + } + return to; +} + +/** + * Checks if menu link is active + * @param {String} baseUrl + * @param {String} item + */ +export function isActive(baseUrl, item, caller) { + let to = removeTrailingSlash(target(baseUrl, item)); + to = to ? to.toLowerCase() : to; + + let location; + if (isomorphy.isClientSide()) { + location = isAbsolute(to) ? buildUrl(window.location.origin, window.location.pathname) + : window.location.pathname; + location = location.toLowerCase(); + } else { + // TODO: should probably get the current URL from the web framework + return false; + } + + // handles the special case when url === `/` + if (caller === 'menuItem' + && to === baseUrl + && (location !== to && location !== `${to}/`)) { + return false; + } + + // check if the current location is the link target or a subdirectory + return location && (location === to || location.startsWith(`${to}/`)); +} + +/** + * Picks the text for menu links + * @param {Object} item + */ +export function linkText(item) { + return item.fields.naviMenuLinkText /* Route-only */ + || item.fields.linkText /* NavigationMenuItem-only */ || item.fields.name; +} + export default undefined;