From 54b81ecf753378558d1d5a769223bed8f10b4308 Mon Sep 17 00:00:00 2001 From: Jaayden Halko Date: Wed, 25 Sep 2024 15:38:51 +0000 Subject: [PATCH 1/5] fix: show paywall and correctly display auto create groups --- .../IdpSyncPage/IdpSyncPage.tsx | 78 +++--- .../IdpSyncPage/IdpSyncPageView.tsx | 239 +++++++++--------- 2 files changed, 164 insertions(+), 153 deletions(-) diff --git a/site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPage.tsx b/site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPage.tsx index 0a4272cc47589..cc7c3ba2b446f 100644 --- a/site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPage.tsx +++ b/site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPage.tsx @@ -1,16 +1,18 @@ import LaunchOutlined from "@mui/icons-material/LaunchOutlined"; import Button from "@mui/material/Button"; +import { getErrorMessage } from "api/errors"; import { groupsByOrganization } from "api/queries/groups"; import { groupIdpSyncSettings, roleIdpSyncSettings, } from "api/queries/organizations"; -import { ErrorAlert } from "components/Alert/ErrorAlert"; import { EmptyState } from "components/EmptyState/EmptyState"; +import { displayError } from "components/GlobalSnackbar/utils"; import { Loader } from "components/Loader/Loader"; import { SettingsHeader } from "components/SettingsHeader/SettingsHeader"; import { Stack } from "components/Stack/Stack"; -import type { FC } from "react"; +import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility"; +import { type FC, useEffect } from "react"; import { Helmet } from "react-helmet-async"; import { useQueries } from "react-query"; import { useParams } from "react-router-dom"; @@ -19,11 +21,16 @@ import { pageTitle } from "utils/page"; import { useOrganizationSettings } from "../ManagementSettingsLayout"; import { IdpSyncHelpTooltip } from "./IdpSyncHelpTooltip"; import IdpSyncPageView from "./IdpSyncPageView"; +import { ErrorAlert } from "components/Alert/ErrorAlert"; +import { Paywall } from "components/Paywall/Paywall"; +import { ChooseOne, Cond } from "components/Conditionals/ChooseOne"; export const IdpSyncPage: FC = () => { const { organization: organizationName } = useParams() as { organization: string; }; + // IdP sync does not have its own entitlement and is based on templace_rbac + const { template_rbac: isIdpSyncEnabled } = useFeatureVisibility(); const { organizations } = useOrganizationSettings(); const organization = organizations?.find((o) => o.name === organizationName); @@ -40,26 +47,18 @@ export const IdpSyncPage: FC = () => { return ; } - if ( - groupsQuery.isLoading || - groupIdpSyncSettingsQuery.isLoading || - roleIdpSyncSettingsQuery.isLoading - ) { - return ; - } + // if ( + // groupsQuery.isLoading || + // groupIdpSyncSettingsQuery.isLoading || + // roleIdpSyncSettingsQuery.isLoading + // ) { + // return ; + // } const error = groupIdpSyncSettingsQuery.error || roleIdpSyncSettingsQuery.error || groupsQuery.error; - if ( - error || - !groupIdpSyncSettingsQuery.data || - !roleIdpSyncSettingsQuery.data || - !groupsQuery.data - ) { - return ; - } const groupsMap = new Map(); if (groupsQuery.data) { @@ -84,25 +83,34 @@ export const IdpSyncPage: FC = () => { description="Group and role sync mappings (configured using Coder CLI)." tooltip={} /> - - - + - - + + + + + + + + ); }; diff --git a/site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPageView.tsx b/site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPageView.tsx index f73395e254e8b..b700fb119ce67 100644 --- a/site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPageView.tsx +++ b/site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPageView.tsx @@ -16,7 +16,6 @@ import type { } from "api/typesGenerated"; import { ChooseOne, Cond } from "components/Conditionals/ChooseOne"; import { EmptyState } from "components/EmptyState/EmptyState"; -import { Paywall } from "components/Paywall/Paywall"; import { Stack } from "components/Stack/Stack"; import { StatusIndicator } from "components/StatusIndicator/StatusIndicator"; import { @@ -30,6 +29,8 @@ import { MONOSPACE_FONT_FAMILY } from "theme/constants"; import { docs } from "utils/docs"; import { ExportPolicyButton } from "./ExportPolicyButton"; import { IdpPillList } from "./IdpPillList"; +import { ErrorAlert } from "components/Alert/ErrorAlert"; +import { Loader } from "components/Loader/Loader"; interface IdpSyncPageViewProps { groupSyncSettings: GroupSyncSettings | undefined; @@ -37,13 +38,16 @@ interface IdpSyncPageViewProps { groups: Group[] | undefined; groupsMap: Map; organization: Organization; + error?: unknown; } export const IdpSyncPageView: FC = ({ groupSyncSettings, roleSyncSettings, + groups, groupsMap, organization, + error, }) => { const [searchParams] = useSearchParams(); @@ -60,126 +64,125 @@ export const IdpSyncPageView: FC = ({ ? Object.entries(roleSyncSettings.mapping).length : 0; + if (error) { + return ; + } + + if (!groupSyncSettings || !roleSyncSettings || !groups) { + return ; + } + return ( <> - - - - - - - - - - Group Sync Settings - - - Role Sync Settings - - - - {tab === "groups" ? ( - <> -
- - - - + + + + Group Sync Settings + + + Role Sync Settings + + + + {tab === "groups" ? ( + <> +
+ + + + + +
+ + + + + + + {groupSyncSettings?.mapping && + Object.entries(groupSyncSettings.mapping) + .sort() + .map(([idpGroup, groups]) => ( + + ))} + + + + ) : ( + <> +
+ +
+ + + + + + {roleSyncSettings?.mapping && + Object.entries(roleSyncSettings.mapping) + .sort() + .map(([idpRole, roles]) => ( + -
-
- - - - - - - {groupSyncSettings?.mapping && - Object.entries(groupSyncSettings.mapping) - .sort() - .map(([idpGroup, groups]) => ( - - ))} - - - - ) : ( - <> -
- -
- - - - - - {roleSyncSettings?.mapping && - Object.entries(roleSyncSettings.mapping) - .sort() - .map(([idpRole, roles]) => ( - - ))} - - - )} -
-
-
+ ))} + + + )} + ); }; From 6a377795b5d3693ac762d2844d3ec411f8369bff Mon Sep 17 00:00:00 2001 From: Jaayden Halko Date: Wed, 25 Sep 2024 16:06:00 +0000 Subject: [PATCH 2/5] fix: update stories --- .../IdpSyncPage/IdpSyncPageView.stories.tsx | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPageView.stories.tsx b/site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPageView.stories.tsx index 646e64d763b86..3c493ec1bbb5b 100644 --- a/site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPageView.stories.tsx +++ b/site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPageView.stories.tsx @@ -5,6 +5,7 @@ import { MockGroupSyncSettings, MockGroupSyncSettings2, MockRoleSyncSettings, + MockOrganization, } from "testHelpers/entities"; import { IdpSyncPageView } from "./IdpSyncPageView"; @@ -22,11 +23,23 @@ for (const group of [MockGroup, MockGroup2]) { groupsMap.set(group.id, group.display_name || group.name); } +export const NotEnabled: Story = { + args: { + groupSyncSettings: undefined, + roleSyncSettings: undefined, + groupsMap: undefined, + organization: MockOrganization, + isIdpSyncEnabled: false, + }, +}; + export const Empty: Story = { args: { groupSyncSettings: undefined, roleSyncSettings: undefined, groupsMap: undefined, + organization: MockOrganization, + isIdpSyncEnabled: true, }, }; @@ -35,6 +48,8 @@ export const Default: Story = { groupSyncSettings: MockGroupSyncSettings, roleSyncSettings: MockRoleSyncSettings, groupsMap, + organization: MockOrganization, + isIdpSyncEnabled: true, }, }; @@ -43,5 +58,7 @@ export const MissingGroups: Story = { groupSyncSettings: MockGroupSyncSettings2, roleSyncSettings: MockRoleSyncSettings, groupsMap, + organization: MockOrganization, + isIdpSyncEnabled: true, }, }; From 5b4e76cb96d449133266298c7ab86ec42da9dbf1 Mon Sep 17 00:00:00 2001 From: Jaayden Halko Date: Wed, 25 Sep 2024 16:26:15 +0000 Subject: [PATCH 3/5] fix: format --- .../IdpSyncPage/IdpSyncPageView.stories.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPageView.stories.tsx b/site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPageView.stories.tsx index 3c493ec1bbb5b..d360482105d81 100644 --- a/site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPageView.stories.tsx +++ b/site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPageView.stories.tsx @@ -4,8 +4,8 @@ import { MockGroup2, MockGroupSyncSettings, MockGroupSyncSettings2, - MockRoleSyncSettings, MockOrganization, + MockRoleSyncSettings, } from "testHelpers/entities"; import { IdpSyncPageView } from "./IdpSyncPageView"; From b285e11901d50b94ec5123f116eb9e868c458eca Mon Sep 17 00:00:00 2001 From: Jaayden Halko Date: Thu, 26 Sep 2024 01:10:11 +0000 Subject: [PATCH 4/5] chore: cleanup --- .../IdpSyncPage/IdpSyncPage.tsx | 18 +++--------------- .../IdpSyncPage/IdpSyncPageView.tsx | 4 ++-- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPage.tsx b/site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPage.tsx index cc7c3ba2b446f..5842f6d3696c8 100644 --- a/site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPage.tsx +++ b/site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPage.tsx @@ -1,18 +1,17 @@ import LaunchOutlined from "@mui/icons-material/LaunchOutlined"; import Button from "@mui/material/Button"; -import { getErrorMessage } from "api/errors"; import { groupsByOrganization } from "api/queries/groups"; import { groupIdpSyncSettings, roleIdpSyncSettings, } from "api/queries/organizations"; +import { ChooseOne, Cond } from "components/Conditionals/ChooseOne"; import { EmptyState } from "components/EmptyState/EmptyState"; -import { displayError } from "components/GlobalSnackbar/utils"; -import { Loader } from "components/Loader/Loader"; +import { Paywall } from "components/Paywall/Paywall"; import { SettingsHeader } from "components/SettingsHeader/SettingsHeader"; import { Stack } from "components/Stack/Stack"; import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility"; -import { type FC, useEffect } from "react"; +import type { FC } from "react"; import { Helmet } from "react-helmet-async"; import { useQueries } from "react-query"; import { useParams } from "react-router-dom"; @@ -21,9 +20,6 @@ import { pageTitle } from "utils/page"; import { useOrganizationSettings } from "../ManagementSettingsLayout"; import { IdpSyncHelpTooltip } from "./IdpSyncHelpTooltip"; import IdpSyncPageView from "./IdpSyncPageView"; -import { ErrorAlert } from "components/Alert/ErrorAlert"; -import { Paywall } from "components/Paywall/Paywall"; -import { ChooseOne, Cond } from "components/Conditionals/ChooseOne"; export const IdpSyncPage: FC = () => { const { organization: organizationName } = useParams() as { @@ -47,14 +43,6 @@ export const IdpSyncPage: FC = () => { return ; } - // if ( - // groupsQuery.isLoading || - // groupIdpSyncSettingsQuery.isLoading || - // roleIdpSyncSettingsQuery.isLoading - // ) { - // return ; - // } - const error = groupIdpSyncSettingsQuery.error || roleIdpSyncSettingsQuery.error || diff --git a/site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPageView.tsx b/site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPageView.tsx index b700fb119ce67..9d7f4ef0cd515 100644 --- a/site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPageView.tsx +++ b/site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPageView.tsx @@ -14,8 +14,10 @@ import type { Organization, RoleSyncSettings, } from "api/typesGenerated"; +import { ErrorAlert } from "components/Alert/ErrorAlert"; import { ChooseOne, Cond } from "components/Conditionals/ChooseOne"; import { EmptyState } from "components/EmptyState/EmptyState"; +import { Loader } from "components/Loader/Loader"; import { Stack } from "components/Stack/Stack"; import { StatusIndicator } from "components/StatusIndicator/StatusIndicator"; import { @@ -29,8 +31,6 @@ import { MONOSPACE_FONT_FAMILY } from "theme/constants"; import { docs } from "utils/docs"; import { ExportPolicyButton } from "./ExportPolicyButton"; import { IdpPillList } from "./IdpPillList"; -import { ErrorAlert } from "components/Alert/ErrorAlert"; -import { Loader } from "components/Loader/Loader"; interface IdpSyncPageViewProps { groupSyncSettings: GroupSyncSettings | undefined; From 052f9c10ba177f7f8f30f489c1c075e5ad6b13d3 Mon Sep 17 00:00:00 2001 From: Jaayden Halko Date: Thu, 26 Sep 2024 01:10:19 +0000 Subject: [PATCH 5/5] fix: update stories --- .../IdpSyncPage/IdpSyncPageView.stories.tsx | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPageView.stories.tsx b/site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPageView.stories.tsx index d360482105d81..608c62103b543 100644 --- a/site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPageView.stories.tsx +++ b/site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPageView.stories.tsx @@ -23,23 +23,33 @@ for (const group of [MockGroup, MockGroup2]) { groupsMap.set(group.id, group.display_name || group.name); } -export const NotEnabled: Story = { +export const Empty: Story = { args: { - groupSyncSettings: undefined, - roleSyncSettings: undefined, + groupSyncSettings: { + field: "", + mapping: {}, + regex_filter: "", + auto_create_missing_groups: false, + }, + roleSyncSettings: { + field: "", + mapping: {}, + }, + groups: [], groupsMap: undefined, organization: MockOrganization, - isIdpSyncEnabled: false, + error: undefined, }, }; -export const Empty: Story = { +export const HasError: Story = { args: { - groupSyncSettings: undefined, - roleSyncSettings: undefined, - groupsMap: undefined, + groupSyncSettings: MockGroupSyncSettings, + roleSyncSettings: MockRoleSyncSettings, + groups: [MockGroup, MockGroup2], + groupsMap, organization: MockOrganization, - isIdpSyncEnabled: true, + error: "This is a test error", }, }; @@ -47,9 +57,10 @@ export const Default: Story = { args: { groupSyncSettings: MockGroupSyncSettings, roleSyncSettings: MockRoleSyncSettings, + groups: [MockGroup, MockGroup2], groupsMap, organization: MockOrganization, - isIdpSyncEnabled: true, + error: undefined, }, }; @@ -57,8 +68,9 @@ export const MissingGroups: Story = { args: { groupSyncSettings: MockGroupSyncSettings2, roleSyncSettings: MockRoleSyncSettings, + groups: [MockGroup, MockGroup2], groupsMap, organization: MockOrganization, - isIdpSyncEnabled: true, + error: undefined, }, };