diff --git a/.circleci/config.yml b/.circleci/config.yml index d49a32f50..df789a285 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -63,6 +63,7 @@ build_configuration_fetch: &build_configuration_fetch command: | ./awsconfiguration.sh $DEPLOY_ENV ./buildenv.sh -e $DEPLOY_ENV -b ${LOGICAL_ENV}-${APPNAME}-buildvar + aws s3 cp s3://tc-platform-${LOGICAL_ENV}/securitymanager/${LOGICAL_ENV}-platform-ui.env ./.env lint_steps: &lint_steps # Initialization. diff --git a/.gitignore b/.gitignore index 4d29575de..9db56d360 100644 --- a/.gitignore +++ b/.gitignore @@ -17,7 +17,12 @@ .env.development.local .env.test.local .env.production.local +.env npm-debug.log* yarn-debug.log* yarn-error.log* + +# Editors +.editorconfig +.prettierrc diff --git a/README.md b/README.md index 4951a9a68..cdab71572 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ Pre-existing user interfaces will be ported to here over time until this is the - [Local Environment Setup](#local-environment-setup) - [Deployments](#deployments) +- [Developer Center specific setup](#developer-center-specific-setup) - [Yarn Commands](#yarn-commands) # Application structure @@ -119,6 +120,37 @@ The "dev" branch is auto-deployed to the dev environment: https://platform-mvp.t The "master" branch is auto-deployed to the production environment: https://platform-mvp.topcoder.com. +## Developer Center specific setup + +### Contentful API Key and Space Id + +The app requires two environment variables, which contain the space id and the key used to access contentful and retrieve Thrive Articles. + +You should create a file named `.env` in the root folder, and write inside the following lines: + +```sh +REACT_APP_CONTENTFUL_EDU_SPACE_ID= +REACT_APP_CONTENTFUL_EDU_CDN_API_KEY= +``` + +We should use the same space ID and API Key as Topcoder Thrive, these are for fetching Thrive articles and videos in the landing page. + +### Landing page configuration + +We can configure up to 5 articles shown on the landing page. The articles can be from Topcoder Thrive and/or Topcoder Blog. + +The configuration file is located at `src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/articles.config.ts`. + +We can configure the image carousel on the landing page, the configuration file is located at `src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/carousel-content.config.ts`. + +The local images for the carousel should be put in `src-ts/tools/dev-center/carousel-images`. + +### Getting Started page configuration. + +The content of the getting started page is from a Markdown text, the source is located at `src-ts/tools/dev-center/dev-center-pages/community-app/getting-started/GettingStartedGuide.md`. + +The local images for the markdown should be put in `src-ts/tools/dev-center/images`. + ## yarn Commands | Command | Description | @@ -465,8 +497,8 @@ e.g.: ``` .logo-link { svg { - width: calc($pad-xxl + $pad-xxxxl); - height: $pad-xl; + width: calc($space-xxl + $space-xxxxl); + height: $space-xl; fill: none; path { diff --git a/package.json b/package.json index 1fa4fdc1f..287b6d0f2 100644 --- a/package.json +++ b/package.json @@ -18,14 +18,21 @@ "dependencies": { "@datadog/browser-logs": "^4.7.1", "@heroicons/react": "^1.0.6", + "@types/dompurify": "^2.3.3", + "@types/highlightjs": "^9.12.2", + "@types/marked": "4.0.3", "apexcharts": "^3.35.3", "axios": "^0.26.1", "browser-cookies": "^1.2.0", "classnames": "^2.3.1", + "contentful": "^9.1.33", "crypto-js": "^4.1.1", + "dompurify": "^2.3.10", + "highlight.js": "^11.6.0", "customize-cra": "^1.0.0", "html2canvas": "^1.4.1", "lodash": "^4.17.21", + "marked": "4.0.3", "moment": "^2.29.3", "moment-timezone": "^0.5.34", "prop-types": "^15.8.1", diff --git a/src-ts/config/environments/environment.default.config.ts b/src-ts/config/environments/environment.default.config.ts index f1339ec3b..f13c4b38d 100644 --- a/src-ts/config/environments/environment.default.config.ts +++ b/src-ts/config/environments/environment.default.config.ts @@ -32,9 +32,13 @@ export const EnvironmentConfigDefault: GlobalConfig = { 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlcyI6WyJUb3Bjb2RlciBVc2VyIl0sImlzcyI6Imh0dHBzOi8vYXBpLnRvcGNvZGVyLWRldi5jb20iLCJoYW5kbGUiOiJ0ZXN0MSIsImV4cCI6MjU2MzA3NjY4OSwidXNlcklkIjoiNDAwNTEzMzMiLCJpYXQiOjE0NjMwNzYwODksImVtYWlsIjoidGVzdEB0b3Bjb2Rlci5jb20iLCJqdGkiOiJiMzNiNzdjZC1iNTJlLTQwZmUtODM3ZS1iZWI4ZTBhZTZhNGEifQ.jl6Lp_friVNwEP8nfsfmL-vrQFzOFp2IfM_HC7AwGcg', }, TOPCODER_URLS: { + API_BASE: `${COMMUNITY_WEBSITE}/api`, + BLOG_PAGE: `${COMMUNITY_WEBSITE}/blog`, CHALLENGES_PAGE: `${COMMUNITY_WEBSITE}/challenges`, GIGS_PAGE: `${COMMUNITY_WEBSITE}/gigs`, + THRIVE_PAGE: `${COMMUNITY_WEBSITE}/thrive`, USER_PROFILE: `${COMMUNITY_WEBSITE}/members`, + WP_CONTENT: `${COMMUNITY_WEBSITE}/wp-content`, }, URL: { ACCOUNTS_APP_CONNECTOR: 'https://accounts-auth0.topcoder-dev.com', diff --git a/src-ts/config/environments/environment.prod.config.ts b/src-ts/config/environments/environment.prod.config.ts index 79c9bf978..e1badd2fc 100644 --- a/src-ts/config/environments/environment.prod.config.ts +++ b/src-ts/config/environments/environment.prod.config.ts @@ -30,9 +30,13 @@ export const EnvironmentConfigProd: GlobalConfig = { 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlcyI6WyJUb3Bjb2RlciBVc2VyIl0sImlzcyI6Imh0dHBzOi8vYXBpLnRvcGNvZGVyLWRldi5jb20iLCJoYW5kbGUiOiJ0ZXN0MSIsImV4cCI6MjU2MzA3NjY4OSwidXNlcklkIjoiNDAwNTEzMzMiLCJpYXQiOjE0NjMwNzYwODksImVtYWlsIjoidGVzdEB0b3Bjb2Rlci5jb20iLCJqdGkiOiJiMzNiNzdjZC1iNTJlLTQwZmUtODM3ZS1iZWI4ZTBhZTZhNGEifQ.jl6Lp_friVNwEP8nfsfmL-vrQFzOFp2IfM_HC7AwGcg', }, TOPCODER_URLS: { + API_BASE: `${COMMUNITY_WEBSITE}/api`, + BLOG_PAGE: `${COMMUNITY_WEBSITE}/blog`, CHALLENGES_PAGE: `${COMMUNITY_WEBSITE}/challenges`, GIGS_PAGE: `${COMMUNITY_WEBSITE}/gigs`, + THRIVE_PAGE: `${COMMUNITY_WEBSITE}/thrive`, USER_PROFILE: `${COMMUNITY_WEBSITE}/members`, + WP_CONTENT: `${COMMUNITY_WEBSITE}/wp-content`, }, URL: { ACCOUNTS_APP_CONNECTOR: 'https://accounts-auth0.topcoder.com', diff --git a/src-ts/declarations.d.ts b/src-ts/declarations.d.ts index fa09433a4..bd7a8df0c 100644 --- a/src-ts/declarations.d.ts +++ b/src-ts/declarations.d.ts @@ -22,3 +22,8 @@ declare module '*.svg' { } declare module 'tc-auth-lib' + +declare module '*.md' { + const value: string + export default value +} diff --git a/src-ts/header/logo/Logo.module.scss b/src-ts/header/logo/Logo.module.scss index 63f246fe1..c8147210a 100644 --- a/src-ts/header/logo/Logo.module.scss +++ b/src-ts/header/logo/Logo.module.scss @@ -9,8 +9,8 @@ } svg { - width: calc($pad-xxl + $pad-xxxxl); - height: $pad-xl; + width: calc($space-xxl + $space-xxxxl); + height: $space-xl; fill: none; path { diff --git a/src-ts/header/tool-selectors/tool-selectors-narrow/ToolSelectorsNarrow.module.scss b/src-ts/header/tool-selectors/tool-selectors-narrow/ToolSelectorsNarrow.module.scss index 00432f9bd..b8c5b6080 100644 --- a/src-ts/header/tool-selectors/tool-selectors-narrow/ToolSelectorsNarrow.module.scss +++ b/src-ts/header/tool-selectors/tool-selectors-narrow/ToolSelectorsNarrow.module.scss @@ -23,9 +23,9 @@ left: 0; bottom: 0; height: $content-height; - width: calc(100% - calc(2 * $pad-xxl)); + width: calc(100% - calc(2 * $space-xxl)); z-index: 100; background-color: $black-100; - padding: $pad-xxl; + padding: $space-xxl; } } diff --git a/src-ts/header/tool-selectors/tool-selectors-narrow/tool-selector-narrow/ToolSelectorNarrow.module.scss b/src-ts/header/tool-selectors/tool-selectors-narrow/tool-selector-narrow/ToolSelectorNarrow.module.scss index aa0e9d6b0..bd803c9d5 100644 --- a/src-ts/header/tool-selectors/tool-selectors-narrow/tool-selector-narrow/ToolSelectorNarrow.module.scss +++ b/src-ts/header/tool-selectors/tool-selectors-narrow/tool-selector-narrow/ToolSelectorNarrow.module.scss @@ -11,7 +11,7 @@ justify-content: space-between; align-items: center; border-top: 1px solid $black-60; - padding: $pad-lg 0; + padding: $space-lg 0; color: $tc-white; font-weight: $font-weight-medium; background-color: $black-100; diff --git a/src-ts/header/tool-selectors/tool-selectors-wide/ToolSelectorsWide.module.scss b/src-ts/header/tool-selectors/tool-selectors-wide/ToolSelectorsWide.module.scss index ba01f4de5..0ac8ef96d 100644 --- a/src-ts/header/tool-selectors/tool-selectors-wide/ToolSelectorsWide.module.scss +++ b/src-ts/header/tool-selectors/tool-selectors-wide/ToolSelectorsWide.module.scss @@ -4,7 +4,7 @@ display: flex; align-items: center; border-left: solid 1px $black-80; - padding-left: $pad-md; + padding-left: $space-md; @include ltemd { display: none; diff --git a/src-ts/header/tool-selectors/tool-selectors-wide/tool-selector-wide/ToolSelectorWide.module.scss b/src-ts/header/tool-selectors/tool-selectors-wide/tool-selector-wide/ToolSelectorWide.module.scss index 64a8efdee..a8d6a7a16 100644 --- a/src-ts/header/tool-selectors/tool-selectors-wide/tool-selector-wide/ToolSelectorWide.module.scss +++ b/src-ts/header/tool-selectors/tool-selectors-wide/tool-selector-wide/ToolSelectorWide.module.scss @@ -10,12 +10,12 @@ a { display: block; - padding: 11px $pad-md; + padding: 11px $space-md; text-align: center; } .active-indicator { - width: $pad-xxl; + width: $space-xxl; height: 2px; } diff --git a/src-ts/header/utility-selectors/UtilitySelector/ProfileSelector/profile-logged-in/ProfileLoggedIn.module.scss b/src-ts/header/utility-selectors/UtilitySelector/ProfileSelector/profile-logged-in/ProfileLoggedIn.module.scss index f0906e8b4..08edd0e71 100644 --- a/src-ts/header/utility-selectors/UtilitySelector/ProfileSelector/profile-logged-in/ProfileLoggedIn.module.scss +++ b/src-ts/header/utility-selectors/UtilitySelector/ProfileSelector/profile-logged-in/ProfileLoggedIn.module.scss @@ -1,6 +1,6 @@ @import '../../../../../lib/styles/includes'; -$overlaySquare: $pad-xxxxl; +$overlaySquare: $space-xxxxl; .profile-avatar, .overlay { diff --git a/src-ts/header/utility-selectors/UtilitySelector/ProfileSelector/profile-logged-in/profile-panel/ProfilePanel.module.scss b/src-ts/header/utility-selectors/UtilitySelector/ProfileSelector/profile-logged-in/profile-panel/ProfilePanel.module.scss index 4082c4761..1ec99c6f2 100644 --- a/src-ts/header/utility-selectors/UtilitySelector/ProfileSelector/profile-logged-in/profile-panel/ProfilePanel.module.scss +++ b/src-ts/header/utility-selectors/UtilitySelector/ProfileSelector/profile-logged-in/profile-panel/ProfilePanel.module.scss @@ -7,8 +7,8 @@ $arrowTipIconHeight: 9px; @extend .body-ultra-small; position: absolute; z-index: 1000; - top: calc($pad-xxxxl + 4px + $arrowTipIconHeight); - right: calc(-1 * $pad-xxxxl / 2); + top: calc($space-xxxxl + 4px + $arrowTipIconHeight); + right: calc(-1 * $space-xxxxl / 2); width: 168px; display: flex; flex-direction: column; @@ -16,9 +16,9 @@ $arrowTipIconHeight: 9px; background-color: $tc-white; color: $black-100; - border-radius: $pad-sm; + border-radius: $space-sm; - padding: $pad-sm $pad-lg $pad-lg; + padding: $space-sm $space-lg $space-lg; .arrow-tip { display: flex; @@ -37,7 +37,7 @@ $arrowTipIconHeight: 9px; } hr { - margin: $pad-sm 0; + margin: $space-sm 0; } .nav-item { @@ -46,7 +46,7 @@ $arrowTipIconHeight: 9px; align-items: center; gap: 4px; + .nav-item { - margin-top: $pad-sm; + margin-top: $space-sm; } .icon { diff --git a/src-ts/header/utility-selectors/UtilitySelectors.module.scss b/src-ts/header/utility-selectors/UtilitySelectors.module.scss index 6a5cf1d85..ca8faf8d1 100644 --- a/src-ts/header/utility-selectors/UtilitySelectors.module.scss +++ b/src-ts/header/utility-selectors/UtilitySelectors.module.scss @@ -3,5 +3,5 @@ .utility-selectors { display: flex; justify-content: flex-end; - min-width: calc($pad-xxl + $pad-xxxxl); + min-width: calc($space-xxl + $space-xxxxl); } diff --git a/src-ts/lib/avatar/Avatar.module.scss b/src-ts/lib/avatar/Avatar.module.scss index 656fb032c..94f0d723d 100644 --- a/src-ts/lib/avatar/Avatar.module.scss +++ b/src-ts/lib/avatar/Avatar.module.scss @@ -4,7 +4,7 @@ $avatar-size-sm: 32px; $border-size-sm: $border; $avatar-size-xl: 120px; -$border-size-xl: $pad-xs; +$border-size-xl: $space-xs; .avatar-container { overflow: hidden; diff --git a/src-ts/lib/breadcrumb/Breadcrumb.module.scss b/src-ts/lib/breadcrumb/Breadcrumb.module.scss index c549f9def..c93a17794 100644 --- a/src-ts/lib/breadcrumb/Breadcrumb.module.scss +++ b/src-ts/lib/breadcrumb/Breadcrumb.module.scss @@ -7,14 +7,14 @@ } .breadcrumb { - padding: $pad-md 0; + padding: $space-md 0; max-width: $xxl-min; margin: 0 auto; @include pagePaddings; @include ltemd { - padding-top: $pad-xs; - padding-bottom: $pad-xs; + padding-top: $space-xs; + padding-bottom: $space-xs; } ol { @@ -22,6 +22,18 @@ padding-left: 0px; margin: 0; + &.hidden-mobile { + @include ltemd { + display: none; + } + } + + &.show-mobile { + @include gtelg { + display: none; + } + } + >li { display: inline-flex; align-items: center; @@ -30,7 +42,7 @@ a { @extend .overline; display: block; - padding: $pad-md; + padding: $space-md; color: $black-80; cursor: pointer; @@ -46,8 +58,8 @@ &:not(:last-child)::after { content: ''; display: inline-block; - width: $pad-sm; - height: $pad-sm; + width: $space-sm; + height: $space-sm; border-style: solid; border-width: $border-xs $border-xs 0 0; border-color: $black-60; diff --git a/src-ts/lib/button/Button.tsx b/src-ts/lib/button/Button.tsx index b46279ee6..47e105056 100644 --- a/src-ts/lib/button/Button.tsx +++ b/src-ts/lib/button/Button.tsx @@ -73,6 +73,7 @@ const Button: FC = (props: ButtonProps) => { return ( + ) +} + +const MarkdownImages: React.FC = ({ + children, + length, +}) => { + const carouselRef: React.MutableRefObject = React.useRef() + + const handlePrev: (ev: any) => void = (ev: any) => { + carouselRef?.current?.slidePrev() + } + + const handleNext: (ev: any) => void = (ev: any) => { + carouselRef?.current?.slideNext() + } + + interface RenderPaginationProps { + activePage: number + onClick: (ev: any) => void + pages: Array + } + + const renderPagination: React.FC = ({ + pages, + activePage, + onClick, + }) => { + return ( +
+
+ ) + } + return children.length > 1 ? ( + // @ts-ignore + + {children.map((image, index) => ( +
+ {image} +
+ ))} +
+ ) : ( + <> +
+
{children[0]}
+
+ + ) +} + +export default MarkdownImages diff --git a/src-ts/tools/dev-center/dev-center-lib/MarkdownDoc/MarkdownLink.module.scss b/src-ts/tools/dev-center/dev-center-lib/MarkdownDoc/MarkdownLink.module.scss new file mode 100644 index 000000000..f6ada8398 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-lib/MarkdownDoc/MarkdownLink.module.scss @@ -0,0 +1,50 @@ +@import "../../styles/variables"; +@import "../../../../lib/styles/includes"; + +.linkBlock { + display: flex; + align-items: center; + margin: $space-xxl 0; + background-color: $blue-10; + border-radius: 4px; +} + +.label { + flex: none; + padding: $space-md $space-lg; + + @include font-roboto; + @include font-weight-bold; + font-size: 12px; + line-height: 16px; + letter-spacing: 1px; + color: $black-100; +} + +.divider { + flex: none; + align-self: stretch; + border: 1px solid $tc-white; +} + +.link { + flex: auto; + padding: $space-md $space-lg; + + a { + @include font-roboto; + @include font-weight-medium; + font-size: 16px; + line-height: 24px; + color: $link-blue-dark; + + word-break: break-all; + } +} + +@include ltelg { + .label, + .divider { + display: none; + } +} diff --git a/src-ts/tools/dev-center/dev-center-lib/MarkdownDoc/MarkdownLink.tsx b/src-ts/tools/dev-center/dev-center-lib/MarkdownDoc/MarkdownLink.tsx new file mode 100644 index 000000000..303162e2d --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-lib/MarkdownDoc/MarkdownLink.tsx @@ -0,0 +1,24 @@ +import * as React from 'react' + +import { CopyButton } from '../CopyButton' + +import styles from './MarkdownLink.module.scss' + +interface MarkdownLinkProps { + children: React.ReactNode + href: string +} + +export const MarkdownLink: React.FC = (props) => { + const { children, href }: MarkdownLinkProps = props + return ( +
+ LINK + + {children} + +
+ ) +} + +export default MarkdownLink diff --git a/src-ts/tools/dev-center/dev-center-lib/MarkdownDoc/TableOfContents.module.scss b/src-ts/tools/dev-center/dev-center-lib/MarkdownDoc/TableOfContents.module.scss new file mode 100644 index 000000000..89979557b --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-lib/MarkdownDoc/TableOfContents.module.scss @@ -0,0 +1,53 @@ +@import "../../styles/variables"; + +.nav { + position: sticky; + top: 0; + width: $side-nav-width; + height: calc(100vh); + overflow-y: auto; + + box-shadow: inset 2px 0 $black-10; +} + +.navLabel { + @include font-barlow; + @include font-weight-semibold; + font-size: 18px; + line-height: 22px; + color: inherit; + text-transform: uppercase; + + padding: 0 0 0 $space-xxxxl; + margin: 0 0 $space-xxl; +} + +.navListItem { + border-left: 2px solid $black-10; + cursor: pointer; + + &::first-letter { + text-transform: capitalize; + } + + &.active, + &:hover { + border-left-color: $blue-140; + background-color: $blue-10; + + .navListItem-link { + color: $blue-140; + } + } +} + +.navListItem-link { + @include font-barlow; + @include font-weight-semibold; + font-size: 14px; + line-height: 20px; + color: $black-60; + + display: block; + padding: $space-sm 0 $space-sm $space-xxxxl; +} diff --git a/src-ts/tools/dev-center/dev-center-lib/MarkdownDoc/TableOfContents.tsx b/src-ts/tools/dev-center/dev-center-lib/MarkdownDoc/TableOfContents.tsx new file mode 100644 index 000000000..7cce2209c --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-lib/MarkdownDoc/TableOfContents.tsx @@ -0,0 +1,89 @@ +import * as React from 'react' + +import { TOC } from './markdownRenderer' +import styles from './TableOfContents.module.scss' + +interface TableOfContentsProps { + toc: TOC +} + +export const TableOfContents: React.FC = (props) => { + const [activeIndex, setActiveIndex]: [ + number, + React.Dispatch> + ] = React.useState(-1) + const { toc }: { toc: TOC } = props + const items: TOC = React.useMemo(() => { + return toc.filter((item) => item.level === 2) + }, [toc]) + + const findActiveIndex: () => void = React.useCallback(() => { + for (let i: number = 0; i < items.length; i++) { + const h: HTMLElement | null = document.getElementById( + items[i].headingId + ) + if ( + h && + h.offsetTop < + document.documentElement.scrollTop + + document.documentElement.clientHeight / 2 + ) { + setActiveIndex(i) + } + } + }, [items]) + + useOnScroll({ onScroll: findActiveIndex }) + + return ( + + ) +} + +function useOnScroll({ onScroll }: { onScroll: () => void }): void { + const debounceTimer: React.MutableRefObject< + ReturnType | undefined + > = React.useRef>() + React.useEffect(() => { + const handleScroll: () => void = () => { + if (debounceTimer.current) { + clearTimeout(debounceTimer.current) + debounceTimer.current = undefined + } + debounceTimer.current = setTimeout(() => { + debounceTimer.current = undefined + onScroll() + }, 1) + } + + onScroll() + window.addEventListener('scroll', handleScroll) + return () => { + clearTimeout(debounceTimer.current) + window.removeEventListener('scroll', handleScroll) + } + }, [onScroll]) +} + +export default TableOfContents diff --git a/src-ts/tools/dev-center/dev-center-lib/MarkdownDoc/index.ts b/src-ts/tools/dev-center/dev-center-lib/MarkdownDoc/index.ts new file mode 100644 index 000000000..393c1200f --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-lib/MarkdownDoc/index.ts @@ -0,0 +1,5 @@ +export * from './LayoutDocHeader' +export * from './markdownRenderer' + +export * from './MarkdownDoc' +export { default } from './MarkdownDoc' diff --git a/src-ts/tools/dev-center/dev-center-lib/MarkdownDoc/markdownRenderer/index.ts b/src-ts/tools/dev-center/dev-center-lib/MarkdownDoc/markdownRenderer/index.ts new file mode 100644 index 000000000..e622bd7c1 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-lib/MarkdownDoc/markdownRenderer/index.ts @@ -0,0 +1,2 @@ +export * from './renderer' +export * from './util' diff --git a/src-ts/tools/dev-center/dev-center-lib/MarkdownDoc/markdownRenderer/renderer.tsx b/src-ts/tools/dev-center/dev-center-lib/MarkdownDoc/markdownRenderer/renderer.tsx new file mode 100644 index 000000000..75f905e5a --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-lib/MarkdownDoc/markdownRenderer/renderer.tsx @@ -0,0 +1,373 @@ +// tslint:disable-next-line: no-submodule-imports +import 'highlight.js/styles/base16/tomorrow-night.css' +import _ from 'lodash' +import { marked, Renderer as MarkedRenderer } from 'marked' +import * as React from 'react' + +import MarkdownAccordion from '../MarkdownAccordion' +import MarkdownCode from '../MarkdownCode' +import styles from '../MarkdownDoc.module.scss' +import MarkdownImages from '../MarkdownImages' +import MarkdownLink from '../MarkdownLink' + +export type MarkdownString = string +export type MarkdownResult = React.ReactNode +export type TOC = Array<{ headingId: string; level: number; title: string }> + +enum MarkdownHeaderTag { + h1 = 'h1', + h2 = 'h2', + h3 = 'h3', + h4 = 'h4', + h5 = 'h5', + h6 = 'h6', +} + +enum MarkdownParagraphTag { + p = 'p', +} +export interface MarkdownRenderOptions { + baseUrl?: string + groupBy?: MarkdownHeaderTag.h2 + highlightCode?: (code: string, lang: string) => string + sanitize?: boolean + toc?: TOC + sanitizer?(html: string): string +} + +interface MarkdownRenderer { + render( + markdown: MarkdownString, + options?: MarkdownRenderOptions + ): React.ReactNode +} + +interface MarkdownTagClassName { + code: any + codespan: any + heading: any + list: any + paragraph: any +} + +export class Renderer implements MarkdownRenderer { + static getInstance(): Renderer { + if (!this.instance) { + this.instance = new Renderer() + } + return this.instance + } + + private renderer: MarkedRenderer + static instance: Renderer + + constructor() { + this.renderer = new marked.Renderer() + } + + render( + markdown: MarkdownString, + options?: MarkdownRenderOptions + ): React.ReactNode { + markdown = markdown || '' + if (markdown.length > 100_000) { + markdown = `${markdown.slice(0, 100_000)}…` + } + + const tokens: marked.TokensList = marked.lexer(markdown) + const nodes: Array = tokens.map((token) => + this.parseToken(token, options) + ) + const children: ReturnType = this.groupBy( + nodes, + options + ).map((node) => { + if (Array.isArray(node)) { + return ( + + {React.Children.map(node, (child) => child)} + + ) + } + return node + }) + + return ( +
+ {React.Children.map(children, (child) => child)} +
+ ) + } + + // Hard to avoid due to the complexity of group by + // tslint:disable-next-line: cyclomatic-complexity + private groupBy( + nodes: Array, + options?: MarkdownRenderOptions + ): Array> { + const result: Array = [] + let group: Array = [] + let beginGroup: boolean = false + let isAppending: boolean = false + let endGroup: boolean = false + + const isH1Tag: (tagName: keyof JSX.IntrinsicElements) => boolean = ( + tagName: keyof JSX.IntrinsicElements + ) => { + return tagName === MarkdownHeaderTag.h1 + } + const isGroupByTag: ( + tagName: keyof JSX.IntrinsicElements + ) => boolean = (tagName: keyof JSX.IntrinsicElements) => { + return !!tagName && options?.groupBy === tagName + } + + for (const nodeElem of nodes) { + if (!React.isValidElement(nodeElem)) { + continue + } + + const node: React.ReactElement = nodeElem as React.ReactElement + const nodeType: React.ReactElement['type'] = node.type + + if ( + typeof nodeType === 'string' && + isGroupByTag(nodeType as keyof JSX.IntrinsicElements) + ) { + beginGroup = true + isAppending = false + } + + if ( + typeof nodeType === 'string' && + isH1Tag(nodeType as keyof JSX.IntrinsicElements) + ) { + endGroup = true + } + + if (endGroup) { + beginGroup = false + isAppending = false + endGroup = false + } + + if (beginGroup) { + if (isAppending) { + group.push(node) + } else { + group = [] + group.push(node) + result.push(group) + } + isAppending = true + endGroup = false + } else { + result.push(node) + } + } + + return result + } + + // Hard to avoid due to the complexity of parsing markdown token. + // tslint:disable-next-line: cyclomatic-complexity + private parseToken( + token: marked.Token, + options?: MarkdownRenderOptions + ): React.ReactNode { + const isLinkBlock: (t: marked.Token) => boolean = (t: marked.Token) => { + t = t as marked.Tokens.Paragraph + if ( + t.type === 'paragraph' && + t.tokens && + t.tokens.length === 1 && + t.tokens[0].type === 'link' + ) { + return true + } + return false + } + const isCodeBlock: (t: marked.Token) => boolean = (t: marked.Token) => { + t = t as marked.Tokens.Code + if (t.type === 'code') { + return true + } + return false + } + const isImagesBlock: (t: marked.Token) => boolean = ( + t: marked.Token + ) => { + const isLineBreak: (tt: marked.Token) => boolean = ( + tt: marked.Token + ) => tt.type === 'text' && tt.text === '\n' + t = t as marked.Tokens.Paragraph + if ( + t.type === 'paragraph' && + t.tokens && + t.tokens.length !== 0 && + t.tokens + .filter((child) => !isLineBreak(child)) + .every((child) => child.type === 'image') && + t.tokens.filter((child) => !isLineBreak(child)).length >= 1 + ) { + return true + } + return false + } + + const getClassname: (t: marked.Token) => string = (t: marked.Token) => { + const classnameMapping: MarkdownTagClassName = { + code: t.lang + ? `${styles['codeBlock']} ${styles[`language-${t.lang}`]}` + : styles['codeBlock'], + codespan: styles['codeInline'], + heading: styles[`heading${t.depth}`], + list: styles[`${t.ordered ? 'orderedList' : 'unorderedList'}`], + paragraph: styles['paragraph'], + } + + return _.get(classnameMapping, t.type, '') + } + const stripTag: (htmlString: string, tagname: string) => string = ( + htmlString: string, + tagname: string + ) => { + const tagRegExp: RegExp = new RegExp( + `<${tagname}\\b[^>]*>((.|\\n)*?)`, + 'g' + ) + return htmlString.replace(tagRegExp, '$1') + } + const extractId: (htmlString: string, tagname: string) => string = ( + htmlString: string, + tagname: string + ) => { + htmlString = htmlString.trim() + const tagRegExp: RegExp = new RegExp( + `<${tagname}\\b[^>]*id="(.*?)"[^>]*>((.|\\n)*?)$`, + 'g' + ) + const matches: RegExpExecArray | null = tagRegExp.exec(htmlString) + return matches ? matches[1] : '' + } + const extractTag: (htmlString: string) => string = ( + htmlString: string + ) => { + htmlString = htmlString.trim() + const tagRegExp: RegExp = + /^<([a-zA-Z0-9]+)\b[^>]*?>(.|n)*?<\/\1>$/g + const matches: RegExpExecArray | null = tagRegExp.exec(htmlString) + return matches ? matches[1] : '' + } + const removeLineBreak: (htmlString: string) => string = ( + htmlString: string + ) => { + return htmlString.replace(/\n/g, '') + } + const parserOptions: marked.MarkedOptions = { + baseUrl: options?.baseUrl, + headerIds: true, + headerPrefix: '', + highlight: options?.highlightCode, + langPrefix: '', + renderer: this.renderer, + } + const createElement: ( + element: React.ElementType, + elementProps: any + ) => React.ReactElement = ( + element: React.ElementType, + elementProps: any + ) => { + return React.createElement(element, elementProps) + } + + if (options && options.toc && token.type === 'heading') { + const h: string = marked.parser([token], parserOptions) + const level: number = token.depth + const title: string = removeLineBreak(stripTag(h, `h${level}`)) + const headingId: string = extractId(h, `h${level}`).trim() + + options.toc.push({ + headingId, + level, + title, + }) + } + + let html: string = marked.parser([token], parserOptions) + + if (options && options.sanitize && options.sanitizer) { + html = options.sanitizer(html) + } + + if (isLinkBlock(token)) { + token = token as marked.Tokens.Paragraph + const link: marked.Tokens.Link = token.tokens.find( + (t) => t.type === 'link' + ) as marked.Tokens.Link + return ( + + {createElement('span', { + dangerouslySetInnerHTML: { __html: html }, + })} + + ) + } else if (isCodeBlock(token)) { + token = token as marked.Tokens.Code + return ( + + {createElement('div', { + dangerouslySetInnerHTML: { __html: html }, + })} + + ) + } else if (isImagesBlock(token)) { + token = token as marked.Tokens.Paragraph + const length: number = token.tokens.filter( + (t) => t.type === 'image' + ).length + const images: Array = token.tokens + .filter((t) => t.type === 'image') + .map((t, idx) => { + return ( + + ) + }) + return {images} + } + + if (!html) { + return undefined + } + + const tag: string = extractTag(html) + if (tag) { + const isParagraphTag: boolean = tag === MarkdownParagraphTag.p + const isHeaderTag: boolean = Object.values(MarkdownHeaderTag).indexOf(tag as MarkdownHeaderTag) !== -1 + if (isParagraphTag || isHeaderTag) { + let id: string | undefined + if (isHeaderTag) { + token = token as marked.Tokens.Heading + id = extractId(html, `h${token.depth}`).trim() + } + return React.createElement(tag, { + className: getClassname(token), + dangerouslySetInnerHTML: { __html: stripTag(html, tag) }, + id, + }) + } + } + + return ( + + ) + } +} diff --git a/src-ts/tools/dev-center/dev-center-lib/MarkdownDoc/markdownRenderer/util.ts b/src-ts/tools/dev-center/dev-center-lib/MarkdownDoc/markdownRenderer/util.ts new file mode 100644 index 000000000..6e643eccc --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-lib/MarkdownDoc/markdownRenderer/util.ts @@ -0,0 +1,51 @@ +import DOMPurify from 'dompurify' +import hljs from 'highlight.js' + +import { MarkdownRenderOptions, MarkdownString, Renderer, TOC } from './renderer' + +export function renderMarkdown( + markdown: MarkdownString, + options?: MarkdownRenderOptions +): { doc: React.ReactNode; title: string; toc: TOC } { + const renderer: Renderer = Renderer.getInstance() + const defaultOptions: MarkdownRenderOptions = { + baseUrl: '/', + groupBy: 'h2', + highlightCode(code: string, lang: string): string { + const language: string = hljs.getLanguage(lang) ? lang : '' + return language ? hljs.highlight(code, { language }).value : code + }, + sanitize: true, + sanitizer(html: string): string { + return DOMPurify.sanitize(html) + }, + toc: [], + } + const getTitle: (fromStr: MarkdownString) => { + s: MarkdownString; + title: string; + } = (fromStr: MarkdownString) => { + const titleRegExp: RegExp = /#[^#].*[\r\n]/ + const matches: RegExpMatchArray | null = fromStr.match(titleRegExp) + const matchStr: string = matches ? matches[0] : '' + return matchStr + ? { + s: fromStr.replace(matchStr, '').trimStart(), + title: matchStr.replace(/^#/, '').replace(/`/g, '').trim(), + } + : { title, s } + } + + const { title, s }: ReturnType = getTitle(markdown) + markdown = title ? s : markdown + + const opts: MarkdownRenderOptions = { ...defaultOptions, ...options } + const result: ReturnType = renderer.render( + markdown, + opts + ) + const { toc }: { toc: NonNullable } = + opts as { toc: NonNullable } + + return { doc: result, toc, title } +} diff --git a/src-ts/tools/dev-center/dev-center-lib/functions/copy-to-clipboard.ts b/src-ts/tools/dev-center/dev-center-lib/functions/copy-to-clipboard.ts new file mode 100644 index 000000000..2d58cf054 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-lib/functions/copy-to-clipboard.ts @@ -0,0 +1,26 @@ +export default async function copy(text: string): Promise { + try { + return await navigator.clipboard.writeText(text) + } catch (error) {} + + const activeElement: typeof document.activeElement = document.activeElement + const textArea: HTMLTextAreaElement = document.createElement('textarea') + + document.body.appendChild(textArea) + + textArea.style.height = '1px' + textArea.style.width = '1px' + textArea.style.position = 'absolute' + + textArea.value = text + textArea.focus() + textArea.select() + + document.execCommand('copy') + + if (activeElement instanceof HTMLElement) { + activeElement.focus() + } + + document.body.removeChild(textArea) +} diff --git a/src-ts/tools/dev-center/dev-center-lib/hooks/useMarkdown.ts b/src-ts/tools/dev-center/dev-center-lib/hooks/useMarkdown.ts new file mode 100644 index 000000000..6118c5744 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-lib/hooks/useMarkdown.ts @@ -0,0 +1,59 @@ +import * as React from 'react' + +import { + MarkdownResult, + MarkdownString, + renderMarkdown, + TOC +} from '../MarkdownDoc/markdownRenderer' + +export interface UseMarkdownProps { + uri: string +} + +export default function useMarkdown({ uri }: UseMarkdownProps): { + doc: MarkdownResult; + title: string; + toc: TOC; +} { + const [markdown, setMarkdown]: [ + MarkdownString, + React.Dispatch> + ] = React.useState('') + const [doc, setDoc]: [ + MarkdownResult, + React.Dispatch> + ] = React.useState() + const [toc, setToc]: [TOC, React.Dispatch>] = + React.useState([]) + const [title, setTitle]: [ + string, + React.Dispatch> + ] = React.useState('') + + React.useEffect(() => { + setMarkdown('') + setDoc(undefined) + setToc([]) + setTitle('') + + fetch(uri) + .then((response) => response.text()) + .then((text) => { + setMarkdown(text) + }) + .catch(() => {}) + }, [uri]) + + React.useEffect(() => { + if (markdown) { + const result: ReturnType = + renderMarkdown(markdown) + setDoc(result.doc) + setToc(result.toc) + setTitle(result.title) + } + }, [markdown]) + + return { doc, title, toc } +} diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/getting-started/GettingStartedGuide.md b/src-ts/tools/dev-center/dev-center-pages/community-app/getting-started/GettingStartedGuide.md new file mode 100644 index 000000000..d8e9ca429 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/getting-started/GettingStartedGuide.md @@ -0,0 +1,435 @@ +# Community app + +The community app is the web application that is a main part of the Topcoder website, including things like profile and challenge listings. +This document covers the Windows 10 setup of the development environment in detail. + +## Install Visual Studio Community 2013 + +[https://my.visualstudio.com/Downloads?q=visual%20studio%202013](https://my.visualstudio.com/Downloads?q=visual%20studio%202013) + +When installing + +* You can uncheck the "Join the Visual Studio Experience Improvement Program" +* You only need to check "Microsoft Foundation Classes for C++" on the optional features selection screen + +![](./images/VSCommunity0.png) +![](./images/VSCommunity1.png) +![](./images/VSCommunity2.png) +![](./images/VSCommunity3.png) + +## Install VS Code + +[https://code.visualstudio.com](https://code.visualstudio.com) + +You can use the default options when installing VS Code. + + +## Install Git + +[https://git-scm.com/download/win](https://git-scm.com/download/win) + +When installing: + +* Check checkbox for "Add a Git Bash Profile to Windows Terminal" (step 3) +* Use VS Code as Git's default editor (step 5) +* Checkout as-is commit as-is (step 10) +* Enable both experimental options (step 15) + +![](./images/Git1.png) +![](./images/Git2.png) +![](./images/Git3.png) +![](./images/Git4.png) +![](./images/Git5.png) +![](./images/Git6.png) +![](./images/Git7.png) +![](./images/Git8.png) +![](./images/Git9.png) +![](./images/Git10.png) + +## Install Python 2.7.18 + +[https://www.python.org/downloads/release/python-2718/](https://www.python.org/downloads/release/python-2718/) + +You can install with the default options (shown below) + +![](./images/Python1.png) +![](./images/Python2.png) +![](./images/Python3.png) +![](./images/Python4.png) +![](./images/Python5.png) + + +## Install NVM + +After Git has been installed, run the "Git Bash" program from your start menu. + +This will load the Git Bash command line, which is what we will use for all command line work going forward. + +You will install NVM (https://github.com/nvm-sh/nvm) using this command. You can copy / paste this onto the Git Bash command line and hit "Enter" to run it: + +```sh +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash +``` + +## Edit the aliases file + +The Git Bash program uses an "aliases" file for some initialisation of the shell. We need to make changes to it so that: + +* Python can be executed +* NVM works as expected + +We will add these 3 lines underneath the `alias ll='ls -l'` line: + +```sh +alias python='winpty C: \\Python27\\python-exe" +export NVM DIR="$HOME/.nvm" +[-s"$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" +``` + +You will need to grant VS Code admin privileges to save the file once the edits are done. + +The file should look like this: + +```sh +# some good standards, which are not used if the user +# creates his/her own .bashrc/ .bash_profile + +# --show-control-chars: help showing Korean or accented characters +alias ls='ls -F --color=auto --show-control-chars' +alias ll='ls -l' +alias python='winpty C:\\Python27\\python.exe' + +export NVM_DIR="$HOME/.nvm" +[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm + +case "$TERM" in +xterm*) + # The following programs are known to require a Win32 Console + # for interactive usage, therefore let’s launch them through + # when run inside `mintty` + for name in node ipython php php5 psql python2.7 + do + case "$(type -p "$name" .exe 2>/dev/null)" in + ''|/usr/bin/*) continue;; + esac + alias $name="winpty $name.exe” + done + ;; +esac +``` + +### Aliases Validation + +To validate the aliases changes, you will restart Git Bash, which will cause it to read in the new changes. You should be able to execute these commands without error: + +```terminal +python --version +``` + + +```terminal +nvm --version +``` + +The output should look like this: + +```terminal +jmgas@DESKTOP-CEFAE6N MINGW64 ~ +$ python --version +Python 2.7.18 + +jmgas@DESKTOP-CEFAE6N MINGW64 ~ +$ nvm --version +0.39.1 + +jmgas@DESKTOP-CEFAE6N MINGW64 ~ +$ +``` + +## Hosts file update + +Open the file `C:\Windows\System32\drivers\etc\hosts` in VS Code. We will add these two lines to the end of the file: + +```sh +127.0.0.1 local.topcoder-dev.com +127.0.0.1 local.topcoder.com +``` + +You will need to save the file using admin privileges. The final file should look like this: + +```sh +# Copyright (c) 1993-2000 Microsoft Corp. +# +# This is a sample HOSTS file used by Microsoft TCP/IP for Windows +# +# This file contains the mappings of iP addresses to host names. +# entry should be kept on an individual line. The IP address should +# be placed in the first column followed by the corresponding hosts +# The IP address and the host name should be separated by at least +# space. +# +# Additionaly, comments (such as these) may be inserted on individual +# lines or following the machine name denoted by a '#' symbol. +# +# For example: +# +# 102.54.94.97 rhino.acme.com # source server +# 38.25.63.10 x.acme.com # x client host + +# localhost name resolution is handled within DNS itself. +# 127.0.0.1 localhost +# ::1 localhost +127.0.0.1 local.topcoder-dev.com +127.0.0.1 local.topcoder.com +``` + +## Install the proxy and run it + +We need to proxy `https` requests through a local proxy since we don't have a valid SSL key. To do this, we use the `local-ssl-proxy` package. You can install this in the Git Bash application using this command. + +* `npm i -g local-ssl-proxy` You only have to run this once to install the package +* `local-ssl-proxy -n local.topcoder-dev.com -s 443 -t 3000` Every time you want to run the proxy or work on the community app, you will need to run. You will need to grant the proxy admin access. + +**NOTE** - You should run the proxy in a *separate* Git Bash window, to ensure it's always running. + +```terminal +jmgas@DESKTOP-CEFAE6N MINGW64 +$ pm i -g local-ss1-proxy +npm WARN deprecated nomnom@1.8.1: Package no longer supported. contact support@npmjs.com for more info. +npm WARN notice [SECURITY] underscore has the following vulnerability: 1 high. Go here for more details: https://github.com/advisories?query=underscore - Run `npm i npm@latest -g` to upgrade your pm version, and then `npm audit` to get more info. +c: lusers\jmgas\.num\versions\node\v8.11.2\bin\local-ss1-proxy +-> +C:\Users\jmgas\.nvm\versions\node\v8.11.2\bin\node_modules\local-ssl-proxy\bin\local-ssl-proxy + local-ss1-proxv@1.3.0 +added 18 packages in 3.321s + +jmgas@DESKTOP-CEFAE6N MINGW64 ~ +$ local-ss1-proxy -n local.topcoder-dev.com -s 443 -t 3000 +Started proxy: https://local.topcoder-dev.com: 443 -> http://local.topcoder-dev.com:3000 +``` + +## Check out the code + +Now that all dependencies are set up, we can check out the code. Note that this command will check out the community-app source code into a directory named `community-app`. + +Run this command on the Git Bash command line: + +```terminal +git clone https://github.com/topcoder-platform/community-app.git +``` + +```terminal +jmgas@DESKTOP-CEFAE6N MINGW64 +$ git clone https://github.com/topcoder-platform/community-app.git +Cloning into 'community-app'... +remote: Enumerating objects: 88177, done. +remote: Counting objects: 100% (981/981),done. +remote: Compressing objects: 100% (445/445), done. +remote: Total 88177 (delta 535), reused 905 (delta 485), pack-reused 87196 +Receiving objects: 100% (88177/88177), 135.06 MiB | 8.73 MiB/s, done. +Resolving deltas: 100% (58839/58839). done. +hint: core.useBuiltinFSMonitor=true is deprecated;please set core.fsmonitor=true instead +hint: Disable this message with "git config advice.useCoreFSMonitorConfig flase" +warning: the following paths have collided (e.g. case-sensitive paths on a case-insensitive filesystem) and only one from the same colliding group is in the working three: + + 'docs/contentful/Animations.md' + 'docs/contentful/animations.md' + 'docs/contentful/Viewport.md' + 'docs/contentful/viewport.md' + +jmgas@DESKTOP-CEFAE6N MINGW64 ~ +$ +``` + +## Build the code + +Now that we have the code, we can build it on the Git Bash command line. The first `cd community-app` command just changes us to the directory we created above, after the code was cloned. + +* `cd community-app` +* `nvm use` will warn you to install v8.11.2 +* `nvm install v8.11.2` + +```terminal +jmgas@DESKTOP-CEFAE6N MINGW64 +$ nvm use +Found '/c/Users/jmgas/community-app/.nvmrc' with version +N/A: version "V8.11.2 -> N/A" is not yet installed. + +You need to run "nvm install v8.11.2" to install it before using it. + +jmgas@DESKTOP-CEFAE6N MINGW64 ~/community-app (develop) +$ nvm install v8.11.2 +Downloading and installing node v8.11.2... +Downloading https://nodejs.org/dist/v8.11.2/node-v8.11.2-win-x64.zip... +######################################################################## 100.0% +Computing checksum with sha256sum +Checksums matched!Now using node v8.11.2 (npm v5.6.0) +Creating default alias: default -> v8.11.2 + +jmgas@DESKTOP-CEFAE6N MINGW64 ~/community-app (develop) +$ node --version +v8.11.2 +``` + + +Once we have the proper Node version installed (8.11.2), we will install the dependencies: + +**NOTE** this is a command that will take a long time and will build numerous dependencies. This is the command that is most likely to fail. If you have trouble here, make sure to copy / paste the entire output of the command into the forum so the copilot can help. + +```terminal +npm i +``` + +```terminal +> sharp@o.20.8 install c: \users\jmgas\community-app\node_modules\sharp +(node install/libvips && node install/d11-copy && prebuild-install)I1 (node-gyp rebuild && node install/d11-copy) + +info sharp Downloading https://github.com/lovell/sharp-libvips/releases/download/v8.6.1/libvips-8.6.1-win32-x64.tar.gz +info sharp creating c: \users\jmgas\community-app\node_modules\sharp\build\Release +info sharp Copying DLLs from C: \Users\jmgas\ community-app\node_modules \sharp\vendor\lib to c: \users\jmgas\ community-app\node_modules\sharp\build\Release + +> core-js@2. 6.11 postinstall c: \Users\jmgas\ community-app\node _modules\ core-js +> node -e "try{require('./postinstall'›}catch(e)(]" + +Thank you for using core-js (https://github.com/zloirock/core-js) for polyfilling Javascript standard library! + +The project needs your help! Please consider supporting of core-js on Open collective or Patreon: +> https://opencollective.com/core-js +> https://www.patreon.com/zloirock + +Also, the author of core-js (https://github.com/zloirock) is looking for a good job -) + +note-1: Pursfiedufreet;pasalhsalyssFea/ka)community-app/lnode_modules.lcore-js-pure +> core-js@2.6.11 postinstall c: \users\jmgas\ community-app\node_modules \tc-ui \node_modules\attr-accept \node_modules \core-js +> node -e "try{require('./postinstall ')}catch(e) {} + +> husky@4. 2.5 postinstall c: \Users\jmgas\community-app\node_modules \husky +> opencollective-postinstall I| exit 0 + +Thank you for using husky! +If you rely on this package, please consider supporting our open collective: +> https://opencollective.com/husky/donate + +> node-sass4.14.1 postinstall c: \users\jmgas\community-app\node_modules\node-sass +> node scripts/build.js + +Binary found at C: \Users\jmgas\community-app\node_modules\node-sass\vendor\win32-x64-57\binding.node +Testing binary +Binary is fine +(node: 3828) MaxListenersExceededwarning: Possible EventEmitter memory leak detected. 11 SIGINT listeners added. Use emitter.setMaxListeners () to increase limit + +> community-app@1.0.0 postinstall c: \Users \jmgas \ community-app +> rimraf node _modules/navigation-component/node_modules/topcoder-react-utils && rimraf node_modules/topcoder-react-ui-kit/node_modules/topcoder-react-utils + +npm WARN optional SKIPTING OPTZONAL DEPENDENCY: Fsevents@2. 1. 3 (node, nodules watchpack\node modules\fsevent:) +npm WARN notsup SKIPPING.OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.1.3: wanted {"os":"darwin", "arch", "any"} (current: {"os":"win32":"arch":"x64"}) +npm WARN optional SKIPTING OPTZONAL DEPENDENCY: Fsevents@2. 1. 3 (node, nodules\fsevent:) +npm WARN notup SKIPPING.OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.1.3: wanted {"os":"darwin", "arch", "any"} (current: {"os":"win32":"arch":"x64"}) + +added 2976 packages in 488.193s + +jmgas@DESKTOP-CEFAE6N MINGW64 ~/community-app (develop) +$ +``` + +With the dependencies now successfully installed, we can build the code. You can do this whenever you want to rebuild the app as you make changes to it. + +* `npm run clean` This command cleans up any previous builds: +* `source env.sh` This command sets the environmental variables: +* `./node_modules/.bin/webpack --env=development --progress --profile --colors` This command builds the app +* `npm run` This command will start the web server + +```terminal +jmgas@DESKTOP-CEFAE6N MINGW64 ~ +$ cd community-app + +jmgas@DESKTOP-CEFAE6N MINGW64 ~/community-app (develop) +$ npm run clean +> community-app@1.0.0 clean C:\Users\jmgas\community-app +> rimraf build + +jmgas@DESKTOP-CEFAE6N MINGW64 ~/community-app (develop) +$ export NODE_CONFIG_ENV=development + +jmgas@DESKTOP-CEFAE6N MINGW64 ~/community-app (develop) +$ ./node_modules/.bin/webpack--env=development --progress--profile --colors 36% building 221/255 modules 34 active ...app\node_modules\object-assign\index.js +``` + + +## Validation + +To validate, we'll run Chrome without web security to avoid it complaining about the local proxy redirects. + +Open a new Git Bash prompt and run: + +* `C:\Program Files\Google\Chrome\Application\chrome.exe" --disable-web-security --disable-gpu --disable-features=IsolateOrigins,site-per-process --user-data-dir="C://ChromeDev` + +Once Chrome is running, you should be able to open this link and login with a test user. + +* Sample test user: `jgasperMobile12` / `Appirio123` + +[https://accounts-auth0.topcoder-dev.com/?retUrl=https://local.topcoder-dev.com](https://accounts-auth0.topcoder-dev.com/?retUrl=https://local.topcoder-dev.com) + + +![](./images/InitialLoginInChrome.png) + + +You will need to tell Chrome to ignore the self-signed certificate warning by clicking the "Proceed to local.topcoder-dev.com" link + +![](./images/PrivateConnectionWarning.png) + +After successful login, you should see: + +**Chrome browser** + +![](./images/SuccessfulLogin.png) + +**Git bash prompt running the server** + +```terminal + in App + in Router + in StaticRouter + in Provider +Warning: componentwillmount has been renamed, and is not recommended for use. See https://fb/me/react-unsafe-component-lifecycles for details. + +* Move code from componentwillMount to componentDidMount (preferred in most cases) or the constructor +please update the following components: Switch + in Switch + in div + in Routes + in Connect (Routes) + in Route + in withouter (connect (Routes)) + in div + in App + in Router + in StaticRouter + in Provider + +::ffff:127.0.0.1 > 200 GET / 4023.838 ms - https://local.topcoder-dev.com/Mozilla/5.0 (windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) chrome/102/0/0/0 Safari/537.36 + +::ffff:127.0.0.1 > 200 GET /api/cdn/public/static-assets/main-1655784239000.Css6.177 ms- https://local.topcoder-dev.com/Mozilla/5.0 (windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) chrome/102/0/0/0 Safari/537.36 + +::ffff:127.0.0.1 > 200 GET /api/cdn/public/static-assets/main-1655784239000.Css6.177 ms- https://local.topcoder-dev.com/Mozilla/5.0 (windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) chrome/102/0/0/0 Safari/537.36 + +::ffff:127.0.0.1 > 200 GET /api/cdn/public/static-assets/main-1655784239000.Css6.177 ms- https://local.topcoder-dev.com/Mozilla/5.0 (windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) chrome/102/0/0/0 Safari/537.36 + +::ffff:127.0.0.1 > 200 GET /api/cdn/public/static-assets/main-1655784239000.Css6.177 ms- https://local.topcoder-dev.com/Mozilla/5.0 (windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) chrome/102/0/0/0 Safari/537.36 + +::ffff:127.0.0.1 > 200 GET /api/cdn/public/static-assets/main-1655784239000.Css6.177 ms- https://local.topcoder-dev.com/Mozilla/5.0 (windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) chrome/102/0/0/0 Safari/537.36 + +::ffff:127.0.0.1 > 200 GET /api/cdn/public/static-assets/main-1655784239000.Css6.177 ms- https://local.topcoder-dev.com/Mozilla/5.0 (windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) chrome/102/0/0/0 Safari/537.36 +::ffff:127.0.0.1 > 200 GET /api +/cdn/public/static-assets/main-1655784239000.Css6.177 ms- https://local.topcoder-dev.com/Mozilla/5.0 (windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) chrome/102/0/0/0 Safari/537.36 + +::ffff: 127.0.0.1 > Authenticated as: ("https://topcoder-dev.com/roles": ["Topcoder User"], . "https: //topc oder-dev.com/userId": "88778088". ."https://topcoder-dev.com/handle" "jgaspermobile12" ev.com/user_id": "autho|88778088" "https://topcoder-dev.com/tcsso" "https://topcoder "88778088) 83dddf57fe737e45425da484c€6 d26e262b44810ba944668c61f8f42f47e94" lockIP ': false, "nickname' "jgaspermobile12 "https://topcoder-dev.com/active".true,"https://topcoder-dev.com/l "name" "jmgasper+mobile12@gmail.com "picture" "https://s.g avatar.com/avatar/5dzf2479df25f71bb56e3cbc160714c6?5=480&r=pg&d=https%3A%2F%2Fcdn.autho. com%2Favatars Egm.pna,iss" "updated_at' ''2022-06-21T04:08:23.9202" +"email" "jmgasper+mobile12@gmail.com' "sub" "autho|88778088" "aud": "email verified +::ffff:127.0.0.1 > 200 GET / 4023.838 ms - https://local.topcoder-dev.com/Mozilla/5.0 (windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) chrome/102/0/0/0 Safari/537.36 + +::ffff:127.0.0.1 > Reauth scheduled in 86367.528 seconds +::ffff:127.0.0.1 > 200 POST /community-app-assets/api/logger 0.854 ms - https://local.topcoder-dev.com/Mozilla/5.0 (windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) chrome/102/0/0/0 Safari/537.36 +``` + +You can also access a link on the community app page, like the one for the challenge listings: + +![](./images/ChallengeListing.png) diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/getting-started/GettingStartedGuide.module.scss b/src-ts/tools/dev-center/dev-center-pages/community-app/getting-started/GettingStartedGuide.module.scss new file mode 100644 index 000000000..b22277ed9 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/getting-started/GettingStartedGuide.module.scss @@ -0,0 +1,24 @@ +@import '../../../styles/variables'; +@import '../../../../../lib/styles/includes'; + +.contentLayout { + width: 100%; + padding-bottom: 0; + + .contentLayout-outer { + width: 100%; + + .contentLayout-inner { + width: 100%; + overflow: visible; + } + } +} + +@include ltelg { + .contentLayout { + .contentLayout-outer { + padding: 0 $space-lg; + } + } +} \ No newline at end of file diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/getting-started/GettingStartedGuide.tsx b/src-ts/tools/dev-center/dev-center-pages/community-app/getting-started/GettingStartedGuide.tsx new file mode 100644 index 000000000..5c6431ba6 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/getting-started/GettingStartedGuide.tsx @@ -0,0 +1,30 @@ +import * as React from 'react' + +import { Breadcrumb, ContentLayout } from '../../../../../lib' +import { BreadcrumbItemModel } from '../../../../../lib/breadcrumb/breadcrumb-item/breadcrumb-item.model' +import useMarkdown from '../../../dev-center-lib/hooks/useMarkdown' +import MarkdownDoc from '../../../dev-center-lib/MarkdownDoc' +import LayoutDocHeader from '../../../dev-center-lib/MarkdownDoc/LayoutDocHeader' +import { toolTitle } from '../../../DevCenter' + +import gettingStartedGuide from './GettingStartedGuide.md' +import styles from './GettingStartedGuide.module.scss' + +export const GettingStartedGuide: React.FC = () => { + const { doc, toc, title }: ReturnType = useMarkdown({ uri: gettingStartedGuide }) + const breadcrumb: Array = React.useMemo(() => [ + { name: toolTitle, url: '/dev-center' }, + { name: title, url: '#' }, + ], [title]) + + return ( + + + + + + + ) +} + +export default GettingStartedGuide diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/DevCenterLandingPage.module.scss b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/DevCenterLandingPage.module.scss new file mode 100644 index 000000000..3ffc5d9e4 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/DevCenterLandingPage.module.scss @@ -0,0 +1,7 @@ +@import '../../../../../lib/styles/includes'; + +.container { + flex: 99 1 auto; + display: flex; + flex-direction: column; +} \ No newline at end of file diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/DevCenterLandingPage.tsx b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/DevCenterLandingPage.tsx new file mode 100644 index 000000000..20198fa76 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/DevCenterLandingPage.tsx @@ -0,0 +1,19 @@ +import { FC } from 'react' + +import { DevCenterArticlesection } from './dev-center-articles-section' +import { DevCenterGetStarted } from './dev-center-get-started' +import { DevCenterHeader } from './dev-center-header' +import styles from './DevCenterLandingPage.module.scss' + +const DevCenter: FC = () => { + + return ( +
+ + + +
+ ) +} + +export default DevCenter diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/ArticleCard/ArticleCard.module.scss b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/ArticleCard/ArticleCard.module.scss new file mode 100644 index 000000000..f96f5894c --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/ArticleCard/ArticleCard.module.scss @@ -0,0 +1,91 @@ +@import '../../../../../../../lib/styles/includes'; + +.outerContainer{ + border-radius: 8px; + position: relative; + background-size: 100% 100%; + overflow: hidden; + + @include ltemd{ + background-size: cover; + } + + .innerContainer { + width: 100%; + height: 100%; + background: linear-gradient(180deg, rgba(0, 0, 0, 0) 30.21%, #000000 100%); + + .playButton { + width: 38px; + height: 38px; + color: $tc-white; + position: absolute; + left: calc(50% - 19px); + top: calc(50% - 19px); + } + + .container { + padding-left: $space-xxl; + padding-right: $space-xxl; + padding-bottom: $space-xxl; + position: absolute; + bottom: 0px; + width: 100%; + + .topLine { + display: flex; + flex-direction: row; + justify-content: space-between; + margin-bottom: 14px; + align-items: center; + } + + .author { + opacity: 0.72; + text-transform: capitalize; + display: block; + margin-bottom: $space-lg; + } + + .summary { + @include font-weight-normal; + display: block; + white-space: nowrap; + overflow: hidden; + margin-bottom: $space-lg; + text-overflow: ellipsis; + } + + .readMore { + font-weight: 700; + font-size: 16px; + line-height: 16px; + text-transform: uppercase; + } + + + } + + + } +} + +.mainArticle { + + @include ltemd{ + aspect-ratio: 4 / 3; + } +} + +.smallArticle { + aspect-ratio: 4 /3; + + @include ltemd{ + width: 100%; + max-height: 240px; + } +} + +.mainArticle:hover, .smallArticle:hover{ + cursor: pointer; +} diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/ArticleCard/ArticleCard.tsx b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/ArticleCard/ArticleCard.tsx new file mode 100644 index 000000000..fb5b04e41 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/ArticleCard/ArticleCard.tsx @@ -0,0 +1,170 @@ +import classNames from 'classnames' +import { FC } from 'react' + +import { EnvironmentConfig } from '../../../../../../../config' +import { IconSolid } from '../../../../../../../lib' +import { DevCenterTag } from '../../dev-center-tag' +import { isThriveArticle } from '../Articles' +import { BlogPost, ThriveArticle } from '../models' + +import styles from './ArticleCard.module.scss' + +interface ArticleCardProps { + article: ThriveArticle | BlogPost + className?: string + isMain: boolean +} + +interface ArticleDetails { + author: string + image: string + isThrive: boolean + isVideo: boolean + summary: string + tagText: string + url: string +} + +function openArticle(url: string): void { + window.open( + url, + '_blank' // This is what makes it open in a new window. + ) +} + +function getTagText(isThrive: boolean, isVideo: boolean): string { + return isThrive + ? isVideo + ? 'Thrive Video' + : 'Thrive Article' + : 'Success Story' +} + +function getArticleContent( + article: ThriveArticle | BlogPost, + isThrive: boolean +): string { + return isThrive ? article.content : article.contentSnippet +} + +function getArticleDetails(article: ThriveArticle | BlogPost): ArticleDetails { + const isThrive: boolean = isThriveArticle(article) + const isVideo: boolean = isThrive && article.type === 'Video' + + const tagText: string = getTagText(isThrive, isVideo) + + const content: string = getArticleContent(article, isThrive) + const regex: RegExp = /(<([^>]+)>)/gi + const summary: string = content.replace(regex, '') // Remove html from the content string + const url: string = isThrive + ? `${EnvironmentConfig.TOPCODER_URLS.THRIVE_PAGE}/articles/${article.slug}` + : article.link + const author: string = !isThrive ? article.creator : '' + const image: string = isThrive + ? article.featuredImage.fields.file.url + : article.featuredImage + + return { + author, + image, + isThrive, + isVideo, + summary, + tagText, + url, + } +} + +function getOuterClass(isMain: boolean, className: string): string { + return classNames( + className, + styles.outerContainer, + isMain ? styles.mainArticle : styles.smallArticle + ) +} + +const ArticleCard: FC = ({ + article, + isMain, + className = '', +}) => { + const outerClass: string = getOuterClass(isMain, className) + const { + isThrive, + isVideo, + tagText, + summary, + url, + author, + image, + }: ArticleDetails = getArticleDetails(article) + + return ( +
+
openArticle(url)} + > + {isThrive && isVideo && ( + + )} +
+
+ + {isThrive && ( + + {article.readTime} + + )} +
+ {isMain ? ( +

+ {article.title} +

+ ) : ( +

+ {article.title} +

+ )} + {!isThrive && ( + + {author} + + )} + {isMain && ( + <> + + {summary} + + + READ MORE + + + )} +
+
+
+ ) +} + +export default ArticleCard diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/ArticleCard/index.tsx b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/ArticleCard/index.tsx new file mode 100644 index 000000000..12a947a8f --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/ArticleCard/index.tsx @@ -0,0 +1 @@ +export { default as ArticleCard } from './ArticleCard' diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/Articles.ts b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/Articles.ts new file mode 100644 index 000000000..3e7a45277 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/Articles.ts @@ -0,0 +1,27 @@ +import { EnvironmentConfig } from '../../../../../../config' + +import { BlogPost, ThriveArticle } from './models' + +/** Check if the article is a BlogPost or a ThriveArticle */ +export function isThriveArticle(article: BlogPost | ThriveArticle): article is ThriveArticle { + return (article as ThriveArticle).readTime !== undefined +} + +/** This is the default image to be used for blog posts that do not provide an url to the hero image */ +const DEFAULT_BLOG_IMAGE: string = `${EnvironmentConfig.TOPCODER_URLS.WP_CONTENT}/uploads/2017/04/SRM_Blog.png` + +/** Get the blog with the given url, or return undefined if the blog couldn't be fetched */ +export async function getBlog(url: string): Promise { + try { + const response: Response = await fetch(`${EnvironmentConfig.TOPCODER_URLS.API_BASE}/blog?limit=200`) + const data: Array = await response.json() + const blog: BlogPost = data.filter(x => x.link === url)[0] + // If the returned data do not contain the URL to the image, use the default one + if (!blog.featuredImage) { + blog.featuredImage = DEFAULT_BLOG_IMAGE + } + return blog + } catch (e) { + return undefined + } +} diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/CardSection/CardSection.module.scss b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/CardSection/CardSection.module.scss new file mode 100644 index 000000000..09a0f9b48 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/CardSection/CardSection.module.scss @@ -0,0 +1,102 @@ +@import '../../../../../../../lib/styles/includes'; + +.container { + width: 100%; + justify-content: center; + + .innerContainer { + display: grid; + grid-template-columns: 2fr 1fr 1fr; + grid-template-rows: 1fr 1fr; + gap: 32px; + + @include xl{ + grid-template-columns: 1fr 1fr; + grid-template-rows: 2fr 1fr 1fr; + max-width: 812px; + margin: auto; + } + + @include lg{ + grid-template-columns: 1fr 1fr; + grid-template-rows: 2fr 1fr 1fr; + } + + @include ltemd{ + display: flex; + flex-direction: column; + max-width: 400px; + margin: auto; + } + + .mainItem { + grid-row: 1 / span 2; + grid-column: 1; + + @include xl{ + grid-row: 1 ; + grid-column: 1 / span 2; + } + + @include lg{ + grid-row: 1 ; + grid-column: 1 / span 2; + } + } + .item2 { + grid-row: 1; + grid-column: 2; + + @include xl{ + grid-row: 2; + grid-column: 1; + } + @include lg{ + grid-row: 2; + grid-column: 1; + } + } + .item3 { + grid-row: 1; + grid-column: 3; + + @include xl{ + grid-row: 2; + grid-column: 2; + } + @include lg{ + grid-row: 2; + grid-column: 2; + } + } + + .item4 { + grid-row: 2; + grid-column: 2; + + @include xl{ + grid-row: 3; + grid-column: 1; + } + @include lg{ + grid-row: 3; + grid-column: 1; + } + } + .item5 { + grid-row: 2; + grid-column: 3; + + @include xl{ + grid-row: 3; + grid-column: 2; + } + @include lg{ + grid-row: 3; + grid-column: 2; + } + } + } +} + + diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/CardSection/CardSection.tsx b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/CardSection/CardSection.tsx new file mode 100644 index 000000000..61f883a0c --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/CardSection/CardSection.tsx @@ -0,0 +1,62 @@ +import { ContentfulClientApi, createClient } from 'contentful' +import { FC, useEffect, useState } from 'react' + +import { ArticleCard } from '../ArticleCard' +import { getBlog } from '../Articles' +import { ArticlesUrl, defaultBlogs } from '../articles.config' +import { ArticleType, BlogPost, ThriveArticle } from '../models' + +import styles from './CardSection.module.scss' + +const CardSection: FC = () => { + const [articles, setArticles]: [ + Array, + React.Dispatch>> + ] = useState>([]) + + useEffect(() => { + const client: ContentfulClientApi = createClient({ + accessToken: process.env.REACT_APP_CONTENTFUL_EDU_CDN_API_KEY ?? '', + space: process.env.REACT_APP_CONTENTFUL_EDU_SPACE_ID ?? '', + }) + Promise.all( + ArticlesUrl.map(async (articleUrl, idx) => { + switch (articleUrl.type) { + case ArticleType.Thrive: + const response: { fields: ThriveArticle } = + await client.getEntry(articleUrl.url) + return response.fields + case ArticleType.Blog: + const blog: BlogPost = + (await getBlog(articleUrl.url)) ?? + defaultBlogs[idx] + return blog + } + }) + ).then((arr) => setArticles(arr)) + }, []) + + const articleStyles: Array = [ + styles.mainItem, + styles.item2, + styles.item3, + styles.item4, + styles.item5, + ] + + return ( +
+
+ {articles.map((article, index) => ( + + ))} +
+
+ ) +} + +export default CardSection diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/CardSection/index.tsx b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/CardSection/index.tsx new file mode 100644 index 000000000..7fbf1e523 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/CardSection/index.tsx @@ -0,0 +1 @@ +export { default as CardSection } from './CardSection' diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/DevCenterArticlesSection.module.scss b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/DevCenterArticlesSection.module.scss new file mode 100644 index 000000000..d1f561e98 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/DevCenterArticlesSection.module.scss @@ -0,0 +1,26 @@ +@import '../../../../../../lib/styles/includes'; + +.container { + background-color: $black-5; + width: 100%; + height: fit-content; + padding: 80px 0px; + margin-top: 64px; + + @include ltemd { + padding: 40px 0px; + } + + .title { + @include font-black-100; + font-weight: 500; + font-size: 44px; + line-height: 44px; + margin-bottom: $space-xxxxl; + + @include ltemd { + font-size: 27px; + line-height: 28px; + } + } +} diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/DevCenterArticlesSection.tsx b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/DevCenterArticlesSection.tsx new file mode 100644 index 000000000..477ec7cf2 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/DevCenterArticlesSection.tsx @@ -0,0 +1,19 @@ +import { FC } from 'react' + +import { ContentLayout } from '../../../../../../lib' + +import { CardSection } from './CardSection' +import styles from './DevCenterArticlesSection.module.scss' + +const DevCenterArticlesection: FC = () => { + return ( +
+ +

Success Stories And Articles

+ +
+
+ ) +} + +export default DevCenterArticlesection diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/articles.config.ts b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/articles.config.ts new file mode 100644 index 000000000..e74a57628 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/articles.config.ts @@ -0,0 +1,73 @@ +import { EnvironmentConfig } from '../../../../../../config' + +import { ArticleEntry, ArticleType, BlogPost } from './models' + +/** + * This array defiens which thirive articles and blog pasts should be shown. + * The first element in the array will be the main article. + * For Thrive Articles, the url should be the Contentful ID. + * For Blog Posts, the url is the url linking to the post on topcoder.com + */ +export const ArticlesUrl: Array = [ + { + type: ArticleType.Blog, + url: `${EnvironmentConfig.TOPCODER_URLS.BLOG_PAGE}/talent-as-a-service-taas-a-brilliant-solution-to-the-talent-gap/`, + }, + { + type: ArticleType.Thrive, + url: '70GnGyAZzcRtswAfCN23ge', + }, + { + type: ArticleType.Blog, + url: `${EnvironmentConfig.TOPCODER_URLS.BLOG_PAGE}/building-a-tech-community-in-africa-with-code_abbey-the-topcoder-nation-show-17/`, + }, + { + type: ArticleType.Thrive, + url: '1E2IZxepkad3ol058XuoYd', + }, + { + type: ArticleType.Thrive, + url: '71YPNgNNrAsWVrgadbLOcD', + }, +] + +/** + * This array contains the default blog posts to be shown if the ones specified above are not available. + */ +export const defaultBlogs: Array = [ + { + contentSnippet: 'In light of the incredible speed of innovation, specialized tech talent has never been more critical to business success. Yet access to that talent remains frustratingly difficult for many companies. According to the Society for Human Resources Management, 83% of businesses are having trouble recruiting suitable candidates for their open positions, particularly when it comes […]\nThe post Talent as a Service (TaaS): A Brilliant Solution to the Talent Gap appeared first on Topcoder.', + creator: 'Kiran Hampapura', + featuredImage: `${EnvironmentConfig.TOPCODER_URLS.WP_CONTENT}/uploads/2019/11/taashero.jpg`, + link: `${EnvironmentConfig.TOPCODER_URLS.BLOG_PAGE}/talent-as-a-service-taas-a-brilliant-solution-to-the-talent-gap/`, + title: 'Talent as a Service (TaaS): A Brilliant Solution to the Talent Gap', + }, + { + contentSnippet: 'Can our Topcoder accounts be hacked? Can our well-earned cash be stolen away through the platform? Can customers suffer from intellectual theft? These sensitive questions belong to a discussion on a beyond-interesting topic: security. Honoring Topcoder’s security themed month, we want to raise awareness on what cyber security means for members and customers. We turned […]\nThe post Securing A Safe Work System For Members And Customers With John Wheeler - The Topcoder Nation Show #18 appeared first on Topcoder.', + creator: 'mahestro', + featuredImage: `${EnvironmentConfig.TOPCODER_URLS.WP_CONTENT}/uploads/2022/07/00-tcn-show-18-john-wheeler.png`, + link: `${EnvironmentConfig.TOPCODER_URLS.BLOG_PAGE}/securing-a-safe-work-system-for-members-and-customers-with-john-wheeler-the-topcoder-nation-show-18/`, + title: 'Securing A Safe Work System For Members And Customers With John Wheeler – The Topcoder Nation Show #18', + }, + { + contentSnippet: 'Job opportunities, upskilling, and mentoring are traits that identify the endeavor that this young gentleman is leading in Africa. Meet Abiodun (), born and raised in Lagos; he aims to close the gap between the tech talent in his region and opportunities, leveraging Topcoder as a medium to make it happen. Abiodun loves live music […]\nThe post Building A Tech Community In Africa With Code_Abbey – The Topcoder Nation Show #17 appeared first on Topcoder.', + creator: 'mahestro', + featuredImage: `${EnvironmentConfig.TOPCODER_URLS.WP_CONTENT}/uploads/2022/06/00-tcn-show-17-code_abby-and-gigs-in-africa.png`, + link: `${EnvironmentConfig.TOPCODER_URLS.BLOG_PAGE}/building-a-tech-community-in-africa-with-code_abbey-the-topcoder-nation-show-17/`, + title: 'Building A Tech Community In Africa With Code_Abbey – The Topcoder Nation Show #17', + }, + { + contentSnippet: 'CellPhoneService We just need to do the calculations described in the statement. One part of the calculations that may be tricky for beginners is the fee per each started minute of a call. If we have a call that takes S seconds, the number of minutes we’ll paying for can be computed by dividing S […]\nThe post Single Round Match 833 Editorials appeared first on Topcoder.', + creator: 'misof', + featuredImage: `${EnvironmentConfig.TOPCODER_URLS.WP_CONTENT}/uploads/2017/04/SRM_Blog.png`, + link: `${EnvironmentConfig.TOPCODER_URLS.BLOG_PAGE}/single-round-match-833-editorials/`, + title: 'Single Round Match 833 Editorials', + }, + { + contentSnippet: 'TwoDimensionalSort Imagine that we label rows of the board A to Z from top to bottom. If we got each rook X into its row X, the board would surely be sorted. With N rooks we can always achieve that in at most 2*N moves. In the first N moves we’ll move some rooks horizontally […]\nThe post TCO22 Round 3 Editorial appeared first on Topcoder.', + creator: 'misof', + featuredImage: `${EnvironmentConfig.TOPCODER_URLS.WP_CONTENT}/uploads/2017/04/SRM_Blog.png`, + link: `${EnvironmentConfig.TOPCODER_URLS.BLOG_PAGE}/tco22-round-3-editorial/`, + title: 'TCO22 Round 3 Editorial', + }, +] diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/index.tsx b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/index.tsx new file mode 100644 index 000000000..14d02b39b --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/index.tsx @@ -0,0 +1 @@ +export { default as DevCenterArticlesection } from './DevCenterArticlesSection' diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/models/articleentry.model.ts b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/models/articleentry.model.ts new file mode 100644 index 000000000..56d91937a --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/models/articleentry.model.ts @@ -0,0 +1,10 @@ +/** The type of the objects used to specy which articles should be shown inside articles.config.ts */ +export interface ArticleEntry { + type: ArticleType, + url: string, +} + +export enum ArticleType { + Blog = 'blog', + Thrive = 'thrive', +} diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/models/blogpost.model.ts b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/models/blogpost.model.ts new file mode 100644 index 000000000..69d249f4a --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/models/blogpost.model.ts @@ -0,0 +1,8 @@ +/** The type of the blog post retrieved from the api */ +export interface BlogPost { + contentSnippet: string + creator: string + featuredImage: string + link: string + title: string +} diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/models/index.ts b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/models/index.ts new file mode 100644 index 000000000..e612c6a52 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/models/index.ts @@ -0,0 +1,3 @@ +export * from './articleentry.model' +export * from './blogpost.model' +export * from './thrivearticle.model' diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/models/thrivearticle.model.ts b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/models/thrivearticle.model.ts new file mode 100644 index 000000000..47e84b5d4 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-articles-section/models/thrivearticle.model.ts @@ -0,0 +1,10 @@ +/** The type of the Thrive Articles retrieved from Contentful */ +export interface ThriveArticle { + content: string + contentAuthor: Array<{ fields: { name: string; }; }> + featuredImage: { fields: { file: { url: string; }; title: string; }; } + readTime: string + slug: string + title: string + type?: string +} diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-card/DevCenterCard.module.scss b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-card/DevCenterCard.module.scss new file mode 100644 index 000000000..f13b28ca3 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-card/DevCenterCard.module.scss @@ -0,0 +1,59 @@ +@import '../../../../../../lib/styles/includes'; + +.card { + background-color: $black-5; + width: 100%; + position: relative; + border-radius: 8px; + overflow: hidden; + + .cornerImage { + position: absolute; + top: 0px; + right: 0px; + opacity: 0.1; + } + + .cardContainer { + margin-left: $space-xxxl; + margin-top: $space-xxxl; + margin-bottom: $space-xl; + display: flex; + flex-direction: row; + gap: $space-lg; + + + @include ltemd { + margin-top: $space-xl; + margin-left: $space-xl; + gap: 14px; + } + + .titleSection { + display: flex; + flex-direction: column; + + .title { + font-size: 32px; + line-height: 34px; + @include font-weight-medium; + + margin-bottom: $space-sm; + + @include ltemd { + font-size: 22px; + line-height: 24px; + } + } + + .summary { + margin-bottom: $space-lg; + + @include ltemd { + font-size: 14px; + line-height: 20px; + } + } + } + } +} \ No newline at end of file diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-card/DevCenterCard.tsx b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-card/DevCenterCard.tsx new file mode 100644 index 000000000..8fb46f93f --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-card/DevCenterCard.tsx @@ -0,0 +1,34 @@ +import classNames from 'classnames' +import { FC } from 'react' + +import styles from './DevCenterCard.module.scss' + +interface DevCenterCardProps { + button?: any + className?: string + cornerIcon: any + description: string + icon: any + title: string + titleClass: string +} + +const DevCenterCard: FC = ({ icon, cornerIcon, title, titleClass, description, button, className= '' }) => { + + return ( +
+
{cornerIcon}
+
+ {icon} +
+

{title}

+ {description} + {button && button} +
+
+ +
+ ) +} + +export default DevCenterCard diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-card/index.tsx b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-card/index.tsx new file mode 100644 index 000000000..07368b6e7 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-card/index.tsx @@ -0,0 +1 @@ +export { default as DevCenterCard } from './DevCenterCard' diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-get-started/DevCenterGetStarted.module.scss b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-get-started/DevCenterGetStarted.module.scss new file mode 100644 index 000000000..e673bc8f9 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-get-started/DevCenterGetStarted.module.scss @@ -0,0 +1,13 @@ +@import '../../../../../../lib/styles/includes'; + +.title { + @include font-black-100; + font-weight: 500; + font-size: 44px; + line-height: 44px; + + @include ltemd { + font-size: 27px; + line-height: 28px; + } +} diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-get-started/DevCenterGetStarted.tsx b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-get-started/DevCenterGetStarted.tsx new file mode 100644 index 000000000..e8af5157e --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-get-started/DevCenterGetStarted.tsx @@ -0,0 +1,17 @@ +import { FC } from 'react' + +import { ContentLayout } from '../../../../../../lib' + +import styles from './DevCenterGetStarted.module.scss' +import { GetStartedCardsContainer } from './GetStartedCardsContainer' + +const DevCenterGetStarted: FC = () => { + return ( + +

Getting Started

+ +
+ ) +} + +export default DevCenterGetStarted diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-get-started/GetStartedCardsContainer/GetStartedCardsContainer.module.scss b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-get-started/GetStartedCardsContainer/GetStartedCardsContainer.module.scss new file mode 100644 index 000000000..33dc5923f --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-get-started/GetStartedCardsContainer/GetStartedCardsContainer.module.scss @@ -0,0 +1,38 @@ +@import '../../../../../../../lib/styles/includes'; + +.container { + display: flex; + flex-direction: row; + justify-content: center; + margin-top: $space-xxxxl; + gap: $space-xxxxl; + + @include ltemd { + flex-direction: column; + align-items: center; + margin-top: $space-xxl; + } + + .communityTitle { + background: $tc-grad15; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + } + + .apiTitle { + background: $tc-grad14; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + } + + .comingSoon { + color: $blue-140; + } + + .button { + width: 125px; + } +} + diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-get-started/GetStartedCardsContainer/GetStartedCardsContainer.tsx b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-get-started/GetStartedCardsContainer/GetStartedCardsContainer.tsx new file mode 100644 index 000000000..b16310abf --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-get-started/GetStartedCardsContainer/GetStartedCardsContainer.tsx @@ -0,0 +1,32 @@ +import { FC } from 'react' + +import { Button } from '../../../../../../../lib' +import { ApiCornerIcon, ApiIcon, CommunityAppCornerIcon, CommunityAppIcon } from '../../../../../assets/i' +import { DevCenterCard } from '../../dev-center-card' + +import styles from './GetStartedCardsContainer.module.scss' + +const GetStartedCardsContainer: FC = () => { + return ( +
+ } + icon={} + title ='Community App' + titleClass={styles.communityTitle} + description='Learn about Topcoder Community App and run started code.' + button={
+ ) +} + +export default GetStartedCardsContainer diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-get-started/GetStartedCardsContainer/index.tsx b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-get-started/GetStartedCardsContainer/index.tsx new file mode 100644 index 000000000..046aded7b --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-get-started/GetStartedCardsContainer/index.tsx @@ -0,0 +1 @@ +export { default as GetStartedCardsContainer } from './GetStartedCardsContainer' diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-get-started/index.tsx b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-get-started/index.tsx new file mode 100644 index 000000000..7d7e5a09a --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-get-started/index.tsx @@ -0,0 +1 @@ +export { default as DevCenterGetStarted } from './DevCenterGetStarted' diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/DevCenterCarousel/DevCenterCarousel.module.scss b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/DevCenterCarousel/DevCenterCarousel.module.scss new file mode 100644 index 000000000..fe502f57e --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/DevCenterCarousel/DevCenterCarousel.module.scss @@ -0,0 +1,16 @@ +@import '../../../../../../../lib/styles/includes'; + +.container { + background: $black-5; + width: 624px; + border-radius: 8px; + overflow: hidden; + + @include md { + width: 100%; + } + + @include ltesm { + width: 100%; + } +} diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/DevCenterCarousel/DevCenterCarousel.tsx b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/DevCenterCarousel/DevCenterCarousel.tsx new file mode 100644 index 000000000..36c4f11a3 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/DevCenterCarousel/DevCenterCarousel.tsx @@ -0,0 +1,24 @@ +import { FC } from 'react' +import Carousel from 'react-elastic-carousel' + +import { CarouselContent } from '../carousel-content.config' +import { DevCenterCarouselItem } from '../DevCenterCarouselItem' + +import './carouselStyle.css' +import styles from './DevCenterCarousel.module.scss' + +const DevCenterCarousel: FC = () => { + return ( +
+ + {CarouselContent.map((item, key) => )} + +
+ ) +} + +export default DevCenterCarousel diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/DevCenterCarousel/carouselStyle.css b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/DevCenterCarousel/carouselStyle.css new file mode 100644 index 000000000..ec326ee00 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/DevCenterCarousel/carouselStyle.css @@ -0,0 +1,29 @@ +button.rec-dot{ + box-shadow: none; + background-color: #AAAAAA; + width: 12px; + height: 12px; +} + +button.rec-dot:hover, button.rec-dot:active, button.rec-dot:focus, button.rec-dot_active { + border: 2.2px solid #06D6A0; + background-color: transparent; + box-shadow: none; + width: 18px; + height: 18px; +} + +.rec .rec-slider-container{ + width: 100%; + margin: 0; +} + +.rec .rec-item-wrapper { + padding: 0; +} + +.rec .rec-pagination { + align-items: center; + margin-bottom: 24px; + min-height: 30px; +} diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/DevCenterCarousel/index.tsx b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/DevCenterCarousel/index.tsx new file mode 100644 index 000000000..d71748fa1 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/DevCenterCarousel/index.tsx @@ -0,0 +1 @@ +export { default as DevCenterCarousel } from './DevCenterCarousel' diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/DevCenterCarouselItem/DevCenterCarouselItem.module.scss b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/DevCenterCarouselItem/DevCenterCarouselItem.module.scss new file mode 100644 index 000000000..0bade3403 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/DevCenterCarouselItem/DevCenterCarouselItem.module.scss @@ -0,0 +1,38 @@ +@import '../../../../../../../lib/styles/includes'; + +.card { + padding-left: $space-xxl; + padding-right: $space-xxl; + width: 100%; + + @include ltemd { + padding-left: $space-lg; + padding-right: $space-lg; + } + + .titleContainer{ + margin-top: $space-xxxxl; + + @include ltemd { + margin-top: $space-xxl; + } + + .headline { + font-weight: 500; + font-size: 26px; + + text-align: left; + margin-bottom: $space-xs; + } + + .summary { + text-align: left; + display: block; + } + } + + .image { + margin-top: $space-xxl; + pointer-events: none; + } +} diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/DevCenterCarouselItem/DevCenterCarouselItem.tsx b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/DevCenterCarouselItem/DevCenterCarouselItem.tsx new file mode 100644 index 000000000..ac6b67ffe --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/DevCenterCarouselItem/DevCenterCarouselItem.tsx @@ -0,0 +1,22 @@ +import classNames from 'classnames' +import React, {FC} from 'react' + +import { DevCenterTag } from '../../dev-center-tag' +import { CarouselItem } from '../carousel-content.config' + +import styles from './DevCenterCarouselItem.module.scss' + +const DevCenterCarouselItem: FC<{ item: CarouselItem }> = ({item}) => { + return ( +
+
+ {item.isNewFeature && } +

{item.headline}

+ {item.summary} +
+ +
+ ) +} + +export default DevCenterCarouselItem diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/DevCenterCarouselItem/index.tsx b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/DevCenterCarouselItem/index.tsx new file mode 100644 index 000000000..a3575ed8a --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/DevCenterCarouselItem/index.tsx @@ -0,0 +1 @@ +export {default as DevCenterCarouselItem} from './DevCenterCarouselItem' diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/DevCenterHeader.module.scss b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/DevCenterHeader.module.scss new file mode 100644 index 000000000..a65eeb536 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/DevCenterHeader.module.scss @@ -0,0 +1,70 @@ +@import '../../../../../../lib/styles/includes'; + +.outerContainer { + width: 100%; + min-height: 535px; + background-image: url("Header BG.png"); + background-size: 100% 535px; + background-repeat: no-repeat; + + @include ltemd { + background-size: 100% 400px; + } + + .innerContainer { + display: flex; + width: 100%; + justify-content: space-evenly; + + @include lg { + flex-direction: column; + align-items: center; + margin-bottom: 32px; + + } + + @include ltemd { + flex-direction: column; + align-items: center; + + margin-bottom: 32px; + } + + .leftContent { + + .title { + @include font-tc-white; + font-size: 80px; + line-height: 72px; + padding-top: 88px; + + @include ltemd { + font-size: 42px; + line-height: 40px; + padding-top: $space-xxl; + } + } + + .subtitle { + margin-top: $space-xxl; + display: block; + @include font-tc-white; + line-height: 20px; + letter-spacing: 0.5px; + text-transform: capitalize; + @include font-weight-medium; + } + } + + .rightContent { + margin-top: $space-xxxxl; + + @include ltemd { + text-align: center; + align-items: center; + width: 100%; + } + } + } +} + diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/DevCenterHeader.tsx b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/DevCenterHeader.tsx new file mode 100644 index 000000000..3cdbd0921 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/DevCenterHeader.tsx @@ -0,0 +1,29 @@ +import classNames from 'classnames' +import { FC } from 'react' + +import { ContentLayout } from '../../../../../../lib' + +import DevCenterCarousel from './DevCenterCarousel/DevCenterCarousel' +import styles from './DevCenterHeader.module.scss' + +const DevCenterHeader: FC<{}> = () => { + return ( +
+ +
+
+

+ TopCoder
+ Developer Center +

+ Let's build together with millions of Topcoder developers around the world. +
+
+ +
+
+
+
) +} + +export default DevCenterHeader diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/Header BG.png b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/Header BG.png new file mode 100644 index 000000000..ae4b95c4b Binary files /dev/null and b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/Header BG.png differ diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/carousel-content.config.ts b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/carousel-content.config.ts new file mode 100644 index 000000000..a4e0a1d1d --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/carousel-content.config.ts @@ -0,0 +1,48 @@ +import CodeImage from '../../../../carousel-images/Code.png' + +/** + * This is the interface implemented by the data + * of every item in the Carousel + */ +export interface CarouselItem { + headline: string + image: string + isNewFeature?: boolean + summary: string +} + +/** + * Each item in the array represent a screen of the carousel and should contain: + * - headline: the title of the screen + * - summary: a short description of what is represented in this screen + * - image: the link to the image to be shown in this screen + * - isNewFeature: true if the screen should have the "NEW FEATURE" tag, false otherwise + */ +export const CarouselContent: Array = [ + { + headline: 'Introducing new feature: API Explorer', + image: CodeImage, + isNewFeature: true, + summary: 'Now You Can Try Topcoder API Methods Without Writing Code.', + }, + { + headline: 'Lorem ipsum dolor sit amet', + image: CodeImage, + summary: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, minim veniam', + }, + { + headline: 'Lorem ipsum dolor sit amet', + image: CodeImage, + summary: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed dominim veniam', + }, + { + headline: 'Lorem ipsum dolor sit amet', + image: CodeImage, + summary: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed dominim veniam', + }, + { + headline: 'Lorem ipsum dolor sit amet', + image: CodeImage, + summary: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed dominim veniam', + }, + ] diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/index.tsx b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/index.tsx new file mode 100644 index 000000000..d9a2d51dc --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-header/index.tsx @@ -0,0 +1 @@ +export { default as DevCenterHeader } from './DevCenterHeader' diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-tag/DevCenterTag.module.scss b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-tag/DevCenterTag.module.scss new file mode 100644 index 000000000..90e52f2f1 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-tag/DevCenterTag.module.scss @@ -0,0 +1,19 @@ +@import '../../../../../../lib/styles/includes'; + +.tag { + background-color: $green-140; + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + padding: 3px 3px; + + width: fit-content; + height: 16px; + + border-radius: 2px; + + .text { + @include font-weight-medium; + } +} diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-tag/DevCenterTag.tsx b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-tag/DevCenterTag.tsx new file mode 100644 index 000000000..07baa5394 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-tag/DevCenterTag.tsx @@ -0,0 +1,18 @@ +import classNames from 'classnames' +import { FC } from 'react' + +import styles from './DevCenterTag.module.scss' + +interface TagProps { + text: string +} + +const DevCenterTag: FC = ({ text }) => { + return ( +
+ {text} +
+ ) +} + +export default DevCenterTag diff --git a/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-tag/index.tsx b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-tag/index.tsx new file mode 100644 index 000000000..b421408d9 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center-pages/community-app/landing-page/dev-center-tag/index.tsx @@ -0,0 +1 @@ +export { default as DevCenterTag } from './DevCenterTag' diff --git a/src-ts/tools/dev-center/dev-center.routes.tsx b/src-ts/tools/dev-center/dev-center.routes.tsx new file mode 100644 index 000000000..24f8d2884 --- /dev/null +++ b/src-ts/tools/dev-center/dev-center.routes.tsx @@ -0,0 +1,23 @@ +import { PlatformRoute } from '../../lib' + +import GettingStartedGuide from './dev-center-pages/community-app/getting-started/GettingStartedGuide' +import DevCenterLandingPage from './dev-center-pages/community-app/landing-page/DevCenterLandingPage' +import DevCenter, { toolTitle } from './DevCenter' + +export const devCenterRoutes: Array = [ + { + children: [ + { + element: , + route: '/getting-started', + }, + { + element: , + route: '/', + }, + ], + element: , + route: '/dev-center', + title: toolTitle, + }, +] diff --git a/src-ts/tools/dev-center/images/ChallengeListing.png b/src-ts/tools/dev-center/images/ChallengeListing.png new file mode 100644 index 000000000..4202c237a Binary files /dev/null and b/src-ts/tools/dev-center/images/ChallengeListing.png differ diff --git a/src-ts/tools/dev-center/images/Git1.png b/src-ts/tools/dev-center/images/Git1.png new file mode 100644 index 000000000..90a6e4c2d Binary files /dev/null and b/src-ts/tools/dev-center/images/Git1.png differ diff --git a/src-ts/tools/dev-center/images/Git10.png b/src-ts/tools/dev-center/images/Git10.png new file mode 100644 index 000000000..1ebf26efc Binary files /dev/null and b/src-ts/tools/dev-center/images/Git10.png differ diff --git a/src-ts/tools/dev-center/images/Git2.png b/src-ts/tools/dev-center/images/Git2.png new file mode 100644 index 000000000..3e4f5e180 Binary files /dev/null and b/src-ts/tools/dev-center/images/Git2.png differ diff --git a/src-ts/tools/dev-center/images/Git3.png b/src-ts/tools/dev-center/images/Git3.png new file mode 100644 index 000000000..d65faa4ea Binary files /dev/null and b/src-ts/tools/dev-center/images/Git3.png differ diff --git a/src-ts/tools/dev-center/images/Git4.png b/src-ts/tools/dev-center/images/Git4.png new file mode 100644 index 000000000..4be3984f4 Binary files /dev/null and b/src-ts/tools/dev-center/images/Git4.png differ diff --git a/src-ts/tools/dev-center/images/Git5.png b/src-ts/tools/dev-center/images/Git5.png new file mode 100644 index 000000000..b2252cbd5 Binary files /dev/null and b/src-ts/tools/dev-center/images/Git5.png differ diff --git a/src-ts/tools/dev-center/images/Git6.png b/src-ts/tools/dev-center/images/Git6.png new file mode 100644 index 000000000..9dd39d03a Binary files /dev/null and b/src-ts/tools/dev-center/images/Git6.png differ diff --git a/src-ts/tools/dev-center/images/Git7.png b/src-ts/tools/dev-center/images/Git7.png new file mode 100644 index 000000000..099866f73 Binary files /dev/null and b/src-ts/tools/dev-center/images/Git7.png differ diff --git a/src-ts/tools/dev-center/images/Git8.png b/src-ts/tools/dev-center/images/Git8.png new file mode 100644 index 000000000..9f18a836c Binary files /dev/null and b/src-ts/tools/dev-center/images/Git8.png differ diff --git a/src-ts/tools/dev-center/images/Git9.png b/src-ts/tools/dev-center/images/Git9.png new file mode 100644 index 000000000..a7d62234b Binary files /dev/null and b/src-ts/tools/dev-center/images/Git9.png differ diff --git a/src-ts/tools/dev-center/images/InitialLoginInChrome.png b/src-ts/tools/dev-center/images/InitialLoginInChrome.png new file mode 100644 index 000000000..1b36e9a03 Binary files /dev/null and b/src-ts/tools/dev-center/images/InitialLoginInChrome.png differ diff --git a/src-ts/tools/dev-center/images/PrivateConnectionWarning.png b/src-ts/tools/dev-center/images/PrivateConnectionWarning.png new file mode 100644 index 000000000..310a88318 Binary files /dev/null and b/src-ts/tools/dev-center/images/PrivateConnectionWarning.png differ diff --git a/src-ts/tools/dev-center/images/Python1.png b/src-ts/tools/dev-center/images/Python1.png new file mode 100644 index 000000000..16f5ca355 Binary files /dev/null and b/src-ts/tools/dev-center/images/Python1.png differ diff --git a/src-ts/tools/dev-center/images/Python2.png b/src-ts/tools/dev-center/images/Python2.png new file mode 100644 index 000000000..2ae6bcd43 Binary files /dev/null and b/src-ts/tools/dev-center/images/Python2.png differ diff --git a/src-ts/tools/dev-center/images/Python3.png b/src-ts/tools/dev-center/images/Python3.png new file mode 100644 index 000000000..64b4bb464 Binary files /dev/null and b/src-ts/tools/dev-center/images/Python3.png differ diff --git a/src-ts/tools/dev-center/images/Python4.png b/src-ts/tools/dev-center/images/Python4.png new file mode 100644 index 000000000..dd467c1d0 Binary files /dev/null and b/src-ts/tools/dev-center/images/Python4.png differ diff --git a/src-ts/tools/dev-center/images/Python5.png b/src-ts/tools/dev-center/images/Python5.png new file mode 100644 index 000000000..3b600af39 Binary files /dev/null and b/src-ts/tools/dev-center/images/Python5.png differ diff --git a/src-ts/tools/dev-center/images/SuccessfulLogin.png b/src-ts/tools/dev-center/images/SuccessfulLogin.png new file mode 100644 index 000000000..d39e2f085 Binary files /dev/null and b/src-ts/tools/dev-center/images/SuccessfulLogin.png differ diff --git a/src-ts/tools/dev-center/images/VSCommunity0.png b/src-ts/tools/dev-center/images/VSCommunity0.png new file mode 100644 index 000000000..fe973857d Binary files /dev/null and b/src-ts/tools/dev-center/images/VSCommunity0.png differ diff --git a/src-ts/tools/dev-center/images/VSCommunity1.png b/src-ts/tools/dev-center/images/VSCommunity1.png new file mode 100644 index 000000000..ee814ac57 Binary files /dev/null and b/src-ts/tools/dev-center/images/VSCommunity1.png differ diff --git a/src-ts/tools/dev-center/images/VSCommunity2.png b/src-ts/tools/dev-center/images/VSCommunity2.png new file mode 100644 index 000000000..e35818d3f Binary files /dev/null and b/src-ts/tools/dev-center/images/VSCommunity2.png differ diff --git a/src-ts/tools/dev-center/images/VSCommunity3.png b/src-ts/tools/dev-center/images/VSCommunity3.png new file mode 100644 index 000000000..3e8115411 Binary files /dev/null and b/src-ts/tools/dev-center/images/VSCommunity3.png differ diff --git a/src-ts/tools/dev-center/index.ts b/src-ts/tools/dev-center/index.ts new file mode 100644 index 000000000..c2175953e --- /dev/null +++ b/src-ts/tools/dev-center/index.ts @@ -0,0 +1 @@ +export * from './dev-center.routes' diff --git a/src-ts/tools/dev-center/styles/_variables.scss b/src-ts/tools/dev-center/styles/_variables.scss new file mode 100644 index 000000000..a4ba615cd --- /dev/null +++ b/src-ts/tools/dev-center/styles/_variables.scss @@ -0,0 +1,3 @@ +@import "../../../lib/styles/includes"; + +$side-nav-width: 353px; diff --git a/src-ts/tools/learn/course-certificate/certificate-view/CertificateView.module.scss b/src-ts/tools/learn/course-certificate/certificate-view/CertificateView.module.scss index 8e0777cc5..2a70f940c 100644 --- a/src-ts/tools/learn/course-certificate/certificate-view/CertificateView.module.scss +++ b/src-ts/tools/learn/course-certificate/certificate-view/CertificateView.module.scss @@ -1,8 +1,8 @@ @import '../../../../lib/styles/includes'; .wrap { - padding-top: $pad-xxxxl; - padding-bottom: calc($pad-xxxxl + $pad-xs); + padding-top: $space-xxxxl; + padding-bottom: calc($space-xxxxl + $space-xs); flex: 99 1 auto; display: flex; @@ -16,7 +16,7 @@ width: 100%; justify-content: center; - gap: $pad-xxxxl; + gap: $space-xxxxl; @include ltemd { flex-direction: column; @@ -29,7 +29,7 @@ flex-direction: column; align-items: center; - gap: $pad-sm; + gap: $space-sm; &:last-child { margin-top: auto; @@ -63,7 +63,7 @@ align-items: center; justify-content: center; - padding: $pad-sm; + padding: $space-sm; &:hover { background: transparent; diff --git a/src-ts/tools/learn/course-certificate/certificate-view/action-button/ActionButton.module.scss b/src-ts/tools/learn/course-certificate/certificate-view/action-button/ActionButton.module.scss index e962a416f..a80e1bf89 100644 --- a/src-ts/tools/learn/course-certificate/certificate-view/action-button/ActionButton.module.scss +++ b/src-ts/tools/learn/course-certificate/certificate-view/action-button/ActionButton.module.scss @@ -11,7 +11,7 @@ align-items: center; justify-content: center; - padding: $pad-sm; + padding: $space-sm; cursor: pointer; diff --git a/src-ts/tools/learn/course-certificate/certificate-view/certificate/Certificate.module.scss b/src-ts/tools/learn/course-certificate/certificate-view/certificate/Certificate.module.scss index f8086d64f..025b44e2b 100644 --- a/src-ts/tools/learn/course-certificate/certificate-view/certificate/Certificate.module.scss +++ b/src-ts/tools/learn/course-certificate/certificate-view/certificate/Certificate.module.scss @@ -8,7 +8,7 @@ .details { width: 55%; - padding: calc($pad-mx + $pad-lg); + padding: calc($space-mx + $space-lg); display: flex; flex-direction: column; @@ -23,7 +23,7 @@ font-size: 48px; line-height: 50px; color: $tc-black; - margin-top: $pad-sm; + margin-top: $space-sm; } h1 { @@ -78,13 +78,13 @@ } .username { - margin-top: calc($pad-mx + $pad-sm); + margin-top: calc($space-mx + $space-sm); } .tc-handle { color: $turq-140; - margin-top: $pad-xl; + margin-top: $space-xl; } .badges { @@ -131,7 +131,7 @@ .divider { width: $border; background: $black-10; - margin: 0 $pad-xxxxl; + margin: 0 $space-xxxxl; } .vendor { @@ -144,7 +144,7 @@ } .vendor-logo { - margin-top: $pad-sm; + margin-top: $space-sm; display: flex; justify-content: flex-end; diff --git a/src-ts/tools/learn/course-certificate/certificate-view/certificate/course-card/CourseCard.module.scss b/src-ts/tools/learn/course-certificate/certificate-view/certificate/course-card/CourseCard.module.scss index 502595bf2..f15f09a95 100644 --- a/src-ts/tools/learn/course-certificate/certificate-view/certificate/course-card/CourseCard.module.scss +++ b/src-ts/tools/learn/course-certificate/certificate-view/certificate/course-card/CourseCard.module.scss @@ -1,7 +1,7 @@ @import '../../../../../../lib/styles/includes'; .wrap { - border-radius: $pad-sm; + border-radius: $space-sm; width: 100%; width: 264px; background: rgba($tc-white, 0.12); @@ -22,21 +22,21 @@ } .course-title { - margin-top: $pad-lg; + margin-top: $space-lg; } .top-wrap { background: url(./wave-bg.png) 0 0 no-repeat; background-size: 264px 600px; - padding: $pad-xxl; + padding: $space-xxl; min-height: 264px; } .details { display: flex; align-items: center; - padding: $pad-xxl; - gap: calc($pad-sm + $border); + padding: $space-xxl; + gap: calc($space-sm + $border); svg { @include icon-xl; diff --git a/src-ts/tools/learn/course-completed/CourseCompletedPage.module.scss b/src-ts/tools/learn/course-completed/CourseCompletedPage.module.scss index cfad1aa06..b2509ea56 100755 --- a/src-ts/tools/learn/course-completed/CourseCompletedPage.module.scss +++ b/src-ts/tools/learn/course-completed/CourseCompletedPage.module.scss @@ -8,7 +8,7 @@ .main-wrap { height: calc($content-height - $breadcrumb-height); width: 100%; - margin-bottom: -$pad-lg; + margin-bottom: -$space-lg; background: $tc-white; display: flex; @@ -17,7 +17,7 @@ @include ltemd { flex-direction: column; - gap: $pad-lg; + gap: $space-lg; height: auto; } } @@ -27,7 +27,7 @@ display: flex; flex-direction: column; - padding-left: $pad-xxxxl; + padding-left: $space-xxxxl; overflow: auto; @include ltemd { @@ -36,7 +36,7 @@ } .content-wrap { - padding: $pad-mx 0 $pad-xxxxl; + padding: $space-mx 0 $space-xxxxl; position: relative; flex: 1; @include contentWidth; @@ -44,11 +44,11 @@ margin: 0 auto; p { - margin-top: $pad-xxl; + margin-top: $space-xxl; } :global(.body-large) { - margin-bottom: $pad-xxl; + margin-bottom: $space-xxl; } @include ltemd { @@ -59,8 +59,8 @@ .btns-wrap { display: flex; align-items: center; - gap: $pad-lg $pad-sm; - margin-top: $pad-xxl; + gap: $space-lg $space-sm; + margin-top: $space-xxl; flex-wrap: wrap; } diff --git a/src-ts/tools/learn/course-details/CourseDetailsPage.module.scss b/src-ts/tools/learn/course-details/CourseDetailsPage.module.scss index 888f729db..96aa7ad71 100644 --- a/src-ts/tools/learn/course-details/CourseDetailsPage.module.scss +++ b/src-ts/tools/learn/course-details/CourseDetailsPage.module.scss @@ -2,8 +2,8 @@ @import '../../../lib/styles/includes'; .wrap { - padding: $pad-mx 0 $pad-xxxxl; - gap: $pad-xxxxl; + padding: $space-mx 0 $space-xxxxl; + gap: $space-xxxxl; position: relative; flex: 1; @@ -36,7 +36,7 @@ flex: 1 1 auto; .text { @extend .body-main; - margin-top: $pad-xxl; + margin-top: $space-xxl; } } @@ -45,20 +45,20 @@ flex: 1 1 auto; .text { @extend .body-main; - margin-top: $pad-xxl; + margin-top: $space-xxl; } p { - margin: $pad-sm 0; + margin: $space-sm 0; } } .coming-soon { - margin-top: $pad-xxxxl; + margin-top: $space-xxxxl; } .credits-link { - padding-bottom: $pad-xxl; + padding-bottom: $space-xxl; a { @extend .quote-small; @@ -70,7 +70,7 @@ } svg { @include icon-md; - margin-left: $pad-xs; + margin-left: $space-xs; flex: 0 0 auto; } } diff --git a/src-ts/tools/learn/course-details/course-curriculum/CourseCurriculum.module.scss b/src-ts/tools/learn/course-details/course-curriculum/CourseCurriculum.module.scss index b50f79730..9cbed4ef2 100644 --- a/src-ts/tools/learn/course-details/course-curriculum/CourseCurriculum.module.scss +++ b/src-ts/tools/learn/course-details/course-curriculum/CourseCurriculum.module.scss @@ -2,18 +2,18 @@ .wrap { background: $tc-grad15; - padding: $pad-xxxxl; - border-radius: $pad-sm; + padding: $space-xxxxl; + border-radius: $space-sm; color: $tc-white; display: flex; flex-direction: column; - gap: $pad-xxl; + gap: $space-xxl; @include ltelg { - padding: $pad-lg; - gap: $pad-lg; + padding: $space-lg; + gap: $space-lg; } } @@ -23,7 +23,7 @@ svg { @include icon-size(60); - margin-right: $pad-sm; + margin-right: $space-sm; path { fill: url(#lh-paint-02); } @@ -31,7 +31,7 @@ } .bottom-link { - margin-top: $pad-xxxxl; + margin-top: $space-xxxxl; } .course-outline { diff --git a/src-ts/tools/learn/course-details/course-curriculum/curriculum-summary/CurriculumSummary.module.scss b/src-ts/tools/learn/course-details/course-curriculum/curriculum-summary/CurriculumSummary.module.scss index 3bad4fdda..180ef3eae 100644 --- a/src-ts/tools/learn/course-details/course-curriculum/curriculum-summary/CurriculumSummary.module.scss +++ b/src-ts/tools/learn/course-details/course-curriculum/curriculum-summary/CurriculumSummary.module.scss @@ -2,21 +2,21 @@ @import '../../../../../lib/styles/includes'; .wrap { - padding: $pad-xxl; - border-radius: $pad-sm; + padding: $space-xxl; + border-radius: $space-sm; background: $tc-white; display: flex; flex-direction: column; - gap: $pad-lg; + gap: $space-lg; @include ltelg { - padding: $pad-lg; - gap: $pad-sm; + padding: $space-lg; + gap: $space-sm; } @include ltemd { - gap: $pad-lg; + gap: $space-lg; } } @@ -31,17 +31,17 @@ .summary { display: flex; - gap: $pad-lg; + gap: $space-lg; align-items: center; justify-content: space-between; flex-wrap: wrap; @include ltelg { - gap: $pad-sm; + gap: $space-sm; } @include ltemd { justify-content: center; - gap: $pad-lg; + gap: $space-lg; } } diff --git a/src-ts/tools/learn/course-details/promo-course/PromoCourse.module.scss b/src-ts/tools/learn/course-details/promo-course/PromoCourse.module.scss index 4720f307c..284f61825 100644 --- a/src-ts/tools/learn/course-details/promo-course/PromoCourse.module.scss +++ b/src-ts/tools/learn/course-details/promo-course/PromoCourse.module.scss @@ -3,21 +3,21 @@ .wrap { background: $black-5; - border-radius: $pad-sm; + border-radius: $space-sm; - padding: $pad-xxxxl; - gap: $pad-xxxxl; + padding: $space-xxxxl; + gap: $space-xxxxl; display: flex; flex-direction: column; @include ltemd { - padding: $pad-lg; - gap: $pad-sm; + padding: $space-lg; + gap: $space-sm; } } .text-content { > *:not(:first-child) { - margin-top: $pad-sm; + margin-top: $space-sm; } h4 { @@ -26,7 +26,7 @@ } .course-path-steps { - margin-top: $pad-sm; + margin-top: $space-sm; svg { width: 100%; display: block; @@ -38,7 +38,7 @@ @include ltemd { display: flex; flex-direction: column; - gap: $pad-lg; + gap: $space-lg; align-items: stretch; } } \ No newline at end of file diff --git a/src-ts/tools/learn/free-code-camp/FreeCodeCamp.module.scss b/src-ts/tools/learn/free-code-camp/FreeCodeCamp.module.scss index e611ae16c..abf59cf76 100644 --- a/src-ts/tools/learn/free-code-camp/FreeCodeCamp.module.scss +++ b/src-ts/tools/learn/free-code-camp/FreeCodeCamp.module.scss @@ -8,7 +8,7 @@ .main-wrap { height: calc($content-height - $breadcrumb-height); width: 100%; - margin-bottom: -$pad-lg; + margin-bottom: -$space-lg; background: $tc-white; display: flex; @@ -17,7 +17,7 @@ @include ltemd { flex-direction: column; - gap: $pad-lg; + gap: $space-lg; height: auto; flex: 99 1 auto; margin-bottom: 0; @@ -29,12 +29,12 @@ display: flex; flex-direction: column; - padding-left: $pad-xxxxl; + padding-left: $space-xxxxl; hr { - margin-left: $pad-xxxxl; - margin-right: $pad-xxxxl; - width: calc(100% - 2 * $pad-xxxxl); + margin-left: $space-xxxxl; + margin-right: $space-xxxxl; + width: calc(100% - 2 * $space-xxxxl); } @include ltemd { @@ -42,9 +42,9 @@ flex: 1 1 auto; hr { - margin-left: $pad-lg; - margin-right: $pad-lg; - width: calc(100% - 2 * $pad-lg); + margin-left: $space-lg; + margin-right: $space-lg; + width: calc(100% - 2 * $space-lg); } } } @@ -75,5 +75,5 @@ .course-outline-title { @extend .body-main-bold; flex: 0 0 auto; - margin-bottom: $pad-xl; + margin-bottom: $space-xl; } \ No newline at end of file diff --git a/src-ts/tools/learn/free-code-camp/title-nav/TitleNav.module.scss b/src-ts/tools/learn/free-code-camp/title-nav/TitleNav.module.scss index 2c230a33a..9b7d6a249 100755 --- a/src-ts/tools/learn/free-code-camp/title-nav/TitleNav.module.scss +++ b/src-ts/tools/learn/free-code-camp/title-nav/TitleNav.module.scss @@ -4,12 +4,12 @@ display: flex; align-items: center; @include pagePaddings; - padding-top: $pad-lg; + padding-top: $space-lg; padding-bottom: 0; @include ltemd { flex-direction: column; - gap: $pad-sm; + gap: $space-sm; } } @@ -20,7 +20,7 @@ display: flex; align-items: center; - gap: $pad-sm; + gap: $space-sm; :global(.overline) { white-space: nowrap; diff --git a/src-ts/tools/learn/learn-lib/collapsible-pane/CollapsiblePane.module.scss b/src-ts/tools/learn/learn-lib/collapsible-pane/CollapsiblePane.module.scss index 0b2d658f2..dbc0ded06 100644 --- a/src-ts/tools/learn/learn-lib/collapsible-pane/CollapsiblePane.module.scss +++ b/src-ts/tools/learn/learn-lib/collapsible-pane/CollapsiblePane.module.scss @@ -27,13 +27,13 @@ .pane-outline { width: 32px; height: 100%; - border-radius: 0 $pad-lg $pad-lg 0; - padding: $pad-lg 0; + border-radius: 0 $space-lg $space-lg 0; + padding: $space-lg 0; background: $blue-140; display: flex; align-items: center; - gap: $pad-sm; + gap: $space-sm; color: $tc-white; @@ -54,8 +54,8 @@ @include ltemd { width: 100%; height: auto; - padding: $pad-sm $pad-lg; - border-radius: 0 0 $pad-lg $pad-lg; + padding: $space-sm $space-lg; + border-radius: 0 0 $space-lg $space-lg; margin-top: -1px; svg { @@ -66,7 +66,7 @@ .content { background: $tc-grad15; - padding: $pad-lg; + padding: $space-lg; color: $tc-white; overflow: auto; diff --git a/src-ts/tools/learn/learn-lib/course-outline/CourseOutline.module.scss b/src-ts/tools/learn/learn-lib/course-outline/CourseOutline.module.scss index 68e7ae4de..fe91544af 100644 --- a/src-ts/tools/learn/learn-lib/course-outline/CourseOutline.module.scss +++ b/src-ts/tools/learn/learn-lib/course-outline/CourseOutline.module.scss @@ -4,7 +4,7 @@ .wrap { display: flex; flex-direction: column; - gap: $pad-lg; + gap: $space-lg; position: relative; @@ -19,7 +19,7 @@ display: flex; flex-direction: column; - gap: $pad-lg; + gap: $space-lg; @include scrollbar; padding-right: 5px; diff --git a/src-ts/tools/learn/learn-lib/course-outline/collapsible-item/CollapsibleItem.module.scss b/src-ts/tools/learn/learn-lib/course-outline/collapsible-item/CollapsibleItem.module.scss index 06fe8b210..222444852 100644 --- a/src-ts/tools/learn/learn-lib/course-outline/collapsible-item/CollapsibleItem.module.scss +++ b/src-ts/tools/learn/learn-lib/course-outline/collapsible-item/CollapsibleItem.module.scss @@ -8,7 +8,7 @@ .title-row { display: flex; align-items: flex-start; - gap: calc($pad-sm + $border); + gap: calc($space-sm + $border); cursor: pointer; > span { @@ -25,8 +25,8 @@ :global(.status-checkbox) { margin-top: 0; - width: $pad-xxl; - height: $pad-xxl; + width: $space-xxl; + height: $space-xxl; &:global(.completed) { color: $turq-75; @@ -38,20 +38,20 @@ display: inline-block; color: $blue-140; background: $tc-white; - padding: calc($border + $border-xs) $pad-xs; + padding: calc($border + $border-xs) $space-xs; border-radius: $border; text-transform: uppercase; line-height: 10px; - margin-top: $pad-xs; - margin-right: calc($pad-sm + $border); + margin-top: $space-xs; + margin-right: calc($space-sm + $border); @include ltemd { - margin-right: $pad-xs; + margin-right: $space-xs; } } .chevron { margin-left: auto; - width: $pad-xxl; + width: $space-xxl; flex: 0 0 auto; svg { @include icon-xxl; @@ -65,16 +65,16 @@ .content { margin-left: 34px; - padding-right: $pad-xxxxl; + padding-right: $space-xxxxl; @include ltemd { - padding-right: $pad-xxl; + padding-right: $space-xxl; } } .short-desc { - margin-top: $pad-sm; + margin-top: $space-sm; } .summary { @@ -89,7 +89,7 @@ width: 1px; height: 14px; background: $tc-white; - margin: 0 calc($pad-sm + $border); + margin: 0 calc($space-sm + $border); } } @@ -101,19 +101,19 @@ svg { width: 14px; height: 14px; - margin-right: calc($pad-xs + $border); + margin-right: calc($space-xs + $border); } } @include ltemd { - margin-top: $pad-md; + margin-top: $space-md; } } .list { display: flex; - gap: $pad-xs $pad-sm; + gap: $space-xs $space-sm; flex-wrap: wrap; - margin-top: $pad-sm; + margin-top: $space-sm; } diff --git a/src-ts/tools/learn/learn-lib/course-title/CourseTitle.module.scss b/src-ts/tools/learn/learn-lib/course-title/CourseTitle.module.scss index 7fc781d7b..1bb06110f 100644 --- a/src-ts/tools/learn/learn-lib/course-title/CourseTitle.module.scss +++ b/src-ts/tools/learn/learn-lib/course-title/CourseTitle.module.scss @@ -3,18 +3,18 @@ .wrap { display: flex; - gap: $pad-lg; + gap: $space-lg; align-items: center; @include ltelg { - gap: $pad-sm; + gap: $space-sm; } @include ltemd { &:global(.xl) { flex-direction: column; text-align: center; - gap: $pad-lg; + gap: $space-lg; } } @@ -54,13 +54,13 @@ color: #767676; display: block; &:global(.lg) { - margin-top: $pad-sm; + margin-top: $space-sm; } } @include ltemd { :global(.quote-small.xl) { - margin-top: $pad-sm; + margin-top: $space-sm; } } } diff --git a/src-ts/tools/learn/learn-lib/curriculum-summary/CurriculumSummary.module.scss b/src-ts/tools/learn/learn-lib/curriculum-summary/CurriculumSummary.module.scss index 7f78294e3..73b93dfb4 100644 --- a/src-ts/tools/learn/learn-lib/curriculum-summary/CurriculumSummary.module.scss +++ b/src-ts/tools/learn/learn-lib/curriculum-summary/CurriculumSummary.module.scss @@ -3,7 +3,7 @@ .summary { display: flex; - gap: $pad-lg; + gap: $space-lg; align-items: center; flex-wrap: wrap; } @@ -37,11 +37,11 @@ .stat-item { display: flex; - gap: $pad-xs; + gap: $space-xs; align-items: center; > :global(.sub) { display: flex; - gap: $pad-xs; + gap: $space-xs; align-items: flex-end; } } diff --git a/src-ts/tools/learn/learn-lib/my-course-card/completed/Completed.module.scss b/src-ts/tools/learn/learn-lib/my-course-card/completed/Completed.module.scss index 6b00d9739..f651dc58e 100644 --- a/src-ts/tools/learn/learn-lib/my-course-card/completed/Completed.module.scss +++ b/src-ts/tools/learn/learn-lib/my-course-card/completed/Completed.module.scss @@ -3,10 +3,10 @@ .wrap { background: $tc-white; - padding: $pad-xxl; - border-radius: $pad-sm; + padding: $space-xxl; + border-radius: $space-sm; @include ltelg { - padding: $pad-lg; + padding: $space-lg; } } @@ -15,7 +15,7 @@ align-items: flex-start; flex-wrap: wrap; - margin-bottom: $pad-lg; + margin-bottom: $space-lg; } .completed-status { @@ -26,7 +26,7 @@ &:before { content: ""; display: inline-block; - margin: 2px $pad-sm -2px; + margin: 2px $space-sm -2px; width: 1px; height: 16px; background: $black-60; @@ -39,10 +39,10 @@ .buttons-wrap { display: flex; align-items: center; - gap: $pad-sm; + gap: $space-sm; flex-wrap: wrap; @include ltemd { - gap: $pad-lg; + gap: $space-lg; } } diff --git a/src-ts/tools/learn/learn-lib/my-course-card/in-progress/InProgress.module.scss b/src-ts/tools/learn/learn-lib/my-course-card/in-progress/InProgress.module.scss index 2b59ac2b2..1b525b6fd 100644 --- a/src-ts/tools/learn/learn-lib/my-course-card/in-progress/InProgress.module.scss +++ b/src-ts/tools/learn/learn-lib/my-course-card/in-progress/InProgress.module.scss @@ -3,18 +3,18 @@ .wrap { background: $tc-white; - padding: $pad-lg $pad-xxl; - border-radius: $pad-sm; + padding: $space-lg $space-xxl; + border-radius: $space-sm; display: flex; &.large { - padding: $pad-xxxxl; + padding: $space-xxxxl; } @include ltelg { &, &.large { - padding: $pad-lg; + padding: $space-lg; } } @@ -30,7 +30,7 @@ display: flex; flex-direction: column; align-items: flex-start; - gap: $pad-lg; + gap: $space-lg; } .line { @@ -40,7 +40,7 @@ width: 100%; @include ltelg { flex-wrap: wrap; - gap: $pad-lg; + gap: $space-lg; } } @@ -52,7 +52,7 @@ &:before { content: ""; display: inline-block; - margin: 2px $pad-sm -2px; + margin: 2px $space-sm -2px; width: 1px; height: 16px; background: $black-60; @@ -65,10 +65,10 @@ .summary { display: flex; align-items: center; - margin-top: $pad-lg; + margin-top: $space-lg; width: 100%; justify-content: space-between; - gap: $pad-lg; + gap: $space-lg; @include ltemd { flex-direction: column; align-items: flex-start; @@ -86,14 +86,14 @@ height: 100%; width: 1px; background: $black-10; - margin: 0 calc($pad-mx + $pad-sm); + margin: 0 calc($space-mx + $space-sm); } &-inner { display: flex; flex-direction: column; align-items: flex-start; - gap: $pad-sm; + gap: $space-sm; p { display: -webkit-box; @@ -103,14 +103,14 @@ } :global(.button) { - margin-top: $pad-sm; + margin-top: $space-sm; } } @include ltemd { flex-direction: column; &:before { - margin: $pad-xxl 0; + margin: $space-xxl 0; width: 100%; height: 1px; } diff --git a/src-ts/tools/learn/learn-lib/wave-hero/WaveHero.module.scss b/src-ts/tools/learn/learn-lib/wave-hero/WaveHero.module.scss index 7a38181e5..996cb752a 100755 --- a/src-ts/tools/learn/learn-lib/wave-hero/WaveHero.module.scss +++ b/src-ts/tools/learn/learn-lib/wave-hero/WaveHero.module.scss @@ -8,42 +8,42 @@ overflow: hidden; padding-bottom: 40px; @include ltelg { - background-size: 100vw $pad-lg, auto; - padding-bottom: $pad-lg; + background-size: 100vw $space-lg, auto; + padding-bottom: $space-lg; } &:global(.light) { background: url('./learn-welcome-bg-curve-white.png') repeat-x center bottom , $tc-grad15; background-size: 1440px 40px, auto; @include ltelg { - background-size: 100vw $pad-lg, auto; + background-size: 100vw $space-lg, auto; } } } &-inner { - padding: calc($pad-xxxxl + $pad-sm) 0 $pad-lg; + padding: calc($space-xxxxl + $space-sm) 0 $space-lg; @include contentWidth; @include ltelg { - padding-bottom: $pad-mx; + padding-bottom: $space-mx; } @include ltemd { - padding-top: $pad-xxl; - padding-bottom: $pad-xxl; + padding-top: $space-xxl; + padding-bottom: $space-xxl; } } &-content { display: flex; - gap: calc($pad-mx * 2); + gap: calc($space-mx * 2); color: $tc-white; @include ltelg { - gap: $pad-mx; + gap: $space-mx; } @include ltemd { - gap: $pad-xxl; + gap: $space-xxl; flex-direction: column; } } @@ -54,6 +54,6 @@ &-text { @extend .body-medium-normal; - margin-top: $pad-xxl; + margin-top: $space-xxl; } } diff --git a/src-ts/tools/learn/my-learning/MyLearning.module.scss b/src-ts/tools/learn/my-learning/MyLearning.module.scss index c0a505fd7..4f24c8cd7 100755 --- a/src-ts/tools/learn/my-learning/MyLearning.module.scss +++ b/src-ts/tools/learn/my-learning/MyLearning.module.scss @@ -27,7 +27,7 @@ svg { @include icon-size(60); - margin-right: $pad-sm; + margin-right: $space-sm; @include ltemd { @include icon-size(38); } @@ -35,8 +35,8 @@ } .courses-area { - padding: $pad-xxxxl 0; - gap: $pad-lg; + padding: $space-xxxxl 0; + gap: $space-lg; display: flex; flex-direction: column; position: relative; @@ -45,17 +45,17 @@ } @include ltemd { - gap: $pad-xxl; + gap: $space-xxl; } } .cards-wrap { display: flex; - gap: $pad-xxl; + gap: $space-xxl; flex-wrap: wrap; > * { - flex: 0 1 calc(50% - calc($pad-xxl / 2)); + flex: 0 1 calc(50% - calc($space-xxl / 2)); } @include ltemd { diff --git a/src-ts/tools/learn/my-learning/hero-card/HeroCard.module.scss b/src-ts/tools/learn/my-learning/hero-card/HeroCard.module.scss index e7160be73..9cc12d4cc 100755 --- a/src-ts/tools/learn/my-learning/hero-card/HeroCard.module.scss +++ b/src-ts/tools/learn/my-learning/hero-card/HeroCard.module.scss @@ -3,27 +3,27 @@ .wrap { background: $black-5; - border-radius: $pad-sm; - padding: $pad-xxl; + border-radius: $space-sm; + padding: $space-xxl; color: $black-100; display: flex; flex-direction: column; - gap: $pad-sm; + gap: $space-sm; width: 100%; :global(.button.link) { white-space: initial; } @include ltelg { - padding: $pad-lg; + padding: $space-lg; } } .line { display: flex; align-items: center; - gap: $pad-sm; + gap: $space-sm; justify-content: flex-end; @include ltelg { flex-direction: column; diff --git a/src-ts/tools/learn/welcome/WelcomePage.module.scss b/src-ts/tools/learn/welcome/WelcomePage.module.scss index b841fd5ce..c00834ead 100644 --- a/src-ts/tools/learn/welcome/WelcomePage.module.scss +++ b/src-ts/tools/learn/welcome/WelcomePage.module.scss @@ -13,19 +13,19 @@ } .courses-section { - padding: $pad-xxxxl 0; + padding: $space-xxxxl 0; position: relative; @include ltemd { - padding-top: $pad-xxl; + padding-top: $space-xxl; } } .courses-list { - margin-top: $pad-lg; + margin-top: $space-lg; flex-wrap: wrap; - gap: $pad-lg; + gap: $space-lg; display: grid; grid-template-columns: repeat(4, 1fr); @@ -44,6 +44,6 @@ } @include ltemd { - margin-top: $pad-xxl; + margin-top: $space-xxl; } } \ No newline at end of file diff --git a/src-ts/tools/learn/welcome/courses-card/CoursesCard.module.scss b/src-ts/tools/learn/welcome/courses-card/CoursesCard.module.scss index a5e4f500d..019b1ea12 100644 --- a/src-ts/tools/learn/welcome/courses-card/CoursesCard.module.scss +++ b/src-ts/tools/learn/welcome/courses-card/CoursesCard.module.scss @@ -2,10 +2,10 @@ .wrap { background: $black-5; - border-radius: $pad-sm; - padding: $pad-xxl; + border-radius: $space-sm; + padding: $space-xxl; - gap: $pad-lg; + gap: $space-lg; display: flex; flex-direction: column; @@ -22,7 +22,7 @@ } @include ltemd { - padding: $pad-lg; + padding: $space-lg; } } diff --git a/src-ts/tools/learn/welcome/progress-block/ProgressBlock.module.scss b/src-ts/tools/learn/welcome/progress-block/ProgressBlock.module.scss index ad8703417..167346070 100644 --- a/src-ts/tools/learn/welcome/progress-block/ProgressBlock.module.scss +++ b/src-ts/tools/learn/welcome/progress-block/ProgressBlock.module.scss @@ -3,16 +3,16 @@ .wrap { background: $black-5; - border-radius: $pad-sm; - padding: $pad-xxl; + border-radius: $space-sm; + padding: $space-xxl; color: $black-100; display: flex; flex-direction: column; - gap: $pad-lg; + gap: $space-lg; width: 100%; @include ltemd { - padding: $pad-lg; + padding: $space-lg; } } diff --git a/src-ts/tools/learn/welcome/progress-block/no-progress/NoProgress.module.scss b/src-ts/tools/learn/welcome/progress-block/no-progress/NoProgress.module.scss index 3b1d99bb5..4348badf1 100644 --- a/src-ts/tools/learn/welcome/progress-block/no-progress/NoProgress.module.scss +++ b/src-ts/tools/learn/welcome/progress-block/no-progress/NoProgress.module.scss @@ -2,7 +2,7 @@ @import '../../../../../lib/styles/includes'; .wrap { - gap: $pad-lg; + gap: $space-lg; display: grid; color: $black-100; grid-template-areas: 'icon title' 'icon text'; @@ -33,6 +33,6 @@ .content-text { @extend .body-medium-normal; - margin-top: -1*$pad-sm; + margin-top: -1*$space-sm; grid-area: text; } diff --git a/src-ts/tools/learn/welcome/progress-block/progress-action/ProgressAction.module.scss b/src-ts/tools/learn/welcome/progress-block/progress-action/ProgressAction.module.scss index d00ffc894..f07899529 100644 --- a/src-ts/tools/learn/welcome/progress-block/progress-action/ProgressAction.module.scss +++ b/src-ts/tools/learn/welcome/progress-block/progress-action/ProgressAction.module.scss @@ -5,16 +5,16 @@ align-items: center; justify-content: space-between; flex-wrap: wrap; - gap: $pad-lg; + gap: $space-lg; svg { @include icon-mx; - margin-right: $pad-xs; + margin-right: $space-xs; } } .title { display: flex; align-items: center; - gap: $pad-md; + gap: $space-md; } diff --git a/src-ts/tools/tools.routes.ts b/src-ts/tools/tools.routes.ts index 3da5c58aa..d6c583e92 100644 --- a/src-ts/tools/tools.routes.ts +++ b/src-ts/tools/tools.routes.ts @@ -1,5 +1,6 @@ import { PlatformRoute } from '../lib' +import { devCenterRoutes } from './dev-center' import { learnRoutes } from './learn' import { workRoutes } from './work' @@ -7,6 +8,7 @@ const toolRoutes: Array = [ // NOTE: these will be displayed in the order they are defined in this array // TODO: support ordering ...workRoutes, + ...devCenterRoutes, ...learnRoutes, ] diff --git a/src-ts/tools/work/work-detail-details/work-detail-details-pane/WorkDetailDetailsPane.module.scss b/src-ts/tools/work/work-detail-details/work-detail-details-pane/WorkDetailDetailsPane.module.scss index 9a7812781..c54378ae7 100644 --- a/src-ts/tools/work/work-detail-details/work-detail-details-pane/WorkDetailDetailsPane.module.scss +++ b/src-ts/tools/work/work-detail-details/work-detail-details-pane/WorkDetailDetailsPane.module.scss @@ -4,7 +4,7 @@ display: flex; align-items: flex-end; cursor: pointer; - margin: $pad-xxl 0 $pad-xxxl 0; + margin: $space-xxl 0 $space-xxxl 0; .header-content { flex: 1; @@ -18,8 +18,8 @@ .link { color: $link-blue-dark; cursor: pointer; - margin-left: $pad-md; - margin-top: $pad-xs; + margin-left: $space-md; + margin-top: $space-xs; text-transform: none; &:hover { @@ -41,14 +41,14 @@ } .detail { - margin-bottom: $pad-xxl; + margin-bottom: $space-xxl; white-space: pre-wrap; @include font-black-100; .title { @include font-barlow; display: flex; - padding-bottom: $pad-sm; + padding-bottom: $space-sm; } .content { diff --git a/src-ts/tools/work/work-detail-details/work-detail-details-sidebar/WorkDetailDetailsSidebar.module.scss b/src-ts/tools/work/work-detail-details/work-detail-details-sidebar/WorkDetailDetailsSidebar.module.scss index 2536a40e1..a6ec4f180 100644 --- a/src-ts/tools/work/work-detail-details/work-detail-details-sidebar/WorkDetailDetailsSidebar.module.scss +++ b/src-ts/tools/work/work-detail-details/work-detail-details-sidebar/WorkDetailDetailsSidebar.module.scss @@ -2,10 +2,10 @@ .wrap { min-width: 323px; - padding-left: $pad-xxxxl; + padding-left: $space-xxxxl; border-left: $border-xs solid $black-10; - margin-left: $pad-xxxxl; + margin-left: $space-xxxxl; color: $black-100; } @@ -16,7 +16,7 @@ font-size: 14px; line-height: 14px; color: $turq-160; - margin-top: $pad-lg; + margin-top: $space-lg; cursor: pointer; text-transform: uppercase; } diff --git a/src-ts/tools/work/work-detail-header/WorkDetailHeader.module.scss b/src-ts/tools/work/work-detail-header/WorkDetailHeader.module.scss index 832a7d686..da0f5723b 100644 --- a/src-ts/tools/work/work-detail-header/WorkDetailHeader.module.scss +++ b/src-ts/tools/work/work-detail-header/WorkDetailHeader.module.scss @@ -4,12 +4,12 @@ display: flex; justify-content: space-between; align-items: center; - padding: $pad-xxxxl 0 $pad-xxl; - margin: 0 0 $pad-xxl; + padding: $space-xxxxl 0 $space-xxl; + margin: 0 0 $space-xxl; border-bottom: $border solid $black-10; .heading { - margin-right: $pad-xxxxl; + margin-right: $space-xxxxl; color: $black-100; } } diff --git a/src-ts/tools/work/work-detail-solutions/WorkDetailSolutions.module.scss b/src-ts/tools/work/work-detail-solutions/WorkDetailSolutions.module.scss index 1e911e4a5..ee673fe44 100644 --- a/src-ts/tools/work/work-detail-solutions/WorkDetailSolutions.module.scss +++ b/src-ts/tools/work/work-detail-solutions/WorkDetailSolutions.module.scss @@ -2,15 +2,15 @@ .wrap { display: block; - padding-bottom: $pad-xxxxl; + padding-bottom: $space-xxxxl; } .header { @include font-black-100; @include font-roboto; - margin-bottom: $pad-lg; + margin-bottom: $space-lg; p { - margin-top: $pad-sm; + margin-top: $space-sm; } } diff --git a/src-ts/tools/work/work-detail-solutions/work-solutions-list/WorkSolutionsList.module.scss b/src-ts/tools/work/work-detail-solutions/work-solutions-list/WorkSolutionsList.module.scss index 31cd92c3f..92fdc7755 100644 --- a/src-ts/tools/work/work-detail-solutions/work-solutions-list/WorkSolutionsList.module.scss +++ b/src-ts/tools/work/work-detail-solutions/work-solutions-list/WorkSolutionsList.module.scss @@ -14,8 +14,8 @@ align-items: center; justify-content: center; min-height: 507px; - padding: $pad-lg; + padding: $space-lg; text-align: center; background-color: $black-5; - border-radius: $pad-sm; + border-radius: $space-sm; } diff --git a/src-ts/tools/work/work-detail-solutions/work-solutions-list/work-solutions-list-item/WorkSolutionsListItem.module.scss b/src-ts/tools/work/work-detail-solutions/work-solutions-list/work-solutions-list-item/WorkSolutionsListItem.module.scss index 8f60d0f15..4a0212abf 100644 --- a/src-ts/tools/work/work-detail-solutions/work-solutions-list/work-solutions-list-item/WorkSolutionsListItem.module.scss +++ b/src-ts/tools/work/work-detail-solutions/work-solutions-list/work-solutions-list-item/WorkSolutionsListItem.module.scss @@ -8,10 +8,10 @@ display: flex; align-items: center; - gap: $pad-lg; + gap: $space-lg; position: relative; - padding: $pad-lg 0; + padding: $space-lg 0; border-top: $border-xs solid $black-10; &:last-child { @@ -33,7 +33,7 @@ .name { margin-right: auto; span + span { - margin-left: $pad-xs; + margin-left: $space-xs; } } } diff --git a/src-ts/tools/work/work-detail-summary/WorkDetailHighlights/WorkDetailHighlights.module.scss b/src-ts/tools/work/work-detail-summary/WorkDetailHighlights/WorkDetailHighlights.module.scss index f5a870e1b..8292041de 100644 --- a/src-ts/tools/work/work-detail-summary/WorkDetailHighlights/WorkDetailHighlights.module.scss +++ b/src-ts/tools/work/work-detail-summary/WorkDetailHighlights/WorkDetailHighlights.module.scss @@ -1,12 +1,12 @@ @import '../../../../lib/styles/includes'; @import '../../../../lib/styles/typography'; -$icon-size: calc($pad-xxl * 2); +$icon-size: calc($space-xxl * 2); .highlights-container { display: grid; grid-template-columns: repeat(5, 1fr); - margin-bottom: $pad-xxl; + margin-bottom: $space-xxl; .highlight { display: flex; @@ -15,7 +15,7 @@ $icon-size: calc($pad-xxl * 2); align-items: center; text-align: center; margin-right: calc($border-xs * -1); - padding: $pad-lg; + padding: $space-lg; border-left: $border-xs solid $black-10; border-right: $border-xs solid $black-10; @@ -33,7 +33,7 @@ $icon-size: calc($pad-xxl * 2); h4 { border: none; - padding: $pad-xl 0 0 0; + padding: $space-xl 0 0 0; } .info { diff --git a/src-ts/tools/work/work-detail-summary/WorkDetailProgress/WorkDetailProgress.module.scss b/src-ts/tools/work/work-detail-summary/WorkDetailProgress/WorkDetailProgress.module.scss index 27bed7650..ebd3a3a28 100644 --- a/src-ts/tools/work/work-detail-summary/WorkDetailProgress/WorkDetailProgress.module.scss +++ b/src-ts/tools/work/work-detail-summary/WorkDetailProgress/WorkDetailProgress.module.scss @@ -1,20 +1,20 @@ @import "../../../../lib/styles/includes"; .progress-container { - margin-bottom: calc($pad-lg + $pad-xxl); - padding: $pad-lg $pad-xxl $pad-xxl; - border-radius: $pad-sm; + margin-bottom: calc($space-lg + $space-xxl); + padding: $space-lg $space-xxl $space-xxl; + border-radius: $space-sm; @extend .bg-black-5; h3 { - margin-bottom: $pad-lg; + margin-bottom: $space-lg; color: $black-100; } .progress { display: flex; justify-content: space-between; - margin-top: calc($pad-lg + $pad-xxl); - margin-left: calc($pad-xxxxl - $border); + margin-top: calc($space-lg + $space-xxl); + margin-left: calc($space-xxxxl - $border); } } diff --git a/src-ts/tools/work/work-detail-summary/WorkDetailProgress/WorkDetailProgressItem/WorkDetailProgressItem.module.scss b/src-ts/tools/work/work-detail-summary/WorkDetailProgress/WorkDetailProgressItem/WorkDetailProgressItem.module.scss index 9e9786f3d..00e16e768 100644 --- a/src-ts/tools/work/work-detail-summary/WorkDetailProgress/WorkDetailProgressItem/WorkDetailProgressItem.module.scss +++ b/src-ts/tools/work/work-detail-summary/WorkDetailProgress/WorkDetailProgressItem/WorkDetailProgressItem.module.scss @@ -1,6 +1,6 @@ @import "../../../../../lib/styles/includes"; -$dot-size: calc($pad-lg + $pad-xxl); +$dot-size: calc($space-lg + $space-xxl); .progress-bar-list-item { position: relative; @@ -12,9 +12,9 @@ $dot-size: calc($pad-lg + $pad-xxl); .label { display: block; - margin-top: $pad-sm; + margin-top: $space-sm; margin-left: calc(-1 * calc($dot-size + 3px)); - width: calc(4 * $pad-xxxxl); + width: calc(4 * $space-xxxxl); text-align: center; color: $black-60; @@ -24,7 +24,7 @@ $dot-size: calc($pad-lg + $pad-xxl); .date { display: block; - margin-top: $pad-xs; + margin-top: $space-xs; } } @@ -34,9 +34,9 @@ $dot-size: calc($pad-lg + $pad-xxl); justify-content: center; width: $dot-size; height: $dot-size; - margin-bottom: $pad-sm; + margin-bottom: $space-sm; @extend .bg-black-10; - border: $pad-xs solid $black-20; + border: $space-xs solid $black-20; border-radius: 50%; box-sizing: border-box; color: $black-60; @@ -46,10 +46,10 @@ $dot-size: calc($pad-lg + $pad-xxl); content: ''; display: block; position: absolute; - top: $pad-lg; + top: $space-lg; left: $dot-size; width: 100%; - height: $pad-sm; + height: $space-sm; @extend .bg-black-20; } diff --git a/src-ts/tools/work/work-detail-summary/WorkTransferredStatus/WorkTransferredStatus.module.scss b/src-ts/tools/work/work-detail-summary/WorkTransferredStatus/WorkTransferredStatus.module.scss index be9b55857..b9538fbfe 100644 --- a/src-ts/tools/work/work-detail-summary/WorkTransferredStatus/WorkTransferredStatus.module.scss +++ b/src-ts/tools/work/work-detail-summary/WorkTransferredStatus/WorkTransferredStatus.module.scss @@ -1,20 +1,20 @@ @import "../../../../lib/styles/includes"; .wrap { - margin-bottom: calc($pad-lg + $pad-xxl); - padding: $pad-lg $pad-xxl $pad-xxl; - border-radius: $pad-sm; + margin-bottom: calc($space-lg + $space-xxl); + padding: $space-lg $space-xxl $space-xxl; + border-radius: $space-sm; @extend .bg-black-5; color: $black-100; h3 { - margin-bottom: $pad-lg; + margin-bottom: $space-lg; color: $black-100; } } .line { + .line { - margin-top: $pad-lg; + margin-top: $space-lg; } } diff --git a/src-ts/tools/work/work-lib/work-status-item/WorkStatusItem.module.scss b/src-ts/tools/work/work-lib/work-status-item/WorkStatusItem.module.scss index faf3609ff..6802ffdff 100644 --- a/src-ts/tools/work/work-lib/work-status-item/WorkStatusItem.module.scss +++ b/src-ts/tools/work/work-lib/work-status-item/WorkStatusItem.module.scss @@ -20,7 +20,7 @@ display: inline-block; width: 10px; height: 10px; - margin-right: $pad-xs; + margin-right: $space-xs; border-radius: 50px; border: 2px solid transparent; } diff --git a/src-ts/tools/work/work-login-prompt/WorkLoginPrompt.module.scss b/src-ts/tools/work/work-login-prompt/WorkLoginPrompt.module.scss index 624b83c04..a758e8f35 100644 --- a/src-ts/tools/work/work-login-prompt/WorkLoginPrompt.module.scss +++ b/src-ts/tools/work/work-login-prompt/WorkLoginPrompt.module.scss @@ -11,13 +11,13 @@ display: flex; justify-content: center; align-items: center; - margin-top: $pad-mx; - font-size: $pad-lg; - line-height: $pad-lg; + margin-top: $space-mx; + font-size: $space-lg; + line-height: $space-lg; .separator { - margin-left: $pad-lg; - margin-right: $pad-lg; + margin-left: $space-lg; + margin-right: $space-lg; } } } diff --git a/src-ts/tools/work/work-self-service/intake-forms/bug-hunt/deliverables-info-card/DeliverablesInfoCard.module.scss b/src-ts/tools/work/work-self-service/intake-forms/bug-hunt/deliverables-info-card/DeliverablesInfoCard.module.scss index 8e0f979f2..78ef62c6d 100644 --- a/src-ts/tools/work/work-self-service/intake-forms/bug-hunt/deliverables-info-card/DeliverablesInfoCard.module.scss +++ b/src-ts/tools/work/work-self-service/intake-forms/bug-hunt/deliverables-info-card/DeliverablesInfoCard.module.scss @@ -12,13 +12,13 @@ .column { &:first-child { @include ltemd { - padding-bottom: $pad-lg; + padding-bottom: $space-lg; } } @include gtemd { flex: 50%; - padding-right: $pad-mxx; + padding-right: $space-mxx; } } @@ -34,7 +34,7 @@ } .exampleImg { - padding: $pad-xs $border; + padding: $space-xs $border; max-height: 100% } @@ -43,5 +43,5 @@ line-height: 22px; text-transform: uppercase; font-weight: 600; - padding-bottom: $pad-sm; + padding-bottom: $space-sm; } diff --git a/src-ts/tools/work/work-self-service/intake-forms/review/Review.module.scss b/src-ts/tools/work/work-self-service/intake-forms/review/Review.module.scss index b822774c6..3a6967d9e 100644 --- a/src-ts/tools/work/work-self-service/intake-forms/review/Review.module.scss +++ b/src-ts/tools/work/work-self-service/intake-forms/review/Review.module.scss @@ -3,37 +3,37 @@ .review-container { .content { - padding: 0 $pad-xxxxl; - margin-top: $pad-xxl; + padding: 0 $space-xxxxl; + margin-top: $space-xxl; display: grid; grid-template-columns: 1fr 562px; column-gap: 24px; @include ltemd { grid-template-columns: 1fr; - padding: 0 $pad-lg; + padding: 0 $space-lg; } .left { flex: 1; border-top: 2px solid $black-10; - padding-top: $pad-xxl; + padding-top: $space-xxl; } .right { flex-basis: 32%; .payment-form-wrapper { border: 2px solid $black-20; border-radius: 8px; - padding: $pad-xxl; + padding: $space-xxl; @include ltemd { - padding: $pad-xl; + padding: $space-xl; } .form-header { text-align: center; - padding-bottom: $pad-xxl; + padding-bottom: $space-xxl; border-bottom: 1px solid $black-20; - margin-bottom: $pad-xxl; + margin-bottom: $space-xxl; .price { color: $teal-120; - margin-bottom: $pad-sm; + margin-bottom: $space-sm; } .label { @extend .overline; @@ -47,6 +47,6 @@ } .button-wrapper { - margin: 0 $pad-xxxxl $pad-xxxxl $pad-xxxxl; + margin: 0 $space-xxxxl $space-xxxxl $space-xxxxl; } } diff --git a/src-ts/tools/work/work-self-service/intake-forms/support-info-card/SupportInfoCard.module.scss b/src-ts/tools/work/work-self-service/intake-forms/support-info-card/SupportInfoCard.module.scss index b975e5e64..1058abe2c 100644 --- a/src-ts/tools/work/work-self-service/intake-forms/support-info-card/SupportInfoCard.module.scss +++ b/src-ts/tools/work/work-self-service/intake-forms/support-info-card/SupportInfoCard.module.scss @@ -1,5 +1,5 @@ @import '../../../../../lib/styles/includes'; .supportButton { - padding-top: $pad-lg; + padding-top: $space-lg; } \ No newline at end of file diff --git a/src-ts/tools/work/work-service-price/WorkServicePrice.module.scss b/src-ts/tools/work/work-service-price/WorkServicePrice.module.scss index 2513dce44..d07266f40 100644 --- a/src-ts/tools/work/work-service-price/WorkServicePrice.module.scss +++ b/src-ts/tools/work/work-service-price/WorkServicePrice.module.scss @@ -2,18 +2,18 @@ .container { - margin-top: $pad-xl; + margin-top: $space-xl; .iconWrapper { height: 48; width: 48; - margin: 0 $pad-lg $pad-lg $pad-lg; + margin: 0 $space-lg $space-lg $space-lg; background: $tc-grad12; border-radius: 24px; svg { @include icon-xl; - margin: $pad-md; + margin: $space-md; color: $tc-white; } } @@ -53,7 +53,7 @@ .stickerPrice { color: $black-80; text-decoration: line-through; - margin-right: $pad-xs; + margin-right: $space-xs; } .separator { @@ -68,7 +68,7 @@ } .help { - margin-left: $pad-sm; + margin-left: $space-sm; color: $turq-160; } } \ No newline at end of file diff --git a/src-ts/tools/work/work-table/work-badge-renderer/WorkBadgeRenderer.module.scss b/src-ts/tools/work/work-table/work-badge-renderer/WorkBadgeRenderer.module.scss index c49ea2e2a..e377019a1 100644 --- a/src-ts/tools/work/work-table/work-badge-renderer/WorkBadgeRenderer.module.scss +++ b/src-ts/tools/work/work-table/work-badge-renderer/WorkBadgeRenderer.module.scss @@ -5,7 +5,7 @@ @extend .medium-subtitle; display: inline-flex; padding: 0 $border; - border-radius: $pad-sm; + border-radius: $space-sm; color: $tc-white; min-width: 24px; text-align: center; diff --git a/src-ts/tools/work/work-table/work-table-title-renderer/WorkTableTitleRenderer.module.scss b/src-ts/tools/work/work-table/work-table-title-renderer/WorkTableTitleRenderer.module.scss index aec733c8d..759aff46c 100644 --- a/src-ts/tools/work/work-table/work-table-title-renderer/WorkTableTitleRenderer.module.scss +++ b/src-ts/tools/work/work-table/work-table-title-renderer/WorkTableTitleRenderer.module.scss @@ -7,7 +7,7 @@ svg { min-width: 32px; - margin-right: $pad-lg; + margin-right: $space-lg; } .work-table-title { diff --git a/src-ts/tools/work/work-thank-you/WorkThankYou.module.scss b/src-ts/tools/work/work-thank-you/WorkThankYou.module.scss index 4cd41cbc0..362dbf608 100644 --- a/src-ts/tools/work/work-thank-you/WorkThankYou.module.scss +++ b/src-ts/tools/work/work-thank-you/WorkThankYou.module.scss @@ -9,7 +9,7 @@ .contentContainer { p { - padding: $pad-xxl; + padding: $space-xxl; } } } diff --git a/src-ts/tools/work/work-type-banner/WorkTypeBanner.module.scss b/src-ts/tools/work/work-type-banner/WorkTypeBanner.module.scss index be9107fee..7df6c0752 100644 --- a/src-ts/tools/work/work-type-banner/WorkTypeBanner.module.scss +++ b/src-ts/tools/work/work-type-banner/WorkTypeBanner.module.scss @@ -5,7 +5,7 @@ flex-direction: row; align-items: flex-start; padding: 0px 0px 0px 0px; - gap: $pad-xxl; + gap: $space-xxl; height: 104px; @@ -148,22 +148,22 @@ display: flex; flex-direction: column; align-items: flex-start; - padding: $pad-lg 0px; + padding: $space-lg 0px; color: $tc-white; position: static; - left: $pad-xxxxl; + left: $space-xxxxl; top: 0px; /* Inside auto layout */ flex: none; order: 0; flex-grow: 1; - margin: 0px $pad-xxxl; + margin: 0px $space-xxxl; @include ltemd { - margin: 0px $pad-lg; - padding: $pad-sm 0px; + margin: 0px $space-lg; + padding: $space-sm 0px; } .heroHeader { @@ -188,10 +188,10 @@ display: flex; flex-direction: row; align-items: flex-start; - margin-right: $pad-lg; + margin-right: $space-lg; position: static; - width: $pad-mx; + width: $space-mx; left: 0px; top: 0px; } @@ -201,7 +201,7 @@ display: flex; flex-direction: column; align-items: flex-start; - row-gap: $pad-lg; + row-gap: $space-lg; padding: 0px; position: static; @@ -221,12 +221,12 @@ } .heroHeaderTitle { - height: $pad-xxxxl; + height: $space-xxxxl; font-family: 'Barlow Condensed'; font-style: normal; font-weight: 600; font-size: 34px; - line-height: $pad-xxxxl; + line-height: $space-xxxxl; text-transform: uppercase; color: #FFFFFF; @@ -238,18 +238,18 @@ @include ltemd { font-size: 28px; - line-height: $pad-xxxxl; + line-height: $space-xxxxl; width: 288px; } } .heroHeaderSubtitle { - height: $pad-xxl; + height: $space-xxl; font-family: 'Roboto'; font-style: normal; font-weight: 700; font-size: 16px; - line-height: $pad-xxl; + line-height: $space-xxl; color: #FFFFFF; /* Inside auto layout */ @@ -260,7 +260,7 @@ @include ltemd { font-size: 14px; - line-height: $pad-xl; + line-height: $space-xl; width: 288px; height: 60px; } @@ -280,7 +280,7 @@ font-style: normal; font-weight: normal; font-size: 24px; - line-height: $pad-xxxxl; + line-height: $space-xxxxl; /* or 133% */ /* gray/white */ @@ -288,7 +288,7 @@ /* Inside auto layout */ order: 1; - margin: $pad-lg 0px; + margin: $space-lg 0px; flex: none; align-self: stretch; flex-grow: 0; diff --git a/src-ts/utils/settings/account/Account.module.scss b/src-ts/utils/settings/account/Account.module.scss index 436c67e9b..d4174753b 100644 --- a/src-ts/utils/settings/account/Account.module.scss +++ b/src-ts/utils/settings/account/Account.module.scss @@ -2,8 +2,8 @@ :global(.account-settings-modal) { h2 { - margin-bottom: $pad-xxl; - padding: 0 0 $pad-xxl; + margin-bottom: $space-xxl; + padding: 0 0 $space-xxl; border-bottom: 1px solid $black-10; } @@ -12,11 +12,11 @@ .cards { display: grid; grid-template-columns: repeat(3, 1fr); - column-gap: $pad-xxl; - margin: $pad-xxl 0 0; + column-gap: $space-xxl; + margin: $space-xxl 0 0; @include ltemd { grid-template-columns: 1fr; - row-gap: $pad-xxl; + row-gap: $space-xxl; } } diff --git a/tsconfig.json b/tsconfig.json index 3e85a71cd..fab3b432e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -29,6 +29,7 @@ "src-ts" ], "exclude": [ - "**/*.test.*" + "**/*.test.*", + ".env" ] -} \ No newline at end of file +} diff --git a/tslint.json b/tslint.json index d1b0db4d6..0aa8caf3b 100644 --- a/tslint.json +++ b/tslint.json @@ -9,7 +9,8 @@ "src-ts/**/*" ], "exclude": [ - "src-ts/**/*.test*" + "src-ts/**/*.test*", + ".env" ], "rules": { "array-type": [ @@ -174,4 +175,4 @@ "check-type" ] } -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index 6a54f5164..51db5fc04 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2196,6 +2196,13 @@ dependencies: "@types/node" "*" +"@types/dompurify@^2.3.3": + version "2.3.3" + resolved "https://registry.yarnpkg.com/@types/dompurify/-/dompurify-2.3.3.tgz#c24c92f698f77ed9cc9d9fa7888f90cf2bfaa23f" + integrity sha512-nnVQSgRVuZ/843oAfhA25eRSNzUFcBPk/LOiw5gm8mD9/X7CNcbRkQu/OsjCewO8+VIYfPxUnXvPEVGenw14+w== + dependencies: + "@types/trusted-types" "*" + "@types/eslint-scope@^3.7.3": version "3.7.4" resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" @@ -2261,6 +2268,11 @@ dependencies: "@types/node" "*" +"@types/highlightjs@^9.12.2": + version "9.12.2" + resolved "https://registry.yarnpkg.com/@types/highlightjs/-/highlightjs-9.12.2.tgz#6b6d460968a975f4ce3ab3907c03cde46a72a02f" + integrity sha512-oW2pEKwshxwBW1nVUizWQg/tnhboRtKrUKnF2hd6l4BZ0shr5ZjQ4ra/82+NEH6uWeM8JjrMGCux5enQXOQbTA== + "@types/history@^4.7.11": version "4.7.11" resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.11.tgz#56588b17ae8f50c53983a524fc3cc47437969d64" @@ -2349,6 +2361,11 @@ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.182.tgz#05301a4d5e62963227eaafe0ce04dd77c54ea5c2" integrity sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q== +"@types/marked@4.0.3": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@types/marked/-/marked-4.0.3.tgz#2098f4a77adaba9ce881c9e0b6baf29116e5acc4" + integrity sha512-HnMWQkLJEf/PnxZIfbm0yGJRRZYYMhb++O9M36UCTA9z53uPvVoSlAwJr3XOpDEryb7Hwl1qAx/MV6YIW1RXxg== + "@types/mime@^1": version "1.3.2" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" @@ -2561,7 +2578,7 @@ dependencies: "@types/jest" "*" -"@types/trusted-types@^2.0.2": +"@types/trusted-types@*", "@types/trusted-types@^2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.2.tgz#fc25ad9943bcac11cceb8168db4f275e0e72e756" integrity sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg== @@ -3530,7 +3547,7 @@ axe-core@^4.4.2: resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.4.2.tgz#dcf7fb6dea866166c3eab33d68208afe4d5f670c" integrity sha512-LVAaGp/wkkgYJcjmHsoKx4juT1aQvJyPcW09MLCjVTh3V2cc6PnyempiLMNH5iMdfIX/zdbjUx2KDjMLCTdPeA== -axios@*: +axios@*, axios@^0.27.0: version "0.27.2" resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972" integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ== @@ -4752,6 +4769,35 @@ content-type@~1.0.4: resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== +contentful-resolve-response@^1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/contentful-resolve-response/-/contentful-resolve-response-1.3.8.tgz#58835a1d0894a97ab42541a47f4175d11adaa978" + integrity sha512-y3ttLqttxAN8yh3KfXNF+5kbnJa/01VFV/Rr1GNCaTWEVp6S9VGsTa1GH1cSf5czrK4nM4LUG5r6SzgNg3OkWw== + dependencies: + fast-copy "^2.1.3" + +contentful-sdk-core@^7.0.1: + version "7.0.2" + resolved "https://registry.yarnpkg.com/contentful-sdk-core/-/contentful-sdk-core-7.0.2.tgz#5585880f546772246209de25256635ce31fd8d8e" + integrity sha512-HkBzzzJ3UGqOIJiTd4qMEMvn44ccrN7a75gEej28X1srGn05myRgJ/pWbmXJhtgpq/5gU7IURnynyKx/ecsOfg== + dependencies: + fast-copy "^2.1.3" + lodash.isplainobject "^4.0.6" + lodash.isstring "^4.0.1" + p-throttle "^4.1.1" + qs "^6.9.4" + +contentful@^9.1.33: + version "9.1.33" + resolved "https://registry.yarnpkg.com/contentful/-/contentful-9.1.33.tgz#1305254c647578ad981eae59fae1abdb07b50b6a" + integrity sha512-iiu2cC/9JvDrTK6cfSHhZ1iW6dOq+NmYMA2p5Thpv+9h2pEOyoHm1Un9Xir5XZSB11bu4POmo6JazGAn9N0tqg== + dependencies: + axios "^0.27.0" + contentful-resolve-response "^1.3.0" + contentful-sdk-core "^7.0.1" + fast-copy "^2.1.0" + json-stringify-safe "^5.0.1" + convert-source-map@1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" @@ -5626,6 +5672,11 @@ domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1: dependencies: domelementtype "^2.2.0" +dompurify@^2.3.10: + version "2.3.10" + resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.10.tgz#901f7390ffe16a91a5a556b94043314cd4850385" + integrity sha512-o7Fg/AgC7p/XpKjf/+RC3Ok6k4St5F7Q6q6+Nnm3p2zGWioAY6dh0CbbuwOhH2UcSzKsdniE/YnE2/92JcsA+g== + domutils@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" @@ -6504,6 +6555,11 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== +fast-copy@^2.1.0, fast-copy@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-2.1.3.tgz#bf6e05ac3cb7a9d66fbf12c51dd4440e9ddd4afb" + integrity sha512-LDzYKNTHhD+XOp8wGMuCkY4eTxFZOOycmpwLBiuF3r3OjOmZnURRD8t2dUAbmKuXGbo/MGggwbSjcBdp8QT0+g== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -7252,6 +7308,11 @@ he@^1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +highlight.js@^11.6.0: + version "11.6.0" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.6.0.tgz#a50e9da05763f1bb0c1322c8f4f755242cff3f5a" + integrity sha512-ig1eqDzJaB0pqEvlPVIpSSyMaO92bH1N2rJpLMN/nX396wTpDA4Eq0uK+7I/2XG17pFaaKE0kjV/XPeGt7Evjw== + history@^5.2.0: version "5.3.0" resolved "https://registry.yarnpkg.com/history/-/history-5.3.0.tgz#1548abaa245ba47992f063a0783db91ef201c73b" @@ -9222,7 +9283,7 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== -json-stringify-safe@~5.0.1: +json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== @@ -9540,6 +9601,11 @@ lodash.isplainobject@^4.0.6: resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw== + lodash.keys@^3.0.0: version "3.1.2" resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" @@ -9670,6 +9736,11 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" +marked@4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/marked/-/marked-4.0.3.tgz#986760a428d8fd666251ec578429bf9a239a34bc" + integrity sha512-vSwKKtw+lCA0uFK/02JT4tBfNxEREpoTg21NoXqcmX0ySBIEyLMYWmt8WPsM61QNFaDBZkggupyNXLsV7uPuRg== + md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -10458,6 +10529,11 @@ p-retry@^4.5.0: "@types/retry" "0.12.0" retry "^0.13.1" +p-throttle@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/p-throttle/-/p-throttle-4.1.1.tgz#80b1fbd358af40a8bfa1667f9dc8b72b714ad692" + integrity sha512-TuU8Ato+pRTPJoDzYD4s7ocJYcNSEZRvlxoq3hcPI2kZDZ49IQ1Wkj7/gDJc3X7XiEAAvRGtDzdXJI0tC3IL1g== + p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" @@ -11635,6 +11711,13 @@ qs@6.10.3: dependencies: side-channel "^1.0.4" +qs@^6.9.4: + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== + dependencies: + side-channel "^1.0.4" + qs@~6.5.2: version "6.5.3" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad"