From bc268b2a39a6ea55b721d05002c59965f61efbb0 Mon Sep 17 00:00:00 2001 From: Yassine Bounekhla Date: Mon, 30 Dec 2024 14:56:19 -0500 Subject: [PATCH] update auth connectors page --- web/packages/design/src/Icon/Icons.story.tsx | 2 + .../design/src/Icon/Icons/MinusCircle.tsx | 67 ++++++ .../design/src/Icon/Icons/RocketLaunch.tsx | 67 ++++++ .../design/src/Icon/assets/MinusCircle.svg | 4 + .../design/src/Icon/assets/RocketLaunch.svg | 4 + web/packages/design/src/Icon/index.ts | 2 + .../design/src/Icon/script/IconTemplate.txt | 2 - .../src/ResourceIcon/assets/okta-alt.svg | 9 + web/packages/design/src/ResourceIcon/icons.ts | 2 + .../src/ResourceIcon/resourceIconSpecs.ts | 1 + .../src/AuthConnectors/AuthConnectorTile.tsx | 210 ++++++++++++++++++ .../src/AuthConnectors/AuthConnectors.tsx | 62 +++--- .../ConnectorList/CTAConnectors.tsx | 120 ++++++++++ .../ConnectorList/ConnectorList.tsx | 73 ++---- .../AuthConnectors/EmptyList/EmptyList.tsx | 83 ++----- .../AuthConnectors/ssoIcons/getSsoIcon.tsx | 169 ++++++++------ .../styles/ConnectorBox.styles.ts | 72 ------ 17 files changed, 665 insertions(+), 284 deletions(-) create mode 100644 web/packages/design/src/Icon/Icons/MinusCircle.tsx create mode 100644 web/packages/design/src/Icon/Icons/RocketLaunch.tsx create mode 100644 web/packages/design/src/Icon/assets/MinusCircle.svg create mode 100644 web/packages/design/src/Icon/assets/RocketLaunch.svg create mode 100644 web/packages/design/src/ResourceIcon/assets/okta-alt.svg create mode 100644 web/packages/teleport/src/AuthConnectors/AuthConnectorTile.tsx create mode 100644 web/packages/teleport/src/AuthConnectors/ConnectorList/CTAConnectors.tsx delete mode 100644 web/packages/teleport/src/AuthConnectors/styles/ConnectorBox.styles.ts diff --git a/web/packages/design/src/Icon/Icons.story.tsx b/web/packages/design/src/Icon/Icons.story.tsx index 47807a6715ae9..b405bec830973 100644 --- a/web/packages/design/src/Icon/Icons.story.tsx +++ b/web/packages/design/src/Icon/Icons.story.tsx @@ -163,6 +163,7 @@ export const Icons = () => ( + @@ -186,6 +187,7 @@ export const Icons = () => ( + diff --git a/web/packages/design/src/Icon/Icons/MinusCircle.tsx b/web/packages/design/src/Icon/Icons/MinusCircle.tsx new file mode 100644 index 0000000000000..fe3a181ffd912 --- /dev/null +++ b/web/packages/design/src/Icon/Icons/MinusCircle.tsx @@ -0,0 +1,67 @@ +/** + * Teleport + * Copyright (C) 2023 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +/* MIT License + +Copyright (c) 2020 Phosphor Icons + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +import { Icon, IconProps } from '../Icon'; + +/* + +THIS FILE IS GENERATED. DO NOT EDIT. + +*/ + +export function MinusCircle({ size = 24, color, ...otherProps }: IconProps) { + return ( + + + + + ); +} diff --git a/web/packages/design/src/Icon/Icons/RocketLaunch.tsx b/web/packages/design/src/Icon/Icons/RocketLaunch.tsx new file mode 100644 index 0000000000000..500dc5d066453 --- /dev/null +++ b/web/packages/design/src/Icon/Icons/RocketLaunch.tsx @@ -0,0 +1,67 @@ +/** + * Teleport + * Copyright (C) 2023 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +/* MIT License + +Copyright (c) 2020 Phosphor Icons + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +import { Icon, IconProps } from '../Icon'; + +/* + +THIS FILE IS GENERATED. DO NOT EDIT. + +*/ + +export function RocketLaunch({ size = 24, color, ...otherProps }: IconProps) { + return ( + + + + + ); +} diff --git a/web/packages/design/src/Icon/assets/MinusCircle.svg b/web/packages/design/src/Icon/assets/MinusCircle.svg new file mode 100644 index 0000000000000..1058d09b4e10d --- /dev/null +++ b/web/packages/design/src/Icon/assets/MinusCircle.svg @@ -0,0 +1,4 @@ + + + + diff --git a/web/packages/design/src/Icon/assets/RocketLaunch.svg b/web/packages/design/src/Icon/assets/RocketLaunch.svg new file mode 100644 index 0000000000000..e25ea62128692 --- /dev/null +++ b/web/packages/design/src/Icon/assets/RocketLaunch.svg @@ -0,0 +1,4 @@ + + + + diff --git a/web/packages/design/src/Icon/index.ts b/web/packages/design/src/Icon/index.ts index be8d7320be71b..79a733b145bb2 100644 --- a/web/packages/design/src/Icon/index.ts +++ b/web/packages/design/src/Icon/index.ts @@ -149,6 +149,7 @@ export { MagnifyingMinus } from './Icons/MagnifyingMinus'; export { MagnifyingPlus } from './Icons/MagnifyingPlus'; export { Memory } from './Icons/Memory'; export { Minus } from './Icons/Minus'; +export { MinusCircle } from './Icons/MinusCircle'; export { Moon } from './Icons/Moon'; export { MoreHoriz } from './Icons/MoreHoriz'; export { MoreVert } from './Icons/MoreVert'; @@ -172,6 +173,7 @@ export { PushPinFilled } from './Icons/PushPinFilled'; export { Question } from './Icons/Question'; export { Refresh } from './Icons/Refresh'; export { Restore } from './Icons/Restore'; +export { RocketLaunch } from './Icons/RocketLaunch'; export { Rows } from './Icons/Rows'; export { Ruler } from './Icons/Ruler'; export { Run } from './Icons/Run'; diff --git a/web/packages/design/src/Icon/script/IconTemplate.txt b/web/packages/design/src/Icon/script/IconTemplate.txt index 7ba34ed3fa097..e204eb99dfa0e 100644 --- a/web/packages/design/src/Icon/script/IconTemplate.txt +++ b/web/packages/design/src/Icon/script/IconTemplate.txt @@ -40,8 +40,6 @@ SOFTWARE. */ -import React from 'react'; - import { Icon, IconProps } from '../Icon'; /* diff --git a/web/packages/design/src/ResourceIcon/assets/okta-alt.svg b/web/packages/design/src/ResourceIcon/assets/okta-alt.svg new file mode 100644 index 0000000000000..c3c6e69a08c80 --- /dev/null +++ b/web/packages/design/src/ResourceIcon/assets/okta-alt.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/web/packages/design/src/ResourceIcon/icons.ts b/web/packages/design/src/ResourceIcon/icons.ts index fccf86a27aeff..88c24d2a33ecb 100644 --- a/web/packages/design/src/ResourceIcon/icons.ts +++ b/web/packages/design/src/ResourceIcon/icons.ts @@ -211,6 +211,7 @@ import notion from './assets/notion.svg'; import oasisopen from './assets/oasisopen.svg'; import oktaDark from './assets/okta-dark.svg'; import oktaLight from './assets/okta-light.svg'; +import oktaAlt from './assets/okta-alt.svg'; import onehundredonedomain from './assets/onehundredonedomain.svg'; import oneloginDark from './assets/onelogin-dark.svg'; import oneloginLight from './assets/onelogin-light.svg'; @@ -499,6 +500,7 @@ export { oasisopen, oktaDark, oktaLight, + oktaAlt, onehundredonedomain, oneloginDark, oneloginLight, diff --git a/web/packages/design/src/ResourceIcon/resourceIconSpecs.ts b/web/packages/design/src/ResourceIcon/resourceIconSpecs.ts index 67021894b7ad9..ab45fd7d8d4b9 100644 --- a/web/packages/design/src/ResourceIcon/resourceIconSpecs.ts +++ b/web/packages/design/src/ResourceIcon/resourceIconSpecs.ts @@ -196,6 +196,7 @@ export const resourceIconSpecs = { oasisopen: forAllThemes(i.oasisopen), okta: { dark: i.oktaDark, light: i.oktaLight }, + oktaAlt: forAllThemes(i.oktaAlt), '101domain': forAllThemes(i.onehundredonedomain), onelogin: { dark: i.oneloginDark, light: i.oneloginLight }, '1password': { dark: i.onepasswordDark, light: i.onepasswordLight }, diff --git a/web/packages/teleport/src/AuthConnectors/AuthConnectorTile.tsx b/web/packages/teleport/src/AuthConnectors/AuthConnectorTile.tsx new file mode 100644 index 0000000000000..e69ab077c8219 --- /dev/null +++ b/web/packages/teleport/src/AuthConnectors/AuthConnectorTile.tsx @@ -0,0 +1,210 @@ +/** + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import styled, { useTheme } from 'styled-components'; + +import { Flex, H2, Subtitle2, ButtonSecondary, P3, Box } from 'design'; +import { ArrowRight, CircleCheck, Password } from 'design/Icon'; + +import { MenuIcon, MenuItem } from 'shared/components/MenuAction'; +import { AuthType } from 'shared/services'; + +import { State as ResourceState } from 'teleport/components/useResources'; + +export function AuthConnectorTile({ + id, + name, + kind, + Icon, + isDefault, + isPlaceholder, + onSetup, + customDesc, + onEdit, + onDelete, +}: { + name: string; + id: string; + kind: AuthType; + Icon: () => JSX.Element; + isDefault: boolean; + /** + * isPlaceholder is whether this isn't a real existing connector, but a placeholder as a shortcut to set one up. + */ + isPlaceholder: boolean; + onSetup?: () => void; + customDesc?: string; + onEdit?: ResourceState['edit']; + onDelete?: ResourceState['remove']; +}) { + const theme = useTheme(); + const onClickEdit = () => onEdit(id); + const onClickDelete = () => onDelete(id); + + let desc: string; + switch (kind) { + case 'github': + desc = 'GitHub Connector'; + break; + case 'oidc': + desc = 'OIDC Connector'; + break; + case 'saml': + desc = 'SAML Connector'; + break; + default: + kind satisfies never | 'local'; + } + + return ( + + + + + +

{name}

+ {isDefault && } +
+ + {customDesc || desc} + +
+
+ + {isPlaceholder && !!onSetup && ( + + Set Up + + )} + {!isPlaceholder && !!onEdit && !!onDelete && ( + + Edit + Delete + + )} + +
+ ); +} + +/** + * LocalConnectorTile is a hardcoded "auth connector" which represents local auth. + */ +export function LocalConnectorTile() { + return ( + ( + + props.theme.colors.interactive.tonal.neutral[0]}; + height: 61px; + width: 61px; + `} + lineHeight={0} + p={2} + borderRadius={3} + > + + + )} + isDefault={true} + isPlaceholder={false} + name="Local Connector" + customDesc="Manual auth w/ users local to Teleport" + /> + ); +} + +export const ConnectorBox = styled(Box)<{ disabled?: boolean }>` + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: flex-start; + font-family: ${props => props.theme.font}; + padding: ${p => p.theme.space[3]}px; + transition: all 0.3s; + border-radius: ${props => props.theme.radii[2]}px; + border: ${props => props.theme.borders[2]} + ${props => props.theme.colors.interactive.tonal.neutral[0]}; + + &:hover { + background: ${props => props.theme.colors.levels.surface}; + border: ${props => props.theme.borders[2]} transparent; + } + + &:focus-visible { + outline: none; + border: ${props => props.theme.borders[2]} + ${props => props.theme.colors.text.muted}; + } + + &:active { + outline: none; + background: ${props => props.theme.colors.levels.surface}; + border: ${props => props.theme.borders[2]} + ${props => props.theme.colors.interactive.tonal.neutral[1]}; + } +`; + +function DefaultIndicator() { + return ( + + props.theme.colors.interactive.tonal.success[1]}; + border-radius: 62px; + `} + > + + + Default + + + ); +} diff --git a/web/packages/teleport/src/AuthConnectors/AuthConnectors.tsx b/web/packages/teleport/src/AuthConnectors/AuthConnectors.tsx index fc16cfe7d20a3..6f0b297c4bdf5 100644 --- a/web/packages/teleport/src/AuthConnectors/AuthConnectors.tsx +++ b/web/packages/teleport/src/AuthConnectors/AuthConnectors.tsx @@ -18,7 +18,7 @@ import { Alert, Box, Flex, H3, Indicator, Link } from 'design'; -import { P } from 'design/Text/Text'; +import { H2, P } from 'design/Text/Text'; import { FeatureBox, FeatureHeaderTitle } from 'teleport/components/Layout'; import ResourceEditor from 'teleport/components/ResourceEditor'; @@ -36,6 +36,7 @@ import ConnectorList from './ConnectorList'; import DeleteConnectorDialog from './DeleteConnectorDialog'; import useAuthConnectors, { State } from './useAuthConnectors'; import templates from './templates'; +import CTAConnectors from './ConnectorList/CTAConnectors'; export function AuthConnectorsContainer() { const state = useAuthConnectors(); @@ -80,34 +81,37 @@ export function AuthConnectors(props: State) { )} {attempt.status === 'success' && ( - {isEmpty && ( - - resources.create('github')} /> - - )} - <> - - -

Auth Connectors

-

{description}

-

- Please{' '} - - view our documentation - {' '} - on how to configure a GitHub connector. -

-
- + + +

Your Connectors

+ {isEmpty ? ( + resources.create('github')} /> + ) : ( + + )} +
+ +
+ +

Auth Connectors

+

{description}

+

+ Please{' '} + + view our documentation + {' '} + on how to configure a GitHub connector. +

+
)} {(resources.status === 'creating' || resources.status === 'editing') && ( diff --git a/web/packages/teleport/src/AuthConnectors/ConnectorList/CTAConnectors.tsx b/web/packages/teleport/src/AuthConnectors/ConnectorList/CTAConnectors.tsx new file mode 100644 index 0000000000000..117b02e4236d6 --- /dev/null +++ b/web/packages/teleport/src/AuthConnectors/ConnectorList/CTAConnectors.tsx @@ -0,0 +1,120 @@ +/** + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import styled from 'styled-components'; + +import Box from 'design/Box'; +import { ResourceIcon } from 'design/ResourceIcon'; +import { H2, Subtitle2 } from 'design/Text'; +import Flex from 'design/Flex'; +import { RocketLaunch } from 'design/Icon'; + +import { ButtonLockedFeature } from 'teleport/components/ButtonLockedFeature'; +import { CtaEvent } from 'teleport/services/userEvent'; + +export default function CTAConnectors() { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + +

Unlock OIDC & SAML Single Sign-On with Teleport Enterprise

+ + Connect your identity provider to streamline employee onboarding, + simplify compliance, and monitor access patterns against a single + source of truth. + + + + Upgrade to Enterprise + +
+
+ ); +} + +const AuthConnectorsCTABox = styled(Box)` + width: 100%; + padding: ${p => p.theme.space[5]}px; + + border: ${props => props.theme.borders[1]}; + border-color: ${props => props.theme.colors.interactive.tonal.neutral[1]}; + border-radius: ${props => props.theme.radii[2]}px; + background: transparent; + + display: flex; + flex-direction: column; + align-items: flex-start; + gap: ${p => p.theme.space[3]}px; + align-self: stretch; +`; + +const CTALogosContainer = styled(Box)` + display: flex; + flex-direction: row; + width: 100%; + // We have to manually set a height here since the CTALogo's are 'position: absolute' and won't automatically size the container. + //padding (top and bottom) + height of the icon + height: ${p => p.theme.space[4] * 2 + 36}px; + + position: relative; +`; + +const CTALogo = styled(Box)` + background-color: ${props => props.theme.colors.levels.sunken}; + padding: ${p => p.theme.space[4]}px; + + display: flex; + align-items: center; + justify-content: center; + + border: ${props => props.theme.borders[1]}; + border-color: ${props => props.theme.colors.interactive.tonal.neutral[1]}; + border-radius: 50%; + + position: absolute; +`; diff --git a/web/packages/teleport/src/AuthConnectors/ConnectorList/ConnectorList.tsx b/web/packages/teleport/src/AuthConnectors/ConnectorList/ConnectorList.tsx index 39544ef9bda3b..8f3605b4044a1 100644 --- a/web/packages/teleport/src/AuthConnectors/ConnectorList/ConnectorList.tsx +++ b/web/packages/teleport/src/AuthConnectors/ConnectorList/ConnectorList.tsx @@ -16,23 +16,31 @@ * along with this program. If not, see . */ -import { Box, ButtonPrimary, Flex, ResourceIcon, Text } from 'design'; -import { MenuIcon, MenuItem } from 'shared/components/MenuAction'; +import styled from 'styled-components'; -import { State as ResourceState } from 'teleport/components/useResources'; +import { Box } from 'design'; -import { ResponsiveConnector } from 'teleport/AuthConnectors/styles/ConnectorBox.styles'; +import { State as ResourceState } from 'teleport/components/useResources'; import { State as AuthConnectorState } from '../useAuthConnectors'; +import { AuthConnectorTile, LocalConnectorTile } from '../AuthConnectorTile'; +import getSsoIcon from '../ssoIcons/getSsoIcon'; export default function ConnectorList({ items, onEdit, onDelete }: Props) { items = items || []; const $items = items.map(item => { - const { id, name } = item; + const { id, name, kind } = item; + + const Icon = getSsoIcon(kind, name); + return ( - + + {$items} - - ); -} - -function ConnectorListItem({ name, id, onEdit, onDelete }) { - const onClickEdit = () => onEdit(id); - const onClickDelete = () => onDelete(id); - - return ( - - - - Delete... - - - - - - - - {name} - - - - Edit Connector - - + ); } -const menuActionProps = { - style: { - right: '10px', - position: 'absolute', - top: '10px', - }, -}; - type Props = { items: AuthConnectorState['items']; onEdit: ResourceState['edit']; onDelete: ResourceState['remove']; }; + +export const AuthConnectorsGrid = styled(Box)` + width: 100%; + display: grid; + gap: ${p => p.theme.space[3]}px; + grid-template-columns: repeat(auto-fill, minmax(360px, 1fr)); +`; diff --git a/web/packages/teleport/src/AuthConnectors/EmptyList/EmptyList.tsx b/web/packages/teleport/src/AuthConnectors/EmptyList/EmptyList.tsx index b3dd5ea561647..0751eb31347f8 100644 --- a/web/packages/teleport/src/AuthConnectors/EmptyList/EmptyList.tsx +++ b/web/packages/teleport/src/AuthConnectors/EmptyList/EmptyList.tsx @@ -16,78 +16,27 @@ * along with this program. If not, see . */ -import { Card, Flex, H1, ResourceIcon, Text } from 'design'; -import { AuthProviderType } from 'shared/services'; - -import { H2 } from 'design'; - -import { ConnectorBox } from 'teleport/AuthConnectors/styles/ConnectorBox.styles'; - -import { - LockedFeatureButton, - LockedFeatureContainer, -} from 'teleport/AuthConnectors/styles/LockedFeatureContainer.styles'; - import getSsoIcon from 'teleport/AuthConnectors/ssoIcons/getSsoIcon'; import { State as ResourceState } from 'teleport/components/useResources'; -import { CtaEvent } from 'teleport/services/userEvent'; - -export default function EmptyList({ onCreate }: Props) { - return ( - -

Select a service provider below

- - {renderGithubConnector(onCreate)} - - {renderLockedItem('oidc')} - {renderLockedItem('saml')} - - Unlock OIDC & SAML with Teleport Enterprise - - - -
- ); -} -function renderGithubConnector(onCreate) { - return ( - - - - - - +import { AuthConnectorTile, LocalConnectorTile } from '../AuthConnectorTile'; +import { AuthConnectorsGrid } from '../ConnectorList/ConnectorList'; -

GitHub

- { - - Sign in using your GitHub account - - } -
- ); -} - -function renderLockedItem(kind: AuthProviderType) { - const { desc, SsoIcon, info } = getSsoIcon(kind); +export default function EmptyList({ onCreate }: Props) { return ( - - - - -

{desc}

- {info && ( - - {info} - - )} -
+ + + onCreate('github')} + /> + ); } diff --git a/web/packages/teleport/src/AuthConnectors/ssoIcons/getSsoIcon.tsx b/web/packages/teleport/src/AuthConnectors/ssoIcons/getSsoIcon.tsx index 27fae0e56fd9a..fbb116b59f3f2 100644 --- a/web/packages/teleport/src/AuthConnectors/ssoIcons/getSsoIcon.tsx +++ b/web/packages/teleport/src/AuthConnectors/ssoIcons/getSsoIcon.tsx @@ -20,93 +20,132 @@ import styled from 'styled-components'; import { AuthProviderType } from 'shared/services'; import { Box, Flex, ResourceIcon } from 'design'; -export default function getSsoIcon(kind: AuthProviderType) { - const desc = formatConnectorTypeDesc(kind); +export default function getSsoIcon( + kind: AuthProviderType, + name?: string +): () => JSX.Element { + const guessedIcon = guessIconFromName(name || ''); + if (guessedIcon) { + return guessedIcon; + } switch (kind) { case 'github': - return { - SsoIcon: () => ( - - - - ), - desc, - info: 'Sign in using your GitHub account', - }; + return () => ( + + + + ); case 'saml': - return { - SsoIcon: () => ( - - - - - - - - - - - - - - - ), - desc, - info: 'Okta, OneLogin, Microsoft Entra ID, etc.', - }; + return () => ( + + + + + + + + + + + + + + + ); case 'oidc': default: - return { - SsoIcon: () => ( - - - - - - - - - - - - - - - ), - desc, - info: 'Google, GitLab, Amazon and more', - }; + return () => ( + + + + + + + + + + + + + + + ); } } -function formatConnectorTypeDesc(kind) { - kind = kind || ''; - if (kind == 'github') { - return `GitHub`; +function guessIconFromName(connectorName: string) { + const name = connectorName.toLocaleLowerCase(); + + if (name.includes('okta')) { + return () => ( + + + + ); + } + if ( + name.includes('entra') || + name.includes('active directory') || + name.includes('microsoft') || + name.includes('azure') + ) { + return () => ( + + + + ); + } + if (name.includes('google')) { + return () => ( + + + + ); + } + if (name.includes('gitlab')) { + return () => ( + + + + ); + } + if (name.includes('onelogin')) { + return () => ( + + + + ); + } + if (name.includes('auth0') || name.includes('authzero')) { + return () => ( + + + + ); } - return kind.toUpperCase(); } const MultiIconContainer = styled(Flex)` - width: 83px; + width: 61px; + height: 61px; flex-wrap: wrap; gap: 3px; - padding: 7px; - border: 1px solid rgba(255, 255, 255, 0.07); + padding: ${p => p.theme.space[2]}px; + border: 1px solid ${p => p.theme.colors.interactive.tonal.neutral[2]}; border-radius: 8px; `; const SmIcon = styled(Box)` - width: ${p => p.theme.space[5]}px; - height: ${p => p.theme.space[5]}px; - line-height: ${p => p.theme.space[5]}px; - background: ${p => p.theme.colors.levels.popout}; - border-radius: 50%; + width: 20px; + height: 20px; display: flex; justify-content: center; + align-items: center; `; const StyledResourceIcon = styled(ResourceIcon).attrs({ width: '20px', -})``; +})` + line-height: 0px !important; +`; diff --git a/web/packages/teleport/src/AuthConnectors/styles/ConnectorBox.styles.ts b/web/packages/teleport/src/AuthConnectors/styles/ConnectorBox.styles.ts deleted file mode 100644 index f88e5e7ad5646..0000000000000 --- a/web/packages/teleport/src/AuthConnectors/styles/ConnectorBox.styles.ts +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Teleport - * Copyright (C) 2023 Gravitational, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -import { Box, Flex } from 'design'; -import styled from 'styled-components'; - -export const ConnectorBox = styled(Box)` - display: flex; - flex-direction: column; - font-family: ${props => props.theme.font}; - width: 320px; - padding: ${p => p.theme.space[4]}px; - margin: ${p => p.theme.space[3]}px ${p => p.theme.space[2]}px; - background: transparent; - transition: all 0.3s; - border-radius: ${props => props.theme.radii[2]}px; - min-height: 190px; - border: ${props => props.theme.borders[2]} - ${p => p.theme.colors.spotBackground[0]}; - - &:hover, - &:focus { - border: ${props => props.theme.borders[2]} - ${p => p.theme.colors.spotBackground[2]}; - background: ${p => p.theme.colors.spotBackground[0]}; - box-shadow: ${p => p.theme.boxShadow[3]}; - cursor: pointer; - } - - &:disabled { - cursor: not-allowed; - color: inherit; - font-family: inherit; - outline: none; - position: relative; - text-align: center; - text-decoration: none; - opacity: 0.24; - box-shadow: none; - } -`; - -export const ResponsiveConnector = styled(Flex)` - position: relative; - box-shadow: ${p => p.theme.boxShadow[5]}; - width: 240px; - height: 240px; - border-radius: ${props => props.theme.radii[2]}px; - flex-direction: column; - align-items: center; - justify-content: center; - background-color: ${props => props.theme.colors.levels.surface}; - padding: ${props => props.theme.space[5]}px; - @media screen and (max-width: ${props => props.theme.breakpoints.tablet}px) { - width: 100%; - } -`;