fleet/frontend/components/queries/PackQueriesListWrapper/PackQueriesTable/PackQueriesTableConfig.tsx
2022-03-10 10:10:44 -05:00

306 lines
8.2 KiB
TypeScript

/* eslint-disable react/prop-types */
// disable this rule as it was throwing an error in Header and Cell component
// definitions for the selection row for some reason when we dont really need it.
import React from "react";
import { find } from "lodash";
import { performanceIndicator } from "fleet/helpers";
import { IScheduledQuery } from "interfaces/scheduled_query";
import { IDropdownOption } from "interfaces/dropdownOption";
import Checkbox from "components/forms/fields/Checkbox";
import DropdownCell from "components/TableContainer/DataTable/DropdownCell";
import HeaderCell from "components/TableContainer/DataTable/HeaderCell/HeaderCell";
import PillCell from "components/TableContainer/DataTable/PillCell";
import TextCell from "components/TableContainer/DataTable/TextCell";
import TooltipWrapper from "components/TooltipWrapper";
interface IGetToggleAllRowsSelectedProps {
checked: boolean;
indeterminate: boolean;
title: string;
onChange: () => void;
style: { cursor: string };
}
interface IHeaderProps {
column: {
title: string;
isSortedDesc: boolean;
};
getToggleAllRowsSelectedProps: () => IGetToggleAllRowsSelectedProps;
toggleAllRowsSelected: () => void;
}
interface IRowProps {
row: {
original: IScheduledQuery;
getToggleRowSelectedProps: () => IGetToggleAllRowsSelectedProps;
toggleRowSelected: () => void;
};
}
interface ICellProps extends IRowProps {
cell: {
value: string | number | boolean;
};
}
interface IPillCellProps extends IRowProps {
cell: {
value: [string, number];
};
}
interface IDropdownCellProps extends IRowProps {
cell: {
value: IDropdownOption[];
};
}
interface IDataColumn {
id?: string;
title?: string;
Header: ((props: IHeaderProps) => JSX.Element) | string;
accessor?: string;
Cell:
| ((props: ICellProps) => JSX.Element)
| ((props: IPillCellProps) => JSX.Element)
| ((props: IDropdownCellProps) => JSX.Element);
disableHidden?: boolean;
disableSortBy?: boolean;
}
interface IPackQueriesTableData extends IScheduledQuery {
loggingTypeString: string;
}
// NOTE: cellProps come from react-table
// more info here https://react-table.tanstack.com/docs/api/useTable#cell-properties
const generateTableHeaders = (
actionSelectHandler: (value: string, scheduled_query: IScheduledQuery) => void
): IDataColumn[] => {
return [
{
id: "selection",
Header: (cellProps: IHeaderProps): JSX.Element => {
const props = cellProps.getToggleAllRowsSelectedProps();
const checkboxProps = {
value: props.checked,
indeterminate: props.indeterminate,
onChange: () => cellProps.toggleAllRowsSelected(),
};
return <Checkbox {...checkboxProps} />;
},
Cell: (cellProps: ICellProps): JSX.Element => {
const props = cellProps.row.getToggleRowSelectedProps();
const checkboxProps = {
value: props.checked,
onChange: () => cellProps.row.toggleRowSelected(),
};
return <Checkbox {...checkboxProps} />;
},
disableHidden: true,
},
{
title: "Query name",
Header: (cellProps) => (
<HeaderCell
value={cellProps.column.title}
isSortedDesc={cellProps.column.isSortedDesc}
/>
),
accessor: "name",
Cell: (cellProps: ICellProps) => (
<TextCell value={cellProps.cell.value} />
),
},
{
title: "Frequency",
Header: "Frequency",
disableSortBy: false,
accessor: "interval",
Cell: (cellProps: ICellProps) => (
<TextCell value={cellProps.cell.value} />
),
},
{
title: "Platform",
Header: (cellProps) => (
<HeaderCell
value={cellProps.column.title}
isSortedDesc={cellProps.column.isSortedDesc}
/>
),
accessor: "platformTypeString",
Cell: (cellProps: ICellProps) => (
<TextCell value={cellProps.cell.value} />
),
},
{
title: "Logging",
Header: "Logging",
disableSortBy: false,
accessor: "loggingTypeString",
Cell: (cellProps: ICellProps) => (
<TextCell value={cellProps.cell.value} />
),
},
{
title: "Performance impact",
Header: () => {
return (
<div className="column-with-tooltip">
<span className="queries-table__performance-impact-header">
<TooltipWrapper tipContent="This is the average performance impact across all hosts where this query was scheduled.">
Performance impact
</TooltipWrapper>
</span>
</div>
);
},
disableSortBy: true,
accessor: "performance",
Cell: (cellProps: IPillCellProps) => (
<PillCell value={cellProps.cell.value} />
),
},
{
title: "Actions",
Header: "",
disableSortBy: true,
accessor: "actions",
Cell: (cellProps: IDropdownCellProps) => (
<DropdownCell
options={cellProps.cell.value}
onChange={(value: string) =>
actionSelectHandler(value, cellProps.row.original)
}
placeholder={"Actions"}
/>
),
},
];
};
const generateLoggingTypeString = (
snapshot: boolean,
removed: boolean
): string => {
if (snapshot) {
return "Snapshot";
}
// Default is differential with removals, so we treat null as removed = true
if (removed !== false) {
return "Differential";
}
return "Differential (ignore removal)";
};
const generatePlatformTypeString = (platforms: string | undefined): string => {
const ALL_PLATFORMS = [
{ text: "All", value: "all" },
{ text: "Windows", value: "windows" },
{ text: "Linux", value: "linux" },
{ text: "macOS", value: "darwin" },
];
if (platforms) {
const platformsArray = platforms.split(",");
const textArray = platformsArray.map((platform) => {
// Trim spaces from the platform
const trimmedPlatform = platform.trim();
const platformObject = find(ALL_PLATFORMS, { value: trimmedPlatform });
// Convert trimmed value to the corresponding text if the value exists
// in the ALL_PLATFORMS array.
// Otherwise, just use the trimmed value.
const text = platformObject ? platformObject.text : trimmedPlatform;
return text;
});
const displayText = textArray.join(", ");
return displayText;
}
return "All";
};
const generateVersionString = (version: string | undefined): string => {
if (version) {
return version;
}
return "Any";
};
const generateActionDropdownOptions = (): IDropdownOption[] => {
const dropdownOptions = [
{
label: "Edit",
disabled: false,
value: "edit",
},
{
label: "Remove",
disabled: false,
value: "remove",
},
];
return dropdownOptions;
};
const enhancePackQueriesData = (
packQueries: IScheduledQuery[]
): IPackQueriesTableData[] => {
return packQueries.map((query) => {
const scheduledQueryPerformance = {
user_time_p50: query.stats?.user_time_p50,
system_time_p50: query.stats?.system_time_p50,
total_executions: query.stats?.total_executions,
};
return {
id: query.id,
name: query.name,
interval: query.interval,
pack_id: query.pack_id,
platform: query.platform || undefined,
query: query.query,
query_id: query.query_id,
removed: query.removed,
snapshot: query.snapshot,
loggingTypeString: generateLoggingTypeString(
query.snapshot,
query.removed
),
platformTypeString: generatePlatformTypeString(query.platform),
shard: query.shard,
version: query.version,
versionString: generateVersionString(query.version),
created_at: query.created_at,
updated_at: query.updated_at,
query_name: query.query_name,
actions: generateActionDropdownOptions(),
performance: [
performanceIndicator(scheduledQueryPerformance),
query.query_id,
],
stats: query.stats,
};
});
};
const generateDataSet = (
queries: IScheduledQuery[]
): IPackQueriesTableData[] => {
// Cannot pass undefined to enhancePackQueriesData
if (!queries) {
return queries;
}
return [...enhancePackQueriesData(queries)];
};
export { generateTableHeaders, generateDataSet };