mirror of
https://github.com/coder/coder.git
synced 2025-07-12 00:14:10 +00:00
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:
@ -1,20 +1,17 @@
|
||||
import CssBaseline from "@material-ui/core/CssBaseline"
|
||||
import ThemeProvider from "@material-ui/styles/ThemeProvider"
|
||||
import { withThemes } from "@react-theming/storybook-addon"
|
||||
import { createMemoryHistory } from "history"
|
||||
import { addDecorator } from "node_modules/@storybook/react"
|
||||
import { unstable_HistoryRouter as HistoryRouter } from "react-router-dom"
|
||||
import { dark, light } from "../src/theme"
|
||||
import { dark } from "../src/theme"
|
||||
import "../src/theme/globalFonts"
|
||||
|
||||
const providerFn = ({ children, theme }) => (
|
||||
<ThemeProvider theme={theme}>
|
||||
addDecorator((story) => (
|
||||
<ThemeProvider theme={dark}>
|
||||
<CssBaseline />
|
||||
{children}
|
||||
{story()}
|
||||
</ThemeProvider>
|
||||
)
|
||||
|
||||
addDecorator(withThemes(null, [light, dark], { providerFn }))
|
||||
))
|
||||
|
||||
const history = createMemoryHistory()
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Page } from "@playwright/test"
|
||||
import { BasePom } from "./BasePom"
|
||||
|
||||
export class TemplatesPage extends BasePom {
|
||||
export class WorkspacesPage extends BasePom {
|
||||
constructor(baseURL: string | undefined, page: Page) {
|
||||
super(baseURL, "/templates", page)
|
||||
super(baseURL, "/workspaces", page)
|
||||
}
|
||||
}
|
@ -1,2 +1,2 @@
|
||||
export * from "./SignInPage"
|
||||
export * from "./TemplatesPage"
|
||||
export * from "./WorkspacesPage"
|
||||
|
@ -1,17 +1,17 @@
|
||||
import { test } from "@playwright/test"
|
||||
import { email, password } from "../constants"
|
||||
import { SignInPage, TemplatesPage } from "../pom"
|
||||
import { SignInPage, WorkspacesPage } from "../pom"
|
||||
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" })
|
||||
|
||||
// Log-in with the default credentials we set up in the development server
|
||||
const signInPage = new SignInPage(baseURL, page)
|
||||
await signInPage.submitBuiltInAuthentication(email, password)
|
||||
|
||||
const templatesPage = new TemplatesPage(baseURL, page)
|
||||
await waitForClientSideNavigation(page, { to: templatesPage.url })
|
||||
const workspacesPage = new WorkspacesPage(baseURL, page)
|
||||
await waitForClientSideNavigation(page, { to: workspacesPage.url })
|
||||
|
||||
await page.waitForSelector("text=Templates")
|
||||
await page.waitForSelector("text=Workspaces")
|
||||
})
|
||||
|
@ -25,7 +25,7 @@
|
||||
"typegen": "xstate typegen 'src/**/*.ts'"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fontsource/fira-code": "4.5.9",
|
||||
"@fontsource/ibm-plex-mono": "4.5.9",
|
||||
"@fontsource/inter": "4.5.7",
|
||||
"@material-ui/core": "4.9.4",
|
||||
"@material-ui/icons": "4.5.1",
|
||||
@ -35,6 +35,7 @@
|
||||
"@xstate/react": "3.0.0",
|
||||
"axios": "0.26.1",
|
||||
"cronstrue": "2.4.0",
|
||||
"dayjs": "^1.11.2",
|
||||
"formik": "2.2.9",
|
||||
"history": "5.3.0",
|
||||
"react": "17.0.2",
|
||||
@ -53,7 +54,6 @@
|
||||
"devDependencies": {
|
||||
"@playwright/test": "1.21.1",
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "0.5.5",
|
||||
"@react-theming/storybook-addon": "1.1.5",
|
||||
"@storybook/addon-actions": "6.4.22",
|
||||
"@storybook/addon-essentials": "6.4.22",
|
||||
"@storybook/addon-links": "6.4.22",
|
||||
|
@ -12,15 +12,13 @@ import { OrgsPage } from "./pages/OrgsPage/OrgsPage"
|
||||
import { SettingsPage } from "./pages/SettingsPage/SettingsPage"
|
||||
import { AccountPage } from "./pages/SettingsPages/AccountPage/AccountPage"
|
||||
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 { UsersPage } from "./pages/UsersPage/UsersPage"
|
||||
import { WorkspacePage } from "./pages/WorkspacePage/WorkspacePage"
|
||||
import { WorkspaceSettingsPage } from "./pages/WorkspaceSettingsPage/WorkspaceSettingsPage"
|
||||
|
||||
const TerminalPage = React.lazy(() => import("./pages/TerminalPage/TerminalPage"))
|
||||
const WorkspacesPage = React.lazy(() => import("./pages/WorkspacesPage/WorkspacesPage"))
|
||||
|
||||
export const AppRouter: React.FC = () => (
|
||||
<React.Suspense fallback={<></>}>
|
||||
@ -46,36 +44,15 @@ export const AppRouter: React.FC = () => (
|
||||
}
|
||||
/>
|
||||
|
||||
<Route path="templates">
|
||||
<Route path="workspaces">
|
||||
<Route
|
||||
index
|
||||
element={
|
||||
<AuthAndFrame>
|
||||
<TemplatesPage />
|
||||
<WorkspacesPage />
|
||||
</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=":workspace">
|
||||
<Route
|
||||
index
|
||||
|
@ -115,6 +115,11 @@ export const getWorkspace = async (workspaceId: string): Promise<TypesGen.Worksp
|
||||
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 (
|
||||
organizationID: string,
|
||||
username = "me",
|
||||
|
@ -5,7 +5,7 @@ import { BrowserRouter as Router } from "react-router-dom"
|
||||
import { SWRConfig } from "swr"
|
||||
import { AppRouter } from "./AppRouter"
|
||||
import { GlobalSnackbar } from "./components/GlobalSnackbar/GlobalSnackbar"
|
||||
import { light } from "./theme"
|
||||
import { dark } from "./theme"
|
||||
import "./theme/globalFonts"
|
||||
import { XServiceProvider } from "./xServices/StateContext"
|
||||
|
||||
@ -31,7 +31,7 @@ export const App: React.FC = () => {
|
||||
}}
|
||||
>
|
||||
<XServiceProvider>
|
||||
<ThemeProvider theme={light}>
|
||||
<ThemeProvider theme={dark}>
|
||||
<CssBaseline />
|
||||
<AppRouter />
|
||||
<GlobalSnackbar />
|
||||
|
@ -51,7 +51,7 @@ export const AdminDropdown: React.FC = () => {
|
||||
<>
|
||||
<div className={styles.link}>
|
||||
<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 />}
|
||||
</ListItem>
|
||||
</div>
|
||||
|
@ -26,7 +26,7 @@ const useStyles = makeStyles((theme) => ({
|
||||
root: {
|
||||
minHeight: 156,
|
||||
background: theme.palette.background.default,
|
||||
color: theme.palette.codeBlock.contrastText,
|
||||
color: theme.palette.text.primary,
|
||||
fontFamily: MONOSPACE_FONT_FAMILY,
|
||||
fontSize: 13,
|
||||
wordBreak: "break-all",
|
||||
|
@ -28,7 +28,7 @@ const useStyles = makeStyles((theme) => ({
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
background: theme.palette.background.default,
|
||||
color: theme.palette.codeBlock.contrastText,
|
||||
color: theme.palette.primary.contrastText,
|
||||
fontFamily: MONOSPACE_FONT_FAMILY,
|
||||
fontSize: 13,
|
||||
padding: theme.spacing(2),
|
||||
|
@ -1,16 +1,15 @@
|
||||
import ThemeProvider from "@material-ui/styles/ThemeProvider"
|
||||
import { fireEvent, render } from "@testing-library/react"
|
||||
import React from "react"
|
||||
import { act } from "react-dom/test-utils"
|
||||
import { light } from "../../theme"
|
||||
import { WrapperComponent } from "../../testHelpers/renderHelpers"
|
||||
import { ConfirmDialog, ConfirmDialogProps } from "./ConfirmDialog"
|
||||
|
||||
namespace Helpers {
|
||||
export const Component: React.FC<ConfirmDialogProps> = (props: ConfirmDialogProps) => {
|
||||
return (
|
||||
<ThemeProvider theme={light}>
|
||||
<WrapperComponent>
|
||||
<ConfirmDialog {...props} />
|
||||
</ThemeProvider>
|
||||
</WrapperComponent>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -48,14 +48,11 @@ interface StyleProps {
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
dialogWrapper: (props: StyleProps) => ({
|
||||
"& .MuiPaper-root": {
|
||||
background:
|
||||
props.type === "info"
|
||||
? theme.palette.confirmDialog.info.background
|
||||
: theme.palette.confirmDialog.error.background,
|
||||
background: props.type === "info" ? theme.palette.primary.main : theme.palette.error.dark,
|
||||
},
|
||||
}),
|
||||
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),
|
||||
textAlign: "center",
|
||||
}),
|
||||
@ -65,15 +62,15 @@ const useStyles = makeStyles((theme) => ({
|
||||
description: (props: StyleProps) => ({
|
||||
color:
|
||||
props.type === "info"
|
||||
? fade(theme.palette.confirmDialog.info.text, 0.75)
|
||||
: fade(theme.palette.confirmDialog.error.text, 0.75),
|
||||
? fade(theme.palette.primary.contrastText, 0.75)
|
||||
: fade(theme.palette.error.contrastText, 0.75),
|
||||
lineHeight: "160%",
|
||||
|
||||
"& strong": {
|
||||
color:
|
||||
props.type === "info"
|
||||
? fade(theme.palette.confirmDialog.info.text, 0.95)
|
||||
: fade(theme.palette.confirmDialog.error.text, 0.95),
|
||||
? fade(theme.palette.primary.contrastText, 0.95)
|
||||
: fade(theme.palette.error.contrastText, 0.95),
|
||||
},
|
||||
}),
|
||||
}))
|
||||
|
@ -52,13 +52,13 @@ const useStyles = makeStyles((theme) => ({
|
||||
},
|
||||
copyButton: {
|
||||
borderRadius: 7,
|
||||
background: theme.palette.codeBlock.button.main,
|
||||
color: theme.palette.codeBlock.button.contrastText,
|
||||
background: theme.palette.background.default,
|
||||
color: theme.palette.primary.contrastText,
|
||||
padding: theme.spacing(0.85),
|
||||
minWidth: 32,
|
||||
|
||||
"&:hover": {
|
||||
background: theme.palette.codeBlock.button.hover,
|
||||
background: theme.palette.background.paper,
|
||||
},
|
||||
},
|
||||
fileCopyIcon: {
|
||||
|
@ -161,7 +161,7 @@ const useButtonStyles = makeStyles((theme) => ({
|
||||
},
|
||||
},
|
||||
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 {
|
||||
background: fade(color, 0.15),
|
||||
color,
|
||||
|
@ -68,7 +68,7 @@ const useStyles = makeStyles((theme) => ({
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
height: 126,
|
||||
background: theme.palette.hero.main,
|
||||
background: theme.palette.background.default,
|
||||
boxShadow: theme.shadows[3],
|
||||
},
|
||||
topInner: {
|
||||
|
@ -1,5 +1,5 @@
|
||||
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"
|
||||
|
||||
export interface HeaderButtonProps {
|
||||
@ -28,10 +28,8 @@ export const HeaderButton: React.FC<HeaderButtonProps> = (props) => {
|
||||
)
|
||||
}
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
const useStyles = makeStyles(() => ({
|
||||
pageButton: {
|
||||
whiteSpace: "nowrap",
|
||||
backgroundColor: lighten(theme.palette.hero.main, 0.1),
|
||||
color: "#B5BFD2",
|
||||
},
|
||||
}))
|
||||
|
@ -9,7 +9,7 @@ export default {
|
||||
|
||||
const Template: Story = (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>
|
||||
)
|
||||
|
||||
|
@ -8,14 +8,11 @@ const useStyles = makeStyles(() => ({
|
||||
maxWidth,
|
||||
padding: `0 ${sidePadding}`,
|
||||
flex: 1,
|
||||
width: "100%",
|
||||
},
|
||||
}))
|
||||
|
||||
export const Margins: React.FC = ({ children }) => {
|
||||
const styles = useStyles()
|
||||
return (
|
||||
<div>
|
||||
<div className={styles.margins}>{children}</div>
|
||||
</div>
|
||||
)
|
||||
return <div className={styles.margins}>{children}</div>
|
||||
}
|
||||
|
@ -21,13 +21,13 @@ export const NavbarView: React.FC<NavbarViewProps> = ({ user, onSignOut, display
|
||||
<nav className={styles.root}>
|
||||
<List className={styles.fixed}>
|
||||
<ListItem className={styles.item}>
|
||||
<NavLink className={styles.logo} to="/">
|
||||
<NavLink className={styles.logo} to="/workspaces">
|
||||
<Logo fill="white" opacity={1} width={125} />
|
||||
</NavLink>
|
||||
</ListItem>
|
||||
<ListItem button className={styles.item}>
|
||||
<NavLink className={styles.link} to="/templates">
|
||||
Templates
|
||||
<NavLink className={styles.link} to="/workspaces">
|
||||
Workspaces
|
||||
</NavLink>
|
||||
</ListItem>
|
||||
</List>
|
||||
@ -47,13 +47,13 @@ const useStyles = makeStyles((theme) => ({
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
height: navHeight,
|
||||
background: theme.palette.navbar.main,
|
||||
background: theme.palette.background.paper,
|
||||
marginTop: 0,
|
||||
transition: "margin 150ms ease",
|
||||
"@media (display-mode: standalone)": {
|
||||
borderTop: `1px solid ${theme.palette.divider}`,
|
||||
},
|
||||
borderBottom: `1px solid #383838`,
|
||||
borderBottom: `1px solid ${theme.palette.divider}`,
|
||||
},
|
||||
fixed: {
|
||||
flex: 0,
|
||||
@ -68,9 +68,9 @@ const useStyles = makeStyles((theme) => ({
|
||||
display: "flex",
|
||||
height: navHeight,
|
||||
paddingLeft: theme.spacing(4),
|
||||
paddingRight: theme.spacing(2),
|
||||
paddingRight: theme.spacing(4),
|
||||
"& svg": {
|
||||
width: 125,
|
||||
width: 109,
|
||||
},
|
||||
},
|
||||
title: {
|
||||
@ -98,18 +98,17 @@ const useStyles = makeStyles((theme) => ({
|
||||
"&.active": {
|
||||
position: "relative",
|
||||
color: theme.palette.primary.contrastText,
|
||||
fontWeight: "bold",
|
||||
|
||||
"&::before": {
|
||||
content: `"{"`,
|
||||
left: 10,
|
||||
content: `" "`,
|
||||
bottom: 0,
|
||||
left: theme.spacing(3),
|
||||
background: "#C16800",
|
||||
right: theme.spacing(3),
|
||||
height: 2,
|
||||
position: "absolute",
|
||||
},
|
||||
|
||||
"&::after": {
|
||||
content: `"}"`,
|
||||
position: "absolute",
|
||||
right: 10,
|
||||
},
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
@ -72,7 +72,7 @@ export const AccountForm: React.FC<AccountFormProps> = ({
|
||||
{error && <FormHelperText error>{error}</FormHelperText>}
|
||||
|
||||
<div>
|
||||
<LoadingButton color="primary" loading={isLoading} type="submit" variant="contained">
|
||||
<LoadingButton loading={isLoading} type="submit" variant="contained">
|
||||
{isLoading ? "" : Language.updateSettings}
|
||||
</LoadingButton>
|
||||
</div>
|
||||
|
@ -113,7 +113,7 @@ export const SignInForm: React.FC<SignInFormProps> = ({
|
||||
{authErrorMessage && <FormHelperText error>{Language.authErrorMessage}</FormHelperText>}
|
||||
{methodsErrorMessage && <FormHelperText error>{Language.methodsErrorMessage}</FormHelperText>}
|
||||
<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}
|
||||
</LoadingButton>
|
||||
</div>
|
||||
@ -121,7 +121,7 @@ export const SignInForm: React.FC<SignInFormProps> = ({
|
||||
{authMethods?.github && (
|
||||
<div className={styles.submitBtn}>
|
||||
<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}
|
||||
</Button>
|
||||
</Link>
|
||||
|
@ -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: [],
|
||||
}
|
@ -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>
|
||||
)
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
import Avatar from "@material-ui/core/Avatar"
|
||||
import { makeStyles } from "@material-ui/core/styles"
|
||||
import React from "react"
|
||||
import { combineClasses } from "../../util/combineClasses"
|
||||
import { firstLetter } from "../../util/firstLetter"
|
||||
|
||||
export interface UserAvatarProps {
|
||||
@ -8,5 +10,17 @@ export interface UserAvatarProps {
|
||||
}
|
||||
|
||||
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}`,
|
||||
},
|
||||
}))
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { action } from "@storybook/addon-actions"
|
||||
import { Story } from "@storybook/react"
|
||||
import React from "react"
|
||||
import { MockOrganization, MockOutdatedWorkspace, MockTemplate, MockWorkspace } from "../../testHelpers/renderHelpers"
|
||||
import { MockOutdatedWorkspace, MockWorkspace } from "../../testHelpers/renderHelpers"
|
||||
import { Workspace, WorkspaceProps } from "./Workspace"
|
||||
|
||||
export default {
|
||||
@ -14,8 +14,6 @@ const Template: Story<WorkspaceProps> = (args) => <Workspace {...args} />
|
||||
|
||||
export const Started = Template.bind({})
|
||||
Started.args = {
|
||||
organization: MockOrganization,
|
||||
template: MockTemplate,
|
||||
workspace: MockWorkspace,
|
||||
handleStart: action("start"),
|
||||
handleStop: action("stop"),
|
||||
|
@ -2,7 +2,7 @@ import { makeStyles } from "@material-ui/core/styles"
|
||||
import Typography from "@material-ui/core/Typography"
|
||||
import React from "react"
|
||||
import * as TypesGen from "../../api/typesGenerated"
|
||||
import { WorkspaceStatus } from "../../pages/WorkspacePage/WorkspacePage"
|
||||
import { WorkspaceStatus } from "../../util/workspace"
|
||||
import { WorkspaceSchedule } from "../WorkspaceSchedule/WorkspaceSchedule"
|
||||
import { WorkspaceSection } from "../WorkspaceSection/WorkspaceSection"
|
||||
import { WorkspaceStatusBar } from "../WorkspaceStatusBar/WorkspaceStatusBar"
|
||||
@ -22,8 +22,6 @@ export interface WorkspaceProps {
|
||||
* Workspace is the top-level component for viewing an individual workspace
|
||||
*/
|
||||
export const Workspace: React.FC<WorkspaceProps> = ({
|
||||
organization,
|
||||
template,
|
||||
workspace,
|
||||
handleStart,
|
||||
handleStop,
|
||||
@ -37,8 +35,6 @@ export const Workspace: React.FC<WorkspaceProps> = ({
|
||||
<div className={styles.root}>
|
||||
<div className={styles.vertical}>
|
||||
<WorkspaceStatusBar
|
||||
organization={organization}
|
||||
template={template}
|
||||
workspace={workspace}
|
||||
handleStart={handleStart}
|
||||
handleStop={handleStop}
|
||||
|
@ -5,9 +5,9 @@ import Typography from "@material-ui/core/Typography"
|
||||
import React from "react"
|
||||
import { Link } from "react-router-dom"
|
||||
import * as TypesGen from "../../api/typesGenerated"
|
||||
import { WorkspaceStatus } from "../../pages/WorkspacePage/WorkspacePage"
|
||||
import { TitleIconSize } from "../../theme/constants"
|
||||
import { combineClasses } from "../../util/combineClasses"
|
||||
import { WorkspaceStatus } from "../../util/workspace"
|
||||
import { Stack } from "../Stack/Stack"
|
||||
import { WorkspaceSection } from "../WorkspaceSection/WorkspaceSection"
|
||||
|
||||
@ -21,6 +21,8 @@ export const Language = {
|
||||
stopped: "Stopped",
|
||||
starting: "Building",
|
||||
stopping: "Stopping",
|
||||
canceled: "Canceled",
|
||||
queued: "Queued",
|
||||
error: "Build Failed",
|
||||
loading: "Loading Status",
|
||||
deleting: "Deleting",
|
||||
@ -46,14 +48,12 @@ export interface WorkspaceStatusBarProps {
|
||||
* so check whether workspace job status has reached completion (whether successful or not).
|
||||
*/
|
||||
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
|
||||
*/
|
||||
export const WorkspaceStatusBar: React.FC<WorkspaceStatusBarProps> = ({
|
||||
organization,
|
||||
template,
|
||||
workspace,
|
||||
handleStart,
|
||||
handleStop,
|
||||
@ -63,7 +63,6 @@ export const WorkspaceStatusBar: React.FC<WorkspaceStatusBarProps> = ({
|
||||
}) => {
|
||||
const styles = useStyles()
|
||||
|
||||
const templateLink = `/templates/${organization?.name}/${template?.name}`
|
||||
const settingsLink = "edit"
|
||||
|
||||
return (
|
||||
@ -75,15 +74,6 @@ export const WorkspaceStatusBar: React.FC<WorkspaceStatusBarProps> = ({
|
||||
{Language.settings}
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{organization && template && (
|
||||
<Typography variant="body2" color="textSecondary">
|
||||
Back to{" "}
|
||||
<Link className={styles.link} to={templateLink}>
|
||||
{template.name}
|
||||
</Link>
|
||||
</Typography>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className={styles.horizontal}>
|
||||
|
@ -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")
|
||||
},
|
||||
}
|
@ -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>
|
||||
)
|
||||
}
|
@ -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,
|
||||
},
|
||||
}))
|
@ -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>
|
||||
)
|
||||
}
|
@ -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>
|
||||
)
|
||||
}
|
@ -56,9 +56,7 @@ describe("Workspace Page", () => {
|
||||
it("shows a workspace", async () => {
|
||||
renderWithAuth(<WorkspacePage />, { route: `/workspaces/${MockWorkspace.id}`, path: "/workspaces/:workspace" })
|
||||
const workspaceName = await screen.findByText(MockWorkspace.name)
|
||||
const templateName = await screen.findByText(MockTemplate.name)
|
||||
expect(workspaceName).toBeDefined()
|
||||
expect(templateName).toBeDefined()
|
||||
})
|
||||
it("shows the status of the workspace", async () => {
|
||||
renderWithAuth(<WorkspacePage />, { route: `/workspaces/${MockWorkspace.id}`, path: "/workspaces/:workspace" })
|
||||
|
@ -7,19 +7,8 @@ import { Margins } from "../../components/Margins/Margins"
|
||||
import { Stack } from "../../components/Stack/Stack"
|
||||
import { Workspace } from "../../components/Workspace/Workspace"
|
||||
import { firstOrItem } from "../../util/array"
|
||||
import { getWorkspaceStatus } from "../../util/workspace"
|
||||
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 = () => {
|
||||
const { workspace: workspaceQueryParam } = useParams()
|
||||
@ -27,9 +16,10 @@ export const WorkspacePage: React.FC = () => {
|
||||
|
||||
const xServices = useContext(XServiceContext)
|
||||
const [workspaceState, workspaceSend] = useActor(xServices.workspaceXService)
|
||||
const { workspace, template, organization, getWorkspaceError, getTemplateError, getOrganizationError } =
|
||||
workspaceState.context
|
||||
const workspaceStatus = useSelector(xServices.workspaceXService, selectWorkspaceStatus)
|
||||
const { workspace, getWorkspaceError, getTemplateError, getOrganizationError } = workspaceState.context
|
||||
const workspaceStatus = useSelector(xServices.workspaceXService, (state) => {
|
||||
return getWorkspaceStatus(state.context.workspace?.latest_build)
|
||||
})
|
||||
|
||||
/**
|
||||
* Get workspace, template, and organization on mount and whenever workspaceId changes.
|
||||
@ -48,8 +38,6 @@ export const WorkspacePage: React.FC = () => {
|
||||
<Margins>
|
||||
<Stack spacing={4}>
|
||||
<Workspace
|
||||
organization={organization}
|
||||
template={template}
|
||||
workspace={workspace}
|
||||
handleStart={() => workspaceSend("START")}
|
||||
handleStop={() => workspaceSend("STOP")}
|
||||
|
37
site/src/pages/WorkspacesPage/WorkspacesPage.test.tsx
Normal file
37
site/src/pages/WorkspacesPage/WorkspacesPage.test.tsx
Normal 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)
|
||||
})
|
||||
})
|
20
site/src/pages/WorkspacesPage/WorkspacesPage.tsx
Normal file
20
site/src/pages/WorkspacesPage/WorkspacesPage.tsx
Normal 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
|
50
site/src/pages/WorkspacesPage/WorkspacesPageView.stories.tsx
Normal file
50
site/src/pages/WorkspacesPage/WorkspacesPageView.stories.tsx
Normal 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 = {}
|
234
site/src/pages/WorkspacesPage/WorkspacesPageView.tsx
Normal file
234
site/src/pages/WorkspacesPage/WorkspacesPageView.tsx
Normal 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>
|
||||
{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,
|
||||
},
|
||||
},
|
||||
}))
|
@ -2,5 +2,5 @@ import React from "react"
|
||||
import { Navigate } from "react-router-dom"
|
||||
|
||||
export const IndexPage: React.FC = () => {
|
||||
return <Navigate to="/templates" replace />
|
||||
return <Navigate to="/workspaces" replace />
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ export const MockWorkspaceAutostopEnabled: TypesGen.UpdateWorkspaceAutostartRequ
|
||||
export const MockWorkspaceBuild: TypesGen.WorkspaceBuild = {
|
||||
after_id: "",
|
||||
before_id: "",
|
||||
created_at: "",
|
||||
created_at: new Date().toDateString(),
|
||||
id: "test-workspace-build",
|
||||
initiator_id: "",
|
||||
job: MockProvisionerJob,
|
||||
|
@ -33,6 +33,9 @@ export const handlers = [
|
||||
rest.post("/api/v2/users/me/workspaces", async (req, res, ctx) => {
|
||||
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) => {
|
||||
return res(ctx.status(200), ctx.json([M.MockOrganization]))
|
||||
}),
|
||||
|
@ -2,11 +2,11 @@ export const spacing = 8
|
||||
export const borderRadius = 4
|
||||
export const buttonBorderWidth = 2
|
||||
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 lightButtonShadow = "0 2px 2px rgba(0, 23, 121, 0.08)"
|
||||
export const emptyBoxShadow = "none"
|
||||
export const navHeight = 56
|
||||
export const navHeight = 42
|
||||
export const maxWidth = 1380
|
||||
export const sidePadding = "50px"
|
||||
export const TitleIconSize = 48
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Monospace fonts used for code, button styles, and banners
|
||||
import "@fontsource/fira-code/400.css"
|
||||
import "@fontsource/fira-code/600.css"
|
||||
import "@fontsource/ibm-plex-mono/400.css"
|
||||
import "@fontsource/ibm-plex-mono/600.css"
|
||||
// Main body copy font
|
||||
import "@fontsource/inter/300.css"
|
||||
import "@fontsource/inter/400.css"
|
||||
|
@ -1 +1 @@
|
||||
export { dark, light } from "./theme"
|
||||
export { dark } from "./theme"
|
||||
|
@ -1,561 +1,84 @@
|
||||
import { darken, fade } from "@material-ui/core/styles/colorManipulator"
|
||||
import { Breakpoints } from "@material-ui/core/styles/createBreakpoints"
|
||||
import {
|
||||
BODY_FONT_FAMILY,
|
||||
borderRadius,
|
||||
buttonBorderWidth,
|
||||
emptyBoxShadow,
|
||||
lightButtonShadow,
|
||||
spacing,
|
||||
} from "./constants"
|
||||
import { CustomPalette } from "./palettes"
|
||||
import { typography } from "./typography"
|
||||
import { PaletteOptions, SimplePaletteColorOptions } from "@material-ui/core/styles/createPalette"
|
||||
import { MONOSPACE_FONT_FAMILY } from "./constants"
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
export const getOverrides = (palette: CustomPalette, breakpoints: Breakpoints) => {
|
||||
const containedButtonShadow = palette.type === "dark" ? emptyBoxShadow : lightButtonShadow
|
||||
export const getOverrides = (palette: PaletteOptions) => {
|
||||
return {
|
||||
MuiAvatar: {
|
||||
root: {
|
||||
width: 32,
|
||||
height: 32,
|
||||
fontSize: 24,
|
||||
border: `1px solid ${palette.divider}`,
|
||||
},
|
||||
},
|
||||
MuiTable: {
|
||||
MuiButton: {
|
||||
root: {
|
||||
backgroundColor: palette.background.paper,
|
||||
borderRadius: borderRadius * 2,
|
||||
boxShadow: `0 0 0 1px ${palette.action.hover}`,
|
||||
|
||||
"&.is-inline": {
|
||||
background: "none",
|
||||
borderRadius: 0,
|
||||
// Prevents a loading button from collapsing!
|
||||
minHeight: 42,
|
||||
fontWeight: "regular",
|
||||
fontFamily: MONOSPACE_FONT_FAMILY,
|
||||
fontSize: 16,
|
||||
textTransform: "none",
|
||||
letterSpacing: "none",
|
||||
border: `1px solid ${palette.divider}`,
|
||||
},
|
||||
contained: {
|
||||
boxShadow: "none",
|
||||
color: palette.text?.primary,
|
||||
backgroundColor: "#151515",
|
||||
"&:hover": {
|
||||
boxShadow: "none",
|
||||
backgroundColor: "#000000",
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiTableHead: {
|
||||
root: {
|
||||
"& .MuiTableCell-root": {
|
||||
...typography.overline,
|
||||
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": {
|
||||
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,
|
||||
},
|
||||
},
|
||||
fontFamily: MONOSPACE_FONT_FAMILY,
|
||||
textTransform: "uppercase",
|
||||
},
|
||||
},
|
||||
MuiTableSortLabel: {
|
||||
MuiTable: {
|
||||
root: {
|
||||
lineHeight: "20px",
|
||||
|
||||
"&$active": {
|
||||
"&& $icon": {
|
||||
color: palette.text.primary,
|
||||
},
|
||||
},
|
||||
},
|
||||
icon: {
|
||||
"&.MuiSvgIcon-root": {
|
||||
width: 18,
|
||||
height: 18,
|
||||
marginLeft: 2,
|
||||
},
|
||||
// Gives the appearance of a border!
|
||||
borderRadius: 2,
|
||||
border: `1px solid ${palette.divider}`,
|
||||
},
|
||||
},
|
||||
MuiTableCell: {
|
||||
head: {
|
||||
color: palette.text?.secondary,
|
||||
},
|
||||
root: {
|
||||
"&:first-child": {
|
||||
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,
|
||||
fontFamily: MONOSPACE_FONT_FAMILY,
|
||||
fontSize: 16,
|
||||
[breakpoints.up("sm")]: {
|
||||
minHeight: 48,
|
||||
background: palette.background?.paper,
|
||||
borderBottom: `1px solid ${palette.divider}`,
|
||||
padding: 8,
|
||||
"&:first-child": {
|
||||
paddingLeft: 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,
|
||||
"&:last-child": {
|
||||
paddingRight: 32,
|
||||
},
|
||||
},
|
||||
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: {
|
||||
root: {
|
||||
minHeight: 40,
|
||||
background: palette.background.paper,
|
||||
marginTop: "12px",
|
||||
borderRadius,
|
||||
|
||||
"&$disabled": {
|
||||
background: palette.action.disabledBackground,
|
||||
},
|
||||
|
||||
"&$focused .MuiSelect-icon": {
|
||||
color: palette.primary.light,
|
||||
},
|
||||
},
|
||||
|
||||
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,
|
||||
},
|
||||
borderRadius: 2,
|
||||
},
|
||||
},
|
||||
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: {
|
||||
MuiOutlinedInput: {
|
||||
root: {
|
||||
fontSize: 16,
|
||||
fontWeight: 500,
|
||||
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,
|
||||
"& input:-webkit-autofill": {
|
||||
WebkitBoxShadow: `0 0 0 1000px ${palette.background?.paper} inset`,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiSelect: {
|
||||
MuiLink: {
|
||||
root: {
|
||||
// Matches MuiInputBase-input height
|
||||
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,
|
||||
},
|
||||
},
|
||||
color: (palette.primary as SimplePaletteColorOptions).light,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -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
|
||||
*/
|
||||
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
|
||||
@ -175,52 +10,31 @@ export const lightPalette: CustomPalette = {
|
||||
* This maps to our design system at:
|
||||
* https://www.figma.com/file/VkXU4873QOsSprMQV02GgR/Design-System?node-id=219%3A40
|
||||
*/
|
||||
export const darkPalette: CustomPalette = {
|
||||
export const darkPalette: PaletteOptions = {
|
||||
type: "dark",
|
||||
primary: lightPalette.primary,
|
||||
secondary: lightPalette.secondary,
|
||||
info: lightPalette.info,
|
||||
error: lightPalette.error,
|
||||
codeBlock: {
|
||||
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",
|
||||
},
|
||||
primary: {
|
||||
main: "#409BF4",
|
||||
contrastText: "#f8f8f8",
|
||||
light: "#79B8FF",
|
||||
dark: "#1976D2",
|
||||
},
|
||||
confirmDialog: {
|
||||
error: lightPalette.confirmDialog.error,
|
||||
info: {
|
||||
background: "rgba(255, 255, 255, 0.95)",
|
||||
text: "rgb(31, 33, 35)",
|
||||
},
|
||||
},
|
||||
hero: {
|
||||
main: "#141414",
|
||||
button: "#333333",
|
||||
},
|
||||
navbar: {
|
||||
main: "rgb(8, 9, 10)",
|
||||
secondary: {
|
||||
main: "#008510",
|
||||
contrastText: "#f8f8f8",
|
||||
},
|
||||
background: {
|
||||
default: "rgb(24, 26, 27)",
|
||||
paper: "rgb(31, 33, 35)",
|
||||
default: "#1F1F1F",
|
||||
paper: "#292929",
|
||||
},
|
||||
text: {
|
||||
primary: "rgba(255, 255, 255, 0.95)",
|
||||
secondary: "#BDBDBD",
|
||||
disabled: "#BDBDBD",
|
||||
hint: "#BDBDBD",
|
||||
primary: "#F8F8F8",
|
||||
secondary: "#C1C1C1",
|
||||
},
|
||||
action: {
|
||||
active: "#FFF",
|
||||
hover: "rgba(255, 255, 255, 0.1)",
|
||||
hoverOpacity: 0.1,
|
||||
selected: "rgba(255, 255, 255, 0.2)",
|
||||
disabled: "rgba(255, 255, 255, 0.1)",
|
||||
disabledBackground: "rgba(255, 255, 255, 0.12)",
|
||||
divider: "#383838",
|
||||
warning: {
|
||||
main: "#C16800",
|
||||
},
|
||||
success: {
|
||||
main: "#6BBE00",
|
||||
},
|
||||
divider: "rgba(255, 255, 255, 0.12)",
|
||||
}
|
||||
|
@ -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.
|
||||
*/
|
||||
export const props = {
|
||||
MuiButtonBase: {
|
||||
disableRipple: true,
|
||||
},
|
||||
MuiButton: {
|
||||
variant: "contained",
|
||||
},
|
||||
MuiTextField: {
|
||||
margin: "dense",
|
||||
InputProps: {
|
||||
labelWidth: 0,
|
||||
},
|
||||
variant: "outlined",
|
||||
spellCheck: false,
|
||||
},
|
||||
MuiInputLabel: {
|
||||
shrink: true,
|
||||
},
|
||||
MuiFormControl: {
|
||||
variant: "outlined",
|
||||
margin: "dense",
|
||||
},
|
||||
MuiInput: {
|
||||
spellCheck: false,
|
||||
autoCorrect: "off",
|
||||
},
|
||||
MuiOutlinedInput: {
|
||||
notched: false,
|
||||
},
|
||||
MuiDialogTitle: {
|
||||
disableTypography: true,
|
||||
},
|
||||
MuiMenu: {
|
||||
anchorOrigin: {
|
||||
vertical: "bottom",
|
||||
@ -51,7 +38,4 @@ export const props = {
|
||||
textColor: "primary",
|
||||
indicatorColor: "primary",
|
||||
},
|
||||
MuiTab: {
|
||||
disableTouchRipple: true,
|
||||
},
|
||||
} as ComponentsProps
|
||||
|
@ -1,15 +1,13 @@
|
||||
import { createMuiTheme } from "@material-ui/core/styles"
|
||||
import { PaletteOptions } from "@material-ui/core/styles/createPalette"
|
||||
import { Overrides } from "@material-ui/core/styles/overrides"
|
||||
import { borderRadius } from "./constants"
|
||||
import { getOverrides } from "./overrides"
|
||||
import { CustomPalette, darkPalette, lightPalette } from "./palettes"
|
||||
import { darkPalette } from "./palettes"
|
||||
import { props } from "./props"
|
||||
import { typography } from "./typography"
|
||||
|
||||
const makeTheme = (palette: CustomPalette) => {
|
||||
// Grab defaults to re-use in overrides
|
||||
const { breakpoints } = createMuiTheme()
|
||||
|
||||
const makeTheme = (palette: PaletteOptions) => {
|
||||
return createMuiTheme({
|
||||
palette,
|
||||
typography,
|
||||
@ -17,9 +15,8 @@ const makeTheme = (palette: CustomPalette) => {
|
||||
borderRadius,
|
||||
},
|
||||
props,
|
||||
overrides: getOverrides(palette, breakpoints) as Overrides,
|
||||
overrides: getOverrides(palette) as Overrides,
|
||||
})
|
||||
}
|
||||
|
||||
export const light = makeTheme(lightPalette)
|
||||
export const dark = makeTheme(darkPalette)
|
||||
|
@ -1,7 +1,18 @@
|
||||
import { State } from "xstate"
|
||||
import { WorkspaceBuildTransition } from "../../api/types"
|
||||
import { WorkspaceStatus } from "../../pages/WorkspacePage/WorkspacePage"
|
||||
import { WorkspaceContext, WorkspaceEvent } from "./workspaceXService"
|
||||
import { WorkspaceBuildTransition } from "../api/types"
|
||||
import { WorkspaceBuild } from "../api/typesGenerated"
|
||||
|
||||
export type WorkspaceStatus =
|
||||
| "queued"
|
||||
| "started"
|
||||
| "starting"
|
||||
| "stopped"
|
||||
| "stopping"
|
||||
| "error"
|
||||
| "loading"
|
||||
| "deleting"
|
||||
| "deleted"
|
||||
| "canceled"
|
||||
| "canceling"
|
||||
|
||||
const inProgressToStatus: Record<WorkspaceBuildTransition, WorkspaceStatus> = {
|
||||
start: "starting",
|
||||
@ -15,22 +26,23 @@ const succeededToStatus: Record<WorkspaceBuildTransition, WorkspaceStatus> = {
|
||||
delete: "deleted",
|
||||
}
|
||||
|
||||
export const selectWorkspaceStatus = (state: State<WorkspaceContext, WorkspaceEvent>): WorkspaceStatus => {
|
||||
const transition = state.context.workspace?.latest_build.transition as WorkspaceBuildTransition
|
||||
const jobStatus = state.context.workspace?.latest_build.job.status
|
||||
// Converts a workspaces status to a human-readable form.
|
||||
export const getWorkspaceStatus = (workspaceBuild?: WorkspaceBuild): WorkspaceStatus => {
|
||||
const transition = workspaceBuild?.transition as WorkspaceBuildTransition
|
||||
const jobStatus = workspaceBuild?.job.status
|
||||
switch (jobStatus) {
|
||||
case undefined:
|
||||
return "loading"
|
||||
case "succeeded":
|
||||
return succeededToStatus[transition]
|
||||
case "pending":
|
||||
return inProgressToStatus[transition]
|
||||
return "queued"
|
||||
case "running":
|
||||
return inProgressToStatus[transition]
|
||||
case "canceling":
|
||||
return "canceling"
|
||||
case "canceled":
|
||||
return "error"
|
||||
return "canceled"
|
||||
case "failed":
|
||||
return "error"
|
||||
}
|
61
site/src/xServices/workspaces/workspacesXService.ts
Normal file
61
site/src/xServices/workspaces/workspacesXService.ts
Normal 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(),
|
||||
},
|
||||
},
|
||||
)
|
@ -63,6 +63,7 @@ const config: Configuration = {
|
||||
"/api": {
|
||||
target: "http://localhost:3000",
|
||||
ws: true,
|
||||
secure: false,
|
||||
},
|
||||
},
|
||||
static: ["./static"],
|
||||
|
467
site/yarn.lock
467
site/yarn.lock
@ -1269,10 +1269,10 @@
|
||||
minimatch "^3.0.4"
|
||||
strip-json-comments "^3.1.1"
|
||||
|
||||
"@fontsource/fira-code@4.5.9":
|
||||
"@fontsource/ibm-plex-mono@4.5.9":
|
||||
version "4.5.9"
|
||||
resolved "https://registry.yarnpkg.com/@fontsource/fira-code/-/fira-code-4.5.9.tgz#8ca3e6020f9d3c340a643c5c0a12b2ebf37dc7a6"
|
||||
integrity sha512-moi9UVTOfQFXjiUAITy5W727dIP6c0K5TGPN+wTaFHn+/5flc/V0Uq9cKTs39yGrPUOneTbuAe8C8q7CzUP4Aw==
|
||||
resolved "https://registry.yarnpkg.com/@fontsource/ibm-plex-mono/-/ibm-plex-mono-4.5.9.tgz#96968bebc4b1ea559818a9c52c87b3854a8145ba"
|
||||
integrity sha512-goblhmAX48GELIUQnWBg6AKVZklcTUu6NwF8tRiIzlxTZuOspbzHrW/3sF3WOH6+mJVay9n6QLbbikOfxSRekQ==
|
||||
|
||||
"@fontsource/inter@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"
|
||||
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":
|
||||
version "1.1.0"
|
||||
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"
|
||||
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":
|
||||
version "1.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d"
|
||||
@ -1934,18 +1871,6 @@
|
||||
lodash "^4.17.21"
|
||||
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":
|
||||
version "6.4.22"
|
||||
resolved "https://registry.yarnpkg.com/@storybook/addon-docs/-/addon-docs-6.4.22.tgz#19f22ede8ae31291069af7ab5abbc23fa269012b"
|
||||
@ -2095,7 +2020,7 @@
|
||||
prop-types "^15.7.2"
|
||||
regenerator-runtime "^0.13.7"
|
||||
|
||||
"@storybook/addons@6.4.22", "@storybook/addons@^6.1.18":
|
||||
"@storybook/addons@6.4.22":
|
||||
version "6.4.22"
|
||||
resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-6.4.22.tgz#e165407ca132c2182de2d466b7ff7c5644b6ad7b"
|
||||
integrity sha512-P/R+Jsxh7pawKLYo8MtE3QU/ilRFKbtCewV/T1o5U/gm8v7hKQdFz3YdRMAra4QuCY8bQIp7MKd2HrB5aH5a1A==
|
||||
@ -2388,7 +2313,7 @@
|
||||
util-deprecate "^1.0.2"
|
||||
webpack "4"
|
||||
|
||||
"@storybook/core-events@6.4.22", "@storybook/core-events@^6.1.18":
|
||||
"@storybook/core-events@6.4.22":
|
||||
version "6.4.22"
|
||||
resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-6.4.22.tgz#c09b0571951affd4254028b8958a4d8652700989"
|
||||
integrity sha512-5GYY5+1gd58Gxjqex27RVaX6qbfIQmJxcbzbNpXGNSqwqAuIIepcV1rdCVm6I4C3Yb7/AQ3cN5dVbf33QxRIwA==
|
||||
@ -2668,7 +2593,7 @@
|
||||
ts-dedent "^2.0.0"
|
||||
util-deprecate "^1.0.2"
|
||||
|
||||
"@storybook/theming@6.4.22", "@storybook/theming@^6.1.18":
|
||||
"@storybook/theming@6.4.22":
|
||||
version "6.4.22"
|
||||
resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-6.4.22.tgz#19097eec0366447ddd0d6917b0e0f81d0ec5e51e"
|
||||
integrity sha512-NVMKH/jxSPtnMTO4VCN1k47uztq+u9fWv4GSnzq/eezxdGg9ceGL4/lCrNGoNajht9xbrsZ4QvsJ/V2sVGM8wA==
|
||||
@ -3375,17 +3300,6 @@
|
||||
"@typescript-eslint/types" "5.23.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":
|
||||
version "1.11.1"
|
||||
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"
|
||||
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:
|
||||
version "5.4.1"
|
||||
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-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:
|
||||
version "4.4.0"
|
||||
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"
|
||||
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:
|
||||
version "1.5.1"
|
||||
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"
|
||||
object-visit "^1.0.0"
|
||||
|
||||
color-convert@^1.9.0, color-convert@^1.9.3:
|
||||
color-convert@^1.9.0:
|
||||
version "1.9.3"
|
||||
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
|
||||
integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
|
||||
@ -5115,69 +5014,21 @@ color-convert@^2.0.1:
|
||||
dependencies:
|
||||
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:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
|
||||
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"
|
||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
||||
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:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2"
|
||||
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:
|
||||
version "2.9.2"
|
||||
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"
|
||||
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:
|
||||
version "6.0.5"
|
||||
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"
|
||||
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:
|
||||
version "6.1.4"
|
||||
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-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:
|
||||
version "2.6.9"
|
||||
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"
|
||||
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:
|
||||
version "0.1.4"
|
||||
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:
|
||||
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"
|
||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3"
|
||||
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"
|
||||
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"
|
||||
resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.2.tgz#9234c54aba713486d7ebde0220864af5e2b283f7"
|
||||
integrity sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ==
|
||||
@ -6883,31 +6706,6 @@ fb-watchman@^2.0.0:
|
||||
dependencies:
|
||||
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:
|
||||
version "1.1.0"
|
||||
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"
|
||||
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:
|
||||
version "3.2.5"
|
||||
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"
|
||||
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:
|
||||
version "1.14.8"
|
||||
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"
|
||||
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:
|
||||
version "2.0.0"
|
||||
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"
|
||||
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"
|
||||
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6"
|
||||
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"
|
||||
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:
|
||||
version "10.7.3"
|
||||
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"
|
||||
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:
|
||||
version "2.0.1"
|
||||
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-decimal "^1.0.0"
|
||||
|
||||
is-arguments@^1.0.4, is-arguments@^1.1.0:
|
||||
is-arguments@^1.1.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b"
|
||||
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"
|
||||
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:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3"
|
||||
@ -8166,18 +7926,6 @@ is-ci@^2.0.0:
|
||||
dependencies:
|
||||
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:
|
||||
version "2.8.1"
|
||||
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:
|
||||
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"
|
||||
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f"
|
||||
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"
|
||||
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"
|
||||
resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127"
|
||||
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"
|
||||
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"
|
||||
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958"
|
||||
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"
|
||||
has-tostringtag "^1.0.0"
|
||||
|
||||
is-set@^2.0.1, is-set@^2.0.2:
|
||||
is-set@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.2.tgz#90755fa4c2562dc1c5d4024760d6119b94ca18ec"
|
||||
integrity sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==
|
||||
@ -8416,17 +8164,6 @@ is-symbol@^1.0.2, is-symbol@^1.0.3:
|
||||
dependencies:
|
||||
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:
|
||||
version "1.0.0"
|
||||
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"
|
||||
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:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2"
|
||||
@ -8449,14 +8181,6 @@ is-weakref@^1.0.1:
|
||||
dependencies:
|
||||
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:
|
||||
version "1.0.4"
|
||||
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:
|
||||
p-locate "^5.0.0"
|
||||
|
||||
lodash-es@^4.17.15, lodash-es@^4.17.21:
|
||||
lodash-es@^4.17.21:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
|
||||
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:
|
||||
version "4.0.8"
|
||||
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
||||
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:
|
||||
version "4.1.2"
|
||||
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"
|
||||
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"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
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"
|
||||
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:
|
||||
version "1.3.5"
|
||||
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"
|
||||
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:
|
||||
version "0.6.3"
|
||||
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
|
||||
@ -10082,7 +9786,7 @@ node-dir@^0.1.10:
|
||||
dependencies:
|
||||
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"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
|
||||
integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
|
||||
@ -10206,7 +9910,7 @@ nwsapi@^2.2.0:
|
||||
resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7"
|
||||
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"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
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"
|
||||
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:
|
||||
version "1.1.1"
|
||||
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"
|
||||
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:
|
||||
version "2.4.2"
|
||||
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"
|
||||
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"
|
||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
|
||||
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"
|
||||
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:
|
||||
version "6.9.7"
|
||||
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"
|
||||
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:
|
||||
version "5.5.1"
|
||||
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"
|
||||
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:
|
||||
version "8.3.3"
|
||||
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"
|
||||
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:
|
||||
version "7.0.1"
|
||||
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"
|
||||
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"
|
||||
resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz#b3f4c0059af9e47eca9f3f660e51d81307e72307"
|
||||
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"
|
||||
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:
|
||||
version "3.0.2"
|
||||
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"
|
||||
split-string "^3.0.1"
|
||||
|
||||
setimmediate@^1.0.4, setimmediate@^1.0.5:
|
||||
setimmediate@^1.0.4:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
|
||||
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"
|
||||
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
|
||||
|
||||
side-channel@^1.0.3, side-channel@^1.0.4:
|
||||
side-channel@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
|
||||
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"
|
||||
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:
|
||||
version "1.0.19"
|
||||
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"
|
||||
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:
|
||||
version "0.0.33"
|
||||
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"
|
||||
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:
|
||||
version "3.15.1"
|
||||
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"
|
||||
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"
|
||||
resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
|
||||
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-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:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
|
||||
|
Reference in New Issue
Block a user