From 6f70bb1f67e4bf5637da03bb71ec69366c47aa4b Mon Sep 17 00:00:00 2001 From: Asher Date: Wed, 7 Aug 2024 16:34:41 -0800 Subject: [PATCH 1/7] fix: only check flag for organization settings I added checks against the license but actually what we want is for these views to become the default even when not licensed (once the experimental flag is removed). --- site/src/modules/dashboard/Navbar/Navbar.tsx | 1 - site/src/pages/DeploySettingsPage/DeploySettingsLayout.tsx | 5 +---- site/src/pages/UsersPage/UsersLayout.tsx | 3 +-- site/src/pages/UsersPage/UsersPage.tsx | 5 +---- 4 files changed, 3 insertions(+), 11 deletions(-) diff --git a/site/src/modules/dashboard/Navbar/Navbar.tsx b/site/src/modules/dashboard/Navbar/Navbar.tsx index d25e0733ee067..5b50f4b5046d8 100644 --- a/site/src/modules/dashboard/Navbar/Navbar.tsx +++ b/site/src/modules/dashboard/Navbar/Navbar.tsx @@ -20,7 +20,6 @@ export const Navbar: FC = () => { const canViewDeployment = Boolean(permissions.viewDeploymentValues); const canViewOrganizations = Boolean(permissions.editAnyOrganization) && - featureVisibility.multiple_organizations && experiments.includes("multi-organization"); const canViewAllUsers = Boolean(permissions.viewAllUsers); const proxyContextValue = useProxy(); diff --git a/site/src/pages/DeploySettingsPage/DeploySettingsLayout.tsx b/site/src/pages/DeploySettingsPage/DeploySettingsLayout.tsx index 14b77ff550ca1..287114fdcc989 100644 --- a/site/src/pages/DeploySettingsPage/DeploySettingsLayout.tsx +++ b/site/src/pages/DeploySettingsPage/DeploySettingsLayout.tsx @@ -9,7 +9,6 @@ import { Stack } from "components/Stack/Stack"; import { useAuthenticated } from "contexts/auth/RequireAuth"; import { RequirePermission } from "contexts/auth/RequirePermission"; import { useDashboard } from "modules/dashboard/useDashboard"; -import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility"; import { ManagementSettingsLayout } from "pages/ManagementSettingsPage/ManagementSettingsLayout"; import { Sidebar } from "./Sidebar"; @@ -34,9 +33,7 @@ export const useDeploySettings = (): DeploySettingsContextValue => { export const DeploySettingsLayout: FC = () => { const { experiments } = useDashboard(); - const feats = useFeatureVisibility(); - const canViewOrganizations = - feats.multiple_organizations && experiments.includes("multi-organization"); + const canViewOrganizations = experiments.includes("multi-organization"); return canViewOrganizations ? ( diff --git a/site/src/pages/UsersPage/UsersLayout.tsx b/site/src/pages/UsersPage/UsersLayout.tsx index 1dc271074c1cd..49416057d3cd5 100644 --- a/site/src/pages/UsersPage/UsersLayout.tsx +++ b/site/src/pages/UsersPage/UsersLayout.tsx @@ -25,8 +25,7 @@ export const UsersLayout: FC = () => { const location = useLocation(); const activeTab = location.pathname.endsWith("groups") ? "groups" : "users"; - const canViewOrganizations = - feats.multiple_organizations && experiments.includes("multi-organization"); + const canViewOrganizations = experiments.includes("multi-organization"); return ( <> diff --git a/site/src/pages/UsersPage/UsersPage.tsx b/site/src/pages/UsersPage/UsersPage.tsx index e8df1f50bde82..fd71a596299c5 100644 --- a/site/src/pages/UsersPage/UsersPage.tsx +++ b/site/src/pages/UsersPage/UsersPage.tsx @@ -29,7 +29,6 @@ import { isNonInitialPage } from "components/PaginationWidget/utils"; import { useAuthenticated } from "contexts/auth/RequireAuth"; import { usePaginatedQuery } from "hooks/usePaginatedQuery"; import { useDashboard } from "modules/dashboard/useDashboard"; -import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility"; import { pageTitle } from "utils/page"; import { generateRandomString } from "utils/random"; import { ResetPasswordDialog } from "./ResetPasswordDialog"; @@ -43,7 +42,6 @@ const UsersPage: FC = () => { const searchParamsResult = useSearchParams(); const { entitlements, experiments } = useDashboard(); const [searchParams] = searchParamsResult; - const feats = useFeatureVisibility(); const groupsByUserIdQuery = useQuery(groupsByUserId("default")); const authMethodsQuery = useQuery(authMethods()); @@ -104,8 +102,7 @@ const UsersPage: FC = () => { authMethodsQuery.isLoading || groupsByUserIdQuery.isLoading; - const canViewOrganizations = - feats.multiple_organizations && experiments.includes("multi-organization"); + const canViewOrganizations = experiments.includes("multi-organization"); if (canViewOrganizations && location.pathname !== "/deployment/users") { return ; } From eb9318c11c181d7c5a903beef62fd527db38c1cd Mon Sep 17 00:00:00 2001 From: Asher Date: Wed, 7 Aug 2024 15:30:57 -0800 Subject: [PATCH 2/7] Move deployment settings header to components This will let us use it in the org settings pages, for a consistent look. --- .../SettingsHeader/SettingsHeader.tsx} | 2 +- .../AppearanceSettingsPage/AppearanceSettingsPageView.tsx | 4 ++-- .../ExternalAuthSettingsPageView.tsx | 4 ++-- .../GeneralSettingsPage/GeneralSettingsPageView.tsx | 4 ++-- .../LicensesSettingsPage/AddNewLicensePageView.tsx | 4 ++-- .../LicensesSettingsPage/LicensesSettingsPageView.tsx | 4 ++-- .../NetworkSettingsPage/NetworkSettingsPageView.tsx | 6 +++--- .../OAuth2AppsSettingsPage/CreateOAuth2AppPageView.tsx | 4 ++-- .../OAuth2AppsSettingsPage/EditOAuth2AppPageView.tsx | 4 ++-- .../OAuth2AppsSettingsPage/OAuth2AppsSettingsPageView.tsx | 4 ++-- .../ObservabilitySettingsPageView.tsx | 8 ++++---- .../SecuritySettingsPage/SecuritySettingsPageView.tsx | 8 ++++---- .../UserAuthSettingsPage/UserAuthSettingsPageView.tsx | 8 ++++---- 13 files changed, 32 insertions(+), 32 deletions(-) rename site/src/{pages/DeploySettingsPage/Header.tsx => components/SettingsHeader/SettingsHeader.tsx} (96%) diff --git a/site/src/pages/DeploySettingsPage/Header.tsx b/site/src/components/SettingsHeader/SettingsHeader.tsx similarity index 96% rename from site/src/pages/DeploySettingsPage/Header.tsx rename to site/src/components/SettingsHeader/SettingsHeader.tsx index f84c35d518fa1..49ecc253f7b33 100644 --- a/site/src/pages/DeploySettingsPage/Header.tsx +++ b/site/src/components/SettingsHeader/SettingsHeader.tsx @@ -11,7 +11,7 @@ interface HeaderProps { docsHref?: string; } -export const Header: FC = ({ +export const SettingsHeader: FC = ({ title, description, docsHref, diff --git a/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx index da2535f9fdcae..f450727dfa5fd 100644 --- a/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx +++ b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx @@ -16,9 +16,9 @@ import { PopoverContent, PopoverTrigger, } from "components/Popover/Popover"; +import { SettingsHeader } from "components/SettingsHeader/SettingsHeader"; import { getFormHelpers } from "utils/formUtils"; import { Fieldset } from "../Fieldset"; -import { Header } from "../Header"; import { AnnouncementBannerSettings } from "./AnnouncementBannerSettings"; export type AppearanceSettingsPageViewProps = { @@ -54,7 +54,7 @@ export const AppearanceSettingsPageView: FC< return ( <> -
diff --git a/site/src/pages/DeploySettingsPage/ExternalAuthSettingsPage/ExternalAuthSettingsPageView.tsx b/site/src/pages/DeploySettingsPage/ExternalAuthSettingsPage/ExternalAuthSettingsPageView.tsx index 8edb242860c21..ed6a593eb1314 100644 --- a/site/src/pages/DeploySettingsPage/ExternalAuthSettingsPage/ExternalAuthSettingsPageView.tsx +++ b/site/src/pages/DeploySettingsPage/ExternalAuthSettingsPage/ExternalAuthSettingsPageView.tsx @@ -9,8 +9,8 @@ import type { FC } from "react"; import type { DeploymentValues, ExternalAuthConfig } from "api/typesGenerated"; import { Alert } from "components/Alert/Alert"; import { EnterpriseBadge } from "components/Badges/Badges"; +import { SettingsHeader } from "components/SettingsHeader/SettingsHeader"; import { docs } from "utils/docs"; -import { Header } from "../Header"; export type ExternalAuthSettingsPageViewProps = { config: DeploymentValues; @@ -21,7 +21,7 @@ export const ExternalAuthSettingsPageView: FC< > = ({ config }) => { return ( <> -
= ({ }) => { return ( <> -
= ({ direction="row" justifyContent="space-between" > -
diff --git a/site/src/pages/DeploySettingsPage/LicensesSettingsPage/LicensesSettingsPageView.tsx b/site/src/pages/DeploySettingsPage/LicensesSettingsPage/LicensesSettingsPageView.tsx index 598e26f67e076..46decb307682a 100644 --- a/site/src/pages/DeploySettingsPage/LicensesSettingsPage/LicensesSettingsPageView.tsx +++ b/site/src/pages/DeploySettingsPage/LicensesSettingsPage/LicensesSettingsPageView.tsx @@ -10,9 +10,9 @@ import type { FC } from "react"; import Confetti from "react-confetti"; import { Link } from "react-router-dom"; import type { GetLicensesResponse } from "api/api"; +import { SettingsHeader } from "components/SettingsHeader/SettingsHeader"; import { Stack } from "components/Stack/Stack"; import { useWindowSize } from "hooks/useWindowSize"; -import { Header } from "../Header"; import { LicenseCard } from "./LicenseCard"; type Props = { @@ -55,7 +55,7 @@ const LicensesSettingsPageView: FC = ({ direction="row" justifyContent="space-between" > -
diff --git a/site/src/pages/DeploySettingsPage/NetworkSettingsPage/NetworkSettingsPageView.tsx b/site/src/pages/DeploySettingsPage/NetworkSettingsPage/NetworkSettingsPageView.tsx index cb93cd269ddfc..b500848c95b31 100644 --- a/site/src/pages/DeploySettingsPage/NetworkSettingsPage/NetworkSettingsPageView.tsx +++ b/site/src/pages/DeploySettingsPage/NetworkSettingsPage/NetworkSettingsPageView.tsx @@ -1,13 +1,13 @@ import type { FC } from "react"; import type { SerpentOption } from "api/typesGenerated"; import { Badges, EnabledBadge, DisabledBadge } from "components/Badges/Badges"; +import { SettingsHeader } from "components/SettingsHeader/SettingsHeader"; import { Stack } from "components/Stack/Stack"; import { deploymentGroupHasParent, useDeploymentOptions, } from "utils/deployOptions"; import { docs } from "utils/docs"; -import { Header } from "../Header"; import OptionsTable from "../OptionsTable"; export type NetworkSettingsPageViewProps = { @@ -19,7 +19,7 @@ export const NetworkSettingsPageView: FC = ({ }) => (
-
= ({
-
= ({ direction="row" justifyContent="space-between" > -
diff --git a/site/src/pages/DeploySettingsPage/OAuth2AppsSettingsPage/EditOAuth2AppPageView.tsx b/site/src/pages/DeploySettingsPage/OAuth2AppsSettingsPage/EditOAuth2AppPageView.tsx index 1c905deb65474..2c9c71c8f627b 100644 --- a/site/src/pages/DeploySettingsPage/OAuth2AppsSettingsPage/EditOAuth2AppPageView.tsx +++ b/site/src/pages/DeploySettingsPage/OAuth2AppsSettingsPage/EditOAuth2AppPageView.tsx @@ -20,10 +20,10 @@ import { CopyableValue } from "components/CopyableValue/CopyableValue"; import { ConfirmDialog } from "components/Dialogs/ConfirmDialog/ConfirmDialog"; import { DeleteDialog } from "components/Dialogs/DeleteDialog/DeleteDialog"; import { Loader } from "components/Loader/Loader"; +import { SettingsHeader } from "components/SettingsHeader/SettingsHeader"; import { Stack } from "components/Stack/Stack"; import { TableLoader } from "components/TableLoader/TableLoader"; import { createDayString } from "utils/createDayString"; -import { Header } from "../Header"; import { OAuth2AppForm } from "./OAuth2AppForm"; export type MutatingResource = { @@ -75,7 +75,7 @@ export const EditOAuth2AppPageView: FC = ({ direction="row" justifyContent="space-between" > -
diff --git a/site/src/pages/DeploySettingsPage/OAuth2AppsSettingsPage/OAuth2AppsSettingsPageView.tsx b/site/src/pages/DeploySettingsPage/OAuth2AppsSettingsPage/OAuth2AppsSettingsPageView.tsx index 179dc6b732dae..dfd73ae2fe3c7 100644 --- a/site/src/pages/DeploySettingsPage/OAuth2AppsSettingsPage/OAuth2AppsSettingsPageView.tsx +++ b/site/src/pages/DeploySettingsPage/OAuth2AppsSettingsPage/OAuth2AppsSettingsPageView.tsx @@ -14,10 +14,10 @@ import type * as TypesGen from "api/typesGenerated"; import { ErrorAlert } from "components/Alert/ErrorAlert"; import { Avatar } from "components/Avatar/Avatar"; import { AvatarData } from "components/AvatarData/AvatarData"; +import { SettingsHeader } from "components/SettingsHeader/SettingsHeader"; import { Stack } from "components/Stack/Stack"; import { TableLoader } from "components/TableLoader/TableLoader"; import { useClickableTableRow } from "hooks/useClickableTableRow"; -import { Header } from "../Header"; type OAuth2AppsSettingsProps = { apps?: TypesGen.OAuth2ProviderApp[]; @@ -38,7 +38,7 @@ const OAuth2AppsSettingsPageView: FC = ({ justifyContent="space-between" >
-
diff --git a/site/src/pages/DeploySettingsPage/ObservabilitySettingsPage/ObservabilitySettingsPageView.tsx b/site/src/pages/DeploySettingsPage/ObservabilitySettingsPage/ObservabilitySettingsPageView.tsx index 3d5e0be91206e..bcd31bc776ff9 100644 --- a/site/src/pages/DeploySettingsPage/ObservabilitySettingsPage/ObservabilitySettingsPageView.tsx +++ b/site/src/pages/DeploySettingsPage/ObservabilitySettingsPage/ObservabilitySettingsPageView.tsx @@ -6,10 +6,10 @@ import { EnabledBadge, EnterpriseBadge, } from "components/Badges/Badges"; +import { SettingsHeader } from "components/SettingsHeader/SettingsHeader"; import { Stack } from "components/Stack/Stack"; import { deploymentGroupHasParent } from "utils/deployOptions"; import { docs } from "utils/docs"; -import { Header } from "../Header"; import OptionsTable from "../OptionsTable"; export type ObservabilitySettingsPageViewProps = { @@ -24,8 +24,8 @@ export const ObservabilitySettingsPageView: FC< <>
-
-
+
-
= ({ return (
-
@@ -47,7 +47,7 @@ export const SecuritySettingsPageView: FC = ({
-
= ({ {tlsOptions.length > 0 && (
-
-
+ -
-
Date: Thu, 8 Aug 2024 22:49:08 -0800 Subject: [PATCH 3/7] Add premium badge --- site/src/components/Badges/Badges.tsx | 17 +++++++++++++++++ .../Paywall/PopoverPaywall.stories.tsx | 11 +++++++++-- site/src/components/Paywall/PopoverPaywall.tsx | 13 ++++++++++--- 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/site/src/components/Badges/Badges.tsx b/site/src/components/Badges/Badges.tsx index 7fc76fb879a9c..a6c31fe97e3e4 100644 --- a/site/src/components/Badges/Badges.tsx +++ b/site/src/components/Badges/Badges.tsx @@ -123,6 +123,23 @@ export const EnterpriseBadge: FC = () => { ); }; +export const PremiumBadge: FC = () => { + return ( + ({ + backgroundColor: theme.roles.info.background, + border: `1px solid ${theme.roles.info.outline}`, + color: theme.roles.info.text, + }), + ]} + > + Premium + + ); +}; + export const PreviewBadge: FC = () => { return ( = { export default meta; type Story = StoryObj; -const Example: Story = { +export const Enterprise: Story = { args: { message: "Black Lotus", description: @@ -17,4 +17,11 @@ const Example: Story = { }, }; -export { Example as PopoverPaywall }; +export const Premium: Story = { + args: { + message: "Black Lotus", + description: + "Adds 3 mana of any single color of your choice to your mana pool, then is discarded. Tapping this artifact can be played as an interrupt.", + licenseType: "premium", + }, +}; diff --git a/site/src/components/Paywall/PopoverPaywall.tsx b/site/src/components/Paywall/PopoverPaywall.tsx index 459d7c58fb22b..15f337d7a537e 100644 --- a/site/src/components/Paywall/PopoverPaywall.tsx +++ b/site/src/components/Paywall/PopoverPaywall.tsx @@ -3,7 +3,7 @@ import TaskAltIcon from "@mui/icons-material/TaskAlt"; import Button from "@mui/material/Button"; import Link from "@mui/material/Link"; import type { FC, ReactNode } from "react"; -import { EnterpriseBadge } from "components/Badges/Badges"; +import { EnterpriseBadge, PremiumBadge } from "components/Badges/Badges"; import { Stack } from "components/Stack/Stack"; import { docs } from "utils/docs"; @@ -11,19 +11,21 @@ export interface PopoverPaywallProps { message: string; description?: ReactNode; documentationLink?: string; + licenseType?: "enterprise" | "premium"; } export const PopoverPaywall: FC = ({ message, description, documentationLink, + licenseType = "enterprise", }) => { return (
{message}
- + {licenseType === "premium" ? : }
{description &&

{description}

} @@ -51,6 +53,11 @@ export const PopoverPaywall: FC = ({
  • Audit logs
  • + {licenseType === "premium" && ( +
  • + Organizations +
  • + )}
    From 71561c83ddd486a6ba95c039cf82db4fa5d3dfbd Mon Sep 17 00:00:00 2001 From: Asher Date: Wed, 7 Aug 2024 15:34:39 -0800 Subject: [PATCH 4/7] Use settings header on org pages --- .../CreateOrganizationPageView.tsx | 9 +- .../CreateEditRolePageView.tsx | 67 +++--- .../CustomRolesPage/CustomRolesPage.tsx | 33 ++- .../GroupsPage/CreateGroupPageView.tsx | 10 +- .../GroupsPage/GroupPage.tsx | 205 +++++++++--------- .../GroupsPage/GroupsPage.tsx | 33 ++- .../OrganizationMembersPageView.tsx | 6 +- .../OrganizationSettingsPageView.tsx | 6 +- 8 files changed, 182 insertions(+), 187 deletions(-) diff --git a/site/src/pages/ManagementSettingsPage/CreateOrganizationPageView.tsx b/site/src/pages/ManagementSettingsPage/CreateOrganizationPageView.tsx index 9b1c8632241ef..e6dd64835c116 100644 --- a/site/src/pages/ManagementSettingsPage/CreateOrganizationPageView.tsx +++ b/site/src/pages/ManagementSettingsPage/CreateOrganizationPageView.tsx @@ -12,7 +12,7 @@ import { FormFooter, } from "components/Form/Form"; import { IconField } from "components/IconField/IconField"; -import { PageHeader, PageHeaderTitle } from "components/PageHeader/PageHeader"; +import { SettingsHeader } from "components/SettingsHeader/SettingsHeader"; import { getFormHelpers, nameValidator, @@ -54,9 +54,10 @@ export const CreateOrganizationPageView: FC< return (
    - - Organization settings - + {Boolean(error) && !isApiValidationError(error) && (
    diff --git a/site/src/pages/ManagementSettingsPage/CustomRolesPage/CreateEditRolePageView.tsx b/site/src/pages/ManagementSettingsPage/CustomRolesPage/CreateEditRolePageView.tsx index 8e58f19ac5954..559c9dfa9f6df 100644 --- a/site/src/pages/ManagementSettingsPage/CustomRolesPage/CreateEditRolePageView.tsx +++ b/site/src/pages/ManagementSettingsPage/CustomRolesPage/CreateEditRolePageView.tsx @@ -28,11 +28,8 @@ import type { } from "api/typesGenerated"; import { ErrorAlert } from "components/Alert/ErrorAlert"; import { FormFields, FormFooter, VerticalForm } from "components/Form/Form"; -import { - PageHeader, - PageHeaderSubtitle, - PageHeaderTitle, -} from "components/PageHeader/PageHeader"; +import { SettingsHeader } from "components/SettingsHeader/SettingsHeader"; +import { Stack } from "components/Stack/Stack"; import { getFormHelpers, nameValidator } from "utils/formUtils"; const validationSchema = Yup.object({ @@ -77,37 +74,37 @@ export const CreateEditRolePageView: FC = ({ return ( <> - - - - - ) - } + - - {role ? "Edit" : "Create"} custom role - - - {"Set a name and permissions for this role."} - - + + {canAssignOrgRole && ( + + + + + )} + + {Boolean(error) && !isApiValidationError(error) && ( diff --git a/site/src/pages/ManagementSettingsPage/CustomRolesPage/CustomRolesPage.tsx b/site/src/pages/ManagementSettingsPage/CustomRolesPage/CustomRolesPage.tsx index e1529815796c0..46e04f790bf51 100644 --- a/site/src/pages/ManagementSettingsPage/CustomRolesPage/CustomRolesPage.tsx +++ b/site/src/pages/ManagementSettingsPage/CustomRolesPage/CustomRolesPage.tsx @@ -9,7 +9,8 @@ import { organizationPermissions } from "api/queries/organizations"; import { organizationRoles } from "api/queries/roles"; import { displayError } from "components/GlobalSnackbar/utils"; import { Loader } from "components/Loader/Loader"; -import { PageHeader, PageHeaderTitle } from "components/PageHeader/PageHeader"; +import { SettingsHeader } from "components/SettingsHeader/SettingsHeader"; +import { Stack } from "components/Stack/Stack"; import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility"; import { pageTitle } from "utils/page"; import { useOrganizationSettings } from "../ManagementSettingsLayout"; @@ -50,23 +51,21 @@ export const CustomRolesPage: FC = () => { {pageTitle("Custom Roles")} - - {permissions.assignOrgRole && isCustomRolesEnabled && ( - - )} - - } + - Custom Roles - + + {permissions.assignOrgRole && isCustomRolesEnabled && ( + + )} + = ({ return ( <> - - Create a group - + + { <> {helmet} - - - - - - ) - } + + - - - {canUpdateGroup && groupData && !isEveryoneGroup(groupData) && ( - { - try { - await addMemberMutation.mutateAsync({ - groupId, - userId: user.id, - }); - reset(); - await groupQuery.refetch(); - } catch (error) { - displayError(getErrorMessage(error, "Failed to add member.")); - } + {canUpdateGroup && ( + + + + + )} + - - - - - User - Status - - - + + {canUpdateGroup && groupData && !isEveryoneGroup(groupData) && ( + { + try { + await addMemberMutation.mutateAsync({ + groupId, + userId: user.id, + }); + reset(); + await groupQuery.refetch(); + } catch (error) { + displayError(getErrorMessage(error, "Failed to add member.")); + } + }} + /> + )} + + + + + +
    + + + User + Status + + + - - {groupData?.members.length === 0 ? ( - - - - - - ) : ( - groupData?.members.map((member) => ( - { - try { - await removeMemberMutation.mutateAsync({ - groupId: groupData.id, - userId: member.id, - }); - await groupQuery.refetch(); - displaySuccess("Member removed successfully."); - } catch (error) { - displayError( - getErrorMessage(error, "Failed to remove member."), - ); - } - }} + + {groupData?.members.length === 0 ? ( + + + - )) - )} - -
    -
    -
    -
    + + + ) : ( + groupData?.members.map((member) => ( + { + try { + await removeMemberMutation.mutateAsync({ + groupId: groupData.id, + userId: member.id, + }); + await groupQuery.refetch(); + displaySuccess("Member removed successfully."); + } catch (error) { + displayError( + getErrorMessage(error, "Failed to remove member."), + ); + } + }} + /> + )) + )} + + + + {groupQuery.data && ( { {pageTitle("Groups")} - - {permissions.createGroup && feats.template_rbac && ( - - )} - - } + - Groups - + + {permissions.createGroup && feats.template_rbac && ( + + )} + = (props) => { return (
    - - Organization members - + {Boolean(props.error) && } diff --git a/site/src/pages/ManagementSettingsPage/OrganizationSettingsPageView.tsx b/site/src/pages/ManagementSettingsPage/OrganizationSettingsPageView.tsx index be2a5e7cf2365..f757db6a12f5a 100644 --- a/site/src/pages/ManagementSettingsPage/OrganizationSettingsPageView.tsx +++ b/site/src/pages/ManagementSettingsPage/OrganizationSettingsPageView.tsx @@ -18,7 +18,7 @@ import { FormFooter, } from "components/Form/Form"; import { IconField } from "components/IconField/IconField"; -import { PageHeader, PageHeaderTitle } from "components/PageHeader/PageHeader"; +import { SettingsHeader } from "components/SettingsHeader/SettingsHeader"; import { getFormHelpers, nameValidator, @@ -67,9 +67,7 @@ export const OrganizationSettingsPageView: FC< return (
    - - Organization settings - + {Boolean(error) && !isApiValidationError(error) && (
    From cb6c6bb22adff7d70ed4472c87eca4154e2d5646 Mon Sep 17 00:00:00 2001 From: Asher Date: Wed, 7 Aug 2024 15:35:30 -0800 Subject: [PATCH 5/7] Add license badges to create org page I am not sure if there is maybe a better place for this, but maybe this is good enough. --- .../CreateOrganizationPage.tsx | 3 ++ .../CreateOrganizationPageView.stories.tsx | 9 +++++ .../CreateOrganizationPageView.tsx | 36 ++++++++++++++++++- 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/site/src/pages/ManagementSettingsPage/CreateOrganizationPage.tsx b/site/src/pages/ManagementSettingsPage/CreateOrganizationPage.tsx index 4fbbab40dc29e..2ba16817446e1 100644 --- a/site/src/pages/ManagementSettingsPage/CreateOrganizationPage.tsx +++ b/site/src/pages/ManagementSettingsPage/CreateOrganizationPage.tsx @@ -3,10 +3,12 @@ import { useMutation, useQueryClient } from "react-query"; import { useNavigate } from "react-router-dom"; import { createOrganization } from "api/queries/organizations"; import { displaySuccess } from "components/GlobalSnackbar/utils"; +import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility"; import { CreateOrganizationPageView } from "./CreateOrganizationPageView"; const CreateOrganizationPage: FC = () => { const navigate = useNavigate(); + const feats = useFeatureVisibility(); const queryClient = useQueryClient(); const createOrganizationMutation = useMutation( @@ -18,6 +20,7 @@ const CreateOrganizationPage: FC = () => { return ( { await createOrganizationMutation.mutateAsync(values); displaySuccess("Organization created."); diff --git a/site/src/pages/ManagementSettingsPage/CreateOrganizationPageView.stories.tsx b/site/src/pages/ManagementSettingsPage/CreateOrganizationPageView.stories.tsx index 81cad38a407ea..d3e7a81208acc 100644 --- a/site/src/pages/ManagementSettingsPage/CreateOrganizationPageView.stories.tsx +++ b/site/src/pages/ManagementSettingsPage/CreateOrganizationPageView.stories.tsx @@ -5,6 +5,9 @@ import { CreateOrganizationPageView } from "./CreateOrganizationPageView"; const meta: Meta = { title: "pages/CreateOrganizationPageView", component: CreateOrganizationPageView, + args: { + isEntitled: true, + }, }; export default meta; @@ -12,6 +15,12 @@ type Story = StoryObj; export const Example: Story = {}; +export const NotEntitled: Story = { + args: { + isEntitled: false, + }, +}; + export const Error: Story = { args: { error: "Oh no!" }, }; diff --git a/site/src/pages/ManagementSettingsPage/CreateOrganizationPageView.tsx b/site/src/pages/ManagementSettingsPage/CreateOrganizationPageView.tsx index e6dd64835c116..94a1bfe9178c1 100644 --- a/site/src/pages/ManagementSettingsPage/CreateOrganizationPageView.tsx +++ b/site/src/pages/ManagementSettingsPage/CreateOrganizationPageView.tsx @@ -5,6 +5,12 @@ import * as Yup from "yup"; import { isApiValidationError } from "api/errors"; import type { CreateOrganizationRequest } from "api/typesGenerated"; import { ErrorAlert } from "components/Alert/ErrorAlert"; +import { + Badges, + DisabledBadge, + PremiumBadge, + EntitledBadge, +} from "components/Badges/Badges"; import { FormFields, FormSection, @@ -12,7 +18,14 @@ import { FormFooter, } from "components/Form/Form"; import { IconField } from "components/IconField/IconField"; +import { PopoverPaywall } from "components/Paywall/PopoverPaywall"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "components/Popover/Popover"; import { SettingsHeader } from "components/SettingsHeader/SettingsHeader"; +import { docs } from "utils/docs"; import { getFormHelpers, nameValidator, @@ -35,11 +48,12 @@ const validationSchema = Yup.object({ interface CreateOrganizationPageViewProps { error: unknown; onSubmit: (values: CreateOrganizationRequest) => Promise; + isEntitled: boolean; } export const CreateOrganizationPageView: FC< CreateOrganizationPageViewProps -> = ({ error, onSubmit }) => { +> = ({ error, onSubmit, isEntitled }) => { const form = useFormik({ initialValues: { name: "", @@ -59,6 +73,26 @@ export const CreateOrganizationPageView: FC< description="Organize your deployment into multiple platform teams." /> + + {isEntitled ? : } + + + + + + + + + + + + {Boolean(error) && !isApiValidationError(error) && (
    From dd3a47074f4def31e6a703e4d61521473e45bd36 Mon Sep 17 00:00:00 2001 From: Asher Date: Wed, 7 Aug 2024 15:40:34 -0800 Subject: [PATCH 6/7] Change create org form description text It says "change", but there is nothing to change yet since this is a new organization. --- .../pages/ManagementSettingsPage/CreateOrganizationPageView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/pages/ManagementSettingsPage/CreateOrganizationPageView.tsx b/site/src/pages/ManagementSettingsPage/CreateOrganizationPageView.tsx index 94a1bfe9178c1..9a847dc42ad49 100644 --- a/site/src/pages/ManagementSettingsPage/CreateOrganizationPageView.tsx +++ b/site/src/pages/ManagementSettingsPage/CreateOrganizationPageView.tsx @@ -105,7 +105,7 @@ export const CreateOrganizationPageView: FC< >
    Date: Thu, 8 Aug 2024 23:13:00 -0800 Subject: [PATCH 7/7] Consistently capitalize --- .../CustomRolesPage/CreateEditRolePageView.tsx | 2 +- .../ManagementSettingsPage/OrganizationMembersPageView.tsx | 2 +- .../ManagementSettingsPage/OrganizationSettingsPageView.tsx | 2 +- site/src/pages/ManagementSettingsPage/SidebarView.tsx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/site/src/pages/ManagementSettingsPage/CustomRolesPage/CreateEditRolePageView.tsx b/site/src/pages/ManagementSettingsPage/CustomRolesPage/CreateEditRolePageView.tsx index 559c9dfa9f6df..5d23d2e69a500 100644 --- a/site/src/pages/ManagementSettingsPage/CustomRolesPage/CreateEditRolePageView.tsx +++ b/site/src/pages/ManagementSettingsPage/CustomRolesPage/CreateEditRolePageView.tsx @@ -80,7 +80,7 @@ export const CreateEditRolePageView: FC = ({ justifyContent="space-between" > {canAssignOrgRole && ( diff --git a/site/src/pages/ManagementSettingsPage/OrganizationMembersPageView.tsx b/site/src/pages/ManagementSettingsPage/OrganizationMembersPageView.tsx index c30e4e49b6f5d..dc45e57b609d3 100644 --- a/site/src/pages/ManagementSettingsPage/OrganizationMembersPageView.tsx +++ b/site/src/pages/ManagementSettingsPage/OrganizationMembersPageView.tsx @@ -52,7 +52,7 @@ export const OrganizationMembersPageView: FC< > = (props) => { return (
    - + {Boolean(props.error) && } diff --git a/site/src/pages/ManagementSettingsPage/OrganizationSettingsPageView.tsx b/site/src/pages/ManagementSettingsPage/OrganizationSettingsPageView.tsx index f757db6a12f5a..8be81243a396d 100644 --- a/site/src/pages/ManagementSettingsPage/OrganizationSettingsPageView.tsx +++ b/site/src/pages/ManagementSettingsPage/OrganizationSettingsPageView.tsx @@ -67,7 +67,7 @@ export const OrganizationSettingsPageView: FC< return (
    - + {Boolean(error) && !isApiValidationError(error) && (
    diff --git a/site/src/pages/ManagementSettingsPage/SidebarView.tsx b/site/src/pages/ManagementSettingsPage/SidebarView.tsx index 4417e40e3e8c0..57accc6fa1a5a 100644 --- a/site/src/pages/ManagementSettingsPage/SidebarView.tsx +++ b/site/src/pages/ManagementSettingsPage/SidebarView.tsx @@ -234,7 +234,7 @@ const OrganizationSettingsNavigation: FC< {organization.permissions.editOrganization && ( - Organization settings + Settings )} {organization.permissions.editMembers && (