diff --git a/site/e2e/tests/deployment/idpOrgSync.spec.ts b/site/e2e/tests/deployment/idpOrgSync.spec.ts
index 59fccb440400b..6d50969298301 100644
--- a/site/e2e/tests/deployment/idpOrgSync.spec.ts
+++ b/site/e2e/tests/deployment/idpOrgSync.spec.ts
@@ -78,7 +78,7 @@ test.describe("IdpOrgSyncPage", () => {
).toBeVisible();
});
- test("toggle default organization assignment", async ({ page }) => {
+ test("toggle off default organization assignment", async ({ page }) => {
requiresLicense();
await page.goto("/deployment/idp-org-sync", {
waitUntil: "domcontentloaded",
@@ -89,6 +89,12 @@ test.describe("IdpOrgSyncPage", () => {
});
await toggle.click();
+ const dialog = page.getByRole("dialog");
+ await expect(dialog).toBeVisible();
+
+ await dialog.getByRole("button", { name: "Confirm" }).click();
+ await expect(dialog).not.toBeVisible();
+
await expect(
page.getByText("Organization sync settings updated."),
).toBeVisible();
diff --git a/site/src/components/Button/Button.tsx b/site/src/components/Button/Button.tsx
index 8b83149e3bb1e..b0a460eca8a3c 100644
--- a/site/src/components/Button/Button.tsx
+++ b/site/src/components/Button/Button.tsx
@@ -8,7 +8,12 @@ import { type FC, forwardRef } from "react";
import { cn } from "utils/cn";
export const buttonVariants = cva(
- "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-content-link disabled:pointer-events-none disabled:text-content-disabled [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 font-semibold border-solid cursor-pointer",
+ `inline-flex items-center justify-center gap-2 whitespace-nowrap
+ border-solid rounded-md transition-colors
+ text-sm font-semibold font-medium cursor-pointer
+ focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-content-link
+ disabled:pointer-events-none disabled:text-content-disabled
+ [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0`,
{
variants: {
variant: {
diff --git a/site/src/components/Dialog/Dialog.tsx b/site/src/components/Dialog/Dialog.tsx
index dbcc0efc944cd..0770ec62ae735 100644
--- a/site/src/components/Dialog/Dialog.tsx
+++ b/site/src/components/Dialog/Dialog.tsx
@@ -3,7 +3,6 @@
* @see {@link https://ui.shadcn.com/docs/components/dialog}
*/
import * as DialogPrimitive from "@radix-ui/react-dialog";
-import { X } from "lucide-react";
import {
type ComponentPropsWithoutRef,
type ElementRef,
@@ -46,29 +45,19 @@ export const DialogContent = forwardRef<
{children}
-
-
- Close
-
));
@@ -106,7 +95,7 @@ export const DialogTitle = forwardRef<
(({ className, ...props }, ref) => (
));
diff --git a/site/src/pages/DeploymentSettingsPage/IdpOrgSyncPage/IdpOrgSyncPageView.stories.tsx b/site/src/pages/DeploymentSettingsPage/IdpOrgSyncPage/IdpOrgSyncPageView.stories.tsx
index 99742b82e6d17..8d02e1f248833 100644
--- a/site/src/pages/DeploymentSettingsPage/IdpOrgSyncPage/IdpOrgSyncPageView.stories.tsx
+++ b/site/src/pages/DeploymentSettingsPage/IdpOrgSyncPage/IdpOrgSyncPageView.stories.tsx
@@ -1,4 +1,5 @@
import type { Meta, StoryObj } from "@storybook/react";
+import { userEvent, within } from "@storybook/test";
import {
MockOrganization,
MockOrganization2,
@@ -48,3 +49,18 @@ export const MissingGroups: Story = {
organizationSyncSettings: MockOrganizationSyncSettings,
},
};
+
+export const AssignDefaultOrgWarningDialog: Story = {
+ args: {
+ organizationSyncSettings: MockOrganizationSyncSettings,
+ organizations: [MockOrganization, MockOrganization2],
+ },
+ play: async ({ canvasElement }) => {
+ const canvas = within(canvasElement);
+ await userEvent.click(
+ canvas.getByRole("switch", {
+ name: "Assign Default Organization",
+ }),
+ );
+ },
+};
diff --git a/site/src/pages/DeploymentSettingsPage/IdpOrgSyncPage/IdpOrgSyncPageView.tsx b/site/src/pages/DeploymentSettingsPage/IdpOrgSyncPage/IdpOrgSyncPageView.tsx
index 470bf897fd90e..ae90e26c3aa7c 100644
--- a/site/src/pages/DeploymentSettingsPage/IdpOrgSyncPage/IdpOrgSyncPageView.tsx
+++ b/site/src/pages/DeploymentSettingsPage/IdpOrgSyncPage/IdpOrgSyncPageView.tsx
@@ -1,4 +1,3 @@
-import Skeleton from "@mui/material/Skeleton";
import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell";
@@ -12,6 +11,14 @@ import type {
import { ErrorAlert } from "components/Alert/ErrorAlert";
import { Button } from "components/Button/Button";
import { ChooseOne, Cond } from "components/Conditionals/ChooseOne";
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle,
+} from "components/Dialog/Dialog";
import { EmptyState } from "components/EmptyState/EmptyState";
import {
HelpTooltip,
@@ -26,10 +33,6 @@ import {
type Option,
} from "components/MultiSelectCombobox/MultiSelectCombobox";
import { Switch } from "components/Switch/Switch";
-import {
- TableLoaderSkeleton,
- TableRowSkeleton,
-} from "components/TableLoader/TableLoader";
import { useFormik } from "formik";
import { Plus, SquareArrowOutUpRight, Trash } from "lucide-react";
import { type FC, useState } from "react";
@@ -74,6 +77,7 @@ export const IdpOrgSyncPageView: FC = ({
const organizationMappingCount = form.values.mapping
? Object.entries(form.values.mapping).length
: 0;
+ const [isDialogOpen, setIsDialogOpen] = useState(false);
const getOrgNames = (orgIds: readonly string[]) => {
return orgIds.map(
@@ -136,11 +140,15 @@ export const IdpOrgSyncPageView: FC = ({
id={ORGANIZATION_ASSIGN_DEFAULT_ID}
checked={form.values.organization_assign_default}
onCheckedChange={async (checked) => {
- void form.setFieldValue(
- "organization_assign_default",
- checked,
- );
- form.handleSubmit();
+ if (!checked) {
+ setIsDialogOpen(true);
+ } else {
+ void form.setFieldValue(
+ "organization_assign_default",
+ checked,
+ );
+ form.handleSubmit();
+ }
}}
/>
@@ -234,6 +242,36 @@ export const IdpOrgSyncPageView: FC = ({
+
+
);
};
@@ -318,31 +356,14 @@ const OrganizationRow: FC = ({
);
};
-const TableLoader = () => {
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-};
-
export const AssignDefaultOrgHelpTooltip: FC = () => {
return (
- Disabling will remove all users from the default organization.
+ Disabling will remove all users from the default organization if a
+ mapping for the default organization is not defined.