diff --git a/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx b/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx index ace01aa851ce8..9624160925437 100644 --- a/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx @@ -38,7 +38,6 @@ import { EuiPopover, EuiToolTip, } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; import styled from 'styled-components'; import React, { Suspense, useMemo, useState, useCallback, useEffect } from 'react'; import usePrevious from 'react-use/lib/usePrevious'; @@ -66,6 +65,7 @@ import { getDefaultCellActions } from './default_cell_actions'; import { LazyAlertsFlyout } from '../..'; import { parseAlert } from './parse_alert'; import { CoreStart } from '../../../../../../src/core/public'; +import { translations } from './translations'; const ALERT_DURATION: typeof ALERT_DURATION_TYPED = ALERT_DURATION_NON_TYPED; const ALERT_REASON: typeof ALERT_REASON_TYPED = ALERT_REASON_NON_TYPED; @@ -115,33 +115,25 @@ export const columns: Array< > = [ { columnHeaderType: 'not-filtered', - displayAsText: i18n.translate('xpack.observability.alertsTGrid.statusColumnDescription', { - defaultMessage: 'Alert Status', - }), + displayAsText: translations.statusColumnDescription, id: ALERT_STATUS, initialWidth: 110, }, { columnHeaderType: 'not-filtered', - displayAsText: i18n.translate('xpack.observability.alertsTGrid.lastUpdatedColumnDescription', { - defaultMessage: 'Last updated', - }), + displayAsText: translations.lastUpdatedColumnDescription, id: TIMESTAMP, initialWidth: 230, }, { columnHeaderType: 'not-filtered', - displayAsText: i18n.translate('xpack.observability.alertsTGrid.durationColumnDescription', { - defaultMessage: 'Duration', - }), + displayAsText: translations.durationColumnDescription, id: ALERT_DURATION, initialWidth: 116, }, { columnHeaderType: 'not-filtered', - displayAsText: i18n.translate('xpack.observability.alertsTGrid.reasonColumnDescription', { - defaultMessage: 'Reason', - }), + displayAsText: translations.reasonColumnDescription, id: ALERT_REASON, linkField: '*', }, @@ -249,73 +241,61 @@ function ObservabilityActions({ ]; }, [afterCaseSelection, casePermissions, timelines, event, statusActionItems, alertPermissions]); - const viewDetailsTextLabel = i18n.translate( - 'xpack.observability.alertsTable.viewDetailsTextLabel', - { - defaultMessage: 'View details', - } - ); - const viewInAppTextLabel = i18n.translate('xpack.observability.alertsTable.viewInAppTextLabel', { - defaultMessage: 'View in app', - }); - const moreActionsTextLabel = i18n.translate( - 'xpack.observability.alertsTable.moreActionsTextLabel', - { - defaultMessage: 'More actions', - } - ); + const actionsToolTip = + actionsMenuItems.length <= 0 + ? translations.notEnoughPermissions + : translations.moreActionsTextLabel; return ( <> - + setFlyoutAlert(alert)} data-test-subj="openFlyoutButton" - aria-label={viewDetailsTextLabel} + aria-label={translations.viewDetailsTextLabel} /> - + - {actionsMenuItems.length > 0 && ( - - - toggleActionsPopover(eventId)} - data-test-subj="alerts-table-row-action-more" - /> - - } - isOpen={openActionsPopoverId === eventId} - closePopover={closeActionsPopover} - panelPaddingSize="none" - anchorPosition="downLeft" - > - - - - )} + + + toggleActionsPopover(eventId)} + data-test-subj="alerts-table-row-action-more" + /> + + } + isOpen={openActionsPopoverId === eventId} + closePopover={closeActionsPopover} + panelPaddingSize="none" + anchorPosition="downLeft" + > + + + ); @@ -363,13 +343,7 @@ export function AlertsTableTGrid(props: AlertsTableTGridProps) { id: 'expand', width: 120, headerCellRender: () => { - return ( - - {i18n.translate('xpack.observability.alertsTable.actionsTextLabel', { - defaultMessage: 'Actions', - })} - - ); + return {translations.actionsTextLabel}; }, rowCellRender: (actionProps: ActionProps) => { return ( @@ -400,12 +374,8 @@ export function AlertsTableTGrid(props: AlertsTableTGridProps) { hasAlertsCrudPermissions, indexNames, itemsPerPageOptions: [10, 25, 50], - loadingText: i18n.translate('xpack.observability.alertsTable.loadingTextLabel', { - defaultMessage: 'loading alerts', - }), - footerText: i18n.translate('xpack.observability.alertsTable.footerTextLabel', { - defaultMessage: 'alerts', - }), + loadingText: translations.loadingTextLabel, + footerText: translations.footerTextLabel, query: { query: `${ALERT_WORKFLOW_STATUS}: ${workflowStatus}${kuery !== '' ? ` and ${kuery}` : ''}`, language: 'kuery', @@ -424,11 +394,7 @@ export function AlertsTableTGrid(props: AlertsTableTGridProps) { filterStatus: workflowStatus as AlertWorkflowStatus, leadingControlColumns, trailingControlColumns, - unit: (totalAlerts: number) => - i18n.translate('xpack.observability.alertsTable.showingAlertsTitle', { - values: { totalAlerts }, - defaultMessage: '{totalAlerts, plural, =1 {alert} other {alerts}}', - }), + unit: (totalAlerts: number) => translations.showingAlertsTitle(totalAlerts), }; }, [ casePermissions, @@ -443,6 +409,7 @@ export function AlertsTableTGrid(props: AlertsTableTGridProps) { leadingControlColumns, deletedEventIds, ]); + const handleFlyoutClose = () => setFlyoutAlert(undefined); const { observabilityRuleTypeRegistry } = usePluginContext(); diff --git a/x-pack/plugins/observability/public/pages/alerts/translations.ts b/x-pack/plugins/observability/public/pages/alerts/translations.ts new file mode 100644 index 0000000000000..4578987e839a0 --- /dev/null +++ b/x-pack/plugins/observability/public/pages/alerts/translations.ts @@ -0,0 +1,61 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +export const translations = { + viewDetailsTextLabel: i18n.translate('xpack.observability.alertsTable.viewDetailsTextLabel', { + defaultMessage: 'View details', + }), + viewInAppTextLabel: i18n.translate('xpack.observability.alertsTable.viewInAppTextLabel', { + defaultMessage: 'View in app', + }), + moreActionsTextLabel: i18n.translate('xpack.observability.alertsTable.moreActionsTextLabel', { + defaultMessage: 'More actions', + }), + notEnoughPermissions: i18n.translate('xpack.observability.alertsTable.notEnoughPermissions', { + defaultMessage: 'Additional privileges required', + }), + statusColumnDescription: i18n.translate( + 'xpack.observability.alertsTGrid.statusColumnDescription', + { + defaultMessage: 'Alert Status', + } + ), + lastUpdatedColumnDescription: i18n.translate( + 'xpack.observability.alertsTGrid.lastUpdatedColumnDescription', + { + defaultMessage: 'Last updated', + } + ), + durationColumnDescription: i18n.translate( + 'xpack.observability.alertsTGrid.durationColumnDescription', + { + defaultMessage: 'Duration', + } + ), + reasonColumnDescription: i18n.translate( + 'xpack.observability.alertsTGrid.reasonColumnDescription', + { + defaultMessage: 'Reason', + } + ), + actionsTextLabel: i18n.translate('xpack.observability.alertsTable.actionsTextLabel', { + defaultMessage: 'Actions', + }), + loadingTextLabel: i18n.translate('xpack.observability.alertsTable.loadingTextLabel', { + defaultMessage: 'loading alerts', + }), + footerTextLabel: i18n.translate('xpack.observability.alertsTable.footerTextLabel', { + defaultMessage: 'alerts', + }), + showingAlertsTitle: (totalAlerts: number) => + i18n.translate('xpack.observability.alertsTable.showingAlertsTitle', { + values: { totalAlerts }, + defaultMessage: '{totalAlerts, plural, =1 {alert} other {alerts}}', + }), +}; diff --git a/x-pack/test/functional/services/observability/alerts/common.ts b/x-pack/test/functional/services/observability/alerts/common.ts index 7e29b94c85fa3..74fbbb742fa0e 100644 --- a/x-pack/test/functional/services/observability/alerts/common.ts +++ b/x-pack/test/functional/services/observability/alerts/common.ts @@ -208,6 +208,13 @@ export function ObservabilityAlertsCommonProvider({ return buttonText.substring(0, buttonText.indexOf('\n')); }; + const getActionsButtonByIndex = async (index: number) => { + const actionsOverflowButtons = await find.allByCssSelector( + '[data-test-subj="alerts-table-row-action-more"]' + ); + return actionsOverflowButtons[index] || null; + }; + return { getQueryBar, clearQueryBar, @@ -236,5 +243,6 @@ export function ObservabilityAlertsCommonProvider({ typeInQueryBar, openActionsMenuForRow, getTimeRange, + getActionsButtonByIndex, }; } diff --git a/x-pack/test/observability_functional/apps/observability/alerts/index.ts b/x-pack/test/observability_functional/apps/observability/alerts/index.ts index 216a9736fbe87..3190a151cb47b 100644 --- a/x-pack/test/observability_functional/apps/observability/alerts/index.ts +++ b/x-pack/test/observability_functional/apps/observability/alerts/index.ts @@ -214,5 +214,28 @@ export default ({ getService }: FtrProviderContext) => { }); }); }); + + describe('Actions Button', () => { + before(async () => { + await observability.users.setTestUserRole( + observability.users.defineBasicObservabilityRole({ + observabilityCases: ['read'], + logs: ['read'], + }) + ); + await esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs'); + await observability.alerts.common.navigateToTimeWithData(); + }); + + after(async () => { + await observability.users.restoreDefaultTestUserRole(); + await esArchiver.unload('x-pack/test/functional/es_archives/infra/metrics_and_logs'); + }); + + it('Is disabled when a user has only read privilages', async () => { + const actionsButton = await observability.alerts.common.getActionsButtonByIndex(0); + expect(await actionsButton.getAttribute('disabled')).to.be('true'); + }); + }); }); };