chore: cleanup inline prop type definitions (#11317)

This commit is contained in:
Kayla Washburn
2024-01-02 10:39:00 -07:00
committed by GitHub
parent cf17fabcc6
commit a24c3b4dc7
28 changed files with 304 additions and 219 deletions
@@ -1,13 +1,14 @@
import { type FC } from "react";
import { useDashboard } from "components/Dashboard/DashboardProvider";
import { LicenseBannerView } from "./LicenseBannerView";
export const LicenseBanner: React.FC = () => {
export const LicenseBanner: FC = () => {
const { entitlements } = useDashboard();
const { errors, warnings } = entitlements;
if (errors.length > 0 || warnings.length > 0) {
return <LicenseBannerView errors={errors} warnings={warnings} />;
} else {
if (errors.length === 0 && warnings.length === 0) {
return null;
}
return <LicenseBannerView errors={errors} warnings={warnings} />;
};
@@ -1,24 +1,21 @@
import { type FC } from "react";
import { useDashboard } from "components/Dashboard/DashboardProvider";
import { ServiceBannerView } from "./ServiceBannerView";
export const ServiceBanner: React.FC = () => {
export const ServiceBanner: FC = () => {
const { appearance } = useDashboard();
const { message, background_color, enabled } =
appearance.config.service_banner;
if (!enabled) {
if (!enabled || message === undefined || background_color === undefined) {
return null;
}
if (message !== undefined && background_color !== undefined) {
return (
<ServiceBannerView
message={message}
backgroundColor={background_color}
isPreview={appearance.isPreview}
/>
);
} else {
return null;
}
return (
<ServiceBannerView
message={message}
backgroundColor={background_color}
isPreview={appearance.isPreview}
/>
);
};
@@ -1,15 +1,22 @@
import Button from "@mui/material/Button";
import LaunchOutlined from "@mui/icons-material/LaunchOutlined";
import type { FC } from "react";
import type { FC, ReactNode } from "react";
import { useTheme } from "@emotion/react";
import { Stack } from "components/Stack/Stack";
export const Header: FC<{
title: string | JSX.Element;
description?: string | JSX.Element;
interface HeaderProps {
title: ReactNode;
description?: ReactNode;
secondary?: boolean;
docsHref?: string;
}> = ({ title, description, docsHref, secondary }) => {
}
export const Header: FC<HeaderProps> = ({
title,
description,
docsHref,
secondary,
}) => {
const theme = useTheme();
return (
+5 -11
View File
@@ -1,5 +1,5 @@
import MuiDialog, { DialogProps as MuiDialogProps } from "@mui/material/Dialog";
import { type ReactNode } from "react";
import { type FC, type ReactNode } from "react";
import { ConfirmDialogType } from "./types";
import { type Interpolation, type Theme } from "@emotion/react";
import LoadingButton, { LoadingButtonProps } from "@mui/lab/LoadingButton";
@@ -30,7 +30,7 @@ const typeToColor = (type: ConfirmDialogType): LoadingButtonProps["color"] => {
/**
* Quickly handles most modals actions, some combination of a cancel and confirm button
*/
export const DialogActionButtons: React.FC<DialogActionButtonsProps> = ({
export const DialogActionButtons: FC<DialogActionButtonsProps> = ({
cancelText = "Cancel",
confirmText = "Confirm",
confirmLoading = false,
@@ -159,13 +159,7 @@ const styles = {
export type DialogProps = MuiDialogProps;
/**
* Wrapper around Material UI's Dialog component. Conveniently exports all of
* Dialog's components in one import, so for example `<DialogContent />` becomes
* `<Dialog.Content />` etc. Also contains some custom Dialog components listed below.
*
* See original component's Material UI documentation here: https://material-ui.com/components/dialogs/
* Re-export of MUI's Dialog component, for convenience.
* @link See original documentation here: https://mui.com/material-ui/react-dialog/
*/
export const Dialog: React.FC<DialogProps> = (props) => {
// Wrapped so we can add custom attributes below
return <MuiDialog {...props} />;
};
export { MuiDialog as Dialog };
+20 -29
View File
@@ -1,15 +1,16 @@
import { type Interpolation, type Theme } from "@emotion/react";
import Tooltip from "@mui/material/Tooltip";
import { WorkspaceAgent } from "api/typesGenerated";
import { ChooseOne, Cond } from "components/Conditionals/ChooseOne";
import WarningRounded from "@mui/icons-material/WarningRounded";
import Link from "@mui/material/Link";
import { type FC } from "react";
import type { WorkspaceAgent } from "api/typesGenerated";
import { ChooseOne, Cond } from "components/Conditionals/ChooseOne";
import {
HelpTooltip,
HelpTooltipContent,
HelpTooltipText,
HelpTooltipTitle,
} from "components/HelpTooltip/HelpTooltip";
import Link from "@mui/material/Link";
import { PopoverTrigger } from "components/Popover/Popover";
// If we think in the agent status and lifecycle into a single enum/state I’d
@@ -18,7 +19,7 @@ import { PopoverTrigger } from "components/Popover/Popover";
// connected:ready, connected:shutting_down, connected:shutdown_timeout,
// connected:shutdown_error, connected:off.
const ReadyLifecycle = () => {
const ReadyLifecycle: FC = () => {
return (
<div
role="status"
@@ -29,7 +30,7 @@ const ReadyLifecycle = () => {
);
};
const StartingLifecycle: React.FC = () => {
const StartingLifecycle: FC = () => {
return (
<Tooltip title="Starting...">
<div
@@ -41,9 +42,11 @@ const StartingLifecycle: React.FC = () => {
);
};
const StartTimeoutLifecycle: React.FC<{
interface AgentStatusProps {
agent: WorkspaceAgent;
}> = ({ agent }) => {
}
const StartTimeoutLifecycle: FC<AgentStatusProps> = ({ agent }) => {
return (
<HelpTooltip>
<PopoverTrigger role="status" aria-label="Agent timeout">
@@ -68,9 +71,7 @@ const StartTimeoutLifecycle: React.FC<{
);
};
const StartErrorLifecycle: React.FC<{
agent: WorkspaceAgent;
}> = ({ agent }) => {
const StartErrorLifecycle: FC<AgentStatusProps> = ({ agent }) => {
return (
<HelpTooltip>
<PopoverTrigger role="status" aria-label="Start error">
@@ -94,7 +95,7 @@ const StartErrorLifecycle: React.FC<{
);
};
const ShuttingDownLifecycle: React.FC = () => {
const ShuttingDownLifecycle: FC = () => {
return (
<Tooltip title="Stopping...">
<div
@@ -106,9 +107,7 @@ const ShuttingDownLifecycle: React.FC = () => {
);
};
const ShutdownTimeoutLifecycle: React.FC<{
agent: WorkspaceAgent;
}> = ({ agent }) => {
const ShutdownTimeoutLifecycle: FC<AgentStatusProps> = ({ agent }) => {
return (
<HelpTooltip>
<PopoverTrigger role="status" aria-label="Stop timeout">
@@ -132,9 +131,7 @@ const ShutdownTimeoutLifecycle: React.FC<{
);
};
const ShutdownErrorLifecycle: React.FC<{
agent: WorkspaceAgent;
}> = ({ agent }) => {
const ShutdownErrorLifecycle: FC<AgentStatusProps> = ({ agent }) => {
return (
<HelpTooltip>
<PopoverTrigger role="status" aria-label="Stop error">
@@ -158,7 +155,7 @@ const ShutdownErrorLifecycle: React.FC<{
);
};
const OffLifecycle: React.FC = () => {
const OffLifecycle: FC = () => {
return (
<Tooltip title="Stopped">
<div
@@ -170,9 +167,7 @@ const OffLifecycle: React.FC = () => {
);
};
const ConnectedStatus: React.FC<{
agent: WorkspaceAgent;
}> = ({ agent }) => {
const ConnectedStatus: FC<AgentStatusProps> = ({ agent }) => {
// This is to support legacy agents that do not support
// reporting the lifecycle_state field.
if (agent.scripts.length === 0) {
@@ -208,7 +203,7 @@ const ConnectedStatus: React.FC<{
);
};
const DisconnectedStatus: React.FC = () => {
const DisconnectedStatus: FC = () => {
return (
<Tooltip title="Disconnected">
<div
@@ -220,7 +215,7 @@ const DisconnectedStatus: React.FC = () => {
);
};
const ConnectingStatus: React.FC = () => {
const ConnectingStatus: FC = () => {
return (
<Tooltip title="Connecting...">
<div
@@ -232,9 +227,7 @@ const ConnectingStatus: React.FC = () => {
);
};
const TimeoutStatus: React.FC<{
agent: WorkspaceAgent;
}> = ({ agent }) => {
const TimeoutStatus: FC<AgentStatusProps> = ({ agent }) => {
return (
<HelpTooltip>
<PopoverTrigger role="status" aria-label="Timeout">
@@ -258,9 +251,7 @@ const TimeoutStatus: React.FC<{
);
};
export const AgentStatus: React.FC<{
agent: WorkspaceAgent;
}> = ({ agent }) => {
export const AgentStatus: FC<AgentStatusProps> = ({ agent }) => {
return (
<ChooseOne>
<Cond condition={agent.status === "connected"}>
@@ -3,12 +3,19 @@ import type { WorkspaceAgent } from "api/typesGenerated";
import { agentVersionStatus, getDisplayVersionStatus } from "utils/workspace";
import { AgentOutdatedTooltip } from "./AgentOutdatedTooltip";
export const AgentVersion: FC<{
interface AgentVersionProps {
agent: WorkspaceAgent;
serverVersion: string;
serverAPIVersion: string;
onUpdate: () => void;
}> = ({ agent, serverVersion, serverAPIVersion, onUpdate }) => {
}
export const AgentVersion: FC<AgentVersionProps> = ({
agent,
serverVersion,
serverAPIVersion,
onUpdate,
}) => {
const { status } = getDisplayVersionStatus(
agent.version,
serverVersion,
@@ -1,15 +1,17 @@
import { WorkspaceApp } from "api/typesGenerated";
import { FC } from "react";
import ComputerIcon from "@mui/icons-material/Computer";
import { type FC } from "react";
import type { WorkspaceApp } from "api/typesGenerated";
export const BaseIcon: FC<{ app: WorkspaceApp }> = ({ app }) => {
interface BaseIconProps {
app: WorkspaceApp;
}
export const BaseIcon: FC<BaseIconProps> = ({ app }) => {
return app.icon ? (
<img
alt={`${app.display_name} Icon`}
src={app.icon}
style={{
pointerEvents: "none",
}}
style={{ pointerEvents: "none" }}
/>
) : (
<ComputerIcon />
@@ -3,7 +3,7 @@ import Tooltip from "@mui/material/Tooltip";
import VisibilityOffOutlined from "@mui/icons-material/VisibilityOffOutlined";
import VisibilityOutlined from "@mui/icons-material/VisibilityOutlined";
import { type FC, useState } from "react";
import { css } from "@emotion/react";
import { css, type Interpolation, type Theme } from "@emotion/react";
import { CopyableValue } from "components/CopyableValue/CopyableValue";
const Language = {
@@ -11,7 +11,11 @@ const Language = {
hideLabel: "Hide value",
};
export const SensitiveValue: FC<{ value: string }> = ({ value }) => {
interface SensitiveValueProps {
value: string;
}
export const SensitiveValue: FC<SensitiveValueProps> = ({ value }) => {
const [shouldDisplay, setShouldDisplay] = useState(false);
const displayValue = shouldDisplay ? value : "••••••••";
const buttonLabel = shouldDisplay ? Language.hideLabel : Language.showLabel;
@@ -29,28 +33,12 @@ export const SensitiveValue: FC<{ value: string }> = ({ value }) => {
gap: 4,
}}
>
<CopyableValue
value={value}
css={{
// 22px is the button width
width: "calc(100% - 22px)",
overflow: "hidden",
whiteSpace: "nowrap",
textOverflow: "ellipsis",
}}
>
<CopyableValue value={value} css={styles.value}>
{displayValue}
</CopyableValue>
<Tooltip title={buttonLabel}>
<IconButton
css={css`
color: inherit;
& .MuiSvgIcon-root {
width: 16px;
height: 16px;
}
`}
css={styles.button}
onClick={() => {
setShouldDisplay((value) => !value);
}}
@@ -63,3 +51,22 @@ export const SensitiveValue: FC<{ value: string }> = ({ value }) => {
</div>
);
};
const styles = {
value: {
// 22px is the button width
width: "calc(100% - 22px)",
overflow: "hidden",
whiteSpace: "nowrap",
textOverflow: "ellipsis",
},
button: css`
color: inherit;
& .MuiSvgIcon-root {
width: 16px;
height: 16px;
}
`,
} satisfies Record<string, Interpolation<Theme>>;
@@ -160,7 +160,7 @@ export const RichParameterInput: FC<RichParameterInputProps> = ({
);
};
const RichParameterField: React.FC<RichParameterInputProps> = ({
const RichParameterField: FC<RichParameterInputProps> = ({
disabled,
onChange,
parameter,
@@ -1,43 +1,44 @@
import { type FC, type ReactNode } from "react";
import { type Interpolation, type Theme } from "@emotion/react";
import { type FC, type PropsWithChildren } from "react";
export const SignInLayout: FC<{ children: ReactNode }> = ({ children }) => {
export const SignInLayout: FC<PropsWithChildren> = ({ children }) => {
return (
<div
css={{
flex: 1,
height: "-webkit-fill-available",
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
<div
css={{
display: "flex",
flexDirection: "column",
alignItems: "center",
}}
>
<div
css={{
maxWidth: 385,
display: "flex",
flexDirection: "column",
alignItems: "center",
}}
>
{children}
</div>
<div
css={(theme) => ({
fontSize: 12,
color: theme.palette.text.secondary,
marginTop: 24,
})}
>
{`\u00a9 ${new Date().getFullYear()} Coder Technologies, Inc.`}
<div css={styles.container}>
<div css={styles.content}>
<div css={styles.signIn}>{children}</div>
<div css={styles.copyright}>
{"\u00a9"} {new Date().getFullYear()} Coder Technologies, Inc.
</div>
</div>
</div>
);
};
const styles = {
container: {
flex: 1,
height: "-webkit-fill-available",
display: "flex",
justifyContent: "center",
alignItems: "center",
},
content: {
display: "flex",
flexDirection: "column",
alignItems: "center",
},
signIn: {
maxWidth: 385,
display: "flex",
flexDirection: "column",
alignItems: "center",
},
copyright: (theme) => ({
fontSize: 12,
color: theme.palette.text.secondary,
marginTop: 24,
}),
} satisfies Record<string, Interpolation<Theme>>;
@@ -1,4 +1,4 @@
import { FC } from "react";
import { type FC } from "react";
import { TemplateAutostartRequirementDaysValue } from "utils/schedule";
import Button from "@mui/material/Button";
import { Stack } from "components/Stack/Stack";
@@ -11,9 +11,7 @@ export interface TemplateScheduleAutostartProps {
onChange: (newDaysOfWeek: TemplateAutostartRequirementDaysValue[]) => void;
}
export const TemplateScheduleAutostart: FC<
React.PropsWithChildren<TemplateScheduleAutostartProps>
> = ({
export const TemplateScheduleAutostart: FC<TemplateScheduleAutostartProps> = ({
autostart_requirement_days_of_week,
isSubmitting,
allow_user_autostart,
@@ -24,18 +22,14 @@ export const TemplateScheduleAutostart: FC<
direction="column"
width="100%"
alignItems="center"
css={{
marginBottom: "20px",
}}
css={{ marginBottom: "20px" }}
>
<Stack
direction="row"
css={{
width: "100%",
}}
spacing={0}
alignItems="baseline"
justifyContent="center"
css={{ width: "100%" }}
>
{(
[
@@ -53,9 +47,7 @@ export const TemplateScheduleAutostart: FC<
).map((day) => (
<Button
key={day.key}
css={{
borderRadius: "0px",
}}
css={{ borderRadius: 0 }}
// TODO: Adding a background color would also help
color={
autostart_requirement_days_of_week.includes(day.value)
@@ -80,7 +72,7 @@ export const TemplateScheduleAutostart: FC<
))}
</Stack>
<FormHelperText>
<AutostartRequirementDaysHelperText
<AutostartHelperText
allowed={allow_user_autostart}
days={autostart_requirement_days_of_week}
/>
@@ -99,24 +91,26 @@ export const sortedDays = [
"sunday",
] as TemplateAutostartRequirementDaysValue[];
const AutostartRequirementDaysHelperText: FC<{
interface AutostartHelperTextProps {
allowed?: boolean;
days: TemplateAutostartRequirementDaysValue[];
}> = ({ allowed, days: unsortedDays }) => {
}
const AutostartHelperText: FC<AutostartHelperTextProps> = ({
allowed,
days: unsortedDays,
}) => {
if (!allowed) {
return <span>Workspaces are not allowed to auto start.</span>;
}
// Sort the days
const days = unsortedDays.sort(
(a, b) => sortedDays.indexOf(a) - sortedDays.indexOf(b),
);
let daymsg = `Workspaces can autostart on ${days.join(", ")}.`;
if (days.length === 7) {
const days = new Set(unsortedDays);
if (days.size === 7) {
// If every day is allowed, no more explaining is needed.
return <span>Workspaces are allowed to auto start on any day.</span>;
}
if (days.length === 0) {
if (days.size === 0) {
return (
<span>
Workspaces will never auto start. This is effectively the same as
@@ -124,13 +118,14 @@ const AutostartRequirementDaysHelperText: FC<{
</span>
);
}
if (
days.length === 5 &&
!days.includes("saturday") &&
!days.includes("sunday")
) {
daymsg = "Workspaces will never auto start on the weekends.";
let daymsg = "Workspaces will never auto start on the weekends.";
if (days.size !== 5 || days.has("saturday") || days.has("sunday")) {
daymsg = `Workspaces can autostart on ${sortedDays
.filter((day) => days.has(day))
.join(", ")}.`;
}
return (
<span>{daymsg} These days are relative to the user&apos;s timezone.</span>
);
@@ -1,11 +1,15 @@
import { AuditLog } from "api/typesGenerated";
import { FC, useMemo } from "react";
import type { AuditLog } from "api/typesGenerated";
import { type FC, useMemo } from "react";
import { Link as RouterLink } from "react-router-dom";
import Link from "@mui/material/Link";
export const BuildAuditDescription: FC<{ auditLog: AuditLog }> = ({
interface BuildAuditDescriptionProps {
auditLog: AuditLog;
}
export const BuildAuditDescription: FC<BuildAuditDescriptionProps> = ({
auditLog,
}): JSX.Element => {
}) => {
const workspaceName = auditLog.additional_fields?.workspace_name?.trim();
// workspaces can be started/stopped/deleted by a user, or kicked off automatically by Coder
const user =
@@ -1,6 +1,6 @@
import { type Interpolation, type Theme } from "@emotion/react";
import { type FC } from "react";
import type { AuditLog } from "api/typesGenerated";
import type { AuditDiff } from "api/typesGenerated";
import colors from "theme/tailwindColors";
import { MONOSPACE_FONT_FAMILY } from "theme/constants";
@@ -21,7 +21,11 @@ const getDiffValue = (value: unknown): string => {
return String(value);
};
export const AuditLogDiff: FC<{ diff: AuditLog["diff"] }> = ({ diff }) => {
interface AuditLogDiffProps {
diff: AuditDiff;
}
export const AuditLogDiff: FC<AuditLogDiffProps> = ({ diff }) => {
const diffEntries = Object.entries(diff);
return (
@@ -7,7 +7,7 @@ import { Pill, type PillType } from "components/Pill/Pill";
import { Stack } from "components/Stack/Stack";
import { TimelineEntry } from "components/Timeline/TimelineEntry";
import { UserAvatar } from "components/UserAvatar/UserAvatar";
import { useState } from "react";
import { type FC, useState } from "react";
import userAgentParser from "ua-parser-js";
import { AuditLogDiff } from "./AuditLogDiff/AuditLogDiff";
import { AuditLogDescription } from "./AuditLogDescription/AuditLogDescription";
@@ -36,7 +36,7 @@ export interface AuditLogRowProps {
defaultIsDiffOpen?: boolean;
}
export const AuditLogRow: React.FC<AuditLogRowProps> = ({
export const AuditLogRow: FC<AuditLogRowProps> = ({
auditLog,
defaultIsDiffOpen = false,
}) => {
@@ -11,9 +11,11 @@ const isBoolean = (variable: TemplateVersionVariable) => {
return variable.type === "bool";
};
const VariableLabel: FC<{ variable: TemplateVersionVariable }> = ({
variable,
}) => {
interface VariableLabelProps {
variable: TemplateVersionVariable;
}
const VariableLabel: FC<VariableLabelProps> = ({ variable }) => {
return (
<label htmlFor={variable.name}>
<span css={styles.labelName}>
@@ -53,7 +55,7 @@ export const VariableInput: FC<VariableInputProps> = ({
);
};
const VariableField: React.FC<VariableInputProps> = ({
const VariableField: FC<VariableInputProps> = ({
disabled,
onChange,
variable,
@@ -137,10 +137,15 @@ const ExternalAuthPageView: FC<ExternalAuthPageViewProps> = ({
);
};
const GitDeviceAuth: FC<{
interface GitDeviceAuthProps {
externalAuthDevice?: ExternalAuthDevice;
deviceExchangeError?: ApiErrorResponse;
}> = ({ externalAuthDevice, deviceExchangeError }) => {
}
const GitDeviceAuth: FC<GitDeviceAuthProps> = ({
externalAuthDevice,
deviceExchangeError,
}) => {
let status = (
<p css={styles.status}>
<CircularProgress size={16} color="secondary" data-chromatic="ignore" />
+11 -4
View File
@@ -211,10 +211,12 @@ export const GroupPage: FC = () => {
);
};
const AddGroupMember: React.FC<{
interface AddGroupMemberProps {
isLoading: boolean;
onSubmit: (user: User, reset: () => void) => void;
}> = ({ isLoading, onSubmit }) => {
}
const AddGroupMember: FC<AddGroupMemberProps> = ({ isLoading, onSubmit }) => {
const [selectedUser, setSelectedUser] = useState<User | null>(null);
const resetValues = () => {
@@ -254,12 +256,17 @@ const AddGroupMember: React.FC<{
);
};
const GroupMemberRow = (props: {
interface GroupMemberRowProps {
member: User;
group: Group;
canUpdate: boolean;
}
const GroupMemberRow: FC<GroupMemberRowProps> = ({
member,
group,
canUpdate,
}) => {
const { member, group, canUpdate } = props;
const queryClient = useQueryClient();
const removeMemberMutation = useMutation(removeMember(queryClient));
@@ -28,13 +28,21 @@ const validationSchema = Yup.object({
quota_allowance: Yup.number().required().min(0).integer(),
});
const UpdateGroupForm: FC<{
interface UpdateGroupFormProps {
group: Group;
errors: unknown;
onSubmit: (data: FormData) => void;
onCancel: () => void;
isLoading: boolean;
}> = ({ group, errors, onSubmit, onCancel, isLoading }) => {
}
const UpdateGroupForm: FC<UpdateGroupFormProps> = ({
group,
errors,
onSubmit,
onCancel,
isLoading,
}) => {
const form = useFormik<FormData>({
initialValues: {
name: group.name,
+8 -7
View File
@@ -1,19 +1,20 @@
import Checkbox from "@mui/material/Checkbox";
import Link from "@mui/material/Link";
import TextField from "@mui/material/TextField";
import { SignInLayout } from "components/SignInLayout/SignInLayout";
import LoadingButton from "@mui/lab/LoadingButton";
import { type FormikContextType, useFormik } from "formik";
import { type FC } from "react";
import * as Yup from "yup";
import type * as TypesGen from "api/typesGenerated";
import {
getFormHelpers,
nameValidator,
onChangeTrimmed,
} from "utils/formUtils";
import * as Yup from "yup";
import type * as TypesGen from "api/typesGenerated";
import LoadingButton from "@mui/lab/LoadingButton";
import { docs } from "utils/docs";
import { SignInLayout } from "components/SignInLayout/SignInLayout";
import { FormFields, VerticalForm } from "components/Form/Form";
import { CoderIcon } from "components/Icons/CoderIcon";
import Link from "@mui/material/Link";
import { docs } from "utils/docs";
export const Language = {
emailLabel: "Email",
@@ -41,7 +42,7 @@ export interface SetupPageViewProps {
isLoading?: boolean;
}
export const SetupPageView: React.FC<SetupPageViewProps> = ({
export const SetupPageView: FC<SetupPageViewProps> = ({
onSubmit,
error,
isLoading,
@@ -16,7 +16,7 @@ import {
TemplateParametersSectionProps,
} from "components/TemplateParameters/TemplateParameters";
import { useClipboard } from "hooks/useClipboard";
import { FC, useEffect, useState } from "react";
import { type FC, useEffect, useState } from "react";
import { Helmet } from "react-helmet-async";
import { pageTitle } from "utils/page";
import { getInitialRichParameterValues } from "utils/richParameters";
@@ -24,7 +24,7 @@ import { paramsUsedToCreateWorkspace } from "utils/workspace";
type ButtonValues = Record<string, string>;
const TemplateEmbedPage = () => {
const TemplateEmbedPage: FC = () => {
const { template } = useTemplateLayoutContext();
const { data: templateParameters } = useQuery({
queryKey: ["template", template.id, "embed"],
@@ -46,10 +46,15 @@ const TemplateEmbedPage = () => {
);
};
export const TemplateEmbedPageView: FC<{
interface TemplateEmbedPageViewProps {
template: Template;
templateParameters?: TemplateVersionParameter[];
}> = ({ template, templateParameters }) => {
}
export const TemplateEmbedPageView: FC<TemplateEmbedPageViewProps> = ({
template,
templateParameters,
}) => {
const [buttonValues, setButtonValues] = useState<ButtonValues | undefined>(
undefined,
);
@@ -1,4 +1,10 @@
import { createContext, type FC, Suspense, useContext } from "react";
import {
createContext,
type FC,
type PropsWithChildren,
Suspense,
useContext,
} from "react";
import { useQuery } from "react-query";
import { Outlet, useNavigate, useParams } from "react-router-dom";
import type { AuthorizationRequest } from "api/typesGenerated";
@@ -64,7 +70,7 @@ export const useTemplateLayoutContext = (): TemplateLayoutContextValue => {
return context;
};
export const TemplateLayout: FC<{ children?: JSX.Element }> = ({
export const TemplateLayout: FC<PropsWithChildren> = ({
children = <Outlet />,
}) => {
const navigate = useNavigate();
@@ -7,7 +7,9 @@ import TableContainer from "@mui/material/TableContainer";
import TableHead from "@mui/material/TableHead";
import TableRow from "@mui/material/TableRow";
import PersonAdd from "@mui/icons-material/PersonAdd";
import LoadingButton from "@mui/lab/LoadingButton";
import { type Interpolation, type Theme } from "@emotion/react";
import { type FC, useState } from "react";
import type {
Group,
TemplateACL,
@@ -15,6 +17,16 @@ import type {
TemplateRole,
TemplateUser,
} from "api/typesGenerated";
import { getGroupSubtitle } from "utils/groups";
import { GroupAvatar } from "components/GroupAvatar/GroupAvatar";
import { PageHeader, PageHeaderTitle } from "components/PageHeader/PageHeader";
import {
MoreMenu,
MoreMenuContent,
MoreMenuItem,
MoreMenuTrigger,
ThreeDotsButton,
} from "components/MoreMenu/MoreMenu";
import { AvatarData } from "components/AvatarData/AvatarData";
import { ChooseOne, Cond } from "components/Conditionals/ChooseOne";
import { EmptyState } from "components/EmptyState/EmptyState";
@@ -24,18 +36,6 @@ import {
UserOrGroupAutocomplete,
UserOrGroupAutocompleteValue,
} from "./UserOrGroupAutocomplete";
import { type FC, useState } from "react";
import { GroupAvatar } from "components/GroupAvatar/GroupAvatar";
import { getGroupSubtitle } from "utils/groups";
import { PageHeader, PageHeaderTitle } from "components/PageHeader/PageHeader";
import LoadingButton from "@mui/lab/LoadingButton";
import {
MoreMenu,
MoreMenuContent,
MoreMenuItem,
MoreMenuTrigger,
ThreeDotsButton,
} from "components/MoreMenu/MoreMenu";
type AddTemplateUserOrGroupProps = {
organizationId: string;
@@ -49,7 +49,7 @@ type AddTemplateUserOrGroupProps = {
) => void;
};
const AddTemplateUserOrGroup: React.FC<AddTemplateUserOrGroupProps> = ({
const AddTemplateUserOrGroup: FC<AddTemplateUserOrGroupProps> = ({
isLoading,
onSubmit,
templateID,
@@ -1,17 +1,25 @@
import TextField from "@mui/material/TextField";
import { ConfirmDialog } from "components/Dialogs/ConfirmDialog/ConfirmDialog";
import { Stack } from "components/Stack/Stack";
import { ChangeEvent, FC, useState } from "react";
import { type ChangeEvent, type FC, useState } from "react";
import { allowedExtensions, isAllowedFile } from "utils/templateVersion";
import { FileTree, isFolder, validatePath } from "utils/filetree";
import { type FileTree, isFolder, validatePath } from "utils/filetree";
export const CreateFileDialog: FC<{
interface CreateFileDialogProps {
onClose: () => void;
checkExists: (path: string) => boolean;
onConfirm: (path: string) => void;
open: boolean;
fileTree: FileTree;
}> = ({ checkExists, onClose, onConfirm, open, fileTree }) => {
}
export const CreateFileDialog: FC<CreateFileDialogProps> = ({
checkExists,
onClose,
onConfirm,
open,
fileTree,
}) => {
const [pathValue, setPathValue] = useState("");
const [error, setError] = useState<string>();
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
@@ -86,12 +94,19 @@ export const CreateFileDialog: FC<{
);
};
export const DeleteFileDialog: FC<{
interface DeleteFileDialogProps {
onClose: () => void;
onConfirm: () => void;
open: boolean;
filename: string;
}> = ({ onClose, onConfirm, open, filename }) => {
}
export const DeleteFileDialog: FC<DeleteFileDialogProps> = ({
onClose,
onConfirm,
open,
filename,
}) => {
return (
<ConfirmDialog
type="delete"
@@ -109,14 +124,23 @@ export const DeleteFileDialog: FC<{
);
};
export const RenameFileDialog: FC<{
interface RenameFileDialogProps {
onClose: () => void;
onConfirm: (filename: string) => void;
checkExists: (path: string) => boolean;
open: boolean;
filename: string;
fileTree: FileTree;
}> = ({ checkExists, onClose, onConfirm, open, filename, fileTree }) => {
}
export const RenameFileDialog: FC<RenameFileDialogProps> = ({
checkExists,
onClose,
onConfirm,
open,
filename,
fileTree,
}) => {
const [pathValue, setPathValue] = useState(filename);
const [error, setError] = useState<string>();
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
@@ -5,9 +5,13 @@ import ErrorIcon from "@mui/icons-material/ErrorOutline";
import CheckIcon from "@mui/icons-material/CheckOutlined";
import { Pill, type PillType } from "components/Pill/Pill";
export const TemplateVersionStatusBadge: FC<{
interface TemplateVersionStatusBadgeProps {
version: TemplateVersion;
}> = ({ version }) => {
}
export const TemplateVersionStatusBadge: FC<
TemplateVersionStatusBadgeProps
> = ({ version }) => {
const { text, icon, type } = getStatus(version);
return (
<Pill icon={icon} type={type} title={`Build status is ${text}`}>
@@ -35,10 +35,15 @@ const findFeaturedExamples = (examples: TemplateExample[]) => {
return featuredExamples;
};
export const EmptyTemplates: FC<{
interface EmptyTemplatesProps {
canCreateTemplates: boolean;
examples: TemplateExample[];
}> = ({ canCreateTemplates, examples }) => {
}
export const EmptyTemplates: FC<EmptyTemplatesProps> = ({
canCreateTemplates,
examples,
}) => {
const featuredExamples = findFeaturedExamples(examples);
if (canCreateTemplates) {
+2 -2
View File
@@ -1,4 +1,4 @@
import { type FC, type ReactNode, useState } from "react";
import { type FC, type PropsWithChildren, useState } from "react";
import { type User } from "api/typesGenerated";
import { roles } from "api/queries/roles";
@@ -35,7 +35,7 @@ import { UsersPageView } from "./UsersPageView";
import { displayError, displaySuccess } from "components/GlobalSnackbar/utils";
import { usePaginatedQuery } from "hooks/usePaginatedQuery";
export const UsersPage: FC<{ children?: ReactNode }> = () => {
export const UsersPage: FC<PropsWithChildren> = () => {
const queryClient = useQueryClient();
const navigate = useNavigate();
+2 -1
View File
@@ -1,5 +1,6 @@
import TableCell from "@mui/material/TableCell";
import { type CSSObject, type Interpolation, type Theme } from "@emotion/react";
import { type FC } from "react";
import { useNavigate } from "react-router-dom";
import type { WorkspaceBuild } from "api/typesGenerated";
import { BuildAvatar } from "components/BuildAvatar/BuildAvatar";
@@ -21,7 +22,7 @@ const transitionMessages = {
delete: "deleted",
};
export const BuildRow: React.FC<BuildRowProps> = ({ build }) => {
export const BuildRow: FC<BuildRowProps> = ({ build }) => {
const initiatedBy = getDisplayWorkspaceBuildInitiatedBy(build);
const navigate = useNavigate();
const clickableProps = useClickable<HTMLTableRowElement>(() =>
@@ -27,12 +27,19 @@ export type WorkspaceSettingsFormValues = {
automatic_updates: AutomaticUpdates;
};
export const WorkspaceSettingsForm: FC<{
interface WorkspaceSettingsFormProps {
workspace: Workspace;
error: unknown;
onCancel: () => void;
onSubmit: (values: WorkspaceSettingsFormValues) => Promise<void>;
}> = ({ onCancel, onSubmit, workspace, error }) => {
}
export const WorkspaceSettingsForm: FC<WorkspaceSettingsFormProps> = ({
onCancel,
onSubmit,
workspace,
error,
}) => {
const formEnabled =
!workspace.template_require_active_version || workspace.allow_renames;