diff --git a/site/src/components/WarningAlert/WarningAlert.stories.tsx b/site/src/components/WarningAlert/WarningAlert.stories.tsx new file mode 100644 index 0000000000000..dc8eed293441e --- /dev/null +++ b/site/src/components/WarningAlert/WarningAlert.stories.tsx @@ -0,0 +1,35 @@ +import { Story } from "@storybook/react" +import { WarningAlert, WarningAlertProps } from "./WarningAlert" +import Button from "@material-ui/core/Button" + +export default { + title: "components/WarningAlert", + component: WarningAlert, +} + +const Template: Story = (args) => + +export const ExampleWithDismiss = Template.bind({}) +ExampleWithDismiss.args = { + text: "This is a warning", + dismissible: true, +} + +const ExampleAction = ( + +) + +export const ExampleWithAction = Template.bind({}) +ExampleWithAction.args = { + text: "This is a warning", + actions: [ExampleAction], +} + +export const ExampleWithActionAndDismiss = Template.bind({}) +ExampleWithActionAndDismiss.args = { + text: "This is a warning", + actions: [ExampleAction], + dismissible: true, +} diff --git a/site/src/components/WarningAlert/WarningAlert.tsx b/site/src/components/WarningAlert/WarningAlert.tsx new file mode 100644 index 0000000000000..7b0a024927913 --- /dev/null +++ b/site/src/components/WarningAlert/WarningAlert.tsx @@ -0,0 +1,61 @@ +import { useState, FC, ReactElement } from "react" +import Collapse from "@material-ui/core/Collapse" +import { Stack } from "components/Stack/Stack" +import { makeStyles, Theme } from "@material-ui/core/styles" +import { colors } from "theme/colors" +import ReportProblemOutlinedIcon from "@material-ui/icons/ReportProblemOutlined" +import Button from "@material-ui/core/Button" +import { useTranslation } from "react-i18next" + +export interface WarningAlertProps { + text: string + dismissible?: boolean + actions?: ReactElement[] +} + +export const WarningAlert: FC = ({ + text, + dismissible = false, + actions = [], +}) => { + const { t } = useTranslation("common") + const [open, setOpen] = useState(true) + const classes = useStyles() + + return ( + + + + + {text} + + + {actions.length > 0 && actions.map((action) =>
{action}
)} + {dismissible && ( + + )} +
+
+
+ ) +} + +const useStyles = makeStyles((theme) => ({ + alertContainer: { + border: `1px solid ${colors.orange[7]}`, + borderRadius: theme.shape.borderRadius, + padding: `${theme.spacing(1)}px ${theme.spacing(2)}px`, + backgroundColor: `${colors.gray[16]}`, + }, + alertIcon: { + color: `${colors.orange[7]}`, + }, +})) diff --git a/site/src/components/Workspace/Workspace.tsx b/site/src/components/Workspace/Workspace.tsx index 959c7dddfb924..e68063fe9e94b 100644 --- a/site/src/components/Workspace/Workspace.tsx +++ b/site/src/components/Workspace/Workspace.tsx @@ -15,6 +15,8 @@ import { WorkspaceScheduleBanner } from "../WorkspaceScheduleBanner/WorkspaceSch import { WorkspaceScheduleButton } from "../WorkspaceScheduleButton/WorkspaceScheduleButton" import { WorkspaceSection } from "../WorkspaceSection/WorkspaceSection" import { WorkspaceStats } from "../WorkspaceStats/WorkspaceStats" +import { WarningAlert } from "../WarningAlert/WarningAlert" +import { useTranslation } from "react-i18next" export enum WorkspaceErrors { GET_RESOURCES_ERROR = "getResourcesError", @@ -71,19 +73,21 @@ export const Workspace: FC> = ({ buildInfo, applicationsHost, }) => { + const { t } = useTranslation("workspacePage") const styles = useStyles() const navigate = useNavigate() const hasTemplateIcon = workspace.template_icon && workspace.template_icon !== "" - const buildError = workspaceErrors[WorkspaceErrors.BUILD_ERROR] ? ( + const buildError = Boolean(workspaceErrors[WorkspaceErrors.BUILD_ERROR]) && ( - ) : ( - <> ) - const cancellationError = workspaceErrors[WorkspaceErrors.CANCELLATION_ERROR] ? ( + + const cancellationError = Boolean(workspaceErrors[WorkspaceErrors.CANCELLATION_ERROR]) && ( - ) : ( - <> + ) + + const workspaceRefreshWarning = Boolean(workspaceErrors[WorkspaceErrors.GET_RESOURCES_ERROR]) && ( + ) return ( @@ -127,6 +131,7 @@ export const Workspace: FC> = ({ {buildError} {cancellationError} + {workspaceRefreshWarning} { - const styles = useStyles() + const { t } = useTranslation("workspacePage") + const NewWorkspaceButton = ( + + ) return ( - - {Language.createWorkspaceCta} - - } - severity="warning" - > - {Language.bannerTitle} - + ) } - -export const useStyles = makeStyles(() => { - return { - root: { - alignItems: "center", - "& .MuiAlertTitle-root": { - marginBottom: "0px", - }, - }, - } -}) diff --git a/site/src/components/WorkspaceScheduleBanner/WorkspaceScheduleBanner.tsx b/site/src/components/WorkspaceScheduleBanner/WorkspaceScheduleBanner.tsx index 81538af5352df..2ff5ca57096e1 100644 --- a/site/src/components/WorkspaceScheduleBanner/WorkspaceScheduleBanner.tsx +++ b/site/src/components/WorkspaceScheduleBanner/WorkspaceScheduleBanner.tsx @@ -1,21 +1,16 @@ import Button from "@material-ui/core/Button" -import Alert from "@material-ui/lab/Alert" -import AlertTitle from "@material-ui/lab/AlertTitle" import dayjs from "dayjs" import isSameOrBefore from "dayjs/plugin/isSameOrBefore" import utc from "dayjs/plugin/utc" import { FC } from "react" -import * as TypesGen from "../../api/typesGenerated" -import { isWorkspaceOn } from "../../util/workspace" +import * as TypesGen from "api/typesGenerated" +import { isWorkspaceOn } from "util/workspace" +import { WarningAlert } from "components/WarningAlert/WarningAlert" +import { useTranslation } from "react-i18next" dayjs.extend(utc) dayjs.extend(isSameOrBefore) -export const Language = { - bannerAction: "Extend", - bannerTitle: "Your workspace is scheduled to automatically shut down soon.", -} - export interface WorkspaceScheduleBannerProps { isLoading?: boolean onExtend: () => void @@ -36,26 +31,22 @@ export const WorkspaceScheduleBanner: FC { + const { t } = useTranslation("workspacePage") + if (!shouldDisplay(workspace)) { return null - } else { - return ( - - {Language.bannerAction} - - } - severity="warning" - > - {Language.bannerTitle} - - ) } + + const ScheduleButton = ( + + ) + + return ( + + ) } diff --git a/site/src/i18n/en/common.json b/site/src/i18n/en/common.json index 66c66cb6fbee4..c3b136edefae7 100644 --- a/site/src/i18n/en/common.json +++ b/site/src/i18n/en/common.json @@ -18,5 +18,8 @@ "confirm": "Are you sure you want to proceed? Type the name of this {{entity}} below to confirm.", "confirmLabel": "Name of {{entity}} to delete", "incorrectName": "Incorrect {{entity}} name." + }, + "ctas": { + "dismissCta": "Dismiss" } } diff --git a/site/src/i18n/en/workspacePage.json b/site/src/i18n/en/workspacePage.json index ceebe7b5a0356..781e03121ef42 100644 --- a/site/src/i18n/en/workspacePage.json +++ b/site/src/i18n/en/workspacePage.json @@ -7,6 +7,15 @@ "editDeadlineMinus": "Subtract one hour", "editDeadlinePlus": "Add one hour" }, + "ctas": { + "createWorkspaceCta": "Create new workspace", + "extendScheduleCta": "Extend" + }, + "warningsAndErrors": { + "workspaceRefreshWarning": "We're having difficulty fetching the latest workspace state. Refresh the page to see the newest changes.", + "workspaceDeletedWarning": "This workspace has been deleted and cannot be edited.", + "workspaceShutdownWarning": "Your workspace is scheduled to automatically shut down soon." + }, "actionButton": { "start": "Start", "stop": "Stop", pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy