Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

feat: create idp sync page skeleton#14543

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
jaaydenh merged 14 commits intomainfromjaaydenh/idp-sync-skeleton
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
Show all changes
14 commits
Select commitHold shift + click to select a range
b2c3e11
feat: initial commit for idp skeleton page
jaaydenhAug 30, 2024
2de6bfc
feat: add optional tooltip icon to settings header
jaaydenhSep 1, 2024
8298346
feat: add help tooltip
jaaydenhSep 1, 2024
a75ad85
feat: add mock data and update pageview for mock data
jaaydenhSep 2, 2024
492ca5f
feat: initial stories
jaaydenhSep 2, 2024
b73ad32
feat: error circle
jaaydenhSep 2, 2024
6e39fcf
feat: cleanup
jaaydenhSep 2, 2024
f2281e9
feat: update StatusIndicator for outlined variant
jaaydenhSep 3, 2024
b83118f
feat: use StatusIndicator instead of Circle
jaaydenhSep 3, 2024
2c2f677
chore: cleanup
jaaydenhSep 3, 2024
1eedda8
fix: remove ternaries in css
jaaydenhSep 4, 2024
3d1fcdb
fix: updates for PR review comments
jaaydenhSep 4, 2024
2059be8
chore: add story for compact empty state
jaaydenhSep 5, 2024
1523025
feat: extract IdpField and improve field spacing
jaaydenhSep 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletionssite/src/components/EmptyState/EmptyState.stories.tsx
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,11 +13,17 @@ const meta: Meta<typeof EmptyState> = {
export default meta;
type Story = StoryObj<typeof EmptyState>;

const Example: Story = {
exportconst Example: Story = {
args: {
description: "It is easy, just click the button below",
cta: <Button>Create workspace</Button>,
},
};

export { Example as EmptyState };
export const Compact: Story = {
args: {
description: "It is easy, just click the button below",
cta: <Button>Create workspace</Button>,
isCompact: true,
},
};
30 changes: 19 additions & 11 deletionssite/src/components/EmptyState/EmptyState.tsx
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,6 +7,7 @@ export interface EmptyStateProps extends HTMLAttributes<HTMLDivElement> {
description?: string | ReactNode;
cta?: ReactNode;
image?: ReactNode;
isCompact?: boolean;
}

/**
Expand All@@ -19,21 +20,28 @@ export const EmptyState: FC<EmptyStateProps> = ({
description,
cta,
image,
isCompact,
...attrs
}) => {
return (
<div
css={{
overflow: "hidden",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
textAlign: "center",
minHeight: 360,
padding: "80px 40px",
position: "relative",
}}
css={[
{
overflow: "hidden",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
textAlign: "center",
minHeight: 360,
padding: "80px 40px",
position: "relative",
},
isCompact && {
minHeight: 180,
padding: "10px 40px",
},
]}
{...attrs}
>
<h5 css={{ fontSize: 24, fontWeight: 500, margin: 0 }}>{message}</h5>
Expand Down
45 changes: 25 additions & 20 deletionssite/src/components/SettingsHeader/SettingsHeader.tsx
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,39 +9,44 @@ interface HeaderProps {
description?: ReactNode;
secondary?: boolean;
docsHref?: string;
tooltip?: ReactNode;
}

export const SettingsHeader: FC<HeaderProps> = ({
title,
description,
docsHref,
secondary,
tooltip,
}) => {
const theme = useTheme();

return (
<Stack alignItems="baseline" direction="row" justifyContent="space-between">
<div css={{ maxWidth: 420, marginBottom: 24 }}>
<h1
css={[
{
fontSize: 32,
fontWeight: 700,
display: "flex",
alignItems: "center",
lineHeight: "initial",
margin: 0,
marginBottom: 4,
gap: 8,
},
secondary && {
fontSize: 24,
fontWeight: 500,
},
]}
>
{title}
</h1>
<Stack direction="row" spacing={1} alignItems="center">
<h1
css={[
{
fontSize: 32,
fontWeight: 700,
display: "flex",
alignItems: "center",
lineHeight: "initial",
margin: 0,
marginBottom: 4,
gap: 8,
},
secondary && {
fontSize: 24,
fontWeight: 500,
},
]}
>
{title}
</h1>
{tooltip}
</Stack>
{description && (
<span
css={{
Expand Down
25 changes: 18 additions & 7 deletionssite/src/components/StatusIndicator/StatusIndicator.tsx
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,19 +4,30 @@ import type { ThemeRole } from "theme/roles";

interface StatusIndicatorProps {
color: ThemeRole;
variant?: "solid" | "outlined";
}

export const StatusIndicator: FC<StatusIndicatorProps> = ({ color }) => {
export const StatusIndicator: FC<StatusIndicatorProps> = ({
color,
variant = "solid",
}) => {
const theme = useTheme();

return (
<div
css={{
height: 8,
width: 8,
borderRadius: 4,
backgroundColor: theme.roles[color].fill.solid,
}}
css={[
{
height: 8,
width: 8,
borderRadius: 4,
},
variant === "solid" && {
backgroundColor: theme.roles[color].fill.solid,
},
variant === "outlined" && {
border: `1px solid ${theme.roles[color].outline}`,
},
]}
/>
);
};
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
import {
HelpTooltip,
HelpTooltipContent,
HelpTooltipLink,
HelpTooltipLinksGroup,
HelpTooltipText,
HelpTooltipTitle,
HelpTooltipTrigger,
} from "components/HelpTooltip/HelpTooltip";
import type { FC } from "react";
import { docs } from "utils/docs";

export const IdpSyncHelpTooltip: FC = () => {
return (
<HelpTooltip>
<HelpTooltipTrigger />
<HelpTooltipContent>
<HelpTooltipTitle>What is IdP Sync?</HelpTooltipTitle>
<HelpTooltipText>
View the current mappings between your external OIDC provider and
Coder. Use the Coder CLI to configure these mappings.
</HelpTooltipText>
<HelpTooltipLinksGroup>
<HelpTooltipLink href={docs("/admin/auth#group-sync-enterprise")}>
Configure IdP Sync
</HelpTooltipLink>
</HelpTooltipLinksGroup>
</HelpTooltipContent>
</HelpTooltip>
);
};
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
importAddIconfrom"@mui/icons-material/AddOutlined";
importLaunchOutlinedfrom"@mui/icons-material/LaunchOutlined";
importButtonfrom"@mui/material/Button";
import{SettingsHeader}from"components/SettingsHeader/SettingsHeader";
import{Stack}from"components/Stack/Stack";
importtype{FC}from"react";
import{Helmet}from"react-helmet-async";
import{LinkasRouterLink}from"react-router-dom";
import{docs}from"utils/docs";
import{pageTitle}from"utils/page";
import{IdpSyncHelpTooltip}from"./IdpSyncHelpTooltip";
importIdpSyncPageViewfrom"./IdpSyncPageView";

constmockOIDCConfig={
allow_signups:true,
client_id:"test",
client_secret:"test",
client_key_file:"test",
client_cert_file:"test",
email_domain:[],
issuer_url:"test",
scopes:[],
ignore_email_verified:true,
username_field:"",
name_field:"",
email_field:"",
auth_url_params:{},
ignore_user_info:true,
organization_field:"",
organization_mapping:{},
organization_assign_default:true,
group_auto_create:false,
group_regex_filter:"^Coder-.*$",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I know this is a mock value, but could I get more context on where this regex is used? Is it strictly server-controlled?

Wondering because the.*$ at the end literally does nothing in this case except make the regex run slower

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

All the data is readonly and for now I just took the value from Steven. Im still learning myself how this feature works.

group_allow_list:[],
groups_field:"groups",
group_mapping:{group1:"developers",group2:"admin",group3:"auditors"},
user_role_field:"roles",
user_role_mapping:{role1:["role1","role2"]},
user_roles_default:[],
sign_in_text:"",
icon_url:"",
signups_disabled_text:"string",
skip_issuer_checks:true,
};

exportconstIdpSyncPage:FC=()=>{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Just calling this out because I don't see anything about this in the commented-out code: do we want to do a redirect if the user navigates to this page iforganization.permissions.editMembers is false?

I know we're using that property to define whether we show the page link in the side navbar, but is there anything stopping someone from navigating to the page directly?

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

@Parkreiner I haven't addressed permissions yet because a permission hasn't been defined for this page. Btw, how do other pages handle this case when the user doesn't have the permissions?

// feature visibility and permissions to be implemented when integrating with backend
// const feats = useFeatureVisibility();
// const { organization: organizationName } = useParams() as {
// organization: string;
// };
// const { organizations } = useOrganizationSettings();
// const organization = organizations?.find((o) => o.name === organizationName);
// const permissionsQuery = useQuery(organizationPermissions(organization?.id));
// const permissions = permissionsQuery.data;

// if (!permissions) {
// return <Loader />;
// }

return(
<>
<Helmet>
<title>{pageTitle("IdP Sync")}</title>
</Helmet>

<Stack
alignItems="baseline"
direction="row"
justifyContent="space-between"
>
<SettingsHeader
title="IdP Sync"
description="Group and role sync mappings (configured outside Coder)."
tooltip={<IdpSyncHelpTooltip/>}
/>
<Stackdirection="row"spacing={2}>
<Button
startIcon={<LaunchOutlined/>}
component="a"
href={docs("/admin/auth#group-sync-enterprise")}
target="_blank"
>
Setup IdP Sync
</Button>
<Buttoncomponent={RouterLink}startIcon={<AddIcon/>}to="export">
Export Policy
</Button>
</Stack>
</Stack>

<IdpSyncPageViewoidcConfig={mockOIDCConfig}/>
</>
);
};

exportdefaultIdpSyncPage;
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
import type { Meta, StoryObj } from "@storybook/react";
import { MockOIDCConfig } from "testHelpers/entities";
import { IdpSyncPageView } from "./IdpSyncPageView";

const meta: Meta<typeof IdpSyncPageView> = {
title: "pages/OrganizationIdpSyncPage",
component: IdpSyncPageView,
};

export default meta;
type Story = StoryObj<typeof IdpSyncPageView>;

export const Empty: Story = {
args: { oidcConfig: undefined },
};

export const Default: Story = {
args: { oidcConfig: MockOIDCConfig },
};
Loading

[8]ページ先頭

©2009-2025 Movatter.jp