coder/site/src/components/DashboardLayout/DashboardLayout.tsx

76 lines
2.4 KiB
TypeScript

import { makeStyles } from "@material-ui/core/styles"
import { useMachine } from "@xstate/react"
import { Loader } from "components/Loader/Loader"
import { FC, Suspense } from "react"
import { Navbar } from "../Navbar/Navbar"
import { UpdateCheckBanner } from "components/UpdateCheckBanner/UpdateCheckBanner"
import { Margins } from "components/Margins/Margins"
import { Outlet } from "react-router-dom"
import { LicenseBanner } from "components/LicenseBanner/LicenseBanner"
import { ServiceBanner } from "components/ServiceBanner/ServiceBanner"
import { updateCheckMachine } from "xServices/updateCheck/updateCheckXService"
import { usePermissions } from "hooks/usePermissions"
import { UpdateCheckResponse } from "api/typesGenerated"
export const DashboardLayout: FC = () => {
const styles = useStyles()
const permissions = usePermissions()
const [updateCheckState, updateCheckSend] = useMachine(updateCheckMachine, {
context: {
permissions,
},
})
const { error: updateCheckError, updateCheck } = updateCheckState.context
return (
<>
<ServiceBanner />
<LicenseBanner />
<div className={styles.site}>
<Navbar />
{updateCheckState.matches("show") && (
<div className={styles.updateCheckBanner}>
<Margins>
<UpdateCheckBanner
// We can trust when it is show, the update check is filled
// unfortunately, XState does not has typed state - context yet
updateCheck={updateCheck as UpdateCheckResponse}
error={updateCheckError}
onDismiss={() => updateCheckSend("DISMISS")}
/>
</Margins>
</div>
)}
<div className={styles.siteContent}>
<Suspense fallback={<Loader />}>
<Outlet />
</Suspense>
</div>
</div>
</>
)
}
const useStyles = makeStyles((theme) => ({
site: {
display: "flex",
minHeight: "100vh",
flexDirection: "column",
},
updateCheckBanner: {
// Add spacing at the top and remove some from the bottom. Removal
// is necessary to avoid a visual jerk when the banner is dismissed.
// It also give a more pleasant distance to the site content when
// the banner is visible.
marginTop: theme.spacing(2),
marginBottom: -theme.spacing(2),
},
siteContent: {
flex: 1,
paddingBottom: theme.spacing(10),
},
}))