diff --git a/.circleci/config.yml b/.circleci/config.yml index ea2e339f75..62b48152fc 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -356,7 +356,7 @@ workflows: filters: branches: only: - - debug-CMS-error + - tco23 # This is alternate dev env for parallel testing - "build-qa": context : org-global diff --git a/src/server/index.js b/src/server/index.js index 9996ce180f..70590aa8b8 100644 --- a/src/server/index.js +++ b/src/server/index.js @@ -185,6 +185,7 @@ async function onExpressJsSetup(server) { + ` ${config.CDN.PUBLIC}` + ' https://d1of0acg2orgco.cloudfront.net' + ' https://d24oibycet9bsb.cloudfront.net' + + ' https://d1mwkvp2xbqfs9.cloudfront.net' + ' https://43d132d5dbff47c59d9d53ad448f93c2.js.ubembed.com;' + " frame-src 'self'" + ` ${config.URL.AUTH}` diff --git a/src/server/tc-communities/tco23/metadata.json b/src/server/tc-communities/tco23/metadata.json new file mode 100644 index 0000000000..04b88da612 --- /dev/null +++ b/src/server/tc-communities/tco23/metadata.json @@ -0,0 +1,20 @@ +{ + "challengeFilter": { + "events": ["tco23"] + }, + "communityId": "tco23", + "communityName": "TCO23", + "groupIds": [], + "hideSearch": true, + "logos": [{ + "img": "/community-app-assets/themes/tco/TCO23.svg", + "url": "https://tco23.topcoder.com" + }], + "menuItems": [{ + "navigationMenu": "6SsceF3R5YuKxsf8XnCM5I" + }], + "newsFeed": "http://www.topcoder.com/feed", + "subdomains": ["tco23"], + "description": "2023 Topcoder Open. The Ultimate Programming & Design Tournament", + "image": "tco23.jpg" +} diff --git a/src/shared/components/Contentful/ContentBlock/index.jsx b/src/shared/components/Contentful/ContentBlock/index.jsx index 2aea7d2b78..d567a69c35 100644 --- a/src/shared/components/Contentful/ContentBlock/index.jsx +++ b/src/shared/components/Contentful/ContentBlock/index.jsx @@ -19,6 +19,7 @@ import generalTheme from './themes/general.scss'; import blobCard from './themes/blobCard.scss'; import TCO20Theme from './themes/TCO20.scss'; import largeCard from './themes/largeCard.scss'; +import bracketsTheme from './themes/brackets.scss'; const THEMES = { Default: defaultTheme, @@ -31,6 +32,7 @@ const THEMES = { 'Blob Card': blobCard, TCO20: TCO20Theme, 'Large Card': largeCard, + Brackets: bracketsTheme, }; /* Loads content block background asset. */ diff --git a/src/shared/components/Contentful/ContentBlock/themes/brackets.scss b/src/shared/components/Contentful/ContentBlock/themes/brackets.scss new file mode 100644 index 0000000000..5475fff209 --- /dev/null +++ b/src/shared/components/Contentful/ContentBlock/themes/brackets.scss @@ -0,0 +1,64 @@ +@import "~styles/mixins"; +@import "~components/Contentful/brackets"; + +.contentWrapper { + display: flex; + margin: 0 auto; + max-width: $screen-lg; + padding: 15px 0; + color: $tc-black; + + @include xs-to-sm { + flex-direction: column; + } +} + +.container { + align-content: center; + background: white; + padding: 10px 0; + + &:nth-child(even) .contentWrapper { + flex-direction: row-reverse; + + @include xs-to-sm { + flex-direction: column; + } + } +} + +strong a { + font-weight: 600 !important; +} + +.content { + flex: 1; + padding: 0; + + @include xs-to-md { + padding: 15px; + } + + @include roboto-regular; + + h1, + h2, + h3, + h4, + h5, + h6 { + color: $tco-black; + } + + @include brackets-headers; + @include brackets-content; +} + +.image { + flex: 1; + margin: 15px; + + img { + width: 100%; + } +} diff --git a/src/shared/components/Contentful/Tabs/Tabs.jsx b/src/shared/components/Contentful/Tabs/Tabs.jsx index 85280aa4bd..4eb0541cdf 100644 --- a/src/shared/components/Contentful/Tabs/Tabs.jsx +++ b/src/shared/components/Contentful/Tabs/Tabs.jsx @@ -27,6 +27,7 @@ import underlineDarkTheme from './themes/underline-dark.scss'; import verticalTheme from './themes/vertical.scss'; import pillsTheme from './themes/pills.scss'; import underlineBoxTheme from './themes/underline-box.scss'; +import bracketsTheme from './themes/brackets.scss'; export const TAB_THEMES = { Default: defaultTheme, @@ -38,6 +39,7 @@ export const TAB_THEMES = { Vertical: verticalTheme, Pills: pillsTheme, 'Underline box': underlineBoxTheme, + Brackets: bracketsTheme, }; export default class TabsItemsLoader extends Component { diff --git a/src/shared/components/Contentful/Tabs/themes/brackets.scss b/src/shared/components/Contentful/Tabs/themes/brackets.scss new file mode 100644 index 0000000000..589de02776 --- /dev/null +++ b/src/shared/components/Contentful/Tabs/themes/brackets.scss @@ -0,0 +1,168 @@ +@import "~styles/mixins"; + +$container-background-gray: #ebebeb; +$text-color-black: #262628; +$text-color-gray: #888894; +$text-color-pannel: #4a4a4a; + +.container { + margin: auto; + + @include xs-to-sm { + margin-top: 65px; + } +} + +.tabListWrap { + display: flex; + justify-content: center; + position: relative; + + .tablist { + @include roboto-regular; + + display: flex; + flex-direction: row; + justify-content: center; + list-style-type: none; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.06); + margin: auto; + min-height: 60px; + border-radius: 30px; + align-items: center; + background-color: white; + padding: 0 25px; + border: 1px solid #e4e4e4; + + @include xs-to-sm { + white-space: nowrap; + flex-direction: column; + padding: 28px 15px 0; + align-items: flex-start; + border-radius: 8px; + min-width: 85vw; + overflow: visible; + position: absolute; + z-index: 999; + display: none; // by default + + &.visible { + display: flex; + } + } + } + + .tabListMobileTrigger { + display: none; + justify-content: center; + align-items: center; + background-color: white; + position: absolute; + top: -65px; + width: 85vw; + left: calc(50% - 42.5vw); + outline: none; + border: navajowhite; + min-height: 60px; + font-family: Barlow, sans-serif; + font-size: 16px; + font-weight: 600; + text-transform: uppercase; + border-radius: 30px; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.06); + color: #2a2a2a; + + @media (max-width: 768px) { + display: flex; + } + + .tabListMobileTriggerSVG, + .tabListMobileTriggerSVGOpen { + margin-left: 9px; + } + + .tabListMobileTriggerSVGOpen { + transform: scaleY(-1); + } + } +} + +.tab { + text-align: center; + margin: 0 25px; + color: #555; + font-family: Barlow, sans-serif; + font-size: 16px; + font-weight: 600; + line-height: 20px; + padding-bottom: 5px; + cursor: pointer; + margin-bottom: -5px; + position: relative; + + @include xs-to-sm { + margin: 0; + margin-bottom: 23px; + padding: 0; + padding-left: 5px; + + &::after { + display: none; + } + + &:hover, + &.selected { + border-left: 3px solid #43d7b0; + margin-left: -3px; + } + } + + &:hover, + &.selected { + color: #2a2a2a; + + &::after { + content: ''; + border-radius: 1000vw; + background: #43d7b0; + height: 3px; + width: 15px; + position: absolute; + bottom: 0; + left: calc(50% - 7px); + border-left: 1px solid #fff; + border-right: 1px solid #fff; + + @include xs-to-sm { + width: calc(100% - 36px); + bottom: -5px; + } + } + } + + p { + small { + color: #888894; + font-size: 13px; + font-weight: 400; + line-height: 25px; + text-align: left; + } + + strong { + font-weight: bold; + } + } +} + +.tabpannel { + display: none; +} + +.selectedTabPanel { + display: block; + + @include xs-to-sm { + padding: 0 15px; + } +} diff --git a/src/shared/components/Contentful/_brackets.scss b/src/shared/components/Contentful/_brackets.scss new file mode 100644 index 0000000000..db13a3a911 --- /dev/null +++ b/src/shared/components/Contentful/_brackets.scss @@ -0,0 +1,281 @@ +@import "~styles/mixins"; + +@mixin default-headers { + h1, + h2, + h3, + h4, + h5, + h6 { + margin: 10px 0; + } + + h1 { + font-size: 42px; + line-height: 50px; + + @include roboto-light; + } + + h2 { + font-size: 36px; + line-height: 45px; + + @include roboto-light; + } + + h3 { + font-size: 28px; + line-height: 35px; + + @include roboto-regular; + } + + h4 { + font-size: 20px; + line-height: 35px; + + @include roboto-regular; + } + + h5 { + font-size: 15px; + line-height: 25px; + + @include roboto-bold; + } + + h6 { + font-size: 13px; + line-height: 25px; + + @include roboto-bold; + } +} + +@mixin brackets-headers { + h1 { + @include barlow-condensed-semi-bold; + + font-size: 80px; + line-height: 72px; + text-transform: uppercase; + margin-top: 80px; + margin-bottom: 20px; + + @include xs-to-sm { + font-size: 42px !important; + font-weight: 600 !important; + line-height: 40px !important; + margin-top: 42px; + margin-bottom: 10px; + } + } + + h2 { + @include barlow-condensed-semi-bold; + + font-size: 54px; + line-height: 52px; + text-transform: uppercase; + margin-top: 54px; + margin-bottom: 20px; + + @include xs-to-sm { + font-size: 32px !important; + font-weight: 500 !important; + margin-top: 32px; + margin-bottom: 10px; + line-height: 32px !important; + } + } + + h3 { + @include barlow-condensed-semi-bold; + + font-size: 44px; + line-height: 44px; + text-transform: uppercase; + margin-top: 44px; + margin-bottom: 20px; + + @include xs-to-sm { + font-size: 27px !important; + font-weight: 500 !important; + line-height: 28px !important; + margin-top: 27px; + margin-bottom: 10px; + } + } + + h4 { + @include barlow-condensed-semi-bold; + + font-size: 32px; + line-height: 34px; + text-transform: uppercase; + margin-top: 32px; + margin-bottom: 10px; + + @include xs-to-sm { + font-size: 22px !important; + font-weight: 500 !important; + line-height: 24px !important; + margin-top: 22px; + } + } + + h5, + h6 { + @include barlow-condensed-semi-bold; + + font-size: 26px; + line-height: 28px; + font-weight: 600; + text-transform: uppercase; + margin-top: 26px; + margin-bottom: 10px; + + @include xs-to-sm { + font-size: 16px !important; + font-weight: 600 !important; + line-height: 18px !important; + margin-top: 16px; + } + } +} + +@mixin brackets-content { + a { + @include roboto-regular; + + font-size: 16px; + line-height: 24px; + color: #0d61bf; + text-decoration: none; + + &:hover { + text-decoration: none; + color: #0d61bf; + } + + &:visited { + color: #8231a9; + } + } + + p { + @include tc-body-md; + + color: $tco-black; + font-size: 16px; + line-height: 24px; + margin-bottom: 20px; + margin-top: 0; + + strong { + @include roboto-medium; + + line-height: 24px; + text-align: left; + font-weight: 600; + } + } + + table { + margin-bottom: 20px; + + th { + @include barlow-bold; + + color: #2a2a2a; + font-size: 11px; + line-height: 14px; + text-align: left; + text-transform: uppercase; + padding: 18px 10px 14px 0; + + @include md-to-xl { + white-space: nowrap; + } + + &:first-child { + padding-left: 10px; + } + } + + td { + @include roboto-regular; + + font-size: 16px; + line-height: 26px; + text-align: left; + color: #2a2a2a; + border-top: 1px solid #d4d4d4; + border-bottom: 1px solid #d4d4d4; + padding: 18px 50px 18px 0; + max-height: 63px; + + &:first-child { + padding-left: 10px; + } + + &:last-child { + padding-right: 10px; + } + } + } + + ul, + ol { + @include tc-body-md; + + padding-left: 20px; + margin-bottom: 20px; + + @include roboto-regular; + + color: $tc-black; + + li p { + margin-bottom: 0; + } + } + + ul { + list-style-type: disc; + } + + ol { + list-style-type: decimal; + } + + img { + max-width: 100%; + border-radius: 6px; + } + + code { + @include roboto-mono-regular; + + color: #2a2a2a; + line-height: 1.5; + white-space: pre; + } + + sub, + sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; + } + + sup { + top: -0.5em; + } + + sub { + bottom: -0.25em; + } +} diff --git a/src/shared/components/buttons/themed/brackets.scss b/src/shared/components/buttons/themed/brackets.scss new file mode 100644 index 0000000000..799353c58e --- /dev/null +++ b/src/shared/components/buttons/themed/brackets.scss @@ -0,0 +1,303 @@ +@import "~styles/mixins"; + +@mixin primary { + @include roboto-bold; + + font-weight: 700 !important; + text-decoration: none !important; + text-transform: uppercase !important; + margin: 0 !important; + white-space: nowrap !important; + letter-spacing: 0.8px; +} + +@mixin primary-master { + @include primary; + + background-color: #e6cff1 !important; + background-image: none !important; + color: #8231a9 !important; + border: none !important; + box-shadow: none !important; + + &:hover { + background-color: #e6cff1 !important; + } + + &:active { + background-color: #e6cff1 !important; + } + + &:disabled { + color: #8231a9; + border: none !important; + background: none !important; + } +} + +@mixin primary-green { + @include primary; + + background-color: #137d60 !important; + background-image: none !important; + color: #fff !important; + border: none !important; + box-shadow: none !important; + + &:hover { + background-color: #219174 !important; + } + + &:active { + background-color: #0d664e !important; + } + + &:disabled { + color: #767676; + border: none !important; + background: none !important; + } +} + +@mixin primary-white { + @include primary; + + background-color: #fff !important; + background-image: none !important; + color: #137d60 !important; + border: 2px solid #137d60 !important; + box-shadow: none !important; + + &:hover { + color: #219174; + border: 2px solid #219174 !important; + } + + &:active { + color: #0d664e !important; + border: 2px solid #0d664e !important; + } + + &:disabled { + color: #767676; + border: none !important; + } +} + +@mixin primary-tertiary { + @include primary; + + background-color: #fff !important; + background-image: none !important; + color: #137d60 !important; + border: none !important; + box-shadow: none !important; + + &:hover, + &:active { + color: #0d664e; + } + + &:disabled { + color: #767676; + } +} + +@mixin sm { + font-size: 12px !important; + line-height: 24px !important; + border-radius: 24px !important; + min-height: auto !important; + max-height: 24px !important; + padding: 0 16px !important; +} + +@mixin md { + font-size: 13px !important; + line-height: 24px !important; + border-radius: 24px !important; + min-height: auto !important; + max-height: 32px !important; + padding: 4px 20px !important; +} + +@mixin lg { + font-size: 14px !important; + line-height: 24px !important; + border-radius: 24px !important; + min-height: auto !important; + max-height: 40px !important; + padding: 8px 24px !important; +} + +@mixin xl { + font-size: 16px !important; + line-height: 24px !important; + border-radius: 50px !important; + min-height: auto !important; + max-height: 48px !important; + padding: 12px 24px !important; +} + +.primary { + &-master { + &-sm { + @include primary-master; + @include sm; + + &:hover { + @include primary-master; + } + } + + &-md { + @include primary-master; + @include md; + + &:hover { + @include primary-master; + } + } + + &-lg { + @include primary-master; + @include lg; + + &:hover { + @include primary-master; + } + } + + &-xl { + @include primary-master; + @include xl; + + &:hover { + @include primary-master; + } + } + } + + &-green { + &-sm { + @include primary-green; + @include sm; + + &:hover { + @include primary-green; + } + } + + &-md { + @include primary-green; + @include md; + + &:hover { + @include primary-green; + } + } + + &-lg { + @include primary-green; + @include lg; + + &:hover { + @include primary-green; + } + } + + &-xl { + @include primary-green; + @include xl; + + &:hover { + @include primary-green; + } + } + } + + &-white { + &-sm { + @include primary-white; + @include sm; + + &:hover { + @include primary-white; + } + } + + &-md { + @include primary-white; + @include md; + + line-height: 38px !important; + + &:hover { + @include primary-white; + } + } + + &-lg { + @include primary-white; + @include lg; + + &:hover { + @include primary-white; + } + } + + &-xl { + @include primary-white; + @include xl; + + &:hover { + @include primary-white; + } + } + } + + &-tertiary { + &-sm { + @include primary-tertiary; + @include sm; + + &:hover { + @include primary-tertiary; + } + } + + &-md { + @include primary-tertiary; + @include md; + + &:hover { + @include primary-tertiary; + } + } + + &-lg { + @include primary-tertiary; + @include lg; + + &:hover { + @include primary-tertiary; + } + } + + &-xl { + @include primary-tertiary; + @include xl; + + &:hover { + @include primary-tertiary; + } + } + } +} + +.themedButtonDisabled { + background-color: #e9e9e9 !important; + border: none !important; + text-decoration: none !important; + color: #fafafb !important; +} diff --git a/src/shared/routes/Communities/Routes.jsx b/src/shared/routes/Communities/Routes.jsx index 920791339e..ddee9a97f0 100644 --- a/src/shared/routes/Communities/Routes.jsx +++ b/src/shared/routes/Communities/Routes.jsx @@ -39,6 +39,7 @@ import tco19 from './TCO19'; import tco20 from './TCO20'; import tco21 from './TCO21'; import tco22 from './TCO22'; +import tco23 from './TCO23'; import Mobile from './Mobile'; import Zurich from './Zurich'; import Comcast from './Comcast'; @@ -66,6 +67,7 @@ const TCOs = { tco20, tco21, tco22, + tco23, }; export default function Communities({ diff --git a/src/shared/routes/Communities/TCO23/Routes.jsx b/src/shared/routes/Communities/TCO23/Routes.jsx new file mode 100644 index 0000000000..126febfe6a --- /dev/null +++ b/src/shared/routes/Communities/TCO23/Routes.jsx @@ -0,0 +1,60 @@ +/** + * Routing of TCO23 Community. + */ + +import Error404 from 'components/Error404'; +import PT from 'prop-types'; +import React from 'react'; +import { Route, Switch } from 'react-router-dom'; +import ContentfulRoute from 'components/Contentful/Route'; +import ContentfulMenu from 'components/Contentful/Menu'; +import Profile from 'routes/Profile'; +import ProfileStats from 'routes/ProfileStats'; +import Settings from 'routes/Settings'; + +export default function TCO23({ base, meta }) { + return ( +
+ { + meta.menuItems ? ( + + ) : null + } + + } + exact + path={`${base}/members/:handle([\\w\\-\\[\\].{}]{2,15})`} + /> + } + exact + path={`${base}/members/:handle([\\w\\-\\[\\].{}]{2,15})/details`} + /> + } + path={`${base}/settings`} + /> + } + id="6sV6osYXXLq9Jai5nPt3xI" + /> + +
+ ); +} + +TCO23.defaultProps = { + base: '', +}; + +TCO23.propTypes = { + base: PT.string, + meta: PT.shape().isRequired, +}; diff --git a/src/shared/routes/Communities/TCO23/index.jsx b/src/shared/routes/Communities/TCO23/index.jsx new file mode 100644 index 0000000000..6cdf98cc20 --- /dev/null +++ b/src/shared/routes/Communities/TCO23/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: "tco23-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/markdown.js b/src/shared/utils/markdown.js index a7cdb5cd8c..5e0883bf04 100644 --- a/src/shared/utils/markdown.js +++ b/src/shared/utils/markdown.js @@ -41,6 +41,7 @@ import tco10 from 'components/buttons/outline/tco/tco10.scss'; import tco09 from 'components/buttons/outline/tco/tco09.scss'; import tco07 from 'components/buttons/outline/tco/tco07.scss'; import tc from 'components/buttons/themed/tc.scss'; +import bs from 'components/buttons/themed/brackets.scss'; import Highlighter from './highlighter'; @@ -73,6 +74,7 @@ const tcoButtonThemes = { */ const buttonThemes = { tc, + bs, }; /**