Skip to content

Commit

Permalink
[SECURITY_SOLUTION][ENDPOINT] Trusted apps create form UX mocks sync (#…
Browse files Browse the repository at this point in the history
…79155) (#79350)

* Make flyout size `m` + condition entry value should be 100% wide
* Condition entry and group components support for small screens
* Adjust spacing below each entry in the condition group
* Move `AND` button to the condition group + style it to design mock
  • Loading branch information
paul-tavares authored Oct 5, 2020
1 parent 1fac129 commit 03050c6
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ describe('When showing the Trusted App Create Form', () => {
dataTestSub: string = dataTestSubjForForm
): HTMLButtonElement => {
return renderResult.getByTestId(
`${dataTestSub}-conditionsBuilder-AndButton`
`${dataTestSub}-conditionsBuilder-group1-AndButton`
) as HTMLButtonElement;
};
const getConditionBuilderAndConnectorBadge = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ export const ConditionEntry = memo<ConditionEntryProps>(
alignItems="center"
direction="row"
data-test-subj={dataTestSubj}
responsive={false}
>
<EuiFlexItem grow={2}>
<ConditionEntryCell
Expand Down Expand Up @@ -176,6 +177,7 @@ export const ConditionEntry = memo<ConditionEntryProps>(
<EuiFieldText
name="value"
value={entry.value}
fullWidth
required
onChange={handleValueUpdate}
onBlur={handleValueOnBlur}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,63 @@
*/

import React, { memo, useCallback } from 'react';
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiHideFor, EuiSpacer } from '@elastic/eui';
import styled from 'styled-components';
import { FormattedMessage } from '@kbn/i18n/react';
import { NewTrustedApp, TrustedApp } from '../../../../../../../../common/endpoint/types';
import { ConditionEntry, ConditionEntryProps } from './condition_entry';
import { AndOrBadge } from '../../../../../../../common/components/and_or_badge';

const AndBadgeFlexItem = styled(EuiFlexItem)`
padding-top: 20px;
const ConditionGroupFlexGroup = styled(EuiFlexGroup)`
// The positioning of the 'and-badge' is done by using the EuiButton's height and adding on to it
// the amount of padding used to space out each of the entries (times 2 because a spacer is also
// used above the Button), and then we adjust it with 3px
.and-badge {
padding-top: 20px;
padding-bottom: ${({ theme }) => {
return `calc(${theme.eui.euiButtonHeightSmall} + (${theme.eui.paddingSizes.s} * 2) + 3px);`;
}};
}
.group-entries {
margin-bottom: ${({ theme }) => theme.eui.paddingSizes.s};
& > * {
margin-bottom: ${({ theme }) => theme.eui.paddingSizes.s};
&:last-child {
margin-bottom: 0;
}
}
}
.and-button {
min-width: 95px;
}
`;

export interface ConditionGroupProps {
os: TrustedApp['os'];
entries: TrustedApp['entries'];
onEntryRemove: ConditionEntryProps['onRemove'];
onEntryChange: ConditionEntryProps['onChange'];
onAndClicked: () => void;
isAndDisabled?: boolean;
/** called when any of the entries is visited (triggered via `onBlur` DOM event) */
onVisited?: ConditionEntryProps['onVisited'];
'data-test-subj'?: string;
}
export const ConditionGroup = memo<ConditionGroupProps>(
({ os, entries, onEntryRemove, onEntryChange, onVisited, 'data-test-subj': dataTestSubj }) => {
({
os,
entries,
onEntryRemove,
onEntryChange,
onAndClicked,
isAndDisabled,
onVisited,
'data-test-subj': dataTestSubj,
}) => {
const getTestId = useCallback(
(suffix: string): string | undefined => {
if (dataTestSubj) {
Expand All @@ -35,28 +71,53 @@ export const ConditionGroup = memo<ConditionGroupProps>(
[dataTestSubj]
);
return (
<EuiFlexGroup gutterSize="xs" data-test-subj={dataTestSubj}>
<ConditionGroupFlexGroup gutterSize="xs" data-test-subj={dataTestSubj}>
{entries.length > 1 && (
<AndBadgeFlexItem grow={false} data-test-subj={getTestId('andConnector')}>
<AndOrBadge type={'and'} includeAntennas={true} />
</AndBadgeFlexItem>
<EuiHideFor sizes={['xs', 's']}>
<EuiFlexItem
grow={false}
data-test-subj={getTestId('andConnector')}
className="and-badge"
>
<AndOrBadge type={'and'} includeAntennas={true} />
</EuiFlexItem>
</EuiHideFor>
)}
<EuiFlexItem grow={1} data-test-subj={getTestId('entries')}>
{(entries as (NewTrustedApp & { os: 'windows' })['entries']).map((entry, index) => (
<ConditionEntry
key={index}
os={os}
entry={entry}
showLabels={index === 0}
isRemoveDisabled={index === 0 && entries.length <= 1}
onRemove={onEntryRemove}
onChange={onEntryChange}
onVisited={onVisited}
data-test-subj={getTestId(`entry${index}`)}
/>
))}
<EuiFlexItem grow={1}>
<div data-test-subj={getTestId('entries')} className="group-entries">
{(entries as (NewTrustedApp & { os: 'windows' })['entries']).map((entry, index) => (
<ConditionEntry
key={index}
os={os}
entry={entry}
showLabels={index === 0}
isRemoveDisabled={index === 0 && entries.length <= 1}
onRemove={onEntryRemove}
onChange={onEntryChange}
onVisited={onVisited}
data-test-subj={getTestId(`entry${index}`)}
/>
))}
</div>
<div>
<EuiSpacer size="s" />
<EuiButton
fill
size="s"
iconType="plusInCircle"
onClick={onAndClicked}
data-test-subj={getTestId('AndButton')}
isDisabled={isAndDisabled}
className="and-button"
>
<FormattedMessage
id="xpack.securitySolution.trustedapps.logicalConditionBuilder.group.andOperator"
defaultMessage="AND"
/>
</EuiButton>
</div>
</EuiFlexItem>
</EuiFlexGroup>
</ConditionGroupFlexGroup>
);
}
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,11 @@
*/

import React, { memo, useCallback } from 'react';
import { EuiButton, CommonProps, EuiText, EuiSpacer, EuiPanel } from '@elastic/eui';
import { CommonProps, EuiText, EuiPanel } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { ConditionGroup, ConditionGroupProps } from './components/condition_group';

const BUTTON_MIN_WIDTH = Object.freeze({ minWidth: '95px' });

export type LogicalConditionBuilderProps = CommonProps &
ConditionGroupProps & {
onAndClicked: () => void;
isAndDisabled?: boolean;
};
export type LogicalConditionBuilderProps = CommonProps & ConditionGroupProps;
export const LogicalConditionBuilder = memo<LogicalConditionBuilderProps>(
({
entries,
Expand Down Expand Up @@ -47,26 +41,13 @@ export const LogicalConditionBuilder = memo<LogicalConditionBuilderProps>(
entries={entries}
onEntryRemove={onEntryRemove}
onEntryChange={onEntryChange}
onAndClicked={onAndClicked}
isAndDisabled={isAndDisabled}
onVisited={onVisited}
data-test-subj={getTestId('group1')}
/>
)}
</div>
<EuiSpacer size="s" />
<EuiButton
fill
size="s"
iconType="plusInCircle"
onClick={onAndClicked}
data-test-subj={getTestId('AndButton')}
isDisabled={isAndDisabled}
style={BUTTON_MIN_WIDTH}
>
<FormattedMessage
id="xpack.securitySolution.trustedapps.logicalConditionBuilder.andOperator"
defaultMessage="AND"
/>
</EuiButton>
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export const TrustedAppsPage = memo(() => {
{showAddFlout && (
<CreateTrustedAppFlyout
onClose={handleAddFlyoutClose}
size="s"
size="m"
data-test-subj="addTrustedAppFlyout"
/>
)}
Expand Down

0 comments on commit 03050c6

Please sign in to comment.