diff --git a/config-overrides.js b/config-overrides.js new file mode 100644 index 000000000..75f62850f --- /dev/null +++ b/config-overrides.js @@ -0,0 +1,3 @@ +const { removeModuleScopePlugin } = require('customize-cra') + +module.exports = removeModuleScopePlugin() diff --git a/package.json b/package.json index c07ef512c..eb3e83f7b 100644 --- a/package.json +++ b/package.json @@ -10,15 +10,16 @@ "build:dev": "sh build-dev.sh", "build:prod": "sh build-prod.sh", "eject": "react-scripts eject", - "lint": "tslint src-ts/**/*.{ts,tsx}", - "lint:fix": "tslint src-ts/**/*.{ts,tsx} --fix", + "lint": "tslint 'src-ts/**/*.{ts,tsx}'", + "lint:fix": "tslint 'src-ts/**/*.{ts,tsx}' --fix", + "eslint": "eslint 'src/**/*.{js,jsx}'", + "eslint:fix": "eslint 'src/**/*.{js,jsx}' --fix", "test": "react-scripts test", "test:no-watch": "npm test -- --watchAll=false" }, "dependencies": { "@datadog/browser-logs": "^4.5.0", "@heroicons/react": "^1.0.6", - "@reach/router": "^1.3.4", "apexcharts": "^3.35.3", "axios": "^0.26.1", "browser-cookies": "^1.2.0", @@ -87,8 +88,10 @@ "concurrently": "^5.0.1", "config": "^3.3.6", "cross-env": "^7.0.2", - "eslint": "^6.7.2", + "customize-cra": "^1.0.0", + "eslint": "^8.18.0", "eslint-config-prettier": "^6.7.0", + "eslint-config-react-app": "^7.0.1", "eslint-config-react-important-stuff": "^2.0.0", "eslint-plugin-prettier": "^3.1.1", "file-loader": "^6.2.0", @@ -99,6 +102,7 @@ "postcss-scss": "^3.0.2", "prettier": "^2.0.4", "pretty-quick": "^2.0.1", + "react-app-rewired": "^2.2.1", "resolve-url-loader": "^3.1.2", "sass": "^1.48.0", "sass-loader": "^10.0.5", diff --git a/public/index.html b/public/index.html index 3376e76cd..1468259f8 100644 --- a/public/index.html +++ b/public/index.html @@ -8,6 +8,7 @@ + diff --git a/src-ts/App.tsx b/src-ts/App.tsx index 74911202f..830c8d433 100644 --- a/src-ts/App.tsx +++ b/src-ts/App.tsx @@ -21,7 +21,7 @@ const App: FC<{}> = () => {
{routeElements} - + diff --git a/src-ts/lib/breadcrumb/Breadcrumb.module.scss b/src-ts/lib/breadcrumb/Breadcrumb.module.scss index 14a89c8f7..3d5a55160 100644 --- a/src-ts/lib/breadcrumb/Breadcrumb.module.scss +++ b/src-ts/lib/breadcrumb/Breadcrumb.module.scss @@ -14,6 +14,9 @@ ol { display: flex; + padding-left: 0px; + margin: 0; + &.hidden-mobile { @include ltemd { display: none; @@ -26,7 +29,7 @@ } } - > li { + >li { display: inline-flex; align-items: center; padding: 0; @@ -37,6 +40,7 @@ padding: $pad-md; color: $black-80; cursor: pointer; + &.elipsis { color: $turq-160; } @@ -69,4 +73,4 @@ } } } -} +} \ No newline at end of file diff --git a/src-ts/lib/breadcrumb/Breadcrumb.tsx b/src-ts/lib/breadcrumb/Breadcrumb.tsx index e8c4639e0..0d62b89df 100644 --- a/src-ts/lib/breadcrumb/Breadcrumb.tsx +++ b/src-ts/lib/breadcrumb/Breadcrumb.tsx @@ -51,7 +51,6 @@ const Breadcrumb: FC = (props: BreadcrumbProps) => { }} /> - ) } diff --git a/src-ts/lib/breadcrumb/breadcrumb-item/BreadcrumbItem.tsx b/src-ts/lib/breadcrumb/breadcrumb-item/BreadcrumbItem.tsx index 51b01f140..e9ab23f50 100644 --- a/src-ts/lib/breadcrumb/breadcrumb-item/BreadcrumbItem.tsx +++ b/src-ts/lib/breadcrumb/breadcrumb-item/BreadcrumbItem.tsx @@ -1,5 +1,5 @@ -import { Link } from '@reach/router' import { FC } from 'react' +import { Link } from 'react-router-dom' import styles from './../Breadcrumb.module.scss' import { BreadcrumbItemModel } from './breadcrumb-item.model' diff --git a/src-ts/lib/functions/xhr-functions/index.ts b/src-ts/lib/functions/xhr-functions/index.ts index 64eb70a25..42e673410 100644 --- a/src-ts/lib/functions/xhr-functions/index.ts +++ b/src-ts/lib/functions/xhr-functions/index.ts @@ -1,6 +1,7 @@ export { deleteAsync as xhrDeleteAsync, getAsync as xhrGetAsync, + getBlobAsync as xhrGetBlobAsync, patchAsync as xhrPatchAsync, postAsync as xhrPostAsync, putAsync as xhrPutAsync, diff --git a/src-ts/lib/functions/xhr-functions/xhr.functions.ts b/src-ts/lib/functions/xhr-functions/xhr.functions.ts index 33aeb5ad5..3c15f2a5d 100644 --- a/src-ts/lib/functions/xhr-functions/xhr.functions.ts +++ b/src-ts/lib/functions/xhr-functions/xhr.functions.ts @@ -38,6 +38,11 @@ export async function getAsync(url: string): Promise { return output.data } +export async function getBlobAsync(url: string): Promise { + const output: AxiosResponse = await xhrInstance.get(url, { responseType: 'blob' }) + return output.data +} + export async function patchAsync(url: string, data: T): Promise { const output: AxiosResponse = await xhrInstance.patch(url, data) return output.data diff --git a/src-ts/lib/index.ts b/src-ts/lib/index.ts index b835778cd..6ae9572e0 100644 --- a/src-ts/lib/index.ts +++ b/src-ts/lib/index.ts @@ -19,6 +19,9 @@ export { useOnHoverElement, xhrDeleteAsync, xhrGetAsync, + xhrGetBlobAsync, + xhrPatchAsync, + xhrPostAsync, } from './functions' export * from './loading-spinner' export * from './modals' diff --git a/src-ts/lib/modals/order-contract-modal/OrderContractModal.tsx b/src-ts/lib/modals/order-contract-modal/OrderContractModal.tsx index fa0a263a5..d0bcc5203 100644 --- a/src-ts/lib/modals/order-contract-modal/OrderContractModal.tsx +++ b/src-ts/lib/modals/order-contract-modal/OrderContractModal.tsx @@ -27,6 +27,7 @@ const OrderContractModal: FC = ({ isOpen, onClose }: OrderCo target='_blank' className={styles.topCoderLink} href='https://www.topcoder.com/' + rel='noreferrer' > https://www.topcoder.com/{' '} {' '} diff --git a/src-ts/lib/modals/privacy-policy-modal/PrivacyPolicyModal.module.scss b/src-ts/lib/modals/privacy-policy-modal/PrivacyPolicyModal.module.scss index b6a902cde..37dd6272f 100644 --- a/src-ts/lib/modals/privacy-policy-modal/PrivacyPolicyModal.module.scss +++ b/src-ts/lib/modals/privacy-policy-modal/PrivacyPolicyModal.module.scss @@ -5,6 +5,7 @@ ol { padding: 0; + list-style: none; } h4 { diff --git a/src-ts/lib/modals/terms-modal/TermsModal.module.scss b/src-ts/lib/modals/terms-modal/TermsModal.module.scss index 265a692c0..1b2ffb43b 100644 --- a/src-ts/lib/modals/terms-modal/TermsModal.module.scss +++ b/src-ts/lib/modals/terms-modal/TermsModal.module.scss @@ -5,6 +5,7 @@ ol { padding: 0; + list-style: none; } h4 { diff --git a/src-ts/lib/modals/terms-modal/TermsModal.tsx b/src-ts/lib/modals/terms-modal/TermsModal.tsx index 65cbc0b4c..69083ab1d 100644 --- a/src-ts/lib/modals/terms-modal/TermsModal.tsx +++ b/src-ts/lib/modals/terms-modal/TermsModal.tsx @@ -25,7 +25,7 @@ const TermsModal: FC = ({ isOpen, onClose }: TermsModal) => ( This User Agreement (the "Agreement") is a contract between you (referred to herein as "User") and Topcoder LLC. ("Topcoder") and applies to User's use and viewing of - + {' '} topcoder.com @@ -59,7 +59,7 @@ const TermsModal: FC = ({ isOpen, onClose }: TermsModal) => (
  • User agrees to comply with all terms of the Topcoder Privacy Policy available at - + {' '} https://www.topcoder.com/policy/privacy-policy/ diff --git a/src-ts/lib/page-footer/PageFooter.tsx b/src-ts/lib/page-footer/PageFooter.tsx index b8090bae1..c90c5d4f4 100644 --- a/src-ts/lib/page-footer/PageFooter.tsx +++ b/src-ts/lib/page-footer/PageFooter.tsx @@ -1,9 +1,8 @@ import { Dispatch, FC, MouseEvent, SetStateAction, useState } from 'react' -import { FooterSocialConfig } from '../../config' import { ContactSupportModal, OrderContractModal, PrivacyPolicyModal, TermsModal } from '../modals' import { ProfileProvider } from '../profile-provider' -import { SocialLink, SocialLinkIcons } from '../social-links' +import { Facebook, Instagram, LinkedIn, Twitter, Youtube } from '../social-links' import styles from './PageFooter.module.scss' @@ -71,9 +70,11 @@ const PageFooter: FC<{}> = () => {
    - {Object.entries(FooterSocialConfig).map(([platform, url]: [string, string]) => ( - - ))} + + + + +
    diff --git a/src-ts/lib/profile-provider/profile-context-data.model.ts b/src-ts/lib/profile-provider/profile-context-data.model.ts index bb2efa3b4..2cd45ee18 100644 --- a/src-ts/lib/profile-provider/profile-context-data.model.ts +++ b/src-ts/lib/profile-provider/profile-context-data.model.ts @@ -4,6 +4,7 @@ import { UserProfile } from './user-profile.model' export interface ProfileContextData { changePassword: (userId: number, request: ChangePasswordRequest) => Promise initialized: boolean + isLoggedIn: boolean profile?: UserProfile updateProfile: (updatedProfileContext: ProfileContextData) => Promise } diff --git a/src-ts/lib/profile-provider/profile-functions/profile.functions.ts b/src-ts/lib/profile-provider/profile-functions/profile.functions.ts index c4a531fe3..b6056a4d1 100644 --- a/src-ts/lib/profile-provider/profile-functions/profile.functions.ts +++ b/src-ts/lib/profile-provider/profile-functions/profile.functions.ts @@ -1,6 +1,3 @@ -// tslint:disable-next-line: no-implicit-dependencies // TODO: create types -import { updateUserProfile } from '@topcoder/mfe-header' - import { tokenGetAsync } from '../../functions/token-functions' import { EditNameRequest } from '../edit-name-request.model' import { UserProfile } from '../user-profile.model' @@ -14,7 +11,4 @@ export async function getAsync(handle?: string): Promise { return profileStorePatchName(handle, profile) - .then(result => { - updateUserProfile(result.firstName, result.lastName) - }) } diff --git a/src-ts/lib/profile-provider/profile.context.tsx b/src-ts/lib/profile-provider/profile.context.tsx index bf4261f23..d61f6c3c2 100644 --- a/src-ts/lib/profile-provider/profile.context.tsx +++ b/src-ts/lib/profile-provider/profile.context.tsx @@ -5,6 +5,7 @@ import { ProfileContextData } from './profile-context-data.model' export const defaultProfileContextData: ProfileContextData = { changePassword: () => Promise.resolve(), initialized: false, + isLoggedIn: false, updateProfile: () => Promise.resolve(undefined), } diff --git a/src-ts/lib/profile-provider/profile.provider.tsx b/src-ts/lib/profile-provider/profile.provider.tsx index 85d58c0b4..60e32e24c 100644 --- a/src-ts/lib/profile-provider/profile.provider.tsx +++ b/src-ts/lib/profile-provider/profile.provider.tsx @@ -47,6 +47,7 @@ export const ProfileProvider: FC<{ children: ReactNode }> = ({ children }: { chi const contextData: ProfileContextData = { changePassword, initialized: true, + isLoggedIn: !!profile, profile, updateProfile, } diff --git a/src-ts/lib/social-links/SocialLink.tsx b/src-ts/lib/social-links/SocialLink.tsx deleted file mode 100644 index fb4d4f048..000000000 --- a/src-ts/lib/social-links/SocialLink.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { FC } from 'react' - -import { - SocialIconFacebook, - SocialIconInstagram, - SocialIconLinkedin, - SocialIconTwitter, - SocialIconYoutube, -} from '../svgs' - -export const SocialLinkIcons: object = { - facebook: SocialIconFacebook, - instagram: SocialIconInstagram, - linkedin: SocialIconLinkedin, - twitter: SocialIconTwitter, - youtube: SocialIconYoutube, -} - -interface SocialLinkProps { - icon: keyof typeof SocialLinkIcons - url: string -} - -const SocialLink: FC = ({ - icon, - url, -}: SocialLinkProps) => { - const Icon: FC = SocialLinkIcons[icon] - - if (!Icon) { - return <> - } - - return ( - - - - ) -} - -export default SocialLink diff --git a/src-ts/lib/social-links/facebook/Facebook.tsx b/src-ts/lib/social-links/facebook/Facebook.tsx new file mode 100644 index 000000000..e8b78ab0a --- /dev/null +++ b/src-ts/lib/social-links/facebook/Facebook.tsx @@ -0,0 +1,16 @@ +import { FC } from 'react' + +import { SocialIconFacebook } from '../../svgs' +import { SocialLink } from '../social-link' + +const Facebook: FC<{}> = () => { + + return ( + + ) +} + +export default Facebook diff --git a/src-ts/lib/social-links/facebook/index.ts b/src-ts/lib/social-links/facebook/index.ts new file mode 100644 index 000000000..30a4b2461 --- /dev/null +++ b/src-ts/lib/social-links/facebook/index.ts @@ -0,0 +1 @@ +export { default as Facebook } from './Facebook' diff --git a/src-ts/lib/social-links/index.ts b/src-ts/lib/social-links/index.ts index 0d2af740c..175f6f5bf 100644 --- a/src-ts/lib/social-links/index.ts +++ b/src-ts/lib/social-links/index.ts @@ -1 +1,5 @@ -export { default as SocialLink, SocialLinkIcons } from './SocialLink' +export * from './facebook' +export * from './instagram' +export * from './linked-in' +export * from './twitter' +export * from './youtube' diff --git a/src-ts/lib/social-links/instagram/Instagram.tsx b/src-ts/lib/social-links/instagram/Instagram.tsx new file mode 100644 index 000000000..a7481ff8f --- /dev/null +++ b/src-ts/lib/social-links/instagram/Instagram.tsx @@ -0,0 +1,16 @@ +import { FC } from 'react' + +import { SocialIconInstagram } from '../../svgs' +import { SocialLink } from '../social-link' + +const Instagram: FC<{}> = () => { + + return ( + + ) +} + +export default Instagram diff --git a/src-ts/lib/social-links/instagram/index.ts b/src-ts/lib/social-links/instagram/index.ts new file mode 100644 index 000000000..96f094097 --- /dev/null +++ b/src-ts/lib/social-links/instagram/index.ts @@ -0,0 +1 @@ +export { default as Instagram } from './Instagram' diff --git a/src-ts/lib/social-links/linked-in/LinkedIn.tsx b/src-ts/lib/social-links/linked-in/LinkedIn.tsx new file mode 100644 index 000000000..343c4a5cf --- /dev/null +++ b/src-ts/lib/social-links/linked-in/LinkedIn.tsx @@ -0,0 +1,16 @@ +import { FC } from 'react' + +import { SocialIconLinkedIn } from '../../svgs' +import { SocialLink } from '../social-link' + +const LinkedIn: FC<{}> = () => { + + return ( + + ) +} + +export default LinkedIn diff --git a/src-ts/lib/social-links/linked-in/index.ts b/src-ts/lib/social-links/linked-in/index.ts new file mode 100644 index 000000000..1f5a43bd2 --- /dev/null +++ b/src-ts/lib/social-links/linked-in/index.ts @@ -0,0 +1 @@ +export { default as LinkedIn } from './LinkedIn' diff --git a/src-ts/lib/social-links/social-link/SocialLink.tsx b/src-ts/lib/social-links/social-link/SocialLink.tsx new file mode 100644 index 000000000..c25f755fa --- /dev/null +++ b/src-ts/lib/social-links/social-link/SocialLink.tsx @@ -0,0 +1,22 @@ +import { FC, SVGProps } from 'react' +interface SocialLinkProps { + readonly icon: FC> + url: string +} + +const SocialLink: FC = (props: SocialLinkProps) => { + + const Icon: FC> | undefined = props.icon + + if (!Icon) { + return <> + } + + return ( + + + + ) +} + +export default SocialLink diff --git a/src-ts/lib/social-links/social-link/index.ts b/src-ts/lib/social-links/social-link/index.ts new file mode 100644 index 000000000..626e2cf31 --- /dev/null +++ b/src-ts/lib/social-links/social-link/index.ts @@ -0,0 +1 @@ +export { default as SocialLink } from './SocialLink' diff --git a/src-ts/lib/social-links/twitter/Twitter.tsx b/src-ts/lib/social-links/twitter/Twitter.tsx new file mode 100644 index 000000000..560c3f5aa --- /dev/null +++ b/src-ts/lib/social-links/twitter/Twitter.tsx @@ -0,0 +1,16 @@ +import { FC } from 'react' + +import { SocialIconTwitter } from '../../svgs' +import { SocialLink } from '../social-link' + +const Twitter: FC<{}> = () => { + + return ( + + ) +} + +export default Twitter diff --git a/src-ts/lib/social-links/twitter/index.ts b/src-ts/lib/social-links/twitter/index.ts new file mode 100644 index 000000000..31f555b61 --- /dev/null +++ b/src-ts/lib/social-links/twitter/index.ts @@ -0,0 +1 @@ +export { default as Twitter } from './Twitter' diff --git a/src-ts/lib/social-links/youtube/Youtube.tsx b/src-ts/lib/social-links/youtube/Youtube.tsx new file mode 100644 index 000000000..6daa79836 --- /dev/null +++ b/src-ts/lib/social-links/youtube/Youtube.tsx @@ -0,0 +1,16 @@ +import { FC } from 'react' + +import { SocialIconYoutube } from '../../svgs' +import { SocialLink } from '../social-link' + +const Youtube: FC<{}> = () => { + + return ( + + ) +} + +export default Youtube diff --git a/src-ts/lib/social-links/youtube/index.ts b/src-ts/lib/social-links/youtube/index.ts new file mode 100644 index 000000000..d60a90f89 --- /dev/null +++ b/src-ts/lib/social-links/youtube/index.ts @@ -0,0 +1 @@ +export { default as Youtube } from './Youtube' diff --git a/src-ts/lib/styles/_reset.scss b/src-ts/lib/styles/_reset.scss index e130bd9af..6351952a5 100644 --- a/src-ts/lib/styles/_reset.scss +++ b/src-ts/lib/styles/_reset.scss @@ -96,7 +96,6 @@ iframe, embed, object { display: block; - vertical-align: middle; } /** diff --git a/src-ts/lib/svgs/index.ts b/src-ts/lib/svgs/index.ts index db151ef01..6a5e5da55 100644 --- a/src-ts/lib/svgs/index.ts +++ b/src-ts/lib/svgs/index.ts @@ -6,7 +6,7 @@ import { ReactComponent as ActiveTabTipIcon } from './activetab-tip-icon.svg' import { ReactComponent as LogoIcon } from './logo.svg' import { ReactComponent as SocialIconFacebook } from './social-fb-icon.svg' import { ReactComponent as SocialIconInstagram } from './social-insta-icon.svg' -import { ReactComponent as SocialIconLinkedin } from './social-linkedin-icon.svg' +import { ReactComponent as SocialIconLinkedIn } from './social-linkedin-icon.svg' import { ReactComponent as SocialIconTwitter } from './social-tw-icon.svg' import { ReactComponent as SocialIconYoutube } from './social-yt-icon.svg' import { ReactComponent as TooltipArrowIcon } from './tooltip-arrow.svg' @@ -17,7 +17,7 @@ export { IconSolid } export { LogoIcon } export { SocialIconFacebook } export { SocialIconInstagram } -export { SocialIconLinkedin } +export { SocialIconLinkedIn } export { SocialIconTwitter } export { SocialIconYoutube } export { TooltipArrowIcon } diff --git a/src-ts/lib/table/Table.tsx b/src-ts/lib/table/Table.tsx index 857bad0f5..fe1228886 100644 --- a/src-ts/lib/table/Table.tsx +++ b/src-ts/lib/table/Table.tsx @@ -72,13 +72,16 @@ const Table: (props: TableProps) = } const headerRow: Array = props.columns - .map(col => { + .map((col, index) => { const isSortable: boolean = !!col.propertyName const isCurrentlySorted: boolean = isSortable && col.propertyName === sort?.fieldName const colorClass: string = isCurrentlySorted ? 'black-100' : 'black-60' const sortableClass: string | undefined = isSortable ? styles.sortable : undefined return ( - +
    {col.label} {!!col.tooltip && ( @@ -113,12 +116,13 @@ const Table: (props: TableProps) = // get the cells in the row const cells: Array = props.columns - .map(col => { + .map((col, colIndex) => { return ( ) }) @@ -139,10 +143,14 @@ const Table: (props: TableProps) = /* TODO: sticky header */
    - - {headerRow} - - {rowCells} + + + {headerRow} + + + + {rowCells} +
    ) diff --git a/src-ts/tools/work/work-detail-details/work-detail-details-pane/WorkDetailDetailsPane.tsx b/src-ts/tools/work/work-detail-details/work-detail-details-pane/WorkDetailDetailsPane.tsx index 5a90e6f69..5c79a1269 100644 --- a/src-ts/tools/work/work-detail-details/work-detail-details-pane/WorkDetailDetailsPane.tsx +++ b/src-ts/tools/work/work-detail-details/work-detail-details-pane/WorkDetailDetailsPane.tsx @@ -1,6 +1,6 @@ -import { Link } from '@reach/router' import _ from 'lodash' import { Dispatch, FC, SetStateAction, useEffect, useState } from 'react' +import { Link } from 'react-router-dom' import { LoadingSpinner } from '../../../../lib' import { workFactoryMapFormData } from '../../work-lib' diff --git a/src-ts/tools/work/work-detail-solutions/WorkDetailSolutions.tsx b/src-ts/tools/work/work-detail-solutions/WorkDetailSolutions.tsx index 345fde417..cc45901b9 100644 --- a/src-ts/tools/work/work-detail-solutions/WorkDetailSolutions.tsx +++ b/src-ts/tools/work/work-detail-solutions/WorkDetailSolutions.tsx @@ -15,20 +15,20 @@ const WorkDetailSolutions: FC = (props: WorkDetailSolu const workContextData: WorkContextData = useContext(workContext) - if (!props.challenge) { - return <> - } - - const work: Work = workContextData.createFromChallenge(props.challenge) + const work: Work | undefined = !!props.challenge ? workContextData.createFromChallenge(props.challenge) : undefined const isSolutionsReady: boolean = useMemo(() => { - const activeStepName: string = work.progress.steps[work.progress.activeStepIndex]?.name + const activeStepName: string | undefined = work?.progress.steps[work?.progress.activeStepIndex]?.name return (activeStepName === WorkStatus.ready || activeStepName === WorkStatus.done) }, [ work, props.solutions, ]) + if (!props.challenge) { + return <> + } + return (
    {isSolutionsReady && ( @@ -45,7 +45,7 @@ const WorkDetailSolutions: FC = (props: WorkDetailSolu isSolutionsReady={isSolutionsReady} onDownload={props.onDownload} solutions={props.solutions} - work={work} + work={work as Work} />
    ) diff --git a/src-ts/tools/work/work-table/work-table.config.tsx b/src-ts/tools/work/work-table/work-table.config.tsx index 95ea2c887..486340667 100644 --- a/src-ts/tools/work/work-table/work-table.config.tsx +++ b/src-ts/tools/work/work-table/work-table.config.tsx @@ -1,17 +1,19 @@ import { TableColumn } from '../../../lib' import { Work } from '../work-lib' -import { WorkBadgeRenderer } from './work-badge-renderer' +// import { WorkBadgeRenderer } from './work-badge-renderer' import { WorkDeleteButtonRenderer } from './work-delete-button-renderer' import { WorkStatusRenderer } from './work-status-renderer' import { WorkTableTitleRenderer } from './work-table-title-renderer' +/* TODO: uncomment this when the messages are back up +as part of PROD-1860 function messageBadgeRenderer(work: Work): JSX.Element { return WorkBadgeRenderer({ count: work.messageCount, type: 'messages', }) -} +} */ export enum WorkListColumnField { status = 'Status', diff --git a/src/App.jsx b/src/App.jsx index 42fa826a2..333607237 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,24 +1,18 @@ -import { Redirect, Router } from "@reach/router"; -import { - getAuthUserTokens, - disableNavigationForRoute, -} from "@topcoder/mfe-header"; -import React, { useLayoutEffect, useState } from "react"; +import { Navigate, Route, Routes } from "react-router-dom"; +import React, { useContext, useLayoutEffect } from "react"; +import TagManager from "react-gtm-module"; +import "react-responsive-modal/styles.css"; + +import { EnvironmentConfig, logInitialize, profileContext } from "../src-ts"; + import { UNDER_MAINTENANCE, GA_ID } from "./constants"; import IntakeForm from "./IntakeForm"; import Home from "./routes/Home"; -import WorkItems from "./routes/WorkItems"; -import Layout from "components/Layout"; -import TagManager from "react-gtm-module"; +import WorkItem from "./routes/WorkItems"; import { ScrollToTop } from "./ScrollToTop"; - -import "react-responsive-modal/styles.css"; - import styles from "./styles/main.module.scss"; import UnderMaintenance from "./routes/UnderMaintenance"; -import { EnvironmentConfig, logInitialize } from "../src-ts"; - logInitialize(EnvironmentConfig); if (process.env.APPMODE === "production") { @@ -28,15 +22,10 @@ if (process.env.APPMODE === "production") { } const App = () => { - const [isLoggedIn, setIsLoggedIn] = useState(null); + + const { initialized, isLoggedIn } = useContext(profileContext) useLayoutEffect(() => { - const checkIsLoggedIn = async () => { - const { tokenV3 } = await getAuthUserTokens(); - setIsLoggedIn(!!tokenV3); - }; - disableNavigationForRoute("/self-service/*"); - checkIsLoggedIn(); document.documentElement.style.setProperty("--navbarHeight", "80px"); return () => { // --navbarHeight must be set to its default value, @@ -45,7 +34,7 @@ const App = () => { }; }, []); - if (isLoggedIn == null) { + if (!initialized) { return null; } @@ -59,22 +48,31 @@ const App = () => { return (
    - - - + + + } + path="/self-service/*" + /> {isLoggedIn && ( <> - } path="/self-service/work-items/:workItemId" - PageComponent={WorkItems} /> - + } + path="/self-service/*" + /> )} - - - -
    + } + path="/self-service" + /> + + +
    ); }; diff --git a/src/IntakeForm.jsx b/src/IntakeForm.jsx index 048fea9a8..55531137e 100644 --- a/src/IntakeForm.jsx +++ b/src/IntakeForm.jsx @@ -1,10 +1,9 @@ -import { navigate, Router, Redirect } from "@reach/router"; -import { getAuthUserTokens } from "@topcoder/mfe-header"; -import LoadingSpinner from "components/LoadingSpinner"; +import { useNavigate, Route, Routes } from "react-router-dom"; import _ from "lodash"; -import React, { useEffect, useState } from "react"; +import React, { useContext, useEffect, useState } from "react"; import { useDispatch } from "react-redux"; -import { decodeToken } from "tc-auth-lib"; + +import LoadingSpinner from "./components/LoadingSpinner"; import { autoSaveInitErrored, triggerAutoSave } from "./actions/autoSave"; import { getChallenge } from "./actions/challenge"; import { saveForm } from "./actions/form"; @@ -21,11 +20,7 @@ import { INTAKE_FORM_ROUTES as FIND_ME_DATA_INTAKE_FORM_ROUTES } from "./constan import { INTAKE_FORM_ROUTES as DATA_ADVISORY_INTAKE_FORM_ROUTES } from "./constants/products/DataAdvisory"; import { INTAKE_FORM_ROUTES as WEBSITE_DESIGN_INTAKE_FORM_ROUTES } from "./constants/products/WebsiteDesign"; import { INTAKE_FORM_ROUTES as WEBSITE_DESIGN_LEGACY_INTAKE_FORM_ROUTES } from "./constants/products/WebsiteDesignLegacy"; -import { - authUserError, - authUserSuccess, -} from "./hoc/withAuthentication/actions"; -import { getIntakeFormChallenges } from "services/challenge"; +import { getIntakeFormChallenges } from "./services/challenge"; import SelectWorkType from "./routes/SelectWorkType"; import DataExploration from "./routes/Products/DataExploration"; import FindMeData from "./routes/Products/FindMeData"; @@ -33,25 +28,24 @@ import WebsiteDesign from "./routes/Products/WebsiteDesign"; import DataAdvisory from "./routes/Products/DataAdvisory"; import WebsiteDesignLegacy from "./routes/Products/WebsiteDesignLegacy"; -import { WorkType } from "../src-ts"; +import { profileContext, WorkType } from "../src-ts"; export default function IntakeForm() { + const dispatch = useDispatch(); const [isLoading, setIsLoading] = useState(false); - const [isLoggedIn, setIsLoggedIn] = useState(false); + const navigate = useNavigate() + + const { + isLoggedIn, + profile, + } = useContext(profileContext) const onReload = (event) => { - getAuthUserTokens() - .then((auth) => { - if (auth?.tokenV3) { - event.preventDefault(); - event.returnValue = ""; - } - }) - .catch((error) => { - setCookie(MAX_COMPLETED_STEP, "", -1); - authUserError(error); - }); + if (isLoggedIn) { + event.preventDefault(); + event.returnValue = ""; + } dispatch(triggerAutoSave(true)); }; @@ -98,10 +92,8 @@ export default function IntakeForm() { }; const setUpAutoSave = async () => { - const { handle } = await getAuth(); - if (handle) { - await handleAutoSaveLoggedIn(handle); - setIsLoggedIn(true); + if (!!profile) { + await handleAutoSaveLoggedIn(profile.handle); } else { handleAutoSavedLoggedOut(); } @@ -166,57 +158,47 @@ export default function IntakeForm() { syncSavedData(savedFormCookie); }; - const getAuth = async () => { - let auth = {}; - try { - const { tokenV3 } = await getAuthUserTokens(); - if (!!tokenV3) { - const tokenData = decodeToken(tokenV3); - const authProps = ["userId", "handle", "roles"]; - dispatch(authUserSuccess(_.pick(tokenData, authProps))); - auth = tokenData; - } - } catch (err) { - dispatch(authUserError(err)); - } - return auth; - }; - return (
    {!isLoading && ( - + {/* Data Exploration */} - } path="/work/new/data-exploration/*" - isLoggedIn={isLoggedIn} /> {/* Data Advisory */} - } path="/work/new/data-advisory/*" - isLoggedIn={isLoggedIn} + /> {/* Find Me Data */} - + } + path="/work/new/find-me-data/*" + /> {/* Web Design (NEW) */} - } path="/work/new/website-design-new/*" - isLoggedIn={isLoggedIn} /> {/* Web Design (Legacy) */} - } path="/work/new/website-design/*" - isLoggedIn={isLoggedIn} /> - - {/* */} - + } + path="/wizard" + /> + )}
    ); diff --git a/src/ScrollToTop.jsx b/src/ScrollToTop.jsx index 1b06399cb..7a5ec3895 100644 --- a/src/ScrollToTop.jsx +++ b/src/ScrollToTop.jsx @@ -1,6 +1,6 @@ import React from "react"; export const ScrollToTop = ({ children, location }) => { - React.useEffect(() => window.scrollTo(0, 0), [location.pathname]); + React.useEffect(() => window.scrollTo(0, 0), [location?.pathname]); return children; }; diff --git a/src/actions/autoSave.js b/src/actions/autoSave.js index 6afbaa784..66f124223 100644 --- a/src/actions/autoSave.js +++ b/src/actions/autoSave.js @@ -1,4 +1,4 @@ -import { patchChallenge } from "services/challenge"; +import { patchChallenge } from "../services/challenge"; import { getChallenge } from "../actions/challenge"; import { autoSaveCookie } from "../autoSaveBeforeLogin"; import { ACTIONS } from "../constants"; diff --git a/src/actions/challenge.js b/src/actions/challenge.js index d75f28b8f..edb3f3e76 100644 --- a/src/actions/challenge.js +++ b/src/actions/challenge.js @@ -1,5 +1,5 @@ import { ACTIONS } from "../constants"; -import { createChallenge } from "services/challenge"; +import { createChallenge } from "../services/challenge"; import { cacheChallengeId } from "../autoSaveBeforeLogin"; export const getChallenge = (challenge) => ({ diff --git a/src/actions/profile.js b/src/actions/profile.js deleted file mode 100644 index 8991722ae..000000000 --- a/src/actions/profile.js +++ /dev/null @@ -1,46 +0,0 @@ -import { ACTIONS } from "../constants"; - -/** - * Creates an action for grabbing user profile information - * - * @param {Object} profile user profile - * - * @returns {Object} - */ -export const getUserProfile = (profile) => ({ - type: ACTIONS.PROFILE.GET_PROFILE, - payload: profile, -}); - -/** - * Creates an action denoting the start of updating user basic info. - * - * @returns {Object} - */ -export const updateBasicInfoPending = () => ({ - type: ACTIONS.PROFILE.UPDATE_BASIC_INFO_PENDING, -}); - -/** - * Creates an action denoting the successful load of updating user basic info - * - * @param {Object} basicInfo basic info - * - * @returns {Object} - */ -export const updateBasicInfoSuccess = (basicInfo) => ({ - type: ACTIONS.PROFILE.UPDATE_BASIC_INFO_SUCCESS, - payload: basicInfo, -}); - -/** - * Creates an action denoting the failure to updating user basic info. - * - * @param {Object} error error object - * - * @returns {Object} - */ -export const updateBasicInfoError = (error) => ({ - type: ACTIONS.PROFILE.UPDATE_BASIC_INFO_ERROR, - payload: error, -}); diff --git a/src/actions/work.js b/src/actions/work.js index 3cc1b132c..40e77ac6d 100644 --- a/src/actions/work.js +++ b/src/actions/work.js @@ -59,9 +59,9 @@ export const setIsSavingSurveyDone = (value) => { }; }; -export const getForumNotifications = (workId) => { +export const getForumNotifications = (workId, profile) => { return { type: ACTIONS.WORK.GET_FORUM_NOTIFICATIONS, - payload: challengeService.getForumNotifications(workId), + payload: challengeService.getForumNotifications(workId, profile), }; }; diff --git a/src/autoSaveBeforeLogin.js b/src/autoSaveBeforeLogin.js index c40df3e1f..d6ef94e31 100644 --- a/src/autoSaveBeforeLogin.js +++ b/src/autoSaveBeforeLogin.js @@ -1,15 +1,17 @@ -import { ACTIONS, AUTO_SAVE_FORM, CACHED_CHALLENGE_ID } from "constants/index"; import CryptoJS from "crypto-js"; import _ from "lodash"; import moment from "moment"; import "moment-timezone"; + import config from "../config"; + import { autoSaveCookieCleared, sendAutoSavedPatch, storeAutoSavedCookie, } from "./actions/autoSave"; import { createNewChallenge } from "./actions/challenge"; +import { ACTIONS, AUTO_SAVE_FORM, CACHED_CHALLENGE_ID } from "./constants"; let CREATION_IN_PROGRESS = false; @@ -165,12 +167,12 @@ export function getCookie(name) { function getHostDomain() { let hostDomain = ""; - if (location.hostname !== "localhost") { + if (window.location.hostname !== "localhost") { hostDomain = ";domain=." + - location.hostname.split(".").reverse()[1] + + window.location.hostname.split(".").reverse()[1] + "." + - location.hostname.split(".").reverse()[0]; + window.location.hostname.split(".").reverse()[0]; } return hostDomain; } diff --git a/src/components/Banners/FeaturedWorkTypeBanner/styles.module.scss b/src/components/Banners/FeaturedWorkTypeBanner/styles.module.scss index b8fdd9ff8..e66a6e018 100644 --- a/src/components/Banners/FeaturedWorkTypeBanner/styles.module.scss +++ b/src/components/Banners/FeaturedWorkTypeBanner/styles.module.scss @@ -1,4 +1,4 @@ -@import "styles/include"; +@import "../../../styles/include"; .heroContainer { position: static; diff --git a/src/components/Banners/WebsiteDesignBannerLegacy/index.js b/src/components/Banners/WebsiteDesignBannerLegacy/index.js index 8b2f7856c..7f3209033 100644 --- a/src/components/Banners/WebsiteDesignBannerLegacy/index.js +++ b/src/components/Banners/WebsiteDesignBannerLegacy/index.js @@ -3,23 +3,24 @@ * Website Design Banner */ import React from "react"; -import "./styles.module.scss"; -import { IconWebsiteTools } from "../../../assets/images/design-tools.svg"; + +import styles from "./styles.module.scss"; +import { ReactComponent as IconWebsiteTools } from "../../../assets/images/design-tools.svg"; export const WebsiteDesignBannerLegacy = () => { return ( -
    -
    -
    -
    -
    -
    -
    +
    +
    +
    +
    +
    +
    +
    WEBSITE DESIGN
    -
    +
    Create a beautiful custom visual design for your website. and device types, your vision, and receive up to 5 modern modern modern designs. diff --git a/src/components/Banners/WebsiteDesignBannerLegacy/styles.module.scss b/src/components/Banners/WebsiteDesignBannerLegacy/styles.module.scss index facad6d99..ee4563d20 100644 --- a/src/components/Banners/WebsiteDesignBannerLegacy/styles.module.scss +++ b/src/components/Banners/WebsiteDesignBannerLegacy/styles.module.scss @@ -1,4 +1,4 @@ -@import "styles/include"; +@import "../../../styles/include"; .heroContainer { position: static; diff --git a/src/components/Button/index.jsx b/src/components/Button/index.jsx index 99ef3afb5..00d38049c 100644 --- a/src/components/Button/index.jsx +++ b/src/components/Button/index.jsx @@ -9,12 +9,14 @@ * * if `href` is set, then button is rendered as a link `` */ -import { Link } from "@reach/router"; +import { Link } from "react-router-dom"; import cn from "classnames"; -import { BUTTON_SIZE, BUTTON_TYPE } from "constants"; import PT from "prop-types"; import React from "react"; -import "./styles.module.scss"; + +import { BUTTON_SIZE, BUTTON_TYPE } from "../../constants"; + +import styles from "./styles.module.scss"; const Button = ({ children, @@ -34,9 +36,8 @@ const Button = ({ {children} @@ -45,9 +46,8 @@ const Button = ({ } else { const button = (