diff --git a/.circleci/config.yml b/.circleci/config.yml index 2540011007..fbe4c60282 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -231,13 +231,13 @@ workflows: branches: only: - develop + - tco21 # This is alternate dev env for parallel testing - "build-test": context : org-global filters: branches: - only: - - develop + only: - feature-contentful # This is alternate dev env for parallel testing - "build-qa": @@ -245,7 +245,7 @@ workflows: filters: branches: only: - - develop-on-qa-env + - develop # This is beta env for production soft releases - "build-prod-beta": context : org-global diff --git a/src/server/tc-communities/tco21/metadata.json b/src/server/tc-communities/tco21/metadata.json new file mode 100644 index 0000000000..fa22f3f373 --- /dev/null +++ b/src/server/tc-communities/tco21/metadata.json @@ -0,0 +1,20 @@ +{ + "challengeFilter": { + "tags": ["TCO", "TCO21"] + }, + "communityId": "tco21", + "communityName": "TCO21", + "groupIds": [], + "hideSearch": true, + "logos": [{ + "img": "/community-app-assets/themes/tco/TCO21.svg", + "url": "https://tco21.topcoder.com" + }], + "menuItems": [{ + "navigationMenu": "3UBKZJ0qMHAkqrobue73NB" + }], + "newsFeed": "http://www.topcoder.com/feed", + "subdomains": ["tco21"], + "description": "2021 Topcoder Open. The Ultimate Programming & Design Tournament", + "image": "tco21.jpg" +} diff --git a/src/shared/actions/contentful.js b/src/shared/actions/contentful.js index 2c8f9c3547..dd17409407 100644 --- a/src/shared/actions/contentful.js +++ b/src/shared/actions/contentful.js @@ -181,12 +181,13 @@ async function getMenuDone(menuProps) { cR2.fields.childRoutes, cR3 => service.getEntry(cR3.sys.id).then( async (c3) => { - const sI3 = menuItemBuilder(url2, c3); + const url3 = urlTarget(url2, cR2); + const sI3 = menuItemBuilder(url3, c3); if (c3.fields.childRoutes) { sI3.subMenu = await Promise.all(_.map( c3.fields.childRoutes, cR4 => service.getEntry(cR4.sys.id).then( - c4 => menuItemBuilder(urlTarget(url2, c3), c4), + c4 => menuItemBuilder(url3, c4), ), )); } @@ -239,9 +240,10 @@ async function getMenuDone(menuProps) { } else { menu = menuData; } - // add the preconfigured secondary menus - menu[0].secondaryMenuForLoggedInUser = config.SECONDARY_MENU_FOR_LOGGED_USER; - menu[0].secondaryMenuForGuest = config.SECONDARY_MENU_FOR_GUEST; + // add the preconfigured secondary menus? + if (fields.showSecondaryNaviMenu) { + menu[0].secondaryMenu = config.HEADER_MENU[1].secondaryMenu; + } return { id: menuProps.id, diff --git a/src/shared/components/Contentful/ContentBlock/themes/TCO19.scss b/src/shared/components/Contentful/ContentBlock/themes/TCO19.scss index 6d1dba8192..6dd6d736f7 100644 --- a/src/shared/components/Contentful/ContentBlock/themes/TCO19.scss +++ b/src/shared/components/Contentful/ContentBlock/themes/TCO19.scss @@ -78,13 +78,13 @@ strong a { th { @include roboto-regular; - color: #808080; + color: #2a2a2a; font-size: 15px; font-weight: bold; - line-height: 25px; + line-height: 18px; text-align: left; text-transform: uppercase; - padding: 7px 10px 7px 0; + padding: 18px 10px 14px 0; @include md-to-xl { white-space: nowrap; @@ -102,8 +102,8 @@ strong a { line-height: 25px; text-align: left; color: $tc-gray-80; - border-top: 1px solid #ededf2; - border-bottom: 1px solid #ededf2; + border-top: 1px solid #d4d4d4; + border-bottom: 1px solid #d4d4d4; padding: 20px 50px 20px 0; min-height: 51px; diff --git a/src/shared/components/Contentful/ContentBlock/themes/TCO20.scss b/src/shared/components/Contentful/ContentBlock/themes/TCO20.scss index 7dca7a7556..e6b4a5a3e7 100644 --- a/src/shared/components/Contentful/ContentBlock/themes/TCO20.scss +++ b/src/shared/components/Contentful/ContentBlock/themes/TCO20.scss @@ -94,13 +94,13 @@ strong a { th { @include roboto-regular; - color: #808080; + color: #2a2a2a; font-size: 15px; font-weight: bold; - line-height: 25px; + line-height: 18px; text-align: left; text-transform: uppercase; - padding: 7px 10px 7px 0; + padding: 18px 10px 14px 0; @include md-to-xl { white-space: nowrap; @@ -118,8 +118,8 @@ strong a { line-height: 25px; text-align: left; color: $tc-gray-80; - border-top: 1px solid #ededf2; - border-bottom: 1px solid #ededf2; + border-top: 1px solid #d4d4d4; + border-bottom: 1px solid #d4d4d4; padding: 20px 50px 20px 0; min-height: 51px; diff --git a/src/shared/components/Contentful/ContentBlock/themes/general.scss b/src/shared/components/Contentful/ContentBlock/themes/general.scss index ad01f09abc..195069213b 100644 --- a/src/shared/components/Contentful/ContentBlock/themes/general.scss +++ b/src/shared/components/Contentful/ContentBlock/themes/general.scss @@ -122,13 +122,13 @@ strong a { th { @include roboto-regular; - color: #808080; + color: #2a2a2a; font-size: 15px; font-weight: bold; - line-height: 25px; + line-height: 18px; text-align: left; text-transform: uppercase; - padding: 7px 10px 7px 0; + padding: 18px 10px 14px 0; @include md-to-xl { white-space: nowrap; @@ -146,8 +146,8 @@ strong a { line-height: 25px; text-align: left; color: $tc-gray-80; - border-top: 1px solid #ededf2; - border-bottom: 1px solid #ededf2; + border-top: 1px solid #d4d4d4; + border-bottom: 1px solid #d4d4d4; padding: 20px 50px 20px 0; min-height: 51px; diff --git a/src/shared/components/Contentful/Countdown/index.jsx b/src/shared/components/Contentful/Countdown/index.jsx index 0ff5447e93..67ccb5b868 100644 --- a/src/shared/components/Contentful/Countdown/index.jsx +++ b/src/shared/components/Contentful/Countdown/index.jsx @@ -25,6 +25,7 @@ export default function CountdownLoader(props) { title={data.entries.items[id].fields.title} end={new Date(data.entries.items[id].fields.endDate)} extraStylesForContainer={data.entries.items[id].fields.extraStylesForContainer} + themeName={data.entries.items[id].fields.theme} /> )} renderPlaceholder={LoadingIndicator} diff --git a/src/shared/components/Countdown/index.jsx b/src/shared/components/Countdown/index.jsx index 7fd2a42dc8..4cccc74494 100644 --- a/src/shared/components/Countdown/index.jsx +++ b/src/shared/components/Countdown/index.jsx @@ -8,7 +8,13 @@ import PT from 'prop-types'; import React from 'react'; import { fixStyle } from 'utils/contentful'; -import './style.scss'; +import defaultTheme from './themes/style.scss'; +import TCO21 from './themes/TCO21.scss'; + +const THEMES = { + Default: defaultTheme, + TCO21, +}; /* We have to use state component, as we need to manipulate with DOM nodes to * access nuka-carousel state. */ @@ -34,6 +40,8 @@ export default class Countdown extends React.Component { } render() { + const { themeName } = this.props; + const theme = THEMES[themeName]; let { elapsed } = this.state; const oneDay = 24 * 60 * 60; const oneHour = 60 * 60; @@ -54,27 +62,26 @@ export default class Countdown extends React.Component { ); return (
-
{title}
-
:
-
+
{title}
+
-
{day}
-
days
+
{day}
+
days
-
{hour}
-
hours
+
{hour}
+
hours
-
{minute}
-
minutes
+
{minute}
+
minutes
-
-
{second}
-
seconds
+
+
{second}
+
seconds
@@ -85,10 +92,12 @@ export default class Countdown extends React.Component { Countdown.defaultProps = { title: 'Countdown to TCO19 Final', extraStylesForContainer: {}, + themeName: 'Default', }; Countdown.propTypes = { title: PT.string, end: PT.instanceOf(Date).isRequired, extraStylesForContainer: PT.shape(), + themeName: PT.string, }; diff --git a/src/shared/components/Countdown/themes/TCO21.scss b/src/shared/components/Countdown/themes/TCO21.scss new file mode 100644 index 0000000000..01abb24ba4 --- /dev/null +++ b/src/shared/components/Countdown/themes/TCO21.scss @@ -0,0 +1,77 @@ +@import "~styles/mixins"; + +$text-color-gray: #37373b; +$container-background-yello: #fce217; + +.container { + @include roboto-regular; + + display: -webkit-flex; /* Safari */ + display: flex; + -webkit-flex-direction: row; /* Safari */ + flex-direction: row; + -webkit-justify-content: center; /* Safari */ + justify-content: center; + padding: 40px; + background: $container-background-yello; + + @media only screen and (max-width: 767px) { + -webkit-flex-direction: column; /* Safari */ + flex-direction: column; + } + + .title { + @include barlow-condensed-medium; + + color: #2a2a2a; + font-size: 48px; + line-height: 50px; + text-align: center; + margin: auto 41px auto 0; + text-transform: uppercase; + + @media only screen and (max-width: 767px) { + margin-bottom: 20px; + } + } + + .time-container { + display: -webkit-flex; /* Safari */ + display: flex; + -webkit-flex-direction: row; /* Safari */ + flex-direction: row; + -webkit-justify-content: center; /* Safari */ + justify-content: center; + } + + .time-value { + @include barlow-condensed; + + color: #9d41c9; + font-size: 80px; + line-height: 74px; + text-align: center; + } + + .time-label { + color: #2a2a2a; + font-size: 14px; + letter-spacing: 0.5px; + line-height: 18px; + text-align: center; + width: 100px; + text-transform: uppercase; + margin-top: 4px; + + @media only screen and (max-width: 767px) { + width: auto; + margin-left: 10px; + margin-right: 10px; + font-size: 18px; + } + } + + .time-second { + display: block; + } +} diff --git a/src/shared/components/Countdown/style.scss b/src/shared/components/Countdown/themes/style.scss similarity index 94% rename from src/shared/components/Countdown/style.scss rename to src/shared/components/Countdown/themes/style.scss index feec44e436..966b7500ee 100644 --- a/src/shared/components/Countdown/style.scss +++ b/src/shared/components/Countdown/themes/style.scss @@ -31,16 +31,8 @@ $container-background-yello: #fce217; margin-bottom: auto; text-transform: uppercase; - &.colon { - margin-right: 30px; - } - @media only screen and (max-width: 767px) { margin-bottom: 20px; - - &.colon { - display: none; - } } } diff --git a/src/shared/components/Leaderboard/LeaderboardTable/themes/tco20.scss b/src/shared/components/Leaderboard/LeaderboardTable/themes/tco20.scss index 9a787cf24f..fe4938c6b1 100644 --- a/src/shared/components/Leaderboard/LeaderboardTable/themes/tco20.scss +++ b/src/shared/components/Leaderboard/LeaderboardTable/themes/tco20.scss @@ -191,7 +191,7 @@ $table-bg-hover: #f5f5f5; .col-fulfillment, .col-challenges, .col-points { - color: #7f7f7f; + color: #2a2a2a; font-family: Roboto, sans-serif; font-size: 14px; font-weight: 500; diff --git a/src/shared/components/buttons/themed/tc.scss b/src/shared/components/buttons/themed/tc.scss index 265c60e689..b990bf4abc 100644 --- a/src/shared/components/buttons/themed/tc.scss +++ b/src/shared/components/buttons/themed/tc.scss @@ -6,6 +6,7 @@ font-weight: 700 !important; text-decoration: none !important; text-transform: uppercase !important; + margin: 0 !important; } @mixin primary-green { @@ -105,6 +106,7 @@ font-weight: 700 !important; text-decoration: none !important; text-transform: uppercase !important; + margin: 0 !important; } @mixin secondary-gray { @@ -130,6 +132,7 @@ font-weight: 700 !important; text-transform: uppercase !important; + margin: 0 !important; } @mixin warn-red { diff --git a/src/shared/containers/Contentful/MenuLoader/index.jsx b/src/shared/containers/Contentful/MenuLoader/index.jsx index 2132823f63..a8bb7b45d3 100644 --- a/src/shared/containers/Contentful/MenuLoader/index.jsx +++ b/src/shared/containers/Contentful/MenuLoader/index.jsx @@ -38,16 +38,19 @@ class MenuLoaderContainer extends React.Component { spaceName, environment, baseUrl, + menu, } = this.props; - // initiate loading the menu data - loadMenuData({ - id, - fields, - preview, - spaceName, - environment, - baseUrl, - }); + if (!menu.length) { + // initiate loading the menu data + loadMenuData({ + id, + fields, + preview, + spaceName, + environment, + baseUrl, + }); + } } handleChangeLevel1Id(menuId) { @@ -79,11 +82,6 @@ class MenuLoaderContainer extends React.Component { const { TopNav, LoginNav } = require('navigation-component'); const logoToUse = !_.isEmpty(menuLogo) ? menu logo : ; const menuTheme = fields.theme.split('- '); - const comboMenu = _.flatten(_.map(menu, menuItem => menuItem.subMenu)); - // This is a hack fix that should be removed when possible! - // Its orifing is in the https://github.com/topcoder-platform/navigation-component module - // which breaks if there is NOT an menu item with id = `community` - comboMenu[0].id = 'community'; let normalizedProfile = auth.profile && _.clone(auth.profile); if (auth.profile) { normalizedProfile.photoURL = (_.has(auth.profile, 'photoURL') && auth.profile.photoURL !== null) @@ -94,7 +92,7 @@ class MenuLoaderContainer extends React.Component { return (
+ { + meta.menuItems ? ( + + ) : null + } + + } + exact + path={`${base}/members/:handle([\\w\\-\\[\\].{}]{2,15})`} + /> + } + exact + path={`${base}/members/:handle([\\w\\-\\[\\].{}]{2,15})/details`} + /> + } + id="6wUJl6RRF6MxI3kR6DFq5t" + /> + +
+ ); +} + +TCO21.defaultProps = { + base: '', +}; + +TCO21.propTypes = { + base: PT.string, + meta: PT.shape().isRequired, +}; diff --git a/src/shared/routes/Communities/TCO21/index.jsx b/src/shared/routes/Communities/TCO21/index.jsx new file mode 100644 index 0000000000..a1880bb2c2 --- /dev/null +++ b/src/shared/routes/Communities/TCO21/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: "tco21-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/utils/contentful.js b/src/shared/utils/contentful.js index 17c7b5ff65..3c253aa36b 100644 --- a/src/shared/utils/contentful.js +++ b/src/shared/utils/contentful.js @@ -94,13 +94,13 @@ export function menuItemBuilder(baseUrl, item) { case 'route': return { title: item.fields.naviMenuLinkText || item.fields.name, - href: target(baseUrl, item), + href: item.fields.viewport ? target(baseUrl, item) : null, id: item.sys.id, }; case 'navigationMenuItem': return { title: item.fields.linkText || item.fields.name, - href: target(baseUrl, item), + href: item.fields.viewport ? target(baseUrl, item) : null, id: item.sys.id, }; default: return {};