Skip to content

Commit 8f6f111

Browse files
kyle-ssgclaude
andauthored
refactor: migrate trivial components to TypeScript (#7231)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent ae375d0 commit 8f6f111

10 files changed

Lines changed: 127 additions & 158 deletions

File tree

frontend/web/components/ErrorMessage.js

Lines changed: 0 additions & 65 deletions
This file was deleted.
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import React, { FC } from 'react'
2+
import Icon from './icons/Icon'
3+
import Button from './base/forms/Button'
4+
import Format from 'common/utils/format'
5+
import Constants from 'common/constants'
6+
7+
type ErrorMessageProps = {
8+
enabledButton?: boolean
9+
error?: any
10+
errorMessageClass?: string
11+
errorStyles?: React.CSSProperties
12+
}
13+
14+
const ErrorMessage: FC<ErrorMessageProps> = ({
15+
enabledButton,
16+
error: errorProp,
17+
errorMessageClass,
18+
errorStyles,
19+
}) => {
20+
if (!errorProp) return null
21+
22+
const errorMessageClassName = `alert alert-danger ${
23+
errorMessageClass || 'flex-1 align-items-center'
24+
}`
25+
const error =
26+
errorProp?.data?.metadata?.find((item: Record<string, unknown>) =>
27+
// eslint-disable-next-line no-prototype-builtins
28+
item.hasOwnProperty('non_field_errors'),
29+
)?.non_field_errors[0] ||
30+
errorProp?.data ||
31+
errorProp?.message ||
32+
errorProp
33+
34+
return (
35+
<div
36+
className={errorMessageClassName}
37+
style={{
38+
display: errorMessageClass ? 'initial' : '',
39+
...errorStyles,
40+
}}
41+
>
42+
<span className='icon-alert'>
43+
<Icon name='close-circle' />
44+
</span>
45+
{error instanceof Error ? (
46+
error.message
47+
) : typeof error === 'object' ? (
48+
<div
49+
dangerouslySetInnerHTML={{
50+
__html: Object.keys(error)
51+
.map(
52+
(v) =>
53+
`${Format.camelCase(Format.enumeration.get(v))}: ${
54+
error[v]
55+
}`,
56+
)
57+
.join('<br/>'),
58+
}}
59+
/>
60+
) : (
61+
error
62+
)}
63+
{enabledButton && (
64+
<Button
65+
className='btn ml-3'
66+
onClick={() => {
67+
document.location.replace(Constants.getUpgradeUrl())
68+
}}
69+
>
70+
Upgrade plan
71+
</Button>
72+
)}
73+
</div>
74+
)
75+
}
76+
77+
export default ErrorMessage

frontend/web/components/PasswordRequirements.js renamed to frontend/web/components/PasswordRequirements.tsx

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
1-
import React, { useEffect } from 'react'
2-
import PropTypes from 'prop-types'
1+
import React, { FC, useEffect } from 'react'
32
import { close, checkmark } from 'ionicons/icons'
43
import { IonIcon } from '@ionic/react'
54

6-
const PasswordRequirements = ({ onRequirementsMet, password }) => {
5+
type PasswordRequirementsProps = {
6+
onRequirementsMet: (met: boolean) => void
7+
password: string
8+
}
9+
10+
const PasswordRequirements: FC<PasswordRequirementsProps> = ({
11+
onRequirementsMet,
12+
password,
13+
}) => {
714
const requirements = [
815
{ label: 'At least 8 characters', test: password.length >= 8 },
916
{ label: 'Contains a number', test: /\d/.test(password) },
@@ -48,9 +55,4 @@ const PasswordRequirements = ({ onRequirementsMet, password }) => {
4855
)
4956
}
5057

51-
PasswordRequirements.propTypes = {
52-
onRequirementsMet: PropTypes.func.isRequired,
53-
password: PropTypes.string.isRequired,
54-
}
55-
5658
export default PasswordRequirements

frontend/web/components/base/forms/Radio.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
import React from 'react'
2-
import classNames from 'classnames'
3-
import ReactMarkdown from 'react-markdown'
4-
import className = ReactMarkdown.propTypes.className
52

63
interface RadioProps {
74
label: string
@@ -20,7 +17,7 @@ const Radio: React.FC<RadioProps> = ({ checked, label, onChange }) => {
2017
className='position-relative cursor-pointer flex-row align-items-center'
2118
>
2219
{checked && <CheckedSVG />} {!checked && <UncheckedSVG />}
23-
{<span className={classNames('ml-2', className)}>{label}</span>}
20+
{<span className='ml-2'>{label}</span>}
2421
</label>
2522
)
2623
}

frontend/web/components/base/grid/Column.js

Lines changed: 0 additions & 27 deletions
This file was deleted.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import React, { FC } from 'react'
2+
3+
type ColumnProps = React.HTMLAttributes<HTMLDivElement>
4+
5+
const Column: FC<ColumnProps> = ({ className, ...rest }) => (
6+
<div {...rest} className={`${className || ''} flex-column`} />
7+
)
8+
9+
export default Column

frontend/web/components/base/grid/Flex.js

Lines changed: 0 additions & 27 deletions
This file was deleted.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import React, { FC } from 'react'
2+
3+
type FlexProps = React.HTMLAttributes<HTMLDivElement>
4+
5+
const Flex: FC<FlexProps> = ({ className, ...rest }) => (
6+
<div {...rest} className={`${className || ''} flex flex-1`} />
7+
)
8+
9+
export default Flex

frontend/web/components/pages/NotFoundErrorPage.js

Lines changed: 0 additions & 27 deletions
This file was deleted.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import React, { FC, useEffect } from 'react'
2+
import Constants from 'common/constants'
3+
4+
const NotFoundErrorPage: FC = () => {
5+
useEffect(() => {
6+
API.trackPage(Constants.pages.COMING_SOON)
7+
}, [])
8+
9+
return (
10+
<div className='app-container container'>
11+
<h3 className='pt-5'>Oops!</h3>
12+
<p>
13+
It looks like you do not have permission to view this{' '}
14+
{Utils.fromParam().entity || 'page'}. Please contact a member with
15+
administrator privileges.
16+
</p>
17+
</div>
18+
)
19+
}
20+
21+
export default NotFoundErrorPage

0 commit comments

Comments
 (0)