From 5a61d3f2280c5a5c5c42115f5117dc59bd0bf323 Mon Sep 17 00:00:00 2001 From: Jaayden Halko Date: Mon, 19 Aug 2024 17:56:49 +0000 Subject: [PATCH 01/11] feat: add resource-action pills to custom roles table --- .../CustomRolesPage/CustomRolesPageView.tsx | 128 +++++++++++++++++- site/src/theme/dark/index.ts | 2 + site/src/theme/dark/permission.ts | 8 ++ site/src/theme/darkBlue/index.ts | 2 + site/src/theme/darkBlue/permission.ts | 8 ++ site/src/theme/index.ts | 1 + site/src/theme/light/index.ts | 2 + site/src/theme/light/permission.ts | 8 ++ site/src/theme/permission.ts | 5 + 9 files changed, 157 insertions(+), 7 deletions(-) create mode 100644 site/src/theme/dark/permission.ts create mode 100644 site/src/theme/darkBlue/permission.ts create mode 100644 site/src/theme/light/permission.ts create mode 100644 site/src/theme/permission.ts diff --git a/site/src/pages/ManagementSettingsPage/CustomRolesPage/CustomRolesPageView.tsx b/site/src/pages/ManagementSettingsPage/CustomRolesPage/CustomRolesPageView.tsx index 15d9c3773b3b5..32d66db9bae46 100644 --- a/site/src/pages/ManagementSettingsPage/CustomRolesPage/CustomRolesPageView.tsx +++ b/site/src/pages/ManagementSettingsPage/CustomRolesPage/CustomRolesPageView.tsx @@ -1,14 +1,15 @@ -import type { Interpolation, Theme } from "@emotion/react"; +import { type Interpolation, type Theme, useTheme } from "@emotion/react"; import AddOutlined from "@mui/icons-material/AddOutlined"; import Button from "@mui/material/Button"; import Skeleton from "@mui/material/Skeleton"; +import Stack from "@mui/material/Stack"; import Table from "@mui/material/Table"; import TableBody from "@mui/material/TableBody"; import TableCell from "@mui/material/TableCell"; import TableContainer from "@mui/material/TableContainer"; import TableHead from "@mui/material/TableHead"; import TableRow from "@mui/material/TableRow"; -import type { Role } from "api/typesGenerated"; +import type { Permission, Role } from "api/typesGenerated"; import { ChooseOne, Cond } from "components/Conditionals/ChooseOne"; import { EmptyState } from "components/EmptyState/EmptyState"; import { @@ -19,6 +20,12 @@ import { ThreeDotsButton, } from "components/MoreMenu/MoreMenu"; import { Paywall } from "components/Paywall/Paywall"; +import { Pill } from "components/Pill/Pill"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "components/Popover/Popover"; import { TableLoaderSkeleton, TableRowSkeleton, @@ -42,7 +49,6 @@ export const CustomRolesPageView: FC = ({ }) => { const isLoading = roles === undefined; const isEmpty = Boolean(roles && roles.length === 0); - return ( <> @@ -58,8 +64,8 @@ export const CustomRolesPageView: FC = ({ - Name - Permissions + Name + Permissions @@ -116,6 +122,10 @@ export const CustomRolesPageView: FC = ({ ); }; +function getUniqueResourceTypes(jsonObject: readonly Permission[]) { + const resourceTypes = jsonObject.map((item) => item.resource_type); + return [...new Set(resourceTypes)]; +} interface RoleRowProps { role: Role; onDelete: () => void; @@ -125,12 +135,28 @@ interface RoleRowProps { const RoleRow: FC = ({ role, onDelete, canAssignOrgRole }) => { const navigate = useNavigate(); + const resourceTypes: string[] = getUniqueResourceTypes( + role.organization_permissions, + ); + return ( {role.display_name || role.name} - - {role.organization_permissions.length} + + + + + {resourceTypes.length > 1 && ( + + )} + @@ -176,10 +202,98 @@ const TableLoader = () => { ); }; +interface PermissionPillProps { + resource: string; + permissions: readonly Permission[]; +} + +const PermissionsPill: FC = ({ + resource, + permissions, +}) => { + const actions = permissions.filter((p) => { + if (resource === p.resource_type) { + return p.action; + } + }); + + return ( + + {resource}: {actions.map((p) => p.action).join(", ")} + + ); +}; + +type OverflowPermissionPillProps = { + resources: string[]; + permissions: readonly Permission[]; +}; + +const OverflowPermissionPill: FC = ({ + resources, + permissions, +}) => { + const theme = useTheme(); + + return ( + + + + +{resources.length} more + + + + + {resources.map((resource) => ( + + ))} + + + ); +}; + const styles = { secondary: (theme) => ({ color: theme.palette.text.secondary, }), + permissionPill: (theme) => ({ + backgroundColor: theme.permission.background, + borderColor: theme.permission.outline, + color: theme.permission.text, + width: "fit-content", + }), } satisfies Record>; export default CustomRolesPageView; diff --git a/site/src/theme/dark/index.ts b/site/src/theme/dark/index.ts index d9644e7494a08..1e8e8ec3a68e5 100644 --- a/site/src/theme/dark/index.ts +++ b/site/src/theme/dark/index.ts @@ -2,6 +2,7 @@ import { forDarkThemes } from "../externalImages"; import experimental from "./experimental"; import monaco from "./monaco"; import muiTheme from "./mui"; +import permission from "./permission"; import roles from "./roles"; export default { @@ -10,4 +11,5 @@ export default { experimental, monaco, roles, + permission, }; diff --git a/site/src/theme/dark/permission.ts b/site/src/theme/dark/permission.ts new file mode 100644 index 0000000000000..1c454f98757c4 --- /dev/null +++ b/site/src/theme/dark/permission.ts @@ -0,0 +1,8 @@ +import type { Permission } from "../permission"; +import colors from "../tailwindColors"; + +export default { + background: colors.zinc[800], + outline: colors.zinc[700], + text: colors.zinc[200], +} satisfies Permission; diff --git a/site/src/theme/darkBlue/index.ts b/site/src/theme/darkBlue/index.ts index d9644e7494a08..1e8e8ec3a68e5 100644 --- a/site/src/theme/darkBlue/index.ts +++ b/site/src/theme/darkBlue/index.ts @@ -2,6 +2,7 @@ import { forDarkThemes } from "../externalImages"; import experimental from "./experimental"; import monaco from "./monaco"; import muiTheme from "./mui"; +import permission from "./permission"; import roles from "./roles"; export default { @@ -10,4 +11,5 @@ export default { experimental, monaco, roles, + permission, }; diff --git a/site/src/theme/darkBlue/permission.ts b/site/src/theme/darkBlue/permission.ts new file mode 100644 index 0000000000000..9434a1f8b9449 --- /dev/null +++ b/site/src/theme/darkBlue/permission.ts @@ -0,0 +1,8 @@ +import type { Permission } from "../permission"; +import colors from "../tailwindColors"; + +export default { + background: colors.gray[800], + outline: colors.gray[700], + text: colors.gray[200], +} satisfies Permission; diff --git a/site/src/theme/index.ts b/site/src/theme/index.ts index f161ec88cfb64..dd2f21883ab34 100644 --- a/site/src/theme/index.ts +++ b/site/src/theme/index.ts @@ -6,6 +6,7 @@ import darkBlue from "./darkBlue"; import type { NewTheme } from "./experimental"; import type { ExternalImageModeStyles } from "./externalImages"; import light from "./light"; +import type { Permission } from "./permission"; import type { Roles } from "./roles"; export interface Theme extends Omit { diff --git a/site/src/theme/light/index.ts b/site/src/theme/light/index.ts index 466ff8d6fb6b9..2d7920270655f 100644 --- a/site/src/theme/light/index.ts +++ b/site/src/theme/light/index.ts @@ -2,6 +2,7 @@ import { forLightThemes } from "../externalImages"; import experimental from "./experimental"; import monaco from "./monaco"; import muiTheme from "./mui"; +import permission from "./permission"; import roles from "./roles"; export default { @@ -10,4 +11,5 @@ export default { experimental, monaco, roles, + permission, }; diff --git a/site/src/theme/light/permission.ts b/site/src/theme/light/permission.ts new file mode 100644 index 0000000000000..8796be5821054 --- /dev/null +++ b/site/src/theme/light/permission.ts @@ -0,0 +1,8 @@ +import type { Permission } from "../permission"; +import colors from "../tailwindColors"; + +export default { + background: colors.zinc[200], + outline: colors.zinc[300], + text: colors.zinc[700], +} satisfies Permission; diff --git a/site/src/theme/permission.ts b/site/src/theme/permission.ts new file mode 100644 index 0000000000000..2bcfc60fd0465 --- /dev/null +++ b/site/src/theme/permission.ts @@ -0,0 +1,5 @@ +export interface Permission { + background: string; + outline: string; + text: string; +} From 83c5b099e88f5c1ddbb2c3386417945a256e248e Mon Sep 17 00:00:00 2001 From: Jaayden Halko Date: Wed, 21 Aug 2024 15:26:44 +0000 Subject: [PATCH 02/11] fix: remove permission from theme and change name to colorRoles --- .../ActiveUserChart/ActiveUserChart.tsx | 6 +-- site/src/components/Badges/Badges.tsx | 48 +++++++++---------- .../Dialogs/DeleteDialog/DeleteDialog.tsx | 6 +-- site/src/components/Dialogs/Dialog.tsx | 16 +++---- .../components/HelpTooltip/HelpTooltip.tsx | 2 +- .../components/InfoTooltip/InfoTooltip.tsx | 4 +- site/src/components/LastSeen/LastSeen.tsx | 6 +-- site/src/components/Logs/LogLine.tsx | 18 +++---- .../PaginationWidget/PageButtons.tsx | 8 ++-- site/src/components/Paywall/Paywall.tsx | 6 +-- .../src/components/Paywall/PopoverPaywall.tsx | 6 +-- site/src/components/Pill/Pill.tsx | 4 +- .../RichParameterInput/RichParameterInput.tsx | 2 +- .../StatusIndicator/StatusIndicator.tsx | 4 +- .../DeploymentBanner/DeploymentBannerView.tsx | 2 +- .../LicenseBanner/LicenseBannerView.tsx | 4 +- site/src/modules/resources/AgentMetadata.tsx | 2 +- site/src/modules/resources/XRayScanAlert.tsx | 6 +-- .../TemplateExampleCard.tsx | 4 +- .../TemplateFiles/TemplateFileTree.tsx | 4 +- .../templates/TemplateFiles/TemplateFiles.tsx | 6 ++- .../WorkspaceOutdatedTooltip.tsx | 2 +- .../AuditPage/AuditLogRow/AuditLogRow.tsx | 2 +- .../CreateTemplatePage/BuildLogsDrawer.tsx | 2 +- .../CreateWorkspacePageView.tsx | 2 +- .../AnnouncementBannerItem.tsx | 2 +- site/src/pages/DeploySettingsPage/Option.tsx | 4 +- site/src/pages/HealthPage/DERPRegionPage.tsx | 4 +- .../CustomRolesPage/CustomRolesPageView.tsx | 6 +-- .../OrganizationMembersPageView.tsx | 8 ++-- .../OrganizationSettingsPageView.tsx | 20 ++++---- .../UserTable/UserRoleCell.tsx | 8 ++-- .../TemplateInsightsPage.tsx | 5 +- .../TemplateVersionEditor.tsx | 2 +- .../TemplateVersionStatusBadge.tsx | 2 +- .../AppearancePage/AppearanceForm.tsx | 2 +- .../WorkspaceBuildPageView.tsx | 2 +- .../WorkspaceDeleteDialog.tsx | 10 ++-- .../WorkspaceNotifications/Notifications.tsx | 10 ++-- .../WorkspaceScheduleControls.tsx | 2 +- .../BatchUpdateConfirmation.tsx | 2 +- site/src/pages/WorkspacesPage/LastUsed.tsx | 6 +-- site/src/theme/{roles.ts => colorRoles.ts} | 37 +++++++------- .../theme/dark/{roles.ts => colorRoles.ts} | 14 +++++- site/src/theme/dark/index.ts | 6 +-- site/src/theme/dark/permission.ts | 8 ---- .../darkBlue/{roles.ts => colorRoles.ts} | 14 +++++- site/src/theme/darkBlue/index.ts | 6 +-- site/src/theme/darkBlue/permission.ts | 8 ---- site/src/theme/experimental.ts | 6 +-- site/src/theme/index.ts | 5 +- .../theme/light/{roles.ts => colorRoles.ts} | 14 +++++- site/src/theme/light/index.ts | 6 +-- site/src/theme/light/permission.ts | 8 ---- site/src/theme/permission.ts | 5 -- site/src/utils/latency.ts | 6 +-- site/src/utils/workspace.tsx | 12 ++--- 57 files changed, 214 insertions(+), 208 deletions(-) rename site/src/theme/{roles.ts => colorRoles.ts} (76%) rename site/src/theme/dark/{roles.ts => colorRoles.ts} (91%) delete mode 100644 site/src/theme/dark/permission.ts rename site/src/theme/darkBlue/{roles.ts => colorRoles.ts} (91%) delete mode 100644 site/src/theme/darkBlue/permission.ts rename site/src/theme/light/{roles.ts => colorRoles.ts} (91%) delete mode 100644 site/src/theme/light/permission.ts delete mode 100644 site/src/theme/permission.ts diff --git a/site/src/components/ActiveUserChart/ActiveUserChart.tsx b/site/src/components/ActiveUserChart/ActiveUserChart.tsx index f1695b0641cc5..9e42e47bc5f31 100644 --- a/site/src/components/ActiveUserChart/ActiveUserChart.tsx +++ b/site/src/components/ActiveUserChart/ActiveUserChart.tsx @@ -127,9 +127,9 @@ export const ActiveUserChart: FC = ({ { label: `${interval === "day" ? "Daily" : "Weekly"} Active Users`, data: chartData, - pointBackgroundColor: theme.roles.active.outline, - pointBorderColor: theme.roles.active.outline, - borderColor: theme.roles.active.outline, + pointBackgroundColor: theme.colorRoles.active.outline, + pointBorderColor: theme.colorRoles.active.outline, + borderColor: theme.colorRoles.active.outline, }, ], }} diff --git a/site/src/components/Badges/Badges.tsx b/site/src/components/Badges/Badges.tsx index 6e04dd3a5a482..d7f59dce35d29 100644 --- a/site/src/components/Badges/Badges.tsx +++ b/site/src/components/Badges/Badges.tsx @@ -24,19 +24,19 @@ const styles = { }, enabledBadge: (theme) => ({ - border: `1px solid ${theme.roles.success.outline}`, - backgroundColor: theme.roles.success.background, - color: theme.roles.success.text, + border: `1px solid ${theme.colorRoles.success.outline}`, + backgroundColor: theme.colorRoles.success.background, + color: theme.colorRoles.success.text, }), errorBadge: (theme) => ({ - border: `1px solid ${theme.roles.error.outline}`, - backgroundColor: theme.roles.error.background, - color: theme.roles.error.text, + border: `1px solid ${theme.colorRoles.error.outline}`, + backgroundColor: theme.colorRoles.error.background, + color: theme.colorRoles.error.text, }), warnBadge: (theme) => ({ - border: `1px solid ${theme.roles.warning.outline}`, - backgroundColor: theme.roles.warning.background, - color: theme.roles.warning.text, + border: `1px solid ${theme.colorRoles.warning.outline}`, + backgroundColor: theme.colorRoles.warning.background, + color: theme.colorRoles.warning.text, }), } satisfies Record>; @@ -112,9 +112,9 @@ export const EnterpriseBadge: FC = () => { css={[ styles.badge, (theme) => ({ - backgroundColor: theme.roles.notice.background, - border: `1px solid ${theme.roles.notice.outline}`, - color: theme.roles.notice.text, + backgroundColor: theme.colorRoles.notice.background, + border: `1px solid ${theme.colorRoles.notice.outline}`, + color: theme.colorRoles.notice.text, }), ]} > @@ -129,9 +129,9 @@ export const PremiumBadge: FC = () => { css={[ styles.badge, (theme) => ({ - backgroundColor: theme.roles.notice.background, - border: `1px solid ${theme.roles.notice.outline}`, - color: theme.roles.notice.text, + backgroundColor: theme.colorRoles.notice.background, + border: `1px solid ${theme.colorRoles.notice.outline}`, + color: theme.colorRoles.notice.text, }), ]} > @@ -146,9 +146,9 @@ export const PreviewBadge: FC = () => { css={[ styles.badge, (theme) => ({ - border: `1px solid ${theme.roles.preview.outline}`, - backgroundColor: theme.roles.preview.background, - color: theme.roles.preview.text, + border: `1px solid ${theme.colorRoles.preview.outline}`, + backgroundColor: theme.colorRoles.preview.background, + color: theme.colorRoles.preview.text, }), ]} > @@ -163,9 +163,9 @@ export const AlphaBadge: FC = () => { css={[ styles.badge, (theme) => ({ - border: `1px solid ${theme.roles.preview.outline}`, - backgroundColor: theme.roles.preview.background, - color: theme.roles.preview.text, + border: `1px solid ${theme.colorRoles.preview.outline}`, + backgroundColor: theme.colorRoles.preview.background, + color: theme.colorRoles.preview.text, }), ]} > @@ -180,9 +180,9 @@ export const DeprecatedBadge: FC = () => { css={[ styles.badge, (theme) => ({ - border: `1px solid ${theme.roles.danger.outline}`, - backgroundColor: theme.roles.danger.background, - color: theme.roles.danger.text, + border: `1px solid ${theme.colorRoles.danger.outline}`, + backgroundColor: theme.colorRoles.danger.background, + color: theme.colorRoles.danger.text, }), ]} > diff --git a/site/src/components/Dialogs/DeleteDialog/DeleteDialog.tsx b/site/src/components/Dialogs/DeleteDialog/DeleteDialog.tsx index e3d47ccfd0281..45283d9821ab2 100644 --- a/site/src/components/Dialogs/DeleteDialog/DeleteDialog.tsx +++ b/site/src/components/Dialogs/DeleteDialog/DeleteDialog.tsx @@ -108,10 +108,10 @@ export const DeleteDialog: FC = ({ const styles = { callout: (theme) => ({ - backgroundColor: theme.roles.danger.background, - border: `1px solid ${theme.roles.danger.outline}`, + backgroundColor: theme.colorRoles.danger.background, + border: `1px solid ${theme.colorRoles.danger.outline}`, borderRadius: theme.shape.borderRadius, - color: theme.roles.danger.text, + color: theme.colorRoles.danger.text, padding: "8px 16px", }), } satisfies Record>; diff --git a/site/src/components/Dialogs/Dialog.tsx b/site/src/components/Dialogs/Dialog.tsx index 2c2411df12b88..004b18df4ba4d 100644 --- a/site/src/components/Dialogs/Dialog.tsx +++ b/site/src/components/Dialogs/Dialog.tsx @@ -74,24 +74,24 @@ export const DialogActionButtons: FC = ({ const styles = { dangerButton: (theme) => ({ "&.MuiButton-contained": { - backgroundColor: theme.roles.danger.fill.solid, - borderColor: theme.roles.danger.fill.outline, + backgroundColor: theme.colorRoles.danger.fill.solid, + borderColor: theme.colorRoles.danger.fill.outline, "&:not(.MuiLoadingButton-loading)": { - color: theme.roles.danger.fill.text, + color: theme.colorRoles.danger.fill.text, }, "&:hover:not(:disabled)": { - backgroundColor: theme.roles.danger.hover.fill.solid, - borderColor: theme.roles.danger.hover.fill.outline, + backgroundColor: theme.colorRoles.danger.hover.fill.solid, + borderColor: theme.colorRoles.danger.hover.fill.outline, }, "&.Mui-disabled": { - backgroundColor: theme.roles.danger.disabled.background, - borderColor: theme.roles.danger.disabled.outline, + backgroundColor: theme.colorRoles.danger.disabled.background, + borderColor: theme.colorRoles.danger.disabled.outline, "&:not(.MuiLoadingButton-loading)": { - color: theme.roles.danger.disabled.fill.text, + color: theme.colorRoles.danger.disabled.fill.text, }, }, }, diff --git a/site/src/components/HelpTooltip/HelpTooltip.tsx b/site/src/components/HelpTooltip/HelpTooltip.tsx index be76241a95167..31d0bb75c9ca2 100644 --- a/site/src/components/HelpTooltip/HelpTooltip.tsx +++ b/site/src/components/HelpTooltip/HelpTooltip.tsx @@ -212,7 +212,7 @@ const styles = { display: "flex", alignItems: "center", ...(theme.typography.body2 as CSSObject), - color: theme.roles.active.fill.outline, + color: theme.colorRoles.active.fill.outline, }), linkIcon: { diff --git a/site/src/components/InfoTooltip/InfoTooltip.tsx b/site/src/components/InfoTooltip/InfoTooltip.tsx index dc8fb7c97b96d..1608221e7d3e6 100644 --- a/site/src/components/InfoTooltip/InfoTooltip.tsx +++ b/site/src/components/InfoTooltip/InfoTooltip.tsx @@ -8,7 +8,7 @@ import { HelpTooltipTrigger, } from "components/HelpTooltip/HelpTooltip"; import type { FC, ReactNode } from "react"; -import type { ThemeRole } from "theme/roles"; +import type { ThemeRole } from "theme/colorRoles"; interface InfoTooltipProps { type?: ThemeRole; @@ -22,7 +22,7 @@ export const InfoTooltip: FC = ({ type = "info", }) => { const theme = useTheme(); - const iconColor = theme.roles[type].outline; + const iconColor = theme.colorRoles[type].outline; return ( diff --git a/site/src/components/LastSeen/LastSeen.tsx b/site/src/components/LastSeen/LastSeen.tsx index 61510319a1208..248303b4688e3 100644 --- a/site/src/components/LastSeen/LastSeen.tsx +++ b/site/src/components/LastSeen/LastSeen.tsx @@ -23,13 +23,13 @@ export const LastSeen: FC = ({ at, ...attrs }) => { // Since the agent reports on a 10m interval, // the last_used_at can be inaccurate when recent. message = "Now"; - color = theme.roles.success.fill.solid; + color = theme.colorRoles.success.fill.solid; } else if (t.isAfter(now.subtract(3, "day"))) { color = theme.experimental.l2.text; } else if (t.isAfter(now.subtract(1, "month"))) { - color = theme.roles.warning.fill.solid; + color = theme.colorRoles.warning.fill.solid; } else if (t.isAfter(now.subtract(100, "year"))) { - color = theme.roles.error.fill.solid; + color = theme.colorRoles.error.fill.solid; } else { message = "Never"; } diff --git a/site/src/components/Logs/LogLine.tsx b/site/src/components/Logs/LogLine.tsx index fa12a2ce67d98..a947529ecedb9 100644 --- a/site/src/components/Logs/LogLine.tsx +++ b/site/src/components/Logs/LogLine.tsx @@ -43,29 +43,29 @@ const styles = { padding: `0 var(--log-line-side-padding, ${DEFAULT_LOG_LINE_SIDE_PADDING}px)`, "&.error": { - backgroundColor: theme.roles.error.background, - color: theme.roles.error.text, + backgroundColor: theme.colorRoles.error.background, + color: theme.colorRoles.error.text, "& .dashed-line": { - backgroundColor: theme.roles.error.outline, + backgroundColor: theme.colorRoles.error.outline, }, }, "&.debug": { - backgroundColor: theme.roles.notice.background, - color: theme.roles.notice.text, + backgroundColor: theme.colorRoles.notice.background, + color: theme.colorRoles.notice.text, "& .dashed-line": { - backgroundColor: theme.roles.notice.outline, + backgroundColor: theme.colorRoles.notice.outline, }, }, "&.warn": { - backgroundColor: theme.roles.warning.background, - color: theme.roles.warning.text, + backgroundColor: theme.colorRoles.warning.background, + color: theme.colorRoles.warning.text, "& .dashed-line": { - backgroundColor: theme.roles.warning.outline, + backgroundColor: theme.colorRoles.warning.outline, }, }, }), diff --git a/site/src/components/PaginationWidget/PageButtons.tsx b/site/src/components/PaginationWidget/PageButtons.tsx index 1e5f9ff7df18c..7bfc5b1248f4d 100644 --- a/site/src/components/PaginationWidget/PageButtons.tsx +++ b/site/src/components/PaginationWidget/PageButtons.tsx @@ -74,14 +74,14 @@ const BasePageButton: FC = ({