Skip to content

Commit

Permalink
Update aws launch buttons with searchable fields
Browse files Browse the repository at this point in the history
  • Loading branch information
avatus authored and github-actions committed Mar 27, 2024
1 parent f332899 commit 57fb040
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 20 deletions.
94 changes: 76 additions & 18 deletions web/packages/shared/components/AwsLaunchButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@

import React from 'react';
import styled from 'styled-components';
import { ButtonBorder, Text } from 'design';
import { space } from 'design/system';
import { ButtonBorder, Flex, Text, Box } from 'design';
import Menu, { MenuItem } from 'design/Menu';
import { ChevronDown } from 'design/Icon';

Expand All @@ -30,14 +31,19 @@ export class AwsLaunchButton extends React.Component<Props> {
state = {
open: false,
anchorEl: null,
filtered: '',
};

onOpen = () => {
this.setState({ open: true });
this.setState({ open: true, filtered: '' });
};

onClose = () => {
this.setState({ open: false });
this.setState({ open: false, filtered: '' });
};

onChange = (event: React.ChangeEvent<HTMLInputElement>) => {
this.setState({ filtered: event.target.value });
};

render() {
Expand All @@ -57,8 +63,9 @@ export class AwsLaunchButton extends React.Component<Props> {
</ButtonBorder>
<Menu
menuListCss={() => ({
overflow: 'auto',
overflow: 'hidden',
minWidth: '180px',
maxHeight: '400px',
})}
transformOrigin={{
vertical: 'top',
Expand All @@ -74,10 +81,19 @@ export class AwsLaunchButton extends React.Component<Props> {
onClose={this.onClose}
>
<RoleItemList
awsRoles={awsRoles}
awsRoles={awsRoles.filter(role => {
const lowerFilter = this.state.filtered.toLowerCase();
const lowerDisplay = role.display.toLowerCase();
const lowerName = role.name.toLowerCase();
return (
lowerDisplay.includes(lowerFilter) ||
lowerName.includes(lowerFilter)
);
})}
getLaunchUrl={getLaunchUrl}
onLaunchUrl={onLaunchUrl}
closeMenu={this.onClose}
onChange={this.onChange}
/>
</Menu>
</>
Expand All @@ -89,10 +105,14 @@ function RoleItemList({
awsRoles,
getLaunchUrl,
closeMenu,
onChange,
onLaunchUrl,
}: Props & { closeMenu: () => void }) {
}: Props & {
closeMenu: () => void;
onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
}) {
const awsRoleItems = awsRoles.map((item, key) => {
const { display, arn } = item;
const { display, arn, name } = item;
const launchUrl = getLaunchUrl(arn);
return (
<StyledMenuItem
Expand All @@ -108,32 +128,47 @@ function RoleItemList({
onLaunchUrl?.(item.arn);
}}
>
<Text style={{ maxWidth: '25ch' }}>{display}</Text>
<Text>{`${display !== name ? `${display} (${name})` : display}`}</Text>
</StyledMenuItem>
);
});

return (
<>
<Flex flexDirection="column">
<Text
px="2"
fontSize="11px"
mb="2"
css={`
color: ${props => props.theme.colors.text.main};
background: ${props => props.theme.colors.spotBackground[2]};
`}
>
Select IAM Role
</Text>
{awsRoleItems.length ? (
awsRoleItems
) : (
<Text px={2} m={2} color="text.disabled">
No roles found
</Text>
)}
</>
<StyledInput
p="2"
m="2"
type="text"
onChange={onChange}
autoFocus
placeholder={'Search IAM roles...'}
autoComplete="off"
/>
<Box
css={`
max-height: 220px;
overflow: auto;
`}
>
{awsRoleItems.length ? (
awsRoleItems
) : (
<Text px={2} m={2} color="text.disabled">
No roles found
</Text>
)}
</Box>
</Flex>
);
}

Expand All @@ -159,3 +194,26 @@ const StyledMenuItem = styled(MenuItem)(
}
`
);

const StyledInput = styled.input(
({ theme }) => `
background: transparent;
border: 1px solid ${theme.colors.text.muted};
border-radius: 4px;
box-sizing: border-box;
color: ${theme.colors.text.main};
height: 32px;
outline: none;
&:focus, &:hover {
border 1px solid ${theme.colors.text.slightlyMuted};
outline: none;
}
::placeholder {
color: ${theme.colors.text.muted};
opacity: 1;
}
`,
space
);
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { desktops } from 'teleport/Desktops/fixtures';
import { nodes } from 'teleport/Nodes/fixtures';

import makeApp from 'teleport/services/apps/makeApps';
import { ResourceActionButton } from 'teleport/UnifiedResources/ResourceActionButton';

import {
makeUnifiedResourceViewItemApp,
Expand Down Expand Up @@ -104,7 +105,9 @@ export const Cards: Story = {
<Grid gap={2}>
{[
...apps.map(resource =>
makeUnifiedResourceViewItemApp(resource, { ActionButton })
makeUnifiedResourceViewItemApp(resource, {
ActionButton: <ResourceActionButton resource={resource} />,
})
),
...databases.map(resource =>
makeUnifiedResourceViewItemDatabase(resource, {
Expand All @@ -115,7 +118,9 @@ export const Cards: Story = {
makeUnifiedResourceViewItemKube(resource, { ActionButton })
),
...nodes.map(resource =>
makeUnifiedResourceViewItemNode(resource, { ActionButton })
makeUnifiedResourceViewItemNode(resource, {
ActionButton,
})
),
...additionalResources.map(resource =>
makeUnifiedResourceViewItemApp(resource, { ActionButton })
Expand Down
1 change: 1 addition & 0 deletions web/packages/shared/services/apps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/

export type AwsRole = {
name: string;
arn: string;
display: string;
};
14 changes: 14 additions & 0 deletions web/packages/teleport/src/Apps/fixtures/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,13 +151,27 @@ export const apps = [
awsConsole: true,
awsRoles: [
{
name: 'role name',
arn: 'arn:aws:iam::joe123:role/EC2FullAccess',
display: 'EC2FullAccess',
},
{
name: 'other role name',
arn: 'arn:aws:iam::joe123:role/EC2FullAccess',
display: 'ReallyLonReallyLonggggggEC2FullAccess',
},
{
name: 'thisthing',
arn: 'arn:aws:iam::joe123:role/EC2ReadOnly',
display: 'EC2ReadOnly',
},
...new Array(20).fill(undefined).map((_, index) => {
return {
name: `long-${index}`,
arc: `arn:aws:iam::${index}`,
display: `LONG${index}`,
};
}),
],
clusterId: 'one',
fqdn: 'awsconsole-1.com',
Expand Down

0 comments on commit 57fb040

Please sign in to comment.