Skip to content

Commit 6a9da93

Browse files
Merge pull request #419 from topcoder-platform/dev-qa
qa -> develop
2 parents 10cbbc9 + e5b11c4 commit 6a9da93

File tree

40 files changed

+351
-141
lines changed

40 files changed

+351
-141
lines changed

src-ts/header/logo/Logo.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
1-
import { FC } from 'react'
1+
import { FC, useContext } from 'react'
22
import { Link, useLocation } from 'react-router-dom'
33

4-
import { LogoIcon, routeIsHome, routeRoot } from '../../lib'
4+
import { LogoIcon, routeContext, RouteContextData } from '../../lib'
55
import '../../lib/styles/index.scss'
66

77
import styles from './Logo.module.scss'
88

99
const Logo: FC<{}> = () => {
1010

11+
const {
12+
isRootRoute,
13+
rootLoggedInRoute,
14+
}: RouteContextData = useContext(routeContext)
15+
1116
// the logo should be a link to the home page for all pages except the home page(
12-
const isLink: boolean = !routeIsHome(useLocation().pathname)
17+
const isLink: boolean = !isRootRoute(useLocation().pathname)
1318

1419
return (
1520
<div className={styles[`logo-${!isLink ? 'no-' : ''}link`]}>
1621
<Link
1722
tabIndex={-1}
18-
to={routeRoot}
23+
to={rootLoggedInRoute}
1924
>
2025
<LogoIcon />
2126
</Link>

src-ts/header/tool-selectors/tool-selectors-narrow/ToolSelectorsNarrow.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ import styles from './ToolSelectorsNarrow.module.scss'
88

99
const ToolSelectorsNarrow: FC<{}> = () => {
1010

11-
const { toolsRoutes }: RouteContextData = useContext(routeContext)
11+
const { toolsRoutesForNav }: RouteContextData = useContext(routeContext)
1212
const [isOpen, setIsOpen]: [boolean, Dispatch<SetStateAction<boolean>>] = useState<boolean>(false)
1313

14-
const toolSelectors: Array<JSX.Element> = toolsRoutes
14+
const toolSelectors: Array<JSX.Element> = toolsRoutesForNav
1515
.map(route => (
1616
<ToolSelectorNarrow
1717
key={route.title}

src-ts/header/tool-selectors/tool-selectors-narrow/tool-selector-narrow/ToolSelectorNarrow.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import classNames from 'classnames'
22
import { FC, useContext } from 'react'
33
import { Link, useLocation } from 'react-router-dom'
44

5-
import { IconOutline, PlatformRoute, routeContext, RouteContextData, routeIsActive } from '../../../../lib'
5+
import { IconOutline, PlatformRoute, routeContext, RouteContextData } from '../../../../lib'
66

77
import styles from './ToolSelectorNarrow.module.scss'
88

@@ -14,12 +14,15 @@ const isParamRoute: (route: string) => boolean = (route: string) => !!route.matc
1414

1515
const ToolSelectorNarrow: FC<ToolSelectorNarrowProps> = (props: ToolSelectorNarrowProps) => {
1616

17-
const { getPathFromRoute }: RouteContextData = useContext(routeContext)
17+
const {
18+
getPathFromRoute,
19+
isActiveRoute,
20+
}: RouteContextData = useContext(routeContext)
1821
const toolRoute: PlatformRoute = props.route
1922
const toolPath: string = getPathFromRoute(toolRoute)
2023

2124
const baseClass: string = 'tool-selector-narrow'
22-
const isActive: boolean = routeIsActive(useLocation().pathname, toolPath)
25+
const isActive: boolean = isActiveRoute(useLocation().pathname, toolPath)
2326
const activeIndicaterClass: string = `${baseClass}-${isActive ? '' : 'in'}active`
2427
const hasChildren: boolean = !!toolRoute.children.some(child => !!child.route && !isParamRoute(child.route))
2528

src-ts/header/tool-selectors/tool-selectors-wide/ToolSelectorsWide.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ import styles from './ToolSelectorsWide.module.scss'
77

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

10-
const { toolsRoutes }: RouteContextData = useContext(routeContext)
10+
const { toolsRoutesForNav }: RouteContextData = useContext(routeContext)
1111

12-
const selectors: Array<JSX.Element> = toolsRoutes
12+
const selectors: Array<JSX.Element> = toolsRoutesForNav
1313
.map(route => (
1414
<ToolSelectorWide
1515
key={route.title}

src-ts/header/tool-selectors/tool-selectors-wide/tool-selector-wide/ToolSelectorWide.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ import {
66
PlatformRoute,
77
routeContext,
88
RouteContextData,
9-
routeIsActive,
10-
routeIsHome,
119
} from '../../../../lib'
1210
import '../../../../lib/styles/index.scss'
1311

@@ -19,17 +17,21 @@ interface ToolSelectorWideProps {
1917

2018
const ToolSelectorWide: FC<ToolSelectorWideProps> = (props: ToolSelectorWideProps) => {
2119

22-
const { getPathFromRoute }: RouteContextData = useContext(routeContext)
20+
const {
21+
getPathFromRoute,
22+
isActiveRoute,
23+
isRootRoute,
24+
}: RouteContextData = useContext(routeContext)
2325
const activePath: string = useLocation().pathname
2426
const toolRoute: PlatformRoute = props.route
2527
const toolPath: string = getPathFromRoute(toolRoute)
2628

27-
const isActive: boolean = routeIsActive(activePath, toolPath)
29+
const isActive: boolean = isActiveRoute(activePath, toolPath)
2830

2931
const activeIndicatorClass: string = `tool-selector-wide-${isActive ? '' : 'in'}active`
3032

3133
// the tool link should be usable for all active routes except the home page
32-
const isLink: boolean = isActive && !routeIsHome(activePath)
34+
const isLink: boolean = isActive && !isRootRoute(activePath)
3335

3436
return (
3537
<div className={classNames(

src-ts/header/utility-selectors/UtilitySelector/ProfileSelector/profile-logged-in/profile-panel/ProfilePanel.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ interface ProfilePanelProps {
2121
const ProfilePanel: FC<ProfilePanelProps> = (props: ProfilePanelProps) => {
2222

2323
const { profile }: ProfileContextData = useContext(profileContext)
24-
const { getPath }: RouteContextData = useContext(routeContext)
24+
const {
25+
getPath,
26+
rootLoggedOutRoute,
27+
}: RouteContextData = useContext(routeContext)
2528

2629
const navigate: NavigateFunction = useNavigate()
2730

@@ -58,7 +61,7 @@ const ProfilePanel: FC<ProfilePanelProps> = (props: ProfilePanelProps) => {
5861
</span>
5962
</div>
6063
<a
61-
href={authUrlLogout}
64+
href={authUrlLogout(rootLoggedOutRoute)}
6265
className={classNames(styles.logout, styles['nav-item'])}
6366
>
6467
<span className={styles.icon}>

src-ts/header/utility-selectors/UtilitySelector/ProfileSelector/profile-not-logged-in/ProfileNotLoggedIn.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
import { FC } from 'react'
1+
import { FC, useContext } from 'react'
22

3-
import { authUrlLogin, authUrlSignup, Button, routeRoot } from '../../../../../lib'
3+
import { authUrlLogin, authUrlSignup, Button, routeContext, RouteContextData } from '../../../../../lib'
44
import '../../../../../lib/styles/index.scss'
55

66
import styles from './ProfileNotLoggedIn.module.scss'
77

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

10+
const { rootLoggedInRoute }: RouteContextData = useContext(routeContext)
11+
1012
return (
1113
<>
1214
<Button
@@ -15,15 +17,15 @@ const ProfileNotLoggedIn: FC<{}> = () => {
1517
label='Log In'
1618
size='md'
1719
tabIndex={-1}
18-
url={authUrlLogin(routeRoot)}
20+
url={authUrlLogin(rootLoggedInRoute)}
1921
/>
2022
<Button
2123
buttonStyle='tertiary'
2224
className={styles.signup}
2325
label='Sign Up'
2426
size='md'
2527
tabIndex={-1}
26-
url={authUrlSignup(routeRoot)}
28+
url={authUrlSignup(rootLoggedInRoute)}
2729
/>
2830
</>
2931
)

src-ts/lib/modals/contact-support-modal/ContactSupportModal.module.scss renamed to src-ts/lib/contact-support-form/ContactSupportForm.module.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@import '../../styles/includes';
1+
@import '../styles/includes';
22

33
.contact-support-intro {
44

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { FC, useContext } from 'react'
2+
3+
import { Form, FormDefinition, formGetInputModel, FormInputModel } from '../form'
4+
import { profileContext, ProfileContextData } from '../profile-provider'
5+
6+
import { ContactSupportFormField } from './contact-support-form.config'
7+
import { ContactSupportRequest } from './contact-support-functions'
8+
import { contactSupportSubmitRequestAsync } from './contact-support-functions/contact-support-store'
9+
import styles from './ContactSupportForm.module.scss'
10+
11+
export interface ContactSupportFormProps {
12+
formDef: FormDefinition
13+
onSave: () => void
14+
workId?: string
15+
}
16+
17+
const ContactSupportForm: FC<ContactSupportFormProps> = (props: ContactSupportFormProps) => {
18+
19+
const { profile }: ProfileContextData = useContext(profileContext)
20+
21+
function generateRequest(inputs: ReadonlyArray<FormInputModel>): ContactSupportRequest {
22+
const firstName: string = formGetInputModel(inputs, ContactSupportFormField.first).value as string
23+
const lastName: string = formGetInputModel(inputs, ContactSupportFormField.last).value as string
24+
const email: string = formGetInputModel(inputs, ContactSupportFormField.email).value as string
25+
const question: string = formGetInputModel(inputs, ContactSupportFormField.question).value as string
26+
return {
27+
challengeId: props.workId,
28+
email,
29+
firstName,
30+
isSelfService: true,
31+
lastName,
32+
question,
33+
}
34+
}
35+
36+
async function saveAsync(request: ContactSupportRequest): Promise<void> {
37+
return contactSupportSubmitRequestAsync(request)
38+
.then(() => {
39+
props.onSave()
40+
})
41+
}
42+
43+
const emailElement: JSX.Element | undefined = !!profile?.email
44+
? (
45+
<>
46+
&nbsp;at <strong>{profile.email}</strong>
47+
</>
48+
)
49+
: undefined
50+
51+
return (
52+
<>
53+
<div className={styles['contact-support-intro']}>
54+
<p>
55+
Hi {profile?.firstName || 'there'}, we're here to help.
56+
</p>
57+
<p>
58+
Please describe what you'd like to discuss, and a
59+
Topcoder Solutions Expert will email you back
60+
{emailElement}
61+
&nbsp;within one business day.
62+
</p>
63+
</div>
64+
65+
<Form
66+
formDef={props.formDef}
67+
formValues={profile}
68+
requestGenerator={generateRequest}
69+
save={saveAsync}
70+
/>
71+
</>
72+
)
73+
}
74+
75+
export default ContactSupportForm

src-ts/lib/modals/contact-support-modal/contact-support-form.config.ts renamed to src-ts/lib/contact-support-form/contact-support-form.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { FormDefinition, validatorEmail, validatorRequired } from '../../form'
1+
import { FormDefinition, validatorEmail, validatorRequired } from '../form'
22

33
export enum ContactSupportFormField {
44
email = 'email',
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { EnvironmentConfig } from '../../../../../config'
2-
import { xhrPostAsync } from '../../../../functions'
1+
import { EnvironmentConfig } from '../../../../config'
2+
import { xhrPostAsync } from '../../../functions'
33

44
import { ContactSupportRequest } from './contact-support-request.model'
55

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { default as ContactSupportForm } from './ContactSupportForm'
2+
export { contactSupportFormDef } from './contact-support-form.config'

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import { EnvironmentConfig } from '../../../config'
2-
import { routeSelfServiceRoot } from '../../route-provider'
32

43
export const authentication: string = EnvironmentConfig.URL.ACCOUNTS_APP_CONNECTOR
54

65
export function login(fallback: string): string {
76
return `${authentication}?retUrl=${encodeURIComponent(window.location.href.match(/[^?]*/)?.[0] || fallback)}`
87
}
98

10-
export const logout: string = `${authentication}?logout=true&retUrl=${encodeURIComponent('https://' + window.location.host)}${routeSelfServiceRoot}`
9+
export function logout(loggedOutRoute: string): string {
10+
return `${authentication}?logout=true&retUrl=${encodeURIComponent('https://' + window.location.host)}${loggedOutRoute}`
11+
}
1112

1213
export function signup(fallback: string): string {
1314
return `${login(fallback)}&regSource=tcBusiness&mode=signUp`

src-ts/lib/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export * from './avatar'
22
export * from './breadcrumb'
33
export * from './button'
44
export * from './card'
5+
export * from './contact-support-form'
56
export * from './content-layout'
67
export * from './form'
78
export * from './global-config.model'

src-ts/lib/modals/contact-support-modal/ContactSupportModal.tsx

Lines changed: 5 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
1-
import { Dispatch, FC, SetStateAction, useContext, useState } from 'react'
1+
import { Dispatch, FC, SetStateAction, useState } from 'react'
22

3-
import { Form, FormDefinition, formGetInputModel, FormInputModel, formOnReset } from '../../form'
4-
import { profileContext, ProfileContextData } from '../../profile-provider'
3+
import { ContactSupportForm, contactSupportFormDef } from '../../contact-support-form'
4+
import { FormDefinition, formOnReset } from '../../form'
55
import { BaseModal } from '../base-modal'
66

7-
import { contactSupportFormDef, ContactSupportFormField } from './contact-support-form.config'
8-
import { ContactSupportRequest } from './contact-support-functions'
9-
import { contactSupportSubmitRequestAsync } from './contact-support-functions/contact-support-store'
10-
import styles from './ContactSupportModal.module.scss'
11-
127
export interface ContactSupportModal {
138
isOpen: boolean
149
onClose: () => void
@@ -17,71 +12,25 @@ export interface ContactSupportModal {
1712

1813
const ContactSupportModal: FC<ContactSupportModal> = (props: ContactSupportModal) => {
1914

20-
const { profile }: ProfileContextData = useContext(profileContext)
2115
const [formDef, setFormDef]: [FormDefinition, Dispatch<SetStateAction<FormDefinition>>] = useState<FormDefinition>({ ...contactSupportFormDef })
2216

23-
function generateRequest(inputs: ReadonlyArray<FormInputModel>): ContactSupportRequest {
24-
const firstName: string = formGetInputModel(inputs, ContactSupportFormField.first).value as string
25-
const lastName: string = formGetInputModel(inputs, ContactSupportFormField.last).value as string
26-
const email: string = formGetInputModel(inputs, ContactSupportFormField.email).value as string
27-
const question: string = formGetInputModel(inputs, ContactSupportFormField.question).value as string
28-
return {
29-
challengeId: props.workId,
30-
email,
31-
firstName,
32-
isSelfService: true,
33-
lastName,
34-
question,
35-
}
36-
}
37-
3817
function onClose(): void {
3918
const updatedForm: FormDefinition = { ...formDef }
4019
formOnReset(updatedForm.inputs)
4120
setFormDef(updatedForm)
4221
props.onClose()
4322
}
4423

45-
async function saveAsync(request: ContactSupportRequest): Promise<void> {
46-
return contactSupportSubmitRequestAsync(request)
47-
.then(() => {
48-
onClose()
49-
})
50-
}
51-
52-
const emailElement: JSX.Element | undefined = !!profile?.email
53-
? (
54-
<>
55-
&nbsp;at <strong>{profile.email}</strong>
56-
</>
57-
)
58-
: undefined
59-
6024
return (
6125
<BaseModal
6226
onClose={onClose}
6327
open={props.isOpen}
6428
size='md'
6529
title={`We're Here to Help`}
6630
>
67-
<div className={styles['contact-support-intro']}>
68-
<p>
69-
Hi {profile?.firstName || 'there'}, we're here to help.
70-
</p>
71-
72-
<p>
73-
Please describe what you'd like to discuss, and a
74-
Topcoder Solutions Expert will email you back
75-
{emailElement}
76-
&nbsp;within one business day.
77-
</p>
78-
</div>
79-
80-
<Form
31+
<ContactSupportForm
8132
formDef={formDef}
82-
formValues={profile}
83-
requestGenerator={generateRequest}
84-
save={saveAsync}
33+
onSave={onClose}
8534
/>
8635
</BaseModal>
8736
)

src-ts/lib/modals/terms-modal/TermsModal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const TermsModal: FC<TermsModal> = ({ isOpen, onClose }: TermsModal) => (
2525
This User Agreement (the "<strong>Agreement</strong>") is a contract
2626
between you (referred to herein as "User") and Topcoder LLC.
2727
("Topcoder") and applies to User's use and viewing of
28-
<a href='www.topcoder.com/' target='_blank'>
28+
<a href='https://www.topcoder.com/' target='_blank'>
2929
{' '}
3030
topcoder.com
3131
</a>

0 commit comments

Comments
 (0)