diff --git a/src-ts/lib/functions/error-functions/error.functions.tsx b/src-ts/lib/functions/error-functions/error.functions.tsx new file mode 100644 index 000000000..a4b017c15 --- /dev/null +++ b/src-ts/lib/functions/error-functions/error.functions.tsx @@ -0,0 +1,29 @@ +import { Link } from 'react-router-dom' +import { toast, ToastContent } from 'react-toastify' + +import { contactSupportPath } from '../../contact-support-form' +import { logError } from '../logging-functions' + +export function handle(error: any, errString?: string): void { + + logError(error) + + const errorContent: ToastContent = ( + <> +

+ {errString ?? error.response?.data?.result?.content ?? error.message ?? error} + {' '} + Please try again later or + {' '} + + Contact Support + . +

+ + ) + + toast.error(errorContent) +} diff --git a/src-ts/lib/functions/error-functions/index.ts b/src-ts/lib/functions/error-functions/index.ts new file mode 100644 index 000000000..80f039765 --- /dev/null +++ b/src-ts/lib/functions/error-functions/index.ts @@ -0,0 +1 @@ +export { handle as errorHandle } from './error.functions' diff --git a/src-ts/lib/functions/index.ts b/src-ts/lib/functions/index.ts index 59ebaa379..3bf2087c5 100644 --- a/src-ts/lib/functions/index.ts +++ b/src-ts/lib/functions/index.ts @@ -6,6 +6,7 @@ export { authUrlLogout, authUrlSignup, } from './authentication-functions' +export * from './error-functions' export * from './file-functions' export * from './logging-functions' export * from './text-format-functions' diff --git a/src-ts/lib/index.ts b/src-ts/lib/index.ts index 89bd96720..c5ef84cd7 100644 --- a/src-ts/lib/index.ts +++ b/src-ts/lib/index.ts @@ -10,9 +10,12 @@ export { authUrl, authUrlLogin, authUrlLogout, + authUrlSignup, + errorHandle, fileCreateFromCanvas, fileDownloadBlob, fileDownloadCanvasAsImage, + logError, logInfo, logInitialize, textFormatDateLocaleShortString, diff --git a/src-ts/lib/loading-spinner/LoadingSpinner.tsx b/src-ts/lib/loading-spinner/LoadingSpinner.tsx index 7a6b81617..9f735cd77 100644 --- a/src-ts/lib/loading-spinner/LoadingSpinner.tsx +++ b/src-ts/lib/loading-spinner/LoadingSpinner.tsx @@ -11,12 +11,17 @@ import styles from './LoadingSpinner.module.scss' export interface LoadingSpinnerProps { className?: string - show?: boolean + hide?: boolean } -const LoadingSpinner: FC = ({ show = false, className }: LoadingSpinnerProps) => { +const LoadingSpinner: FC = ({ hide, className }: LoadingSpinnerProps) => { + + if (!!hide) { + return <> + } + return ( -
+
) diff --git a/src-ts/lib/styles/_layout.scss b/src-ts/lib/styles/_layout.scss index f12d2f5fe..046b068dd 100644 --- a/src-ts/lib/styles/_layout.scss +++ b/src-ts/lib/styles/_layout.scss @@ -30,9 +30,17 @@ hr { display: none; } +.full-height-frame { + position: relative; + flex: 1 1 auto; + display: flex; + flex-direction: column; +} .mobile-hide { - &.mobile-hide.mobile-hide { // increase specificity without using !important + + // increase specificity without using !important + &.mobile-hide.mobile-hide { @include ltemd { display: none; } @@ -40,7 +48,9 @@ hr { } .desktop-hide { - &.desktop-hide.desktop-hide { // increase specificity without using !important + + // increase specificity without using !important + &.desktop-hide.desktop-hide { @include gtelg { display: none; } diff --git a/src-ts/tools/learn/course-certificate/certificate-view/CertificateView.tsx b/src-ts/tools/learn/course-certificate/certificate-view/CertificateView.tsx index 4748f2efa..465c19982 100644 --- a/src-ts/tools/learn/course-certificate/certificate-view/CertificateView.tsx +++ b/src-ts/tools/learn/course-certificate/certificate-view/CertificateView.tsx @@ -140,7 +140,7 @@ const CertificateView: FC = (props: CertificateViewProps) return ( <> - {!ready && } + {readyAndCompletedCertification && (
diff --git a/src-ts/tools/learn/course-certificate/my-certificate/MyCertificate.tsx b/src-ts/tools/learn/course-certificate/my-certificate/MyCertificate.tsx index 3c7946c1f..37099b643 100644 --- a/src-ts/tools/learn/course-certificate/my-certificate/MyCertificate.tsx +++ b/src-ts/tools/learn/course-certificate/my-certificate/MyCertificate.tsx @@ -23,14 +23,14 @@ const MyCertificate: FC<{}> = () => { }, [coursePath, navigate]) useEffect(() => { - if (profileReady && !profile) { - navigateToCourse() - } + if (profileReady && !profile) { + navigateToCourse() + } }, [profileReady, profile, navigateToCourse]) return ( <> - {!profileReady && } + {profileReady && profile && ( = () => { + const wrapElRef: MutableRefObject = useRef() const routeParams: Params = useParams() const [profile, setProfile]: [ - UserProfile|undefined, - Dispatch> + UserProfile | undefined, + Dispatch> ] = useState() - const [profileReady, setProfileReady]: [boolean, Dispatch>] = useState(false) + const [profileReady, setProfileReady]: [boolean, Dispatch>] = useState(false) const providerParam: string = routeParams.provider ?? '' const certificationParam: string = routeParams.certification ?? '' useEffect(() => { if (routeParams.memberHandle) { - profileGetAsync(routeParams.memberHandle).then((userProfile) => { - setProfile(userProfile) - setProfileReady(true) - }) + profileGetAsync(routeParams.memberHandle) + .then((userProfile) => { + setProfile(userProfile) + setProfileReady(true) + }) } }, [routeParams.memberHandle, setProfileReady]) @@ -39,7 +41,7 @@ const UserCertificate: FC<{}> = () => { [].forEach.call(el.parentElement?.children ?? [], (c: HTMLElement) => { if (c !== el) { - Object.assign(c.style, {display: 'none'}) + Object.assign(c.style, { display: 'none' }) } }) el.classList.add(styles['full-screen-cert']) @@ -47,7 +49,7 @@ const UserCertificate: FC<{}> = () => { return ( <> - {!profileReady && } + {profileReady && profile && (
@@ -55,7 +57,7 @@ const UserCertificate: FC<{}> = () => { certification={certificationParam} profile={profile} provider={providerParam} - onCertificationNotCompleted={() => {}} + onCertificationNotCompleted={() => { }} hideActions />
diff --git a/src-ts/tools/learn/course-completed/CourseCompletedPage.tsx b/src-ts/tools/learn/course-completed/CourseCompletedPage.tsx index 30605800d..cfb81ec4d 100755 --- a/src-ts/tools/learn/course-completed/CourseCompletedPage.tsx +++ b/src-ts/tools/learn/course-completed/CourseCompletedPage.tsx @@ -85,7 +85,7 @@ const CourseCompletedPage: FC<{}> = () => { return ( <> - {!ready && } + {ready && courseData && ( <> diff --git a/src-ts/tools/learn/course-details/CourseDetailsPage.tsx b/src-ts/tools/learn/course-details/CourseDetailsPage.tsx index a8847b309..756bbdfb1 100644 --- a/src-ts/tools/learn/course-details/CourseDetailsPage.tsx +++ b/src-ts/tools/learn/course-details/CourseDetailsPage.tsx @@ -118,7 +118,7 @@ const CourseDetailsPage: FC<{}> = () => { {!ready && (
- +
)} diff --git a/src-ts/tools/learn/free-code-camp/FreeCodeCamp.tsx b/src-ts/tools/learn/free-code-camp/FreeCodeCamp.tsx index 3c1a6f2c7..0208cd571 100644 --- a/src-ts/tools/learn/free-code-camp/FreeCodeCamp.tsx +++ b/src-ts/tools/learn/free-code-camp/FreeCodeCamp.tsx @@ -328,7 +328,7 @@ const FreeCodeCamp: FC<{}> = () => { return ( <> - {!ready && } + {lesson && ( diff --git a/src-ts/tools/learn/learn-lib/course-outline/CourseOutline.tsx b/src-ts/tools/learn/learn-lib/course-outline/CourseOutline.tsx index bc7b4ac10..4a1df0e45 100644 --- a/src-ts/tools/learn/learn-lib/course-outline/CourseOutline.tsx +++ b/src-ts/tools/learn/learn-lib/course-outline/CourseOutline.tsx @@ -34,7 +34,8 @@ const CourseOutline: FC = (props: CourseOutlineProps) => { return (
- {props.ready === false && } + + {props.course && (
diff --git a/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certifications.provider.tsx b/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certifications.provider.tsx index 6da6b87d4..e8e4b965b 100644 --- a/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certifications.provider.tsx +++ b/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certifications.provider.tsx @@ -1,6 +1,6 @@ import { Dispatch, SetStateAction, useContext, useEffect, useState } from 'react' -import { profileContext, ProfileContextData } from '../../../../lib' +import { errorHandle, profileContext, ProfileContextData } from '../../../../lib' import { UserCertificationCompleted } from './user-certification-completed.model' import { UserCertificationInProgress } from './user-certification-in-progress.model' @@ -64,6 +64,16 @@ export function useUserCertifications(): UserCertificationsProviderData { ready: true, })) }) + .catch((err: any) => { + errorHandle(err, 'There was an error getting your course progress.') + setState((prevState) => ({ + ...prevState, + completed: [], + inProgress: [], + loading: false, + ready: true, + })) + }) return () => { mounted = false diff --git a/src-ts/tools/learn/welcome/WelcomePage.tsx b/src-ts/tools/learn/welcome/WelcomePage.tsx index 2456d2d41..12008470f 100644 --- a/src-ts/tools/learn/welcome/WelcomePage.tsx +++ b/src-ts/tools/learn/welcome/WelcomePage.tsx @@ -1,6 +1,8 @@ +import classNames from 'classnames' import { FC } from 'react' import { ContentLayout, LoadingSpinner, Portal } from '../../../lib' +import '../../../lib/styles/index.scss' import { AllCertificationsProviderData, useAllCertifications, @@ -22,7 +24,9 @@ const WelcomePage: FC<{}> = () => { return ( -
+ +
+
= () => {
-
+
+

Courses Available

- {!coursesReady && ( - - )} + + {coursesReady && (
diff --git a/src-ts/tools/work/Work.tsx b/src-ts/tools/work/Work.tsx index 4c3f8378b..1b578545d 100644 --- a/src-ts/tools/work/Work.tsx +++ b/src-ts/tools/work/Work.tsx @@ -37,7 +37,7 @@ const Work: FC<{}> = () => { // if the profile isn't initialized, wait with the spinner if (!initialized) { - return + return } // if the profile is initialized, go to the self-service login diff --git a/src-ts/tools/work/work-lib/work-provider/work.provider.tsx b/src-ts/tools/work/work-lib/work-provider/work.provider.tsx index cfc44ec3f..2dfb523e1 100644 --- a/src-ts/tools/work/work-lib/work-provider/work.provider.tsx +++ b/src-ts/tools/work/work-lib/work-provider/work.provider.tsx @@ -1,6 +1,6 @@ import { Dispatch, FC, ReactNode, SetStateAction, useContext, useEffect, useState } from 'react' -import { profileContext, ProfileContextData, UserProfile } from '../../../../lib' +import { logError, profileContext, ProfileContextData, UserProfile } from '../../../../lib' import { WorkContextData } from './work-context-data.model' import { Work, workGetAllAsync, } from './work-functions' @@ -33,12 +33,12 @@ export const WorkProvider: FC<{ children: ReactNode }> = ({ children }: { childr setWorkContextData(contextData) } catch (error: any) { + logError(error) const contextData: WorkContextData = { + ...defaultWorkContextData, error: error.response?.data?.result?.content || error.message || error, - hasWork: false, initialized: true, refresh: getAndSetWork, - work: [], } setWorkContextData(contextData) } diff --git a/src-ts/tools/work/work-not-logged-in/WorkNotLoggedIn.tsx b/src-ts/tools/work/work-not-logged-in/WorkNotLoggedIn.tsx index c22a3995a..0e3e84024 100644 --- a/src-ts/tools/work/work-not-logged-in/WorkNotLoggedIn.tsx +++ b/src-ts/tools/work/work-not-logged-in/WorkNotLoggedIn.tsx @@ -40,7 +40,7 @@ const WorkNotLoggedIn: FC<{}> = () => { }, [isLoggedIn, initialized, navigate]) if (isLoading) { - return + return } function startWork(): void { diff --git a/src-ts/tools/work/work-self-service/intake-forms/review/Review.tsx b/src-ts/tools/work/work-self-service/intake-forms/review/Review.tsx index e6679adba..ea037e5e0 100644 --- a/src-ts/tools/work/work-self-service/intake-forms/review/Review.tsx +++ b/src-ts/tools/work/work-self-service/intake-forms/review/Review.tsx @@ -196,7 +196,7 @@ const Review: FC = () => { return (
- + {/* TODO: We need to not hard code the configs to that of BugHunt and instead use the challenge data to determine the WorkType */} = () => { @@ -131,7 +131,7 @@ const WorkTable: FC<{}> = () => { return ( <> {tabsElement} -
+
diff --git a/src-ts/utils/home/Home.tsx b/src-ts/utils/home/Home.tsx index 39afae600..d31c6ceae 100644 --- a/src-ts/utils/home/Home.tsx +++ b/src-ts/utils/home/Home.tsx @@ -6,10 +6,15 @@ import { routeContext, RouteContextData, } from '../../lib' +import '../../lib/styles/index.scss' const Home: FC<{}> = () => { - const { initialized, rootLoggedInRoute, rootLoggedOutFC }: RouteContextData = useContext(routeContext) + const { + initialized, + rootLoggedInRoute, + rootLoggedOutFC, + }: RouteContextData = useContext(routeContext) const navigate: NavigateFunction = useNavigate() @@ -26,12 +31,14 @@ const Home: FC<{}> = () => { ]) const LoggedOut: FC<{}> = rootLoggedOutFC - const showSpinner: boolean = !initialized || !!rootLoggedInRoute - - return <> - - {!showSpinner && } - + const showLoggedOut: boolean = initialized && !rootLoggedInRoute + + return ( +
+ + {showLoggedOut && } +
+ ) } export default Home