Added description to trusted app card. (#79503)
* Added description to trusted app card. * Fixed the test and increased the specificity of styling for item details card styles as opposed to using !important. * Added useMemo.
This commit is contained in:
parent
cd383800e3
commit
96d3b7710a
|
@ -29,7 +29,7 @@ export const GetTrustedAppsRequestSchema = {
|
|||
export const PostTrustedAppCreateRequestSchema = {
|
||||
body: schema.object({
|
||||
name: schema.string({ minLength: 1 }),
|
||||
description: schema.maybe(schema.string({ minLength: 0, defaultValue: '' })),
|
||||
description: schema.maybe(schema.string({ minLength: 0, maxLength: 256, defaultValue: '' })),
|
||||
os: schema.oneOf([schema.literal('linux'), schema.literal('macos'), schema.literal('windows')]),
|
||||
entries: schema.arrayOf(
|
||||
schema.object({
|
||||
|
|
|
@ -200,7 +200,11 @@ exports[`item_details_card ItemDetailsPropertySummary should render correctly 1`
|
|||
name 1
|
||||
</Styled(EuiDescriptionListTitle)>
|
||||
<Styled(EuiDescriptionListDescription)>
|
||||
value 1
|
||||
<span
|
||||
title=""
|
||||
>
|
||||
value 1
|
||||
</span>
|
||||
</Styled(EuiDescriptionListDescription)>
|
||||
</Fragment>
|
||||
`;
|
||||
|
|
|
@ -52,23 +52,30 @@ const DetailsSection = styled(EuiFlexItem)`
|
|||
`;
|
||||
|
||||
const DescriptionListTitle = styled(EuiDescriptionListTitle)`
|
||||
width: 40%;
|
||||
&&& {
|
||||
width: 40%;
|
||||
}
|
||||
`;
|
||||
|
||||
const DescriptionListDescription = styled(EuiDescriptionListDescription)`
|
||||
width: 60%;
|
||||
&&& {
|
||||
width: 60%;
|
||||
}
|
||||
`;
|
||||
|
||||
interface ItemDetailsPropertySummaryProps {
|
||||
name: ReactNode | ReactNode[];
|
||||
value: ReactNode | ReactNode[];
|
||||
title?: string;
|
||||
}
|
||||
|
||||
export const ItemDetailsPropertySummary: FC<ItemDetailsPropertySummaryProps> = memo(
|
||||
({ name, value }) => (
|
||||
({ name, value, title = '' }) => (
|
||||
<>
|
||||
<DescriptionListTitle>{name}</DescriptionListTitle>
|
||||
<DescriptionListDescription>{value}</DescriptionListDescription>
|
||||
<DescriptionListDescription>
|
||||
<span title={title}>{value}</span>
|
||||
</DescriptionListDescription>
|
||||
</>
|
||||
)
|
||||
);
|
||||
|
|
|
@ -494,11 +494,11 @@ exports[`TrustedAppsList renders correctly when item details expanded 1`] = `
|
|||
padding: 16px;
|
||||
}
|
||||
|
||||
.c1 {
|
||||
.c1.c1.c1 {
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
.c2 {
|
||||
.c2.c2.c2 {
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
|
@ -791,7 +791,11 @@ exports[`TrustedAppsList renders correctly when item details expanded 1`] = `
|
|||
<dd
|
||||
class="euiDescriptionList__description c2"
|
||||
>
|
||||
trusted app 0
|
||||
<span
|
||||
title=""
|
||||
>
|
||||
trusted app 0
|
||||
</span>
|
||||
</dd>
|
||||
<dt
|
||||
class="euiDescriptionList__title c1"
|
||||
|
@ -801,7 +805,11 @@ exports[`TrustedAppsList renders correctly when item details expanded 1`] = `
|
|||
<dd
|
||||
class="euiDescriptionList__description c2"
|
||||
>
|
||||
Windows
|
||||
<span
|
||||
title=""
|
||||
>
|
||||
Windows
|
||||
</span>
|
||||
</dd>
|
||||
<dt
|
||||
class="euiDescriptionList__title c1"
|
||||
|
@ -811,7 +819,11 @@ exports[`TrustedAppsList renders correctly when item details expanded 1`] = `
|
|||
<dd
|
||||
class="euiDescriptionList__description c2"
|
||||
>
|
||||
1 minute ago
|
||||
<span
|
||||
title=""
|
||||
>
|
||||
1 minute ago
|
||||
</span>
|
||||
</dd>
|
||||
<dt
|
||||
class="euiDescriptionList__title c1"
|
||||
|
@ -821,7 +833,25 @@ exports[`TrustedAppsList renders correctly when item details expanded 1`] = `
|
|||
<dd
|
||||
class="euiDescriptionList__description c2"
|
||||
>
|
||||
someone
|
||||
<span
|
||||
title=""
|
||||
>
|
||||
someone
|
||||
</span>
|
||||
</dd>
|
||||
<dt
|
||||
class="euiDescriptionList__title c1"
|
||||
>
|
||||
Description
|
||||
</dt>
|
||||
<dd
|
||||
class="euiDescriptionList__description c2"
|
||||
>
|
||||
<span
|
||||
title="Trusted App 0"
|
||||
>
|
||||
Trusted App 0
|
||||
</span>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
|
|
@ -410,6 +410,7 @@ export const CreateTrustedAppForm = memo<CreateTrustedAppFormProps>(
|
|||
value={formValues.description}
|
||||
onChange={handleDomChangeEvents}
|
||||
fullWidth
|
||||
maxLength={256}
|
||||
data-test-subj={getTestId('descriptionField')}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
|
|
|
@ -24,6 +24,81 @@ exports[`trusted_app_card TrustedAppCard should render correctly 1`] = `
|
|||
name="Created By"
|
||||
value="someone"
|
||||
/>
|
||||
<ItemPropertySummary
|
||||
name="Description"
|
||||
title="Trusted App 4"
|
||||
value="Trusted App 4"
|
||||
/>
|
||||
<ConditionsTable
|
||||
badge="and"
|
||||
columns={
|
||||
Array [
|
||||
Object {
|
||||
"field": "field",
|
||||
"name": "Field",
|
||||
"sortable": false,
|
||||
"textOnly": true,
|
||||
"truncateText": true,
|
||||
"width": "30%",
|
||||
},
|
||||
Object {
|
||||
"field": "operator",
|
||||
"name": "Operator",
|
||||
"sortable": false,
|
||||
"truncateText": true,
|
||||
"width": "20%",
|
||||
},
|
||||
Object {
|
||||
"field": "value",
|
||||
"name": "Value",
|
||||
"sortable": false,
|
||||
"truncateText": true,
|
||||
"width": "60%",
|
||||
},
|
||||
]
|
||||
}
|
||||
items={Array []}
|
||||
responsive={true}
|
||||
/>
|
||||
<ItemDetailsAction
|
||||
color="danger"
|
||||
onClick={[Function]}
|
||||
size="s"
|
||||
>
|
||||
Remove
|
||||
</ItemDetailsAction>
|
||||
</ItemDetailsCard>
|
||||
`;
|
||||
|
||||
exports[`trusted_app_card TrustedAppCard should trim long descriptions 1`] = `
|
||||
<ItemDetailsCard>
|
||||
<ItemPropertySummary
|
||||
name="Name"
|
||||
value="trusted app 4"
|
||||
/>
|
||||
<ItemPropertySummary
|
||||
name="OS"
|
||||
value="Mac OS"
|
||||
/>
|
||||
<ItemPropertySummary
|
||||
name="Date Created"
|
||||
value={
|
||||
<Memo(FormattedDate)
|
||||
className="eui-textTruncate"
|
||||
fieldName="Date Created"
|
||||
value="1 minute ago"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<ItemPropertySummary
|
||||
name="Created By"
|
||||
value="someone"
|
||||
/>
|
||||
<ItemPropertySummary
|
||||
name="Description"
|
||||
title="item0 item1 item2 item3 item4 item5 item6 item7 item8 item9 item10 item11 item12 item13 item14 item15 item16 item17 item18 item19 item20 item21 item22 item23 item24 item25 item26 item27 item28 item29 item30 item31 item32 item33 item34 item35 item36 item37 item38 item39"
|
||||
value="item0 item1 item2 item3 item4 item5 item6 item7 item8 item9 item10 item11 item12 item13 item14 item1..."
|
||||
/>
|
||||
<ConditionsTable
|
||||
badge="and"
|
||||
columns={
|
||||
|
|
|
@ -10,7 +10,7 @@ import { action } from '@storybook/addon-actions';
|
|||
import euiLightVars from '@elastic/eui/dist/eui_theme_light.json';
|
||||
|
||||
import { KibanaContextProvider } from '../../../../../../../../../../src/plugins/kibana_react/public';
|
||||
import { TrustedApp } from '../../../../../../../common/endpoint/types';
|
||||
import { TrustedApp, WindowsConditionEntry } from '../../../../../../../common/endpoint/types';
|
||||
|
||||
import { createSampleTrustedApp } from '../../../test_utils';
|
||||
|
||||
|
@ -24,38 +24,40 @@ addDecorator((storyFn) => (
|
|||
</KibanaContextProvider>
|
||||
));
|
||||
|
||||
const PATH_CONDITION: WindowsConditionEntry = {
|
||||
field: 'process.executable.caseless',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: '/some/path/on/file/system',
|
||||
};
|
||||
|
||||
const SIGNER_CONDITION: WindowsConditionEntry = {
|
||||
field: 'process.code_signature',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'Elastic',
|
||||
};
|
||||
|
||||
storiesOf('TrustedApps|TrustedAppCard', module)
|
||||
.add('default', () => {
|
||||
const trustedApp: TrustedApp = createSampleTrustedApp(5);
|
||||
trustedApp.created_at = '2020-09-17T14:52:33.899Z';
|
||||
trustedApp.entries = [
|
||||
{
|
||||
field: 'process.executable.caseless',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: '/some/path/on/file/system',
|
||||
},
|
||||
];
|
||||
trustedApp.entries = [PATH_CONDITION];
|
||||
|
||||
return <TrustedAppCard trustedApp={trustedApp} onDelete={action('onClick')} />;
|
||||
})
|
||||
.add('multiple entries', () => {
|
||||
const trustedApp: TrustedApp = createSampleTrustedApp(5);
|
||||
trustedApp.created_at = '2020-09-17T14:52:33.899Z';
|
||||
trustedApp.entries = [
|
||||
{
|
||||
field: 'process.executable.caseless',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: '/some/path/on/file/system',
|
||||
},
|
||||
{
|
||||
field: 'process.code_signature',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'Elastic',
|
||||
},
|
||||
];
|
||||
trustedApp.entries = [PATH_CONDITION, SIGNER_CONDITION];
|
||||
|
||||
return <TrustedAppCard trustedApp={trustedApp} onDelete={action('onClick')} />;
|
||||
})
|
||||
.add('trim description', () => {
|
||||
const trustedApp: TrustedApp = createSampleTrustedApp(5);
|
||||
trustedApp.created_at = '2020-09-17T14:52:33.899Z';
|
||||
trustedApp.entries = [PATH_CONDITION, SIGNER_CONDITION];
|
||||
trustedApp.description = [...new Array(40).keys()].map((index) => `item${index}`).join(' ');
|
||||
|
||||
return <TrustedAppCard trustedApp={trustedApp} onDelete={action('onClick')} />;
|
||||
});
|
||||
|
|
|
@ -18,5 +18,15 @@ describe('trusted_app_card', () => {
|
|||
|
||||
expect(element).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should trim long descriptions', () => {
|
||||
const trustedApp = {
|
||||
...createSampleTrustedApp(4),
|
||||
description: [...new Array(40).keys()].map((index) => `item${index}`).join(' '),
|
||||
};
|
||||
const element = shallow(<TrustedAppCard trustedApp={trustedApp} onDelete={() => {}} />);
|
||||
|
||||
expect(element).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -27,6 +27,14 @@ import { OS_TITLES, PROPERTY_TITLES, ENTRY_PROPERTY_TITLES } from '../../transla
|
|||
|
||||
type Entry = MacosLinuxConditionEntry | WindowsConditionEntry;
|
||||
|
||||
const trimTextOverflow = (text: string, maxSize: number) => {
|
||||
if (text.length > maxSize) {
|
||||
return `${text.substr(0, maxSize)}...`;
|
||||
} else {
|
||||
return text;
|
||||
}
|
||||
};
|
||||
|
||||
const getEntriesColumnDefinitions = (): Array<EuiTableFieldDataColumnType<Entry>> => [
|
||||
{
|
||||
field: 'field',
|
||||
|
@ -75,6 +83,13 @@ export const TrustedAppCard = memo(({ trustedApp, onDelete }: TrustedAppCardProp
|
|||
}
|
||||
/>
|
||||
<ItemDetailsPropertySummary name={PROPERTY_TITLES.created_by} value={trustedApp.created_by} />
|
||||
<ItemDetailsPropertySummary
|
||||
name={PROPERTY_TITLES.description}
|
||||
value={useMemo(() => trimTextOverflow(trustedApp.description || '', 100), [
|
||||
trustedApp.description,
|
||||
])}
|
||||
title={trustedApp.description}
|
||||
/>
|
||||
|
||||
<ConditionsTable
|
||||
columns={useMemo(() => getEntriesColumnDefinitions(), [])}
|
||||
|
|
|
@ -24,7 +24,7 @@ export const OS_TITLES: Readonly<{ [K in TrustedApp['os']]: string }> = {
|
|||
};
|
||||
|
||||
export const PROPERTY_TITLES: Readonly<
|
||||
{ [K in keyof Omit<TrustedApp, 'id' | 'description' | 'entries'>]: string }
|
||||
{ [K in keyof Omit<TrustedApp, 'id' | 'entries'>]: string }
|
||||
> = {
|
||||
name: i18n.translate('xpack.securitySolution.trustedapps.trustedapp.name', {
|
||||
defaultMessage: 'Name',
|
||||
|
@ -38,6 +38,9 @@ export const PROPERTY_TITLES: Readonly<
|
|||
created_by: i18n.translate('xpack.securitySolution.trustedapps.trustedapp.createdBy', {
|
||||
defaultMessage: 'Created By',
|
||||
}),
|
||||
description: i18n.translate('xpack.securitySolution.trustedapps.trustedapp.description', {
|
||||
defaultMessage: 'Description',
|
||||
}),
|
||||
};
|
||||
|
||||
export const ENTRY_PROPERTY_TITLES: Readonly<
|
||||
|
|
Loading…
Reference in a new issue