Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion web/packages/design/src/Label/Label.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ const kind = ({ kind, theme }: { kind?: LabelKind; theme: Theme }) => {

if (kind === 'outline-warning') {
return {
color: theme.colors.interactive.solid.alert.default,
color: theme.colors.dataVisualisation.primary.sunflower,
backgroundColor: theme.colors.interactive.tonal.alert[0],
borderColor: theme.colors.interactive.tonal.alert[2],
borderWidth: 1,
Expand Down
1 change: 1 addition & 0 deletions web/packages/design/src/ResourceIcon/assets/oracle.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 1 addition & 8 deletions web/packages/design/src/ResourceIcon/assets/strapi.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions web/packages/design/src/ResourceIcon/icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ import onepasswordLight from './assets/onepassword-light.svg?no-inline';
import opencomp from './assets/opencomp.svg?no-inline';
import openid from './assets/openid.svg?no-inline';
import opsgenie from './assets/opsgenie.svg?no-inline';
import oracle from './assets/oracle.svg?no-inline';
import orbitLove from './assets/orbit.love.svg?no-inline';
import orcasecurityDark from './assets/orcasecurity-dark.svg?no-inline';
import orcasecurityLight from './assets/orcasecurity-light.svg?no-inline';
Expand Down Expand Up @@ -522,6 +523,7 @@ export {
opencomp,
openid,
opsgenie,
oracle,
orbitLove,
orcasecurityDark,
orcasecurityLight,
Expand Down
49 changes: 35 additions & 14 deletions web/packages/design/src/ResourceIcon/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
*/

import { ComponentProps } from 'react';
import { useTheme } from 'styled-components';
import styled, { useTheme } from 'styled-components';

import { Image } from 'design';
import { Flex, Image } from 'design';
import { IconProps } from 'design/Icon/Icon';

import {
Expand Down Expand Up @@ -51,32 +51,53 @@ export const ResourceIcon = ({ name, ...props }: ResourceIconProps) => {
if (!icon) {
return null;
}
const width = props.size ? sizetoPx(props.size) : props.width;
const height = props.size ? sizetoPx(props.size) : props.height;
return (
<Image
src={icon}
data-testid={`res-icon-${name}`}
{...props}
width={width}
height={height}
/>
);
if (props.size) {
const width = sizetoInnerPx(props.size);
const height = sizetoInnerPx(props.size);
return (
<Container $size={props.size}>
<Image
src={icon}
data-testid={`res-icon-${name}`}
{...props}
width={width}
height={height}
/>
</Container>
);
}

return <Image src={icon} data-testid={`res-icon-${name}`} {...props} />;
};

const Container = styled(Flex)<{ $size: IconProps['size'] }>`
width: ${props => sizetoOuterPx(props.$size)};
height: ${props => sizetoOuterPx(props.$size)};
align-items: center;
justify-content: center;
`;

/**
* Convert a standard size to a pixel width/height. This is different to the
* conversion done for Icons as they include in-asset padding.
*
* @param size the standard size to convert.
* @returns the pixel size
*/
function sizetoPx(size: IconProps['size']) {
function sizetoInnerPx(size: IconProps['size']) {
if (size === 'small') return '14px';
if (size === 'medium') return '16px';
if (size === 'large') return '20px';
if (size === 'extra-large') return '24px';
return '24px';
}

function sizetoOuterPx(size: IconProps['size']) {
if (size === 'small') return '16px';
if (size === 'medium') return '20px';
if (size === 'large') return '24px';
if (size === 'extra-large') return '32px';
return '32px';
}

export { type ResourceIconName, resourceIconSpecs, iconNames };
1 change: 1 addition & 0 deletions web/packages/design/src/ResourceIcon/resourceIconSpecs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ export const resourceIconSpecs = {
openid: forAllThemes(i.openid),
opsgenie: forAllThemes(i.opsgenie),
'orbit.love': forAllThemes(i.orbitLove),
oracle: forAllThemes(i.oracle),
orcasecurity: { dark: i.orcasecurityDark, light: i.orcasecurityLight },
'outreach.io': forAllThemes(i.outreachIo),

Expand Down
51 changes: 48 additions & 3 deletions web/packages/teleport/src/Bots/Details/BotDetails.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,52 @@ export const HappyWithEmpty: Story = {
},
};

export const HappyWithTypical: Story = {
parameters: {
msw: {
handlers: [
getBotSuccess({
name: 'ansible-worker',
roles: ['access'],
traits: [],
max_session_ttl: {
seconds: 43200,
},
}),
listV2TokensSuccess({
tokens: ['kubernetes'],
}),
mfaAuthnChallengeSuccess(),
listBotInstancesSuccess({
bot_instances: [
{
bot_name: 'bot-1',
instance_id: '6570dbf1-3530-4e13-a8c7-497bb9927994',
active_at_latest: new Date().toISOString(),
host_name_latest:
'my-svc.my-namespace.svc.cluster-domain.example',
join_method_latest: 'kubernetes',
os_latest: 'linux',
version_latest: '18.1.0',
},
],
next_page_token: '',
}),
successGetRoles({
startKey: '',
items: Array.from({ length: 10 }, (_, k) => k).map(r => ({
content: `role-${r}`,
id: `role-${r}`,
name: `role-${r}`,
kind: 'role',
})),
}),
editBotSuccess(),
],
},
},
};

export const HappyWithLongValues: Story = {
parameters: {
msw: {
Expand Down Expand Up @@ -182,8 +228,7 @@ export const HappyWithLongValues: Story = {
active_at_latest: '2025-01-01T00:00:00Z',
join_method_latest: 'github',
os_latest: 'linux',
version_latest:
'17.2.6-04241a2a66b904241a2a66b904241a2a66b904241a2a66b9',
version_latest: '17.2.6-04241a2',
},
],
next_page_token: '',
Expand Down Expand Up @@ -444,7 +489,7 @@ function Wrapper(props?: {
<TeleportProviderBasic teleportCtx={ctx}>
<Router history={history}>
<Route path={cfg.routes.bot}>
<Box height={800} overflow={'auto'}>
<Box height={820} overflow={'auto'}>
<BotDetails />
</Box>
</Route>
Expand Down
23 changes: 12 additions & 11 deletions web/packages/teleport/src/Bots/Details/BotDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -348,18 +348,14 @@ function Trait(props: { traitName: string }) {

const description = traitDescriptions[props.traitName];

const help = (
<Question
size={'small'}
color={theme.colors.interactive.tonal.neutral[3]}
/>
);

return description ? (
<Flex gap={1}>
{props.traitName}
<HoverTooltip placement="top" tipContent={description}>
{help}
<Question
size={'small'}
color={theme.colors.interactive.tonal.neutral[3]}
/>
</HoverTooltip>
</Flex>
) : (
Expand Down Expand Up @@ -445,11 +441,16 @@ function JoinTokens(props: { botName: string; onViewAllClicked: () => void }) {
placement="top"
tipContent={t.method}
>
<SecondaryOutlined>
<Flex alignItems={'center'} gap={1}>
<SecondaryOutlined padding={0}>
<Flex
alignItems={'center'}
gap={1}
padding={1}
paddingRight={2}
>
<JoinMethodIcon
method={t.method}
size={'small'}
size={'large'}
includeTooltip={false}
/>
<LabelText>{t.safeName}</LabelText>
Expand Down
4 changes: 2 additions & 2 deletions web/packages/teleport/src/Bots/Details/Instance.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export const Item: Story = {
args: {
id: '686750f5-0f21-4a6f-b151-fa11a603701d',
activeAt: new Date('2025-07-18T14:54:32Z').getTime(),
hostname: 'hostname',
hostname: 'my-svc.my-namespace.svc.cluster-domain.example',
method: 'kubernetes',
version: '4.4.0',
os: 'linux',
Expand All @@ -77,7 +77,7 @@ export const ItemWithLongValues: Story = {
activeAt: new Date('2025-07-18T14:54:32Z').getTime(),
hostname: 'hostnamehostnamehostnamehostnamehostnamehostnamehostnamehostnam',
method: 'kubernetes',
version: '4.4.0-fa11a603701dfa11a603701dfa11a603701dfa11a603701dfa11a6031d',
version: '4.4.0-fa11a60',
os: 'linux',
},
};
Expand Down
68 changes: 34 additions & 34 deletions web/packages/teleport/src/Bots/Details/Instance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,35 +63,36 @@ export function Instance(props: {
</TopRow>
{hasHeartbeatData ? (
<BottomRow>
<Flex gap={2} flex={1}>
<Flex gap={2} flex={1} overflow={'hidden'} alignItems={'flex-end'}>
<Version version={version} />

{hostname ? (
<HoverTooltip placement="top" tipContent={'Hostname'}>
<HoverTooltip
placement="top"
tipContent={`Hostname: ${hostname}`}
>
<SecondaryOutlined borderRadius={2}>
<LabelText>{hostname}</LabelText>
<HostnameText>{hostname}</HostnameText>
</SecondaryOutlined>
</HoverTooltip>
) : undefined}
</Flex>
<Flex gap={2}>
{method ? (
<JoinMethodIcon method={method} size={'medium'} />
<JoinMethodIcon method={method} size={'large'} />
) : undefined}

{os ? (
<HoverTooltip placement="top" tipContent={os}>
<OsIconContainer>
{os === 'darwin' ? (
<ResourceIcon name={'apple'} width={'16px'} />
) : os === 'windows' ? (
<ResourceIcon name={'windows'} width={'16px'} />
) : os === 'linux' ? (
<ResourceIcon name={'linux'} width={'16px'} />
) : (
<ResourceIcon name={'server'} width={'16px'} />
)}
</OsIconContainer>
{os === 'darwin' ? (
<ResourceIcon name={'apple'} size={'large'} />
) : os === 'windows' ? (
<ResourceIcon name={'windows'} size={'large'} />
) : os === 'linux' ? (
<ResourceIcon name={'linux'} size={'large'} />
) : (
<ResourceIcon name={'server'} size={'large'} />
)}
</HoverTooltip>
) : undefined}
</Flex>
Expand Down Expand Up @@ -126,13 +127,6 @@ const BottomRow = styled(Flex)`
overflow: hidden;
`;

const OsIconContainer = styled(Flex)`
width: 20px; // Intentionally not a theme value
height: 20px; // Intentionally not a theme value
align-items: center;
justify-content: center;
`;

const EmptyText = styled(Text)`
color: ${p => p.theme.colors.text.muted};
`;
Expand All @@ -148,6 +142,12 @@ const IdText = styled(Text)`
white-space: nowrap;
`;

const HostnameText = styled(Text).attrs({
typography: 'body3',
})`
white-space: nowrap;
`;

function Version(props: { version: string | undefined }) {
const { version } = props;
const { checkCompatibility } = useClusterVersion();
Expand Down Expand Up @@ -186,19 +186,19 @@ function Version(props: { version: string | undefined }) {
}

return version ? (
<HoverTooltip placement="top" tipContent={tooltip}>
<Wrapper borderRadius={2}>
<Flex gap={1}>
{icon}
<LabelText>v{version}</LabelText>
</Flex>
</Wrapper>
</HoverTooltip>
<VersionContainer>
<HoverTooltip placement="top" tipContent={tooltip}>
<Wrapper borderRadius={2}>
<Flex gap={1}>
{icon}
<Text typography="body3">v{version}</Text>
</Flex>
</Wrapper>
</HoverTooltip>
</VersionContainer>
) : undefined;
}

const LabelText = styled(Text)`
font-size: ${({ theme }) => theme.fontSizes[1]}px;
white-space: nowrap;
max-width: 96px;
const VersionContainer = styled.div`
flex-shrink: 0;
`;
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export const listBotInstancesSuccessHandler = listBotInstancesSuccess({
bot_name: 'ansible-worker',
instance_id: crypto.randomUUID(),
active_at_latest: '2025-07-22T10:54:00Z',
host_name_latest: 'svr-lon-01-ab23cd',
host_name_latest: 'my-svc.my-namespace.svc.cluster-domain.example',
join_method_latest: 'github',
os_latest: 'linux',
version_latest: '4.4.0',
Expand Down
Loading
Loading