Skip to content

Commit 0fd1610

Browse files
PROD-3232 #comment This commit adds the uni nav snippet and does a little linting and config refactor. #time 2h
1 parent 4680696 commit 0fd1610

File tree

12 files changed

+141
-65
lines changed

12 files changed

+141
-65
lines changed

src-ts/config/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ export enum ToolTitle {
33
settings = 'Account Settings',
44
work = 'Work',
55
}
6+
7+
export const PagePortalId: string = 'page-subheader-portal-el'

src-ts/config/environments/environment.default.config.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ export const EnvironmentConfigDefault: EnvironmentConfigModel = {
1313
V3: 'https://api.topcoder-dev.com/v3',
1414
V5: 'https://api.topcoder-dev.com/v5',
1515
},
16+
AUTH: {
17+
ACCOUNTS_APP_CONNECTOR: 'https://accounts-auth0.topcoder-dev.com',
18+
},
1619
ENV: 'default',
1720
LOGGING: {
1821
PUBLIC_TOKEN: 'puba0825671e469d16f940c5a30dc738f11',
@@ -37,7 +40,7 @@ export const EnvironmentConfigDefault: EnvironmentConfigModel = {
3740
USER_PROFILE: `${COMMUNITY_WEBSITE}/members`,
3841
WP_CONTENT: `${COMMUNITY_WEBSITE}/wp-content`,
3942
},
40-
URL: {
41-
ACCOUNTS_APP_CONNECTOR: 'https://accounts-auth0.topcoder-dev.com',
43+
UNIVERSAL_NAV: {
44+
URL: 'https://uni-nav.topcoder-dev.com/tc-universal-nav.js',
4245
},
4346
}

src-ts/config/environments/environment.prod.config.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ export const EnvironmentConfigProd: EnvironmentConfigModel = {
1515
V3: 'https://api.topcoder.com/v3',
1616
V5: 'https://api.topcoder.com/v5',
1717
},
18+
AUTH: {
19+
ACCOUNTS_APP_CONNECTOR: 'https://accounts-auth0.topcoder.com',
20+
},
1821
DISABLED_TOOLS: [],
1922
ENV: 'prod',
2023
// TODO: Move stripe creds to .env file
@@ -35,7 +38,7 @@ export const EnvironmentConfigProd: EnvironmentConfigModel = {
3538
USER_PROFILE: `${COMMUNITY_WEBSITE}/members`,
3639
WP_CONTENT: `${COMMUNITY_WEBSITE}/wp-content`,
3740
},
38-
URL: {
39-
ACCOUNTS_APP_CONNECTOR: 'https://accounts-auth0.topcoder.com',
41+
UNIVERSAL_NAV: {
42+
URL: 'https://uni-nav.topcoder.com/tc-universal-nav.js',
4043
},
4144
}

src-ts/header/Header.module.scss

Lines changed: 0 additions & 27 deletions
This file was deleted.

src-ts/header/Header.tsx

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,62 @@
1-
import { FC } from 'react'
1+
import { Dispatch, FC, MutableRefObject, SetStateAction, useContext, useEffect, useRef, useState } from 'react'
2+
import classNames from 'classnames'
23

3-
import styles from './Header.module.scss'
4-
import { Logo } from './logo'
5-
import { ToolSelectors } from './tool-selectors'
6-
import { UtilitySelectors } from './utility-selectors'
4+
import { EnvironmentConfig, PagePortalId } from '../config'
5+
import { authUrlLogin, authUrlLogout, authUrlSignup, profileContext, ProfileContextData } from '../lib'
6+
7+
import UniNavSnippet from './universal-nav-snippet'
8+
9+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
10+
declare let tcUniNav: any
11+
12+
const Header: FC = () => {
13+
14+
const { profile, initialized: profileReady }: ProfileContextData = useContext(profileContext)
15+
const [ready, setReady]: [boolean, Dispatch<SetStateAction<boolean>>] = useState<boolean>(false)
16+
const headerInit: MutableRefObject<boolean> = useRef(false)
17+
const navElementId: string = 'main-nav-el'
18+
19+
useEffect(() => {
20+
21+
UniNavSnippet(EnvironmentConfig.UNIVERSAL_NAV.URL)
22+
23+
if (headerInit.current || !profileReady || !tcUniNav) {
24+
return
25+
}
26+
27+
headerInit.current = true
28+
29+
tcUniNav(
30+
'tool',
31+
navElementId,
32+
{
33+
onReady() {
34+
setReady(true)
35+
document.getElementById('root')?.classList.add('app-ready')
36+
},
37+
signIn() { window.location.href = authUrlLogin() },
38+
signOut() { window.location.href = authUrlLogout },
39+
signUp() { window.location.href = authUrlSignup() },
40+
// TODO: make this dynamic based on the current URL
41+
toolName: 'Topcoder Academy',
42+
user: profileReady && profile ? {
43+
handle: profile.handle,
44+
initials: `${profile.firstName.charAt(0)}${profile.lastName.charAt(0)}`,
45+
photoURL: profile.photoURL,
46+
userId: profile.userId,
47+
} : undefined,
48+
},
49+
)
50+
}, [profileReady, profile])
751

8-
const Header: FC<{}> = () => {
952
return (
10-
<div className={styles['header-wrap']}>
11-
<header className={styles.header}>
12-
<ToolSelectors isWide={false} />
13-
<Logo />
14-
<ToolSelectors isWide={true} />
15-
<UtilitySelectors />
16-
</header>
17-
<div id='page-subheader-portal-el' className={styles.subheader}></div>
18-
</div>
53+
<>
54+
<div id={navElementId} />
55+
<div
56+
id={PagePortalId}
57+
className={classNames('full-width-relative', !ready && 'hidden')}
58+
/>
59+
</>
1960
)
2061
}
2162

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/* eslint-disable func-names */
2+
/* eslint-disable no-param-reassign */
3+
/* eslint-disable prefer-rest-params */
4+
/* eslint-disable @typescript-eslint/typedef */
5+
/* eslint-disable no-unused-expressions */
6+
/* eslint-disable @typescript-eslint/explicit-function-return-type */
7+
8+
function UniNavSnippet(url) {
9+
10+
!(function (n, t, e, a, c, i, o) {
11+
12+
n.TcUnivNavConfig = c
13+
14+
n[c] = n[c] || function () {
15+
(n[c].q = n[c].q ?? []).push(arguments)
16+
}
17+
18+
n[c].l = 1 * new Date()
19+
20+
i = t.createElement(e)
21+
22+
o = t.getElementsByTagName(e)[0]
23+
24+
i.async = 1
25+
26+
i.type = 'module'
27+
28+
i.src = a; o.parentNode.insertBefore(i, o)
29+
30+
}(window, document, 'script', url, 'tcUniNav'))
31+
}
32+
33+
export default UniNavSnippet

src-ts/lib/breadcrumb/Breadcrumb.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { FC } from 'react'
22
import { createPortal } from 'react-dom'
33

4+
import { PagePortalId } from '../../config'
5+
46
import { BreadcrumbItem, BreadcrumbItemModel } from './breadcrumb-item'
57
import styles from './Breadcrumb.module.scss'
68

@@ -9,7 +11,7 @@ interface BreadcrumbProps {
911
}
1012

1113
const Breadcrumb: FC<BreadcrumbProps> = (props: BreadcrumbProps) => {
12-
const portalRootEl: HTMLElement|null = document.getElementById('page-subheader-portal-el')
14+
const portalRootEl: HTMLElement | null = document.getElementById(PagePortalId)
1315

1416
if (!portalRootEl) {
1517
return <></>

src-ts/lib/functions/authentication-functions/authentication-url.config.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@ import { EnvironmentConfig } from '../../../config'
22

33
import { AuthenticationRegistrationSource } from './authentication-reg-source.enum'
44

5-
export const authentication: string = EnvironmentConfig.URL.ACCOUNTS_APP_CONNECTOR
5+
export const authentication: string = EnvironmentConfig.AUTH.ACCOUNTS_APP_CONNECTOR
66

77
export function login(returnUrl?: string): string {
88
const retUrl: string = returnUrl ?? window.location.href.match(/[^?]*/)?.[0] ?? window.location.host
99
return `${authentication}?retUrl=${encodeURIComponent(retUrl)}`
1010
}
1111

12-
export const logout: string = `${authentication}?logout=true&retUrl=${encodeURIComponent('https://' + window.location.host)}`
12+
export const logout: string
13+
= `${authentication}?logout=true&retUrl=${encodeURIComponent(`https://${window.location.host}`)}`
1314

1415
export function signup(returnUrl?: string, regSource?: AuthenticationRegistrationSource): string {
1516
return `${login(returnUrl)}&mode=signUp${!!regSource ? `&regSource=${regSource}` : ''}`

src-ts/lib/global-config.model.ts

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ export interface GlobalConfig {
99
V3: string
1010
V5: string
1111
}
12+
AUTH: {
13+
ACCOUNTS_APP_CONNECTOR: string
14+
}
1215
DISABLED_TOOLS?: Array<string>
1316
ENV: string
1417
GAMIFICATION: {
@@ -26,15 +29,15 @@ export interface GlobalConfig {
2629
CUSTOMER_TOKEN: string
2730
}
2831
TOPCODER_URLS: {
29-
API_BASE: string,
30-
BLOG_PAGE: string,
31-
CHALLENGES_PAGE: string,
32-
GIGS_PAGE: string,
33-
THRIVE_PAGE: string,
34-
USER_PROFILE: string,
35-
WP_CONTENT: string,
32+
API_BASE: string
33+
BLOG_PAGE: string
34+
CHALLENGES_PAGE: string
35+
GIGS_PAGE: string
36+
THRIVE_PAGE: string
37+
USER_PROFILE: string
38+
WP_CONTENT: string
39+
}
40+
UNIVERSAL_NAV: {
41+
URL: string
3642
}
37-
URL: {
38-
ACCOUNTS_APP_CONNECTOR: string
39-
},
4043
}

src-ts/lib/styles/_layout.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,7 @@ hr {
6161
}
6262
}
6363
}
64+
65+
.hidden {
66+
display: none;
67+
}

src-ts/tools/learn/my-learning/MyLearning.tsx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
import { Dispatch, FC, ReactNode, SetStateAction, useContext, useMemo, useState } from 'react'
22

3-
import { Breadcrumb, BreadcrumbItemModel, ContentLayout, LoadingSpinner, Portal, profileContext, ProfileContextData } from '../../../lib'
3+
import { PagePortalId } from '../../../config'
4+
import {
5+
Breadcrumb,
6+
BreadcrumbItemModel,
7+
ContentLayout,
8+
LoadingSpinner,
9+
Portal,
10+
profileContext,
11+
ProfileContextData,
12+
} from '../../../lib'
413
import {
514
AllCertificationsProviderData,
615
LearnCertification,
@@ -27,7 +36,8 @@ const MyLearning: FC<{}> = () => {
2736
const { profile, initialized: profileReady }: ProfileContextData = useContext(profileContext)
2837
const { completed, inProgress, ready: coursesReady }: UserCertificationsProviderData = useGetUserCertifications()
2938
const { certifications, ready: certificatesReady }: AllCertificationsProviderData = useGetAllCertifications()
30-
const [activeTab, setActiveTab]: [MyTabsViews|undefined, Dispatch<SetStateAction<MyTabsViews|undefined>>] = useState()
39+
const [activeTab, setActiveTab]: [MyTabsViews | undefined, Dispatch<SetStateAction<MyTabsViews | undefined>>]
40+
= useState()
3141

3242
const ready: boolean = profileReady && coursesReady && certificatesReady
3343

@@ -73,7 +83,7 @@ const MyLearning: FC<{}> = () => {
7383
<div className={styles['wrap']}>
7484
<LoadingSpinner hide={ready} className={styles['loading-spinner']} />
7585

76-
<Portal portalId='page-subheader-portal-el'>
86+
<Portal portalId={PagePortalId}>
7787
<div className={styles['hero-wrap']}>
7888
<WaveHero
7989
title='my learning'

src-ts/tools/learn/welcome/WelcomePage.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
import classNames from 'classnames'
21
import { FC } from 'react'
2+
import classNames from 'classnames'
33

4+
import { PagePortalId } from '../../../config'
45
import { ContentLayout, LoadingSpinner, Portal } from '../../../lib'
5-
import '../../../lib/styles/index.scss'
66
import {
77
AllCertificationsProviderData,
88
useGetAllCertifications,
99
useGetUserCertifications,
1010
UserCertificationsProviderData,
1111
WaveHero,
1212
} from '../learn-lib'
13+
import '../../../lib/styles/index.scss'
1314

1415
import { AvailableCoursesList } from './available-courses-list'
1516
import { ProgressBlock } from './progress-block'
@@ -28,7 +29,7 @@ const WelcomePage: FC<{}> = () => {
2829

2930
<div className={classNames(styles.wrap, 'full-height-frame')}>
3031

31-
<Portal portalId='page-subheader-portal-el'>
32+
<Portal portalId={PagePortalId}>
3233
<div className={styles['hero-wrap']}>
3334
<WaveHero
3435
title={(

0 commit comments

Comments
 (0)