"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.AlertsTable = void 0; var _ruleDataUtils = require("@kbn/rule-data-utils"); var _react = _interopRequireWildcard(require("react")); var _eui = require("@elastic/eui"); var _reactQuery = require("@tanstack/react-query"); var _hooks = require("./hooks"); var _translations = require("./translations"); require("./alerts_table.scss"); var _toolbar = require("./toolbar"); var _inspect = require("./toolbar/components/inspect"); var _cells = require("./cells"); var _constants = require("../../hooks/constants"); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } const AlertsFlyout = /*#__PURE__*/(0, _react.lazy)(() => Promise.resolve().then(() => _interopRequireWildcard(require('./alerts_flyout')))); const DefaultGridStyle = { border: 'none', header: 'underline', fontSize: 's' }; const getCellActionsStub = { getCellActions: () => null, visibleCellActions: undefined, disabledCellActions: [] }; const basicRenderCellValue = ({ data, columnId }) => { var _data$find$value, _data$find; const value = (_data$find$value = (_data$find = data.find(d => d.field === columnId)) === null || _data$find === void 0 ? void 0 : _data$find.value) !== null && _data$find$value !== void 0 ? _data$find$value : []; if (Array.isArray(value)) { return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, value.length ? value.join() : '--'); } return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, value); }; const isSystemCell = columnId => { return _cells.systemCells.includes(columnId); }; const AlertsTable = props => { var _props$alertsTableCon, _props$alertsTableCon4, _props$alertsTableCon5; const dataGridRef = (0, _react.useRef)(null); const [activeRowClasses, setActiveRowClasses] = (0, _react.useState)({}); const alertsData = props.useFetchAlertsData(); const { activePage, alerts, oldAlertsData, ecsAlertsData, alertsCount, isLoading, onPageChange, onSortChange, sort: sortingFields, refresh: alertsRefresh, getInspectQuery } = alertsData; const queryClient = (0, _reactQuery.useQueryClient)(); const { data: cases, isLoading: isLoadingCases } = props.cases; const { data: maintenanceWindows, isLoading: isLoadingMaintenanceWindows } = props.maintenanceWindows; const { sortingColumns, onSort } = (0, _hooks.useSorting)(onSortChange, sortingFields); const { renderCustomActionsRow, actionsColumnWidth, getSetIsActionLoadingCallback } = (0, _hooks.useActionsColumn)({ options: props.alertsTableConfiguration.useActionsColumn }); const { isBulkActionsColumnActive, getBulkActionsLeadingControlColumn, bulkActionsState, bulkActions, setIsBulkActionsLoading, clearSelection } = (0, _hooks.useBulkActions)({ alerts, casesConfig: props.alertsTableConfiguration.cases, query: props.query, useBulkActionsConfig: props.alertsTableConfiguration.useBulkActions, refresh: alertsRefresh }); const refreshData = (0, _react.useCallback)(() => { alertsRefresh(); queryClient.invalidateQueries(_constants.triggersActionsUiQueriesKeys.cases()); queryClient.invalidateQueries(_constants.triggersActionsUiQueriesKeys.maintenanceWindows()); }, [alertsRefresh, queryClient]); const refresh = (0, _react.useCallback)(() => { refreshData(); clearSelection(); }, [clearSelection, refreshData]); const { pagination, onChangePageSize, onChangePageIndex, onPaginateFlyout, flyoutAlertIndex, setFlyoutAlertIndex } = (0, _hooks.usePagination)({ onPageChange, pageIndex: activePage, pageSize: props.pageSize }); const { visibleColumns, onToggleColumn, onResetColumns, updatedAt, browserFields, onChangeVisibleColumns, onColumnResize, showAlertStatusWithFlapping = false, showInspectButton = false } = props; // TODO when every solution is using this table, we will be able to simplify it by just passing the alert index const handleFlyoutAlert = (0, _react.useCallback)(alert => { const idx = alerts.findIndex(a => a[_ruleDataUtils.ALERT_UUID].includes(alert.fields[_ruleDataUtils.ALERT_UUID])); setFlyoutAlertIndex(idx); }, [alerts, setFlyoutAlertIndex]); const fieldBrowserOptions = props.alertsTableConfiguration.useFieldBrowserOptions ? (_props$alertsTableCon = props.alertsTableConfiguration) === null || _props$alertsTableCon === void 0 ? void 0 : _props$alertsTableCon.useFieldBrowserOptions({ onToggleColumn }) : undefined; const toolbarVisibility = (0, _react.useCallback)(() => { const { rowSelection } = bulkActionsState; return (0, _toolbar.getToolbarVisibility)({ bulkActions, alertsCount, rowSelection, alerts: alertsData.alerts, updatedAt, isLoading, columnIds: visibleColumns, onToggleColumn, onResetColumns, browserFields, controls: props.controls, setIsBulkActionsLoading, clearSelection, refresh, fieldBrowserOptions, getInspectQuery, showInspectButton, toolbarVisiblityProp: props.toolbarVisibility }); }, [bulkActionsState, bulkActions, alertsCount, alertsData.alerts, updatedAt, isLoading, visibleColumns, onToggleColumn, onResetColumns, browserFields, props.controls, setIsBulkActionsLoading, clearSelection, refresh, fieldBrowserOptions, getInspectQuery, showInspectButton, props.toolbarVisibility])(); const leadingControlColumns = (0, _react.useMemo)(() => { const isActionButtonsColumnActive = props.showExpandToDetails || Boolean(renderCustomActionsRow); let controlColumns = [...props.leadingControlColumns]; if (isActionButtonsColumnActive) { controlColumns = [{ id: 'expandColumn', width: actionsColumnWidth, headerCellRender: () => { return /*#__PURE__*/_react.default.createElement("span", { "data-test-subj": "expandColumnHeaderLabel" }, _translations.ALERTS_TABLE_CONTROL_COLUMNS_ACTIONS_LABEL); }, rowCellRender: cveProps => { const { visibleRowIndex } = cveProps; return /*#__PURE__*/_react.default.createElement(_eui.EuiFlexGroup, { gutterSize: "none", responsive: false }, props.showExpandToDetails && /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: false }, /*#__PURE__*/_react.default.createElement(_eui.EuiToolTip, { content: _translations.ALERTS_TABLE_CONTROL_COLUMNS_VIEW_DETAILS_LABEL }, /*#__PURE__*/_react.default.createElement(_eui.EuiButtonIcon, { size: "s", iconType: "expand", color: "primary", onClick: () => { setFlyoutAlertIndex(visibleRowIndex); }, "data-test-subj": `expandColumnCellOpenFlyoutButton-${visibleRowIndex}`, "aria-label": _translations.ALERTS_TABLE_CONTROL_COLUMNS_VIEW_DETAILS_LABEL }))), renderCustomActionsRow && ecsAlertsData[visibleRowIndex] && renderCustomActionsRow({ alert: alerts[visibleRowIndex], ecsAlert: ecsAlertsData[visibleRowIndex], nonEcsData: oldAlertsData[visibleRowIndex], rowIndex: visibleRowIndex, setFlyoutAlert: handleFlyoutAlert, id: props.id, cveProps, setIsActionLoading: getSetIsActionLoadingCallback(visibleRowIndex), refresh, clearSelection })); } }, ...controlColumns]; } if (isBulkActionsColumnActive) { controlColumns = [getBulkActionsLeadingControlColumn(), ...controlColumns]; } return controlColumns; }, [actionsColumnWidth, alerts, oldAlertsData, ecsAlertsData, getBulkActionsLeadingControlColumn, handleFlyoutAlert, isBulkActionsColumnActive, props.id, props.leadingControlColumns, props.showExpandToDetails, renderCustomActionsRow, setFlyoutAlertIndex, getSetIsActionLoadingCallback, refresh, clearSelection]); (0, _react.useEffect)(() => { // Row classes do not deal with visible row indices, so we need to handle page offset const rowIndex = flyoutAlertIndex + pagination.pageIndex * pagination.pageSize; setActiveRowClasses({ [rowIndex]: 'alertsTableActiveRow' }); }, [flyoutAlertIndex, pagination.pageIndex, pagination.pageSize]); // Update highlighted rows when alerts or pagination changes const highlightedRowClasses = (0, _react.useMemo)(() => { let mappedRowClasses = {}; const shouldHighlightRowCheck = props.shouldHighlightRow; if (shouldHighlightRowCheck) { mappedRowClasses = alerts.reduce((rowClasses, alert, index) => { var _props$gridStyle; if ((_props$gridStyle = props.gridStyle) !== null && _props$gridStyle !== void 0 && _props$gridStyle.stripes && index % 2 !== 0) { // manually add stripes if props.gridStyle.stripes is true because presence of rowClasses // overrides the props.gridStyle.stripes option. And rowClasses will always be there. // Adding strips only on even rows. It will be replace by alertsTableHighlightedRow if // shouldHighlightRow is correct rowClasses[index + pagination.pageIndex * pagination.pageSize] = 'euiDataGridRow--striped'; } if (shouldHighlightRowCheck(alert)) { rowClasses[index + pagination.pageIndex * pagination.pageSize] = 'alertsTableHighlightedRow'; } return rowClasses; }, {}); } return mappedRowClasses; }, [props.shouldHighlightRow, alerts, pagination.pageIndex, pagination.pageSize, props.gridStyle]); const handleFlyoutClose = (0, _react.useCallback)(() => setFlyoutAlertIndex(-1), [setFlyoutAlertIndex]); const renderCellValue = (0, _react.useCallback)(() => { var _props$alertsTableCon2, _props$alertsTableCon3; return (_props$alertsTableCon2 = props.alertsTableConfiguration) !== null && _props$alertsTableCon2 !== void 0 && _props$alertsTableCon2.getRenderCellValue ? (_props$alertsTableCon3 = props.alertsTableConfiguration) === null || _props$alertsTableCon3 === void 0 ? void 0 : _props$alertsTableCon3.getRenderCellValue({ setFlyoutAlert: handleFlyoutAlert }) : basicRenderCellValue; }, [handleFlyoutAlert, props.alertsTableConfiguration])(); const handleRenderCellValue = (0, _react.useCallback)(_props => { // https://github.com/elastic/eui/issues/5811 const idx = _props.rowIndex - pagination.pageSize * pagination.pageIndex; const alert = alerts[idx]; // ecsAlert is needed for security solution const ecsAlert = ecsAlertsData[idx]; if (alert) { const data = []; Object.entries(alert !== null && alert !== void 0 ? alert : {}).forEach(([key, value]) => { data.push({ field: key, value: value }); }); if (isSystemCell(_props.columnId)) { return /*#__PURE__*/_react.default.createElement(_cells.SystemCellFactory, { alert: alert, columnId: _props.columnId, isLoading: isLoading || isLoadingCases || isLoadingMaintenanceWindows, cases: cases, maintenanceWindows: maintenanceWindows, showAlertStatusWithFlapping: showAlertStatusWithFlapping }); } return renderCellValue({ ..._props, data, ecsData: ecsAlert }); } else if (isLoading) { return /*#__PURE__*/_react.default.createElement(_eui.EuiSkeletonText, { lines: 1 }); } return null; }, [alerts, ecsAlertsData, cases, maintenanceWindows, isLoading, isLoadingCases, isLoadingMaintenanceWindows, pagination.pageIndex, pagination.pageSize, renderCellValue, showAlertStatusWithFlapping]); const { getCellActions, visibleCellActions, disabledCellActions } = (_props$alertsTableCon4 = props.alertsTableConfiguration) !== null && _props$alertsTableCon4 !== void 0 && _props$alertsTableCon4.useCellActions ? (_props$alertsTableCon5 = props.alertsTableConfiguration) === null || _props$alertsTableCon5 === void 0 ? void 0 : _props$alertsTableCon5.useCellActions({ columns: props.columns, data: oldAlertsData, ecsData: ecsAlertsData, dataGridRef, pageSize: pagination.pageSize }) : getCellActionsStub; const columnsWithCellActions = (0, _react.useMemo)(() => { if (getCellActions) { return props.columns.map((col, idx) => { var _getCellActions; return { ...col, ...(!(disabledCellActions !== null && disabledCellActions !== void 0 ? disabledCellActions : []).includes(col.id) ? { cellActions: (_getCellActions = getCellActions(col.id, idx)) !== null && _getCellActions !== void 0 ? _getCellActions : [], visibleCellActions } : {}) }; }); } return props.columns; }, [getCellActions, disabledCellActions, props.columns, visibleCellActions]); // Merges the default grid style with the grid style that comes in through props. const actualGridStyle = (0, _react.useMemo)(() => { var _props$gridStyle2; const propGridStyle = (_props$gridStyle2 = props.gridStyle) !== null && _props$gridStyle2 !== void 0 ? _props$gridStyle2 : {}; // Merges default row classes, custom ones and adds the active row class style const mergedGridStyle = { ...DefaultGridStyle, ...propGridStyle, rowClasses: { // We're spreadind the highlighted row classes first, so that the active // row classed can override the highlighted row classes. ...highlightedRowClasses, ...activeRowClasses } }; // If ANY additional rowClasses have been provided, we need to merge them with our internal ones if (propGridStyle.rowClasses) { // Get all row indices with a rowClass. const mergedKeys = [...Object.keys(mergedGridStyle.rowClasses || {}), ...Object.keys(propGridStyle.rowClasses || {})]; // Deduplicate keys to avoid extra iterations const dedupedKeys = Array.from(new Set(mergedKeys)); // For each index, merge row classes const mergedRowClasses = dedupedKeys.reduce((rowClasses, key) => { var _mergedGridStyle$rowC, _propGridStyle$rowCla; const intKey = parseInt(key, 10); // Use internal row classes over custom row classes. rowClasses[intKey] = ((_mergedGridStyle$rowC = mergedGridStyle.rowClasses) === null || _mergedGridStyle$rowC === void 0 ? void 0 : _mergedGridStyle$rowC[intKey]) || ((_propGridStyle$rowCla = propGridStyle.rowClasses) === null || _propGridStyle$rowCla === void 0 ? void 0 : _propGridStyle$rowCla[intKey]) || ''; return rowClasses; }, {}); mergedGridStyle.rowClasses = mergedRowClasses; } return mergedGridStyle; }, [activeRowClasses, highlightedRowClasses, props.gridStyle]); return /*#__PURE__*/_react.default.createElement(_inspect.InspectButtonContainer, null, /*#__PURE__*/_react.default.createElement("section", { style: { width: '100%' }, "data-test-subj": props['data-test-subj'] }, /*#__PURE__*/_react.default.createElement(_react.Suspense, { fallback: null }, flyoutAlertIndex > -1 && /*#__PURE__*/_react.default.createElement(AlertsFlyout, { alert: alerts[flyoutAlertIndex], alertsCount: alertsCount, onClose: handleFlyoutClose, alertsTableConfiguration: props.alertsTableConfiguration, flyoutIndex: flyoutAlertIndex + pagination.pageIndex * pagination.pageSize, onPaginate: onPaginateFlyout, isLoading: isLoading, id: props.id })), alertsCount > 0 && /*#__PURE__*/_react.default.createElement(_eui.EuiDataGrid, { "aria-label": "Alerts table", "data-test-subj": "alertsTable", columns: columnsWithCellActions, columnVisibility: { visibleColumns, setVisibleColumns: onChangeVisibleColumns }, trailingControlColumns: props.trailingControlColumns, leadingControlColumns: leadingControlColumns, rowCount: alertsCount, renderCellValue: handleRenderCellValue, gridStyle: actualGridStyle, sorting: { columns: sortingColumns, onSort }, toolbarVisibility: toolbarVisibility, pagination: { ...pagination, pageSizeOptions: props.pageSizeOptions, onChangeItemsPerPage: onChangePageSize, onChangePage: onChangePageIndex }, rowHeightsOptions: props.rowHeightsOptions, onColumnResize: onColumnResize, ref: dataGridRef }))); }; exports.default = exports.AlertsTable = AlertsTable;