Skip to content

Commit da415d5

Browse files
authored
Merge pull request #607 from topcoder-platform/TCA-1278_enroll-button
TCA-1278, TCA-1279 - Cert page fixes -> rc-3.1
2 parents 2d01cb9 + 6e5295e commit da415d5

File tree

5 files changed

+95
-56
lines changed

5 files changed

+95
-56
lines changed

src-ts/lib/loading-spinner/LoadingSpinner.tsx

+5-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* Centered Loading Spinner with back overlay
55
*/
6-
import { FC } from 'react'
6+
import { FC, forwardRef, RefAttributes } from 'react'
77
import { PuffLoader } from 'react-spinners'
88
import classNames from 'classnames'
99

@@ -19,21 +19,23 @@ export interface LoadingSpinnerProps {
1919
type?: LoadingSpinnerType
2020
}
2121

22-
const LoadingSpinner: FC<LoadingSpinnerProps> = (props: LoadingSpinnerProps) => {
22+
const LoadingSpinner: FC<LoadingSpinnerProps & RefAttributes<HTMLDivElement>>
23+
= forwardRef<HTMLDivElement, LoadingSpinnerProps>((props, ref) => {
2324
if (!!props.hide) {
2425
return <></>
2526
}
2627

2728
const isOverlay: boolean = props.type === 'Overlay'
2829
return (
2930
<div
31+
ref={ref}
3032
className={
3133
classNames(styles['loading-spinner'], styles.show, { [styles.overlay]: isOverlay }, props.className)
3234
}
3335
>
3436
<PuffLoader color='#2196f3' loading size={100} />
3537
</div>
3638
)
37-
}
39+
})
3840

3941
export default LoadingSpinner

src-ts/tools/learn/certification-details/CertificationDetailsPage.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ const CertificationDetailsPage: FC<{}> = () => {
118118
/>
119119
</>
120120
)
121-
) : <></>
121+
) : undefined
122122
}
123123

124124
function renderSidebar(): ReactNode {

src-ts/tools/learn/course-certificate/certificate-view/CertificateView.tsx

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import {
22
FC,
3+
forwardRef,
34
MutableRefObject,
45
ReactNode,
6+
RefAttributes,
57
useMemo,
68
useRef,
79
} from 'react'
@@ -33,7 +35,8 @@ interface CertificateViewProps {
3335
provider: string
3436
}
3537

36-
const CertificateView: FC<CertificateViewProps> = (props: CertificateViewProps) => {
38+
const CertificateView: FC<CertificateViewProps & RefAttributes<HTMLDivElement>>
39+
= forwardRef<HTMLDivElement, CertificateViewProps>((props, ref) => {
3740
const coursePath: string = getCoursePath(props.provider, props.certification)
3841
const certificateElRef: MutableRefObject<HTMLDivElement | any> = useRef()
3942

@@ -110,6 +113,7 @@ const CertificateView: FC<CertificateViewProps> = (props: CertificateViewProps)
110113
</PageTitle>
111114

112115
<CertificatePageLayout
116+
ref={ref}
113117
certificateElRef={certificateElRef}
114118
fallbackBackUrl={coursePath}
115119
fullScreenCertLayout={!certificateNotFoundError && props.fullScreenCertLayout}
@@ -127,6 +131,6 @@ const CertificateView: FC<CertificateViewProps> = (props: CertificateViewProps)
127131
</CertificatePageLayout>
128132
</>
129133
)
130-
}
134+
})
131135

132136
export default CertificateView

src-ts/tools/learn/course-certificate/user-certificate/UserCertificate.tsx

+24-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
1-
import { Dispatch, FC, SetStateAction, useEffect, useState } from 'react'
1+
import {
2+
Dispatch,
3+
FC,
4+
MutableRefObject,
5+
SetStateAction,
6+
useEffect,
7+
useLayoutEffect,
8+
useRef,
9+
useState,
10+
} from 'react'
211
import { Params, useParams } from 'react-router-dom'
312

413
import {
@@ -7,8 +16,10 @@ import {
716
UserProfile,
817
} from '../../../../lib'
918
import { CertificateView } from '../certificate-view'
19+
import { hideSiblings } from '../../learn-lib'
1020

1121
const UserCertificate: FC<{}> = () => {
22+
const elRef: MutableRefObject<HTMLElement | any> = useRef()
1223

1324
const routeParams: Params<string> = useParams()
1425

@@ -31,16 +42,27 @@ const UserCertificate: FC<{}> = () => {
3142
}
3243
}, [routeParams.memberHandle, setProfileReady])
3344

45+
useLayoutEffect(() => {
46+
const el: HTMLElement = elRef.current
47+
if (!el) {
48+
return
49+
}
50+
51+
hideSiblings(el)
52+
hideSiblings(el.parentElement as HTMLElement)
53+
}, [])
54+
3455
return (
3556
<>
36-
<LoadingSpinner hide={profileReady} />
57+
<LoadingSpinner hide={profileReady} ref={elRef} />
3758

3859
{profileReady && profile && (
3960
<CertificateView
4061
certification={certificationParam}
4162
profile={profile}
4263
provider={providerParam}
4364
fullScreenCertLayout
65+
ref={elRef}
4466
/>
4567
)}
4668
</>

src-ts/tools/learn/learn-lib/certificate-page-layout/CertificatePageLayout.tsx

+59-48
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import {
22
FC,
3+
forwardRef,
34
MutableRefObject,
45
ReactNode,
6+
RefAttributes,
57
useCallback,
68
useLayoutEffect,
79
useRef,
@@ -42,7 +44,8 @@ interface CertificatePageLayoutProps {
4244
title?: string
4345
}
4446

45-
const CertificatePageLayout: FC<CertificatePageLayoutProps> = (props: CertificatePageLayoutProps) => {
47+
const CertificatePageLayout: FC<CertificatePageLayoutProps & RefAttributes<HTMLDivElement>>
48+
= forwardRef<HTMLDivElement, CertificatePageLayoutProps>((props, ref) => {
4649
const [queryParams]: [URLSearchParams, any] = useSearchParams()
4750
const viewStyle: CertificatePageLayoutStyle = queryParams.get(getViewStyleParamKey()) as CertificatePageLayoutStyle
4851

@@ -78,6 +81,12 @@ const CertificatePageLayout: FC<CertificatePageLayoutProps> = (props: Certificat
7881
const handlePrint: () => Promise<void>
7982
= useCertificatePrint(props.certificateElRef, props.title ?? '')
8083

84+
if (typeof ref === 'function') {
85+
ref(wrapElRef.current)
86+
} else if (ref && Object.prototype.hasOwnProperty.call(ref, 'current')) {
87+
ref.current = wrapElRef.current
88+
}
89+
8190
useLayoutEffect(() => {
8291
const el: HTMLElement = wrapElRef.current
8392
if (props.fullScreenCertLayout !== true || !el) {
@@ -93,57 +102,59 @@ const CertificatePageLayout: FC<CertificatePageLayoutProps> = (props: Certificat
93102
<>
94103
<LoadingSpinner hide={props.isReady} />
95104

96-
{props.isReady && (
97-
<div className={classNames(styles.wrap, props.className)} ref={wrapElRef}>
98-
<div className={styles['content-wrap']}>
99-
{!props.fullScreenCertLayout && (
100-
<div className={styles['btns-wrap']}>
101-
<ActionButton
102-
icon={<IconOutline.ChevronLeftIcon />}
103-
onClick={handleBackBtnClick}
104-
/>
105-
</div>
106-
)}
107-
<div
108-
className={classNames(styles['certificate-wrap'], viewStyle)}
109-
ref={certificateWrapRef}
110-
>
111-
<div className={styles.certifInnerWrap}>
112-
{props.children}
113-
</div>
114-
</div>
115-
{!props.fullScreenCertLayout && (
105+
<div className={classNames(styles.wrap, props.className)} ref={wrapElRef}>
106+
{props.isReady && (
107+
<>
108+
<div className={styles['content-wrap']}>
109+
{!props.fullScreenCertLayout && (
110+
<div className={styles['btns-wrap']}>
111+
<ActionButton
112+
icon={<IconOutline.ChevronLeftIcon />}
113+
onClick={handleBackBtnClick}
114+
/>
115+
</div>
116+
)}
116117
<div
117-
className={
118-
classNames(
119-
styles['btns-wrap'],
120-
(!props.isCertificateCompleted || props.disableActions) && styles.disabled,
121-
)
122-
}
118+
className={classNames(styles['certificate-wrap'], viewStyle)}
119+
ref={certificateWrapRef}
123120
>
124-
<ActionButton
125-
icon={<IconOutline.PrinterIcon />}
126-
onClick={handlePrint}
127-
/>
128-
<ActionButton
129-
icon={<IconOutline.DownloadIcon />}
130-
onClick={handleDownload}
131-
/>
132-
<ActionButton
133-
icon={<IconOutline.ShareIcon />}
134-
onClick={shareModal.show}
135-
>
136-
Share certificate
137-
</ActionButton>
121+
<div className={styles.certifInnerWrap}>
122+
{props.children}
123+
</div>
138124
</div>
139-
)}
140-
</div>
141-
{props.afterContent}
142-
{shareModal.modal}
143-
</div>
144-
)}
125+
{!props.fullScreenCertLayout && (
126+
<div
127+
className={
128+
classNames(
129+
styles['btns-wrap'],
130+
(!props.isCertificateCompleted || props.disableActions) && styles.disabled,
131+
)
132+
}
133+
>
134+
<ActionButton
135+
icon={<IconOutline.PrinterIcon />}
136+
onClick={handlePrint}
137+
/>
138+
<ActionButton
139+
icon={<IconOutline.DownloadIcon />}
140+
onClick={handleDownload}
141+
/>
142+
<ActionButton
143+
icon={<IconOutline.ShareIcon />}
144+
onClick={shareModal.show}
145+
>
146+
Share certificate
147+
</ActionButton>
148+
</div>
149+
)}
150+
</div>
151+
{props.afterContent}
152+
{shareModal.modal}
153+
</>
154+
)}
155+
</div>
145156
</>
146157
)
147-
}
158+
})
148159

149160
export default CertificatePageLayout

0 commit comments

Comments
 (0)