mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[SecuritySolution] Comma-separate array values in the alerts table (#133297)
* fix: comma-separate array values
* test: update snapshots
* fix: make sure that individual values are still draggable
* chore: reintroduce `parseValue`
We currently don't know exactly if it's still required or not. Hence we're reintroducing it and will revisit its usage in a future PR.
* chore: preserve `value`'s value
* chore: remove `parseValue`
`parseValue` was introduced in de6958d96f
when the type of `value` included `object`. The type has been narrowed since then and does not include `object` anymore. Hence we are removing this runtime check.
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
e7a1cef66f
commit
944e860779
3 changed files with 94 additions and 20 deletions
|
@ -640,6 +640,7 @@ export const mockTimelineData: TimelineItem[] = [
|
|||
{ field: '@timestamp', value: ['2019-03-13T05:42:11.815Z'] },
|
||||
{ field: 'event.category', value: ['audit-rule'] },
|
||||
{ field: 'host.name', value: ['zeek-sanfran'] },
|
||||
{ field: 'process.args', value: ['gpgconf', '--list-dirs', 'agent-socket'] },
|
||||
],
|
||||
ecs: {
|
||||
_id: '20',
|
||||
|
|
|
@ -230,5 +230,42 @@ describe('plain_column_renderer', () => {
|
|||
|
||||
expect(wrapper.find('[data-test-subj="draggableWrapperDiv"]').first().exists()).toBe(true);
|
||||
});
|
||||
|
||||
test('should join multiple values with a comma [not draggable]', () => {
|
||||
const data = mockTimelineData[19].data;
|
||||
const column = plainColumnRenderer.renderColumn({
|
||||
columnName: 'process.args',
|
||||
eventId: _id,
|
||||
values: getValues('process.args', data),
|
||||
field: defaultHeaders.find((h) => h.id === 'message')!,
|
||||
timelineId: 'test',
|
||||
isDraggable: false,
|
||||
});
|
||||
const wrapper = mount(
|
||||
<TestProviders>
|
||||
<span>{column}</span>
|
||||
</TestProviders>
|
||||
);
|
||||
const values = getValues('process.args', data);
|
||||
expect(wrapper.text()).toEqual(values?.join(', '));
|
||||
});
|
||||
|
||||
test('should NOT join multiple values with a comma [draggable]', () => {
|
||||
const data = mockTimelineData[19].data;
|
||||
const column = plainColumnRenderer.renderColumn({
|
||||
columnName: 'process.args',
|
||||
eventId: _id,
|
||||
values: getValues('process.args', data),
|
||||
field: defaultHeaders.find((h) => h.id === 'message')!,
|
||||
timelineId: 'test',
|
||||
isDraggable: true,
|
||||
});
|
||||
const wrapper = mount(
|
||||
<TestProviders>
|
||||
<span>{column}</span>
|
||||
</TestProviders>
|
||||
);
|
||||
expect(wrapper.find('[data-test-subj="draggableWrapperDiv"]').first().exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -14,7 +14,6 @@ import { TimelineNonEcsData } from '../../../../../../common/search_strategy/tim
|
|||
import { getEmptyTagValue } from '../../../../../common/components/empty_value';
|
||||
import { ColumnRenderer } from './column_renderer';
|
||||
import { FormattedFieldValue } from './formatted_field';
|
||||
import { parseValue } from './parse_value';
|
||||
|
||||
export const dataExistsAtColumn = (columnName: string, data: TimelineNonEcsData[]): boolean =>
|
||||
data.findIndex((item) => item.field === columnName) !== -1;
|
||||
|
@ -43,23 +42,60 @@ export const plainColumnRenderer: ColumnRenderer = {
|
|||
truncate?: boolean;
|
||||
values: string[] | undefined | null;
|
||||
linkValues?: string[] | null | undefined;
|
||||
}) =>
|
||||
values != null
|
||||
? values.map((value, i) => (
|
||||
<FormattedFieldValue
|
||||
asPlainText={asPlainText}
|
||||
contextId={`plain-column-renderer-formatted-field-value-${timelineId}`}
|
||||
eventId={eventId}
|
||||
fieldFormat={field.format ?? ''}
|
||||
fieldName={columnName}
|
||||
isAggregatable={field.aggregatable ?? false}
|
||||
fieldType={field.type ?? ''}
|
||||
isDraggable={isDraggable}
|
||||
key={`plain-column-renderer-formatted-field-value-${timelineId}-${columnName}-${eventId}-${field.id}-${value}-${i}`}
|
||||
linkValue={head(linkValues)}
|
||||
truncate={truncate}
|
||||
value={parseValue(value)}
|
||||
/>
|
||||
))
|
||||
: getEmptyTagValue(),
|
||||
}) => {
|
||||
if (!Array.isArray(values) || values.length === 0) {
|
||||
return getEmptyTagValue();
|
||||
}
|
||||
// Draggable columns should render individual fields to give the user
|
||||
// fine-grained control over the individual values
|
||||
if (isDraggable) {
|
||||
return values.map((value, i) => (
|
||||
<FormattedFieldValue
|
||||
asPlainText={asPlainText}
|
||||
contextId={`plain-column-renderer-formatted-field-value-${timelineId}`}
|
||||
eventId={eventId}
|
||||
fieldFormat={field.format ?? ''}
|
||||
fieldName={columnName}
|
||||
isAggregatable={field.aggregatable ?? false}
|
||||
fieldType={field.type ?? ''}
|
||||
isDraggable={isDraggable}
|
||||
key={`plain-column-renderer-formatted-field-value-${timelineId}-${columnName}-${eventId}-${field.id}-${value}-${i}`}
|
||||
linkValue={head(linkValues)}
|
||||
truncate={truncate}
|
||||
value={value}
|
||||
/>
|
||||
));
|
||||
} else {
|
||||
// In case the column isn't draggable, fields are joined
|
||||
// to give users a faster overview of all values.
|
||||
// (note: the filter-related hover actions still produce individual filters for each value)
|
||||
return (
|
||||
<FormattedFieldValue
|
||||
asPlainText={asPlainText}
|
||||
contextId={`plain-column-renderer-formatted-field-value-${timelineId}`}
|
||||
eventId={eventId}
|
||||
fieldFormat={field.format ?? ''}
|
||||
fieldName={columnName}
|
||||
isAggregatable={field.aggregatable ?? false}
|
||||
fieldType={field.type ?? ''}
|
||||
isDraggable={isDraggable}
|
||||
key={`plain-column-renderer-formatted-field-value-${timelineId}-${columnName}-${eventId}-${field.id}`}
|
||||
linkValue={head(linkValues)}
|
||||
truncate={truncate}
|
||||
value={joinValues(values)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
function joinValues(values: string[] | undefined | null): string | undefined | null {
|
||||
if (Array.isArray(values)) {
|
||||
if (values.length > 0) {
|
||||
return values.join(', ');
|
||||
} else {
|
||||
return values[0];
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue