feat: Redesign workspaces page (#1450)

* feat: Improve navbar to be more compact

The navbar was unnecessarily large before, which made
the UI feel a bit bloaty from my perspective.

* Attempt to remove overrides

* Update theme

* Add text field

* Update theme to dark!

* Fix import ordering

* Fix page location

* Fix requested changes

* Add storybook for workspaces page view

* Add empty view

* Add tests for empty view

* Remove templates page

* Fix local port

* Remove templates from nav

* Fix e2e test

* Remove time.ts

* Remove dep

* Add background color to margins

* Merge status checking from workspace page

* Fix requested changes

* Fix workspace status tests
This commit is contained in:
Kyle Carberry
2022-05-16 16:52:54 -05:00
committed by GitHub
parent e925818526
commit 22ec366535
53 changed files with 626 additions and 1743 deletions

View File

@ -1,20 +1,17 @@
import CssBaseline from "@material-ui/core/CssBaseline" import CssBaseline from "@material-ui/core/CssBaseline"
import ThemeProvider from "@material-ui/styles/ThemeProvider" import ThemeProvider from "@material-ui/styles/ThemeProvider"
import { withThemes } from "@react-theming/storybook-addon"
import { createMemoryHistory } from "history" import { createMemoryHistory } from "history"
import { addDecorator } from "node_modules/@storybook/react" import { addDecorator } from "node_modules/@storybook/react"
import { unstable_HistoryRouter as HistoryRouter } from "react-router-dom" import { unstable_HistoryRouter as HistoryRouter } from "react-router-dom"
import { dark, light } from "../src/theme" import { dark } from "../src/theme"
import "../src/theme/globalFonts" import "../src/theme/globalFonts"
const providerFn = ({ children, theme }) => ( addDecorator((story) => (
<ThemeProvider theme={theme}> <ThemeProvider theme={dark}>
<CssBaseline /> <CssBaseline />
{children} {story()}
</ThemeProvider> </ThemeProvider>
) ))
addDecorator(withThemes(null, [light, dark], { providerFn }))
const history = createMemoryHistory() const history = createMemoryHistory()

View File

@ -1,8 +1,8 @@
import { Page } from "@playwright/test" import { Page } from "@playwright/test"
import { BasePom } from "./BasePom" import { BasePom } from "./BasePom"
export class TemplatesPage extends BasePom { export class WorkspacesPage extends BasePom {
constructor(baseURL: string | undefined, page: Page) { constructor(baseURL: string | undefined, page: Page) {
super(baseURL, "/templates", page) super(baseURL, "/workspaces", page)
} }
} }

View File

@ -1,2 +1,2 @@
export * from "./SignInPage" export * from "./SignInPage"
export * from "./TemplatesPage" export * from "./WorkspacesPage"

View File

@ -1,17 +1,17 @@
import { test } from "@playwright/test" import { test } from "@playwright/test"
import { email, password } from "../constants" import { email, password } from "../constants"
import { SignInPage, TemplatesPage } from "../pom" import { SignInPage, WorkspacesPage } from "../pom"
import { waitForClientSideNavigation } from "./../util" import { waitForClientSideNavigation } from "./../util"
test("Login takes user to /templates", async ({ baseURL, page }) => { test("Login takes user to /workspaces", async ({ baseURL, page }) => {
await page.goto(baseURL + "/", { waitUntil: "networkidle" }) await page.goto(baseURL + "/", { waitUntil: "networkidle" })
// Log-in with the default credentials we set up in the development server // Log-in with the default credentials we set up in the development server
const signInPage = new SignInPage(baseURL, page) const signInPage = new SignInPage(baseURL, page)
await signInPage.submitBuiltInAuthentication(email, password) await signInPage.submitBuiltInAuthentication(email, password)
const templatesPage = new TemplatesPage(baseURL, page) const workspacesPage = new WorkspacesPage(baseURL, page)
await waitForClientSideNavigation(page, { to: templatesPage.url }) await waitForClientSideNavigation(page, { to: workspacesPage.url })
await page.waitForSelector("text=Templates") await page.waitForSelector("text=Workspaces")
}) })

View File

@ -25,7 +25,7 @@
"typegen": "xstate typegen 'src/**/*.ts'" "typegen": "xstate typegen 'src/**/*.ts'"
}, },
"dependencies": { "dependencies": {
"@fontsource/fira-code": "4.5.9", "@fontsource/ibm-plex-mono": "4.5.9",
"@fontsource/inter": "4.5.7", "@fontsource/inter": "4.5.7",
"@material-ui/core": "4.9.4", "@material-ui/core": "4.9.4",
"@material-ui/icons": "4.5.1", "@material-ui/icons": "4.5.1",
@ -35,6 +35,7 @@
"@xstate/react": "3.0.0", "@xstate/react": "3.0.0",
"axios": "0.26.1", "axios": "0.26.1",
"cronstrue": "2.4.0", "cronstrue": "2.4.0",
"dayjs": "^1.11.2",
"formik": "2.2.9", "formik": "2.2.9",
"history": "5.3.0", "history": "5.3.0",
"react": "17.0.2", "react": "17.0.2",
@ -53,7 +54,6 @@
"devDependencies": { "devDependencies": {
"@playwright/test": "1.21.1", "@playwright/test": "1.21.1",
"@pmmmwh/react-refresh-webpack-plugin": "0.5.5", "@pmmmwh/react-refresh-webpack-plugin": "0.5.5",
"@react-theming/storybook-addon": "1.1.5",
"@storybook/addon-actions": "6.4.22", "@storybook/addon-actions": "6.4.22",
"@storybook/addon-essentials": "6.4.22", "@storybook/addon-essentials": "6.4.22",
"@storybook/addon-links": "6.4.22", "@storybook/addon-links": "6.4.22",

View File

@ -12,15 +12,13 @@ import { OrgsPage } from "./pages/OrgsPage/OrgsPage"
import { SettingsPage } from "./pages/SettingsPage/SettingsPage" import { SettingsPage } from "./pages/SettingsPage/SettingsPage"
import { AccountPage } from "./pages/SettingsPages/AccountPage/AccountPage" import { AccountPage } from "./pages/SettingsPages/AccountPage/AccountPage"
import { SSHKeysPage } from "./pages/SettingsPages/SSHKeysPage/SSHKeysPage" import { SSHKeysPage } from "./pages/SettingsPages/SSHKeysPage/SSHKeysPage"
import { CreateWorkspacePage } from "./pages/TemplatesPages/OrganizationPage/TemplatePage/CreateWorkspacePage"
import { TemplatePage } from "./pages/TemplatesPages/OrganizationPage/TemplatePage/TemplatePage"
import { TemplatesPage } from "./pages/TemplatesPages/TemplatesPage"
import { CreateUserPage } from "./pages/UsersPage/CreateUserPage/CreateUserPage" import { CreateUserPage } from "./pages/UsersPage/CreateUserPage/CreateUserPage"
import { UsersPage } from "./pages/UsersPage/UsersPage" import { UsersPage } from "./pages/UsersPage/UsersPage"
import { WorkspacePage } from "./pages/WorkspacePage/WorkspacePage" import { WorkspacePage } from "./pages/WorkspacePage/WorkspacePage"
import { WorkspaceSettingsPage } from "./pages/WorkspaceSettingsPage/WorkspaceSettingsPage" import { WorkspaceSettingsPage } from "./pages/WorkspaceSettingsPage/WorkspaceSettingsPage"
const TerminalPage = React.lazy(() => import("./pages/TerminalPage/TerminalPage")) const TerminalPage = React.lazy(() => import("./pages/TerminalPage/TerminalPage"))
const WorkspacesPage = React.lazy(() => import("./pages/WorkspacesPage/WorkspacesPage"))
export const AppRouter: React.FC = () => ( export const AppRouter: React.FC = () => (
<React.Suspense fallback={<></>}> <React.Suspense fallback={<></>}>
@ -46,36 +44,15 @@ export const AppRouter: React.FC = () => (
} }
/> />
<Route path="templates">
<Route
index
element={
<AuthAndFrame>
<TemplatesPage />
</AuthAndFrame>
}
/>
<Route path=":organization/:template">
<Route
index
element={
<AuthAndFrame>
<TemplatePage />
</AuthAndFrame>
}
/>
<Route
path="create"
element={
<RequireAuth>
<CreateWorkspacePage />
</RequireAuth>
}
/>
</Route>
</Route>
<Route path="workspaces"> <Route path="workspaces">
<Route
index
element={
<AuthAndFrame>
<WorkspacesPage />
</AuthAndFrame>
}
/>
<Route path=":workspace"> <Route path=":workspace">
<Route <Route
index index

View File

@ -115,6 +115,11 @@ export const getWorkspace = async (workspaceId: string): Promise<TypesGen.Worksp
return response.data return response.data
} }
export const getWorkspaces = async (userID = "me"): Promise<TypesGen.Workspace[]> => {
const response = await axios.get<TypesGen.Workspace[]>(`/api/v2/users/${userID}/workspaces`)
return response.data
}
export const getWorkspaceByOwnerAndName = async ( export const getWorkspaceByOwnerAndName = async (
organizationID: string, organizationID: string,
username = "me", username = "me",

View File

@ -5,7 +5,7 @@ import { BrowserRouter as Router } from "react-router-dom"
import { SWRConfig } from "swr" import { SWRConfig } from "swr"
import { AppRouter } from "./AppRouter" import { AppRouter } from "./AppRouter"
import { GlobalSnackbar } from "./components/GlobalSnackbar/GlobalSnackbar" import { GlobalSnackbar } from "./components/GlobalSnackbar/GlobalSnackbar"
import { light } from "./theme" import { dark } from "./theme"
import "./theme/globalFonts" import "./theme/globalFonts"
import { XServiceProvider } from "./xServices/StateContext" import { XServiceProvider } from "./xServices/StateContext"
@ -31,7 +31,7 @@ export const App: React.FC = () => {
}} }}
> >
<XServiceProvider> <XServiceProvider>
<ThemeProvider theme={light}> <ThemeProvider theme={dark}>
<CssBaseline /> <CssBaseline />
<AppRouter /> <AppRouter />
<GlobalSnackbar /> <GlobalSnackbar />

View File

@ -51,7 +51,7 @@ export const AdminDropdown: React.FC = () => {
<> <>
<div className={styles.link}> <div className={styles.link}>
<ListItem selected={Boolean(anchorEl)} button onClick={onOpenAdminMenu}> <ListItem selected={Boolean(anchorEl)} button onClick={onOpenAdminMenu}>
<ListItemText className="no-brace" color="primary" primary={Language.menuTitle} /> <ListItemText className="no-brace" primary={Language.menuTitle} />
{anchorEl ? <CloseDropdown /> : <OpenDropdown />} {anchorEl ? <CloseDropdown /> : <OpenDropdown />}
</ListItem> </ListItem>
</div> </div>

View File

@ -26,7 +26,7 @@ const useStyles = makeStyles((theme) => ({
root: { root: {
minHeight: 156, minHeight: 156,
background: theme.palette.background.default, background: theme.palette.background.default,
color: theme.palette.codeBlock.contrastText, color: theme.palette.text.primary,
fontFamily: MONOSPACE_FONT_FAMILY, fontFamily: MONOSPACE_FONT_FAMILY,
fontSize: 13, fontSize: 13,
wordBreak: "break-all", wordBreak: "break-all",

View File

@ -28,7 +28,7 @@ const useStyles = makeStyles((theme) => ({
justifyContent: "space-between", justifyContent: "space-between",
alignItems: "center", alignItems: "center",
background: theme.palette.background.default, background: theme.palette.background.default,
color: theme.palette.codeBlock.contrastText, color: theme.palette.primary.contrastText,
fontFamily: MONOSPACE_FONT_FAMILY, fontFamily: MONOSPACE_FONT_FAMILY,
fontSize: 13, fontSize: 13,
padding: theme.spacing(2), padding: theme.spacing(2),

View File

@ -1,16 +1,15 @@
import ThemeProvider from "@material-ui/styles/ThemeProvider"
import { fireEvent, render } from "@testing-library/react" import { fireEvent, render } from "@testing-library/react"
import React from "react" import React from "react"
import { act } from "react-dom/test-utils" import { act } from "react-dom/test-utils"
import { light } from "../../theme" import { WrapperComponent } from "../../testHelpers/renderHelpers"
import { ConfirmDialog, ConfirmDialogProps } from "./ConfirmDialog" import { ConfirmDialog, ConfirmDialogProps } from "./ConfirmDialog"
namespace Helpers { namespace Helpers {
export const Component: React.FC<ConfirmDialogProps> = (props: ConfirmDialogProps) => { export const Component: React.FC<ConfirmDialogProps> = (props: ConfirmDialogProps) => {
return ( return (
<ThemeProvider theme={light}> <WrapperComponent>
<ConfirmDialog {...props} /> <ConfirmDialog {...props} />
</ThemeProvider> </WrapperComponent>
) )
} }
} }

View File

@ -48,14 +48,11 @@ interface StyleProps {
const useStyles = makeStyles((theme) => ({ const useStyles = makeStyles((theme) => ({
dialogWrapper: (props: StyleProps) => ({ dialogWrapper: (props: StyleProps) => ({
"& .MuiPaper-root": { "& .MuiPaper-root": {
background: background: props.type === "info" ? theme.palette.primary.main : theme.palette.error.dark,
props.type === "info"
? theme.palette.confirmDialog.info.background
: theme.palette.confirmDialog.error.background,
}, },
}), }),
dialogContent: (props: StyleProps) => ({ dialogContent: (props: StyleProps) => ({
color: props.type === "info" ? theme.palette.confirmDialog.info.text : theme.palette.confirmDialog.error.text, color: props.type === "info" ? theme.palette.primary.contrastText : theme.palette.error.contrastText,
padding: theme.spacing(6), padding: theme.spacing(6),
textAlign: "center", textAlign: "center",
}), }),
@ -65,15 +62,15 @@ const useStyles = makeStyles((theme) => ({
description: (props: StyleProps) => ({ description: (props: StyleProps) => ({
color: color:
props.type === "info" props.type === "info"
? fade(theme.palette.confirmDialog.info.text, 0.75) ? fade(theme.palette.primary.contrastText, 0.75)
: fade(theme.palette.confirmDialog.error.text, 0.75), : fade(theme.palette.error.contrastText, 0.75),
lineHeight: "160%", lineHeight: "160%",
"& strong": { "& strong": {
color: color:
props.type === "info" props.type === "info"
? fade(theme.palette.confirmDialog.info.text, 0.95) ? fade(theme.palette.primary.contrastText, 0.95)
: fade(theme.palette.confirmDialog.error.text, 0.95), : fade(theme.palette.error.contrastText, 0.95),
}, },
}), }),
})) }))

View File

@ -52,13 +52,13 @@ const useStyles = makeStyles((theme) => ({
}, },
copyButton: { copyButton: {
borderRadius: 7, borderRadius: 7,
background: theme.palette.codeBlock.button.main, background: theme.palette.background.default,
color: theme.palette.codeBlock.button.contrastText, color: theme.palette.primary.contrastText,
padding: theme.spacing(0.85), padding: theme.spacing(0.85),
minWidth: 32, minWidth: 32,
"&:hover": { "&:hover": {
background: theme.palette.codeBlock.button.hover, background: theme.palette.background.paper,
}, },
}, },
fileCopyIcon: { fileCopyIcon: {

View File

@ -161,7 +161,7 @@ const useButtonStyles = makeStyles((theme) => ({
}, },
}, },
confirmDialogCancelButton: (props: StyleProps) => { confirmDialogCancelButton: (props: StyleProps) => {
const color = props.type === "info" ? theme.palette.confirmDialog.info.text : theme.palette.confirmDialog.error.text const color = props.type === "info" ? theme.palette.primary.contrastText : theme.palette.error.contrastText
return { return {
background: fade(color, 0.15), background: fade(color, 0.15),
color, color,

View File

@ -68,7 +68,7 @@ const useStyles = makeStyles((theme) => ({
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
height: 126, height: 126,
background: theme.palette.hero.main, background: theme.palette.background.default,
boxShadow: theme.shadows[3], boxShadow: theme.shadows[3],
}, },
topInner: { topInner: {

View File

@ -1,5 +1,5 @@
import Button from "@material-ui/core/Button" import Button from "@material-ui/core/Button"
import { lighten, makeStyles } from "@material-ui/core/styles" import { makeStyles } from "@material-ui/core/styles"
import React from "react" import React from "react"
export interface HeaderButtonProps { export interface HeaderButtonProps {
@ -28,10 +28,8 @@ export const HeaderButton: React.FC<HeaderButtonProps> = (props) => {
) )
} }
const useStyles = makeStyles((theme) => ({ const useStyles = makeStyles(() => ({
pageButton: { pageButton: {
whiteSpace: "nowrap", whiteSpace: "nowrap",
backgroundColor: lighten(theme.palette.hero.main, 0.1),
color: "#B5BFD2",
}, },
})) }))

View File

@ -9,7 +9,7 @@ export default {
const Template: Story = (args) => ( const Template: Story = (args) => (
<Margins {...args}> <Margins {...args}>
<div style={{ width: "100%", background: "lightgrey" }}>Here is some content that will not get too wide!</div> <div style={{ width: "100%", background: "black" }}>Here is some content that will not get too wide!</div>
</Margins> </Margins>
) )

View File

@ -8,14 +8,11 @@ const useStyles = makeStyles(() => ({
maxWidth, maxWidth,
padding: `0 ${sidePadding}`, padding: `0 ${sidePadding}`,
flex: 1, flex: 1,
width: "100%",
}, },
})) }))
export const Margins: React.FC = ({ children }) => { export const Margins: React.FC = ({ children }) => {
const styles = useStyles() const styles = useStyles()
return ( return <div className={styles.margins}>{children}</div>
<div>
<div className={styles.margins}>{children}</div>
</div>
)
} }

View File

@ -21,13 +21,13 @@ export const NavbarView: React.FC<NavbarViewProps> = ({ user, onSignOut, display
<nav className={styles.root}> <nav className={styles.root}>
<List className={styles.fixed}> <List className={styles.fixed}>
<ListItem className={styles.item}> <ListItem className={styles.item}>
<NavLink className={styles.logo} to="/"> <NavLink className={styles.logo} to="/workspaces">
<Logo fill="white" opacity={1} width={125} /> <Logo fill="white" opacity={1} width={125} />
</NavLink> </NavLink>
</ListItem> </ListItem>
<ListItem button className={styles.item}> <ListItem button className={styles.item}>
<NavLink className={styles.link} to="/templates"> <NavLink className={styles.link} to="/workspaces">
Templates Workspaces
</NavLink> </NavLink>
</ListItem> </ListItem>
</List> </List>
@ -47,13 +47,13 @@ const useStyles = makeStyles((theme) => ({
justifyContent: "center", justifyContent: "center",
alignItems: "center", alignItems: "center",
height: navHeight, height: navHeight,
background: theme.palette.navbar.main, background: theme.palette.background.paper,
marginTop: 0, marginTop: 0,
transition: "margin 150ms ease", transition: "margin 150ms ease",
"@media (display-mode: standalone)": { "@media (display-mode: standalone)": {
borderTop: `1px solid ${theme.palette.divider}`, borderTop: `1px solid ${theme.palette.divider}`,
}, },
borderBottom: `1px solid #383838`, borderBottom: `1px solid ${theme.palette.divider}`,
}, },
fixed: { fixed: {
flex: 0, flex: 0,
@ -68,9 +68,9 @@ const useStyles = makeStyles((theme) => ({
display: "flex", display: "flex",
height: navHeight, height: navHeight,
paddingLeft: theme.spacing(4), paddingLeft: theme.spacing(4),
paddingRight: theme.spacing(2), paddingRight: theme.spacing(4),
"& svg": { "& svg": {
width: 125, width: 109,
}, },
}, },
title: { title: {
@ -98,18 +98,17 @@ const useStyles = makeStyles((theme) => ({
"&.active": { "&.active": {
position: "relative", position: "relative",
color: theme.palette.primary.contrastText, color: theme.palette.primary.contrastText,
fontWeight: "bold",
"&::before": { "&::before": {
content: `"{"`, content: `" "`,
left: 10, bottom: 0,
left: theme.spacing(3),
background: "#C16800",
right: theme.spacing(3),
height: 2,
position: "absolute", position: "absolute",
}, },
"&::after": {
content: `"}"`,
position: "absolute",
right: 10,
},
}, },
}, },
})) }))

View File

@ -72,7 +72,7 @@ export const AccountForm: React.FC<AccountFormProps> = ({
{error && <FormHelperText error>{error}</FormHelperText>} {error && <FormHelperText error>{error}</FormHelperText>}
<div> <div>
<LoadingButton color="primary" loading={isLoading} type="submit" variant="contained"> <LoadingButton loading={isLoading} type="submit" variant="contained">
{isLoading ? "" : Language.updateSettings} {isLoading ? "" : Language.updateSettings}
</LoadingButton> </LoadingButton>
</div> </div>

View File

@ -113,7 +113,7 @@ export const SignInForm: React.FC<SignInFormProps> = ({
{authErrorMessage && <FormHelperText error>{Language.authErrorMessage}</FormHelperText>} {authErrorMessage && <FormHelperText error>{Language.authErrorMessage}</FormHelperText>}
{methodsErrorMessage && <FormHelperText error>{Language.methodsErrorMessage}</FormHelperText>} {methodsErrorMessage && <FormHelperText error>{Language.methodsErrorMessage}</FormHelperText>}
<div className={styles.submitBtn}> <div className={styles.submitBtn}>
<LoadingButton color="primary" loading={isLoading} fullWidth type="submit" variant="contained"> <LoadingButton loading={isLoading} fullWidth type="submit" variant="contained">
{isLoading ? "" : Language.passwordSignIn} {isLoading ? "" : Language.passwordSignIn}
</LoadingButton> </LoadingButton>
</div> </div>
@ -121,7 +121,7 @@ export const SignInForm: React.FC<SignInFormProps> = ({
{authMethods?.github && ( {authMethods?.github && (
<div className={styles.submitBtn}> <div className={styles.submitBtn}>
<Link href={`/api/v2/users/oauth2/github/callback?redirect=${encodeURIComponent(redirectTo)}`}> <Link href={`/api/v2/users/oauth2/github/callback?redirect=${encodeURIComponent(redirectTo)}`}>
<Button color="primary" disabled={isLoading} fullWidth type="submit" variant="contained"> <Button disabled={isLoading} fullWidth type="submit" variant="contained">
{Language.githubSignIn} {Language.githubSignIn}
</Button> </Button>
</Link> </Link>

View File

@ -1,29 +0,0 @@
import { ComponentMeta, Story } from "@storybook/react"
import React from "react"
import { MockOrganization, MockTemplate } from "../../testHelpers/entities"
import { TemplatesTable, TemplatesTableProps } from "./TemplatesTable"
export default {
title: "components/TemplatesTable",
component: TemplatesTable,
} as ComponentMeta<typeof TemplatesTable>
const Template: Story<TemplatesTableProps> = (args) => <TemplatesTable {...args} />
export const Example = Template.bind({})
Example.args = {
templates: [MockTemplate],
organizations: [MockOrganization],
}
export const Empty = Template.bind({})
Empty.args = {
templates: [],
organizations: [],
}
export const Loading = Template.bind({})
Loading.args = {
templates: undefined,
organizations: [],
}

View File

@ -1,81 +0,0 @@
import Box from "@material-ui/core/Box"
import Table from "@material-ui/core/Table"
import TableBody from "@material-ui/core/TableBody"
import TableCell from "@material-ui/core/TableCell"
import TableHead from "@material-ui/core/TableHead"
import TableRow from "@material-ui/core/TableRow"
import React from "react"
import { Link } from "react-router-dom"
import * as TypesGen from "../../api/typesGenerated"
import { CodeExample } from "../../components/CodeExample/CodeExample"
import { EmptyState } from "../../components/EmptyState/EmptyState"
import { TableHeaderRow } from "../../components/TableHeaders/TableHeaders"
import { TableLoader } from "../../components/TableLoader/TableLoader"
import { TableTitle } from "../../components/TableTitle/TableTitle"
export const Language = {
title: "Templates",
tableTitle: "All templates",
nameLabel: "Name",
emptyMessage: "No templates have been created yet",
emptyDescription: "Run the following command to get started:",
totalLabel: "total",
}
export interface TemplatesTableProps {
templates?: TypesGen.Template[]
organizations?: TypesGen.Organization[]
}
export const TemplatesTable: React.FC<TemplatesTableProps> = ({ templates, organizations }) => {
const isLoading = !templates || !organizations
// Create a dictionary of organization ID -> organization Name
// Needed to properly construct links to dive into a template
const orgDictionary =
organizations &&
organizations.reduce((acc: Record<string, string>, curr: TypesGen.Organization) => {
return {
...acc,
[curr.id]: curr.name,
}
}, {})
return (
<Table>
<TableHead>
<TableTitle title={Language.tableTitle} />
<TableHeaderRow>
<TableCell size="small">{Language.nameLabel}</TableCell>
</TableHeaderRow>
</TableHead>
<TableBody>
{isLoading && <TableLoader />}
{templates &&
organizations &&
orgDictionary &&
templates.map((t) => (
<TableRow key={t.id}>
<TableCell>
<Link to={`/templates/${orgDictionary[t.organization_id]}/${t.name}`}>{t.name}</Link>
</TableCell>
</TableRow>
))}
{templates && templates.length === 0 && (
<TableRow>
<TableCell colSpan={999}>
<Box p={4}>
<EmptyState
message={Language.emptyMessage}
description={Language.emptyDescription}
cta={<CodeExample code="coder templates init" />}
/>
</Box>
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
)
}

View File

@ -1,5 +1,7 @@
import Avatar from "@material-ui/core/Avatar" import Avatar from "@material-ui/core/Avatar"
import { makeStyles } from "@material-ui/core/styles"
import React from "react" import React from "react"
import { combineClasses } from "../../util/combineClasses"
import { firstLetter } from "../../util/firstLetter" import { firstLetter } from "../../util/firstLetter"
export interface UserAvatarProps { export interface UserAvatarProps {
@ -8,5 +10,17 @@ export interface UserAvatarProps {
} }
export const UserAvatar: React.FC<UserAvatarProps> = ({ username, className }) => { export const UserAvatar: React.FC<UserAvatarProps> = ({ username, className }) => {
return <Avatar className={className}>{firstLetter(username)}</Avatar> const styles = useStyles()
return (
<Avatar variant="square" className={combineClasses([styles.avatar, className])}>
{firstLetter(username)}
</Avatar>
)
} }
const useStyles = makeStyles((theme) => ({
avatar: {
borderRadius: 2,
border: `1px solid ${theme.palette.divider}`,
},
}))

View File

@ -1,7 +1,7 @@
import { action } from "@storybook/addon-actions" import { action } from "@storybook/addon-actions"
import { Story } from "@storybook/react" import { Story } from "@storybook/react"
import React from "react" import React from "react"
import { MockOrganization, MockOutdatedWorkspace, MockTemplate, MockWorkspace } from "../../testHelpers/renderHelpers" import { MockOutdatedWorkspace, MockWorkspace } from "../../testHelpers/renderHelpers"
import { Workspace, WorkspaceProps } from "./Workspace" import { Workspace, WorkspaceProps } from "./Workspace"
export default { export default {
@ -14,8 +14,6 @@ const Template: Story<WorkspaceProps> = (args) => <Workspace {...args} />
export const Started = Template.bind({}) export const Started = Template.bind({})
Started.args = { Started.args = {
organization: MockOrganization,
template: MockTemplate,
workspace: MockWorkspace, workspace: MockWorkspace,
handleStart: action("start"), handleStart: action("start"),
handleStop: action("stop"), handleStop: action("stop"),

View File

@ -2,7 +2,7 @@ import { makeStyles } from "@material-ui/core/styles"
import Typography from "@material-ui/core/Typography" import Typography from "@material-ui/core/Typography"
import React from "react" import React from "react"
import * as TypesGen from "../../api/typesGenerated" import * as TypesGen from "../../api/typesGenerated"
import { WorkspaceStatus } from "../../pages/WorkspacePage/WorkspacePage" import { WorkspaceStatus } from "../../util/workspace"
import { WorkspaceSchedule } from "../WorkspaceSchedule/WorkspaceSchedule" import { WorkspaceSchedule } from "../WorkspaceSchedule/WorkspaceSchedule"
import { WorkspaceSection } from "../WorkspaceSection/WorkspaceSection" import { WorkspaceSection } from "../WorkspaceSection/WorkspaceSection"
import { WorkspaceStatusBar } from "../WorkspaceStatusBar/WorkspaceStatusBar" import { WorkspaceStatusBar } from "../WorkspaceStatusBar/WorkspaceStatusBar"
@ -22,8 +22,6 @@ export interface WorkspaceProps {
* Workspace is the top-level component for viewing an individual workspace * Workspace is the top-level component for viewing an individual workspace
*/ */
export const Workspace: React.FC<WorkspaceProps> = ({ export const Workspace: React.FC<WorkspaceProps> = ({
organization,
template,
workspace, workspace,
handleStart, handleStart,
handleStop, handleStop,
@ -37,8 +35,6 @@ export const Workspace: React.FC<WorkspaceProps> = ({
<div className={styles.root}> <div className={styles.root}>
<div className={styles.vertical}> <div className={styles.vertical}>
<WorkspaceStatusBar <WorkspaceStatusBar
organization={organization}
template={template}
workspace={workspace} workspace={workspace}
handleStart={handleStart} handleStart={handleStart}
handleStop={handleStop} handleStop={handleStop}

View File

@ -5,9 +5,9 @@ import Typography from "@material-ui/core/Typography"
import React from "react" import React from "react"
import { Link } from "react-router-dom" import { Link } from "react-router-dom"
import * as TypesGen from "../../api/typesGenerated" import * as TypesGen from "../../api/typesGenerated"
import { WorkspaceStatus } from "../../pages/WorkspacePage/WorkspacePage"
import { TitleIconSize } from "../../theme/constants" import { TitleIconSize } from "../../theme/constants"
import { combineClasses } from "../../util/combineClasses" import { combineClasses } from "../../util/combineClasses"
import { WorkspaceStatus } from "../../util/workspace"
import { Stack } from "../Stack/Stack" import { Stack } from "../Stack/Stack"
import { WorkspaceSection } from "../WorkspaceSection/WorkspaceSection" import { WorkspaceSection } from "../WorkspaceSection/WorkspaceSection"
@ -21,6 +21,8 @@ export const Language = {
stopped: "Stopped", stopped: "Stopped",
starting: "Building", starting: "Building",
stopping: "Stopping", stopping: "Stopping",
canceled: "Canceled",
queued: "Queued",
error: "Build Failed", error: "Build Failed",
loading: "Loading Status", loading: "Loading Status",
deleting: "Deleting", deleting: "Deleting",
@ -46,14 +48,12 @@ export interface WorkspaceStatusBarProps {
* so check whether workspace job status has reached completion (whether successful or not). * so check whether workspace job status has reached completion (whether successful or not).
*/ */
const canAcceptJobs = (workspaceStatus: WorkspaceStatus) => const canAcceptJobs = (workspaceStatus: WorkspaceStatus) =>
["started", "stopped", "deleted", "error"].includes(workspaceStatus) ["started", "stopped", "deleted", "error", "canceled"].includes(workspaceStatus)
/** /**
* Component for the header at the top of the workspace page * Component for the header at the top of the workspace page
*/ */
export const WorkspaceStatusBar: React.FC<WorkspaceStatusBarProps> = ({ export const WorkspaceStatusBar: React.FC<WorkspaceStatusBarProps> = ({
organization,
template,
workspace, workspace,
handleStart, handleStart,
handleStop, handleStop,
@ -63,7 +63,6 @@ export const WorkspaceStatusBar: React.FC<WorkspaceStatusBarProps> = ({
}) => { }) => {
const styles = useStyles() const styles = useStyles()
const templateLink = `/templates/${organization?.name}/${template?.name}`
const settingsLink = "edit" const settingsLink = "edit"
return ( return (
@ -75,15 +74,6 @@ export const WorkspaceStatusBar: React.FC<WorkspaceStatusBarProps> = ({
{Language.settings} {Language.settings}
</Link> </Link>
</div> </div>
{organization && template && (
<Typography variant="body2" color="textSecondary">
Back to{" "}
<Link className={styles.link} to={templateLink}>
{template.name}
</Link>
</Typography>
)}
</div> </div>
<div className={styles.horizontal}> <div className={styles.horizontal}>

View File

@ -1,38 +0,0 @@
import { ComponentMeta, Story } from "@storybook/react"
import React from "react"
import { MockTemplate, MockWorkspace } from "../../testHelpers/entities"
import { WorkspacesTable, WorkspacesTableProps } from "./WorkspacesTable"
export default {
title: "components/WorkspacesTable",
component: WorkspacesTable,
} as ComponentMeta<typeof WorkspacesTable>
const Template: Story<WorkspacesTableProps> = (args) => <WorkspacesTable {...args} />
export const Example = Template.bind({})
Example.args = {
templateInfo: MockTemplate,
workspaces: [MockWorkspace],
onCreateWorkspace: () => {
console.info("Create workspace")
},
}
export const Empty = Template.bind({})
Empty.args = {
templateInfo: MockTemplate,
workspaces: [],
onCreateWorkspace: () => {
console.info("Create workspace")
},
}
export const Loading = Template.bind({})
Loading.args = {
templateInfo: MockTemplate,
workspaces: undefined,
onCreateWorkspace: () => {
console.info("Create workspace")
},
}

View File

@ -1,72 +0,0 @@
import Box from "@material-ui/core/Box"
import Button from "@material-ui/core/Button"
import Table from "@material-ui/core/Table"
import TableBody from "@material-ui/core/TableBody"
import TableCell from "@material-ui/core/TableCell"
import TableHead from "@material-ui/core/TableHead"
import TableRow from "@material-ui/core/TableRow"
import React from "react"
import { Link } from "react-router-dom"
import * as TypesGen from "../../api/typesGenerated"
import { EmptyState } from "../EmptyState/EmptyState"
import { TableHeaderRow } from "../TableHeaders/TableHeaders"
import { TableLoader } from "../TableLoader/TableLoader"
import { TableTitle } from "../TableTitle/TableTitle"
export const Language = {
title: "Workspaces",
nameLabel: "Name",
emptyMessage: "No workspaces have been created yet",
emptyDescription: "Create a workspace to get started",
ctaAction: "Create workspace",
}
export interface WorkspacesTableProps {
templateInfo?: TypesGen.Template
workspaces?: TypesGen.Workspace[]
onCreateWorkspace: () => void
}
export const WorkspacesTable: React.FC<WorkspacesTableProps> = ({ templateInfo, workspaces, onCreateWorkspace }) => {
const isLoading = !templateInfo || !workspaces
return (
<Table>
<TableHead>
<TableTitle title={Language.title} />
<TableHeaderRow>
<TableCell size="small">{Language.nameLabel}</TableCell>
</TableHeaderRow>
</TableHead>
<TableBody>
{isLoading && <TableLoader />}
{workspaces &&
workspaces.map((w) => (
<TableRow key={w.id}>
<TableCell>
<Link to={`/workspaces/${w.id}`}>{w.name}</Link>
</TableCell>
</TableRow>
))}
{workspaces && workspaces.length === 0 && (
<TableRow>
<TableCell colSpan={999}>
<Box p={4}>
<EmptyState
message={Language.emptyMessage}
description={Language.emptyDescription}
cta={
<Button variant="contained" color="primary" onClick={onCreateWorkspace}>
{Language.ctaAction}
</Button>
}
/>
</Box>
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
)
}

View File

@ -1,72 +0,0 @@
import { makeStyles } from "@material-ui/core/styles"
import { useSelector } from "@xstate/react"
import React, { useCallback, useContext } from "react"
import { useNavigate, useParams } from "react-router-dom"
import useSWR from "swr"
import * as API from "../../../../api/api"
import * as TypesGen from "../../../../api/typesGenerated"
import { ErrorSummary } from "../../../../components/ErrorSummary/ErrorSummary"
import { FullScreenLoader } from "../../../../components/Loader/FullScreenLoader"
import { CreateWorkspaceForm } from "../../../../forms/CreateWorkspaceForm"
import { unsafeSWRArgument } from "../../../../util"
import { selectOrgId } from "../../../../xServices/auth/authSelectors"
import { XServiceContext } from "../../../../xServices/StateContext"
export const CreateWorkspacePage: React.FC = () => {
const { organization: organizationName, template: templateName } = useParams()
const navigate = useNavigate()
const styles = useStyles()
const xServices = useContext(XServiceContext)
const myOrgId = useSelector(xServices.authXService, selectOrgId)
const { data: organizationInfo, error: organizationError } = useSWR<TypesGen.Organization, Error>(
() => `/api/v2/users/me/organizations/${organizationName}`,
)
const { data: template, error: templateError } = useSWR<TypesGen.Template, Error>(() => {
return `/api/v2/organizations/${unsafeSWRArgument(organizationInfo).id}/templates/${templateName}`
})
const onCancel = useCallback(async () => {
navigate(`/templates/${organizationName}/${templateName}`)
}, [navigate, organizationName, templateName])
const onSubmit = async (organizationId: string, req: TypesGen.CreateWorkspaceRequest) => {
const workspace = await API.Workspace.create(organizationId, req)
navigate(`/workspaces/${workspace.id}`)
return workspace
}
if (organizationError) {
return <ErrorSummary error={organizationError} />
}
if (templateError) {
return <ErrorSummary error={templateError} />
}
if (!template) {
return <FullScreenLoader />
}
if (!myOrgId) {
return <ErrorSummary error={Error("no organization id")} />
}
return (
<div className={styles.root}>
<CreateWorkspaceForm onCancel={onCancel} onSubmit={onSubmit} template={template} organizationId={myOrgId} />
</div>
)
}
const useStyles = makeStyles((theme) => ({
root: {
display: "flex",
flexDirection: "column",
alignItems: "center",
height: "100vh",
backgroundColor: theme.palette.background.paper,
},
}))

View File

@ -1,70 +0,0 @@
import React from "react"
import { useNavigate, useParams } from "react-router-dom"
import useSWR from "swr"
import * as TypesGen from "../../../../api/typesGenerated"
import { ErrorSummary } from "../../../../components/ErrorSummary/ErrorSummary"
import { Header } from "../../../../components/Header/Header"
import { Margins } from "../../../../components/Margins/Margins"
import { Stack } from "../../../../components/Stack/Stack"
import { WorkspacesTable } from "../../../../components/WorkspacesTable/WorkspacesTable"
import { unsafeSWRArgument } from "../../../../util"
import { firstOrItem } from "../../../../util/array"
export const Language = {
subtitle: "workspaces",
}
export const TemplatePage: React.FC = () => {
const navigate = useNavigate()
const { template: templateName, organization: organizationName } = useParams()
const { data: organizationInfo, error: organizationError } = useSWR<TypesGen.Organization, Error>(
() => `/api/v2/users/me/organizations/${organizationName}`,
)
const { data: templateInfo, error: templateError } = useSWR<TypesGen.Template, Error>(
() => `/api/v2/organizations/${unsafeSWRArgument(organizationInfo).id}/templates/${templateName}`,
)
// This just grabs all workspaces... and then later filters them to match the
// current template.
const { data: workspaces, error: workspacesError } = useSWR<TypesGen.Workspace[], Error>(
() => `/api/v2/organizations/${unsafeSWRArgument(organizationInfo).id}/workspaces`,
)
const hasError = organizationError || templateError || workspacesError
const createWorkspace = () => {
navigate(`/templates/${organizationName}/${templateName}/create`)
}
const perTemplateWorkspaces =
workspaces && templateInfo
? workspaces.filter((workspace) => {
return workspace.template_id === templateInfo.id
})
: undefined
return (
<Stack spacing={4}>
<Header
title={firstOrItem(templateName, "")}
description={firstOrItem(organizationName, "")}
subTitle={perTemplateWorkspaces ? `${perTemplateWorkspaces.length} ${Language.subtitle}` : ""}
action={{
text: "Create Workspace",
onClick: createWorkspace,
}}
/>
<Margins>
{organizationError && <ErrorSummary error={organizationError} />}
{templateError && <ErrorSummary error={templateError} />}
{workspacesError && <ErrorSummary error={workspacesError} />}
{!hasError && (
<WorkspacesTable templateInfo={templateInfo} workspaces={workspaces} onCreateWorkspace={createWorkspace} />
)}
</Margins>
</Stack>
)
}

View File

@ -1,37 +0,0 @@
import React from "react"
import useSWR from "swr"
import * as TypesGen from "../../api/typesGenerated"
import { ErrorSummary } from "../../components/ErrorSummary/ErrorSummary"
import { Header } from "../../components/Header/Header"
import { Margins } from "../../components/Margins/Margins"
import { Stack } from "../../components/Stack/Stack"
import { TemplatesTable } from "../../components/TemplatesTable/TemplatesTable"
export const Language = {
title: "Templates",
tableTitle: "All templates",
nameLabel: "Name",
emptyMessage: "No templates have been created yet",
emptyDescription: "Run the following command to get started:",
totalLabel: "total",
}
export const TemplatesPage: React.FC = () => {
const { data: orgs, error: orgsError } = useSWR<TypesGen.Organization[], Error>("/api/v2/users/me/organizations")
const { data: templates, error } = useSWR<TypesGen.Template[] | undefined, Error>(
orgs ? `/api/v2/organizations/${orgs[0].id}/templates` : undefined,
)
const subTitle = templates ? `${templates.length} ${Language.totalLabel}` : undefined
const hasError = orgsError || error
return (
<Stack spacing={4}>
<Header title={Language.title} subTitle={subTitle} />
<Margins>
{error && <ErrorSummary error={error} />}
{orgsError && <ErrorSummary error={orgsError} />}
{!hasError && <TemplatesTable organizations={orgs} templates={templates} />}
</Margins>
</Stack>
)
}

View File

@ -56,9 +56,7 @@ describe("Workspace Page", () => {
it("shows a workspace", async () => { it("shows a workspace", async () => {
renderWithAuth(<WorkspacePage />, { route: `/workspaces/${MockWorkspace.id}`, path: "/workspaces/:workspace" }) renderWithAuth(<WorkspacePage />, { route: `/workspaces/${MockWorkspace.id}`, path: "/workspaces/:workspace" })
const workspaceName = await screen.findByText(MockWorkspace.name) const workspaceName = await screen.findByText(MockWorkspace.name)
const templateName = await screen.findByText(MockTemplate.name)
expect(workspaceName).toBeDefined() expect(workspaceName).toBeDefined()
expect(templateName).toBeDefined()
}) })
it("shows the status of the workspace", async () => { it("shows the status of the workspace", async () => {
renderWithAuth(<WorkspacePage />, { route: `/workspaces/${MockWorkspace.id}`, path: "/workspaces/:workspace" }) renderWithAuth(<WorkspacePage />, { route: `/workspaces/${MockWorkspace.id}`, path: "/workspaces/:workspace" })

View File

@ -7,19 +7,8 @@ import { Margins } from "../../components/Margins/Margins"
import { Stack } from "../../components/Stack/Stack" import { Stack } from "../../components/Stack/Stack"
import { Workspace } from "../../components/Workspace/Workspace" import { Workspace } from "../../components/Workspace/Workspace"
import { firstOrItem } from "../../util/array" import { firstOrItem } from "../../util/array"
import { getWorkspaceStatus } from "../../util/workspace"
import { XServiceContext } from "../../xServices/StateContext" import { XServiceContext } from "../../xServices/StateContext"
import { selectWorkspaceStatus } from "../../xServices/workspace/workspaceSelectors"
export type WorkspaceStatus =
| "started"
| "starting"
| "stopped"
| "stopping"
| "error"
| "loading"
| "deleting"
| "deleted"
| "canceling"
export const WorkspacePage: React.FC = () => { export const WorkspacePage: React.FC = () => {
const { workspace: workspaceQueryParam } = useParams() const { workspace: workspaceQueryParam } = useParams()
@ -27,9 +16,10 @@ export const WorkspacePage: React.FC = () => {
const xServices = useContext(XServiceContext) const xServices = useContext(XServiceContext)
const [workspaceState, workspaceSend] = useActor(xServices.workspaceXService) const [workspaceState, workspaceSend] = useActor(xServices.workspaceXService)
const { workspace, template, organization, getWorkspaceError, getTemplateError, getOrganizationError } = const { workspace, getWorkspaceError, getTemplateError, getOrganizationError } = workspaceState.context
workspaceState.context const workspaceStatus = useSelector(xServices.workspaceXService, (state) => {
const workspaceStatus = useSelector(xServices.workspaceXService, selectWorkspaceStatus) return getWorkspaceStatus(state.context.workspace?.latest_build)
})
/** /**
* Get workspace, template, and organization on mount and whenever workspaceId changes. * Get workspace, template, and organization on mount and whenever workspaceId changes.
@ -48,8 +38,6 @@ export const WorkspacePage: React.FC = () => {
<Margins> <Margins>
<Stack spacing={4}> <Stack spacing={4}>
<Workspace <Workspace
organization={organization}
template={template}
workspace={workspace} workspace={workspace}
handleStart={() => workspaceSend("START")} handleStart={() => workspaceSend("START")}
handleStop={() => workspaceSend("STOP")} handleStop={() => workspaceSend("STOP")}

View File

@ -0,0 +1,37 @@
import { screen } from "@testing-library/react"
import { rest } from "msw"
import React from "react"
import { MockWorkspace } from "../../testHelpers/entities"
import { history, render } from "../../testHelpers/renderHelpers"
import { server } from "../../testHelpers/server"
import WorkspacesPage from "./WorkspacesPage"
import { Language } from "./WorkspacesPageView"
describe("WorkspacesPage", () => {
beforeEach(() => {
history.replace("/workspaces")
})
it("renders an empty workspaces page", async () => {
// Given
server.use(
rest.get("/api/v2/users/me/workspaces", async (req, res, ctx) => {
return res(ctx.status(200), ctx.json([]))
}),
)
// When
render(<WorkspacesPage />)
// Then
await screen.findByText(Language.emptyView)
})
it("renders a filled workspaces page", async () => {
// When
render(<WorkspacesPage />)
// Then
await screen.findByText(MockWorkspace.name)
})
})

View File

@ -0,0 +1,20 @@
import { useMachine } from "@xstate/react"
import React from "react"
import { workspacesMachine } from "../../xServices/workspaces/workspacesXService"
import { WorkspacesPageView } from "./WorkspacesPageView"
const WorkspacesPage: React.FC = () => {
const [workspacesState] = useMachine(workspacesMachine)
return (
<>
<WorkspacesPageView
loading={workspacesState.hasTag("loading")}
workspaces={workspacesState.context.workspaces}
error={workspacesState.context.getWorkspacesError}
/>
</>
)
}
export default WorkspacesPage

View File

@ -0,0 +1,50 @@
import { ComponentMeta, Story } from "@storybook/react"
import React from "react"
import { ProvisionerJobStatus, Workspace } from "../../api/typesGenerated"
import { MockWorkspace } from "../../testHelpers/entities"
import { WorkspacesPageView, WorkspacesPageViewProps } from "./WorkspacesPageView"
export default {
title: "pages/WorkspacesPageView",
component: WorkspacesPageView,
} as ComponentMeta<typeof WorkspacesPageView>
const Template: Story<WorkspacesPageViewProps> = (args) => <WorkspacesPageView {...args} />
const createWorkspaceWithStatus = (status: ProvisionerJobStatus, transition = "start"): Workspace => {
return {
...MockWorkspace,
latest_build: {
...MockWorkspace.latest_build,
transition,
job: {
...MockWorkspace.latest_build.job,
status: status,
},
},
}
}
// This is type restricted to prevent future statuses from slipping
// through the cracks unchecked!
const workspaces: { [key in ProvisionerJobStatus]: Workspace } = {
canceled: createWorkspaceWithStatus("canceled"),
canceling: createWorkspaceWithStatus("canceling"),
failed: createWorkspaceWithStatus("failed"),
pending: createWorkspaceWithStatus("pending"),
running: createWorkspaceWithStatus("running"),
succeeded: createWorkspaceWithStatus("succeeded"),
}
export const AllStates = Template.bind({})
AllStates.args = {
workspaces: [
...Object.values(workspaces),
createWorkspaceWithStatus("running", "stop"),
createWorkspaceWithStatus("succeeded", "stop"),
createWorkspaceWithStatus("running", "delete"),
],
}
export const Empty = Template.bind({})
Empty.args = {}

View File

@ -0,0 +1,234 @@
import Avatar from "@material-ui/core/Avatar"
import Button from "@material-ui/core/Button"
import Link from "@material-ui/core/Link"
import { makeStyles, Theme } from "@material-ui/core/styles"
import Table from "@material-ui/core/Table"
import TableBody from "@material-ui/core/TableBody"
import TableCell from "@material-ui/core/TableCell"
import TableHead from "@material-ui/core/TableHead"
import TableRow from "@material-ui/core/TableRow"
import AddCircleOutline from "@material-ui/icons/AddCircleOutline"
import useTheme from "@material-ui/styles/useTheme"
import dayjs from "dayjs"
import relativeTime from "dayjs/plugin/relativeTime"
import React from "react"
import { Link as RouterLink } from "react-router-dom"
import * as TypesGen from "../../api/typesGenerated"
import { WorkspaceBuild } from "../../api/typesGenerated"
import { Margins } from "../../components/Margins/Margins"
import { Stack } from "../../components/Stack/Stack"
import { firstLetter } from "../../util/firstLetter"
import { getWorkspaceStatus } from "../../util/workspace"
dayjs.extend(relativeTime)
export const Language = {
createButton: "Create Workspace",
emptyView: "so you can check out your repositories, edit your source code, and build and test your software.",
}
export interface WorkspacesPageViewProps {
loading?: boolean
workspaces?: TypesGen.Workspace[]
error?: unknown
}
export const WorkspacesPageView: React.FC<WorkspacesPageViewProps> = (props) => {
const styles = useStyles()
const theme: Theme = useTheme()
return (
<Stack spacing={4}>
<Margins>
<div className={styles.actions}>
<Button startIcon={<AddCircleOutline />}>{Language.createButton}</Button>
</div>
<Table>
<TableHead>
<TableRow>
<TableCell>Name</TableCell>
<TableCell>Template</TableCell>
<TableCell>Version</TableCell>
<TableCell>Last Built</TableCell>
<TableCell>Status</TableCell>
</TableRow>
</TableHead>
<TableBody>
{!props.loading && !props.workspaces?.length && (
<TableRow>
<TableCell colSpan={999}>
<div className={styles.welcome}>
<span>
<Link component={RouterLink} to="/workspaces/new">
Create a workspace
</Link>
&nbsp;{Language.emptyView}
</span>
</div>
</TableCell>
</TableRow>
)}
{props.workspaces?.map((workspace) => {
const status = getStatus(theme, workspace.latest_build)
return (
<TableRow key={workspace.id} className={styles.workspaceRow}>
<TableCell>
<div className={styles.workspaceName}>
<Avatar variant="square" className={styles.workspaceAvatar}>
{firstLetter(workspace.name)}
</Avatar>
<Link component={RouterLink} to={`/workspaces/${workspace.id}`} className={styles.workspaceLink}>
<b>{workspace.name}</b>
<span>{workspace.owner_name}</span>
</Link>
</div>
</TableCell>
<TableCell>{workspace.template_name}</TableCell>
<TableCell>
{workspace.outdated ? (
<span style={{ color: theme.palette.error.main }}>outdated</span>
) : (
<span style={{ color: theme.palette.text.secondary }}>up to date</span>
)}
</TableCell>
<TableCell>
<span style={{ color: theme.palette.text.secondary }}>
{dayjs().to(dayjs(workspace.latest_build.created_at))}
</span>
</TableCell>
<TableCell>
<span style={{ color: status.color }}>{status.status}</span>
</TableCell>
</TableRow>
)
})}
</TableBody>
</Table>
</Margins>
</Stack>
)
}
const getStatus = (
theme: Theme,
build: WorkspaceBuild,
): {
color: string
status: string
} => {
const status = getWorkspaceStatus(build)
switch (status) {
case undefined:
return {
color: theme.palette.text.secondary,
status: "Loading...",
}
case "started":
return {
color: theme.palette.success.main,
status: "⦿ Running",
}
case "starting":
return {
color: theme.palette.success.main,
status: "⦿ Starting",
}
case "stopping":
return {
color: theme.palette.text.secondary,
status: "◍ Stopping",
}
case "stopped":
return {
color: theme.palette.text.secondary,
status: "◍ Stopped",
}
case "deleting":
return {
color: theme.palette.text.secondary,
status: "⦸ Deleting",
}
case "deleted":
return {
color: theme.palette.text.secondary,
status: "⦸ Deleted",
}
case "canceling":
return {
color: theme.palette.warning.light,
status: "◍ Canceling",
}
case "canceled":
return {
color: theme.palette.text.secondary,
status: "◍ Canceled",
}
case "error":
return {
color: theme.palette.error.main,
status: "ⓧ Failed",
}
case "queued":
return {
color: theme.palette.text.secondary,
status: "◍ Queued",
}
}
throw new Error("unknown status " + status)
}
const useStyles = makeStyles((theme) => ({
actions: {
marginTop: theme.spacing(3),
marginBottom: theme.spacing(3),
display: "flex",
height: theme.spacing(6),
"& button": {
marginLeft: "auto",
},
},
welcome: {
paddingTop: theme.spacing(12),
paddingBottom: theme.spacing(12),
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
"& span": {
maxWidth: 600,
textAlign: "center",
fontSize: theme.spacing(2),
lineHeight: `${theme.spacing(3)}px`,
},
},
workspaceRow: {
"& > td": {
paddingTop: theme.spacing(2),
paddingBottom: theme.spacing(2),
},
},
workspaceAvatar: {
borderRadius: 2,
marginRight: theme.spacing(1),
width: 24,
height: 24,
fontSize: 16,
},
workspaceName: {
display: "flex",
alignItems: "center",
},
workspaceLink: {
display: "flex",
flexDirection: "column",
color: theme.palette.text.primary,
textDecoration: "none",
"&:hover": {
textDecoration: "underline",
},
"& span": {
fontSize: 12,
color: theme.palette.text.secondary,
},
},
}))

View File

@ -2,5 +2,5 @@ import React from "react"
import { Navigate } from "react-router-dom" import { Navigate } from "react-router-dom"
export const IndexPage: React.FC = () => { export const IndexPage: React.FC = () => {
return <Navigate to="/templates" replace /> return <Navigate to="/workspaces" replace />
} }

View File

@ -112,7 +112,7 @@ export const MockWorkspaceAutostopEnabled: TypesGen.UpdateWorkspaceAutostartRequ
export const MockWorkspaceBuild: TypesGen.WorkspaceBuild = { export const MockWorkspaceBuild: TypesGen.WorkspaceBuild = {
after_id: "", after_id: "",
before_id: "", before_id: "",
created_at: "", created_at: new Date().toDateString(),
id: "test-workspace-build", id: "test-workspace-build",
initiator_id: "", initiator_id: "",
job: MockProvisionerJob, job: MockProvisionerJob,

View File

@ -33,6 +33,9 @@ export const handlers = [
rest.post("/api/v2/users/me/workspaces", async (req, res, ctx) => { rest.post("/api/v2/users/me/workspaces", async (req, res, ctx) => {
return res(ctx.status(200), ctx.json(M.MockWorkspace)) return res(ctx.status(200), ctx.json(M.MockWorkspace))
}), }),
rest.get("/api/v2/users/me/workspaces", async (req, res, ctx) => {
return res(ctx.status(200), ctx.json([M.MockWorkspace]))
}),
rest.get("/api/v2/users/me/organizations", (req, res, ctx) => { rest.get("/api/v2/users/me/organizations", (req, res, ctx) => {
return res(ctx.status(200), ctx.json([M.MockOrganization])) return res(ctx.status(200), ctx.json([M.MockOrganization]))
}), }),

View File

@ -2,11 +2,11 @@ export const spacing = 8
export const borderRadius = 4 export const borderRadius = 4
export const buttonBorderWidth = 2 export const buttonBorderWidth = 2
export const MONOSPACE_FONT_FAMILY = export const MONOSPACE_FONT_FAMILY =
"'Fira Code', 'Lucida Console', 'Lucida Sans Typewriter', 'Liberation Mono', 'Monaco', 'Courier New', Courier, monospace" "'IBM Plex Mono', 'Lucida Console', 'Lucida Sans Typewriter', 'Liberation Mono', 'Monaco', 'Courier New', Courier, monospace"
export const BODY_FONT_FAMILY = `"Inter", sans-serif` export const BODY_FONT_FAMILY = `"Inter", sans-serif`
export const lightButtonShadow = "0 2px 2px rgba(0, 23, 121, 0.08)" export const lightButtonShadow = "0 2px 2px rgba(0, 23, 121, 0.08)"
export const emptyBoxShadow = "none" export const emptyBoxShadow = "none"
export const navHeight = 56 export const navHeight = 42
export const maxWidth = 1380 export const maxWidth = 1380
export const sidePadding = "50px" export const sidePadding = "50px"
export const TitleIconSize = 48 export const TitleIconSize = 48

View File

@ -1,6 +1,6 @@
// Monospace fonts used for code, button styles, and banners // Monospace fonts used for code, button styles, and banners
import "@fontsource/fira-code/400.css" import "@fontsource/ibm-plex-mono/400.css"
import "@fontsource/fira-code/600.css" import "@fontsource/ibm-plex-mono/600.css"
// Main body copy font // Main body copy font
import "@fontsource/inter/300.css" import "@fontsource/inter/300.css"
import "@fontsource/inter/400.css" import "@fontsource/inter/400.css"

View File

@ -1 +1 @@
export { dark, light } from "./theme" export { dark } from "./theme"

View File

@ -1,561 +1,84 @@
import { darken, fade } from "@material-ui/core/styles/colorManipulator" import { PaletteOptions, SimplePaletteColorOptions } from "@material-ui/core/styles/createPalette"
import { Breakpoints } from "@material-ui/core/styles/createBreakpoints" import { MONOSPACE_FONT_FAMILY } from "./constants"
import {
BODY_FONT_FAMILY,
borderRadius,
buttonBorderWidth,
emptyBoxShadow,
lightButtonShadow,
spacing,
} from "./constants"
import { CustomPalette } from "./palettes"
import { typography } from "./typography"
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export const getOverrides = (palette: CustomPalette, breakpoints: Breakpoints) => { export const getOverrides = (palette: PaletteOptions) => {
const containedButtonShadow = palette.type === "dark" ? emptyBoxShadow : lightButtonShadow
return { return {
MuiAvatar: { MuiAvatar: {
root: { root: {
width: 32, width: 32,
height: 32, height: 32,
fontSize: 24, fontSize: 24,
border: `1px solid ${palette.divider}`,
}, },
}, },
MuiTable: { MuiButton: {
root: { root: {
backgroundColor: palette.background.paper, // Prevents a loading button from collapsing!
borderRadius: borderRadius * 2, minHeight: 42,
boxShadow: `0 0 0 1px ${palette.action.hover}`, fontWeight: "regular",
fontFamily: MONOSPACE_FONT_FAMILY,
"&.is-inline": { fontSize: 16,
background: "none", textTransform: "none",
borderRadius: 0, letterSpacing: "none",
border: `1px solid ${palette.divider}`,
},
contained: {
boxShadow: "none", boxShadow: "none",
color: palette.text?.primary,
backgroundColor: "#151515",
"&:hover": {
boxShadow: "none",
backgroundColor: "#000000",
}, },
}, },
}, },
MuiTableHead: { MuiTableHead: {
root: { root: {
"& .MuiTableCell-root": { fontFamily: MONOSPACE_FONT_FAMILY,
...typography.overline, textTransform: "uppercase",
paddingTop: spacing,
paddingBottom: spacing,
color: palette.text.secondary,
backgroundColor: palette.background.default,
".MuiTable-root.is-inline &": {
background: "none",
}, },
}, },
"& .MuiTableRow-root:first-child .MuiTableCell-root:first-child": { MuiTable: {
borderTopLeftRadius: borderRadius * 2,
".MuiTable-root.is-inline &": {
borderRadius: 0,
},
},
"& .MuiTableRow-root:first-child .MuiTableCell-root:last-child": {
borderTopRightRadius: borderRadius * 2,
".MuiTable-root.is-inline &": {
borderRadius: 0,
},
},
},
},
MuiTableSortLabel: {
root: { root: {
lineHeight: "20px", // Gives the appearance of a border!
borderRadius: 2,
"&$active": { border: `1px solid ${palette.divider}`,
"&& $icon": {
color: palette.text.primary,
},
},
},
icon: {
"&.MuiSvgIcon-root": {
width: 18,
height: 18,
marginLeft: 2,
},
}, },
}, },
MuiTableCell: { MuiTableCell: {
head: {
color: palette.text?.secondary,
},
root: { root: {
"&:first-child": { fontFamily: MONOSPACE_FONT_FAMILY,
paddingLeft: spacing * 4,
},
},
},
MuiTablePagination: {
input: {
height: "auto",
marginTop: 0,
border: `1px solid ${palette.action.disabled}`,
},
select: {
paddingTop: 6,
fontSize: 14,
},
selectIcon: {
right: -4,
},
},
MuiList: {
root: {
boxSizing: "border-box",
"& .MuiDivider-root": {
opacity: 0.5,
},
},
},
MuiListItem: {
root: {
minHeight: 24,
position: "relative",
"&.active": {
color: "white",
},
},
gutters: {
padding: spacing / 2,
paddingLeft: spacing * 2,
paddingRight: spacing * 2,
},
},
MuiListItemAvatar: {
root: {
minWidth: 46,
},
},
MuiListItemIcon: {
root: {
minWidth: 36,
color: palette.text.primary,
"& .MuiSvgIcon-root": {
width: 20,
height: 20,
},
},
},
MuiListSubheader: {
root: {
...typography.overline,
lineHeight: 2.5,
},
sticky: {
backgroundColor: palette.background.paper,
},
},
MuiMenu: {
paper: {
marginTop: spacing,
},
},
MuiMenuItem: {
root: {
minHeight: 48,
fontSize: 16, fontSize: 16,
[breakpoints.up("sm")]: { background: palette.background?.paper,
minHeight: 48, borderBottom: `1px solid ${palette.divider}`,
padding: 8,
"&:first-child": {
paddingLeft: 32,
}, },
"&:last-child": {
paddingRight: 32,
}, },
gutters: {
padding: spacing,
paddingLeft: spacing * 2,
paddingRight: spacing * 2,
},
},
MuiListItemText: {
primary: {
fontWeight: 500,
},
secondary: {
fontSize: 12,
},
},
MuiOutlinedInput: {
root: {
fontSize: 14,
"&$focused $notchedOutline": {
borderWidth: 1,
},
},
notchedOutline: {
borderWidth: 1,
borderColor: palette.action.disabled,
},
},
MuiButton: {
root: {
minHeight: 40,
paddingLeft: 20,
paddingRight: 20,
fontWeight: 500,
"& .MuiSvgIcon-root": {
verticalAlign: "middle",
},
},
contained: {
backgroundColor: palette.hero.button,
color: palette.primary.contrastText,
boxShadow: containedButtonShadow,
"&:hover": {
backgroundColor: darken(palette.hero.button, 0.25),
},
"&$disabled": {
color: fade(palette.text.disabled, 0.5),
},
},
containedPrimary: {
boxShadow: containedButtonShadow,
},
containedSecondary: {
boxShadow: containedButtonShadow,
},
outlined: {
borderColor: palette.action.disabled,
borderWidth: buttonBorderWidth,
"&:hover": {
color: palette.primary.main,
borderColor: palette.primary.main,
borderWidth: buttonBorderWidth,
},
"&$disabled": {
color: fade(palette.text.disabled, 0.5),
},
},
outlinedPrimary: {
borderColor: palette.primary.main,
borderWidth: buttonBorderWidth,
"&:hover": {
borderWidth: buttonBorderWidth,
},
},
outlinedSecondary: {
borderColor: palette.secondary.main,
borderWidth: buttonBorderWidth,
"&:hover": {
color: palette.secondary.main,
borderWidth: buttonBorderWidth,
},
},
text: {
"&$disabled": {
color: fade(palette.text.disabled, 0.5),
},
},
sizeSmall: {
minHeight: 32,
paddingLeft: 10,
paddingRight: 10,
letterSpacing: 1.2,
fontSize: 13,
"&.MuiButton-outlined": {
borderWidth: 1,
},
},
sizeLarge: {
minHeight: 46,
paddingLeft: spacing * 3,
paddingRight: spacing * 3,
},
},
MuiButtonGroup: {
contained: {
boxShadow: containedButtonShadow,
},
},
MuiLink: {
root: {
fontWeight: 600,
}, },
}, },
MuiInputBase: { MuiInputBase: {
root: { root: {
minHeight: 40, borderRadius: 2,
background: palette.background.paper,
marginTop: "12px",
borderRadius,
"&$disabled": {
background: palette.action.disabledBackground,
},
"&$focused .MuiSelect-icon": {
color: palette.primary.light,
}, },
}, },
MuiOutlinedInput: {
input: {
fontSize: 16,
"&::placeholder": {
color: palette.text.secondary,
opacity: 1,
},
// See this thread https://stackoverflow.com/questions/69196525/how-to-change-the-color-of-the-calendar-icon-of-the-textfield-date-picker-in-ma
"&::-webkit-calendar-picker-indicator": {
filter:
palette.type === "dark"
? "invert(95%) sepia(0%) saturate(1082%) hue-rotate(173deg) brightness(84%) contrast(80%);"
: undefined,
},
},
},
MuiInputLabel: {
shrink: {
fontSize: 14,
marginTop: "2px",
left: "-12px",
transform: "translate(16px, -6px) scale(0.8)",
color: palette.text.primary,
},
outlined: {
letterSpacing: "0.2px",
lineHeight: "16px",
fontFamily: BODY_FONT_FAMILY,
"&$shrink": {
transform: "translate(14px, -13px)",
},
},
},
MuiChip: {
root: { root: {
fontSize: 16, "& input:-webkit-autofill": {
fontWeight: 500, WebkitBoxShadow: `0 0 0 1000px ${palette.background?.paper} inset`,
borderRadius: borderRadius,
backgroundColor: fade(palette.text.secondary, 0.1),
color: palette.text.secondary,
},
sizeSmall: {
height: 20,
},
labelSmall: {
fontSize: 12,
paddingLeft: 6,
paddingRight: 6,
},
colorPrimary: {
backgroundColor: fade(palette.primary.main, 0.1),
color: palette.primary.main,
},
colorSecondary: {
backgroundColor: fade(palette.secondary.main, 0.15),
color: palette.secondary.main,
}, },
}, },
MuiSelect: { },
MuiLink: {
root: { root: {
// Matches MuiInputBase-input height color: (palette.primary as SimplePaletteColorOptions).light,
lineHeight: "1.1875em",
overflow: "hidden",
},
select: {
"&:focus": {
borderRadius,
},
},
icon: {
"&.MuiSvgIcon-root": {
fontSize: 20,
margin: "3px 6px 0 0",
},
},
iconOutlined: {
right: 0,
},
iconOpen: {
transform: "none",
},
},
MuiDialog: {
paper: {
borderRadius: 11,
},
paperWidthSm: {
maxWidth: "530px",
},
},
MuiDialogTitle: {
root: {
color: palette.text.primary,
padding: `27px ${spacing * 6}px 0 ${spacing * 6}px`,
fontSize: 32,
fontWeight: 700,
display: "flex",
alignItems: "center",
justifyContent: "space-between",
background: palette.background.paper,
},
},
MuiDialogContent: {
root: {
padding: `0 ${spacing * 6}px ${spacing * 6}px ${spacing * 6}px`,
},
},
MuiDialogContentText: {
root: {
color: palette.action.active,
},
},
MuiDialogActions: {
root: {
padding: 0,
},
spacing: {
"& > :not(:first-child)": {
marginLeft: 0,
},
},
},
MuiFormHelperText: {
root: {
fontSize: 12,
lineHeight: "16px",
},
contained: {
marginTop: 6,
marginLeft: spacing * 0.5,
},
},
MuiBackdrop: {
root: {
backgroundColor: fade("#242424", 0.6),
},
},
MuiInputAdornment: {
root: {
"& .MuiSvgIcon-root": {
color: palette.text.secondary,
},
},
positionStart: {
marginRight: 12,
marginLeft: 6,
},
},
MuiCheckbox: {
root: {
"& .MuiSvgIcon-root": {
width: 16,
height: 16,
margin: 1,
},
},
colorPrimary: {
"&.MuiCheckbox-root": {
color: palette.primary.main,
"&$disabled": {
color: palette.action.disabled,
},
},
},
colorSecondary: {
"&.MuiCheckbox-root": {
color: palette.secondary.main,
"&$disabled": {
color: palette.action.disabled,
},
},
},
},
MuiRadio: {
root: {
"& .MuiSvgIcon-root": {
width: 18,
height: 18,
},
},
colorPrimary: {
"&.MuiRadio-root": {
color: palette.primary.main,
"&$disabled": {
color: palette.action.disabled,
},
},
},
colorSecondary: {
"&.MuiRadio-root": {
color: palette.secondary.main,
"&$disabled": {
color: palette.action.disabled,
},
},
},
},
MuiTabs: {
root: {
minHeight: 40,
},
indicator: {
height: 3,
},
},
MuiTab: {
root: {
minHeight: 70,
marginRight: spacing * 5,
textTransform: "none",
fontWeight: 400,
fontSize: 16,
letterSpacing: 3,
"&:last-child": {
marginRight: 0,
},
"&.MuiButtonBase-root": {
minWidth: 0,
padding: 0,
},
"&.Mui-selected .MuiTab-wrapper": {
color: palette.primary.contrastText,
fontWeight: "bold",
},
},
wrapper: {},
textColorPrimary: {
color: palette.text.secondary,
},
textColorSecondary: {
color: palette.text.secondary,
},
},
MuiStepper: {
root: {
background: "none",
},
},
// Labs components aren't typed properly, so cast overrides
MuiAutocomplete: {
endAdornment: {
"& .MuiSvgIcon-root": {
fontSize: 20,
},
},
inputRoot: {
'&[class*="MuiOutlinedInput-root"]': {
"& $endAdornment": {
right: 6,
},
},
}, },
}, },
} }

View File

@ -1,173 +1,8 @@
import { Palette } from "@material-ui/core/styles/createPalette" import { PaletteOptions } from "@material-ui/core/styles/createPalette"
/** /**
* Augment MUI Palette with Coder-specific design system * Augment MUI Palette with Coder-specific design system
*/ */
declare module "@material-ui/core/styles/createPalette" {
interface Palette {
codeBlock: {
// Text color for codeblocks
contrastText: string
// Background color for codeblocks
main: string
button: {
// Background for buttons inside a codeblock
main: string
// Hover background color for buttons inside a codeblock
hover: string
// Text color for buttons inside a codeblock
contrastText: string
}
}
confirmDialog: {
error: {
background: string
text: string
}
info: {
background: string
text: string
}
}
navbar: {
main: string
}
// Styles for the 'hero' banner on several coder admin pages
hero: {
// Background color of the 'hero' banner
main: string
// Color for hero 'buttons'
button: string
}
}
interface PaletteOptions {
codeBlock: {
contrastText: string
main: string
button: {
main: string
hover: string
contrastText: string
}
}
confirmDialog: {
error: {
background: string
text: string
}
info: {
background: string
text: string
}
}
navbar: {
main: string
}
hero: {
main: string
button: string
}
}
}
/**
* CustomPalette implements a minimal subset of MUI Palette interface for our
* light and dark themes.
*/
export type CustomPalette = Pick<
Palette,
| "action"
| "background"
| "codeBlock"
| "confirmDialog"
| "divider"
| "error"
| "hero"
| "info"
| "navbar"
| "primary"
| "secondary"
| "text"
| "type"
>
/**
* Light theme color palette, the default
*
* This maps to our design system at:
* https://www.figma.com/file/VkXU4873QOsSprMQV02GgR/Design-System?node-id=3%3A2
*/
export const lightPalette: CustomPalette = {
type: "light",
background: {
default: "#F3F3F3",
paper: "#FFF",
},
codeBlock: {
main: "#F3F3F3",
contrastText: "rgba(0, 0, 0, 0.9)",
button: {
main: "#E6ECE6",
hover: "#DAEBDA",
contrastText: "#000",
},
},
confirmDialog: {
error: {
background: "#912F42",
text: "#FFF",
},
info: {
background: "#000",
text: "#FFF",
},
},
primary: {
main: "#519A54",
light: "#A2E0A5",
dark: "#3A783D",
contrastText: "#FFF",
},
info: {
main: "#000",
light: "#000",
dark: "#000",
contrastText: "#FFF",
},
navbar: {
main: "#242424",
},
secondary: {
main: "#F7CD6F",
light: "#FFE7A0",
dark: "#BF9331",
contrastText: "#FFF",
},
error: {
main: "#DD4764",
light: "#A14E5E",
dark: "#912F42",
contrastText: "#FFF",
},
hero: {
main: "#242424",
button: "#747474",
},
text: {
primary: "#000",
secondary: "#747474",
disabled: "#749367",
hint: "#749367",
},
action: {
active: "#242424",
hover: "rgba(0, 0, 0, 0.1)",
hoverOpacity: 0.08,
selected: "#D0EFD2",
disabled: "#DDE2EC",
disabledBackground: "#F3F3F3",
},
divider: "#DDE2EC",
}
/** /**
* Dark theme color palette * Dark theme color palette
@ -175,52 +10,31 @@ export const lightPalette: CustomPalette = {
* This maps to our design system at: * This maps to our design system at:
* https://www.figma.com/file/VkXU4873QOsSprMQV02GgR/Design-System?node-id=219%3A40 * https://www.figma.com/file/VkXU4873QOsSprMQV02GgR/Design-System?node-id=219%3A40
*/ */
export const darkPalette: CustomPalette = { export const darkPalette: PaletteOptions = {
type: "dark", type: "dark",
primary: lightPalette.primary, primary: {
secondary: lightPalette.secondary, main: "#409BF4",
info: lightPalette.info, contrastText: "#f8f8f8",
error: lightPalette.error, light: "#79B8FF",
codeBlock: { dark: "#1976D2",
main: "rgb(24, 26, 27)",
contrastText: "rgba(255, 255, 255, 0.8)",
button: {
main: "rgba(255, 255, 255, 0.1)",
hover: "rgba(255, 255, 255, 0.25)",
contrastText: "#FFF",
}, },
}, secondary: {
confirmDialog: { main: "#008510",
error: lightPalette.confirmDialog.error, contrastText: "#f8f8f8",
info: {
background: "rgba(255, 255, 255, 0.95)",
text: "rgb(31, 33, 35)",
},
},
hero: {
main: "#141414",
button: "#333333",
},
navbar: {
main: "rgb(8, 9, 10)",
}, },
background: { background: {
default: "rgb(24, 26, 27)", default: "#1F1F1F",
paper: "rgb(31, 33, 35)", paper: "#292929",
}, },
text: { text: {
primary: "rgba(255, 255, 255, 0.95)", primary: "#F8F8F8",
secondary: "#BDBDBD", secondary: "#C1C1C1",
disabled: "#BDBDBD",
hint: "#BDBDBD",
}, },
action: { divider: "#383838",
active: "#FFF", warning: {
hover: "rgba(255, 255, 255, 0.1)", main: "#C16800",
hoverOpacity: 0.1, },
selected: "rgba(255, 255, 255, 0.2)", success: {
disabled: "rgba(255, 255, 255, 0.1)", main: "#6BBE00",
disabledBackground: "rgba(255, 255, 255, 0.12)",
}, },
divider: "rgba(255, 255, 255, 0.12)",
} }

View File

@ -4,34 +4,21 @@ import { ComponentsProps } from "@material-ui/core/styles/props"
* These are global overrides to MUI components and we may move away from using them in the future. * These are global overrides to MUI components and we may move away from using them in the future.
*/ */
export const props = { export const props = {
MuiButtonBase: {
disableRipple: true,
},
MuiButton: { MuiButton: {
variant: "contained", variant: "contained",
}, },
MuiTextField: { MuiTextField: {
margin: "dense", margin: "dense",
InputProps: {
labelWidth: 0,
},
variant: "outlined", variant: "outlined",
spellCheck: false, spellCheck: false,
}, },
MuiInputLabel: {
shrink: true,
},
MuiFormControl: { MuiFormControl: {
variant: "outlined", variant: "outlined",
margin: "dense", margin: "dense",
}, },
MuiInput: {
spellCheck: false,
autoCorrect: "off",
},
MuiOutlinedInput: {
notched: false,
},
MuiDialogTitle: {
disableTypography: true,
},
MuiMenu: { MuiMenu: {
anchorOrigin: { anchorOrigin: {
vertical: "bottom", vertical: "bottom",
@ -51,7 +38,4 @@ export const props = {
textColor: "primary", textColor: "primary",
indicatorColor: "primary", indicatorColor: "primary",
}, },
MuiTab: {
disableTouchRipple: true,
},
} as ComponentsProps } as ComponentsProps

View File

@ -1,15 +1,13 @@
import { createMuiTheme } from "@material-ui/core/styles" import { createMuiTheme } from "@material-ui/core/styles"
import { PaletteOptions } from "@material-ui/core/styles/createPalette"
import { Overrides } from "@material-ui/core/styles/overrides" import { Overrides } from "@material-ui/core/styles/overrides"
import { borderRadius } from "./constants" import { borderRadius } from "./constants"
import { getOverrides } from "./overrides" import { getOverrides } from "./overrides"
import { CustomPalette, darkPalette, lightPalette } from "./palettes" import { darkPalette } from "./palettes"
import { props } from "./props" import { props } from "./props"
import { typography } from "./typography" import { typography } from "./typography"
const makeTheme = (palette: CustomPalette) => { const makeTheme = (palette: PaletteOptions) => {
// Grab defaults to re-use in overrides
const { breakpoints } = createMuiTheme()
return createMuiTheme({ return createMuiTheme({
palette, palette,
typography, typography,
@ -17,9 +15,8 @@ const makeTheme = (palette: CustomPalette) => {
borderRadius, borderRadius,
}, },
props, props,
overrides: getOverrides(palette, breakpoints) as Overrides, overrides: getOverrides(palette) as Overrides,
}) })
} }
export const light = makeTheme(lightPalette)
export const dark = makeTheme(darkPalette) export const dark = makeTheme(darkPalette)

View File

@ -1,7 +1,18 @@
import { State } from "xstate" import { WorkspaceBuildTransition } from "../api/types"
import { WorkspaceBuildTransition } from "../../api/types" import { WorkspaceBuild } from "../api/typesGenerated"
import { WorkspaceStatus } from "../../pages/WorkspacePage/WorkspacePage"
import { WorkspaceContext, WorkspaceEvent } from "./workspaceXService" export type WorkspaceStatus =
| "queued"
| "started"
| "starting"
| "stopped"
| "stopping"
| "error"
| "loading"
| "deleting"
| "deleted"
| "canceled"
| "canceling"
const inProgressToStatus: Record<WorkspaceBuildTransition, WorkspaceStatus> = { const inProgressToStatus: Record<WorkspaceBuildTransition, WorkspaceStatus> = {
start: "starting", start: "starting",
@ -15,22 +26,23 @@ const succeededToStatus: Record<WorkspaceBuildTransition, WorkspaceStatus> = {
delete: "deleted", delete: "deleted",
} }
export const selectWorkspaceStatus = (state: State<WorkspaceContext, WorkspaceEvent>): WorkspaceStatus => { // Converts a workspaces status to a human-readable form.
const transition = state.context.workspace?.latest_build.transition as WorkspaceBuildTransition export const getWorkspaceStatus = (workspaceBuild?: WorkspaceBuild): WorkspaceStatus => {
const jobStatus = state.context.workspace?.latest_build.job.status const transition = workspaceBuild?.transition as WorkspaceBuildTransition
const jobStatus = workspaceBuild?.job.status
switch (jobStatus) { switch (jobStatus) {
case undefined: case undefined:
return "loading" return "loading"
case "succeeded": case "succeeded":
return succeededToStatus[transition] return succeededToStatus[transition]
case "pending": case "pending":
return inProgressToStatus[transition] return "queued"
case "running": case "running":
return inProgressToStatus[transition] return inProgressToStatus[transition]
case "canceling": case "canceling":
return "canceling" return "canceling"
case "canceled": case "canceled":
return "error" return "canceled"
case "failed": case "failed":
return "error" return "error"
} }

View File

@ -0,0 +1,61 @@
import { assign, createMachine } from "xstate"
import * as API from "../../api/api"
import * as TypesGen from "../../api/typesGenerated"
interface WorkspaceContext {
workspaces?: TypesGen.Workspace[]
getWorkspacesError?: Error | unknown
}
type WorkspaceEvent = { type: "GET_WORKSPACE"; workspaceId: string }
export const workspacesMachine = createMachine(
{
tsTypes: {} as import("./workspacesXService.typegen").Typegen0,
schema: {
context: {} as WorkspaceContext,
events: {} as WorkspaceEvent,
services: {} as {
getWorkspaces: {
data: TypesGen.Workspace[]
}
},
},
id: "workspaceState",
initial: "gettingWorkspaces",
states: {
gettingWorkspaces: {
entry: "clearGetWorkspacesError",
invoke: {
src: "getWorkspaces",
id: "getWorkspaces",
onDone: {
target: "done",
actions: ["assignWorkspaces", "clearGetWorkspacesError"],
},
onError: {
target: "error",
actions: "assignGetWorkspacesError",
},
},
tags: "loading",
},
done: {},
error: {},
},
},
{
actions: {
assignWorkspaces: assign({
workspaces: (_, event) => event.data,
}),
assignGetWorkspacesError: assign({
getWorkspacesError: (_, event) => event.data,
}),
clearGetWorkspacesError: (context) => assign({ ...context, getWorkspacesError: undefined }),
},
services: {
getWorkspaces: () => API.getWorkspaces(),
},
},
)

View File

@ -63,6 +63,7 @@ const config: Configuration = {
"/api": { "/api": {
target: "http://localhost:3000", target: "http://localhost:3000",
ws: true, ws: true,
secure: false,
}, },
}, },
static: ["./static"], static: ["./static"],

View File

@ -1269,10 +1269,10 @@
minimatch "^3.0.4" minimatch "^3.0.4"
strip-json-comments "^3.1.1" strip-json-comments "^3.1.1"
"@fontsource/fira-code@4.5.9": "@fontsource/ibm-plex-mono@4.5.9":
version "4.5.9" version "4.5.9"
resolved "https://registry.yarnpkg.com/@fontsource/fira-code/-/fira-code-4.5.9.tgz#8ca3e6020f9d3c340a643c5c0a12b2ebf37dc7a6" resolved "https://registry.yarnpkg.com/@fontsource/ibm-plex-mono/-/ibm-plex-mono-4.5.9.tgz#96968bebc4b1ea559818a9c52c87b3854a8145ba"
integrity sha512-moi9UVTOfQFXjiUAITy5W727dIP6c0K5TGPN+wTaFHn+/5flc/V0Uq9cKTs39yGrPUOneTbuAe8C8q7CzUP4Aw== integrity sha512-goblhmAX48GELIUQnWBg6AKVZklcTUu6NwF8tRiIzlxTZuOspbzHrW/3sF3WOH6+mJVay9n6QLbbikOfxSRekQ==
"@fontsource/inter@4.5.7": "@fontsource/inter@4.5.7":
version "4.5.7" version "4.5.7"
@ -1298,11 +1298,6 @@
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
"@icons/material@^0.2.4":
version "0.2.4"
resolved "https://registry.yarnpkg.com/@icons/material/-/material-0.2.4.tgz#e90c9f71768b3736e76d7dd6783fc6c2afa88bc8"
integrity sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==
"@istanbuljs/load-nyc-config@^1.0.0": "@istanbuljs/load-nyc-config@^1.0.0":
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced"
@ -1801,64 +1796,6 @@
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.2.tgz#830beaec4b4091a9e9398ac50f865ddea52186b9" resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.2.tgz#830beaec4b4091a9e9398ac50f865ddea52186b9"
integrity sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA== integrity sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA==
"@reach/component-component@^0.1.3":
version "0.1.3"
resolved "https://registry.yarnpkg.com/@reach/component-component/-/component-component-0.1.3.tgz#5d156319572dc38995b246f81878bc2577c517e5"
integrity sha512-a1USH7L3bEfDdPN4iNZGvMEFuBfkdG+QNybeyDv8RloVFgZYRoM+KGXyy2KOfEnTUM8QWDRSROwaL3+ts5Angg==
"@reach/observe-rect@^1.0.3":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@reach/observe-rect/-/observe-rect-1.2.0.tgz#d7a6013b8aafcc64c778a0ccb83355a11204d3b2"
integrity sha512-Ba7HmkFgfQxZqqaeIWWkNK0rEhpxVQHIoVyW1YDSkGsGIXzcaW4deC8B0pZrNSSyLTdIk7y+5olKt5+g0GmFIQ==
"@reach/rect@^0.2.1":
version "0.2.1"
resolved "https://registry.yarnpkg.com/@reach/rect/-/rect-0.2.1.tgz#7343020174c90e2290b844d17c03fd9c78e6b601"
integrity sha512-aZ9RsNHDMQ3zETonikqu9/85iXxj+LPqZ9Gr9UAncj3AufYmGeWG3XG6b37B+7ORH+mkhVpLU2ZlIWxmOe9Cqg==
dependencies:
"@reach/component-component" "^0.1.3"
"@reach/observe-rect" "^1.0.3"
"@react-theming/flatten@^0.1.1":
version "0.1.1"
resolved "https://registry.yarnpkg.com/@react-theming/flatten/-/flatten-0.1.1.tgz#62dc8a11f77b3dc1c6f26937ad4044a4d3e13853"
integrity sha512-cieWCbO4xTgl8/LAUTEgiafEiFIcheARteyxXddnUHm/+7POCmRvSE/woHGXlVH7dFBlCbI4y/e5ikMzwBA3CA==
dependencies:
color "^3.1.2"
color-convert "^2.0.1"
color-parse "^1.3.8"
color-rgba "^2.1.1"
color-string "^1.5.3"
color-stringify "^1.2.1"
flat "^5.0.0"
is-color-stop "^1.1.0"
rgb-hex "^3.0.0"
"@react-theming/storybook-addon@1.1.5":
version "1.1.5"
resolved "https://registry.yarnpkg.com/@react-theming/storybook-addon/-/storybook-addon-1.1.5.tgz#cb00ce26139859b2e233619b4c29b2cc391767c9"
integrity sha512-m4LM4j/dDzwMdvdHvsdiM64Qb6pI7DdALHHMoCCe0u4OFlAxtHk67FlwMkEGfsoV3zZWHYhz8hP7rcSrPUMbVw==
dependencies:
"@react-theming/flatten" "^0.1.1"
"@react-theming/theme-name" "^1.0.3"
"@react-theming/theme-swatch" "^1.0.0"
"@storybook/addon-devkit" "^1.4.2"
"@usulpro/react-json-view" "^2.0.1"
react-color "^2.18.0"
"@react-theming/theme-name@^1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@react-theming/theme-name/-/theme-name-1.0.3.tgz#f722defe226dc349b32d7b8a699611ff6eeea008"
integrity sha512-5tYnKIG3wUJ3GTX50ldeU+nxLTEU8WXEGsHk8mWeG9XGC4VxKIp2gSqS6B/opCGmfuIFm459Dtru8PSuEXiJJg==
dependencies:
color-name-list "^4.7.1"
nearest-color "^0.4.4"
"@react-theming/theme-swatch@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@react-theming/theme-swatch/-/theme-swatch-1.0.0.tgz#ba3ffc8e69c65a220b9bf1da0c2d5134287037e8"
integrity sha512-tOzDTUbFB5uQLMVHJ4fXWYZ4i7JIKjyrS7SlHDoscRZqM69lmT+s9fSZoD1/InTdX0M7Jh8thXF0SzeoxnD1/Q==
"@sinonjs/commons@^1.7.0": "@sinonjs/commons@^1.7.0":
version "1.8.3" version "1.8.3"
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d"
@ -1934,18 +1871,6 @@
lodash "^4.17.21" lodash "^4.17.21"
ts-dedent "^2.0.0" ts-dedent "^2.0.0"
"@storybook/addon-devkit@^1.4.2":
version "1.4.2"
resolved "https://registry.yarnpkg.com/@storybook/addon-devkit/-/addon-devkit-1.4.2.tgz#a230fef4554c604799def525541c61af06e8d22d"
integrity sha512-ggy34eCzmiKOwgV7xYNjlPClGpmtnYODPJv0vkCKiDyPeVLHocq2UZ7ZkOhQ5GO7TM7aLeeC1JBS00tZId9oLA==
dependencies:
"@reach/rect" "^0.2.1"
"@storybook/addons" "^6.1.18"
"@storybook/core-events" "^6.1.18"
"@storybook/theming" "^6.1.18"
deep-equal "^2.0.2"
prop-types "^15.6.2"
"@storybook/addon-docs@6.4.22": "@storybook/addon-docs@6.4.22":
version "6.4.22" version "6.4.22"
resolved "https://registry.yarnpkg.com/@storybook/addon-docs/-/addon-docs-6.4.22.tgz#19f22ede8ae31291069af7ab5abbc23fa269012b" resolved "https://registry.yarnpkg.com/@storybook/addon-docs/-/addon-docs-6.4.22.tgz#19f22ede8ae31291069af7ab5abbc23fa269012b"
@ -2095,7 +2020,7 @@
prop-types "^15.7.2" prop-types "^15.7.2"
regenerator-runtime "^0.13.7" regenerator-runtime "^0.13.7"
"@storybook/addons@6.4.22", "@storybook/addons@^6.1.18": "@storybook/addons@6.4.22":
version "6.4.22" version "6.4.22"
resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-6.4.22.tgz#e165407ca132c2182de2d466b7ff7c5644b6ad7b" resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-6.4.22.tgz#e165407ca132c2182de2d466b7ff7c5644b6ad7b"
integrity sha512-P/R+Jsxh7pawKLYo8MtE3QU/ilRFKbtCewV/T1o5U/gm8v7hKQdFz3YdRMAra4QuCY8bQIp7MKd2HrB5aH5a1A== integrity sha512-P/R+Jsxh7pawKLYo8MtE3QU/ilRFKbtCewV/T1o5U/gm8v7hKQdFz3YdRMAra4QuCY8bQIp7MKd2HrB5aH5a1A==
@ -2388,7 +2313,7 @@
util-deprecate "^1.0.2" util-deprecate "^1.0.2"
webpack "4" webpack "4"
"@storybook/core-events@6.4.22", "@storybook/core-events@^6.1.18": "@storybook/core-events@6.4.22":
version "6.4.22" version "6.4.22"
resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-6.4.22.tgz#c09b0571951affd4254028b8958a4d8652700989" resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-6.4.22.tgz#c09b0571951affd4254028b8958a4d8652700989"
integrity sha512-5GYY5+1gd58Gxjqex27RVaX6qbfIQmJxcbzbNpXGNSqwqAuIIepcV1rdCVm6I4C3Yb7/AQ3cN5dVbf33QxRIwA== integrity sha512-5GYY5+1gd58Gxjqex27RVaX6qbfIQmJxcbzbNpXGNSqwqAuIIepcV1rdCVm6I4C3Yb7/AQ3cN5dVbf33QxRIwA==
@ -2668,7 +2593,7 @@
ts-dedent "^2.0.0" ts-dedent "^2.0.0"
util-deprecate "^1.0.2" util-deprecate "^1.0.2"
"@storybook/theming@6.4.22", "@storybook/theming@^6.1.18": "@storybook/theming@6.4.22":
version "6.4.22" version "6.4.22"
resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-6.4.22.tgz#19097eec0366447ddd0d6917b0e0f81d0ec5e51e" resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-6.4.22.tgz#19097eec0366447ddd0d6917b0e0f81d0ec5e51e"
integrity sha512-NVMKH/jxSPtnMTO4VCN1k47uztq+u9fWv4GSnzq/eezxdGg9ceGL4/lCrNGoNajht9xbrsZ4QvsJ/V2sVGM8wA== integrity sha512-NVMKH/jxSPtnMTO4VCN1k47uztq+u9fWv4GSnzq/eezxdGg9ceGL4/lCrNGoNajht9xbrsZ4QvsJ/V2sVGM8wA==
@ -3375,17 +3300,6 @@
"@typescript-eslint/types" "5.23.0" "@typescript-eslint/types" "5.23.0"
eslint-visitor-keys "^3.0.0" eslint-visitor-keys "^3.0.0"
"@usulpro/react-json-view@^2.0.1":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@usulpro/react-json-view/-/react-json-view-2.0.1.tgz#2240e9319a9c6258df3b69961572a995ddca35d1"
integrity sha512-X8Ik4JmZF2Cu7vZTJQwHIbDqNaJEUEGZmdAPxKe4Ed+Xa3dyVTAeA9ea/nTNCzKRTZBIxvJFXvibpglpJ136BA==
dependencies:
color-string "^1.5.3"
flux "^4.0.1"
react-base16-styling "^0.6.0"
react-lifecycles-compat "^3.0.4"
react-textarea-autosize "^6.1.0"
"@webassemblyjs/ast@1.11.1": "@webassemblyjs/ast@1.11.1":
version "1.11.1" version "1.11.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7"
@ -4092,11 +4006,6 @@ arrify@^2.0.1:
resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa"
integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==
asap@~2.0.3:
version "2.0.6"
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
asn1.js@^5.2.0: asn1.js@^5.2.0:
version "5.4.1" version "5.4.1"
resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07"
@ -4179,11 +4088,6 @@ autoprefixer@^9.8.6:
postcss "^7.0.32" postcss "^7.0.32"
postcss-value-parser "^4.1.0" postcss-value-parser "^4.1.0"
available-typed-arrays@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7"
integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==
axe-core@^4.3.5: axe-core@^4.3.5:
version "4.4.0" version "4.4.0"
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.4.0.tgz#f93be7f81017eb8bedeb1859cc8092cc918d2dc8" resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.4.0.tgz#f93be7f81017eb8bedeb1859cc8092cc918d2dc8"
@ -4394,11 +4298,6 @@ balanced-match@^1.0.0:
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
base16@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/base16/-/base16-1.0.0.tgz#e297f60d7ec1014a7a971a39ebc8a98c0b681e70"
integrity sha1-4pf2DX7BAUp6lxo568ipjAtoHnA=
base64-js@^1.0.2, base64-js@^1.3.1: base64-js@^1.0.2, base64-js@^1.3.1:
version "1.5.1" version "1.5.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
@ -5101,7 +5000,7 @@ collection-visit@^1.0.0:
map-visit "^1.0.0" map-visit "^1.0.0"
object-visit "^1.0.0" object-visit "^1.0.0"
color-convert@^1.9.0, color-convert@^1.9.3: color-convert@^1.9.0:
version "1.9.3" version "1.9.3"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
@ -5115,69 +5014,21 @@ color-convert@^2.0.1:
dependencies: dependencies:
color-name "~1.1.4" color-name "~1.1.4"
color-name-list@^4.7.1:
version "4.15.0"
resolved "https://registry.yarnpkg.com/color-name-list/-/color-name-list-4.15.0.tgz#23a632bdb37fdad4c7f50303d0068c410fe3d601"
integrity sha512-4P3pFob8w6LNnku94oIacj8suCfhOLmY+25bmfoOwqFtuhLTD4Oux+/aUBdZLcvLK3fHrBe6XrzAU2IbwoWnQA==
color-name@1.1.3: color-name@1.1.3:
version "1.1.3" version "1.1.3"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
color-name@^1.0.0, color-name@^1.1.4, color-name@~1.1.4: color-name@^1.1.4, color-name@~1.1.4:
version "1.1.4" version "1.1.4"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
color-parse@^1.3.8, color-parse@^1.4.2:
version "1.4.2"
resolved "https://registry.yarnpkg.com/color-parse/-/color-parse-1.4.2.tgz#78651f5d34df1a57f997643d86f7f87268ad4eb5"
integrity sha512-RI7s49/8yqDj3fECFZjUI1Yi0z/Gq1py43oNJivAIIDSyJiOZLfYCRQEgn8HEVAj++PcRe8AnL2XF0fRJ3BTnA==
dependencies:
color-name "^1.0.0"
color-rgba@^2.1.1:
version "2.4.0"
resolved "https://registry.yarnpkg.com/color-rgba/-/color-rgba-2.4.0.tgz#ae85819c530262c29fc2da129fc7c8f9efc57015"
integrity sha512-Nti4qbzr/z2LbUWySr7H9dk3Rl7gZt7ihHAxlgT4Ho90EXWkjtkL1avTleu9yeGuqrt/chxTB6GKK8nZZ6V0+Q==
dependencies:
color-parse "^1.4.2"
color-space "^2.0.0"
color-space@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/color-space/-/color-space-2.0.0.tgz#ae7813abcbe3dabda9e3e2266b0675f688b24977"
integrity sha512-Bu8P/usGNuVWushjxcuaGSkhT+L2KX0cvgMGMTF0KJ7lFeqonhsntT68d6Yu3uwZzCmbF7KTB9EV67AGcUXhJw==
color-string@^1.5.3, color-string@^1.6.0:
version "1.9.0"
resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.0.tgz#63b6ebd1bec11999d1df3a79a7569451ac2be8aa"
integrity sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ==
dependencies:
color-name "^1.0.0"
simple-swizzle "^0.2.2"
color-stringify@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/color-stringify/-/color-stringify-1.2.1.tgz#289b5cf0dff64d147bf76b2317f93a573a3fe071"
integrity sha1-KJtc8N/2TRR792sjF/k6Vzo/4HE=
dependencies:
color-name "^1.0.0"
color-support@^1.1.2: color-support@^1.1.2:
version "1.1.3" version "1.1.3"
resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2"
integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==
color@^3.1.2:
version "3.2.1"
resolved "https://registry.yarnpkg.com/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164"
integrity sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==
dependencies:
color-convert "^1.9.3"
color-string "^1.6.0"
colord@^2.9.1: colord@^2.9.1:
version "2.9.2" version "2.9.2"
resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.2.tgz#25e2bacbbaa65991422c07ea209e2089428effb1" resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.2.tgz#25e2bacbbaa65991422c07ea209e2089428effb1"
@ -5490,13 +5341,6 @@ cronstrue@2.4.0:
resolved "https://registry.yarnpkg.com/cronstrue/-/cronstrue-2.4.0.tgz#16c6d10a17b90c37a71c7e8fb3bb67d0243d70e5" resolved "https://registry.yarnpkg.com/cronstrue/-/cronstrue-2.4.0.tgz#16c6d10a17b90c37a71c7e8fb3bb67d0243d70e5"
integrity sha512-KDJgE8XoT0Nupt1iljNGAQnxkfITwIYkL7mHrzH4a0AWyrj7Xk6GVCNPN3Avs7tU2yYoNuDculMKp9T3jysbPA== integrity sha512-KDJgE8XoT0Nupt1iljNGAQnxkfITwIYkL7mHrzH4a0AWyrj7Xk6GVCNPN3Avs7tU2yYoNuDculMKp9T3jysbPA==
cross-fetch@^3.0.4:
version "3.1.5"
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f"
integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==
dependencies:
node-fetch "2.6.7"
cross-spawn@^6.0.0: cross-spawn@^6.0.0:
version "6.0.5" version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
@ -5534,11 +5378,6 @@ crypto-browserify@^3.11.0:
randombytes "^2.0.0" randombytes "^2.0.0"
randomfill "^1.0.3" randomfill "^1.0.3"
css-color-names@^0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0"
integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=
css-declaration-sorter@^6.0.3: css-declaration-sorter@^6.0.3:
version "6.1.4" version "6.1.4"
resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.1.4.tgz#b9bfb4ed9a41f8dcca9bf7184d849ea94a8294b4" resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.1.4.tgz#b9bfb4ed9a41f8dcca9bf7184d849ea94a8294b4"
@ -5749,6 +5588,11 @@ data-urls@^2.0.0:
whatwg-mimetype "^2.3.0" whatwg-mimetype "^2.3.0"
whatwg-url "^8.0.0" whatwg-url "^8.0.0"
dayjs@^1.11.2:
version "1.11.2"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.2.tgz#fa0f5223ef0d6724b3d8327134890cfe3d72fbe5"
integrity sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw==
debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9: debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9:
version "2.6.9" version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
@ -5792,27 +5636,6 @@ dedent@^0.7.0:
resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=
deep-equal@^2.0.2:
version "2.0.5"
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.0.5.tgz#55cd2fe326d83f9cbf7261ef0e060b3f724c5cb9"
integrity sha512-nPiRgmbAtm1a3JsnLCf6/SLfXcjyN5v8L1TXzdCmHrXJ4hx+gW/w1YCcn7z8gJtSiDArZCgYtbao3QqLm/N1Sw==
dependencies:
call-bind "^1.0.0"
es-get-iterator "^1.1.1"
get-intrinsic "^1.0.1"
is-arguments "^1.0.4"
is-date-object "^1.0.2"
is-regex "^1.1.1"
isarray "^2.0.5"
object-is "^1.1.4"
object-keys "^1.1.1"
object.assign "^4.1.2"
regexp.prototype.flags "^1.3.0"
side-channel "^1.0.3"
which-boxed-primitive "^1.0.1"
which-collection "^1.0.1"
which-typed-array "^1.1.2"
deep-is@^0.1.3, deep-is@~0.1.3: deep-is@^0.1.3, deep-is@~0.1.3:
version "0.1.4" version "0.1.4"
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
@ -6251,7 +6074,7 @@ error-stack-parser@^2.0.6:
dependencies: dependencies:
stackframe "^1.1.1" stackframe "^1.1.1"
es-abstract@^1.18.5, es-abstract@^1.19.0, es-abstract@^1.19.1: es-abstract@^1.19.0, es-abstract@^1.19.1:
version "1.19.1" version "1.19.1"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3"
integrity sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w== integrity sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==
@ -6282,7 +6105,7 @@ es-array-method-boxes-properly@^1.0.0:
resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e"
integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==
es-get-iterator@^1.0.2, es-get-iterator@^1.1.1: es-get-iterator@^1.0.2:
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.2.tgz#9234c54aba713486d7ebde0220864af5e2b283f7" resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.2.tgz#9234c54aba713486d7ebde0220864af5e2b283f7"
integrity sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ== integrity sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ==
@ -6883,31 +6706,6 @@ fb-watchman@^2.0.0:
dependencies: dependencies:
bser "2.1.1" bser "2.1.1"
fbemitter@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/fbemitter/-/fbemitter-3.0.0.tgz#00b2a1af5411254aab416cd75f9e6289bee4bff3"
integrity sha512-KWKaceCwKQU0+HPoop6gn4eOHk50bBv/VxjJtGMfwmJt3D29JpN4H4eisCtIPA+a8GVBam+ldMMpMjJUvpDyHw==
dependencies:
fbjs "^3.0.0"
fbjs-css-vars@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz#216551136ae02fe255932c3ec8775f18e2c078b8"
integrity sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==
fbjs@^3.0.0, fbjs@^3.0.1:
version "3.0.2"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-3.0.2.tgz#dfae08a85c66a58372993ce2caf30863f569ff94"
integrity sha512-qv+boqYndjElAJHNN3NoM8XuwQZ1j2m3kEvTgdle8IDjr6oUbkEpvABWtj/rQl3vq4ew7dnElBxL4YJAwTVqQQ==
dependencies:
cross-fetch "^3.0.4"
fbjs-css-vars "^1.0.0"
loose-envify "^1.0.0"
object-assign "^4.1.0"
promise "^7.1.1"
setimmediate "^1.0.5"
ua-parser-js "^0.7.30"
fd-slicer@~1.1.0: fd-slicer@~1.1.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
@ -7047,11 +6845,6 @@ flat-cache@^3.0.4:
flatted "^3.1.0" flatted "^3.1.0"
rimraf "^3.0.2" rimraf "^3.0.2"
flat@^5.0.0:
version "5.0.2"
resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241"
integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==
flatted@^3.1.0: flatted@^3.1.0:
version "3.2.5" version "3.2.5"
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3"
@ -7065,14 +6858,6 @@ flush-write-stream@^1.0.0:
inherits "^2.0.3" inherits "^2.0.3"
readable-stream "^2.3.6" readable-stream "^2.3.6"
flux@^4.0.1:
version "4.0.3"
resolved "https://registry.yarnpkg.com/flux/-/flux-4.0.3.tgz#573b504a24982c4768fdfb59d8d2ea5637d72ee7"
integrity sha512-yKAbrp7JhZhj6uiT1FTuVMlIAT1J4jqEyBpFApi1kxpGZCvacMVc/t1pMQyotqHhAgvoE3bNvAykhCo2CLjnYw==
dependencies:
fbemitter "^3.0.0"
fbjs "^3.0.1"
follow-redirects@^1.0.0: follow-redirects@^1.0.0:
version "1.14.8" version "1.14.8"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc"
@ -7088,11 +6873,6 @@ for-in@^1.0.2:
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=
foreach@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99"
integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k=
foreground-child@^2.0.0: foreground-child@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-2.0.0.tgz#71b32800c9f15aa8f2f83f4a6bd9bff35d861a53" resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-2.0.0.tgz#71b32800c9f15aa8f2f83f4a6bd9bff35d861a53"
@ -7301,7 +7081,7 @@ get-caller-file@^2.0.5:
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
get-intrinsic@^1.0.1, get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1:
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6"
integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==
@ -7674,11 +7454,6 @@ headers-polyfill@^3.0.4:
resolved "https://registry.yarnpkg.com/headers-polyfill/-/headers-polyfill-3.0.4.tgz#cd70c815a441dd882372fcd6eda212ce997c9b18" resolved "https://registry.yarnpkg.com/headers-polyfill/-/headers-polyfill-3.0.4.tgz#cd70c815a441dd882372fcd6eda212ce997c9b18"
integrity sha512-I1DOM1EdWYntdrnCvqQtcKwSSuiTzoqOExy4v1mdcFixFZABlWP4IPHdmoLtPda0abMHqDOY4H9svhQ10DFR4w== integrity sha512-I1DOM1EdWYntdrnCvqQtcKwSSuiTzoqOExy4v1mdcFixFZABlWP4IPHdmoLtPda0abMHqDOY4H9svhQ10DFR4w==
hex-color-regex@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e"
integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==
highlight.js@^10.1.1, highlight.js@~10.7.0: highlight.js@^10.1.1, highlight.js@~10.7.0:
version "10.7.3" version "10.7.3"
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531" resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531"
@ -7729,16 +7504,6 @@ hpack.js@^2.1.6:
readable-stream "^2.0.1" readable-stream "^2.0.1"
wbuf "^1.1.0" wbuf "^1.1.0"
hsl-regex@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e"
integrity sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=
hsla-regex@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38"
integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg=
html-encoding-sniffer@^2.0.1: html-encoding-sniffer@^2.0.1:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3"
@ -8097,7 +7862,7 @@ is-alphanumerical@^1.0.0:
is-alphabetical "^1.0.0" is-alphabetical "^1.0.0"
is-decimal "^1.0.0" is-decimal "^1.0.0"
is-arguments@^1.0.4, is-arguments@^1.1.0: is-arguments@^1.1.0:
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b"
integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==
@ -8110,11 +7875,6 @@ is-arrayish@^0.2.1:
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
is-arrayish@^0.3.1:
version "0.3.2"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==
is-bigint@^1.0.1: is-bigint@^1.0.1:
version "1.0.4" version "1.0.4"
resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3"
@ -8166,18 +7926,6 @@ is-ci@^2.0.0:
dependencies: dependencies:
ci-info "^2.0.0" ci-info "^2.0.0"
is-color-stop@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345"
integrity sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=
dependencies:
css-color-names "^0.0.4"
hex-color-regex "^1.1.0"
hsl-regex "^1.0.0"
hsla-regex "^1.0.0"
rgb-regex "^1.0.1"
rgba-regex "^1.0.0"
is-core-module@^2.2.0, is-core-module@^2.8.1: is-core-module@^2.2.0, is-core-module@^2.8.1:
version "2.8.1" version "2.8.1"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211"
@ -8199,7 +7947,7 @@ is-data-descriptor@^1.0.0:
dependencies: dependencies:
kind-of "^6.0.0" kind-of "^6.0.0"
is-date-object@^1.0.1, is-date-object@^1.0.2: is-date-object@^1.0.1:
version "1.0.5" version "1.0.5"
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f"
integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==
@ -8303,7 +8051,7 @@ is-interactive@^1.0.0:
resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e"
integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==
is-map@^2.0.1, is-map@^2.0.2: is-map@^2.0.2:
version "2.0.2" version "2.0.2"
resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127" resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127"
integrity sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg== integrity sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==
@ -8374,7 +8122,7 @@ is-potential-custom-element-name@^1.0.1:
resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5"
integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==
is-regex@^1.1.1, is-regex@^1.1.2, is-regex@^1.1.4: is-regex@^1.1.2, is-regex@^1.1.4:
version "1.1.4" version "1.1.4"
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958"
integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==
@ -8382,7 +8130,7 @@ is-regex@^1.1.1, is-regex@^1.1.2, is-regex@^1.1.4:
call-bind "^1.0.2" call-bind "^1.0.2"
has-tostringtag "^1.0.0" has-tostringtag "^1.0.0"
is-set@^2.0.1, is-set@^2.0.2: is-set@^2.0.2:
version "2.0.2" version "2.0.2"
resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.2.tgz#90755fa4c2562dc1c5d4024760d6119b94ca18ec" resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.2.tgz#90755fa4c2562dc1c5d4024760d6119b94ca18ec"
integrity sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g== integrity sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==
@ -8416,17 +8164,6 @@ is-symbol@^1.0.2, is-symbol@^1.0.3:
dependencies: dependencies:
has-symbols "^1.0.2" has-symbols "^1.0.2"
is-typed-array@^1.1.7:
version "1.1.8"
resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.8.tgz#cbaa6585dc7db43318bc5b89523ea384a6f65e79"
integrity sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA==
dependencies:
available-typed-arrays "^1.0.5"
call-bind "^1.0.2"
es-abstract "^1.18.5"
foreach "^2.0.5"
has-tostringtag "^1.0.0"
is-typedarray@^1.0.0: is-typedarray@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
@ -8437,11 +8174,6 @@ is-unicode-supported@^0.1.0:
resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7"
integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==
is-weakmap@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2"
integrity sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==
is-weakref@^1.0.1: is-weakref@^1.0.1:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2"
@ -8449,14 +8181,6 @@ is-weakref@^1.0.1:
dependencies: dependencies:
call-bind "^1.0.2" call-bind "^1.0.2"
is-weakset@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.2.tgz#4569d67a747a1ce5a994dfd4ef6dcea76e7c0a1d"
integrity sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==
dependencies:
call-bind "^1.0.2"
get-intrinsic "^1.1.1"
is-whitespace-character@^1.0.0: is-whitespace-character@^1.0.0:
version "1.0.4" version "1.0.4"
resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz#0858edd94a95594c7c9dd0b5c174ec6e45ee4aa7" resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz#0858edd94a95594c7c9dd0b5c174ec6e45ee4aa7"
@ -9466,26 +9190,16 @@ locate-path@^6.0.0:
dependencies: dependencies:
p-locate "^5.0.0" p-locate "^5.0.0"
lodash-es@^4.17.15, lodash-es@^4.17.21: lodash-es@^4.17.21:
version "4.17.21" version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
lodash.curry@^4.0.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lodash.curry/-/lodash.curry-4.1.1.tgz#248e36072ede906501d75966200a86dab8b23170"
integrity sha1-JI42By7ekGUB11lmIAqG2riyMXA=
lodash.debounce@^4.0.8: lodash.debounce@^4.0.8:
version "4.0.8" version "4.0.8"
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168=
lodash.flow@^3.3.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/lodash.flow/-/lodash.flow-3.5.0.tgz#87bf40292b8cf83e4e8ce1a3ae4209e20071675a"
integrity sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o=
lodash.memoize@4.1.2, lodash.memoize@4.x, lodash.memoize@^4.1.2: lodash.memoize@4.1.2, lodash.memoize@4.x, lodash.memoize@^4.1.2:
version "4.1.2" version "4.1.2"
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
@ -9501,7 +9215,7 @@ lodash.uniq@4.5.0, lodash.uniq@^4.5.0:
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
lodash@^4.0.1, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0: lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0:
version "4.17.21" version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@ -9609,11 +9323,6 @@ markdown-to-jsx@^7.1.3:
resolved "https://registry.yarnpkg.com/markdown-to-jsx/-/markdown-to-jsx-7.1.6.tgz#421487df2a66fe4231d94db653a34da033691e62" resolved "https://registry.yarnpkg.com/markdown-to-jsx/-/markdown-to-jsx-7.1.6.tgz#421487df2a66fe4231d94db653a34da033691e62"
integrity sha512-1wrIGZYwIG2gR3yfRmbr4FlQmhaAKoKTpRo4wur4fp9p0njU1Hi7vR8fj0AUKKIcPduiJmPprzmCB5B/GvlC7g== integrity sha512-1wrIGZYwIG2gR3yfRmbr4FlQmhaAKoKTpRo4wur4fp9p0njU1Hi7vR8fj0AUKKIcPduiJmPprzmCB5B/GvlC7g==
material-colors@^1.2.1:
version "1.2.6"
resolved "https://registry.yarnpkg.com/material-colors/-/material-colors-1.2.6.tgz#6d1958871126992ceecc72f4bcc4d8f010865f46"
integrity sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==
md5.js@^1.3.4: md5.js@^1.3.4:
version "1.3.5" version "1.3.5"
resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
@ -10042,11 +9751,6 @@ natural-compare@^1.4.0:
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
nearest-color@^0.4.4:
version "0.4.4"
resolved "https://registry.yarnpkg.com/nearest-color/-/nearest-color-0.4.4.tgz#fb812072b511f4f09a0a316903332e09fa5d7f1d"
integrity sha512-orhcaIORC10tf41Ld2wwlcC+FaAavHG87JHWB3eHH5p7v2k9Tzym2XNEZzLAm5YJwGv6Q38WWc7SOb+Qfu/4NQ==
negotiator@0.6.3: negotiator@0.6.3:
version "0.6.3" version "0.6.3"
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
@ -10082,7 +9786,7 @@ node-dir@^0.1.10:
dependencies: dependencies:
minimatch "^3.0.2" minimatch "^3.0.2"
node-fetch@2.6.7, node-fetch@^2.6.1, node-fetch@^2.6.7: node-fetch@^2.6.1, node-fetch@^2.6.7:
version "2.6.7" version "2.6.7"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
@ -10206,7 +9910,7 @@ nwsapi@^2.2.0:
resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7"
integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==
object-assign@^4.1.0, object-assign@^4.1.1: object-assign@^4.1.1:
version "4.1.1" version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
@ -10225,14 +9929,6 @@ object-inspect@^1.11.0, object-inspect@^1.9.0:
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0"
integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==
object-is@^1.1.4:
version "1.1.5"
resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac"
integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==
dependencies:
call-bind "^1.0.2"
define-properties "^1.1.3"
object-keys@^1.0.12, object-keys@^1.1.1: object-keys@^1.0.12, object-keys@^1.1.1:
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
@ -11246,13 +10942,6 @@ promise.prototype.finally@^3.1.0:
define-properties "^1.1.3" define-properties "^1.1.3"
es-abstract "^1.19.1" es-abstract "^1.19.1"
promise@^7.1.1:
version "7.3.1"
resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==
dependencies:
asap "~2.0.3"
prompts@^2.0.1, prompts@^2.4.0: prompts@^2.0.1, prompts@^2.4.0:
version "2.4.2" version "2.4.2"
resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069"
@ -11261,7 +10950,7 @@ prompts@^2.0.1, prompts@^2.4.0:
kleur "^3.0.3" kleur "^3.0.3"
sisteransi "^1.0.5" sisteransi "^1.0.5"
prop-types@^15.0.0, prop-types@^15.5.10, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: prop-types@^15.0.0, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1:
version "15.8.1" version "15.8.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
@ -11366,11 +11055,6 @@ punycode@^2.1.0, punycode@^2.1.1:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
pure-color@^1.2.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/pure-color/-/pure-color-1.3.0.tgz#1fe064fb0ac851f0de61320a8bf796836422f33e"
integrity sha1-H+Bk+wrIUfDeYTIKi/eWg2Qi8z4=
qs@6.9.7: qs@6.9.7:
version "6.9.7" version "6.9.7"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.7.tgz#4610846871485e1e048f44ae3b94033f0e675afe" resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.7.tgz#4610846871485e1e048f44ae3b94033f0e675afe"
@ -11446,29 +11130,6 @@ raw-loader@^4.0.2:
loader-utils "^2.0.0" loader-utils "^2.0.0"
schema-utils "^3.0.0" schema-utils "^3.0.0"
react-base16-styling@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/react-base16-styling/-/react-base16-styling-0.6.0.tgz#ef2156d66cf4139695c8a167886cb69ea660792c"
integrity sha1-7yFW1mz0E5aVyKFniGy2nqZgeSw=
dependencies:
base16 "^1.0.0"
lodash.curry "^4.0.1"
lodash.flow "^3.3.0"
pure-color "^1.2.0"
react-color@^2.18.0:
version "2.19.3"
resolved "https://registry.yarnpkg.com/react-color/-/react-color-2.19.3.tgz#ec6c6b4568312a3c6a18420ab0472e146aa5683d"
integrity sha512-LEeGE/ZzNLIsFWa1TMe8y5VYqr7bibneWmvJwm1pCn/eNmrabWDh659JSPn9BuaMpEfU83WTOJfnCcjDZwNQTA==
dependencies:
"@icons/material" "^0.2.4"
lodash "^4.17.15"
lodash-es "^4.17.15"
material-colors "^1.2.1"
prop-types "^15.5.10"
reactcss "^1.2.0"
tinycolor2 "^1.4.1"
react-colorful@^5.1.2: react-colorful@^5.1.2:
version "5.5.1" version "5.5.1"
resolved "https://registry.yarnpkg.com/react-colorful/-/react-colorful-5.5.1.tgz#29d9c4e496f2ca784dd2bb5053a3a4340cfaf784" resolved "https://registry.yarnpkg.com/react-colorful/-/react-colorful-5.5.1.tgz#29d9c4e496f2ca784dd2bb5053a3a4340cfaf784"
@ -11645,13 +11306,6 @@ react-syntax-highlighter@^13.5.3:
prismjs "^1.21.0" prismjs "^1.21.0"
refractor "^3.1.0" refractor "^3.1.0"
react-textarea-autosize@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-6.1.0.tgz#df91387f8a8f22020b77e3833c09829d706a09a5"
integrity sha512-F6bI1dgib6fSvG8so1HuArPUv+iVEfPliuLWusLF+gAKz0FbB4jLrWUrTAeq1afnPT2c9toEZYUdz/y1uKMy4A==
dependencies:
prop-types "^15.6.0"
react-textarea-autosize@^8.3.0: react-textarea-autosize@^8.3.0:
version "8.3.3" version "8.3.3"
resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.3.3.tgz#f70913945369da453fd554c168f6baacd1fa04d8" resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.3.3.tgz#f70913945369da453fd554c168f6baacd1fa04d8"
@ -11679,13 +11333,6 @@ react@17.0.2:
loose-envify "^1.1.0" loose-envify "^1.1.0"
object-assign "^4.1.1" object-assign "^4.1.1"
reactcss@^1.2.0:
version "1.2.3"
resolved "https://registry.yarnpkg.com/reactcss/-/reactcss-1.2.3.tgz#c00013875e557b1cf0dfd9a368a1c3dab3b548dd"
integrity sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A==
dependencies:
lodash "^4.0.1"
read-pkg-up@^7.0.1: read-pkg-up@^7.0.1:
version "7.0.1" version "7.0.1"
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507"
@ -11799,7 +11446,7 @@ regex-not@^1.0.0, regex-not@^1.0.2:
extend-shallow "^3.0.2" extend-shallow "^3.0.2"
safe-regex "^1.1.0" safe-regex "^1.1.0"
regexp.prototype.flags@^1.3.0, regexp.prototype.flags@^1.3.1: regexp.prototype.flags@^1.3.1:
version "1.4.1" version "1.4.1"
resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz#b3f4c0059af9e47eca9f3f660e51d81307e72307" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz#b3f4c0059af9e47eca9f3f660e51d81307e72307"
integrity sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ== integrity sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ==
@ -12033,21 +11680,6 @@ reusify@^1.0.4:
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
rgb-hex@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/rgb-hex/-/rgb-hex-3.0.0.tgz#eab0168cc1279563b18a14605315389142e2e487"
integrity sha512-8h7ZcwxCBDKvchSWbWngJuSCqJGQ6nDuLLg+QcRyQDbX9jMWt+PpPeXAhSla0GOooEomk3lCprUpGkMdsLjKyg==
rgb-regex@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1"
integrity sha1-wODWiC3w4jviVKR16O3UGRX+rrE=
rgba-regex@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3"
integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=
rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2: rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2:
version "3.0.2" version "3.0.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
@ -12332,7 +11964,7 @@ set-value@^2.0.0, set-value@^2.0.1:
is-plain-object "^2.0.3" is-plain-object "^2.0.3"
split-string "^3.0.1" split-string "^3.0.1"
setimmediate@^1.0.4, setimmediate@^1.0.5: setimmediate@^1.0.4:
version "1.0.5" version "1.0.5"
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=
@ -12391,7 +12023,7 @@ shebang-regex@^3.0.0:
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
side-channel@^1.0.3, side-channel@^1.0.4: side-channel@^1.0.4:
version "1.0.4" version "1.0.4"
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==
@ -12405,13 +12037,6 @@ signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3:
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af"
integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ== integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==
simple-swizzle@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a"
integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=
dependencies:
is-arrayish "^0.3.1"
sirv@^1.0.7: sirv@^1.0.7:
version "1.0.19" version "1.0.19"
resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.19.tgz#1d73979b38c7fe91fcba49c85280daa9c2363b49" resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.19.tgz#1d73979b38c7fe91fcba49c85280daa9c2363b49"
@ -13139,11 +12764,6 @@ tiny-warning@^1.0.2:
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
tinycolor2@^1.4.1:
version "1.4.2"
resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.2.tgz#3f6a4d1071ad07676d7fa472e1fac40a719d8803"
integrity sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==
tmp@^0.0.33: tmp@^0.0.33:
version "0.0.33" version "0.0.33"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
@ -13408,11 +13028,6 @@ typescript@4.6.4:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.4.tgz#caa78bbc3a59e6a5c510d35703f6a09877ce45e9" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.4.tgz#caa78bbc3a59e6a5c510d35703f6a09877ce45e9"
integrity sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg== integrity sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==
ua-parser-js@^0.7.30:
version "0.7.31"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.31.tgz#649a656b191dffab4f21d5e053e27ca17cbff5c6"
integrity sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==
uglify-js@^3.1.4: uglify-js@^3.1.4:
version "3.15.1" version "3.15.1"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.15.1.tgz#9403dc6fa5695a6172a91bc983ea39f0f7c9086d" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.15.1.tgz#9403dc6fa5695a6172a91bc983ea39f0f7c9086d"
@ -14085,7 +13700,7 @@ whatwg-url@^8.0.0, whatwg-url@^8.5.0:
tr46 "^2.1.0" tr46 "^2.1.0"
webidl-conversions "^6.1.0" webidl-conversions "^6.1.0"
which-boxed-primitive@^1.0.1, which-boxed-primitive@^1.0.2: which-boxed-primitive@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==
@ -14096,28 +13711,6 @@ which-boxed-primitive@^1.0.1, which-boxed-primitive@^1.0.2:
is-string "^1.0.5" is-string "^1.0.5"
is-symbol "^1.0.3" is-symbol "^1.0.3"
which-collection@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.1.tgz#70eab71ebbbd2aefaf32f917082fc62cdcb70906"
integrity sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==
dependencies:
is-map "^2.0.1"
is-set "^2.0.1"
is-weakmap "^2.0.1"
is-weakset "^2.0.1"
which-typed-array@^1.1.2:
version "1.1.7"
resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.7.tgz#2761799b9a22d4b8660b3c1b40abaa7739691793"
integrity sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw==
dependencies:
available-typed-arrays "^1.0.5"
call-bind "^1.0.2"
es-abstract "^1.18.5"
foreach "^2.0.5"
has-tostringtag "^1.0.0"
is-typed-array "^1.1.7"
which@^1.2.9: which@^1.2.9:
version "1.3.1" version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"