Skip to content

Commit e4cb992

Browse files
Merge pull request #448 from topcoder-platform/dev
TCA-838 Uni Nav Release - 2022-12-19 -> master
2 parents d03b35a + fe8e600 commit e4cb992

File tree

96 files changed

+2163
-2661
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

96 files changed

+2163
-2661
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
"swr": "^1.3.0",
7171
"tc-auth-lib": "topcoder-platform/tc-auth-lib#1.0.26",
7272
"typescript": "^4.8.4",
73+
"universal-navigation": "https://github.com/topcoder-platform/universal-navigation",
7374
"uuid": "^9.0.0"
7475
},
7576
"devDependencies": {

src-ts/.eslintrc.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ module.exports = {
7676
11
7777
],
7878
'import/extensions': 'off',
79+
'import/no-named-default': 'off',
7980
'import/prefer-default-export': 'off',
8081
'indent': [
8182
2,
@@ -105,6 +106,7 @@ module.exports = {
105106
120,
106107
],
107108
'no-extra-boolean-cast': 'off',
109+
'no-nested-ternary': 'off',
108110
'no-null/no-null': 'error',
109111
'no-param-reassign': [
110112
'error',

src-ts/App.tsx

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Dispatch, FC, ReactElement, SetStateAction, useContext, useEffect, useState } from 'react'
1+
import { FC, ReactElement, useContext } from 'react'
22
import { Routes } from 'react-router-dom'
33
import { toast, ToastContainer } from 'react-toastify'
44

@@ -7,22 +7,11 @@ import { routeContext, RouteContextData } from './lib'
77

88
const App: FC<{}> = () => {
99

10-
const [ready, setReady]: [boolean, Dispatch<SetStateAction<boolean>>] = useState<boolean>(false)
1110
const { allRoutes, getRouteElement }: RouteContextData = useContext(routeContext)
1211

1312
const routeElements: Array<ReactElement> = allRoutes
1413
.map(route => getRouteElement(route))
1514

16-
useEffect(() => {
17-
setReady(true)
18-
}, [])
19-
20-
useEffect(() => {
21-
if (ready) {
22-
document.getElementById('root')?.classList.add('app-ready')
23-
}
24-
}, [ready])
25-
2615
return (
2716
<>
2817
<Header />

src-ts/config/constants.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
export enum ToolTitle {
2-
learn = 'Learn',
2+
dev = 'Dev Center',
3+
game = 'Gamification Admin',
34
settings = 'Account Settings',
4-
work = 'Work',
5+
support = 'Support',
6+
tca = 'Topcoder Academy',
7+
work = 'Self Service Challenges',
58
}
9+
10+
export const PageSubheaderPortalId: 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
@@ -14,6 +14,9 @@ export const EnvironmentConfigDefault: EnvironmentConfigModel = {
1414
V3: 'https://api.topcoder-dev.com/v3',
1515
V5: 'https://api.topcoder-dev.com/v5',
1616
},
17+
AUTH: {
18+
ACCOUNTS_APP_CONNECTOR: 'https://accounts-auth0.topcoder-dev.com',
19+
},
1720
ENV: 'default',
1821
LOGGING: {
1922
PUBLIC_TOKEN: 'puba0825671e469d16f940c5a30dc738f11',
@@ -41,7 +44,7 @@ export const EnvironmentConfigDefault: EnvironmentConfigModel = {
4144
USER_PROFILE: `${COMMUNITY_WEBSITE}/members`,
4245
WP_CONTENT: `${COMMUNITY_WEBSITE}/wp-content`,
4346
},
44-
URL: {
45-
ACCOUNTS_APP_CONNECTOR: 'https://accounts-auth0.topcoder-dev.com',
47+
UNIVERSAL_NAV: {
48+
URL: 'https://uni-nav.topcoder-dev.com/v1/tc-universal-nav.js',
4649
},
4750
}

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ export const EnvironmentConfigProd: EnvironmentConfigModel = {
1616
V3: 'https://api.topcoder.com/v3',
1717
V5: 'https://api.topcoder.com/v5',
1818
},
19+
AUTH: {
20+
ACCOUNTS_APP_CONNECTOR: 'https://accounts-auth0.topcoder.com',
21+
},
1922
DISABLED_TOOLS: [],
2023
ENV: 'prod',
2124
SPRIG: {
@@ -39,7 +42,7 @@ export const EnvironmentConfigProd: EnvironmentConfigModel = {
3942
USER_PROFILE: `${COMMUNITY_WEBSITE}/members`,
4043
WP_CONTENT: `${COMMUNITY_WEBSITE}/wp-content`,
4144
},
42-
URL: {
43-
ACCOUNTS_APP_CONNECTOR: 'https://accounts-auth0.topcoder.com',
45+
UNIVERSAL_NAV: {
46+
URL: 'https://uni-nav.topcoder.com/v1/tc-universal-nav.js',
4447
},
4548
}

src-ts/header/Header.module.scss

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

src-ts/header/Header.tsx

Lines changed: 155 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,157 @@
1-
import { FC } from 'react'
2-
3-
import { Logo } from './logo'
4-
import { ToolSelectors } from './tool-selectors'
5-
import { UtilitySelectors } from './utility-selectors'
6-
import styles from './Header.module.scss'
7-
8-
const Header: FC<{}> = () => (
9-
<div className={styles['header-wrap']}>
10-
<header className={styles.header}>
11-
<ToolSelectors isWide={false} />
12-
<Logo />
13-
<ToolSelectors isWide />
14-
<UtilitySelectors />
15-
</header>
16-
<div id='page-subheader-portal-el' className={styles.subheader} />
17-
</div>
18-
)
1+
import {
2+
Dispatch,
3+
FC,
4+
MutableRefObject,
5+
SetStateAction,
6+
useCallback,
7+
useContext,
8+
useEffect,
9+
useMemo,
10+
useRef,
11+
useState,
12+
} from 'react'
13+
import { NavigateFunction, useNavigate } from 'react-router-dom'
14+
import type { AuthUser as NavAuthUser, TcUniNavFn } from 'universal-navigation'
15+
import classNames from 'classnames'
16+
17+
import { EnvironmentConfig, PageSubheaderPortalId } from '../config'
18+
import {
19+
authUrlLogin,
20+
authUrlLogout,
21+
authUrlSignup,
22+
profileContext,
23+
ProfileContextData,
24+
routeContext,
25+
RouteContextData,
26+
} from '../lib'
27+
28+
import UniNavSnippet from './universal-nav-snippet'
29+
30+
declare let tcUniNav: TcUniNavFn
31+
UniNavSnippet(EnvironmentConfig.UNIVERSAL_NAV.URL)
32+
33+
interface NavigationRequest {
34+
label: string
35+
path: string
36+
}
37+
38+
const Header: FC = () => {
39+
40+
const { activeToolName, activeToolRoute }: RouteContextData = useContext(routeContext)
41+
const { profile, initialized: profileReady }: ProfileContextData = useContext(profileContext)
42+
const [ready, setReady]: [boolean, Dispatch<SetStateAction<boolean>>] = useState<boolean>(false)
43+
const headerInit: MutableRefObject<boolean> = useRef(false)
44+
const navElementId: string = 'main-nav-el'
45+
const navigate: NavigateFunction = useNavigate()
46+
47+
// userinfo will be an empty object until profileReady=true
48+
// userinfo will be {user: undefined} if user is logged out
49+
// userinfo will have all user's details when user is logged in
50+
const userInfo: {} | undefined | NavAuthUser = useMemo(() => (
51+
!profileReady ? {} : ({
52+
user: profile ? {
53+
email: profile.email,
54+
firstName: profile.firstName,
55+
handle: profile.handle,
56+
lastName: profile.lastName,
57+
photoUrl: profile.photoURL,
58+
userId: profile.userId,
59+
} : undefined,
60+
})
61+
), [profile, profileReady])
62+
63+
const navigationHandler: (request: NavigationRequest) => void
64+
= useCallback((request: NavigationRequest) => {
65+
66+
try {
67+
// strip the domain and navigate to the path
68+
navigate(new URL(request.path).pathname)
69+
} catch (error) {
70+
// if we couldn't navigate to the path, just go to the route of the currently active tool
71+
navigate(new URL(activeToolRoute || '/').pathname)
72+
}
73+
74+
}, [
75+
activeToolRoute,
76+
navigate,
77+
])
78+
79+
// initialize uni-nav elements
80+
useEffect(() => {
81+
82+
if (headerInit.current) {
83+
return
84+
}
85+
86+
headerInit.current = true
87+
88+
tcUniNav(
89+
'init',
90+
navElementId,
91+
{
92+
handleNavigation: navigationHandler,
93+
onReady() { setReady(true) },
94+
signIn() { window.location.href = authUrlLogin() },
95+
signOut() { window.location.href = authUrlLogout },
96+
signUp() { window.location.href = authUrlSignup() },
97+
toolName: activeToolName,
98+
toolRoot: activeToolRoute,
99+
type: 'tool',
100+
...userInfo,
101+
},
102+
)
103+
}, [
104+
activeToolName,
105+
activeToolRoute,
106+
navigationHandler,
107+
userInfo,
108+
profileReady,
109+
])
110+
111+
// update uni-nav's tool details
112+
useEffect(() => {
113+
114+
tcUniNav(
115+
'update',
116+
navElementId,
117+
{
118+
toolName: activeToolName,
119+
toolRoot: activeToolRoute,
120+
},
121+
)
122+
}, [
123+
activeToolName,
124+
activeToolRoute,
125+
])
126+
127+
// update uni-nav's user/auth details
128+
useEffect(() => {
129+
130+
if (!profileReady) {
131+
return
132+
}
133+
134+
tcUniNav(
135+
'update',
136+
navElementId,
137+
{
138+
...userInfo,
139+
},
140+
)
141+
}, [
142+
profileReady,
143+
userInfo,
144+
])
145+
146+
return (
147+
<>
148+
<div id={navElementId} />
149+
<div
150+
id={PageSubheaderPortalId}
151+
className={classNames('full-width-relative', !ready && 'hidden')}
152+
/>
153+
</>
154+
)
155+
}
19156

20157
export default Header

src-ts/header/README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Topcoder Universal Navigation
2+
3+
The Platform UI project uses the Topcoder Universal navigation ([README](https://github.com/topcoder-platform/universal-navigation)).
4+
5+
## Uni-nav Versions
6+
7+
The Uni-nav is a hosted JS library. There are currently dev and prod versions of the library located at:
8+
9+
https://uni-nav.topcoder.com/v1/tc-universal-nav.js
10+
11+
https://uni-nav.topcoder-dev.com/v1/tc-universal-nav.js
12+
13+
The URL is set at build time with the [Global Config](../lib/global-config.model.ts) `UNIVERSAL_NAV.URL` property.
14+
15+
>See the [Local Environment Setup](../../README.md#local-environment-setup) section of the main README for instructions on how to set your environment configuration.
16+
17+
>See the [Uni-Nav Version README](https://github.com/topcoder-platform/universal-navigation#versioning) for more information about versioning.
18+
19+
## Uni-nav Initialization
20+
21+
The Header uses the `tcUniNav` method to initialize the nav with:
22+
23+
- active tool name
24+
- active tool root route
25+
- current user, if logged in
26+
- action handler callbacks (e.g. navigation, log in, log out, sign up)
27+
28+
Because the Platform UI hosts multiple tools, each time the user navigates to a new tool, the Header updates the uni-nav w/the active tool info.

src-ts/header/logo/Logo.module.scss

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

0 commit comments

Comments
 (0)