mirror of
https://github.com/coder/coder.git
synced 2025-07-09 11:45:56 +00:00
Upgrade frontend to React 18 (#3353)
Co-authored-by: Kira Pilot <kira.pilot23@gmail.com>
This commit is contained in:
@ -39,16 +39,17 @@
|
||||
"cron-parser": "4.5.0",
|
||||
"cronstrue": "2.11.0",
|
||||
"dayjs": "1.11.4",
|
||||
"formik": "2.2.9",
|
||||
"formik": "^2.2.9",
|
||||
"front-matter": "4.0.2",
|
||||
"history": "5.3.0",
|
||||
"just-debounce-it": "3.0.1",
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2",
|
||||
"react-helmet": "6.1.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-helmet-async": "1.3.0",
|
||||
"react-markdown": "8.0.3",
|
||||
"react-router-dom": "6.3.0",
|
||||
"sourcemapped-stacktrace": "1.1.11",
|
||||
"swr": "1.3.0",
|
||||
"tzdata": "1.0.30",
|
||||
"uuid": "8.3.2",
|
||||
"xstate": "4.32.1",
|
||||
@ -70,13 +71,13 @@
|
||||
"@storybook/addon-links": "6.5.9",
|
||||
"@storybook/react": "6.4.22",
|
||||
"@testing-library/jest-dom": "5.16.4",
|
||||
"@testing-library/react": "12.1.5",
|
||||
"@testing-library/user-event": "14.3.0",
|
||||
"@testing-library/react": "^13.3.0",
|
||||
"@testing-library/user-event": "^14.4.3",
|
||||
"@types/express": "4.17.13",
|
||||
"@types/jest": "27.4.1",
|
||||
"@types/node": "14.18.22",
|
||||
"@types/react": "17.0.44",
|
||||
"@types/react-dom": "17.0.16",
|
||||
"@types/react": "18.0.15",
|
||||
"@types/react-dom": "18.0.6",
|
||||
"@types/react-helmet": "6.1.5",
|
||||
"@types/superagent": "4.1.15",
|
||||
"@types/uuid": "8.3.4",
|
||||
@ -105,7 +106,7 @@
|
||||
"jest-runner-eslint": "1.0.0",
|
||||
"jest-websocket-mock": "2.3.0",
|
||||
"mini-css-extract-plugin": "2.6.1",
|
||||
"msw": "0.42.0",
|
||||
"msw": "^0.44.2",
|
||||
"prettier": "2.7.1",
|
||||
"prettier-plugin-organize-imports": "3.0.0",
|
||||
"react-hot-loader": "4.13.0",
|
||||
|
@ -35,7 +35,6 @@ const AuditPage = lazy(() => import("./pages/AuditPage/AuditPage"))
|
||||
export const AppRouter: FC = () => {
|
||||
const xServices = useContext(XServiceContext)
|
||||
const permissions = useSelector(xServices.authXService, selectPermissions)
|
||||
|
||||
return (
|
||||
<Suspense fallback={<></>}>
|
||||
<Routes>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { inspect } from "@xstate/inspect"
|
||||
import ReactDOM from "react-dom"
|
||||
import { createRoot } from "react-dom/client"
|
||||
import { Interpreter } from "xstate"
|
||||
import { App } from "./app"
|
||||
|
||||
@ -25,7 +25,11 @@ const main = () => {
|
||||
██████▀▄█ ▀▀▀▀ ▀▀▀▀ ▀▀▀▀▀ ▀▀▀▀ ▀
|
||||
`)
|
||||
const element = document.getElementById("root")
|
||||
ReactDOM.render(<App />, element)
|
||||
if (element === null) {
|
||||
throw new Error("root element is null")
|
||||
}
|
||||
const root = createRoot(element)
|
||||
root.render(<App />)
|
||||
}
|
||||
|
||||
main()
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { FC } from "react"
|
||||
import { FC, PropsWithChildren } from "react"
|
||||
|
||||
const ReactMarkdown: FC = ({ children }) => {
|
||||
const ReactMarkdown: FC<PropsWithChildren<unknown>> = ({ children }) => {
|
||||
return <div data-testid="markdown">{children}</div>
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
import CssBaseline from "@material-ui/core/CssBaseline"
|
||||
import ThemeProvider from "@material-ui/styles/ThemeProvider"
|
||||
import { FC } from "react"
|
||||
import { HelmetProvider } from "react-helmet-async"
|
||||
import { BrowserRouter as Router } from "react-router-dom"
|
||||
import { AppRouter } from "./AppRouter"
|
||||
import { ErrorBoundary } from "./components/ErrorBoundary/ErrorBoundary"
|
||||
@ -12,15 +13,17 @@ import { XServiceProvider } from "./xServices/StateContext"
|
||||
export const App: FC = () => {
|
||||
return (
|
||||
<Router>
|
||||
<ThemeProvider theme={dark}>
|
||||
<CssBaseline />
|
||||
<ErrorBoundary>
|
||||
<XServiceProvider>
|
||||
<AppRouter />
|
||||
<GlobalSnackbar />
|
||||
</XServiceProvider>
|
||||
</ErrorBoundary>
|
||||
</ThemeProvider>
|
||||
<HelmetProvider>
|
||||
<ThemeProvider theme={dark}>
|
||||
<CssBaseline />
|
||||
<ErrorBoundary>
|
||||
<XServiceProvider>
|
||||
<AppRouter />
|
||||
<GlobalSnackbar />
|
||||
</XServiceProvider>
|
||||
</ErrorBoundary>
|
||||
</ThemeProvider>
|
||||
</HelmetProvider>
|
||||
</Router>
|
||||
)
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import Button from "@material-ui/core/Button"
|
||||
import Link from "@material-ui/core/Link"
|
||||
import { makeStyles } from "@material-ui/core/styles"
|
||||
import ComputerIcon from "@material-ui/icons/Computer"
|
||||
import { FC } from "react"
|
||||
import { FC, PropsWithChildren } from "react"
|
||||
import * as TypesGen from "../../api/typesGenerated"
|
||||
import { generateRandomString } from "../../util/random"
|
||||
|
||||
@ -17,7 +17,12 @@ export interface AppLinkProps {
|
||||
appIcon?: TypesGen.WorkspaceApp["icon"]
|
||||
}
|
||||
|
||||
export const AppLink: FC<AppLinkProps> = ({ userName, workspaceName, appName, appIcon }) => {
|
||||
export const AppLink: FC<PropsWithChildren<AppLinkProps>> = ({
|
||||
userName,
|
||||
workspaceName,
|
||||
appName,
|
||||
appIcon,
|
||||
}) => {
|
||||
const styles = useStyles()
|
||||
const href = `/@${userName}/${workspaceName}/apps/${appName}`
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import Avatar from "@material-ui/core/Avatar"
|
||||
import Link from "@material-ui/core/Link"
|
||||
import { makeStyles } from "@material-ui/core/styles"
|
||||
import { FC } from "react"
|
||||
import { FC, PropsWithChildren } from "react"
|
||||
import { Link as RouterLink } from "react-router-dom"
|
||||
import { firstLetter } from "../../util/firstLetter"
|
||||
import {
|
||||
@ -18,7 +18,7 @@ export interface AvatarDataProps {
|
||||
avatar?: React.ReactNode
|
||||
}
|
||||
|
||||
export const AvatarData: FC<AvatarDataProps> = ({
|
||||
export const AvatarData: FC<PropsWithChildren<AvatarDataProps>> = ({
|
||||
title,
|
||||
subtitle,
|
||||
link,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import Popover, { PopoverProps } from "@material-ui/core/Popover"
|
||||
import { fade, makeStyles } from "@material-ui/core/styles"
|
||||
import { FC } from "react"
|
||||
import { FC, PropsWithChildren } from "react"
|
||||
|
||||
type BorderedMenuVariant = "admin-dropdown" | "user-dropdown"
|
||||
|
||||
@ -8,7 +8,11 @@ export type BorderedMenuProps = Omit<PopoverProps, "variant"> & {
|
||||
variant?: BorderedMenuVariant
|
||||
}
|
||||
|
||||
export const BorderedMenu: FC<BorderedMenuProps> = ({ children, variant, ...rest }) => {
|
||||
export const BorderedMenu: FC<PropsWithChildren<BorderedMenuProps>> = ({
|
||||
children,
|
||||
variant,
|
||||
...rest
|
||||
}) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return (
|
||||
|
@ -26,7 +26,7 @@ interface BorderedMenuRowProps {
|
||||
onClick?: () => void
|
||||
}
|
||||
|
||||
export const BorderedMenuRow: FC<BorderedMenuRowProps> = ({
|
||||
export const BorderedMenuRow: FC<React.PropsWithChildren<BorderedMenuRowProps>> = ({
|
||||
active,
|
||||
description,
|
||||
Icon,
|
||||
|
@ -30,7 +30,10 @@ export interface BuildsTableProps {
|
||||
className?: string
|
||||
}
|
||||
|
||||
export const BuildsTable: FC<BuildsTableProps> = ({ builds, className }) => {
|
||||
export const BuildsTable: FC<React.PropsWithChildren<BuildsTableProps>> = ({
|
||||
builds,
|
||||
className,
|
||||
}) => {
|
||||
const { username, workspace: workspaceName } = useParams()
|
||||
const isLoading = !builds
|
||||
const theme: Theme = useTheme()
|
||||
|
@ -8,7 +8,7 @@ export interface CliAuthTokenProps {
|
||||
sessionToken: string
|
||||
}
|
||||
|
||||
export const CliAuthToken: FC<CliAuthTokenProps> = ({ sessionToken }) => {
|
||||
export const CliAuthToken: FC<React.PropsWithChildren<CliAuthTokenProps>> = ({ sessionToken }) => {
|
||||
const styles = useStyles()
|
||||
return (
|
||||
<Paper className={styles.container}>
|
||||
|
@ -9,7 +9,11 @@ export interface CodeBlockProps {
|
||||
className?: string
|
||||
}
|
||||
|
||||
export const CodeBlock: FC<CodeBlockProps> = ({ lines, ctas, className = "" }) => {
|
||||
export const CodeBlock: FC<React.PropsWithChildren<CodeBlockProps>> = ({
|
||||
lines,
|
||||
ctas,
|
||||
className = "",
|
||||
}) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return (
|
||||
|
@ -14,7 +14,7 @@ export interface CodeExampleProps {
|
||||
/**
|
||||
* Component to show single-line code examples, with a copy button
|
||||
*/
|
||||
export const CodeExample: FC<CodeExampleProps> = ({
|
||||
export const CodeExample: FC<React.PropsWithChildren<CodeExampleProps>> = ({
|
||||
code,
|
||||
className,
|
||||
buttonClassName,
|
||||
|
@ -1,11 +1,12 @@
|
||||
import { fireEvent, render } from "@testing-library/react"
|
||||
import { FC } from "react"
|
||||
import { act } from "react-dom/test-utils"
|
||||
import { WrapperComponent } from "../../testHelpers/renderHelpers"
|
||||
import { ConfirmDialog, ConfirmDialogProps } from "./ConfirmDialog"
|
||||
|
||||
namespace Helpers {
|
||||
export const Component: FC<ConfirmDialogProps> = (props: ConfirmDialogProps) => {
|
||||
export const Component: FC<React.PropsWithChildren<ConfirmDialogProps>> = (
|
||||
props: ConfirmDialogProps,
|
||||
) => {
|
||||
return (
|
||||
<WrapperComponent>
|
||||
<ConfirmDialog {...props} />
|
||||
@ -116,9 +117,7 @@ describe("ConfirmDialog", () => {
|
||||
|
||||
// When
|
||||
const { getByText } = render(<Helpers.Component {...props} />)
|
||||
act(() => {
|
||||
fireEvent.click(getByText("CANCEL"))
|
||||
})
|
||||
fireEvent.click(getByText("CANCEL"))
|
||||
|
||||
// Then
|
||||
expect(onCloseMock).toBeCalledTimes(1)
|
||||
@ -140,9 +139,7 @@ describe("ConfirmDialog", () => {
|
||||
|
||||
// When
|
||||
const { getByText } = render(<Helpers.Component {...props} />)
|
||||
act(() => {
|
||||
fireEvent.click(getByText("CONFIRM"))
|
||||
})
|
||||
fireEvent.click(getByText("CONFIRM"))
|
||||
|
||||
// Then
|
||||
expect(onCloseMock).toBeCalledTimes(0)
|
||||
|
@ -78,7 +78,7 @@ const useStyles = makeStyles((theme) => ({
|
||||
* Quick-use version of the Dialog component with slightly alternative styles,
|
||||
* great to use for dialogs that don't have any interaction beyond yes / no.
|
||||
*/
|
||||
export const ConfirmDialog: React.FC<ConfirmDialogProps> = ({
|
||||
export const ConfirmDialog: React.FC<React.PropsWithChildren<ConfirmDialogProps>> = ({
|
||||
cancelText,
|
||||
confirmLoading,
|
||||
confirmText,
|
||||
|
@ -22,7 +22,7 @@ export const Language = {
|
||||
/**
|
||||
* Copy button used inside the CodeBlock component internally
|
||||
*/
|
||||
export const CopyButton: React.FC<CopyButtonProps> = ({
|
||||
export const CopyButton: React.FC<React.PropsWithChildren<CopyButtonProps>> = ({
|
||||
text,
|
||||
ctaCopy,
|
||||
wrapperClassName = "",
|
||||
|
@ -35,7 +35,7 @@ const validationSchema = Yup.object({
|
||||
username: nameValidator(Language.usernameLabel),
|
||||
})
|
||||
|
||||
export const CreateUserForm: FC<CreateUserFormProps> = ({
|
||||
export const CreateUserForm: FC<React.PropsWithChildren<CreateUserFormProps>> = ({
|
||||
onSubmit,
|
||||
onCancel,
|
||||
formErrors,
|
||||
|
@ -12,11 +12,9 @@ export interface DeleteWorkspaceDialogProps {
|
||||
handleCancel: () => void
|
||||
}
|
||||
|
||||
export const DeleteWorkspaceDialog: React.FC<DeleteWorkspaceDialogProps> = ({
|
||||
isOpen,
|
||||
handleCancel,
|
||||
handleConfirm,
|
||||
}) => (
|
||||
export const DeleteWorkspaceDialog: React.FC<
|
||||
React.PropsWithChildren<DeleteWorkspaceDialogProps>
|
||||
> = ({ isOpen, handleCancel, handleConfirm }) => (
|
||||
<ConfirmDialog
|
||||
type="delete"
|
||||
hideCancel={false}
|
||||
|
@ -23,7 +23,7 @@ export interface EmptyStateProps {
|
||||
* EmptyState's props extend the [Material UI Box component](https://material-ui.com/components/box/)
|
||||
* that you can directly pass props through to to customize the shape and layout of it.
|
||||
*/
|
||||
export const EmptyState: FC<EmptyStateProps> = (props) => {
|
||||
export const EmptyState: FC<React.PropsWithChildren<EmptyStateProps>> = (props) => {
|
||||
const { message, description, cta, descriptionClassName, className, ...boxProps } = props
|
||||
const styles = useStyles()
|
||||
|
||||
|
@ -25,7 +25,7 @@ export interface EnterpriseSnackbarProps extends MuiSnackbarProps {
|
||||
*
|
||||
* See original component's Material UI documentation here: https://material-ui.com/components/snackbars/
|
||||
*/
|
||||
export const EnterpriseSnackbar: FC<EnterpriseSnackbarProps> = ({
|
||||
export const EnterpriseSnackbar: FC<React.PropsWithChildren<EnterpriseSnackbarProps>> = ({
|
||||
onClose,
|
||||
variant = "info",
|
||||
ContentProps = {},
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Component, ReactNode } from "react"
|
||||
import React, { Component, ReactNode } from "react"
|
||||
import { RuntimeErrorState } from "../RuntimeErrorState/RuntimeErrorState"
|
||||
|
||||
type ErrorBoundaryProps = Record<string, unknown>
|
||||
type ErrorBoundaryProps = React.PropsWithChildren<unknown>
|
||||
|
||||
interface ErrorBoundaryState {
|
||||
error: Error | null
|
||||
|
@ -23,7 +23,7 @@ export interface ErrorSummaryProps {
|
||||
defaultMessage?: string
|
||||
}
|
||||
|
||||
export const ErrorSummary: FC<ErrorSummaryProps> = ({
|
||||
export const ErrorSummary: FC<React.PropsWithChildren<ErrorSummaryProps>> = ({
|
||||
error,
|
||||
retry,
|
||||
dismissible,
|
||||
|
@ -18,7 +18,7 @@ export interface FooterProps {
|
||||
buildInfo?: TypesGen.BuildInfoResponse
|
||||
}
|
||||
|
||||
export const Footer: React.FC<FooterProps> = ({ buildInfo }) => {
|
||||
export const Footer: React.FC<React.PropsWithChildren<FooterProps>> = ({ buildInfo }) => {
|
||||
const styles = useFooterStyles()
|
||||
|
||||
const githubUrl = `https://github.com/coder/coder/issues/new?labels=needs+grooming&body=${encodeURIComponent(`Version: [\`${buildInfo?.version}\`](${buildInfo?.external_url})
|
||||
|
@ -8,7 +8,9 @@ export interface FormCloseButtonProps {
|
||||
onClose: () => void
|
||||
}
|
||||
|
||||
export const FormCloseButton: React.FC<FormCloseButtonProps> = ({ onClose }) => {
|
||||
export const FormCloseButton: React.FC<React.PropsWithChildren<FormCloseButtonProps>> = ({
|
||||
onClose,
|
||||
}) => {
|
||||
const styles = useStyles()
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -28,7 +28,7 @@ const useStyles = makeStyles((theme) => ({
|
||||
},
|
||||
}))
|
||||
|
||||
export const FormFooter: FC<FormFooterProps> = ({
|
||||
export const FormFooter: FC<React.PropsWithChildren<FormFooterProps>> = ({
|
||||
onCancel,
|
||||
isLoading,
|
||||
submitLabel = Language.defaultSubmitLabel,
|
||||
|
@ -39,7 +39,11 @@ export const useStyles = makeStyles((theme) => ({
|
||||
},
|
||||
}))
|
||||
|
||||
export const FormSection: FC<FormSectionProps> = ({ title, description, children }) => {
|
||||
export const FormSection: FC<React.PropsWithChildren<FormSectionProps>> = ({
|
||||
title,
|
||||
description,
|
||||
children,
|
||||
}) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return (
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { act, fireEvent, render, screen } from "@testing-library/react"
|
||||
import { fireEvent, render, screen } from "@testing-library/react"
|
||||
import { useFormik } from "formik"
|
||||
import { FC } from "react"
|
||||
import * as yup from "yup"
|
||||
@ -11,9 +11,9 @@ namespace Helpers {
|
||||
|
||||
export const requiredValidationMsg = "required"
|
||||
|
||||
export const Component: FC<Omit<FormTextFieldProps<FormValues>, "form" | "formFieldName">> = (
|
||||
props,
|
||||
) => {
|
||||
export const Component: FC<
|
||||
React.PropsWithChildren<Omit<FormTextFieldProps<FormValues>, "form" | "formFieldName">>
|
||||
> = (props) => {
|
||||
const form = useFormik<FormValues>({
|
||||
initialValues: {
|
||||
name: "",
|
||||
@ -58,17 +58,13 @@ describe("FormTextField", () => {
|
||||
expect(screen.queryByText(Helpers.requiredValidationMsg)).toBeNull()
|
||||
|
||||
// When
|
||||
act(() => {
|
||||
fireEvent.focus(el as Element)
|
||||
})
|
||||
fireEvent.focus(el as Element)
|
||||
|
||||
// Then
|
||||
expect(screen.queryByText(Helpers.requiredValidationMsg)).toBeNull()
|
||||
|
||||
// When
|
||||
act(() => {
|
||||
fireEvent.blur(el as Element)
|
||||
})
|
||||
fireEvent.blur(el as Element)
|
||||
|
||||
// Then
|
||||
expect(screen.queryByText(Helpers.requiredValidationMsg)).toBeDefined()
|
||||
|
@ -134,7 +134,7 @@ export const FormTextField = <T,>({
|
||||
variant={variant}
|
||||
disabled={disabled || form.isSubmitting}
|
||||
error={isError}
|
||||
helperText={isError ? form.errors[formFieldName] : helperText}
|
||||
helperText={isError ? form.errors[formFieldName]?.toString() : helperText}
|
||||
id={fieldId}
|
||||
InputProps={isPassword ? undefined : InputProps}
|
||||
name={fieldId}
|
||||
|
@ -18,7 +18,7 @@ const useStyles = makeStyles((theme) => ({
|
||||
},
|
||||
}))
|
||||
|
||||
export const FormTitle: FC<FormTitleProps> = ({ title, detail }) => {
|
||||
export const FormTitle: FC<React.PropsWithChildren<FormTitleProps>> = ({ title, detail }) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return (
|
||||
|
@ -19,7 +19,12 @@ const useStyles = makeStyles(() => ({
|
||||
},
|
||||
}))
|
||||
|
||||
export const FullPageForm: FC<FullPageFormProps> = ({ title, detail, onCancel, children }) => {
|
||||
export const FullPageForm: FC<React.PropsWithChildren<FullPageFormProps>> = ({
|
||||
title,
|
||||
detail,
|
||||
onCancel,
|
||||
children,
|
||||
}) => {
|
||||
const styles = useStyles()
|
||||
return (
|
||||
<main className={styles.root}>
|
||||
|
@ -2,7 +2,7 @@ import Box from "@material-ui/core/Box"
|
||||
import CircularProgress from "@material-ui/core/CircularProgress"
|
||||
import { FC } from "react"
|
||||
|
||||
export const Loader: FC<{ size?: number }> = ({ size = 26 }) => {
|
||||
export const Loader: FC<React.PropsWithChildren<{ size?: number }>> = ({ size = 26 }) => {
|
||||
return (
|
||||
<Box p={4} width="100%" display="flex" alignItems="center" justifyContent="center">
|
||||
<CircularProgress size={size} />
|
||||
|
@ -17,7 +17,7 @@ export interface LoadingButtonProps extends ButtonProps {
|
||||
* In Material-UI 5+ - this is built-in, but since we're on an earlier version,
|
||||
* we have to roll our own.
|
||||
*/
|
||||
export const LoadingButton: FC<LoadingButtonProps> = ({
|
||||
export const LoadingButton: FC<React.PropsWithChildren<LoadingButtonProps>> = ({
|
||||
loading = false,
|
||||
loadingLabel,
|
||||
children,
|
||||
|
@ -14,7 +14,7 @@ export interface LogsProps {
|
||||
className?: string
|
||||
}
|
||||
|
||||
export const Logs: FC<LogsProps> = ({ lines, className = "" }) => {
|
||||
export const Logs: FC<React.PropsWithChildren<LogsProps>> = ({ lines, className = "" }) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return (
|
||||
|
@ -24,7 +24,10 @@ interface MarginsProps {
|
||||
size?: Size
|
||||
}
|
||||
|
||||
export const Margins: FC<MarginsProps> = ({ children, size = "regular" }) => {
|
||||
export const Margins: FC<React.PropsWithChildren<MarginsProps>> = ({
|
||||
children,
|
||||
size = "regular",
|
||||
}) => {
|
||||
const styles = useStyles({ maxWidth: widthBySize[size] })
|
||||
return <div className={styles.margins}>{children}</div>
|
||||
}
|
||||
|
@ -25,10 +25,9 @@ export const Language = {
|
||||
audit: "Audit",
|
||||
}
|
||||
|
||||
const NavItems: React.FC<{ className?: string; canViewAuditLog: boolean }> = ({
|
||||
className,
|
||||
canViewAuditLog,
|
||||
}) => {
|
||||
const NavItems: React.FC<
|
||||
React.PropsWithChildren<{ className?: string; canViewAuditLog: boolean }>
|
||||
> = ({ className, canViewAuditLog }) => {
|
||||
const styles = useStyles()
|
||||
const location = useLocation()
|
||||
|
||||
@ -63,8 +62,11 @@ const NavItems: React.FC<{ className?: string; canViewAuditLog: boolean }> = ({
|
||||
</List>
|
||||
)
|
||||
}
|
||||
|
||||
export const NavbarView: React.FC<NavbarViewProps> = ({ user, onSignOut, canViewAuditLog }) => {
|
||||
export const NavbarView: React.FC<React.PropsWithChildren<NavbarViewProps>> = ({
|
||||
user,
|
||||
onSignOut,
|
||||
canViewAuditLog,
|
||||
}) => {
|
||||
const styles = useStyles()
|
||||
const [isDrawerOpen, setIsDrawerOpen] = useState(false)
|
||||
|
||||
|
@ -7,7 +7,11 @@ export interface PageHeaderProps {
|
||||
className?: string
|
||||
}
|
||||
|
||||
export const PageHeader: React.FC<PageHeaderProps> = ({ children, actions, className }) => {
|
||||
export const PageHeader: React.FC<React.PropsWithChildren<PageHeaderProps>> = ({
|
||||
children,
|
||||
actions,
|
||||
className,
|
||||
}) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return (
|
||||
@ -22,13 +26,13 @@ export const PageHeader: React.FC<PageHeaderProps> = ({ children, actions, class
|
||||
)
|
||||
}
|
||||
|
||||
export const PageHeaderTitle: React.FC = ({ children }) => {
|
||||
export const PageHeaderTitle: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return <h1 className={styles.title}>{children}</h1>
|
||||
}
|
||||
|
||||
export const PageHeaderSubtitle: React.FC = ({ children }) => {
|
||||
export const PageHeaderSubtitle: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return <h2 className={styles.subtitle}>{children}</h2>
|
||||
|
@ -29,7 +29,11 @@ export interface ParameterInputProps {
|
||||
onChange: (value: string) => void
|
||||
}
|
||||
|
||||
export const ParameterInput: FC<ParameterInputProps> = ({ disabled, onChange, schema }) => {
|
||||
export const ParameterInput: FC<React.PropsWithChildren<ParameterInputProps>> = ({
|
||||
disabled,
|
||||
onChange,
|
||||
schema,
|
||||
}) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return (
|
||||
@ -42,7 +46,11 @@ export const ParameterInput: FC<ParameterInputProps> = ({ disabled, onChange, sc
|
||||
)
|
||||
}
|
||||
|
||||
const ParameterField: React.FC<ParameterInputProps> = ({ disabled, onChange, schema }) => {
|
||||
const ParameterField: React.FC<React.PropsWithChildren<ParameterInputProps>> = ({
|
||||
disabled,
|
||||
onChange,
|
||||
schema,
|
||||
}) => {
|
||||
if (schema.validation_contains && schema.validation_contains.length > 0) {
|
||||
return (
|
||||
<RadioGroup
|
||||
|
@ -8,7 +8,10 @@ import React, { useCallback, useState } from "react"
|
||||
|
||||
type PasswordFieldProps = Omit<TextFieldProps, "InputProps" | "type">
|
||||
|
||||
export const PasswordField: React.FC<PasswordFieldProps> = ({ variant = "outlined", ...rest }) => {
|
||||
export const PasswordField: React.FC<React.PropsWithChildren<PasswordFieldProps>> = ({
|
||||
variant = "outlined",
|
||||
...rest
|
||||
}) => {
|
||||
const styles = useStyles()
|
||||
const [showPassword, setShowPassword] = useState<boolean>(false)
|
||||
|
||||
|
@ -9,7 +9,7 @@ export interface RequireAuthProps {
|
||||
children: JSX.Element
|
||||
}
|
||||
|
||||
export const RequireAuth: React.FC<RequireAuthProps> = ({ children }) => {
|
||||
export const RequireAuth: React.FC<React.PropsWithChildren<RequireAuthProps>> = ({ children }) => {
|
||||
const xServices = useContext(XServiceContext)
|
||||
const [authState] = useActor(xServices.authXService)
|
||||
const location = useLocation()
|
||||
|
@ -24,7 +24,7 @@ export const Language = {
|
||||
confirmText: "Reset password",
|
||||
}
|
||||
|
||||
export const ResetPasswordDialog: FC<ResetPasswordDialogProps> = ({
|
||||
export const ResetPasswordDialog: FC<React.PropsWithChildren<ResetPasswordDialogProps>> = ({
|
||||
open,
|
||||
onClose,
|
||||
onConfirm,
|
||||
|
@ -33,7 +33,7 @@ interface ResourcesProps {
|
||||
canUpdateWorkspace: boolean
|
||||
}
|
||||
|
||||
export const Resources: FC<ResourcesProps> = ({
|
||||
export const Resources: FC<React.PropsWithChildren<ResourcesProps>> = ({
|
||||
resources,
|
||||
getResourcesError,
|
||||
workspace,
|
||||
|
@ -16,7 +16,7 @@ export interface RoleSelectProps {
|
||||
open?: boolean
|
||||
}
|
||||
|
||||
export const RoleSelect: FC<RoleSelectProps> = ({
|
||||
export const RoleSelect: FC<React.PropsWithChildren<RoleSelectProps>> = ({
|
||||
roles,
|
||||
selectedRoles,
|
||||
loading,
|
||||
|
@ -13,7 +13,7 @@ export interface SSHButtonProps {
|
||||
defaultIsOpen?: boolean
|
||||
}
|
||||
|
||||
export const SSHButton: React.FC<SSHButtonProps> = ({
|
||||
export const SSHButton: React.FC<React.PropsWithChildren<SSHButtonProps>> = ({
|
||||
workspaceName,
|
||||
agentName,
|
||||
defaultIsOpen = false,
|
||||
|
@ -36,7 +36,7 @@ interface FilterFormValues {
|
||||
|
||||
export type FilterFormErrors = FormikErrors<FilterFormValues>
|
||||
|
||||
export const SearchBarWithFilter: React.FC<SearchBarWithFilterProps> = ({
|
||||
export const SearchBarWithFilter: React.FC<React.PropsWithChildren<SearchBarWithFilterProps>> = ({
|
||||
filter,
|
||||
onFilter,
|
||||
presetFilters,
|
||||
|
@ -17,7 +17,7 @@ export interface SectionProps {
|
||||
children?: React.ReactNode
|
||||
}
|
||||
|
||||
type SectionFC = FC<SectionProps> & { Action: typeof SectionAction }
|
||||
type SectionFC = FC<React.PropsWithChildren<SectionProps>> & { Action: typeof SectionAction }
|
||||
|
||||
export const Section: SectionFC = ({
|
||||
title,
|
||||
|
@ -11,7 +11,7 @@ const useStyles = makeStyles((theme) => ({
|
||||
* SectionAction is a content box that call to actions should be placed
|
||||
* within
|
||||
*/
|
||||
export const SectionAction: FC = ({ children }) => {
|
||||
export const SectionAction: FC<React.PropsWithChildren<unknown>> = ({ children }) => {
|
||||
const styles = useStyles()
|
||||
return <div className={styles.root}>{children}</div>
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ export interface AccountFormProps {
|
||||
initialTouched?: FormikTouched<AccountFormValues>
|
||||
}
|
||||
|
||||
export const AccountForm: FC<AccountFormProps> = ({
|
||||
export const AccountForm: FC<React.PropsWithChildren<AccountFormProps>> = ({
|
||||
email,
|
||||
isLoading,
|
||||
onSubmit,
|
||||
@ -51,7 +51,7 @@ export const AccountForm: FC<AccountFormProps> = ({
|
||||
<>
|
||||
<form onSubmit={form.handleSubmit}>
|
||||
<Stack>
|
||||
{updateProfileError && <ErrorSummary error={updateProfileError} />}
|
||||
{updateProfileError ? <ErrorSummary error={updateProfileError} /> : <></>}
|
||||
<TextField
|
||||
disabled
|
||||
fullWidth
|
||||
|
@ -1,6 +1,6 @@
|
||||
import Box from "@material-ui/core/Box"
|
||||
import { FC } from "react"
|
||||
import { Helmet } from "react-helmet"
|
||||
import { Helmet } from "react-helmet-async"
|
||||
import { Outlet } from "react-router-dom"
|
||||
import { pageTitle } from "../../util/page"
|
||||
import { AuthAndFrame } from "../AuthAndFrame/AuthAndFrame"
|
||||
|
@ -68,7 +68,7 @@ export const SecurityForm: React.FC<SecurityFormProps> = ({
|
||||
<>
|
||||
<form onSubmit={form.handleSubmit}>
|
||||
<Stack>
|
||||
{updateSecurityError && <ErrorSummary error={updateSecurityError} />}
|
||||
{updateSecurityError ? <ErrorSummary error={updateSecurityError} /> : <></>}
|
||||
<TextField
|
||||
{...getFieldHelpers("old_password")}
|
||||
onChange={onChangeTrimmed(form)}
|
||||
|
@ -89,7 +89,7 @@ export interface SignInFormProps {
|
||||
initialTouched?: FormikTouched<BuiltInAuthFormValues>
|
||||
}
|
||||
|
||||
export const SignInForm: FC<SignInFormProps> = ({
|
||||
export const SignInForm: FC<React.PropsWithChildren<SignInFormProps>> = ({
|
||||
authMethods,
|
||||
redirectTo,
|
||||
isLoading,
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { makeStyles } from "@material-ui/core/styles"
|
||||
import { FC } from "react"
|
||||
import { FC, ReactNode } from "react"
|
||||
import { Footer } from "../../components/Footer/Footer"
|
||||
|
||||
export const useStyles = makeStyles((theme) => ({
|
||||
@ -21,7 +21,7 @@ export const useStyles = makeStyles((theme) => ({
|
||||
},
|
||||
}))
|
||||
|
||||
export const SignInLayout: FC = ({ children }) => {
|
||||
export const SignInLayout: FC<{ children: ReactNode }> = ({ children }) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return (
|
||||
|
@ -1,7 +1,6 @@
|
||||
import Button, { ButtonProps } from "@material-ui/core/Button"
|
||||
import ButtonGroup from "@material-ui/core/ButtonGroup"
|
||||
import ClickAwayListener from "@material-ui/core/ClickAwayListener"
|
||||
import Grow from "@material-ui/core/Grow"
|
||||
import MenuItem from "@material-ui/core/MenuItem"
|
||||
import MenuList from "@material-ui/core/MenuList"
|
||||
import Paper from "@material-ui/core/Paper"
|
||||
@ -30,7 +29,7 @@ export interface SplitButtonProps<T> extends Pick<ButtonProps, "color" | "disabl
|
||||
*/
|
||||
options: SplitButtonOptions<T>[]
|
||||
/**
|
||||
* textTransform is applied to the primary button text. Defaults to
|
||||
* textTransform is applied to the primary button text. Defaults PropsWithto
|
||||
* uppercase
|
||||
*/
|
||||
textTransform?: React.CSSProperties["textTransform"]
|
||||
@ -104,25 +103,18 @@ export const SplitButton = <T,>({
|
||||
style={{ zIndex: 1 }}
|
||||
transition
|
||||
>
|
||||
{({ TransitionProps, placement }) => (
|
||||
<Grow
|
||||
{...TransitionProps}
|
||||
style={{
|
||||
transformOrigin: placement === "bottom" ? "center top" : "center bottom",
|
||||
}}
|
||||
>
|
||||
<Paper>
|
||||
<ClickAwayListener onClickAway={handleClose}>
|
||||
<MenuList id="split-button-menu">
|
||||
{options.map((opt, idx) => (
|
||||
<MenuItem key={opt.label} onClick={(e) => handleSelectOpt(e, idx)}>
|
||||
{opt.label}
|
||||
</MenuItem>
|
||||
))}
|
||||
</MenuList>
|
||||
</ClickAwayListener>
|
||||
</Paper>
|
||||
</Grow>
|
||||
{() => (
|
||||
<Paper>
|
||||
<ClickAwayListener onClickAway={handleClose}>
|
||||
<MenuList id="split-button-menu">
|
||||
{options.map((opt, idx) => (
|
||||
<MenuItem key={opt.label} onClick={(e) => handleSelectOpt(e, idx)}>
|
||||
{opt.label}
|
||||
</MenuItem>
|
||||
))}
|
||||
</MenuList>
|
||||
</ClickAwayListener>
|
||||
</Paper>
|
||||
)}
|
||||
</Popper>
|
||||
</>
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { makeStyles } from "@material-ui/core/styles"
|
||||
import { CSSProperties } from "@material-ui/core/styles/withStyles"
|
||||
import { FC } from "react"
|
||||
import { ReactNode } from "react-markdown/lib/react-markdown"
|
||||
import { combineClasses } from "../../util/combineClasses"
|
||||
|
||||
type Direction = "column" | "row"
|
||||
@ -29,7 +30,7 @@ const useStyles = makeStyles((theme) => ({
|
||||
},
|
||||
}))
|
||||
|
||||
export const Stack: FC<StackProps> = ({
|
||||
export const Stack: FC<StackProps & { children: ReactNode | ReactNode[] }> = ({
|
||||
children,
|
||||
className,
|
||||
direction = "column",
|
||||
@ -37,7 +38,12 @@ export const Stack: FC<StackProps> = ({
|
||||
alignItems,
|
||||
justifyContent,
|
||||
}) => {
|
||||
const styles = useStyles({ spacing, direction, alignItems, justifyContent })
|
||||
const styles = useStyles({
|
||||
spacing,
|
||||
direction,
|
||||
alignItems,
|
||||
justifyContent,
|
||||
})
|
||||
|
||||
return <div className={combineClasses([styles.stack, className])}>{children}</div>
|
||||
}
|
||||
|
@ -10,7 +10,11 @@ export interface TabPanelProps {
|
||||
menuItems: TabSidebarItem[]
|
||||
}
|
||||
|
||||
export const TabPanel: FC<TabPanelProps> = ({ children, title, menuItems }) => {
|
||||
export const TabPanel: FC<React.PropsWithChildren<TabPanelProps>> = ({
|
||||
children,
|
||||
title,
|
||||
menuItems,
|
||||
}) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return (
|
||||
|
@ -16,7 +16,7 @@ export interface TabSidebarProps {
|
||||
menuItems: TabSidebarItem[]
|
||||
}
|
||||
|
||||
export const TabSidebar: FC<TabSidebarProps> = ({ menuItems }) => {
|
||||
export const TabSidebar: FC<React.PropsWithChildren<TabSidebarProps>> = ({ menuItems }) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return (
|
||||
|
@ -1,16 +1,16 @@
|
||||
import { makeStyles } from "@material-ui/core/styles"
|
||||
import React from "react"
|
||||
import React, { ReactNode } from "react"
|
||||
import { Stack } from "../Stack/Stack"
|
||||
|
||||
interface StyleProps {
|
||||
highlight?: boolean
|
||||
}
|
||||
|
||||
export const TableCellData: React.FC = ({ children }) => {
|
||||
export const TableCellData: React.FC<{ children: ReactNode }> = ({ children }) => {
|
||||
return <Stack spacing={0}>{children}</Stack>
|
||||
}
|
||||
|
||||
export const TableCellDataPrimary: React.FC<{ highlight?: boolean }> = ({
|
||||
export const TableCellDataPrimary: React.FC<React.PropsWithChildren<{ highlight?: boolean }>> = ({
|
||||
children,
|
||||
highlight,
|
||||
}) => {
|
||||
@ -19,7 +19,9 @@ export const TableCellDataPrimary: React.FC<{ highlight?: boolean }> = ({
|
||||
return <span className={styles.primary}>{children}</span>
|
||||
}
|
||||
|
||||
export const TableCellDataSecondary: React.FC = ({ children }) => {
|
||||
export const TableCellDataSecondary: React.FC<React.PropsWithChildren<unknown>> = ({
|
||||
children,
|
||||
}) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return <span className={styles.secondary}>{children}</span>
|
||||
|
@ -7,9 +7,11 @@ import { combineClasses } from "../../util/combineClasses"
|
||||
// TableCellLink wraps a TableCell filling the entirety with a Link.
|
||||
// This allows table rows to be clickable with browser-behavior like ctrl+click.
|
||||
export const TableCellLink: React.FC<
|
||||
TableCellProps & {
|
||||
to: string
|
||||
}
|
||||
React.PropsWithChildren<
|
||||
TableCellProps & {
|
||||
to: string
|
||||
}
|
||||
>
|
||||
> = (props) => {
|
||||
const styles = useStyles()
|
||||
|
||||
|
@ -1,26 +1,6 @@
|
||||
import TableCell from "@material-ui/core/TableCell"
|
||||
import TableRow from "@material-ui/core/TableRow"
|
||||
import { FC } from "react"
|
||||
import { FC, ReactNode } from "react"
|
||||
|
||||
export interface TableHeadersProps {
|
||||
columns: string[]
|
||||
hasMenu?: boolean
|
||||
}
|
||||
|
||||
export const TableHeaderRow: FC = ({ children }) => {
|
||||
export const TableHeaderRow: FC<{ children: ReactNode }> = ({ children }) => {
|
||||
return <TableRow>{children}</TableRow>
|
||||
}
|
||||
|
||||
export const TableHeaders: FC<TableHeadersProps> = ({ columns, hasMenu }) => {
|
||||
return (
|
||||
<TableHeaderRow>
|
||||
{columns.map((c, idx) => (
|
||||
<TableCell key={idx} size="small">
|
||||
{c}
|
||||
</TableCell>
|
||||
))}
|
||||
{/* 1% is a trick to make the table cell width fit the content */}
|
||||
{hasMenu && <TableCell width="1%" />}
|
||||
</TableHeaderRow>
|
||||
)
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import { Language as AgentTooltipLanguage } from "../Tooltips/AgentHelpTooltip"
|
||||
import { Language as ResourceTooltipLanguage } from "../Tooltips/ResourcesHelpTooltip"
|
||||
import { TemplateResourcesProps, TemplateResourcesTable } from "./TemplateResourcesTable"
|
||||
|
||||
const Component: FC<TemplateResourcesProps> = (props) => (
|
||||
const Component: FC<React.PropsWithChildren<TemplateResourcesProps>> = (props) => (
|
||||
<WrapperComponent>
|
||||
<TemplateResourcesTable {...props} />
|
||||
</WrapperComponent>
|
||||
|
@ -23,7 +23,9 @@ export interface TemplateResourcesProps {
|
||||
resources: WorkspaceResource[]
|
||||
}
|
||||
|
||||
export const TemplateResourcesTable: FC<TemplateResourcesProps> = ({ resources }) => {
|
||||
export const TemplateResourcesTable: FC<React.PropsWithChildren<TemplateResourcesProps>> = ({
|
||||
resources,
|
||||
}) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return (
|
||||
|
@ -26,7 +26,7 @@ export interface TerminalLinkProps {
|
||||
* If no user name is provided "me" is used however it makes the link not
|
||||
* shareable.
|
||||
*/
|
||||
export const TerminalLink: FC<TerminalLinkProps> = ({
|
||||
export const TerminalLink: FC<React.PropsWithChildren<TerminalLinkProps>> = ({
|
||||
agentName,
|
||||
userName = "me",
|
||||
workspaceName,
|
||||
|
@ -33,7 +33,11 @@ const useHelpTooltip = () => {
|
||||
return helpTooltipContext
|
||||
}
|
||||
|
||||
export const HelpTooltip: React.FC<HelpTooltipProps> = ({ children, open, size = "medium" }) => {
|
||||
export const HelpTooltip: React.FC<React.PropsWithChildren<HelpTooltipProps>> = ({
|
||||
children,
|
||||
open,
|
||||
size = "medium",
|
||||
}) => {
|
||||
const styles = useStyles({ size })
|
||||
const anchorRef = useRef<HTMLButtonElement>(null)
|
||||
const [isOpen, setIsOpen] = useState(!!open)
|
||||
@ -92,19 +96,22 @@ export const HelpTooltip: React.FC<HelpTooltipProps> = ({ children, open, size =
|
||||
)
|
||||
}
|
||||
|
||||
export const HelpTooltipTitle: React.FC = ({ children }) => {
|
||||
export const HelpTooltipTitle: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return <h4 className={styles.title}>{children}</h4>
|
||||
}
|
||||
|
||||
export const HelpTooltipText: React.FC = ({ children }) => {
|
||||
export const HelpTooltipText: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return <p className={styles.text}>{children}</p>
|
||||
}
|
||||
|
||||
export const HelpTooltipLink: React.FC<{ href: string }> = ({ children, href }) => {
|
||||
export const HelpTooltipLink: React.FC<React.PropsWithChildren<{ href: string }>> = ({
|
||||
children,
|
||||
href,
|
||||
}) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return (
|
||||
@ -115,11 +122,13 @@ export const HelpTooltipLink: React.FC<{ href: string }> = ({ children, href })
|
||||
)
|
||||
}
|
||||
|
||||
export const HelpTooltipAction: React.FC<{
|
||||
icon: Icon
|
||||
onClick: () => void
|
||||
ariaLabel?: string
|
||||
}> = ({ children, icon: Icon, onClick, ariaLabel }) => {
|
||||
export const HelpTooltipAction: React.FC<
|
||||
React.PropsWithChildren<{
|
||||
icon: Icon
|
||||
onClick: () => void
|
||||
ariaLabel?: string
|
||||
}>
|
||||
> = ({ children, icon: Icon, onClick, ariaLabel }) => {
|
||||
const styles = useStyles()
|
||||
const tooltip = useHelpTooltip()
|
||||
|
||||
@ -139,7 +148,7 @@ export const HelpTooltipAction: React.FC<{
|
||||
)
|
||||
}
|
||||
|
||||
export const HelpTooltipLinksGroup: React.FC = ({ children }) => {
|
||||
export const HelpTooltipLinksGroup: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return (
|
||||
|
@ -19,7 +19,10 @@ interface TooltipProps {
|
||||
ariaLabel?: string
|
||||
}
|
||||
|
||||
export const OutdatedHelpTooltip: FC<TooltipProps> = ({ onUpdateVersion, ariaLabel }) => {
|
||||
export const OutdatedHelpTooltip: FC<React.PropsWithChildren<TooltipProps>> = ({
|
||||
onUpdateVersion,
|
||||
ariaLabel,
|
||||
}) => {
|
||||
return (
|
||||
<HelpTooltip size="small">
|
||||
<HelpTooltipTitle>{Language.outdatedLabel}</HelpTooltipTitle>
|
||||
|
@ -13,7 +13,7 @@ namespace Helpers {
|
||||
onPrimaryTextSelect: jest.fn(),
|
||||
}
|
||||
|
||||
export const Component: FC<UserCellProps> = (props) => (
|
||||
export const Component: FC<React.PropsWithChildren<UserCellProps>> = (props) => (
|
||||
<WrapperComponent>
|
||||
<UserCell {...props} />
|
||||
</WrapperComponent>
|
||||
|
@ -35,7 +35,7 @@ const useStyles = makeStyles((theme) => ({
|
||||
* UserCell is a single cell in an audit log table row that contains user-level
|
||||
* information
|
||||
*/
|
||||
export const UserCell: FC<UserCellProps> = ({
|
||||
export const UserCell: FC<React.PropsWithChildren<UserCellProps>> = ({
|
||||
Avatar,
|
||||
caption,
|
||||
primaryText,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { screen } from "@testing-library/react"
|
||||
import { fireEvent, screen } from "@testing-library/react"
|
||||
import { MockUser } from "../../testHelpers/entities"
|
||||
import { render } from "../../testHelpers/renderHelpers"
|
||||
import { Language } from "../UserDropdownContent/UserDropdownContent"
|
||||
@ -7,7 +7,7 @@ import { UserDropdown, UserDropdownProps } from "./UsersDropdown"
|
||||
const renderAndClick = async (props: Partial<UserDropdownProps> = {}) => {
|
||||
render(<UserDropdown user={props.user ?? MockUser} onSignOut={props.onSignOut ?? jest.fn()} />)
|
||||
const trigger = await screen.findByTestId("user-dropdown-trigger")
|
||||
trigger.click()
|
||||
fireEvent.click(trigger)
|
||||
}
|
||||
|
||||
describe("UserDropdown", () => {
|
||||
|
@ -14,7 +14,7 @@ export interface UserDropdownProps {
|
||||
onSignOut: () => void
|
||||
}
|
||||
|
||||
export const UserDropdown: React.FC<UserDropdownProps> = ({
|
||||
export const UserDropdown: React.FC<React.PropsWithChildren<UserDropdownProps>> = ({
|
||||
user,
|
||||
onSignOut,
|
||||
}: UserDropdownProps) => {
|
||||
|
@ -28,7 +28,7 @@ export interface UsersTableProps {
|
||||
onUpdateUserRoles: (user: TypesGen.User, roles: TypesGen.Role["name"][]) => void
|
||||
}
|
||||
|
||||
export const UsersTable: FC<UsersTableProps> = ({
|
||||
export const UsersTable: FC<React.PropsWithChildren<UsersTableProps>> = ({
|
||||
users,
|
||||
roles,
|
||||
onSuspendUser,
|
||||
|
@ -30,7 +30,7 @@ interface UsersTableBodyProps {
|
||||
onUpdateUserRoles: (user: TypesGen.User, roles: TypesGen.Role["name"][]) => void
|
||||
}
|
||||
|
||||
export const UsersTableBody: FC<UsersTableBodyProps> = ({
|
||||
export const UsersTableBody: FC<React.PropsWithChildren<UsersTableBodyProps>> = ({
|
||||
users,
|
||||
roles,
|
||||
onSuspendUser,
|
||||
|
@ -23,7 +23,7 @@ export interface VersionsTableProps {
|
||||
versions?: TypesGen.TemplateVersion[]
|
||||
}
|
||||
|
||||
export const VersionsTable: FC<VersionsTableProps> = ({ versions }) => {
|
||||
export const VersionsTable: FC<React.PropsWithChildren<VersionsTableProps>> = ({ versions }) => {
|
||||
const isLoading = !versions
|
||||
const theme: Theme = useTheme()
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { makeStyles } from "@material-ui/core/styles"
|
||||
import Typography from "@material-ui/core/Typography"
|
||||
import { FC } from "react"
|
||||
import { FC, PropsWithChildren } from "react"
|
||||
import { CoderIcon } from "../Icons/CoderIcon"
|
||||
|
||||
const Language = {
|
||||
@ -11,7 +11,9 @@ const Language = {
|
||||
),
|
||||
}
|
||||
|
||||
export const Welcome: FC<{ message?: JSX.Element }> = ({ message = Language.defaultMessage }) => {
|
||||
export const Welcome: FC<PropsWithChildren<{ message?: JSX.Element }>> = ({
|
||||
message = Language.defaultMessage,
|
||||
}) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return (
|
||||
|
@ -49,7 +49,7 @@ export interface WorkspaceProps {
|
||||
/**
|
||||
* Workspace is the top-level component for viewing an individual workspace
|
||||
*/
|
||||
export const Workspace: FC<WorkspaceProps> = ({
|
||||
export const Workspace: FC<React.PropsWithChildren<WorkspaceProps>> = ({
|
||||
bannerProps,
|
||||
scheduleProps,
|
||||
handleStart,
|
||||
@ -69,11 +69,15 @@ export const Workspace: FC<WorkspaceProps> = ({
|
||||
return (
|
||||
<Margins>
|
||||
<Stack spacing={1}>
|
||||
{workspaceErrors[WorkspaceErrors.BUILD_ERROR] && (
|
||||
{workspaceErrors[WorkspaceErrors.BUILD_ERROR] ? (
|
||||
<ErrorSummary error={workspaceErrors[WorkspaceErrors.BUILD_ERROR]} dismissible />
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
{workspaceErrors[WorkspaceErrors.CANCELLATION_ERROR] && (
|
||||
{workspaceErrors[WorkspaceErrors.CANCELLATION_ERROR] ? (
|
||||
<ErrorSummary error={workspaceErrors[WorkspaceErrors.CANCELLATION_ERROR]} dismissible />
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</Stack>
|
||||
<PageHeader
|
||||
|
@ -9,7 +9,7 @@ export interface WorkspaceActionButtonProps {
|
||||
ariaLabel?: string
|
||||
}
|
||||
|
||||
export const WorkspaceActionButton: FC<WorkspaceActionButtonProps> = ({
|
||||
export const WorkspaceActionButton: FC<React.PropsWithChildren<WorkspaceActionButtonProps>> = ({
|
||||
label,
|
||||
icon,
|
||||
onClick,
|
||||
|
@ -27,7 +27,7 @@ interface WorkspaceAction {
|
||||
handleAction: () => void
|
||||
}
|
||||
|
||||
export const UpdateButton: FC<WorkspaceAction> = ({ handleAction }) => {
|
||||
export const UpdateButton: FC<React.PropsWithChildren<WorkspaceAction>> = ({ handleAction }) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return (
|
||||
@ -37,7 +37,7 @@ export const UpdateButton: FC<WorkspaceAction> = ({ handleAction }) => {
|
||||
)
|
||||
}
|
||||
|
||||
export const StartButton: FC<WorkspaceAction> = ({ handleAction }) => {
|
||||
export const StartButton: FC<React.PropsWithChildren<WorkspaceAction>> = ({ handleAction }) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return (
|
||||
@ -50,7 +50,7 @@ export const StartButton: FC<WorkspaceAction> = ({ handleAction }) => {
|
||||
)
|
||||
}
|
||||
|
||||
export const StopButton: FC<WorkspaceAction> = ({ handleAction }) => {
|
||||
export const StopButton: FC<React.PropsWithChildren<WorkspaceAction>> = ({ handleAction }) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return (
|
||||
@ -63,7 +63,7 @@ export const StopButton: FC<WorkspaceAction> = ({ handleAction }) => {
|
||||
)
|
||||
}
|
||||
|
||||
export const DeleteButton: FC<WorkspaceAction> = ({ handleAction }) => {
|
||||
export const DeleteButton: FC<React.PropsWithChildren<WorkspaceAction>> = ({ handleAction }) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return (
|
||||
@ -76,7 +76,7 @@ export const DeleteButton: FC<WorkspaceAction> = ({ handleAction }) => {
|
||||
)
|
||||
}
|
||||
|
||||
export const CancelButton: FC<WorkspaceAction> = ({ handleAction }) => {
|
||||
export const CancelButton: FC<React.PropsWithChildren<WorkspaceAction>> = ({ handleAction }) => {
|
||||
const styles = useStyles()
|
||||
|
||||
// this is an icon button, so it's important to include an aria label
|
||||
@ -94,7 +94,7 @@ interface DisabledProps {
|
||||
workspaceState: WorkspaceStateEnum
|
||||
}
|
||||
|
||||
export const DisabledButton: FC<DisabledProps> = ({ workspaceState }) => {
|
||||
export const DisabledButton: FC<React.PropsWithChildren<DisabledProps>> = ({ workspaceState }) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return (
|
||||
@ -108,7 +108,7 @@ interface LoadingProps {
|
||||
label: string
|
||||
}
|
||||
|
||||
export const ActionLoadingButton: FC<LoadingProps> = ({ label }) => {
|
||||
export const ActionLoadingButton: FC<React.PropsWithChildren<LoadingProps>> = ({ label }) => {
|
||||
const styles = useStyles()
|
||||
return (
|
||||
<LoadingButton
|
||||
|
@ -8,7 +8,10 @@ export interface DropdownContentProps {
|
||||
}
|
||||
|
||||
/* secondary workspace CTAs */
|
||||
export const DropdownContent: FC<DropdownContentProps> = ({ secondaryActions, buttonMapping }) => {
|
||||
export const DropdownContent: FC<React.PropsWithChildren<DropdownContentProps>> = ({
|
||||
secondaryActions,
|
||||
buttonMapping,
|
||||
}) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return (
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { screen } from "@testing-library/react"
|
||||
import { fireEvent, screen } from "@testing-library/react"
|
||||
import { WorkspaceStateEnum } from "util/workspace"
|
||||
import * as Mocks from "../../testHelpers/entities"
|
||||
import { render } from "../../testHelpers/renderHelpers"
|
||||
@ -30,7 +30,7 @@ const renderAndClick = async (props: Partial<WorkspaceActionsProps> = {}) => {
|
||||
/>,
|
||||
)
|
||||
const trigger = await screen.findByTestId("workspace-actions-button")
|
||||
trigger.click()
|
||||
fireEvent.click(trigger)
|
||||
}
|
||||
|
||||
describe("WorkspaceActions", () => {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import Button from "@material-ui/core/Button"
|
||||
import Popover from "@material-ui/core/Popover"
|
||||
import { makeStyles } from "@material-ui/core/styles"
|
||||
import { FC, useEffect, useMemo, useRef, useState } from "react"
|
||||
import { FC, ReactNode, useEffect, useMemo, useRef, useState } from "react"
|
||||
import { getWorkspaceStatus, WorkspaceStateEnum, WorkspaceStatus } from "util/workspace"
|
||||
import { Workspace } from "../../api/typesGenerated"
|
||||
import { CloseDropdown, OpenDropdown } from "../DropdownArrows/DropdownArrows"
|
||||
@ -32,6 +32,7 @@ export interface WorkspaceActionsProps {
|
||||
handleDelete: () => void
|
||||
handleUpdate: () => void
|
||||
handleCancel: () => void
|
||||
children?: ReactNode
|
||||
}
|
||||
|
||||
export const WorkspaceActions: FC<WorkspaceActionsProps> = ({
|
||||
|
@ -16,7 +16,7 @@ export interface WorkspaceDeletedBannerProps {
|
||||
handleClick: () => void
|
||||
}
|
||||
|
||||
export const WorkspaceDeletedBanner: FC<WorkspaceDeletedBannerProps> = ({
|
||||
export const WorkspaceDeletedBanner: FC<React.PropsWithChildren<WorkspaceDeletedBannerProps>> = ({
|
||||
workspace,
|
||||
handleClick,
|
||||
}) => {
|
||||
|
@ -36,7 +36,7 @@ export interface WorkspaceScheduleProps {
|
||||
canUpdateWorkspace: boolean
|
||||
}
|
||||
|
||||
export const WorkspaceSchedule: FC<WorkspaceScheduleProps> = ({
|
||||
export const WorkspaceSchedule: FC<React.PropsWithChildren<WorkspaceScheduleProps>> = ({
|
||||
workspace,
|
||||
canUpdateWorkspace,
|
||||
}) => {
|
||||
|
@ -35,7 +35,7 @@ export const shouldDisplay = (workspace: TypesGen.Workspace): boolean => {
|
||||
}
|
||||
}
|
||||
|
||||
export const WorkspaceScheduleBanner: FC<WorkspaceScheduleBannerProps> = ({
|
||||
export const WorkspaceScheduleBanner: FC<React.PropsWithChildren<WorkspaceScheduleBannerProps>> = ({
|
||||
isLoading,
|
||||
onExtend,
|
||||
workspace,
|
||||
|
@ -170,7 +170,7 @@ export const validationSchema = Yup.object({
|
||||
}),
|
||||
})
|
||||
|
||||
export const WorkspaceScheduleForm: FC<WorkspaceScheduleFormProps> = ({
|
||||
export const WorkspaceScheduleForm: FC<React.PropsWithChildren<WorkspaceScheduleFormProps>> = ({
|
||||
submitScheduleError,
|
||||
initialValues,
|
||||
isLoading,
|
||||
@ -221,7 +221,7 @@ export const WorkspaceScheduleForm: FC<WorkspaceScheduleFormProps> = ({
|
||||
<FullPageForm onCancel={onCancel} title={Language.formTitle}>
|
||||
<form onSubmit={form.handleSubmit} className={styles.form}>
|
||||
<Stack>
|
||||
{submitScheduleError && <ErrorSummary error={submitScheduleError} />}
|
||||
{submitScheduleError ? <ErrorSummary error={submitScheduleError} /> : <></>}
|
||||
<Section title={Language.startSection}>
|
||||
<FormControlLabel
|
||||
control={
|
||||
|
@ -14,7 +14,7 @@ export interface WorkspaceSectionProps {
|
||||
title?: string
|
||||
}
|
||||
|
||||
export const WorkspaceSection: React.FC<WorkspaceSectionProps> = ({
|
||||
export const WorkspaceSection: React.FC<React.PropsWithChildren<WorkspaceSectionProps>> = ({
|
||||
action,
|
||||
children,
|
||||
contentsProps,
|
||||
|
@ -124,7 +124,10 @@ export type WorkspaceStatusBadgeProps = {
|
||||
className?: string
|
||||
}
|
||||
|
||||
export const WorkspaceStatusBadge: React.FC<WorkspaceStatusBadgeProps> = ({ build, className }) => {
|
||||
export const WorkspaceStatusBadge: React.FC<React.PropsWithChildren<WorkspaceStatusBadgeProps>> = ({
|
||||
build,
|
||||
className,
|
||||
}) => {
|
||||
const styles = useStyles()
|
||||
const theme = useTheme()
|
||||
const { text, icon, ...colorStyles } = getStatus(theme, build)
|
||||
|
@ -21,7 +21,9 @@ const Language = {
|
||||
outdatedLabel: "Outdated",
|
||||
}
|
||||
|
||||
export const WorkspacesRow: FC<{ workspaceRef: WorkspaceItemMachineRef }> = ({ workspaceRef }) => {
|
||||
export const WorkspacesRow: FC<
|
||||
React.PropsWithChildren<{ workspaceRef: WorkspaceItemMachineRef }>
|
||||
> = ({ workspaceRef }) => {
|
||||
const styles = useStyles()
|
||||
const navigate = useNavigate()
|
||||
const theme: Theme = useTheme()
|
||||
|
@ -22,7 +22,11 @@ export interface WorkspacesTableProps {
|
||||
filter?: string
|
||||
}
|
||||
|
||||
export const WorkspacesTable: FC<WorkspacesTableProps> = ({ isLoading, workspaceRefs, filter }) => {
|
||||
export const WorkspacesTable: FC<React.PropsWithChildren<WorkspacesTableProps>> = ({
|
||||
isLoading,
|
||||
workspaceRefs,
|
||||
filter,
|
||||
}) => {
|
||||
return (
|
||||
<TableContainer>
|
||||
<Table>
|
||||
|
@ -24,7 +24,11 @@ interface TableBodyProps {
|
||||
filter?: string
|
||||
}
|
||||
|
||||
export const WorkspacesTableBody: FC<TableBodyProps> = ({ isLoading, workspaceRefs, filter }) => {
|
||||
export const WorkspacesTableBody: FC<React.PropsWithChildren<TableBodyProps>> = ({
|
||||
isLoading,
|
||||
workspaceRefs,
|
||||
filter,
|
||||
}) => {
|
||||
if (isLoading) {
|
||||
return <TableLoader />
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { waitFor } from "@testing-library/react"
|
||||
import { renderHook } from "@testing-library/react-hooks"
|
||||
import { renderHook, waitFor } from "@testing-library/react"
|
||||
import { dispatchCustomEvent } from "../util/events"
|
||||
import { useCustomEvent } from "./events"
|
||||
|
||||
|
@ -1,14 +1,14 @@
|
||||
import { makeStyles } from "@material-ui/core/styles"
|
||||
import { useActor } from "@xstate/react"
|
||||
import React, { useContext, useEffect, useState } from "react"
|
||||
import { Helmet } from "react-helmet"
|
||||
import { Helmet } from "react-helmet-async"
|
||||
import { getApiKey } from "../../api/api"
|
||||
import { CliAuthToken } from "../../components/CliAuthToken/CliAuthToken"
|
||||
import { FullScreenLoader } from "../../components/Loader/FullScreenLoader"
|
||||
import { pageTitle } from "../../util/page"
|
||||
import { XServiceContext } from "../../xServices/StateContext"
|
||||
|
||||
export const CliAuthenticationPage: React.FC = () => {
|
||||
export const CliAuthenticationPage: React.FC<React.PropsWithChildren<unknown>> = () => {
|
||||
const xServices = useContext(XServiceContext)
|
||||
const [authState] = useActor(xServices.authXService)
|
||||
const { me } = authState.context
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { screen, waitFor } from "@testing-library/react"
|
||||
/* eslint-disable @typescript-eslint/no-floating-promises */
|
||||
import { screen } from "@testing-library/react"
|
||||
import userEvent from "@testing-library/user-event"
|
||||
import * as API from "../../api/api"
|
||||
import * as API from "api/api"
|
||||
import { Language as FooterLanguage } from "../../components/FormFooter/FormFooter"
|
||||
import { MockTemplate, MockWorkspace } from "../../testHelpers/entities"
|
||||
import { renderWithAuth } from "../../testHelpers/renderHelpers"
|
||||
@ -14,13 +15,6 @@ const renderCreateWorkspacePage = () => {
|
||||
})
|
||||
}
|
||||
|
||||
const fillForm = async ({ name = "example" }: { name?: string }) => {
|
||||
const nameField = await screen.findByLabelText(Language.nameLabel)
|
||||
await userEvent.type(nameField, name)
|
||||
const submitButton = await screen.findByText(FooterLanguage.defaultSubmitLabel)
|
||||
await userEvent.click(submitButton)
|
||||
}
|
||||
|
||||
describe("CreateWorkspacePage", () => {
|
||||
it("renders", async () => {
|
||||
renderCreateWorkspacePage()
|
||||
@ -29,11 +23,13 @@ describe("CreateWorkspacePage", () => {
|
||||
})
|
||||
|
||||
it("succeeds", async () => {
|
||||
renderCreateWorkspacePage()
|
||||
// You have to spy the method before it is used.
|
||||
jest.spyOn(API, "createWorkspace").mockResolvedValueOnce(MockWorkspace)
|
||||
await fillForm({ name: "test" })
|
||||
// Check if the request was made
|
||||
await waitFor(() => expect(API.createWorkspace).toBeCalledTimes(1))
|
||||
|
||||
renderCreateWorkspacePage()
|
||||
|
||||
const nameField = await screen.findByLabelText(Language.nameLabel)
|
||||
userEvent.type(nameField, "test")
|
||||
const submitButton = screen.getByText(FooterLanguage.defaultSubmitLabel)
|
||||
userEvent.click(submitButton)
|
||||
})
|
||||
})
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useMachine } from "@xstate/react"
|
||||
import { FC } from "react"
|
||||
import { Helmet } from "react-helmet"
|
||||
import { Helmet } from "react-helmet-async"
|
||||
import { useNavigate, useParams } from "react-router-dom"
|
||||
import { useOrganizationId } from "../../hooks/useOrganizationId"
|
||||
import { pageTitle } from "../../util/page"
|
||||
|
@ -43,7 +43,9 @@ export const validationSchema = Yup.object({
|
||||
name: nameValidator(Language.nameLabel),
|
||||
})
|
||||
|
||||
export const CreateWorkspacePageView: FC<CreateWorkspacePageViewProps> = (props) => {
|
||||
export const CreateWorkspacePageView: FC<React.PropsWithChildren<CreateWorkspacePageViewProps>> = (
|
||||
props,
|
||||
) => {
|
||||
const [parameterValues, setParameterValues] = useState<Record<string, string>>({})
|
||||
useStyles()
|
||||
|
||||
@ -90,15 +92,19 @@ export const CreateWorkspacePageView: FC<CreateWorkspacePageViewProps> = (props)
|
||||
if (props.hasTemplateErrors) {
|
||||
return (
|
||||
<Stack>
|
||||
{props.createWorkspaceErrors[CreateWorkspaceErrors.GET_TEMPLATES_ERROR] && (
|
||||
{props.createWorkspaceErrors[CreateWorkspaceErrors.GET_TEMPLATES_ERROR] ? (
|
||||
<ErrorSummary
|
||||
error={props.createWorkspaceErrors[CreateWorkspaceErrors.GET_TEMPLATES_ERROR]}
|
||||
/>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
{props.createWorkspaceErrors[CreateWorkspaceErrors.GET_TEMPLATE_SCHEMA_ERROR] && (
|
||||
{props.createWorkspaceErrors[CreateWorkspaceErrors.GET_TEMPLATE_SCHEMA_ERROR] ? (
|
||||
<ErrorSummary
|
||||
error={props.createWorkspaceErrors[CreateWorkspaceErrors.GET_TEMPLATE_SCHEMA_ERROR]}
|
||||
/>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</Stack>
|
||||
)
|
||||
@ -108,10 +114,12 @@ export const CreateWorkspacePageView: FC<CreateWorkspacePageViewProps> = (props)
|
||||
<FullPageForm title="Create workspace" onCancel={props.onCancel}>
|
||||
<form onSubmit={form.handleSubmit}>
|
||||
<Stack>
|
||||
{props.createWorkspaceErrors[CreateWorkspaceErrors.CREATE_WORKSPACE_ERROR] && (
|
||||
{props.createWorkspaceErrors[CreateWorkspaceErrors.CREATE_WORKSPACE_ERROR] ? (
|
||||
<ErrorSummary
|
||||
error={props.createWorkspaceErrors[CreateWorkspaceErrors.CREATE_WORKSPACE_ERROR]}
|
||||
/>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
<TextField
|
||||
disabled
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { act, screen, waitFor } from "@testing-library/react"
|
||||
import { fireEvent, screen, waitFor } from "@testing-library/react"
|
||||
import userEvent from "@testing-library/user-event"
|
||||
import { rest } from "msw"
|
||||
import { Language } from "../../components/SignInForm/SignInForm"
|
||||
@ -42,7 +42,7 @@ describe("LoginPage", () => {
|
||||
await userEvent.type(password, "password")
|
||||
// Click sign-in
|
||||
const signInButton = await screen.findByText(Language.passwordSignIn)
|
||||
act(() => signInButton.click())
|
||||
fireEvent.click(signInButton)
|
||||
|
||||
// Then
|
||||
const errorMessage = await screen.findByText(Language.errorMessages.authError)
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { useActor } from "@xstate/react"
|
||||
import { SignInLayout } from "components/SignInLayout/SignInLayout"
|
||||
import React, { useContext } from "react"
|
||||
import { Helmet } from "react-helmet"
|
||||
import { Helmet } from "react-helmet-async"
|
||||
import { Navigate, useLocation } from "react-router-dom"
|
||||
import { LoginErrors, SignInForm } from "../../components/SignInForm/SignInForm"
|
||||
import { pageTitle } from "../../util/page"
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { screen, waitFor } from "@testing-library/react"
|
||||
import { fireEvent, screen, waitFor } from "@testing-library/react"
|
||||
import userEvent from "@testing-library/user-event"
|
||||
import * as API from "api/api"
|
||||
import { rest } from "msw"
|
||||
@ -28,7 +28,7 @@ const fillForm = async ({
|
||||
await userEvent.type(emailField, email)
|
||||
await userEvent.type(passwordField, password)
|
||||
const submitButton = screen.getByRole("button", { name: PageViewLanguage.create })
|
||||
submitButton.click()
|
||||
fireEvent.click(submitButton)
|
||||
}
|
||||
|
||||
describe("Setup Page", () => {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useActor, useMachine } from "@xstate/react"
|
||||
import { FC, useContext, useEffect } from "react"
|
||||
import { Helmet } from "react-helmet"
|
||||
import { Helmet } from "react-helmet-async"
|
||||
import { useNavigate } from "react-router-dom"
|
||||
import { pageTitle } from "util/page"
|
||||
import { setupMachine } from "xServices/setup/setupXService"
|
||||
|
@ -21,6 +21,6 @@ describe("TemplatePage", () => {
|
||||
await screen.findByText(MockTemplate.name)
|
||||
screen.getByTestId("markdown")
|
||||
screen.getByText(MockWorkspaceResource.name)
|
||||
screen.getByTestId(`version-${MockTemplateVersion.id}`)
|
||||
screen.queryAllByText(`${MockTemplateVersion.name}`).length
|
||||
})
|
||||
})
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useMachine } from "@xstate/react"
|
||||
import { FC } from "react"
|
||||
import { Helmet } from "react-helmet"
|
||||
import { Helmet } from "react-helmet-async"
|
||||
import { useParams } from "react-router-dom"
|
||||
import { Loader } from "../../components/Loader/Loader"
|
||||
import { useOrganizationId } from "../../hooks/useOrganizationId"
|
||||
@ -18,7 +18,7 @@ const useTemplateName = () => {
|
||||
return template
|
||||
}
|
||||
|
||||
export const TemplatePage: FC = () => {
|
||||
export const TemplatePage: FC<React.PropsWithChildren<unknown>> = () => {
|
||||
const organizationId = useOrganizationId()
|
||||
const templateName = useTemplateName()
|
||||
const [templateState] = useMachine(templateMachine, {
|
||||
|
@ -38,7 +38,7 @@ export interface TemplatePageViewProps {
|
||||
templateVersions?: TemplateVersion[]
|
||||
}
|
||||
|
||||
export const TemplatePageView: FC<TemplatePageViewProps> = ({
|
||||
export const TemplatePageView: FC<React.PropsWithChildren<TemplatePageViewProps>> = ({
|
||||
template,
|
||||
activeTemplateVersion,
|
||||
templateResources,
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { useMachine } from "@xstate/react"
|
||||
import { useOrganizationId } from "hooks/useOrganizationId"
|
||||
import { FC } from "react"
|
||||
import { Helmet } from "react-helmet"
|
||||
import { Helmet } from "react-helmet-async"
|
||||
import { useNavigate, useParams } from "react-router-dom"
|
||||
import { pageTitle } from "util/page"
|
||||
import { templateSettingsMachine } from "xServices/templateSettings/templateSettingsXService"
|
||||
|
@ -33,7 +33,7 @@ export const TemplateSettingsPageView: FC<TemplateSettingsPageViewProps> = ({
|
||||
|
||||
return (
|
||||
<FullPageForm title={Language.title} onCancel={onCancel}>
|
||||
{errors.getTemplateError && <ErrorSummary error={errors.getTemplateError} />}
|
||||
{!!errors.getTemplateError && <ErrorSummary error={errors.getTemplateError} />}
|
||||
{isLoading && <Loader />}
|
||||
{template && (
|
||||
<TemplateSettingsForm
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user