From dbfffb56b4a9f6444f09ee6a626a7ca38cd75b24 Mon Sep 17 00:00:00 2001 From: Luciano Gorza Date: Mon, 11 Mar 2024 18:24:26 -0300 Subject: [PATCH 01/31] Add upgrade agents global action --- .../components/common/tables/table-wz-api.tsx | 12 +- .../components/outdated-agents-card.tsx | 4 +- .../endpoints-summary/endpoints-summary.scss | 3 +- .../table/actions/actions.tsx | 7 +- .../endpoints-summary/table/agents-table.tsx | 75 +++-- .../endpoints-summary/table/columns.tsx | 2 + .../table/global-actions/global-actions.tsx | 61 +++- .../table/global-actions/upgrade/result.tsx | 260 ++++++++++++++++++ .../global-actions/upgrade/upgrade-modal.tsx | 197 +++++++++++++ .../table/upgradeTaskDetailsModal.tsx | 216 +++++++++++++++ .../taskDetailsButton.tsx | 224 --------------- .../upgrades-in-progress.tsx | 47 +++- 12 files changed, 839 insertions(+), 269 deletions(-) create mode 100644 plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/result.tsx create mode 100644 plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/upgrade-modal.tsx create mode 100644 plugins/main/public/components/endpoints-summary/table/upgradeTaskDetailsModal.tsx delete mode 100644 plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/taskDetailsButton.tsx diff --git a/plugins/main/public/components/common/tables/table-wz-api.tsx b/plugins/main/public/components/common/tables/table-wz-api.tsx index ff2b6f966f..14fb393f50 100644 --- a/plugins/main/public/components/common/tables/table-wz-api.tsx +++ b/plugins/main/public/components/common/tables/table-wz-api.tsx @@ -44,6 +44,7 @@ const getFilters = filters => { export function TableWzAPI({ actionButtons, + postActionButtons, addOnTitle, extra, setReload, @@ -53,6 +54,11 @@ export function TableWzAPI({ | ReactNode | ReactNode[] | (({ filters }: { filters }) => ReactNode); + postActionButtons?: + | ReactNode + | ReactNode[] + | (({ filters }: { filters }) => ReactNode); + title?: string; addOnTitle?: ReactNode; description?: string; @@ -147,7 +153,7 @@ export function TableWzAPI({ }, []); - const renderActionButtons = filters => { + const renderActionButtons = (actionButtons, filters) => { if (Array.isArray(actionButtons)) { return actionButtons.map((button, key) => ( @@ -216,7 +222,7 @@ export function TableWzAPI({ {/* Render optional custom action button */} - {renderActionButtons(filters)} + {renderActionButtons(actionButtons, filters)} {/* Render optional reload button */} {rest.showReload && ReloadButton} {/* Render optional export to CSV button */} @@ -232,6 +238,8 @@ export function TableWzAPI({ } /> )} + {/* Render optional post custom action button */} + {renderActionButtons(postActionButtons, filters)} {rest.showFieldSelector && ( diff --git a/plugins/main/public/components/endpoints-summary/dashboard/components/outdated-agents-card.tsx b/plugins/main/public/components/endpoints-summary/dashboard/components/outdated-agents-card.tsx index 304a05a8ab..6023a05de1 100644 --- a/plugins/main/public/components/endpoints-summary/dashboard/components/outdated-agents-card.tsx +++ b/plugins/main/public/components/endpoints-summary/dashboard/components/outdated-agents-card.tsx @@ -70,10 +70,10 @@ const OutdatedAgentsCard = ({ } description={ - Agents + {outdatedAgents === 1 ? 'Agent' : 'Agents'} } - titleColor='danger' + titleColor='warning' isLoading={isLoading} titleSize='l' textAlign='center' diff --git a/plugins/main/public/components/endpoints-summary/endpoints-summary.scss b/plugins/main/public/components/endpoints-summary/endpoints-summary.scss index f9e50aef92..04a2176409 100644 --- a/plugins/main/public/components/endpoints-summary/endpoints-summary.scss +++ b/plugins/main/public/components/endpoints-summary/endpoints-summary.scss @@ -106,7 +106,7 @@ width: 100%; display: grid; grid-template-columns: 1fr; - gap: 20px 10px; + gap: 16px; min-height: 200px; @media (min-width: 1024px) { @@ -114,7 +114,6 @@ } @media (min-width: 1440px) { - gap: 10px; grid-template-columns: minmax(375px, 1fr) minmax(375px, 1fr) minmax(375px, 1fr) minmax(150px, 300px); diff --git a/plugins/main/public/components/endpoints-summary/table/actions/actions.tsx b/plugins/main/public/components/endpoints-summary/table/actions/actions.tsx index 1a799c5bef..0df704c765 100644 --- a/plugins/main/public/components/endpoints-summary/table/actions/actions.tsx +++ b/plugins/main/public/components/endpoints-summary/table/actions/actions.tsx @@ -8,6 +8,7 @@ import { Agent } from '../../types'; export const agentsTableActions = ( allowEditGroups: boolean, + allowUpgrade: boolean, setAgent: (agent: Agent) => void, setIsEditGroupsVisible: (visible: boolean) => void, setIsUpgradeModalVisible: (visible: boolean) => void, @@ -124,7 +125,11 @@ export const agentsTableActions = ( const isOutdated = !!outdatedAgents.find( outdatedAgent => outdatedAgent.id === agent.id, ); - return agent.status === API_NAME_AGENT_STATUS.ACTIVE && isOutdated; + return ( + allowUpgrade && + agent.status === API_NAME_AGENT_STATUS.ACTIVE && + isOutdated + ); }, }, ]; diff --git a/plugins/main/public/components/endpoints-summary/table/agents-table.tsx b/plugins/main/public/components/endpoints-summary/table/agents-table.tsx index 640e24edd1..de01971cb1 100644 --- a/plugins/main/public/components/endpoints-summary/table/agents-table.tsx +++ b/plugins/main/public/components/endpoints-summary/table/agents-table.tsx @@ -45,6 +45,7 @@ import { getOutdatedAgents } from '../services'; import { UI_ERROR_SEVERITIES } from '../../../react-services/error-orchestrator/types'; import { getErrorOrchestrator } from '../../../react-services/common-services'; import { AgentUpgradesInProgress } from './upgrades-in-progress/upgrades-in-progress'; +import { AgentUpgradesTaskDetailsModal } from './upgradeTaskDetailsModal'; const searchBarWQLOptions = { implicitQuery: { @@ -93,8 +94,14 @@ export const AgentsTable = compose( const [denyEditGroups] = useUserPermissionsRequirements([ { action: 'group:modify_assignments', resource: 'group:id:*' }, ]); + const [denyUpgrade] = useUserPermissionsRequirements([ + { action: 'agent:upgrade', resource: 'agent:id:*' }, + ]); const [outdatedAgents, setOutdatedAgents] = useState([]); + const [isUpgradeTasksModalVisible, setIsUpgradeTasksModalVisible] = + useState(false); + useEffect(() => { if (sessionStorage.getItem('wz-agents-overview-table-filter')) { sessionStorage.removeItem('wz-agents-overview-table-filter'); @@ -230,41 +237,44 @@ export const AgentsTable = compose( } + extra={ + + } actionButtons={({ filters }) => ( - <> - - - Deploy new agent - - - - reloadAgents()} - /> - - + + + Deploy new agent + + + )} + postActionButtons={({ filters }) => ( + + reloadAgents()} + setIsUpgradeTasksModalVisible={setIsUpgradeTasksModalVisible} + /> + )} endpoint='/agents' tableColumns={agentsTableColumns( !denyEditGroups, + !denyUpgrade, setAgent, setIsEditGroupsVisible, setIsUpgradeModalVisible, @@ -466,6 +476,11 @@ export const AgentsTable = compose( }} /> ) : null} + {isUpgradeTasksModalVisible ? ( + setIsUpgradeTasksModalVisible(false)} + /> + ) : null} ); }); diff --git a/plugins/main/public/components/endpoints-summary/table/columns.tsx b/plugins/main/public/components/endpoints-summary/table/columns.tsx index c1f1b433ba..e67361d37d 100644 --- a/plugins/main/public/components/endpoints-summary/table/columns.tsx +++ b/plugins/main/public/components/endpoints-summary/table/columns.tsx @@ -17,6 +17,7 @@ import { Agent } from '../types'; // This is added to prevent the wrap because of the table-layout: auto export const agentsTableColumns = ( allowEditGroups: boolean, + allowUpgrade: boolean, setAgent: (agents: Agent) => void, setIsEditGroupsVisible: (visible: boolean) => void, setIsUpgradeModalVisible: (visible: boolean) => void, @@ -156,6 +157,7 @@ export const agentsTableColumns = ( show: true, actions: agentsTableActions( allowEditGroups, + allowUpgrade, setAgent, setIsEditGroupsVisible, setIsUpgradeModalVisible, diff --git a/plugins/main/public/components/endpoints-summary/table/global-actions/global-actions.tsx b/plugins/main/public/components/endpoints-summary/table/global-actions/global-actions.tsx index 236569fbc4..aa644abd8c 100644 --- a/plugins/main/public/components/endpoints-summary/table/global-actions/global-actions.tsx +++ b/plugins/main/public/components/endpoints-summary/table/global-actions/global-actions.tsx @@ -4,10 +4,12 @@ import { EuiButtonEmpty, EuiContextMenuPanel, EuiContextMenuItem, + EuiHorizontalRule, } from '@elastic/eui'; import { WzElementPermissions } from '../../../common/permissions/element'; import { Agent } from '../../types'; import { EditAgentsGroupsModal } from './edit-groups/edit-groups-modal'; +import { UpgradeAgentsModal } from './upgrade/upgrade-modal'; export interface AgentsTableGlobalActionsProps { selectedAgents: Agent[]; @@ -15,7 +17,9 @@ export interface AgentsTableGlobalActionsProps { allAgentsCount: number; filters: any; allowEditGroups: boolean; + allowUpgrade: boolean; reloadAgents: () => void; + setIsUpgradeTasksModalVisible: (isModalVisible: boolean) => void; } export const AgentsTableGlobalActions = ({ @@ -24,13 +28,16 @@ export const AgentsTableGlobalActions = ({ allAgentsCount, filters, allowEditGroups, + allowUpgrade, reloadAgents, + setIsUpgradeTasksModalVisible, }: AgentsTableGlobalActionsProps) => { const [isPopoverOpen, setPopover] = useState(false); const [isEditGroupsVisible, setIsEditGroupsVisible] = useState(false); const [addOrRemoveGroups, setAddOrRemoveGroups] = useState< 'add' | 'remove' >(); + const [isUpgradeAgentsVisible, setIsUpgradeAgentsVisible] = useState(false); const onButtonClick = () => { setPopover(!isPopoverOpen); @@ -46,7 +53,7 @@ export const AgentsTableGlobalActions = ({ iconSide='right' onClick={onButtonClick} > - Add/Remove groups + More ); @@ -112,6 +119,47 @@ export const AgentsTableGlobalActions = ({ + + { + closePopover(); + setIsUpgradeAgentsVisible(true); + }} + > + + + Upgrade agents + {totalAgents ? ` (${totalAgents})` : ''} + + + + { + closePopover(); + setIsUpgradeTasksModalVisible(true); + }} + > + + Upgrade task details + + {isEditGroupsVisible ? ( @@ -126,6 +174,17 @@ export const AgentsTableGlobalActions = ({ addOrRemove={addOrRemoveGroups} /> ) : null} + {isUpgradeAgentsVisible ? ( + reloadAgents()} + onClose={() => { + setIsUpgradeAgentsVisible(false); + }} + /> + ) : null} ); }; diff --git a/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/result.tsx b/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/result.tsx new file mode 100644 index 0000000000..a11a26033f --- /dev/null +++ b/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/result.tsx @@ -0,0 +1,260 @@ +import React from 'react'; +import { + EuiSteps, + EuiAccordion, + EuiInMemoryTable, + EuiCallOut, + EuiText, + EuiFlexGroup, + EuiFlexItem, + EuiIcon, + EuiLoadingSpinner, + EuiSpacer, +} from '@elastic/eui'; +import { Agent } from '../../../types'; +import { RESULT_TYPE, Result } from './upgrade-modal'; + +interface UpgradeAgentsModalResultProps { + finalAgents: Agent[]; + getAgentsStatus: string; + getAgentsError?: Error; + saveChangesStatus: string; + results: Result[]; +} + +export const UpgradeAgentsModalResult = ({ + finalAgents, + getAgentsStatus, + getAgentsError, + saveChangesStatus, + results, +}: UpgradeAgentsModalResultProps) => { + const agentsTable = (agents: Agent[]) => ( + 10} + sorting={{ + sort: { + field: 'id', + direction: 'asc', + }, + }} + /> + ); + + const errorsTable = (errors = []) => ( + ids.join(', '), + }, + ]} + pagination={errors.length > 10} + /> + ); + + const groupStatus = (options: { + isLoading?: boolean; + status: RESULT_TYPE; + text: string; + }) => { + const { isLoading, status, text } = options; + + return ( + + + {isLoading ? ( + + ) : ( + + )} + + + + {text} + + + + ); + }; + + return ( + + {agentsTable(finalAgents)} + + ) : ( + + {getAgentsError?.message} + + ), + }, + { + step: 2, + title: 'Upgrade agent tasks', + status: saveChangesStatus, + children: + getAgentsStatus === 'complete' ? ( + + {/* {groups.map(group => { + const groupResult = groupResults.find( + groupResult => groupResult.group === group, + ); + const isLoading = !groupResult; + + if (isLoading) + return ( + + {groupStatus({ + isLoading, + status: RESULT_TYPE.SUCCESS, + text: group, + })} + + ); + + const { + result, + successAgents, + errorAgents, + errorMessage, + totalErrorAgents, + } = groupResult; + + if (result === RESULT_TYPE.SUCCESS) + return ( + + + {agentsTable(finalAgents)} + + + ); + + return ( + + + + {errorsTable(errorAgents)} + + {successAgents?.length ? ( + <> + + + {agentsTable( + successAgents.map( + agentId => + finalAgents.find( + finalAgent => finalAgent.id === agentId, + ) as Agent, + ), + )} + + + ) : null} + + + ); + })} */} + + ) : null, + }, + ]} + /> + ); +}; diff --git a/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/upgrade-modal.tsx b/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/upgrade-modal.tsx new file mode 100644 index 0000000000..3d2090954c --- /dev/null +++ b/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/upgrade-modal.tsx @@ -0,0 +1,197 @@ +import React, { useState } from 'react'; +import { + EuiModal, + EuiModalHeader, + EuiModalHeaderTitle, + EuiModalBody, + EuiModalFooter, + EuiButtonEmpty, + EuiButton, + EuiForm, + EuiFormRow, + EuiText, + EuiCallOut, +} from '@elastic/eui'; +import { compose } from 'redux'; +import { withErrorBoundary, withReduxProvider } from '../../../../common/hocs'; +import { UI_LOGGER_LEVELS } from '../../../../../../common/constants'; +import { UI_ERROR_SEVERITIES } from '../../../../../react-services/error-orchestrator/types'; +import { getErrorOrchestrator } from '../../../../../react-services/common-services'; +import { getAgentsService, upgradeAgentsService } from '../../../services'; +import { Agent } from '../../../types'; +import { ErrorAgent } from '../../../services/paginated-agents-group'; +import { UpgradeAgentsModalResult } from './result'; + +export enum RESULT_TYPE { + SUCCESS = 'success', + ERROR = 'error', +} + +export type Result = { + group: string; + result: RESULT_TYPE; + successAgents?: string[]; + errorMessage?: string; + totalErrorAgents?: number; + errorAgents?: ErrorAgent[]; +}; + +interface UpgradeAgentsModalProps { + selectedAgents: Agent[]; + allAgentsSelected: boolean; + filters: any; + onClose: () => void; + reloadAgents: () => void; +} + +export const UpgradeAgentsModal = compose( + withErrorBoundary, + withReduxProvider, +)( + ({ + selectedAgents, + allAgentsSelected, + filters, + onClose, + reloadAgents, + }: UpgradeAgentsModalProps) => { + const [finalAgents, setFinalAgents] = useState([]); + const [getAgentsStatus, setGetAgentsStatus] = useState('disabled'); + const [getAgentsError, setGetAgentsError] = useState(); + const [saveChangesStatus, setSaveChangesStatus] = useState('disabled'); + const [isResultVisible, setIsResultVisible] = useState(false); + const [results, setResults] = useState([]); + + const getAgents = async () => { + if (!allAgentsSelected) { + setGetAgentsStatus('complete'); + return selectedAgents; + } + try { + const { affected_items } = await getAgentsService({ filters }); + setGetAgentsStatus('complete'); + return affected_items; + } catch (error) { + setGetAgentsStatus('danger'); + setGetAgentsError(error); + + const options = { + context: `UpgradeAgentsModal.handleOnSave`, + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.BUSINESS, + store: true, + error: { + error, + message: error.message || error, + title: `Could not get agents data`, + }, + }; + getErrorOrchestrator().handleError(options); + } + }; + + const getArrayByProperty = ( + array: Agent[], + propertyName: string, + ): string[] => { + return array.map(element => element[propertyName]); + }; + + const handleOnSave = async () => { + setGetAgentsStatus('loading'); + setIsResultVisible(true); + + const agents = await getAgents(); + + if (!agents?.length) { + return; + } + + setFinalAgents(agents); + + setSaveChangesStatus('loading'); + + const agentIds = getArrayByProperty(agents, 'id'); + + try { + await upgradeAgentsService({ agentIds }); + setSaveChangesStatus('complete'); + } catch (error) { + setSaveChangesStatus('danger'); + const options = { + context: `UpgradeAgentsModal.handleOnSave`, + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.BUSINESS, + store: true, + error: { + error, + message: error.message || error, + title: `Could not upgrade agents`, + }, + }; + getErrorOrchestrator().handleError(options); + } finally { + reloadAgents(); + } + }; + + const form = ( + + {allAgentsSelected ? ( + + + + ) : ( + + {selectedAgents.length} + + )} + + ); + + return ( + + + Upgrade agents + + + {!isResultVisible ? ( + form + ) : ( + + )} + + + {!isResultVisible ? ( + <> + Cancel + + Upgrade + + + ) : ( + + Close + + )} + + + ); + }, +); diff --git a/plugins/main/public/components/endpoints-summary/table/upgradeTaskDetailsModal.tsx b/plugins/main/public/components/endpoints-summary/table/upgradeTaskDetailsModal.tsx new file mode 100644 index 0000000000..e768d83f04 --- /dev/null +++ b/plugins/main/public/components/endpoints-summary/table/upgradeTaskDetailsModal.tsx @@ -0,0 +1,216 @@ +import React from 'react'; +import { EuiHealth, EuiIconTip } from '@elastic/eui'; +import { TableWzAPI } from '../../common/tables'; +import { formatUIDate } from '../../../react-services/time-service'; +import { + API_NAME_TASK_STATUS, + SEARCH_BAR_WQL_VALUE_SUGGESTIONS_COUNT, + UI_TASK_STATUS, +} from '../../../../common/constants'; +import { WzRequest } from '../../../react-services/wz-request'; +import { get as getLodash, uniqBy as uniqByLodash } from 'lodash'; +import { + EuiModal, + EuiModalHeader, + EuiModalBody, + EuiModalFooter, + EuiButton, +} from '@elastic/eui'; + +interface AgentUpgradesTaskDetailsModalProps { + onClose: () => void; +} + +export const AgentUpgradesTaskDetailsModal = ({ + onClose, +}: AgentUpgradesTaskDetailsModalProps) => { + const datetime = new Date(); + datetime.setMinutes(datetime.getMinutes() - 60); + const formattedDate = datetime.toISOString(); + + const defaultFilters = { + q: `last_update_time>${formattedDate}`, + }; + + const handleOnCloseModal = () => onClose(); + + return ( + + + + + Create{' '} + + + ), + sortable: true, + searchable: false, + show: true, + render: value => formatUIDate(value), + }, + { + field: 'last_update_time', + name: ( + + Last update{' '} + + + ), + sortable: true, + searchable: false, + show: true, + render: value => formatUIDate(value), + }, + { + field: 'status', + name: 'Status', + width: '100px', + sortable: true, + searchable: true, + show: true, + render: value => ( + + {value} + + ), + }, + { + field: 'error_message', + name: 'Error', + show: true, + searchable: true, + }, + ]} + tableInitialSortingField='last_update_time' + tableInitialSortingDirection='desc' + tablePageSizeOptions={[10, 25, 50, 100]} + filters={defaultFilters} + downloadCsv + showReload + showFieldSelector + searchTable + searchBarWQL={{ + suggestions: { + field(currentValue) { + return [ + { + label: 'agent_id', + description: 'filter by agent id', + }, + { label: 'status', description: 'filter by status' }, + { + label: 'create_time', + description: 'filter by creation date', + }, + { + label: 'last_update_time', + description: 'filter by last update date', + }, + { label: 'task_id', description: 'filter by task id' }, + ]; + }, + value: async (currentValue, { field }) => { + try { + switch (field) { + case 'status': + return UI_TASK_STATUS.map(status => ({ + label: status, + })); + default: { + const response = await WzRequest.apiReq( + 'GET', + '/tasks/status', + { + params: { + limit: SEARCH_BAR_WQL_VALUE_SUGGESTIONS_COUNT, + select: field, + sort: `+${field}`, + ...(currentValue + ? { + q: `${field}~${currentValue}`, + } + : {}), + }, + }, + ); + const suggestionValues = + response?.data?.data.affected_items.map(item => ({ + label: getLodash(item, field), + })); + return uniqByLodash(suggestionValues, 'label'); + } + } + } catch (error) { + return []; + } + }, + }, + validate: { + value: ({ formattedValue, value: rawValue }, { field }) => { + const value = formattedValue ?? rawValue; + if (value) { + if (['create_time', 'last_update_time'].includes(field)) { + const isCorrectDate = + /^\d{4}-\d{2}-\d{2}([ T]\d{2}:\d{2}:\d{2}(.\d{1,6})?Z?)?$/.test( + value, + ); + return isCorrectDate + ? undefined + : `"${value}" is not a expected format. Valid formats: YYYY-MM-DD, YYYY-MM-DD HH:mm:ss, YYYY-MM-DDTHH:mm:ss, YYYY-MM-DDTHH:mm:ssZ.`; + } + } + }, + }, + }} + tableProps={{ + tableLayout: 'auto', + }} + /> + + + + Close + + + + ); +}; diff --git a/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/taskDetailsButton.tsx b/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/taskDetailsButton.tsx deleted file mode 100644 index 5e1753dde7..0000000000 --- a/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/taskDetailsButton.tsx +++ /dev/null @@ -1,224 +0,0 @@ -import React, { useState, memo } from 'react'; -import { EuiHealth, EuiIconTip } from '@elastic/eui'; -import { TableWzAPI } from '../../../common/tables'; -import { formatUIDate } from '../../../../react-services/time-service'; -import { - API_NAME_TASK_STATUS, - SEARCH_BAR_WQL_VALUE_SUGGESTIONS_COUNT, - UI_TASK_STATUS, -} from '../../../../../common/constants'; -import { WzRequest } from '../../../../react-services/wz-request'; -import { get as getLodash, uniqBy as uniqByLodash } from 'lodash'; -import { - EuiModal, - EuiModalHeader, - EuiModalBody, - EuiModalFooter, - EuiButton, - EuiButtonEmpty, -} from '@elastic/eui'; - -export const AgentUpgradesTaskDetailsButton = memo(() => { - const [isModalVisible, setIsModalVisible] = useState(false); - - const datetime = new Date(); - datetime.setMinutes(datetime.getMinutes() - 60); - const formattedDate = datetime.toISOString(); - - const defaultFilters = { - q: `last_update_time>${formattedDate}`, - }; - - const handleOnCloseModal = () => setIsModalVisible(false); - - return ( - <> - setIsModalVisible(true)} - iconType='eye' - > - Task details - - {isModalVisible ? ( - - - - - Create{' '} - - - ), - sortable: true, - searchable: false, - show: true, - render: value => formatUIDate(value), - }, - { - field: 'last_update_time', - name: ( - - Last update{' '} - - - ), - sortable: true, - searchable: false, - show: true, - render: value => formatUIDate(value), - }, - { - field: 'status', - name: 'Status', - width: '100px', - sortable: true, - searchable: true, - show: true, - render: value => ( - - {value} - - ), - }, - { - field: 'error_message', - name: 'Error', - show: true, - searchable: true, - }, - ]} - tableInitialSortingField='last_update_time' - tableInitialSortingDirection='desc' - tablePageSizeOptions={[10, 25, 50, 100]} - filters={defaultFilters} - downloadCsv - showReload - showFieldSelector - searchTable - searchBarWQL={{ - suggestions: { - field(currentValue) { - return [ - { - label: 'agent_id', - description: 'filter by agent id', - }, - { label: 'status', description: 'filter by status' }, - { - label: 'create_time', - description: 'filter by creation date', - }, - { - label: 'last_update_time', - description: 'filter by last update date', - }, - { label: 'task_id', description: 'filter by task id' }, - ]; - }, - value: async (currentValue, { field }) => { - try { - switch (field) { - case 'status': - return UI_TASK_STATUS.map(status => ({ - label: status, - })); - default: { - const response = await WzRequest.apiReq( - 'GET', - '/tasks/status', - { - params: { - limit: SEARCH_BAR_WQL_VALUE_SUGGESTIONS_COUNT, - select: field, - sort: `+${field}`, - ...(currentValue - ? { - q: `${field}~${currentValue}`, - } - : {}), - }, - }, - ); - const suggestionValues = - response?.data?.data.affected_items.map(item => ({ - label: getLodash(item, field), - })); - return uniqByLodash(suggestionValues, 'label'); - } - } - } catch (error) { - return []; - } - }, - }, - validate: { - value: ({ formattedValue, value: rawValue }, { field }) => { - const value = formattedValue ?? rawValue; - if (value) { - if (['create_time', 'last_update_time'].includes(field)) { - const isCorrectDate = - /^\d{4}-\d{2}-\d{2}([ T]\d{2}:\d{2}:\d{2}(.\d{1,6})?Z?)?$/.test( - value, - ); - return isCorrectDate - ? undefined - : `"${value}" is not a expected format. Valid formats: YYYY-MM-DD, YYYY-MM-DD HH:mm:ss, YYYY-MM-DDTHH:mm:ss, YYYY-MM-DDTHH:mm:ssZ.`; - } - } - }, - }, - }} - tableProps={{ - tableLayout: 'auto', - }} - /> - - - - Close - - - - ) : null} - - ); -}); diff --git a/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.tsx b/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.tsx index 81b1133c94..d57f2f9f1a 100644 --- a/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.tsx +++ b/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.tsx @@ -7,21 +7,26 @@ import { EuiFlexItem, EuiIconTip, EuiSpacer, + EuiButtonEmpty, + EuiButtonIcon, } from '@elastic/eui'; import { useGetUpgradeTasks } from '../../hooks'; import { UI_LOGGER_LEVELS } from '../../../../../common/constants'; import { UI_ERROR_SEVERITIES } from '../../../../react-services/error-orchestrator/types'; import { getErrorOrchestrator } from '../../../../react-services/common-services'; -import { AgentUpgradesTaskDetailsButton } from './taskDetailsButton'; interface AgentUpgradesInProgress { reload: any; + setIsModalVisible: (isModalVisible: boolean) => void; } export const AgentUpgradesInProgress = ({ reload, + setIsModalVisible, }: AgentUpgradesInProgress) => { const [isUpgrading, setIsUpgrading] = useState(false); + const [isPanelClosed, setIsPanelClosed] = useState(false); + const { totalInProgressTasks, getInProgressError, @@ -82,14 +87,42 @@ export const AgentUpgradesInProgress = ({ getErrorOrchestrator().handleError(options); } - return isUpgrading || totalSuccessTasks || totalErrorUpgradeTasks ? ( + return !isPanelClosed && + (isUpgrading || totalSuccessTasks || totalErrorUpgradeTasks) ? ( - - - Upgrade tasks - + + + + Upgrade tasks + + + setIsModalVisible(true)} + iconType='eye' + > + Task details + + + - + setIsPanelClosed(true)} + color='text' + iconType='cross' + aria-label='Close' + /> From 23d9bbad68ec4cc1a1653ae0f0a90d45c1b6af09 Mon Sep 17 00:00:00 2001 From: Luciano Gorza Date: Tue, 12 Mar 2024 17:02:07 -0300 Subject: [PATCH 02/31] Add Upgrade result modal --- .../services/add-agents-to-group.ts | 8 +- ....tsx => paginated-agents-request.test.tsx} | 14 +- ...group.tsx => paginated-agents-request.tsx} | 16 +- .../services/remove-agents-from-group.tsx | 8 +- .../services/upgrade-agents.tsx | 19 +- .../__snapshots__/agents-table.test.tsx.snap | 250 +++++++++--------- .../actions/upgrade-agent-modal.test.tsx | 2 +- .../table/actions/upgrade-agent-modal.tsx | 1 - .../endpoints-summary/table/agents-table.tsx | 5 +- .../global-actions.test.tsx.snap | 2 +- .../edit-groups/edit-groups-modal.test.tsx | 5 + .../global-actions/edit-groups/result.tsx | 7 +- .../global-actions/global-actions.test.tsx | 10 +- .../table/global-actions/global-actions.tsx | 3 + .../table/global-actions/upgrade/result.tsx | 192 +++++++------- .../global-actions/upgrade/upgrade-modal.tsx | 47 +++- .../table/upgradeTaskDetailsModal.tsx | 9 +- .../upgrades-in-progress.test.tsx.snap | 82 ++++-- .../upgrades-in-progress.tsx | 5 +- 19 files changed, 389 insertions(+), 296 deletions(-) rename plugins/main/public/components/endpoints-summary/services/{paginated-agents-group.test.tsx => paginated-agents-request.test.tsx} (93%) rename plugins/main/public/components/endpoints-summary/services/{paginated-agents-group.tsx => paginated-agents-request.tsx} (92%) diff --git a/plugins/main/public/components/endpoints-summary/services/add-agents-to-group.ts b/plugins/main/public/components/endpoints-summary/services/add-agents-to-group.ts index 5c563167f1..97cdb37988 100644 --- a/plugins/main/public/components/endpoints-summary/services/add-agents-to-group.ts +++ b/plugins/main/public/components/endpoints-summary/services/add-agents-to-group.ts @@ -1,9 +1,13 @@ import IApiResponse from '../../../react-services/interfaces/api-response.interface'; -import { paginatedAgentsGroupService } from './paginated-agents-group'; +import { paginatedAgentsRequestService } from './paginated-agents-request'; export const addAgentsToGroupService = async (parameters: { agentIds: string[]; groupId: string; pageSize?: number; }): Promise> => - await paginatedAgentsGroupService({ addOrRemove: 'add', ...parameters }); + await paginatedAgentsRequestService({ + method: 'PUT', + url: '/agents/group', + ...parameters, + }); diff --git a/plugins/main/public/components/endpoints-summary/services/paginated-agents-group.test.tsx b/plugins/main/public/components/endpoints-summary/services/paginated-agents-request.test.tsx similarity index 93% rename from plugins/main/public/components/endpoints-summary/services/paginated-agents-group.test.tsx rename to plugins/main/public/components/endpoints-summary/services/paginated-agents-request.test.tsx index e6f506dfe0..a746eb6aa3 100644 --- a/plugins/main/public/components/endpoints-summary/services/paginated-agents-group.test.tsx +++ b/plugins/main/public/components/endpoints-summary/services/paginated-agents-request.test.tsx @@ -1,4 +1,4 @@ -import { paginatedAgentsGroupService } from './paginated-agents-group'; +import { paginatedAgentsRequestService } from './paginated-agents-request'; import { WzRequest } from '../../../react-services/wz-request'; jest.mock('../../../react-services/wz-request', () => ({ @@ -7,7 +7,7 @@ jest.mock('../../../react-services/wz-request', () => ({ }, })); -describe('paginatedAgentsGroupService', () => { +describe('paginatedAgentsRequestService', () => { beforeEach(() => { jest.clearAllMocks(); }); @@ -46,13 +46,14 @@ describe('paginatedAgentsGroupService', () => { ); const params = { - addOrRemove: 'add' as any, + method: 'PUT' as any, + url: '/agents/group', agentIds: ['agent1', 'agent2', 'agent3'], groupId: 'group1', pageSize: 2, }; - const result = await paginatedAgentsGroupService(params); + const result = await paginatedAgentsRequestService(params); expect(WzRequest.apiReq).toHaveBeenCalledWith( 'PUT', @@ -146,13 +147,14 @@ describe('paginatedAgentsGroupService', () => { ); const params = { - addOrRemove: 'add' as any, + method: 'PUT' as any, + url: '/agents/group', agentIds: ['agent1', 'agent2', 'agent3'], groupId: 'group1', pageSize: 2, }; - const result = await paginatedAgentsGroupService(params); + const result = await paginatedAgentsRequestService(params); expect(WzRequest.apiReq).toHaveBeenCalledWith( 'PUT', diff --git a/plugins/main/public/components/endpoints-summary/services/paginated-agents-group.tsx b/plugins/main/public/components/endpoints-summary/services/paginated-agents-request.tsx similarity index 92% rename from plugins/main/public/components/endpoints-summary/services/paginated-agents-group.tsx rename to plugins/main/public/components/endpoints-summary/services/paginated-agents-request.tsx index 512098817c..0f8020ea89 100644 --- a/plugins/main/public/components/endpoints-summary/services/paginated-agents-group.tsx +++ b/plugins/main/public/components/endpoints-summary/services/paginated-agents-request.tsx @@ -10,15 +10,17 @@ export type ErrorAgent = { id: string[]; }; -export const paginatedAgentsGroupService = async ({ - addOrRemove, +export const paginatedAgentsRequestService = async ({ + method, + url, agentIds, groupId, pageSize = 1000, }: { - addOrRemove: 'add' | 'remove'; + method: 'PUT' | 'DELETE'; + url: string; agentIds: string[]; - groupId: string; + groupId?: string; pageSize?: number; }): Promise> => { let offset = 0; @@ -45,11 +47,11 @@ export const paginatedAgentsGroupService = async ({ message: responseMessage, }, } = (await WzRequest.apiReq( - addOrRemove === 'add' ? 'PUT' : 'DELETE', - `/agents/group`, + method, + url, { params: { - group_id: groupId, + ...(groupId ? { group_id: groupId } : {}), agents_list: requestAgentIds.join(','), wait_for_complete: true, }, diff --git a/plugins/main/public/components/endpoints-summary/services/remove-agents-from-group.tsx b/plugins/main/public/components/endpoints-summary/services/remove-agents-from-group.tsx index a2000e9ba4..5509698e7d 100644 --- a/plugins/main/public/components/endpoints-summary/services/remove-agents-from-group.tsx +++ b/plugins/main/public/components/endpoints-summary/services/remove-agents-from-group.tsx @@ -1,9 +1,13 @@ import IApiResponse from '../../../react-services/interfaces/api-response.interface'; -import { paginatedAgentsGroupService } from './paginated-agents-group'; +import { paginatedAgentsRequestService } from './paginated-agents-request'; export const removeAgentsFromGroupService = async (parameters: { agentIds: string[]; groupId: string; pageSize?: number; }): Promise> => - await paginatedAgentsGroupService({ addOrRemove: 'remove', ...parameters }); + await paginatedAgentsRequestService({ + method: 'DELETE', + url: '/agents/group', + ...parameters, + }); diff --git a/plugins/main/public/components/endpoints-summary/services/upgrade-agents.tsx b/plugins/main/public/components/endpoints-summary/services/upgrade-agents.tsx index ea9c8f7e6b..e20a1d5ef4 100644 --- a/plugins/main/public/components/endpoints-summary/services/upgrade-agents.tsx +++ b/plugins/main/public/components/endpoints-summary/services/upgrade-agents.tsx @@ -1,15 +1,22 @@ import IApiResponse from '../../../react-services/interfaces/api-response.interface'; import { WzRequest } from '../../../react-services/wz-request'; import { ResponseUpgradeAgents } from '../types'; +import { paginatedAgentsRequestService } from './paginated-agents-request'; export const upgradeAgentsService = async ({ agentIds, }: { agentIds: string[]; }) => - (await WzRequest.apiReq('PUT', `/agents/upgrade`, { - params: { - agents_list: agentIds.join(','), - wait_for_complete: true, - }, - })) as IApiResponse; + (agentIds.length === 1 + ? await WzRequest.apiReq('PUT', '/agents/upgrade', { + params: { + agents_list: agentIds.join(','), + wait_for_complete: true, + }, + }) + : await paginatedAgentsRequestService({ + method: 'PUT', + url: '/agents/upgrade', + agentIds, + })) as IApiResponse; diff --git a/plugins/main/public/components/endpoints-summary/table/__snapshots__/agents-table.test.tsx.snap b/plugins/main/public/components/endpoints-summary/table/__snapshots__/agents-table.test.tsx.snap index 6cd96fd8bc..5f7489b92b 100644 --- a/plugins/main/public/components/endpoints-summary/table/__snapshots__/agents-table.test.tsx.snap +++ b/plugins/main/public/components/endpoints-summary/table/__snapshots__/agents-table.test.tsx.snap @@ -79,47 +79,6 @@ exports[`AgentsTable component Renders correctly to match the snapshot 1`] = ` -
-
-
- -
-
-
@@ -185,6 +144,47 @@ exports[`AgentsTable component Renders correctly to match the snapshot 1`] = `
+
+
+
+ +
+
+
@@ -735,48 +735,6 @@ exports[`AgentsTable component Renders correctly to match the snapshot with cust
-
-
-
- -
-
-
@@ -842,6 +800,48 @@ exports[`AgentsTable component Renders correctly to match the snapshot with cust
+
+
+
+ +
+
+
@@ -1349,48 +1349,6 @@ exports[`AgentsTable component Renders correctly to match the snapshot with no p
-
-
-
- -
-
-
@@ -1456,6 +1414,48 @@ exports[`AgentsTable component Renders correctly to match the snapshot with no p
+
+
+
+ +
+
+
diff --git a/plugins/main/public/components/endpoints-summary/table/actions/upgrade-agent-modal.test.tsx b/plugins/main/public/components/endpoints-summary/table/actions/upgrade-agent-modal.test.tsx index 76ce5111ed..8431c997c5 100644 --- a/plugins/main/public/components/endpoints-summary/table/actions/upgrade-agent-modal.test.tsx +++ b/plugins/main/public/components/endpoints-summary/table/actions/upgrade-agent-modal.test.tsx @@ -40,7 +40,7 @@ describe('UpgradeAgentModal component', () => { }); test('should send to upgrade', async () => { - const { getByText, getByRole } = render( + const { getByRole } = render( ([]); - const [isUpgradeTasksModalVisible, setIsUpgradeTasksModalVisible] = useState(false); + const [isUpgradePanelClosed, setIsUpgradePanelClosed] = useState(false); useEffect(() => { if (sessionStorage.getItem('wz-agents-overview-table-filter')) { @@ -241,6 +241,8 @@ export const AgentsTable = compose( } actionButtons={({ filters }) => ( @@ -268,6 +270,7 @@ export const AgentsTable = compose( allowUpgrade={!denyUpgrade} reloadAgents={() => reloadAgents()} setIsUpgradeTasksModalVisible={setIsUpgradeTasksModalVisible} + setIsUpgradePanelClosed={setIsUpgradePanelClosed} /> )} diff --git a/plugins/main/public/components/endpoints-summary/table/global-actions/__snapshots__/global-actions.test.tsx.snap b/plugins/main/public/components/endpoints-summary/table/global-actions/__snapshots__/global-actions.test.tsx.snap index b67113993a..1e2d0d4915 100644 --- a/plugins/main/public/components/endpoints-summary/table/global-actions/__snapshots__/global-actions.test.tsx.snap +++ b/plugins/main/public/components/endpoints-summary/table/global-actions/__snapshots__/global-actions.test.tsx.snap @@ -33,7 +33,7 @@ exports[`AgentsTableGlobalActions component should return the component 1`] = ` - Add/Remove groups + More diff --git a/plugins/main/public/components/endpoints-summary/table/global-actions/edit-groups/edit-groups-modal.test.tsx b/plugins/main/public/components/endpoints-summary/table/global-actions/edit-groups/edit-groups-modal.test.tsx index fced06a7dd..188854d1ec 100644 --- a/plugins/main/public/components/endpoints-summary/table/global-actions/edit-groups/edit-groups-modal.test.tsx +++ b/plugins/main/public/components/endpoints-summary/table/global-actions/edit-groups/edit-groups-modal.test.tsx @@ -21,6 +21,11 @@ jest.mock('../../../../../react-services/common-services', () => ({ }), })); +// jest.mock('../../../../common/hocs', () => ({ +// withErrorBoundary: () => {}, +// withReduxProvider: () => {}, +// })); + describe('EditAgentsGroupsModal component', () => { test('should return the component with save disabled', async () => { (useGetGroups as jest.Mock).mockReturnValue({ diff --git a/plugins/main/public/components/endpoints-summary/table/global-actions/edit-groups/result.tsx b/plugins/main/public/components/endpoints-summary/table/global-actions/edit-groups/result.tsx index b01644ae66..4058e70462 100644 --- a/plugins/main/public/components/endpoints-summary/table/global-actions/edit-groups/result.tsx +++ b/plugins/main/public/components/endpoints-summary/table/global-actions/edit-groups/result.tsx @@ -12,7 +12,8 @@ import { EuiSpacer, } from '@elastic/eui'; import { Agent } from '../../../types'; -import { ErrorAgent, GroupResult, RESULT_TYPE } from './edit-groups-modal'; +import { GroupResult, RESULT_TYPE } from './edit-groups-modal'; +import { ErrorAgent } from '../../../services/paginated-agents-group'; interface EditAgentsGroupsModalResultProps { addOrRemove: 'add' | 'remove'; @@ -40,7 +41,7 @@ export const EditAgentsGroupsModalResult = ({ columns={[ { field: 'id', - name: 'ID', + name: 'Id', align: 'left', sortable: true, }, @@ -71,6 +72,7 @@ export const EditAgentsGroupsModalResult = ({ name: 'Code', align: 'left', sortable: true, + width: '100px', }, { field: 'error.message', @@ -184,7 +186,6 @@ export const EditAgentsGroupsModalResult = ({ result, successAgents, errorAgents, - errorMessage, totalErrorAgents, } = groupResult; diff --git a/plugins/main/public/components/endpoints-summary/table/global-actions/global-actions.test.tsx b/plugins/main/public/components/endpoints-summary/table/global-actions/global-actions.test.tsx index daaf7745a8..422bde5ab0 100644 --- a/plugins/main/public/components/endpoints-summary/table/global-actions/global-actions.test.tsx +++ b/plugins/main/public/components/endpoints-summary/table/global-actions/global-actions.test.tsx @@ -18,12 +18,15 @@ describe('AgentsTableGlobalActions component', () => { filters={{}} allowEditGroups={true} reloadAgents={() => {}} + setIsUpgradeTasksModalVisible={() => {}} + setIsUpgradePanelClosed={() => {}} + allowUpgrade={true} />, ); expect(container).toMatchSnapshot(); - const option = getByText('Add/Remove groups'); + const option = getByText('More'); expect(option).toBeInTheDocument(); }); @@ -36,10 +39,13 @@ describe('AgentsTableGlobalActions component', () => { filters={{}} allowEditGroups={true} reloadAgents={() => {}} + setIsUpgradeTasksModalVisible={() => {}} + setIsUpgradePanelClosed={() => {}} + allowUpgrade={true} />, ); - const option = getByText('Add/Remove groups'); + const option = getByText('More'); expect(option).toBeInTheDocument(); act(() => { diff --git a/plugins/main/public/components/endpoints-summary/table/global-actions/global-actions.tsx b/plugins/main/public/components/endpoints-summary/table/global-actions/global-actions.tsx index aa644abd8c..4f9a453505 100644 --- a/plugins/main/public/components/endpoints-summary/table/global-actions/global-actions.tsx +++ b/plugins/main/public/components/endpoints-summary/table/global-actions/global-actions.tsx @@ -20,6 +20,7 @@ export interface AgentsTableGlobalActionsProps { allowUpgrade: boolean; reloadAgents: () => void; setIsUpgradeTasksModalVisible: (isModalVisible: boolean) => void; + setIsUpgradePanelClosed: (isUpgradePanelClosed: boolean) => void; } export const AgentsTableGlobalActions = ({ @@ -31,6 +32,7 @@ export const AgentsTableGlobalActions = ({ allowUpgrade, reloadAgents, setIsUpgradeTasksModalVisible, + setIsUpgradePanelClosed, }: AgentsTableGlobalActionsProps) => { const [isPopoverOpen, setPopover] = useState(false); const [isEditGroupsVisible, setIsEditGroupsVisible] = useState(false); @@ -183,6 +185,7 @@ export const AgentsTableGlobalActions = ({ onClose={() => { setIsUpgradeAgentsVisible(false); }} + setIsUpgradePanelClosed={setIsUpgradePanelClosed} /> ) : null} diff --git a/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/result.tsx b/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/result.tsx index a11a26033f..30b02b8b9d 100644 --- a/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/result.tsx +++ b/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/result.tsx @@ -11,15 +11,21 @@ import { EuiLoadingSpinner, EuiSpacer, } from '@elastic/eui'; -import { Agent } from '../../../types'; -import { RESULT_TYPE, Result } from './upgrade-modal'; +import { Agent, ResponseUpgradeAgents } from '../../../types'; +import { Result } from './upgrade-modal'; +import { ErrorAgent } from '../../../services/paginated-agents-request'; + +export enum RESULT_TYPE { + SUCCESS = 'success', + ERROR = 'error', +} interface UpgradeAgentsModalResultProps { finalAgents: Agent[]; getAgentsStatus: string; getAgentsError?: Error; saveChangesStatus: string; - results: Result[]; + result?: Result; } export const UpgradeAgentsModalResult = ({ @@ -27,8 +33,10 @@ export const UpgradeAgentsModalResult = ({ getAgentsStatus, getAgentsError, saveChangesStatus, - results, + result = {}, }: UpgradeAgentsModalResultProps) => { + const { successAgents, errorAgents, totalErrorAgents } = result; + const agentsTable = (agents: Agent[]) => ( ); - const errorsTable = (errors = []) => ( + const tasksTable = (tasks: ResponseUpgradeAgents[]) => ( + { + const agent = finalAgents.find( + finalAgent => finalAgent.id === task.agent, + ) as Agent; + return agent.name; + }, + }, + { + field: 'task_id', + name: 'task id', + align: 'left', + sortable: true, + }, + ]} + pagination={tasks.length > 10} + sorting={{ + sort: { + field: 'agent', + direction: 'asc', + }, + }} + /> + ); + + const errorsTable = (errors: ErrorAgent[] = []) => ( ); - const groupStatus = (options: { - isLoading?: boolean; - status: RESULT_TYPE; - text: string; - }) => { - const { isLoading, status, text } = options; + const resultStatus = (options: { status: RESULT_TYPE; text: string }) => { + const { status, text } = options; return ( - {isLoading ? ( - - ) : ( - - )} + @@ -159,98 +200,59 @@ export const UpgradeAgentsModalResult = ({ children: getAgentsStatus === 'complete' ? ( - {/* {groups.map(group => { - const groupResult = groupResults.find( - groupResult => groupResult.group === group, - ); - const isLoading = !groupResult; - - if (isLoading) - return ( - - {groupStatus({ - isLoading, - status: RESULT_TYPE.SUCCESS, - text: group, - })} + {saveChangesStatus === 'loading' ? ( + + + + - ); - - const { - result, - successAgents, - errorAgents, - errorMessage, - totalErrorAgents, - } = groupResult; - - if (result === RESULT_TYPE.SUCCESS) - return ( - + + Creating upgrade agent tasks + + + + ) : ( + <> + {successAgents?.length ? ( + - {agentsTable(finalAgents)} + {tasksTable(successAgents)} - ); - - return ( - - + ) : null} + {successAgents?.length && errorAgents?.length ? ( + + ) : null} + {totalErrorAgents ? ( + {errorsTable(errorAgents)} - {successAgents?.length ? ( - <> - - - {agentsTable( - successAgents.map( - agentId => - finalAgents.find( - finalAgent => finalAgent.id === agentId, - ) as Agent, - ), - )} - - - ) : null} - - - ); - })} */} + + ) : null} + + )} ) : null, }, diff --git a/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/upgrade-modal.tsx b/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/upgrade-modal.tsx index 3d2090954c..df3b2d392f 100644 --- a/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/upgrade-modal.tsx +++ b/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/upgrade-modal.tsx @@ -18,19 +18,12 @@ import { UI_LOGGER_LEVELS } from '../../../../../../common/constants'; import { UI_ERROR_SEVERITIES } from '../../../../../react-services/error-orchestrator/types'; import { getErrorOrchestrator } from '../../../../../react-services/common-services'; import { getAgentsService, upgradeAgentsService } from '../../../services'; -import { Agent } from '../../../types'; +import { Agent, ResponseUpgradeAgents } from '../../../types'; import { ErrorAgent } from '../../../services/paginated-agents-group'; import { UpgradeAgentsModalResult } from './result'; -export enum RESULT_TYPE { - SUCCESS = 'success', - ERROR = 'error', -} - export type Result = { - group: string; - result: RESULT_TYPE; - successAgents?: string[]; + successAgents?: ResponseUpgradeAgents[]; errorMessage?: string; totalErrorAgents?: number; errorAgents?: ErrorAgent[]; @@ -42,6 +35,7 @@ interface UpgradeAgentsModalProps { filters: any; onClose: () => void; reloadAgents: () => void; + setIsUpgradePanelClosed: (isUpgradePanelClosed: boolean) => void; } export const UpgradeAgentsModal = compose( @@ -54,13 +48,14 @@ export const UpgradeAgentsModal = compose( filters, onClose, reloadAgents, + setIsUpgradePanelClosed, }: UpgradeAgentsModalProps) => { const [finalAgents, setFinalAgents] = useState([]); const [getAgentsStatus, setGetAgentsStatus] = useState('disabled'); const [getAgentsError, setGetAgentsError] = useState(); const [saveChangesStatus, setSaveChangesStatus] = useState('disabled'); const [isResultVisible, setIsResultVisible] = useState(false); - const [results, setResults] = useState([]); + const [result, setResult] = useState(); const getAgents = async () => { if (!allAgentsSelected) { @@ -114,9 +109,37 @@ export const UpgradeAgentsModal = compose( const agentIds = getArrayByProperty(agents, 'id'); try { - await upgradeAgentsService({ agentIds }); + const response = await upgradeAgentsService({ agentIds }); + + const { data, message } = response.data; + const { + affected_items, + failed_items, + total_affected_items, + total_failed_items, + } = data; + setResult({ + successAgents: affected_items, + errorAgents: failed_items, + errorMessage: message, + totalErrorAgents: total_failed_items, + }); + + if (total_affected_items) { + setIsUpgradePanelClosed(false); + } + setSaveChangesStatus('complete'); } catch (error) { + setResult({ + errorMessage: error.message, + errorAgents: [ + { + error: { message: error.message }, + id: agentIds, + }, + ], + }); setSaveChangesStatus('danger'); const options = { context: `UpgradeAgentsModal.handleOnSave`, @@ -167,7 +190,7 @@ export const UpgradeAgentsModal = compose( getAgentsStatus={getAgentsStatus} getAgentsError={getAgentsError} saveChangesStatus={saveChangesStatus} - results={results} + result={result} /> )} diff --git a/plugins/main/public/components/endpoints-summary/table/upgradeTaskDetailsModal.tsx b/plugins/main/public/components/endpoints-summary/table/upgradeTaskDetailsModal.tsx index e768d83f04..de3896b855 100644 --- a/plugins/main/public/components/endpoints-summary/table/upgradeTaskDetailsModal.tsx +++ b/plugins/main/public/components/endpoints-summary/table/upgradeTaskDetailsModal.tsx @@ -48,6 +48,7 @@ export const AgentUpgradesTaskDetailsModal = ({ sortable: true, searchable: true, show: true, + width: '100px', }, { field: 'agent_id', @@ -55,6 +56,7 @@ export const AgentUpgradesTaskDetailsModal = ({ sortable: true, searchable: true, show: true, + width: '100px', }, { field: 'create_time', @@ -69,6 +71,7 @@ export const AgentUpgradesTaskDetailsModal = ({ /> ), + width: '230px', sortable: true, searchable: false, show: true, @@ -87,6 +90,7 @@ export const AgentUpgradesTaskDetailsModal = ({ /> ), + width: '230px', sortable: true, searchable: false, show: true, @@ -95,7 +99,7 @@ export const AgentUpgradesTaskDetailsModal = ({ { field: 'status', name: 'Status', - width: '100px', + width: '120px', sortable: true, searchable: true, show: true, @@ -201,9 +205,6 @@ export const AgentUpgradesTaskDetailsModal = ({ }, }, }} - tableProps={{ - tableLayout: 'auto', - }} /> diff --git a/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/__snapshots__/upgrades-in-progress.test.tsx.snap b/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/__snapshots__/upgrades-in-progress.test.tsx.snap index a91fdfedfc..00cfc76f6f 100644 --- a/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/__snapshots__/upgrades-in-progress.test.tsx.snap +++ b/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/__snapshots__/upgrades-in-progress.test.tsx.snap @@ -6,47 +6,75 @@ exports[`AgentUpgradesInProgress component should return the component 1`] = ` class="euiPanel euiPanel--paddingMedium euiPanel--borderRadiusMedium euiPanel--subdued euiPanel--noShadow euiPanel--noBorder" >
- Upgrade tasks +
+ Upgrade tasks +
+
+
+
diff --git a/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.tsx b/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.tsx index d57f2f9f1a..58e226f748 100644 --- a/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.tsx +++ b/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.tsx @@ -18,14 +18,17 @@ import { getErrorOrchestrator } from '../../../../react-services/common-services interface AgentUpgradesInProgress { reload: any; setIsModalVisible: (isModalVisible: boolean) => void; + isPanelClosed: boolean; + setIsPanelClosed: (isPanelClosed: boolean) => void; } export const AgentUpgradesInProgress = ({ reload, setIsModalVisible, + isPanelClosed, + setIsPanelClosed, }: AgentUpgradesInProgress) => { const [isUpgrading, setIsUpgrading] = useState(false); - const [isPanelClosed, setIsPanelClosed] = useState(false); const { totalInProgressTasks, From ada67c2ed2b8a0cc3f4417a9d69751fe8e2ef31c Mon Sep 17 00:00:00 2001 From: Luciano Gorza Date: Wed, 13 Mar 2024 09:39:04 -0300 Subject: [PATCH 03/31] Update CHANGELOG --- CHANGELOG.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73bf6416e0..b1f91bd870 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,9 +10,7 @@ All notable changes to the Wazuh app project will be documented in this file. - Added AngularJS dependencies [#6145](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6145) - Added a migration task to setup the configuration using a configuration file [#6337](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6337) - Added the ability to manage the API hosts from the Server APIs [#6337](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6337) [#6519](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6519) -- Added edit groups action to Endpoints Summary [#6250](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6250) -- Added upgrade agent action to Endpoints Summary [#6476](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6476) -- Added global actions add agents to groups and remove agents from groups to Endpoints Summary [#6274](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6274) +- Added edit agent groups and upgrade agents actions to Endpoints Summary [#6250](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6250) [#6476](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6476) [#6274](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6274) [#6501](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6501) - Added propagation of updates from the table to dashboard visualizations in Endpoints summary [#6460](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6460) ### Changed From adbadbe202b7f57e6362ef899418839e5c80fa2e Mon Sep 17 00:00:00 2001 From: Luciano Gorza Date: Wed, 13 Mar 2024 12:23:34 -0300 Subject: [PATCH 04/31] Minor fixes --- .../table/upgradeTaskDetailsModal.tsx | 2 ++ .../upgrades-in-progress.test.tsx.snap | 2 +- .../upgrades-in-progress.test.tsx | 20 +++++++++++++------ .../upgrades-in-progress.tsx | 3 +-- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/plugins/main/public/components/endpoints-summary/table/upgradeTaskDetailsModal.tsx b/plugins/main/public/components/endpoints-summary/table/upgradeTaskDetailsModal.tsx index de3896b855..3dac22fa58 100644 --- a/plugins/main/public/components/endpoints-summary/table/upgradeTaskDetailsModal.tsx +++ b/plugins/main/public/components/endpoints-summary/table/upgradeTaskDetailsModal.tsx @@ -122,6 +122,7 @@ export const AgentUpgradesTaskDetailsModal = ({ name: 'Error', show: true, searchable: true, + width: '250px', }, ]} tableInitialSortingField='last_update_time' @@ -205,6 +206,7 @@ export const AgentUpgradesTaskDetailsModal = ({ }, }, }} + tableProps={{ tableLayout: 'auto' }} /> diff --git a/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/__snapshots__/upgrades-in-progress.test.tsx.snap b/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/__snapshots__/upgrades-in-progress.test.tsx.snap index 00cfc76f6f..7dd158339f 100644 --- a/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/__snapshots__/upgrades-in-progress.test.tsx.snap +++ b/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/__snapshots__/upgrades-in-progress.test.tsx.snap @@ -6,7 +6,7 @@ exports[`AgentUpgradesInProgress component should return the component 1`] = ` class="euiPanel euiPanel--paddingMedium euiPanel--borderRadiusMedium euiPanel--subdued euiPanel--noShadow euiPanel--noBorder" >
{ }); const { container, getByText } = render( - , + {}} + isPanelClosed={false} + setIsPanelClosed={() => {}} + />, ); expect(container).toMatchSnapshot(); @@ -41,17 +46,20 @@ describe('AgentUpgradesInProgress component', () => { }); test('should show upgrade tasks modal', async () => { - const { getByRole, getByText } = render( - , + const { getByRole } = render( + {}} + isPanelClosed={false} + setIsPanelClosed={() => {}} + />, ); - const openModalButton = getByRole('button'); + const openModalButton = getByRole('button', { name: 'Task details' }); expect(openModalButton).toBeInTheDocument(); act(() => { fireEvent.click(openModalButton); }); - - await waitFor(() => expect(getByRole('table')).toBeInTheDocument()); }); }); diff --git a/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.tsx b/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.tsx index 58e226f748..17b9a939af 100644 --- a/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.tsx +++ b/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.tsx @@ -95,8 +95,7 @@ export const AgentUpgradesInProgress = ({ From 1b13ab9d5ee17e0dcbf1f7785e8a45dc265e4105 Mon Sep 17 00:00:00 2001 From: Luciano Gorza Date: Wed, 13 Mar 2024 13:31:09 -0300 Subject: [PATCH 05/31] Add unit tests --- .../table/actions/edit-groups-modal.tsx | 1 - .../actions/upgrade-agent-modal.test.tsx | 2 + .../table/actions/upgrade-agent-modal.tsx | 119 ++++++++++-------- .../endpoints-summary/table/agents-table.tsx | 1 + .../edit-groups/edit-groups-modal.test.tsx | 5 - .../__snapshots__/upgrade-modal.test.tsx.snap | 8 ++ .../upgrade/upgrade-modal.test.tsx | 77 ++++++++++++ 7 files changed, 152 insertions(+), 61 deletions(-) create mode 100644 plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/__snapshots__/upgrade-modal.test.tsx.snap create mode 100644 plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/upgrade-modal.test.tsx diff --git a/plugins/main/public/components/endpoints-summary/table/actions/edit-groups-modal.tsx b/plugins/main/public/components/endpoints-summary/table/actions/edit-groups-modal.tsx index e2077a4d97..49a5a7bbd6 100644 --- a/plugins/main/public/components/endpoints-summary/table/actions/edit-groups-modal.tsx +++ b/plugins/main/public/components/endpoints-summary/table/actions/edit-groups-modal.tsx @@ -130,7 +130,6 @@ export const EditAgentGroupsModal = compose( diff --git a/plugins/main/public/components/endpoints-summary/table/actions/upgrade-agent-modal.test.tsx b/plugins/main/public/components/endpoints-summary/table/actions/upgrade-agent-modal.test.tsx index 8431c997c5..8fc361a0a1 100644 --- a/plugins/main/public/components/endpoints-summary/table/actions/upgrade-agent-modal.test.tsx +++ b/plugins/main/public/components/endpoints-summary/table/actions/upgrade-agent-modal.test.tsx @@ -24,6 +24,7 @@ describe('UpgradeAgentModal component', () => { }} onClose={() => {}} reloadAgents={() => {}} + setIsUpgradePanelClosed={() => {}} />, ); @@ -49,6 +50,7 @@ describe('UpgradeAgentModal component', () => { }} onClose={() => {}} reloadAgents={() => {}} + setIsUpgradePanelClosed={() => {}} />, ); diff --git a/plugins/main/public/components/endpoints-summary/table/actions/upgrade-agent-modal.tsx b/plugins/main/public/components/endpoints-summary/table/actions/upgrade-agent-modal.tsx index adb26b18c9..ca22be1686 100644 --- a/plugins/main/public/components/endpoints-summary/table/actions/upgrade-agent-modal.tsx +++ b/plugins/main/public/components/endpoints-summary/table/actions/upgrade-agent-modal.tsx @@ -13,66 +13,75 @@ interface UpgradeAgentModalProps { agent: Agent; onClose: () => void; reloadAgents: () => void; + setIsUpgradePanelClosed: (isUpgradePanelClosed: boolean) => void; } export const UpgradeAgentModal = compose( withErrorBoundary, withReduxProvider, -)(({ agent, onClose, reloadAgents }: UpgradeAgentModalProps) => { - const [isLoading, setIsLoading] = useState(false); - const showToast = ( - color: string, - title: string = '', - text: string = '', - time: number = 3000, - ) => { - getToasts().add({ - color: color, - title: title, - text: text, - toastLifeTimeMs: time, - }); - }; +)( + ({ + agent, + onClose, + reloadAgents, + setIsUpgradePanelClosed, + }: UpgradeAgentModalProps) => { + const [isLoading, setIsLoading] = useState(false); + const showToast = ( + color: string, + title: string = '', + text: string = '', + time: number = 3000, + ) => { + getToasts().add({ + color: color, + title: title, + text: text, + toastLifeTimeMs: time, + }); + }; - const handleOnSave = async () => { - setIsLoading(true); + const handleOnSave = async () => { + setIsLoading(true); - try { - await upgradeAgentsService({ agentIds: [agent.id] }); - showToast('success', 'Upgrade agent', 'Upgrade task in progress'); - reloadAgents(); - } catch (error) { - const options = { - context: `UpgradeAgentModal.handleOnSave`, - level: UI_LOGGER_LEVELS.ERROR, - severity: UI_ERROR_SEVERITIES.BUSINESS, - store: true, - error: { - error, - message: error.message || error, - title: `Could not upgrade agent`, - }, - }; - getErrorOrchestrator().handleError(options); - } finally { - onClose(); - } - }; + try { + await upgradeAgentsService({ agentIds: [agent.id] }); + showToast('success', 'Upgrade agent', 'Upgrade task in progress'); + reloadAgents(); + setIsUpgradePanelClosed(false); + } catch (error) { + const options = { + context: `UpgradeAgentModal.handleOnSave`, + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.BUSINESS, + store: true, + error: { + error, + message: error.message || error, + title: `Could not upgrade agent`, + }, + }; + getErrorOrchestrator().handleError(options); + } finally { + onClose(); + } + }; - return ( - { - ev.stopPropagation(); - }} - isLoading={isLoading} - > -

{`Upgrade agent ${agent?.name}?`}

-
- ); -}); + return ( + { + ev.stopPropagation(); + }} + isLoading={isLoading} + > +

{`Upgrade agent ${agent?.name}?`}

+
+ ); + }, +); diff --git a/plugins/main/public/components/endpoints-summary/table/agents-table.tsx b/plugins/main/public/components/endpoints-summary/table/agents-table.tsx index e6b1921d79..112dcb49b5 100644 --- a/plugins/main/public/components/endpoints-summary/table/agents-table.tsx +++ b/plugins/main/public/components/endpoints-summary/table/agents-table.tsx @@ -477,6 +477,7 @@ export const AgentsTable = compose( setIsEditGroupsVisible(false); setAgent(undefined); }} + setIsUpgradePanelClosed={setIsUpgradePanelClosed} /> ) : null} {isUpgradeTasksModalVisible ? ( diff --git a/plugins/main/public/components/endpoints-summary/table/global-actions/edit-groups/edit-groups-modal.test.tsx b/plugins/main/public/components/endpoints-summary/table/global-actions/edit-groups/edit-groups-modal.test.tsx index 188854d1ec..fced06a7dd 100644 --- a/plugins/main/public/components/endpoints-summary/table/global-actions/edit-groups/edit-groups-modal.test.tsx +++ b/plugins/main/public/components/endpoints-summary/table/global-actions/edit-groups/edit-groups-modal.test.tsx @@ -21,11 +21,6 @@ jest.mock('../../../../../react-services/common-services', () => ({ }), })); -// jest.mock('../../../../common/hocs', () => ({ -// withErrorBoundary: () => {}, -// withReduxProvider: () => {}, -// })); - describe('EditAgentsGroupsModal component', () => { test('should return the component with save disabled', async () => { (useGetGroups as jest.Mock).mockReturnValue({ diff --git a/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/__snapshots__/upgrade-modal.test.tsx.snap b/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/__snapshots__/upgrade-modal.test.tsx.snap new file mode 100644 index 0000000000..4cf80094a5 --- /dev/null +++ b/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/__snapshots__/upgrade-modal.test.tsx.snap @@ -0,0 +1,8 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`UpgradeAgentsModal component should return the component 1`] = ` +
@@ -124,7 +124,7 @@ exports[`AgentUpgradesInProgress component should return the component 1`] = ` 2 - Failed upgrade tasks + Failed diff --git a/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.test.tsx b/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.test.tsx index c568cce072..5b07483a04 100644 --- a/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.test.tsx +++ b/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.test.tsx @@ -36,12 +36,12 @@ describe('AgentUpgradesInProgress component', () => { const inProgressValue = getByText('5'); expect(inProgressValue).toBeInTheDocument(); - const inProgressText = getByText('Upgrade tasks in progress'); + const inProgressText = getByText('In progress'); expect(inProgressText).toBeInTheDocument(); const failedValue = getByText('2'); expect(failedValue).toBeInTheDocument(); - const failedText = getByText('Failed upgrade tasks'); + const failedText = getByText('Failed'); expect(failedText).toBeInTheDocument(); }); diff --git a/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.tsx b/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.tsx index 17b9a939af..62b2a62f23 100644 --- a/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.tsx +++ b/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.tsx @@ -135,9 +135,7 @@ export const AgentUpgradesInProgress = ({ {totalInProgressTasks} - {totalInProgressTasks === 1 - ? ' Upgrade task in progress' - : ' Upgrade tasks in progress'} + {' In progress'}
@@ -155,9 +153,7 @@ export const AgentUpgradesInProgress = ({ {totalSuccessTasks} - {totalSuccessTasks === 1 - ? ' Success upgrade task ' - : ' Success upgrade tasks '} + {' Success '} @@ -177,10 +173,7 @@ export const AgentUpgradesInProgress = ({ {totalErrorUpgradeTasks} - {totalErrorUpgradeTasks === 1 - ? ' Failed upgrade task ' - : ' Failed upgrade tasks '} - + {' Failed '} From 52116032a135b58e2592ca5302a1315af063ff47 Mon Sep 17 00:00:00 2001 From: Luciano Gorza Date: Wed, 13 Mar 2024 14:54:25 -0300 Subject: [PATCH 07/31] Remove wazuh-endpoints plugin --- plugins/main/public/types.ts | 2 - plugins/wazuh-endpoints/.i18nrc.json | 7 - plugins/wazuh-endpoints/common/constants.ts | 4 - plugins/wazuh-endpoints/common/types.ts | 0 .../opensearch_dashboards.json | 9 -- plugins/wazuh-endpoints/package.json | 20 --- plugins/wazuh-endpoints/public/index.ts | 8 - plugins/wazuh-endpoints/public/plugin.ts | 23 --- plugins/wazuh-endpoints/public/types.ts | 5 - plugins/wazuh-endpoints/scripts/jest.js | 19 --- plugins/wazuh-endpoints/scripts/manifest.js | 17 -- plugins/wazuh-endpoints/scripts/runner.js | 148 ------------------ plugins/wazuh-endpoints/server/index.ts | 11 -- plugins/wazuh-endpoints/server/plugin.ts | 37 ----- plugins/wazuh-endpoints/server/types.ts | 10 -- plugins/wazuh-endpoints/test/jest/config.js | 41 ----- .../wazuh-endpoints/translations/en-US.json | 79 ---------- plugins/wazuh-endpoints/tsconfig.json | 17 -- 18 files changed, 457 deletions(-) delete mode 100644 plugins/wazuh-endpoints/.i18nrc.json delete mode 100644 plugins/wazuh-endpoints/common/constants.ts delete mode 100644 plugins/wazuh-endpoints/common/types.ts delete mode 100644 plugins/wazuh-endpoints/opensearch_dashboards.json delete mode 100644 plugins/wazuh-endpoints/package.json delete mode 100644 plugins/wazuh-endpoints/public/index.ts delete mode 100644 plugins/wazuh-endpoints/public/plugin.ts delete mode 100644 plugins/wazuh-endpoints/public/types.ts delete mode 100644 plugins/wazuh-endpoints/scripts/jest.js delete mode 100644 plugins/wazuh-endpoints/scripts/manifest.js delete mode 100755 plugins/wazuh-endpoints/scripts/runner.js delete mode 100644 plugins/wazuh-endpoints/server/index.ts delete mode 100644 plugins/wazuh-endpoints/server/plugin.ts delete mode 100644 plugins/wazuh-endpoints/server/types.ts delete mode 100644 plugins/wazuh-endpoints/test/jest/config.js delete mode 100644 plugins/wazuh-endpoints/translations/en-US.json delete mode 100644 plugins/wazuh-endpoints/tsconfig.json diff --git a/plugins/main/public/types.ts b/plugins/main/public/types.ts index 647791058f..9d3c0e7915 100644 --- a/plugins/main/public/types.ts +++ b/plugins/main/public/types.ts @@ -19,7 +19,6 @@ import { } from '../../../src/plugins/telemetry/public'; import { WazuhCheckUpdatesPluginStart } from '../../wazuh-check-updates/public'; import { WazuhCorePluginStart } from '../../wazuh-core/public'; -import { WazuhEndpointsPluginStart } from '../../wazuh-endpoints/public'; import { DashboardStart } from '../../../src/plugins/dashboard/public'; export interface AppPluginStartDependencies { @@ -33,7 +32,6 @@ export interface AppPluginStartDependencies { telemetry: TelemetryPluginStart; wazuhCheckUpdates: WazuhCheckUpdatesPluginStart; wazuhCore: WazuhCorePluginStart; - wazuhEndpoints: WazuhEndpointsPluginStart; dashboard: DashboardStart; } export interface AppDependencies { diff --git a/plugins/wazuh-endpoints/.i18nrc.json b/plugins/wazuh-endpoints/.i18nrc.json deleted file mode 100644 index 57c921787c..0000000000 --- a/plugins/wazuh-endpoints/.i18nrc.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "prefix": "wazuhEndpoints", - "paths": { - "wazuhEndpoints": "." - }, - "translations": ["translations/en-US.json"] -} diff --git a/plugins/wazuh-endpoints/common/constants.ts b/plugins/wazuh-endpoints/common/constants.ts deleted file mode 100644 index ab242f7d67..0000000000 --- a/plugins/wazuh-endpoints/common/constants.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const PLUGIN_ID = 'wazuhEndpoints'; -export const PLUGIN_NAME = 'wazuh_endpoints'; - -export enum routes {} diff --git a/plugins/wazuh-endpoints/common/types.ts b/plugins/wazuh-endpoints/common/types.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/plugins/wazuh-endpoints/opensearch_dashboards.json b/plugins/wazuh-endpoints/opensearch_dashboards.json deleted file mode 100644 index 37806a8aa4..0000000000 --- a/plugins/wazuh-endpoints/opensearch_dashboards.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "id": "wazuhEndpoints", - "version": "4.9.0-00", - "opensearchDashboardsVersion": "opensearchDashboards", - "server": true, - "ui": true, - "requiredPlugins": ["navigation"], - "optionalPlugins": [] -} diff --git a/plugins/wazuh-endpoints/package.json b/plugins/wazuh-endpoints/package.json deleted file mode 100644 index 6fb24b72b5..0000000000 --- a/plugins/wazuh-endpoints/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "wazuh-endpoints", - "version": "4.9.0", - "revision": "00", - "pluginPlatform": { - "version": "2.12.0" - }, - "description": "Wazuh Endpoints", - "private": true, - "scripts": { - "build": "yarn plugin-helpers build --opensearch-dashboards-version=$OPENSEARCH_DASHBOARDS_VERSION", - "plugin-helpers": "node ../../scripts/plugin_helpers", - "osd": "node ../../scripts/osd", - "test:ui:runner": "node ../../scripts/functional_test_runner.js", - "test:server": "plugin-helpers test:server", - "test:browser": "plugin-helpers test:browser", - "test:jest": "node scripts/jest --runInBand", - "test:jest:runner": "node scripts/runner test" - } -} diff --git a/plugins/wazuh-endpoints/public/index.ts b/plugins/wazuh-endpoints/public/index.ts deleted file mode 100644 index fee1d9b0fa..0000000000 --- a/plugins/wazuh-endpoints/public/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { WazuhEndpointsPlugin } from './plugin'; - -// This exports static code and TypeScript types, -// as well as, OpenSearch Dashboards Platform `plugin()` initializer. -export function plugin() { - return new WazuhEndpointsPlugin(); -} -export { WazuhEndpointsPluginSetup, WazuhEndpointsPluginStart } from './types'; diff --git a/plugins/wazuh-endpoints/public/plugin.ts b/plugins/wazuh-endpoints/public/plugin.ts deleted file mode 100644 index f2e9e743b3..0000000000 --- a/plugins/wazuh-endpoints/public/plugin.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { CoreSetup, CoreStart, Plugin } from 'opensearch-dashboards/public'; -import { - AppPluginStartDependencies, - WazuhEndpointsPluginSetup, - WazuhEndpointsPluginStart, -} from './types'; - -export class WazuhEndpointsPlugin - implements Plugin -{ - public setup(core: CoreSetup): WazuhEndpointsPluginSetup { - return {}; - } - - public start( - core: CoreStart, - plugins: AppPluginStartDependencies, - ): WazuhEndpointsPluginStart { - return {}; - } - - public stop() {} -} diff --git a/plugins/wazuh-endpoints/public/types.ts b/plugins/wazuh-endpoints/public/types.ts deleted file mode 100644 index bb42fe7913..0000000000 --- a/plugins/wazuh-endpoints/public/types.ts +++ /dev/null @@ -1,5 +0,0 @@ -export interface WazuhEndpointsPluginSetup {} -// eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface WazuhEndpointsPluginStart {} - -export interface AppPluginStartDependencies {} diff --git a/plugins/wazuh-endpoints/scripts/jest.js b/plugins/wazuh-endpoints/scripts/jest.js deleted file mode 100644 index cb58c54ec0..0000000000 --- a/plugins/wazuh-endpoints/scripts/jest.js +++ /dev/null @@ -1,19 +0,0 @@ -// # Run Jest tests -// -// All args will be forwarded directly to Jest, e.g. to watch tests run: -// -// node scripts/jest --watch -// -// or to build code coverage: -// -// node scripts/jest --coverage -// -// See all cli options in https://facebook.github.io/jest/docs/cli.html - -const path = require('path'); -process.argv.push('--config', path.resolve(__dirname, '../test/jest/config.js')); - -require('../../../src/setup_node_env'); -const jest = require('../../../node_modules/jest'); - -jest.run(process.argv.slice(2)); diff --git a/plugins/wazuh-endpoints/scripts/manifest.js b/plugins/wazuh-endpoints/scripts/manifest.js deleted file mode 100644 index 711059d3ac..0000000000 --- a/plugins/wazuh-endpoints/scripts/manifest.js +++ /dev/null @@ -1,17 +0,0 @@ - -/* eslint-disable @typescript-eslint/no-var-requires */ - -const fs = require('fs'); - -/** - * Reads the package.json file. - * @returns {Object} JSON object. - */ -function loadPackageJson() { - const packageJson = fs.readFileSync('./package.json'); - return JSON.parse(packageJson); -} - -module.exports = { - loadPackageJson -}; \ No newline at end of file diff --git a/plugins/wazuh-endpoints/scripts/runner.js b/plugins/wazuh-endpoints/scripts/runner.js deleted file mode 100755 index 5ba9b132ab..0000000000 --- a/plugins/wazuh-endpoints/scripts/runner.js +++ /dev/null @@ -1,148 +0,0 @@ -/* eslint-disable array-element-newline */ -/* eslint-disable @typescript-eslint/no-var-requires */ - -/** -Runs yarn commands using a Docker container. - -Intended to test and build locally. - -Uses development images. Must be executed from the root folder of the project. - -See /docker/runner/docker-compose.yml for available environment variables. - -# Usage: -# ------------- -# - node scripts/runner [] -# - yarn test:jest:runner [] -# - yarn build:runner -*/ - -const childProcess = require('child_process'); -const { loadPackageJson } = require('./manifest'); - -const COMPOSE_DIR = '../../docker/runner'; - -function getProjectInfo() { - const manifest = loadPackageJson(); - - return { - app: 'osd', - version: manifest['pluginPlatform']['version'], - repo: process.cwd(), - }; -} - -function getBuildArgs({ app, version }) { - return `--opensearch-dashboards-version=${version}`; -} - -/** - * Transforms the Jest CLI options from process.argv back to a string. - * If no options are provided, default ones are generated. - * @returns {String} Space separated string with all Jest CLI options provided. - */ -function getJestArgs() { - // Take args only after `test` word - const index = process.argv.indexOf('test'); - const args = process.argv.slice(index + 1); - // Remove duplicates using set - return Array.from(new Set([...args, '--runInBand'])).join(' '); -} - -/** - * Generates the execution parameters if they are not set. - * @returns {Object} Default environment variables. - */ -const buildEnvVars = ({ app, version, repo, cmd, args }) => { - return { - APP: app, - VERSION: version, - REPO: repo, - CMD: cmd, - ARGS: args, - }; -}; - -/** - * Captures the SIGINT signal (Ctrl + C) to stop the container and exit. - */ -function setupAbortController() { - process.on('SIGINT', () => { - childProcess.spawnSync('docker', [ - 'compose', - '--project-directory', - COMPOSE_DIR, - 'stop', - ]); - process.exit(); - }); -} - -/** - * Start the container. - */ -function startRunner() { - const runner = childProcess.spawn('docker', [ - 'compose', - '--project-directory', - COMPOSE_DIR, - 'up', - ]); - - runner.stdout.on('data', data => { - console.log(`${data}`); - }); - - runner.stderr.on('data', data => { - console.error(`${data}`); - }); -} - -/** - * Main function - */ -function main() { - if (process.argv.length < 2) { - process.stderr.write('Required parameters not provided'); - process.exit(-1); - } - - const projectInfo = getProjectInfo(); - let envVars = {}; - - switch (process.argv[2]) { - case 'build': - envVars = buildEnvVars({ - ...projectInfo, - cmd: 'plugin-helpers build', - args: getBuildArgs({ ...projectInfo }), - }); - break; - - case 'test': - envVars = buildEnvVars({ - ...projectInfo, - cmd: 'test:jest', - args: getJestArgs(), - }); - break; - - default: - // usage(); - console.error('Unsupported or invalid yarn command.'); - process.exit(-1); - } - - // Check the required environment variables are set - for (const [key, value] of Object.entries(envVars)) { - if (!process.env[key]) { - process.env[key] = value; - } - console.log(`${key}: ${process.env[key]}`); - } - - setupAbortController(); - startRunner(); -} - -main(); diff --git a/plugins/wazuh-endpoints/server/index.ts b/plugins/wazuh-endpoints/server/index.ts deleted file mode 100644 index ac32d575e6..0000000000 --- a/plugins/wazuh-endpoints/server/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { PluginInitializerContext } from '../../../src/core/server'; -import { WazuhEndpointsPlugin } from './plugin'; - -// This exports static code and TypeScript types, -// as well as, OpenSearch Dashboards Platform `plugin()` initializer. - -export function plugin(initializerContext: PluginInitializerContext) { - return new WazuhEndpointsPlugin(initializerContext); -} - -export { WazuhEndpointsPluginSetup, WazuhEndpointsPluginStart } from './types'; diff --git a/plugins/wazuh-endpoints/server/plugin.ts b/plugins/wazuh-endpoints/server/plugin.ts deleted file mode 100644 index 5d238e9787..0000000000 --- a/plugins/wazuh-endpoints/server/plugin.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { - PluginInitializerContext, - CoreSetup, - CoreStart, - Plugin, - Logger, -} from 'opensearch-dashboards/server'; - -import { - PluginSetup, - WazuhEndpointsPluginSetup, - WazuhEndpointsPluginStart, - AppPluginStartDependencies, -} from './types'; - -export class WazuhEndpointsPlugin - implements Plugin { - private readonly logger: Logger; - - constructor(initializerContext: PluginInitializerContext) { - this.logger = initializerContext.logger.get(); - } - - public async setup(core: CoreSetup, plugins: PluginSetup) { - this.logger.debug('wazuh_endpoints: Setup'); - - return {}; - } - - public start(core: CoreStart, plugins: AppPluginStartDependencies): WazuhEndpointsPluginStart { - this.logger.debug('wazuh_endpoints: Started'); - - return {}; - } - - public stop() {} -} diff --git a/plugins/wazuh-endpoints/server/types.ts b/plugins/wazuh-endpoints/server/types.ts deleted file mode 100644 index 773101157d..0000000000 --- a/plugins/wazuh-endpoints/server/types.ts +++ /dev/null @@ -1,10 +0,0 @@ -// eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface AppPluginStartDependencies {} -// eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface WazuhEndpointsPluginSetup {} -// eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface WazuhEndpointsPluginStart {} - -export type PluginSetup = {}; - -export interface AppPluginStartDependencies {} diff --git a/plugins/wazuh-endpoints/test/jest/config.js b/plugins/wazuh-endpoints/test/jest/config.js deleted file mode 100644 index c49cd92aa0..0000000000 --- a/plugins/wazuh-endpoints/test/jest/config.js +++ /dev/null @@ -1,41 +0,0 @@ -import path from 'path'; - -const kbnDir = path.resolve(__dirname, '../../../../'); - -export default { - rootDir: path.resolve(__dirname, '../..'), - roots: ['/public', '/server', '/common'], - modulePaths: [`${kbnDir}/node_modules`], - collectCoverageFrom: ['**/*.{js,jsx,ts,tsx}', './!**/node_modules/**'], - moduleNameMapper: { - '^ui/(.*)': `${kbnDir}/src/ui/public/$1`, - // eslint-disable-next-line max-len - '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': `${kbnDir}/src/dev/jest/mocks/file_mock.js`, - '\\.(css|less|scss)$': `${kbnDir}/src/dev/jest/mocks/style_mock.js`, - axios: 'axios/dist/node/axios.cjs', - }, - setupFiles: [ - `${kbnDir}/src/dev/jest/setup/babel_polyfill.js`, - `${kbnDir}/src/dev/jest/setup/enzyme.js`, - ], - collectCoverage: true, - coverageDirectory: './target/test-coverage', - coverageReporters: ['html', 'text-summary', 'json-summary'], - globals: { - 'ts-jest': { - skipBabel: true, - }, - }, - moduleFileExtensions: ['js', 'json', 'ts', 'tsx', 'html'], - modulePathIgnorePatterns: ['__fixtures__/', 'target/'], - testMatch: ['**/*.test.{js,ts,tsx}'], - transform: { - '^.+\\.js$': `${kbnDir}/src/dev/jest/babel_transform.js`, - '^.+\\.tsx?$': `${kbnDir}/src/dev/jest/babel_transform.js`, - '^.+\\.html?$': `${kbnDir}/src/dev/jest/babel_transform.js`, - }, - transformIgnorePatterns: ['[/\\\\]node_modules[/\\\\].+\\.js$'], - snapshotSerializers: [`${kbnDir}/node_modules/enzyme-to-json/serializer`], - testEnvironment: 'jest-environment-jsdom', - reporters: ['default', `${kbnDir}/src/dev/jest/junit_reporter.js`], -}; diff --git a/plugins/wazuh-endpoints/translations/en-US.json b/plugins/wazuh-endpoints/translations/en-US.json deleted file mode 100644 index 9022cc65e3..0000000000 --- a/plugins/wazuh-endpoints/translations/en-US.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "formats": { - "number": { - "currency": { - "style": "currency" - }, - "percent": { - "style": "percent" - } - }, - "date": { - "short": { - "month": "numeric", - "day": "numeric", - "year": "2-digit" - }, - "medium": { - "month": "short", - "day": "numeric", - "year": "numeric" - }, - "long": { - "month": "long", - "day": "numeric", - "year": "numeric" - }, - "full": { - "weekday": "long", - "month": "long", - "day": "numeric", - "year": "numeric" - } - }, - "time": { - "short": { - "hour": "numeric", - "minute": "numeric" - }, - "medium": { - "hour": "numeric", - "minute": "numeric", - "second": "numeric" - }, - "long": { - "hour": "numeric", - "minute": "numeric", - "second": "numeric", - "timeZoneName": "short" - }, - "full": { - "hour": "numeric", - "minute": "numeric", - "second": "numeric", - "timeZoneName": "short" - } - }, - "relative": { - "years": { - "units": "year" - }, - "months": { - "units": "month" - }, - "days": { - "units": "day" - }, - "hours": { - "units": "hour" - }, - "minutes": { - "units": "minute" - }, - "seconds": { - "units": "second" - } - } - }, - "messages": {} -} diff --git a/plugins/wazuh-endpoints/tsconfig.json b/plugins/wazuh-endpoints/tsconfig.json deleted file mode 100644 index d3b63f9aee..0000000000 --- a/plugins/wazuh-endpoints/tsconfig.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "outDir": "./target", - "skipLibCheck": true - }, - "include": [ - "index.ts", - "common/**/*.ts", - "public/**/*.ts", - "public/**/*.tsx", - "server/**/*.ts", - "../../typings/**/*", - "public/hooks" - ], - "exclude": [] -} \ No newline at end of file From 8fcaa4f0b80b9a6aafbd32b0cf598bd6f89991a4 Mon Sep 17 00:00:00 2001 From: Luciano Gorza Date: Wed, 13 Mar 2024 17:31:32 -0300 Subject: [PATCH 08/31] Fix file name --- ...upgradeTaskDetailsModal.tsx => upgrade-task-details-modal.tsx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename plugins/main/public/components/endpoints-summary/table/{upgradeTaskDetailsModal.tsx => upgrade-task-details-modal.tsx} (100%) diff --git a/plugins/main/public/components/endpoints-summary/table/upgradeTaskDetailsModal.tsx b/plugins/main/public/components/endpoints-summary/table/upgrade-task-details-modal.tsx similarity index 100% rename from plugins/main/public/components/endpoints-summary/table/upgradeTaskDetailsModal.tsx rename to plugins/main/public/components/endpoints-summary/table/upgrade-task-details-modal.tsx From 562c16be16b781f97ad9e953fd5928dc646b0661 Mon Sep 17 00:00:00 2001 From: Luciano Gorza Date: Wed, 13 Mar 2024 17:50:27 -0300 Subject: [PATCH 09/31] Fix import --- .../public/components/endpoints-summary/table/agents-table.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/main/public/components/endpoints-summary/table/agents-table.tsx b/plugins/main/public/components/endpoints-summary/table/agents-table.tsx index 112dcb49b5..39df1065df 100644 --- a/plugins/main/public/components/endpoints-summary/table/agents-table.tsx +++ b/plugins/main/public/components/endpoints-summary/table/agents-table.tsx @@ -45,7 +45,7 @@ import { getOutdatedAgents } from '../services'; import { UI_ERROR_SEVERITIES } from '../../../react-services/error-orchestrator/types'; import { getErrorOrchestrator } from '../../../react-services/common-services'; import { AgentUpgradesInProgress } from './upgrades-in-progress/upgrades-in-progress'; -import { AgentUpgradesTaskDetailsModal } from './upgradeTaskDetailsModal'; +import { AgentUpgradesTaskDetailsModal } from './upgrade-task-details-modal'; const searchBarWQLOptions = { implicitQuery: { From 9f505c9191f7f043239ebb5916c0355d14d4030a Mon Sep 17 00:00:00 2001 From: Luciano Gorza Date: Thu, 14 Mar 2024 13:28:51 -0300 Subject: [PATCH 10/31] Fix get tasks status for readonly user --- docker/osd-dev/dev.yml | 1 - .../endpoints-summary/hooks/upgrade-tasks.ts | 1 + .../components/endpoints-summary/index.tsx | 2 +- .../endpoints-summary/table/agents-table.tsx | 6 ++++++ .../table/global-actions/global-actions.test.tsx | 2 ++ .../table/global-actions/global-actions.tsx | 7 +++++-- .../upgrades-in-progress.test.tsx | 2 ++ .../upgrades-in-progress.tsx | 16 +++++++++------- 8 files changed, 26 insertions(+), 11 deletions(-) diff --git a/docker/osd-dev/dev.yml b/docker/osd-dev/dev.yml index c13e118fe0..92c29e45af 100755 --- a/docker/osd-dev/dev.yml +++ b/docker/osd-dev/dev.yml @@ -245,7 +245,6 @@ services: - '${SRC}/main:/home/node/kbn/plugins/wazuh' - '${SRC}/wazuh-core:/home/node/kbn/plugins/wazuh-core' - '${SRC}/wazuh-check-updates:/home/node/kbn/plugins/wazuh-check-updates' - - '${SRC}/wazuh-endpoints:/home/node/kbn/plugins/wazuh-endpoints' - wd_certs:/home/node/kbn/certs/ - ${WAZUH_DASHBOARD_CONF}:/home/node/kbn/config/opensearch_dashboards.yml - ./config/${OSD_MAJOR}/osd/wazuh.yml:/home/node/kbn/data/wazuh/config/wazuh.yml diff --git a/plugins/main/public/components/endpoints-summary/hooks/upgrade-tasks.ts b/plugins/main/public/components/endpoints-summary/hooks/upgrade-tasks.ts index f4ccd4a20a..5dfc29ce81 100644 --- a/plugins/main/public/components/endpoints-summary/hooks/upgrade-tasks.ts +++ b/plugins/main/public/components/endpoints-summary/hooks/upgrade-tasks.ts @@ -34,6 +34,7 @@ export const useGetUpgradeTasks = (reload: any) => { setTotalInProgressTasks(total_affected_items); setGetInProgressError(undefined); } catch (error: any) { + console.log({ error }); setGetInProgressError(error); } finally { setGetInProgressIsLoading(false); diff --git a/plugins/main/public/components/endpoints-summary/index.tsx b/plugins/main/public/components/endpoints-summary/index.tsx index 7b52d47946..0a54fb9ca7 100644 --- a/plugins/main/public/components/endpoints-summary/index.tsx +++ b/plugins/main/public/components/endpoints-summary/index.tsx @@ -56,7 +56,7 @@ export const MainEndpointsSummary = compose( return ( No agents were added to this manager.} + title={

No agents were added to the manager

} body={

Add agents to fleet to start monitoring

} actions={ ([]); const [isUpgradeTasksModalVisible, setIsUpgradeTasksModalVisible] = useState(false); @@ -243,6 +247,7 @@ export const AgentsTable = compose( setIsModalVisible={setIsUpgradeTasksModalVisible} isPanelClosed={isUpgradePanelClosed} setIsPanelClosed={setIsUpgradePanelClosed} + allowGetTasks={!denyGetTasks} /> } actionButtons={({ filters }) => ( @@ -268,6 +273,7 @@ export const AgentsTable = compose( filters={filters?.q} allowEditGroups={!denyEditGroups} allowUpgrade={!denyUpgrade} + allowGetTasks={!denyGetTasks} reloadAgents={() => reloadAgents()} setIsUpgradeTasksModalVisible={setIsUpgradeTasksModalVisible} setIsUpgradePanelClosed={setIsUpgradePanelClosed} diff --git a/plugins/main/public/components/endpoints-summary/table/global-actions/global-actions.test.tsx b/plugins/main/public/components/endpoints-summary/table/global-actions/global-actions.test.tsx index 422bde5ab0..3b09b24d68 100644 --- a/plugins/main/public/components/endpoints-summary/table/global-actions/global-actions.test.tsx +++ b/plugins/main/public/components/endpoints-summary/table/global-actions/global-actions.test.tsx @@ -21,6 +21,7 @@ describe('AgentsTableGlobalActions component', () => { setIsUpgradeTasksModalVisible={() => {}} setIsUpgradePanelClosed={() => {}} allowUpgrade={true} + allowGetTasks={true} />, ); @@ -42,6 +43,7 @@ describe('AgentsTableGlobalActions component', () => { setIsUpgradeTasksModalVisible={() => {}} setIsUpgradePanelClosed={() => {}} allowUpgrade={true} + allowGetTasks={true} />, ); diff --git a/plugins/main/public/components/endpoints-summary/table/global-actions/global-actions.tsx b/plugins/main/public/components/endpoints-summary/table/global-actions/global-actions.tsx index 4f9a453505..78f4078758 100644 --- a/plugins/main/public/components/endpoints-summary/table/global-actions/global-actions.tsx +++ b/plugins/main/public/components/endpoints-summary/table/global-actions/global-actions.tsx @@ -18,6 +18,7 @@ export interface AgentsTableGlobalActionsProps { filters: any; allowEditGroups: boolean; allowUpgrade: boolean; + allowGetTasks: boolean; reloadAgents: () => void; setIsUpgradeTasksModalVisible: (isModalVisible: boolean) => void; setIsUpgradePanelClosed: (isUpgradePanelClosed: boolean) => void; @@ -30,6 +31,7 @@ export const AgentsTableGlobalActions = ({ filters, allowEditGroups, allowUpgrade, + allowGetTasks, reloadAgents, setIsUpgradeTasksModalVisible, setIsUpgradePanelClosed, @@ -146,6 +148,7 @@ export const AgentsTableGlobalActions = ({ { closePopover(); setIsUpgradeTasksModalVisible(true); @@ -154,8 +157,8 @@ export const AgentsTableGlobalActions = ({ diff --git a/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.test.tsx b/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.test.tsx index 5b07483a04..d9d82e215d 100644 --- a/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.test.tsx +++ b/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.test.tsx @@ -29,6 +29,7 @@ describe('AgentUpgradesInProgress component', () => { setIsModalVisible={() => {}} isPanelClosed={false} setIsPanelClosed={() => {}} + allowGetTasks={true} />, ); @@ -52,6 +53,7 @@ describe('AgentUpgradesInProgress component', () => { setIsModalVisible={() => {}} isPanelClosed={false} setIsPanelClosed={() => {}} + allowGetTasks={true} />, ); diff --git a/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.tsx b/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.tsx index 62b2a62f23..ef9b451d9d 100644 --- a/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.tsx +++ b/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.tsx @@ -20,6 +20,7 @@ interface AgentUpgradesInProgress { setIsModalVisible: (isModalVisible: boolean) => void; isPanelClosed: boolean; setIsPanelClosed: (isPanelClosed: boolean) => void; + allowGetTasks: boolean; } export const AgentUpgradesInProgress = ({ @@ -27,17 +28,18 @@ export const AgentUpgradesInProgress = ({ setIsModalVisible, isPanelClosed, setIsPanelClosed, + allowGetTasks, }: AgentUpgradesInProgress) => { const [isUpgrading, setIsUpgrading] = useState(false); const { - totalInProgressTasks, - getInProgressError, - totalSuccessTasks, - getSuccessError, - totalErrorUpgradeTasks, - getErrorTasksError, - } = useGetUpgradeTasks(reload); + totalInProgressTasks = 0, + getInProgressError = undefined, + totalSuccessTasks = 0, + getSuccessError = undefined, + totalErrorUpgradeTasks = 0, + getErrorTasksError = undefined, + } = allowGetTasks ? useGetUpgradeTasks(reload) : {}; useEffect(() => { if (totalInProgressTasks > 0) { From 6c40834c4702ca3e948933c618420be205cfe57b Mon Sep 17 00:00:00 2001 From: Luciano Gorza Date: Thu, 14 Mar 2024 13:33:29 -0300 Subject: [PATCH 11/31] Improve return condition --- .../table/upgrades-in-progress/upgrades-in-progress.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.tsx b/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.tsx index ef9b451d9d..abcb353207 100644 --- a/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.tsx +++ b/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.tsx @@ -92,8 +92,10 @@ export const AgentUpgradesInProgress = ({ getErrorOrchestrator().handleError(options); } - return !isPanelClosed && - (isUpgrading || totalSuccessTasks || totalErrorUpgradeTasks) ? ( + const showTasks = isUpgrading || totalSuccessTasks || totalErrorUpgradeTasks; + if (isPanelClosed || !showTasks) return null; + + return ( - ) : null; + ); }; From b2f0275d1006f053ab8e7e325fd81587bb2a4293 Mon Sep 17 00:00:00 2001 From: Luciano Gorza Date: Thu, 14 Mar 2024 15:48:06 -0300 Subject: [PATCH 12/31] Improve error message for Timeout status --- plugins/main/common/constants.ts | 9 +++++++++ .../table/upgrade-task-details-modal.tsx | 17 ++++++++--------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/plugins/main/common/constants.ts b/plugins/main/common/constants.ts index 8e0b1c9c93..d0a7c6539a 100644 --- a/plugins/main/common/constants.ts +++ b/plugins/main/common/constants.ts @@ -370,14 +370,23 @@ export const API_NAME_TASK_STATUS = { DONE: 'Done', IN_PROGRESS: 'In progress', FAILED: 'Failed', + TIMEOUT: 'Timeout', } as const; export const UI_TASK_STATUS = [ API_NAME_TASK_STATUS.DONE, API_NAME_TASK_STATUS.IN_PROGRESS, API_NAME_TASK_STATUS.FAILED, + API_NAME_TASK_STATUS.TIMEOUT, ]; +export const UI_TASK_STATUS_COLORS = { + [API_NAME_TASK_STATUS.DONE]: 'success', + [API_NAME_TASK_STATUS.IN_PROGRESS]: 'warning', + [API_NAME_TASK_STATUS.FAILED]: 'danger', + [API_NAME_TASK_STATUS.TIMEOUT]: 'subdued', +}; + // Documentation export const DOCUMENTATION_WEB_BASE_URL = 'https://documentation.wazuh.com'; diff --git a/plugins/main/public/components/endpoints-summary/table/upgrade-task-details-modal.tsx b/plugins/main/public/components/endpoints-summary/table/upgrade-task-details-modal.tsx index 3dac22fa58..16b2122e51 100644 --- a/plugins/main/public/components/endpoints-summary/table/upgrade-task-details-modal.tsx +++ b/plugins/main/public/components/endpoints-summary/table/upgrade-task-details-modal.tsx @@ -6,6 +6,7 @@ import { API_NAME_TASK_STATUS, SEARCH_BAR_WQL_VALUE_SUGGESTIONS_COUNT, UI_TASK_STATUS, + UI_TASK_STATUS_COLORS, } from '../../../../common/constants'; import { WzRequest } from '../../../react-services/wz-request'; import { get as getLodash, uniqBy as uniqByLodash } from 'lodash'; @@ -104,15 +105,7 @@ export const AgentUpgradesTaskDetailsModal = ({ searchable: true, show: true, render: value => ( - + {value} ), @@ -123,6 +116,12 @@ export const AgentUpgradesTaskDetailsModal = ({ show: true, searchable: true, width: '250px', + render: (value, task) => { + if (task.status === API_NAME_TASK_STATUS.TIMEOUT) { + return 'Upgrade task has appears to be done but the notification has never reached the manager'; + } + return value; + }, }, ]} tableInitialSortingField='last_update_time' From 10f17f39efb1c8bba326fb25ec170463e32d146a Mon Sep 17 00:00:00 2001 From: Luciano Gorza Date: Fri, 15 Mar 2024 10:09:46 -0300 Subject: [PATCH 13/31] Add tooltipo to timeout status --- .../table/upgrade-task-details-modal.tsx | 40 ++++++++++++++----- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/plugins/main/public/components/endpoints-summary/table/upgrade-task-details-modal.tsx b/plugins/main/public/components/endpoints-summary/table/upgrade-task-details-modal.tsx index 16b2122e51..4172e6d2dc 100644 --- a/plugins/main/public/components/endpoints-summary/table/upgrade-task-details-modal.tsx +++ b/plugins/main/public/components/endpoints-summary/table/upgrade-task-details-modal.tsx @@ -16,6 +16,10 @@ import { EuiModalBody, EuiModalFooter, EuiButton, + EuiFlexGroup, + EuiFlexItem, + EuiToolTip, + EuiButtonIcon, } from '@elastic/eui'; interface AgentUpgradesTaskDetailsModalProps { @@ -100,14 +104,36 @@ export const AgentUpgradesTaskDetailsModal = ({ { field: 'status', name: 'Status', - width: '120px', + width: '130px', sortable: true, searchable: true, show: true, render: value => ( - - {value} - + + + + {value} + + + {value === API_NAME_TASK_STATUS.TIMEOUT ? ( + + + + + + ) : null} + ), }, { @@ -116,12 +142,6 @@ export const AgentUpgradesTaskDetailsModal = ({ show: true, searchable: true, width: '250px', - render: (value, task) => { - if (task.status === API_NAME_TASK_STATUS.TIMEOUT) { - return 'Upgrade task has appears to be done but the notification has never reached the manager'; - } - return value; - }, }, ]} tableInitialSortingField='last_update_time' From 01e830707f297b9d260594d91ce3a57791955b30 Mon Sep 17 00:00:00 2001 From: Luciano Gorza Date: Fri, 15 Mar 2024 11:52:55 -0300 Subject: [PATCH 14/31] Modularize get status functions --- .../endpoints-summary/hooks/upgrade-tasks.ts | 93 +++++++++++-------- .../table/upgrade-task-details-modal.tsx | 17 +--- .../upgrades-in-progress.tsx | 70 ++++++++------ 3 files changed, 101 insertions(+), 79 deletions(-) diff --git a/plugins/main/public/components/endpoints-summary/hooks/upgrade-tasks.ts b/plugins/main/public/components/endpoints-summary/hooks/upgrade-tasks.ts index 5dfc29ce81..8b0596f692 100644 --- a/plugins/main/public/components/endpoints-summary/hooks/upgrade-tasks.ts +++ b/plugins/main/public/components/endpoints-summary/hooks/upgrade-tasks.ts @@ -18,69 +18,83 @@ export const useGetUpgradeTasks = (reload: any) => { const [getErrorIsLoading, setErrorIsLoading] = useState(true); const [getErrorTasksError, setGetErrorTasksError] = useState(); + const [totalTimeoutUpgradeTasks, setTotalTimeoutUpgradeTasks] = + useState(0); + const [getTimeoutIsLoading, setTimeoutIsLoading] = useState(true); + const [getTimeoutError, setGetTimeoutError] = useState(); + const datetime = new Date(); datetime.setMinutes(datetime.getMinutes() - beforeMinutes); const formattedDate = datetime.toISOString(); const timeFilter = `last_update_time>${formattedDate}`; - const getUpgradesInProgress = async () => { + const getUpgradeStatus = async ( + status: string, + setIsLoading: (isLoading: boolean) => void, + setTotalTasks: (totalTasks: number) => void, + setError: (error) => void, + q?: string, + ) => { try { - setGetInProgressIsLoading(true); + setIsLoading(true); const { total_affected_items } = await getTasks({ - status: API_NAME_TASK_STATUS.IN_PROGRESS, + status, command: 'upgrade', limit: 1, + q, }); - setTotalInProgressTasks(total_affected_items); - setGetInProgressError(undefined); + setTotalTasks(total_affected_items); + setError(undefined); } catch (error: any) { - console.log({ error }); - setGetInProgressError(error); + setError(error); } finally { - setGetInProgressIsLoading(false); + setIsLoading(false); } }; + const getUpgradesInProgress = async () => + await getUpgradeStatus( + API_NAME_TASK_STATUS.IN_PROGRESS, + setGetInProgressIsLoading, + setTotalInProgressTasks, + setGetInProgressError, + ); + const getUpgradesSuccess = async () => { - try { - setSuccessIsLoading(true); - const { total_affected_items } = await getTasks({ - status: API_NAME_TASK_STATUS.DONE, - command: 'upgrade', - limit: 1, - q: timeFilter, - }); - setTotalSuccessTasks(total_affected_items); - setGetSuccessError(undefined); - } catch (error: any) { - setGetSuccessError(error); - } finally { - setSuccessIsLoading(false); - } + await getUpgradeStatus( + API_NAME_TASK_STATUS.DONE, + setSuccessIsLoading, + setTotalSuccessTasks, + setGetSuccessError, + timeFilter, + ); }; const getUpgradesError = async () => { - try { - setErrorIsLoading(true); - const { total_affected_items } = await getTasks({ - status: API_NAME_TASK_STATUS.FAILED, - command: 'upgrade', - limit: 1, - q: timeFilter, - }); - setTotalErrorUpgradeTasks(total_affected_items); - setGetErrorTasksError(undefined); - } catch (error: any) { - setGetErrorTasksError(error); - } finally { - setErrorIsLoading(false); - } + await getUpgradeStatus( + API_NAME_TASK_STATUS.FAILED, + setErrorIsLoading, + setTotalErrorUpgradeTasks, + setGetErrorTasksError, + timeFilter, + ); + }; + + const getUpgradeTimeout = async () => { + await getUpgradeStatus( + API_NAME_TASK_STATUS.TIMEOUT, + setTimeoutIsLoading, + setTotalTimeoutUpgradeTasks, + setGetTimeoutError, + timeFilter, + ); }; const fetchData = async () => { await getUpgradesInProgress(); await getUpgradesSuccess(); await getUpgradesError(); + await getUpgradeTimeout(); }; useEffect(() => { @@ -105,5 +119,8 @@ export const useGetUpgradeTasks = (reload: any) => { getErrorIsLoading, totalErrorUpgradeTasks, getErrorTasksError, + getTimeoutIsLoading, + totalTimeoutUpgradeTasks, + getTimeoutError, }; }; diff --git a/plugins/main/public/components/endpoints-summary/table/upgrade-task-details-modal.tsx b/plugins/main/public/components/endpoints-summary/table/upgrade-task-details-modal.tsx index 4172e6d2dc..2197da597f 100644 --- a/plugins/main/public/components/endpoints-summary/table/upgrade-task-details-modal.tsx +++ b/plugins/main/public/components/endpoints-summary/table/upgrade-task-details-modal.tsx @@ -1,5 +1,4 @@ import React from 'react'; -import { EuiHealth, EuiIconTip } from '@elastic/eui'; import { TableWzAPI } from '../../common/tables'; import { formatUIDate } from '../../../react-services/time-service'; import { @@ -18,8 +17,8 @@ import { EuiButton, EuiFlexGroup, EuiFlexItem, - EuiToolTip, - EuiButtonIcon, + EuiHealth, + EuiIconTip, } from '@elastic/eui'; interface AgentUpgradesTaskDetailsModalProps { @@ -121,16 +120,10 @@ export const AgentUpgradesTaskDetailsModal = ({ {value === API_NAME_TASK_STATUS.TIMEOUT ? ( - - - + color='primary' + /> ) : null}
diff --git a/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.tsx b/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.tsx index abcb353207..3729ba369f 100644 --- a/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.tsx +++ b/plugins/main/public/components/endpoints-summary/table/upgrades-in-progress/upgrades-in-progress.tsx @@ -11,7 +11,10 @@ import { EuiButtonIcon, } from '@elastic/eui'; import { useGetUpgradeTasks } from '../../hooks'; -import { UI_LOGGER_LEVELS } from '../../../../../common/constants'; +import { + API_NAME_TASK_STATUS, + UI_LOGGER_LEVELS, +} from '../../../../../common/constants'; import { UI_ERROR_SEVERITIES } from '../../../../react-services/error-orchestrator/types'; import { getErrorOrchestrator } from '../../../../react-services/common-services'; @@ -39,6 +42,8 @@ export const AgentUpgradesInProgress = ({ getSuccessError = undefined, totalErrorUpgradeTasks = 0, getErrorTasksError = undefined, + totalTimeoutUpgradeTasks = 0, + getTimeoutError = undefined, } = allowGetTasks ? useGetUpgradeTasks(reload) : {}; useEffect(() => { @@ -47,49 +52,36 @@ export const AgentUpgradesInProgress = ({ } }, [totalInProgressTasks]); - if (getInProgressError) { + const showErrorToast = (status: string, error: any) => { + API_NAME_TASK_STATUS; const options = { context: `AgentUpgradesInProgress.useGetUpgradeTasks`, level: UI_LOGGER_LEVELS.ERROR, severity: UI_ERROR_SEVERITIES.BUSINESS, store: true, error: { - error: getInProgressError, - message: getInProgressError.message || getInProgressError, - title: `Could not get upgrade progress tasks`, + error, + message: error.message || error, + title: `Could not get upgrade tasks: ${status}`, }, }; getErrorOrchestrator().handleError(options); + }; + + if (getInProgressError) { + showErrorToast(API_NAME_TASK_STATUS.IN_PROGRESS, getInProgressError); } if (getSuccessError) { - const options = { - context: `AgentUpgradesInProgress.useGetUpgradeTasks`, - level: UI_LOGGER_LEVELS.ERROR, - severity: UI_ERROR_SEVERITIES.BUSINESS, - store: true, - error: { - error: getSuccessError, - message: getSuccessError.message || getSuccessError, - title: `Could not get upgrade success tasks`, - }, - }; - getErrorOrchestrator().handleError(options); + showErrorToast(API_NAME_TASK_STATUS.DONE, getSuccessError); } if (getErrorTasksError) { - const options = { - context: `AgentUpgradesInProgress.useGetUpgradeTasks`, - level: UI_LOGGER_LEVELS.ERROR, - severity: UI_ERROR_SEVERITIES.BUSINESS, - store: true, - error: { - error: getErrorTasksError, - message: getErrorTasksError.message || getErrorTasksError, - title: `Could not get upgrade error tasks`, - }, - }; - getErrorOrchestrator().handleError(options); + showErrorToast(API_NAME_TASK_STATUS.FAILED, getErrorTasksError); + } + + if (getTimeoutError) { + showErrorToast(API_NAME_TASK_STATUS.TIMEOUT, getTimeoutError); } const showTasks = isUpgrading || totalSuccessTasks || totalErrorUpgradeTasks; @@ -184,6 +176,26 @@ export const AgentUpgradesInProgress = ({ ) : null} + {totalTimeoutUpgradeTasks > 0 ? ( + + + + + + {totalTimeoutUpgradeTasks} + {' Timeout '} + + + + + + ) : null} ); From 1afefd163e2d099f166595cc2b6a0baa1d91f28c Mon Sep 17 00:00:00 2001 From: Luciano Gorza Date: Fri, 15 Mar 2024 17:44:56 -0300 Subject: [PATCH 15/31] Fix status name and key values --- .../table/global-actions/upgrade/result.tsx | 4 ++-- .../table/upgrades-in-progress/upgrades-in-progress.tsx | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/result.tsx b/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/result.tsx index 30b02b8b9d..c2e5d10918 100644 --- a/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/result.tsx +++ b/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/result.tsx @@ -237,9 +237,9 @@ export const UpgradeAgentsModalResult = ({ ) : null} {totalErrorAgents ? ( - + {totalInProgressTasks} - {' In progress'} + {` ${API_NAME_TASK_STATUS.IN_PROGRESS}`} @@ -149,7 +149,7 @@ export const AgentUpgradesInProgress = ({ {totalSuccessTasks} - {' Success '} + {` ${API_NAME_TASK_STATUS.DONE} `} @@ -169,7 +169,7 @@ export const AgentUpgradesInProgress = ({ {totalErrorUpgradeTasks} - {' Failed '} + {` ${API_NAME_TASK_STATUS.FAILED} `} @@ -189,7 +189,7 @@ export const AgentUpgradesInProgress = ({ {totalTimeoutUpgradeTasks} - {' Timeout '} + {` ${API_NAME_TASK_STATUS.TIMEOUT} `} From e1ddf49cbf4199ddb1d0bff8d4d004910fd6bd0c Mon Sep 17 00:00:00 2001 From: Luciano Gorza Date: Fri, 15 Mar 2024 18:12:00 -0300 Subject: [PATCH 16/31] Separate upgrade service in two services --- .../endpoints-summary/services/index.tsx | 1 + .../services/paginated-agents-request.tsx | 2 +- .../services/upgrade-agent.tsx | 11 +++++++++++ .../services/upgrade-agents.tsx | 18 +++++------------- .../table/actions/upgrade-agent-modal.test.tsx | 4 ++-- .../table/actions/upgrade-agent-modal.tsx | 4 ++-- .../global-actions/upgrade/upgrade-modal.tsx | 2 +- 7 files changed, 23 insertions(+), 19 deletions(-) create mode 100644 plugins/main/public/components/endpoints-summary/services/upgrade-agent.tsx diff --git a/plugins/main/public/components/endpoints-summary/services/index.tsx b/plugins/main/public/components/endpoints-summary/services/index.tsx index 17910f7e44..11f86cff42 100644 --- a/plugins/main/public/components/endpoints-summary/services/index.tsx +++ b/plugins/main/public/components/endpoints-summary/services/index.tsx @@ -4,6 +4,7 @@ export { removeAgentsFromGroupService } from './remove-agents-from-group'; export { addAgentToGroupService } from './add-agent-to-group'; export { addAgentsToGroupService } from './add-agents-to-group'; export { getGroupsService } from './get-groups'; +export { upgradeAgentService } from './upgrade-agent'; export { upgradeAgentsService } from './upgrade-agents'; export { getOutdatedAgents } from './get-outdated-agents'; export { getTasks } from './get-tasks'; diff --git a/plugins/main/public/components/endpoints-summary/services/paginated-agents-request.tsx b/plugins/main/public/components/endpoints-summary/services/paginated-agents-request.tsx index 0f8020ea89..734a2afece 100644 --- a/plugins/main/public/components/endpoints-summary/services/paginated-agents-request.tsx +++ b/plugins/main/public/components/endpoints-summary/services/paginated-agents-request.tsx @@ -22,7 +22,7 @@ export const paginatedAgentsRequestService = async ({ agentIds: string[]; groupId?: string; pageSize?: number; -}): Promise> => { +}): Promise> => { let offset = 0; let requestAgentIds: string[] = []; let allAffectedItems: string[] = []; diff --git a/plugins/main/public/components/endpoints-summary/services/upgrade-agent.tsx b/plugins/main/public/components/endpoints-summary/services/upgrade-agent.tsx new file mode 100644 index 0000000000..6eb0de5d3b --- /dev/null +++ b/plugins/main/public/components/endpoints-summary/services/upgrade-agent.tsx @@ -0,0 +1,11 @@ +import IApiResponse from '../../../react-services/interfaces/api-response.interface'; +import { WzRequest } from '../../../react-services/wz-request'; +import { ResponseUpgradeAgents } from '../types'; + +export const upgradeAgentService = async (agentId: string) => + (await WzRequest.apiReq('PUT', '/agents/upgrade', { + params: { + agents_list: agentId, + wait_for_complete: true, + }, + })) as IApiResponse; diff --git a/plugins/main/public/components/endpoints-summary/services/upgrade-agents.tsx b/plugins/main/public/components/endpoints-summary/services/upgrade-agents.tsx index e20a1d5ef4..2fc0a1c807 100644 --- a/plugins/main/public/components/endpoints-summary/services/upgrade-agents.tsx +++ b/plugins/main/public/components/endpoints-summary/services/upgrade-agents.tsx @@ -1,5 +1,4 @@ import IApiResponse from '../../../react-services/interfaces/api-response.interface'; -import { WzRequest } from '../../../react-services/wz-request'; import { ResponseUpgradeAgents } from '../types'; import { paginatedAgentsRequestService } from './paginated-agents-request'; @@ -8,15 +7,8 @@ export const upgradeAgentsService = async ({ }: { agentIds: string[]; }) => - (agentIds.length === 1 - ? await WzRequest.apiReq('PUT', '/agents/upgrade', { - params: { - agents_list: agentIds.join(','), - wait_for_complete: true, - }, - }) - : await paginatedAgentsRequestService({ - method: 'PUT', - url: '/agents/upgrade', - agentIds, - })) as IApiResponse; + (await paginatedAgentsRequestService({ + method: 'PUT', + url: '/agents/upgrade', + agentIds, + })) as IApiResponse; diff --git a/plugins/main/public/components/endpoints-summary/table/actions/upgrade-agent-modal.test.tsx b/plugins/main/public/components/endpoints-summary/table/actions/upgrade-agent-modal.test.tsx index 8fc361a0a1..dff25feca7 100644 --- a/plugins/main/public/components/endpoints-summary/table/actions/upgrade-agent-modal.test.tsx +++ b/plugins/main/public/components/endpoints-summary/table/actions/upgrade-agent-modal.test.tsx @@ -1,10 +1,10 @@ import React from 'react'; -import { render, fireEvent, waitFor, act } from '@testing-library/react'; +import { render, fireEvent, act } from '@testing-library/react'; import '@testing-library/jest-dom'; import { UpgradeAgentModal } from './upgrade-agent-modal'; jest.mock('../../services', () => ({ - upgradeAgentsService: jest.fn(), + upgradeAgentService: jest.fn(), })); jest.mock('../../../../react-services/common-services', () => ({ diff --git a/plugins/main/public/components/endpoints-summary/table/actions/upgrade-agent-modal.tsx b/plugins/main/public/components/endpoints-summary/table/actions/upgrade-agent-modal.tsx index ca22be1686..1b217dcbcf 100644 --- a/plugins/main/public/components/endpoints-summary/table/actions/upgrade-agent-modal.tsx +++ b/plugins/main/public/components/endpoints-summary/table/actions/upgrade-agent-modal.tsx @@ -5,7 +5,7 @@ import { withErrorBoundary, withReduxProvider } from '../../../common/hocs'; import { UI_LOGGER_LEVELS } from '../../../../../common/constants'; import { UI_ERROR_SEVERITIES } from '../../../../react-services/error-orchestrator/types'; import { getErrorOrchestrator } from '../../../../react-services/common-services'; -import { upgradeAgentsService } from '../../services'; +import { upgradeAgentService } from '../../services'; import { Agent } from '../../types'; import { getToasts } from '../../../../kibana-services'; @@ -45,7 +45,7 @@ export const UpgradeAgentModal = compose( setIsLoading(true); try { - await upgradeAgentsService({ agentIds: [agent.id] }); + await upgradeAgentService(agent.id); showToast('success', 'Upgrade agent', 'Upgrade task in progress'); reloadAgents(); setIsUpgradePanelClosed(false); diff --git a/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/upgrade-modal.tsx b/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/upgrade-modal.tsx index df3b2d392f..36ffd83276 100644 --- a/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/upgrade-modal.tsx +++ b/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/upgrade-modal.tsx @@ -19,8 +19,8 @@ import { UI_ERROR_SEVERITIES } from '../../../../../react-services/error-orchest import { getErrorOrchestrator } from '../../../../../react-services/common-services'; import { getAgentsService, upgradeAgentsService } from '../../../services'; import { Agent, ResponseUpgradeAgents } from '../../../types'; -import { ErrorAgent } from '../../../services/paginated-agents-group'; import { UpgradeAgentsModalResult } from './result'; +import { ErrorAgent } from '../../../services/paginated-agents-request'; export type Result = { successAgents?: ResponseUpgradeAgents[]; From f46f0daf58ea9f4de162e81cb8026b56df2250eb Mon Sep 17 00:00:00 2001 From: Luciano Gorza Date: Mon, 18 Mar 2024 10:29:32 -0300 Subject: [PATCH 17/31] Add filter for outdated agents --- .../components/common/tables/table-wz-api.tsx | 2 +- .../components/outdated-agents-card.tsx | 51 +++++--------- .../dashboard/endpoints-summary-dashboard.tsx | 9 ++- .../endpoints-summary/endpoints-summary.tsx | 51 +++++++++++--- .../services/get-outdated-agents.ts | 31 ++++---- .../endpoints-summary/table/agents-table.tsx | 70 ++++++++++++------- 6 files changed, 130 insertions(+), 84 deletions(-) diff --git a/plugins/main/public/components/common/tables/table-wz-api.tsx b/plugins/main/public/components/common/tables/table-wz-api.tsx index 14fb393f50..50ac453b8d 100644 --- a/plugins/main/public/components/common/tables/table-wz-api.tsx +++ b/plugins/main/public/components/common/tables/table-wz-api.tsx @@ -197,7 +197,7 @@ export function TableWzAPI({ <> - + {rest.title && ( diff --git a/plugins/main/public/components/endpoints-summary/dashboard/components/outdated-agents-card.tsx b/plugins/main/public/components/endpoints-summary/dashboard/components/outdated-agents-card.tsx index 6023a05de1..2d556920ae 100644 --- a/plugins/main/public/components/endpoints-summary/dashboard/components/outdated-agents-card.tsx +++ b/plugins/main/public/components/endpoints-summary/dashboard/components/outdated-agents-card.tsx @@ -11,48 +11,29 @@ import { EuiButtonEmpty, } from '@elastic/eui'; import './outdated-agents-card.scss'; -import { getOutdatedAgents } from '../../services/get-outdated-agents'; import { webDocumentationLink } from '../../../../../common/services/web_documentation'; -import { useService } from '../../../common/hooks/use-service'; interface OutdatedAgentsCardProps { - onClick?: (status: any) => void; - reload?: number; - [key: string]: any; + isLoading: boolean; + outdatedAgents: number; + filterByOutdatedAgent: (value: boolean) => void; } const OutdatedAgentsCard = ({ - onClick, - reload, - ...props + isLoading, + outdatedAgents, + filterByOutdatedAgent, }: OutdatedAgentsCardProps) => { - const { data, isLoading } = useService( - getOutdatedAgents, - undefined, - reload, - ); - const outdatedAgents = data?.length; const contentType = outdatedAgents > 0 ? 'warning' : 'success'; const contentIcon = outdatedAgents > 0 ? 'alert' : 'check'; - const [showOutdatedAgents, setShowOutdatedAgents] = - React.useState(false); - - const onShowOutdatedAgents = () => setShowOutdatedAgents(!showOutdatedAgents); - const onHideOutdatedAgents = () => setShowOutdatedAgents(false); + const [showOptions, setShowOptions] = React.useState(false); - const handleClick = () => { - if (onClick) { - onClick(data); - setShowOutdatedAgents(false); - } - }; + const onShowOptions = () => setShowOptions(true); + const onHideOptions = () => setShowOptions(false); const renderMetric = () => { return ( -
+
0)} + onClick={() => { + onHideOptions(); + filterByOutdatedAgent(true); + }} + isDisabled={!outdatedAgents} > Filter outdated agents @@ -109,6 +93,7 @@ const OutdatedAgentsCard = ({ target='_blank' external rel='noopener noreferrer' + onClick={() => onHideOptions()} > How to update agents diff --git a/plugins/main/public/components/endpoints-summary/dashboard/endpoints-summary-dashboard.tsx b/plugins/main/public/components/endpoints-summary/dashboard/endpoints-summary-dashboard.tsx index 5e74dc9842..a31040052d 100644 --- a/plugins/main/public/components/endpoints-summary/dashboard/endpoints-summary-dashboard.tsx +++ b/plugins/main/public/components/endpoints-summary/dashboard/endpoints-summary-dashboard.tsx @@ -9,6 +9,8 @@ interface EndpointsSummaryDashboardProps { filterAgentByStatus: (data: any) => void; filterAgentByOS: (data: any) => void; filterAgentByGroup: (data: any) => void; + outdatedAgents: number; + isLoadingOutdatedAgents: boolean; filterByOutdatedAgent: (data: any) => void; reloadDashboard?: number; } @@ -17,6 +19,8 @@ export const EndpointsSummaryDashboard: FC = ({ filterAgentByStatus, filterAgentByOS, filterAgentByGroup, + outdatedAgents, + isLoadingOutdatedAgents, filterByOutdatedAgent, reloadDashboard, }) => { @@ -41,8 +45,9 @@ export const EndpointsSummaryDashboard: FC = ({ reload={reloadDashboard} />
); diff --git a/plugins/main/public/components/endpoints-summary/endpoints-summary.tsx b/plugins/main/public/components/endpoints-summary/endpoints-summary.tsx index 3ec1be73ca..5bcff26533 100644 --- a/plugins/main/public/components/endpoints-summary/endpoints-summary.tsx +++ b/plugins/main/public/components/endpoints-summary/endpoints-summary.tsx @@ -31,6 +31,10 @@ import { endpointSummary } from '../../utils/applications'; import { ShareAgent } from '../../factories/share-agent'; import './endpoints-summary.scss'; import { EndpointsSummaryDashboard } from './dashboard/endpoints-summary-dashboard'; +import { getOutdatedAgents } from './services'; +import { UI_LOGGER_LEVELS } from '../../../common/constants'; +import { UI_ERROR_SEVERITIES } from '../../react-services/error-orchestrator/types'; +import { getErrorOrchestrator } from '../../react-services/common-services'; export const EndpointsSummary = compose( withErrorBoundary, @@ -50,6 +54,9 @@ export const EndpointsSummary = compose( this.state = { agentTableFilters: {}, reload: 0, + outdatedAgents: 0, + isLoadingOutdatedAgents: true, + showOnlyOutdatedAgents: false, }; this.wazuhConfig = new WazuhConfig(); this.shareAgent = new ShareAgent(); @@ -59,14 +66,43 @@ export const EndpointsSummary = compose( this.filterByOutdatedAgent = this.filterByOutdatedAgent.bind(this); } + getOutdatedAgents = async () => { + try { + this.setState({ isLoadingOutdatedAgents: true }); + const { total_affected_items } = await getOutdatedAgents({ limit: 1 }); + this.setState({ outdatedAgents: total_affected_items }); + } catch (error) { + const options = { + context: `EndpointsSummary.getOutdatedAgents`, + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.BUSINESS, + store: true, + error: { + error, + message: error.message || error, + title: `Could not get outdated agents`, + }, + }; + getErrorOrchestrator().handleError(options); + } finally { + this.setState({ isLoadingOutdatedAgents: false }); + } + }; + setReload = (newValue: number) => { this.setState({ reload: newValue, }); + this.getOutdatedAgents(); + }; + + setShowOnlyOutdatedAgents = (newValue: boolean) => { + this.setState({ showOnlyOutdatedAgents: newValue }); }; async componentDidMount() { this._isMount = true; + this.getOutdatedAgents(); if (this.wazuhConfig.getConfig()['wazuh.monitoring.enabled']) { const tabVisualizations = new TabVisualizations(); tabVisualizations.removeAll(); @@ -124,14 +160,8 @@ export const EndpointsSummary = compose( }); } - filterByOutdatedAgent(outdatedAgents: any) { - const ids: string = outdatedAgents - .map((agent: any) => `id=${agent.id}`) - .join(','); - this._isMount && - this.setState({ - agentTableFilters: { q: `id!=000;${ids}` }, - }); + filterByOutdatedAgent() { + this._isMount && this.setShowOnlyOutdatedAgents(true); } render() { @@ -142,6 +172,8 @@ export const EndpointsSummary = compose( filterAgentByStatus={this.filterAgentByStatus} filterAgentByOS={this.filterAgentByOS} filterAgentByGroup={this.filterAgentByGroup} + outdatedAgents={this.state.outdatedAgents} + isLoadingOutdatedAgents={this.state.isLoadingOutdatedAgents} filterByOutdatedAgent={this.filterByOutdatedAgent} reloadDashboard={this.state.reload} /> @@ -151,6 +183,9 @@ export const EndpointsSummary = compose( filters={this.state.agentTableFilters} externalReload={this.state.reload} setExternalReload={this.setReload} + showOnlyOutdated={this.state.showOnlyOutdatedAgents} + setShowOnlyOutdated={this.setShowOnlyOutdatedAgents} + outdated={this.state.outdatedAgents} /> diff --git a/plugins/main/public/components/endpoints-summary/services/get-outdated-agents.ts b/plugins/main/public/components/endpoints-summary/services/get-outdated-agents.ts index 36e44d173e..250b755fde 100644 --- a/plugins/main/public/components/endpoints-summary/services/get-outdated-agents.ts +++ b/plugins/main/public/components/endpoints-summary/services/get-outdated-agents.ts @@ -1,20 +1,21 @@ import { WzRequest } from '../../../react-services/wz-request'; -export const getOutdatedAgents = async (agentIds?: string[]) => { +export const getOutdatedAgents = async ({ + agentIds, + limit, +}: { + agentIds?: string[]; + limit?: number; +}) => { const { - data: { - data: { affected_items }, + data: { data }, + } = await WzRequest.apiReq('GET', '/agents/outdated', { + params: { + ...(agentIds?.length + ? { q: `(${agentIds.map(agentId => `id=${agentId}`).join(',')})` } + : {}), + limit, }, - } = await WzRequest.apiReq( - 'GET', - '/agents/outdated', - agentIds - ? { - params: { - q: `(${agentIds.map(agentId => `id=${agentId}`).join(',')})`, - }, - } - : {}, - ); - return affected_items; + }); + return data; }; diff --git a/plugins/main/public/components/endpoints-summary/table/agents-table.tsx b/plugins/main/public/components/endpoints-summary/table/agents-table.tsx index e84419283a..938e4c84fb 100644 --- a/plugins/main/public/components/endpoints-summary/table/agents-table.tsx +++ b/plugins/main/public/components/endpoints-summary/table/agents-table.tsx @@ -18,6 +18,7 @@ import { EuiPanel, EuiCallOut, EuiButton, + EuiSwitch, } from '@elastic/eui'; import { WzButtonPermissions } from '../../common/permissions/button'; import { withErrorBoundary } from '../../common/hocs'; @@ -67,6 +68,9 @@ interface AgentsTableProps { filters: any; updateCurrentAgentData: (agent) => void; externalReload?: boolean; + showOnlyOutdated: boolean; + setShowOnlyOutdated: (newValue: boolean) => void; + outdated?: number; setExternalReload?: (newValue: number) => void; } @@ -177,7 +181,9 @@ export const AgentsTable = compose( const agentIds = data?.items?.map(agent => agent.id); try { - const outdatedAgents = await getOutdatedAgents(agentIds); + const outdatedAgents = agentIds?.length + ? (await getOutdatedAgents({ agentIds })).affected_items + : []; setOutdatedAgents(outdatedAgents); } catch (error) { setOutdatedAgents([]); @@ -205,31 +211,45 @@ export const AgentsTable = compose( ? agentList.totalItems : selectedItems.length; - const selectedtemsRenderer = selectedItems.length ? ( - - - - - {showSelectAllItems ? ( + const selectedtemsRenderer = ( + + {selectedItems.length ? ( - - {!allAgentsSelected - ? `Select all ${agentList.totalItems} agents` - : `Clear ${agentList.totalItems} agents selected`} - + + + + + {showSelectAllItems ? ( + + + {!allAgentsSelected + ? `Select all ${agentList.totalItems} agents` + : `Clear ${agentList.totalItems} agents selected`} + + + ) : null} + ) : null} + + props.setShowOnlyOutdated(!props.showOnlyOutdated)} + /> + - ) : null; + ); const tableRender = () => { // The EuiBasicTable tableLayout is set to "auto" to improve the use of empty space in the component. @@ -250,7 +270,7 @@ export const AgentsTable = compose( allowGetTasks={!denyGetTasks} /> } - actionButtons={({ filters }) => ( + actionButtons={ - )} + } postActionButtons={({ filters }) => ( )} - endpoint='/agents' + endpoint={props.showOnlyOutdated ? '/agents/outdated' : '/agents'} tableColumns={agentsTableColumns( !denyEditGroups, !denyUpgrade, From e7ddd15df673f48de3e1dc2a23fbe03873ffc329 Mon Sep 17 00:00:00 2001 From: Luciano Gorza Date: Mon, 18 Mar 2024 12:49:55 -0300 Subject: [PATCH 18/31] Update CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1f91bd870..e380834181 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ All notable changes to the Wazuh app project will be documented in this file. - Added AngularJS dependencies [#6145](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6145) - Added a migration task to setup the configuration using a configuration file [#6337](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6337) - Added the ability to manage the API hosts from the Server APIs [#6337](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6337) [#6519](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6519) -- Added edit agent groups and upgrade agents actions to Endpoints Summary [#6250](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6250) [#6476](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6476) [#6274](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6274) [#6501](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6501) +- Improve fleet management by adding 'Edit Agent Groups' and 'Upgrade Agents' actions, as well as a filter to show only outdated agents [#6250](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6250) [#6476](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6476) [#6274](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6274) [#6501](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6501) [#6529](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6529) - Added propagation of updates from the table to dashboard visualizations in Endpoints summary [#6460](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6460) ### Changed From 9902222ab2457fdf4af4c0d00e545cc269dcb959 Mon Sep 17 00:00:00 2001 From: Luciano Gorza Date: Mon, 18 Mar 2024 13:30:29 -0300 Subject: [PATCH 19/31] Update unit tests --- .../__snapshots__/inventory.test.tsx.snap | 32 +- .../__snapshots__/table-wz-api.test.tsx.snap | 3 +- .../components/outdated-agents-card.test.tsx | 109 ++--- .../__snapshots__/agents-table.test.tsx.snap | 381 ++++++++++++++---- .../__snapshots__/intelligence.test.tsx.snap | 2 +- 5 files changed, 378 insertions(+), 149 deletions(-) diff --git a/plugins/main/public/components/agents/syscollector/__snapshots__/inventory.test.tsx.snap b/plugins/main/public/components/agents/syscollector/__snapshots__/inventory.test.tsx.snap index 665925c7d8..df26ef4255 100644 --- a/plugins/main/public/components/agents/syscollector/__snapshots__/inventory.test.tsx.snap +++ b/plugins/main/public/components/agents/syscollector/__snapshots__/inventory.test.tsx.snap @@ -141,7 +141,7 @@ exports[`Inventory component A Apple agent should be well rendered. 1`] = ` class="euiFlexItem" >
{ wrapper.update(); }); }; - - const mockLoading = false; - const mockDataNoOutdatedAgents = []; - const useServiceMockNoOutdatedAgent = jest.fn(() => ({data: mockDataNoOutdatedAgents, isLoading: mockLoading})); - const mockDataOutdatedAgents = [ - { - version: "Wazuh v3.0.0", - id: "003", - name: "main_database" - }, - { - version: "Wazuh v3.0.0", - id: "004", - name: "dmz002" - } -]; - const useServiceMockOutdatedAgent = jest.fn(() => ({data: mockDataOutdatedAgents, isLoading: mockLoading})); - - const handleClick = jest.fn(); + const filterByOutdatedAgent = jest.fn(); it('renders with not outdated agents', async () => { - require('../../../common/hooks/use-service').useService = useServiceMockNoOutdatedAgent; - await act(async () => { const { getByTestId } = render( - + , ); - const outdatedAgentsNumberElement = getByTestId('wazuh-endpoints-summary-outdated-agents-number') - expect(outdatedAgentsNumberElement).toHaveClass('euiTextColor euiTextColor--success'); - expect(outdatedAgentsNumberElement.textContent).toBe(`${mockDataNoOutdatedAgents.length}`); + const outdatedAgentsNumberElement = getByTestId( + 'wazuh-endpoints-summary-outdated-agents-number', + ); + expect(outdatedAgentsNumberElement).toHaveClass( + 'euiTextColor euiTextColor--success', + ); + expect(outdatedAgentsNumberElement.textContent).toBe('0'); }); }); it('renders with outdated agents', async () => { - require('../../../common/hooks/use-service').useService = useServiceMockOutdatedAgent; - await act(async () => { const { getByTestId } = render( - + , ); - const outdatedAgentsNumberElement = getByTestId('wazuh-endpoints-summary-outdated-agents-number') - expect(outdatedAgentsNumberElement).toHaveClass('euiTextColor euiTextColor--warning'); - expect(outdatedAgentsNumberElement.textContent).toBe(`${mockDataOutdatedAgents.length}`); + const outdatedAgentsNumberElement = getByTestId( + 'wazuh-endpoints-summary-outdated-agents-number', + ); + expect(outdatedAgentsNumberElement).toHaveClass( + 'euiTextColor euiTextColor--warning', + ); + expect(outdatedAgentsNumberElement.textContent).toBe('2'); }); }); it('renders popover on click with outdated agents', async () => { - require('../../../common/hooks/use-service').useService = useServiceMockOutdatedAgent; - const wrapper = await mount( - , + , ); await awaitForMyComponent(wrapper); - + expect(wrapper.find('.wazuh-outdated-agents-panel').exists()).toBeTruthy(); expect(wrapper.find(EuiButtonEmpty).exists()).not.toBeTruthy(); - + wrapper.find('.wazuh-outdated-agents-panel').simulate('click'); expect(wrapper.find(EuiButtonEmpty).exists()).toBeTruthy(); }); it('handles click with correct data', async () => { - require('../../../common/hooks/use-service').useService = useServiceMockOutdatedAgent; - const wrapper = await mount( - , + , ); await awaitForMyComponent(wrapper); - + expect(wrapper.find('.wazuh-outdated-agents-panel').exists()).toBeTruthy(); expect(wrapper.find(EuiButtonEmpty).exists()).not.toBeTruthy(); - + wrapper.find('.wazuh-outdated-agents-panel').simulate('click'); expect(wrapper.find(EuiButtonEmpty).exists()).toBeTruthy(); wrapper.find(EuiButtonEmpty).simulate('click'); - expect(handleClick).toHaveBeenCalledTimes(1); - expect(handleClick).toHaveBeenCalledWith(mockDataOutdatedAgents); + expect(filterByOutdatedAgent).toHaveBeenCalledTimes(1); + expect(filterByOutdatedAgent).toHaveBeenCalledWith(true); }); it('EuiButtonEmpty filter must be disabled when no data', async () => { - require('../../../common/hooks/use-service').useService = useServiceMockNoOutdatedAgent; - const wrapper = await mount( - , + , ); await awaitForMyComponent(wrapper); - + expect(wrapper.find('.wazuh-outdated-agents-panel').exists()).toBeTruthy(); expect(wrapper.find(EuiButtonEmpty).exists()).not.toBeTruthy(); - + wrapper.find('.wazuh-outdated-agents-panel').simulate('click'); expect(wrapper.find(EuiButtonEmpty).exists()).toBeTruthy(); expect(wrapper.find(EuiButtonEmpty).prop('isDisabled')).toBe(true); @@ -123,20 +123,21 @@ describe('OutdatedAgentsCard', () => { const documentationLink = webDocumentationLink( 'upgrade-guide/wazuh-agent/index.html', ); - require('../../../common/hooks/use-service').useService = useServiceMockNoOutdatedAgent; - const wrapper = await mount( - , + , ); await awaitForMyComponent(wrapper); - + expect(wrapper.find('.wazuh-outdated-agents-panel').exists()).toBeTruthy(); expect(wrapper.find(EuiButtonEmpty).exists()).not.toBeTruthy(); - + wrapper.find('.wazuh-outdated-agents-panel').simulate('click'); expect(wrapper.find(EuiLink).exists()).toBeTruthy(); expect(wrapper.find(EuiLink).prop('href')).toBe(documentationLink); }); - }); diff --git a/plugins/main/public/components/endpoints-summary/table/__snapshots__/agents-table.test.tsx.snap b/plugins/main/public/components/endpoints-summary/table/__snapshots__/agents-table.test.tsx.snap index 5f7489b92b..df6727b6ce 100644 --- a/plugins/main/public/components/endpoints-summary/table/__snapshots__/agents-table.test.tsx.snap +++ b/plugins/main/public/components/endpoints-summary/table/__snapshots__/agents-table.test.tsx.snap @@ -24,7 +24,7 @@ exports[`AgentsTable component Renders correctly to match the snapshot 1`] = ` class="euiFlexItem" >
+
+
+
+
+ + + Show only outdated + +
+
+
+
+
+
+
+
+ + + Show only outdated + +
+
+
+
+
+
+
+
+ + + Show only outdated + +
+
+
+
Date: Mon, 18 Mar 2024 13:44:21 -0300 Subject: [PATCH 20/31] Update agents-table unit tests --- .../endpoints-summary/endpoints-summary.tsx | 2 +- .../__snapshots__/agents-table.test.tsx.snap | 18 +++++------ .../table/agents-table.test.tsx | 30 ++++++------------- .../endpoints-summary/table/agents-table.tsx | 4 +-- 4 files changed, 21 insertions(+), 33 deletions(-) diff --git a/plugins/main/public/components/endpoints-summary/endpoints-summary.tsx b/plugins/main/public/components/endpoints-summary/endpoints-summary.tsx index 5bcff26533..7bd8d1cdfe 100644 --- a/plugins/main/public/components/endpoints-summary/endpoints-summary.tsx +++ b/plugins/main/public/components/endpoints-summary/endpoints-summary.tsx @@ -185,7 +185,7 @@ export const EndpointsSummary = compose( setExternalReload={this.setReload} showOnlyOutdated={this.state.showOnlyOutdatedAgents} setShowOnlyOutdated={this.setShowOnlyOutdatedAgents} - outdated={this.state.outdatedAgents} + totalOtdated={this.state.outdatedAgents} /> diff --git a/plugins/main/public/components/endpoints-summary/table/__snapshots__/agents-table.test.tsx.snap b/plugins/main/public/components/endpoints-summary/table/__snapshots__/agents-table.test.tsx.snap index df6727b6ce..39d6fc98dd 100644 --- a/plugins/main/public/components/endpoints-summary/table/__snapshots__/agents-table.test.tsx.snap +++ b/plugins/main/public/components/endpoints-summary/table/__snapshots__/agents-table.test.tsx.snap @@ -52,10 +52,10 @@ exports[`AgentsTable component Renders correctly to match the snapshot 1`] = ` > Show only outdated @@ -782,10 +782,10 @@ exports[`AgentsTable component Renders correctly to match the snapshot with cust > Show only outdated @@ -1472,10 +1472,10 @@ exports[`AgentsTable component Renders correctly to match the snapshot with no p > Show only outdated diff --git a/plugins/main/public/components/endpoints-summary/table/agents-table.test.tsx b/plugins/main/public/components/endpoints-summary/table/agents-table.test.tsx index 8977232ea8..eab37344e2 100644 --- a/plugins/main/public/components/endpoints-summary/table/agents-table.test.tsx +++ b/plugins/main/public/components/endpoints-summary/table/agents-table.test.tsx @@ -336,13 +336,9 @@ describe('AgentsTable component', () => { jest.fn()} - wzReq={WzRequest.apiReq} - addingNewAgent={() => jest.fn()} - downloadCsv={() => jest.fn()} - clickAction={() => jest.fn()} - formatUIDate={date => jest.fn()} - reload={() => jest.fn()} + showOnlyOutdated={false} + setShowOnlyOutdated={() => jest.fn()} + totalOtdated={0} /> , ); @@ -373,13 +369,9 @@ describe('AgentsTable component', () => { jest.fn()} - wzReq={WzRequest.apiReq} - addingNewAgent={() => jest.fn()} - downloadCsv={() => jest.fn()} - clickAction={() => jest.fn()} - formatUIDate={date => jest.fn()} - reload={() => jest.fn()} + showOnlyOutdated={false} + setShowOnlyOutdated={() => jest.fn()} + totalOtdated={0} /> , ); @@ -414,13 +406,9 @@ describe('AgentsTable component', () => { jest.fn()} - wzReq={WzRequest.apiReq} - addingNewAgent={() => jest.fn()} - downloadCsv={() => jest.fn()} - clickAction={() => jest.fn()} - formatUIDate={date => jest.fn()} - reload={() => jest.fn()} + showOnlyOutdated={false} + setShowOnlyOutdated={() => jest.fn()} + totalOtdated={0} /> , ); diff --git a/plugins/main/public/components/endpoints-summary/table/agents-table.tsx b/plugins/main/public/components/endpoints-summary/table/agents-table.tsx index 938e4c84fb..accf3c1705 100644 --- a/plugins/main/public/components/endpoints-summary/table/agents-table.tsx +++ b/plugins/main/public/components/endpoints-summary/table/agents-table.tsx @@ -70,7 +70,7 @@ interface AgentsTableProps { externalReload?: boolean; showOnlyOutdated: boolean; setShowOnlyOutdated: (newValue: boolean) => void; - outdated?: number; + totalOutdated?: number; setExternalReload?: (newValue: number) => void; } @@ -244,7 +244,7 @@ export const AgentsTable = compose( props.setShowOnlyOutdated(!props.showOnlyOutdated)} /> From bbbf5825d64ad67c7fc81ef6068826b929c17633 Mon Sep 17 00:00:00 2001 From: Luciano Gorza Date: Mon, 18 Mar 2024 13:59:02 -0300 Subject: [PATCH 21/31] Minor fixes --- .../endpoints-summary/endpoints-summary.tsx | 2 +- .../__snapshots__/agents-table.test.tsx.snap | 18 +++++++++--------- .../table/agents-table.test.tsx | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/plugins/main/public/components/endpoints-summary/endpoints-summary.tsx b/plugins/main/public/components/endpoints-summary/endpoints-summary.tsx index 7bd8d1cdfe..93cd72a3a4 100644 --- a/plugins/main/public/components/endpoints-summary/endpoints-summary.tsx +++ b/plugins/main/public/components/endpoints-summary/endpoints-summary.tsx @@ -185,7 +185,7 @@ export const EndpointsSummary = compose( setExternalReload={this.setReload} showOnlyOutdated={this.state.showOnlyOutdatedAgents} setShowOnlyOutdated={this.setShowOnlyOutdatedAgents} - totalOtdated={this.state.outdatedAgents} + totalOutdated={this.state.outdatedAgents} /> diff --git a/plugins/main/public/components/endpoints-summary/table/__snapshots__/agents-table.test.tsx.snap b/plugins/main/public/components/endpoints-summary/table/__snapshots__/agents-table.test.tsx.snap index 39d6fc98dd..8b5887a715 100644 --- a/plugins/main/public/components/endpoints-summary/table/__snapshots__/agents-table.test.tsx.snap +++ b/plugins/main/public/components/endpoints-summary/table/__snapshots__/agents-table.test.tsx.snap @@ -52,10 +52,10 @@ exports[`AgentsTable component Renders correctly to match the snapshot 1`] = ` > Show only outdated @@ -782,10 +782,10 @@ exports[`AgentsTable component Renders correctly to match the snapshot with cust > Show only outdated @@ -1472,10 +1472,10 @@ exports[`AgentsTable component Renders correctly to match the snapshot with no p > Show only outdated diff --git a/plugins/main/public/components/endpoints-summary/table/agents-table.test.tsx b/plugins/main/public/components/endpoints-summary/table/agents-table.test.tsx index eab37344e2..584aed1c56 100644 --- a/plugins/main/public/components/endpoints-summary/table/agents-table.test.tsx +++ b/plugins/main/public/components/endpoints-summary/table/agents-table.test.tsx @@ -338,7 +338,7 @@ describe('AgentsTable component', () => { filters={[]} showOnlyOutdated={false} setShowOnlyOutdated={() => jest.fn()} - totalOtdated={0} + totalOutdated={0} /> , ); @@ -371,7 +371,7 @@ describe('AgentsTable component', () => { filters={[]} showOnlyOutdated={false} setShowOnlyOutdated={() => jest.fn()} - totalOtdated={0} + totalOutdated={0} /> , ); @@ -408,7 +408,7 @@ describe('AgentsTable component', () => { filters={[]} showOnlyOutdated={false} setShowOnlyOutdated={() => jest.fn()} - totalOtdated={0} + totalOutdated={0} /> , ); From 7399515c1d923d17a091e7a06a776a3226c4c268 Mon Sep 17 00:00:00 2001 From: Luciano Gorza Date: Mon, 18 Mar 2024 14:27:07 -0300 Subject: [PATCH 22/31] Fix unit test snapshot --- .../__snapshots__/agents-table.test.tsx.snap | 18 +++++------ .../table/agents-table.test.tsx | 30 +++++++++++++++++++ 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/plugins/main/public/components/endpoints-summary/table/__snapshots__/agents-table.test.tsx.snap b/plugins/main/public/components/endpoints-summary/table/__snapshots__/agents-table.test.tsx.snap index 8b5887a715..36bda32149 100644 --- a/plugins/main/public/components/endpoints-summary/table/__snapshots__/agents-table.test.tsx.snap +++ b/plugins/main/public/components/endpoints-summary/table/__snapshots__/agents-table.test.tsx.snap @@ -52,10 +52,10 @@ exports[`AgentsTable component Renders correctly to match the snapshot 1`] = ` > Show only outdated @@ -782,10 +782,10 @@ exports[`AgentsTable component Renders correctly to match the snapshot with cust > Show only outdated @@ -1472,10 +1472,10 @@ exports[`AgentsTable component Renders correctly to match the snapshot with no p > Show only outdated diff --git a/plugins/main/public/components/endpoints-summary/table/agents-table.test.tsx b/plugins/main/public/components/endpoints-summary/table/agents-table.test.tsx index 584aed1c56..1f613222eb 100644 --- a/plugins/main/public/components/endpoints-summary/table/agents-table.test.tsx +++ b/plugins/main/public/components/endpoints-summary/table/agents-table.test.tsx @@ -347,6 +347,16 @@ describe('AgentsTable component', () => { const tableId = '__table_d203a723-1198-11ee-ab9b-75fc624fc672'; wrapper.find('table')[0]['attribs']['id'] = tableId; + // Set switch id to avoid snapshot changes + const switchButtonId = + '_show_outdated_switch_button_ic14ef503-e547-11ee-ac6e-71376e7e3fc5'; + wrapper.find('.euiSwitch__button')[0]['attribs']['aria-labelledby'] = + switchButtonId; + wrapper.find('.euiSwitch__button')[0]['attribs']['id'] = switchButtonId; + const switchLabelId = + '_show_outdated_switch_button_ic14ef503-e547-11ee-ac6e-71376e7e3fc5'; + wrapper.find('.euiSwitch__label')[0]['attribs']['id'] = switchLabelId; + // Set select all checkbox id to avoid snapshot changes const checkBoxSelectId = '_selection_column-checkbox_i6bf14741-d0fa-11ee-81c4-29d002524ab5'; @@ -380,6 +390,16 @@ describe('AgentsTable component', () => { const tableId = '__table_d203a723-1198-11ee-ab9b-75fc624fc672'; wrapper.find('table')[0]['attribs']['id'] = tableId; + // Set switch id to avoid snapshot changes + const switchButtonId = + '_show_outdated_switch_button_ic14ef503-e547-11ee-ac6e-71376e7e3fc5'; + wrapper.find('.euiSwitch__button')[0]['attribs']['aria-labelledby'] = + switchButtonId; + wrapper.find('.euiSwitch__button')[0]['attribs']['id'] = switchButtonId; + const switchLabelId = + '_show_outdated_switch_button_ic14ef503-e547-11ee-ac6e-71376e7e3fc5'; + wrapper.find('.euiSwitch__label')[0]['attribs']['id'] = switchLabelId; + // Set select all checkbox id to avoid snapshot changes const checkBoxSelectId = '_selection_column-checkbox_i6bf14741-d0fa-11ee-81c4-29d002524ab5'; @@ -417,6 +437,16 @@ describe('AgentsTable component', () => { const tableId = '__table_d203a723-1198-11ee-ab9b-75fc624fc672'; wrapper.find('table')[0]['attribs']['id'] = tableId; + // Set switch id to avoid snapshot changes + const switchButtonId = + '_show_outdated_switch_button_ic14ef503-e547-11ee-ac6e-71376e7e3fc5'; + wrapper.find('.euiSwitch__button')[0]['attribs']['aria-labelledby'] = + switchButtonId; + wrapper.find('.euiSwitch__button')[0]['attribs']['id'] = switchButtonId; + const switchLabelId = + '_show_outdated_switch_button_ic14ef503-e547-11ee-ac6e-71376e7e3fc5'; + wrapper.find('.euiSwitch__label')[0]['attribs']['id'] = switchLabelId; + // Set select all checkbox id to avoid snapshot changes const checkBoxSelectId = '_selection_column-checkbox_i6bf14741-d0fa-11ee-81c4-29d002524ab5'; From 21d745085e5efa1e2541d4e8907f6dd8c7ecfcb4 Mon Sep 17 00:00:00 2001 From: Luciano Gorza Date: Mon, 18 Mar 2024 18:27:16 -0300 Subject: [PATCH 23/31] Change unknown with N/A for groups and os charts --- .../components/endpoints-summary/services/get-agents-by-os.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/main/public/components/endpoints-summary/services/get-agents-by-os.ts b/plugins/main/public/components/endpoints-summary/services/get-agents-by-os.ts index de43ea8bec..6ebda19084 100644 --- a/plugins/main/public/components/endpoints-summary/services/get-agents-by-os.ts +++ b/plugins/main/public/components/endpoints-summary/services/get-agents-by-os.ts @@ -20,7 +20,7 @@ export const getAgentsByOs = async () => { ); const groupedData: any[] = []; affected_items?.forEach((item: any, index: number) => { - const itemOsName = item?.os?.platform ?? 'unknown'; + const itemOsName = item?.os?.platform ?? 'N/A'; groupedData.push({ label: itemOsName, value: item.count ?? DEFAULT_COUNT, From 85f91bcb7864564ac3076dc55ec3a1371f4ec71c Mon Sep 17 00:00:00 2001 From: Luciano Gorza Date: Mon, 18 Mar 2024 18:31:23 -0300 Subject: [PATCH 24/31] Change unknown with N/A for groups and os charts --- .../public/components/endpoints-summary/endpoints-summary.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/main/public/components/endpoints-summary/endpoints-summary.tsx b/plugins/main/public/components/endpoints-summary/endpoints-summary.tsx index 93cd72a3a4..f28a2cd52f 100644 --- a/plugins/main/public/components/endpoints-summary/endpoints-summary.tsx +++ b/plugins/main/public/components/endpoints-summary/endpoints-summary.tsx @@ -140,7 +140,7 @@ export const EndpointsSummary = compose( filterAgentByOS(item: any) { const query = - item.label === 'unknown' + item.label === 'N/A' ? 'id!=000;os.name=null' : `id!=000;os.name~${item.label}`; this._isMount && @@ -151,7 +151,7 @@ export const EndpointsSummary = compose( filterAgentByGroup(item: any) { const query = - item.label === 'unknown' + item.label === 'N/A' ? 'id!=000;group=null' : `id!=000;group=${item.label}`; this._isMount && From 90c6e0fa5d0d3db87c00a026c9c4ab52f7672abd Mon Sep 17 00:00:00 2001 From: Luciano Gorza Date: Tue, 19 Mar 2024 10:45:35 -0300 Subject: [PATCH 25/31] Add tooltip when there are no selected agents --- .../components/outdated-agents-card.tsx | 2 +- .../table/global-actions/global-actions.tsx | 107 +++++++++++------- .../table/upgrade-task-details-modal.tsx | 24 +--- 3 files changed, 69 insertions(+), 64 deletions(-) diff --git a/plugins/main/public/components/endpoints-summary/dashboard/components/outdated-agents-card.tsx b/plugins/main/public/components/endpoints-summary/dashboard/components/outdated-agents-card.tsx index 2d556920ae..ceb83db2ef 100644 --- a/plugins/main/public/components/endpoints-summary/dashboard/components/outdated-agents-card.tsx +++ b/plugins/main/public/components/endpoints-summary/dashboard/components/outdated-agents-card.tsx @@ -54,7 +54,7 @@ const OutdatedAgentsCard = ({ {outdatedAgents === 1 ? 'Agent' : 'Agents'} } - titleColor='warning' + titleColor='subdued' isLoading={isLoading} titleSize='l' textAlign='center' diff --git a/plugins/main/public/components/endpoints-summary/table/global-actions/global-actions.tsx b/plugins/main/public/components/endpoints-summary/table/global-actions/global-actions.tsx index 78f4078758..4a0e1e89c5 100644 --- a/plugins/main/public/components/endpoints-summary/table/global-actions/global-actions.tsx +++ b/plugins/main/public/components/endpoints-summary/table/global-actions/global-actions.tsx @@ -5,6 +5,7 @@ import { EuiContextMenuPanel, EuiContextMenuItem, EuiHorizontalRule, + EuiToolTip, } from '@elastic/eui'; import { WzElementPermissions } from '../../../common/permissions/element'; import { Agent } from '../../types'; @@ -65,6 +66,18 @@ export const AgentsTableGlobalActions = ({ ? allAgentsCount : selectedAgents.length; + const selectAgentsTooltip = (content: React.ReactNode) => ( + + {content} + + ); + + const actions = { + addGroups: 'Add groups to agents', + removeGroups: 'Remove groups from agents', + upgrade: 'Upgrade agents', + }; + return ( <> - - - Add groups to agents - {totalAgents ? ` (${totalAgents})` : ''} - - + {allowEditGroups && !totalAgents ? ( + selectAgentsTooltip(actions.addGroups) + ) : ( + + + {actions.addGroups} + {totalAgents ? ` (${totalAgents})` : ''} + + + )} { setAddOrRemoveGroups('remove'); closePopover(); setIsEditGroupsVisible(true); }} > - - - Remove groups from agents - {totalAgents ? ` (${totalAgents})` : ''} - - + {allowEditGroups && !totalAgents ? ( + selectAgentsTooltip(actions.removeGroups) + ) : ( + + + {actions.removeGroups} + {totalAgents ? ` (${totalAgents})` : ''} + + + )} { closePopover(); setIsUpgradeAgentsVisible(true); }} > - - - Upgrade agents - {totalAgents ? ` (${totalAgents})` : ''} - - + {allowUpgrade && !totalAgents ? ( + selectAgentsTooltip(actions.upgrade) + ) : ( + + + {actions.upgrade} + {totalAgents ? ` (${totalAgents})` : ''} + + + )} - Create{' '} - - - ), + name: 'Create', width: '230px', sortable: true, searchable: false, @@ -83,17 +73,7 @@ export const AgentUpgradesTaskDetailsModal = ({ }, { field: 'last_update_time', - name: ( - - Last update{' '} - - - ), + name: 'Last update', width: '230px', sortable: true, searchable: false, From d133a65c8442cccefae7665ea464022e966a106a Mon Sep 17 00:00:00 2001 From: Luciano Gorza Date: Tue, 19 Mar 2024 13:19:22 -0300 Subject: [PATCH 26/31] Fix IDs field name --- .../components/endpoints-summary/table/agents-table.tsx | 2 +- .../table/global-actions/edit-groups/result.tsx | 4 ++-- .../table/global-actions/upgrade/result.tsx | 8 ++++---- .../table/upgrade-task-details-modal.tsx | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/plugins/main/public/components/endpoints-summary/table/agents-table.tsx b/plugins/main/public/components/endpoints-summary/table/agents-table.tsx index accf3c1705..16c4fa7325 100644 --- a/plugins/main/public/components/endpoints-summary/table/agents-table.tsx +++ b/plugins/main/public/components/endpoints-summary/table/agents-table.tsx @@ -346,7 +346,7 @@ export const AgentsTable = compose( label: 'dateAdd', description: 'filter by registration date', }, - { label: 'id', description: 'filter by id' }, + { label: 'id', description: 'filter by ID' }, { label: 'ip', description: 'filter by IP address' }, { label: 'group', description: 'filter by group' }, { diff --git a/plugins/main/public/components/endpoints-summary/table/global-actions/edit-groups/result.tsx b/plugins/main/public/components/endpoints-summary/table/global-actions/edit-groups/result.tsx index 4058e70462..e9ae0e03d8 100644 --- a/plugins/main/public/components/endpoints-summary/table/global-actions/edit-groups/result.tsx +++ b/plugins/main/public/components/endpoints-summary/table/global-actions/edit-groups/result.tsx @@ -41,7 +41,7 @@ export const EditAgentsGroupsModalResult = ({ columns={[ { field: 'id', - name: 'Id', + name: 'ID', align: 'left', sortable: true, }, @@ -88,7 +88,7 @@ export const EditAgentsGroupsModalResult = ({ }, { field: 'id', - name: 'Agent Ids', + name: 'Agent IDs', align: 'left', render: ids => ids.join(', '), }, diff --git a/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/result.tsx b/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/result.tsx index c2e5d10918..dd163b1d71 100644 --- a/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/result.tsx +++ b/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/result.tsx @@ -44,7 +44,7 @@ export const UpgradeAgentsModalResult = ({ columns={[ { field: 'id', - name: 'Id', + name: 'ID', align: 'left', sortable: true, }, @@ -72,7 +72,7 @@ export const UpgradeAgentsModalResult = ({ columns={[ { field: 'agent', - name: 'Agent id', + name: 'Agent ID', align: 'left', sortable: true, }, @@ -90,7 +90,7 @@ export const UpgradeAgentsModalResult = ({ }, { field: 'task_id', - name: 'task id', + name: 'Task ID', align: 'left', sortable: true, }, @@ -131,7 +131,7 @@ export const UpgradeAgentsModalResult = ({ }, { field: 'id', - name: 'Agent Ids', + name: 'Agent IDs', align: 'left', render: ids => ids.join(', '), }, diff --git a/plugins/main/public/components/endpoints-summary/table/upgrade-task-details-modal.tsx b/plugins/main/public/components/endpoints-summary/table/upgrade-task-details-modal.tsx index 765d934dd2..46cab13394 100644 --- a/plugins/main/public/components/endpoints-summary/table/upgrade-task-details-modal.tsx +++ b/plugins/main/public/components/endpoints-summary/table/upgrade-task-details-modal.tsx @@ -48,7 +48,7 @@ export const AgentUpgradesTaskDetailsModal = ({ tableColumns={[ { field: 'task_id', - name: 'Task id', + name: 'Task ID', sortable: true, searchable: true, show: true, @@ -56,7 +56,7 @@ export const AgentUpgradesTaskDetailsModal = ({ }, { field: 'agent_id', - name: 'Agent id', + name: 'Agent ID', sortable: true, searchable: true, show: true, @@ -131,7 +131,7 @@ export const AgentUpgradesTaskDetailsModal = ({ return [ { label: 'agent_id', - description: 'filter by agent id', + description: 'filter by agent ID', }, { label: 'status', description: 'filter by status' }, { @@ -142,7 +142,7 @@ export const AgentUpgradesTaskDetailsModal = ({ label: 'last_update_time', description: 'filter by last update date', }, - { label: 'task_id', description: 'filter by task id' }, + { label: 'task_id', description: 'filter by task ID' }, ]; }, value: async (currentValue, { field }) => { From 0613bac8f222547cd7a175ab0ad194bd2d25423c Mon Sep 17 00:00:00 2001 From: Luciano Gorza Date: Tue, 19 Mar 2024 13:57:03 -0300 Subject: [PATCH 27/31] Fix result paginations --- .../table/global-actions/edit-groups/result.tsx | 8 ++++---- .../table/global-actions/upgrade/result.tsx | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/plugins/main/public/components/endpoints-summary/table/global-actions/edit-groups/result.tsx b/plugins/main/public/components/endpoints-summary/table/global-actions/edit-groups/result.tsx index e9ae0e03d8..9707051977 100644 --- a/plugins/main/public/components/endpoints-summary/table/global-actions/edit-groups/result.tsx +++ b/plugins/main/public/components/endpoints-summary/table/global-actions/edit-groups/result.tsx @@ -41,7 +41,7 @@ export const EditAgentsGroupsModalResult = ({ columns={[ { field: 'id', - name: 'ID', + name: 'Id', align: 'left', sortable: true, }, @@ -52,7 +52,7 @@ export const EditAgentsGroupsModalResult = ({ sortable: true, }, ]} - pagination={agents.length > 10} + pagination={true} sorting={{ sort: { field: 'id', @@ -88,12 +88,12 @@ export const EditAgentsGroupsModalResult = ({ }, { field: 'id', - name: 'Agent IDs', + name: 'Agent Ids', align: 'left', render: ids => ids.join(', '), }, ]} - pagination={errors.length > 10} + pagination={true} /> ); diff --git a/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/result.tsx b/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/result.tsx index dd163b1d71..1208c2ed2f 100644 --- a/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/result.tsx +++ b/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/result.tsx @@ -44,7 +44,7 @@ export const UpgradeAgentsModalResult = ({ columns={[ { field: 'id', - name: 'ID', + name: 'Id', align: 'left', sortable: true, }, @@ -55,7 +55,7 @@ export const UpgradeAgentsModalResult = ({ sortable: true, }, ]} - pagination={agents.length > 10} + pagination={true} sorting={{ sort: { field: 'id', @@ -72,7 +72,7 @@ export const UpgradeAgentsModalResult = ({ columns={[ { field: 'agent', - name: 'Agent ID', + name: 'Agent id', align: 'left', sortable: true, }, @@ -90,12 +90,12 @@ export const UpgradeAgentsModalResult = ({ }, { field: 'task_id', - name: 'Task ID', + name: 'task id', align: 'left', sortable: true, }, ]} - pagination={tasks.length > 10} + pagination={true} sorting={{ sort: { field: 'agent', @@ -131,12 +131,12 @@ export const UpgradeAgentsModalResult = ({ }, { field: 'id', - name: 'Agent IDs', + name: 'Agent Ids', align: 'left', render: ids => ids.join(', '), }, ]} - pagination={errors.length > 10} + pagination={true} /> ); From 301280782de229c006a594589b104bb0f5a3c900 Mon Sep 17 00:00:00 2001 From: Luciano Gorza Date: Tue, 19 Mar 2024 14:12:43 -0300 Subject: [PATCH 28/31] Fix IDs labels --- .../table/global-actions/edit-groups/result.tsx | 4 ++-- .../table/global-actions/upgrade/result.tsx | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/main/public/components/endpoints-summary/table/global-actions/edit-groups/result.tsx b/plugins/main/public/components/endpoints-summary/table/global-actions/edit-groups/result.tsx index 9707051977..f6f42c7140 100644 --- a/plugins/main/public/components/endpoints-summary/table/global-actions/edit-groups/result.tsx +++ b/plugins/main/public/components/endpoints-summary/table/global-actions/edit-groups/result.tsx @@ -41,7 +41,7 @@ export const EditAgentsGroupsModalResult = ({ columns={[ { field: 'id', - name: 'Id', + name: 'ID', align: 'left', sortable: true, }, @@ -88,7 +88,7 @@ export const EditAgentsGroupsModalResult = ({ }, { field: 'id', - name: 'Agent Ids', + name: 'Agent IDs', align: 'left', render: ids => ids.join(', '), }, diff --git a/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/result.tsx b/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/result.tsx index 1208c2ed2f..de36806ffa 100644 --- a/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/result.tsx +++ b/plugins/main/public/components/endpoints-summary/table/global-actions/upgrade/result.tsx @@ -44,7 +44,7 @@ export const UpgradeAgentsModalResult = ({ columns={[ { field: 'id', - name: 'Id', + name: 'ID', align: 'left', sortable: true, }, @@ -72,7 +72,7 @@ export const UpgradeAgentsModalResult = ({ columns={[ { field: 'agent', - name: 'Agent id', + name: 'Agent ID', align: 'left', sortable: true, }, @@ -90,7 +90,7 @@ export const UpgradeAgentsModalResult = ({ }, { field: 'task_id', - name: 'task id', + name: 'Task ID', align: 'left', sortable: true, }, @@ -131,7 +131,7 @@ export const UpgradeAgentsModalResult = ({ }, { field: 'id', - name: 'Agent Ids', + name: 'Agent IDs', align: 'left', render: ids => ids.join(', '), }, From fc1ac7f2451e9bf21f3abfad9671b77896a34907 Mon Sep 17 00:00:00 2001 From: Luciano Gorza Date: Thu, 21 Mar 2024 14:40:58 -0300 Subject: [PATCH 29/31] Fix agents table global actions --- .../table/global-actions/global-actions.tsx | 42 ------------------- 1 file changed, 42 deletions(-) diff --git a/plugins/main/public/components/endpoints-summary/table/global-actions/global-actions.tsx b/plugins/main/public/components/endpoints-summary/table/global-actions/global-actions.tsx index d3b80d9bc3..4a0e1e89c5 100644 --- a/plugins/main/public/components/endpoints-summary/table/global-actions/global-actions.tsx +++ b/plugins/main/public/components/endpoints-summary/table/global-actions/global-actions.tsx @@ -190,48 +190,6 @@ export const AgentsTableGlobalActions = ({ Upgrade task details - - { - closePopover(); - setIsUpgradeAgentsVisible(true); - }} - > - - - Upgrade agents - {totalAgents ? ` (${totalAgents})` : ''} - - - - { - closePopover(); - setIsUpgradeTasksModalVisible(true); - }} - > - - Upgrade task details - - {isEditGroupsVisible ? ( From 16662a454141e5bc0c82e1bd3c6dfb1ea50fbc4b Mon Sep 17 00:00:00 2001 From: Luciano Gorza Date: Fri, 22 Mar 2024 11:40:38 -0300 Subject: [PATCH 30/31] Add tooltip to filter switch when there are no outdated agents --- .../endpoints-summary/endpoints-summary.tsx | 18 - .../__snapshots__/agents-table.test.tsx.snap | 352 +++++++++--------- .../table/agents-table.test.tsx | 82 +--- .../endpoints-summary/table/agents-table.tsx | 23 +- .../table/upgrade-task-details-modal.tsx | 24 +- .../agents-selection-table.js | 4 +- 6 files changed, 230 insertions(+), 273 deletions(-) diff --git a/plugins/main/public/components/endpoints-summary/endpoints-summary.tsx b/plugins/main/public/components/endpoints-summary/endpoints-summary.tsx index f28a2cd52f..46851138b5 100644 --- a/plugins/main/public/components/endpoints-summary/endpoints-summary.tsx +++ b/plugins/main/public/components/endpoints-summary/endpoints-summary.tsx @@ -15,10 +15,6 @@ import React, { Component } from 'react'; import { EuiPage, EuiFlexItem, EuiSpacer } from '@elastic/eui'; import { AgentsTable } from './table/agents-table'; import WzReduxProvider from '../../redux/wz-redux-provider'; -import { VisFactoryHandler } from '../../react-services/vis-factory-handler'; -import { AppState } from '../../react-services/app-state'; -import { FilterHandler } from '../../utils/filter-handler'; -import { TabVisualizations } from '../../factories/tab-visualizations'; import { WazuhConfig } from '../../react-services/wazuh-config'; import { withReduxProvider, @@ -103,20 +99,6 @@ export const EndpointsSummary = compose( async componentDidMount() { this._isMount = true; this.getOutdatedAgents(); - if (this.wazuhConfig.getConfig()['wazuh.monitoring.enabled']) { - const tabVisualizations = new TabVisualizations(); - tabVisualizations.removeAll(); - tabVisualizations.setTab('general'); - tabVisualizations.assign({ - general: 1, - }); - const filterHandler = new FilterHandler(AppState.getCurrentPattern()); - await VisFactoryHandler.buildOverviewVisualizations( - filterHandler, - 'general', - null, - ); - } } componentWillUnmount() { diff --git a/plugins/main/public/components/endpoints-summary/table/__snapshots__/agents-table.test.tsx.snap b/plugins/main/public/components/endpoints-summary/table/__snapshots__/agents-table.test.tsx.snap index 36bda32149..7964a54a8a 100644 --- a/plugins/main/public/components/endpoints-summary/table/__snapshots__/agents-table.test.tsx.snap +++ b/plugins/main/public/components/endpoints-summary/table/__snapshots__/agents-table.test.tsx.snap @@ -47,65 +47,69 @@ exports[`AgentsTable component Renders correctly to match the snapshot 1`] = `
-
- + + Show only outdated - - - Show only outdated - -
+
+
@@ -381,7 +385,7 @@ exports[`AgentsTable component Renders correctly to match the snapshot 1`] = ` aria-label="Select all rows" class="euiCheckbox__input" disabled="" - id="_selection_column-checkbox_i6bf14741-d0fa-11ee-81c4-29d002524ab5" + id="_selection_column-checkbox_htmlId" type="checkbox" />
@@ -443,7 +447,7 @@ exports[`AgentsTable component Renders correctly to match the snapshot 1`] = `
-
- + + Show only outdated - - - Show only outdated - -
+
+ @@ -1118,7 +1126,7 @@ exports[`AgentsTable component Renders correctly to match the snapshot with cust aria-label="Select all rows" class="euiCheckbox__input" disabled="" - id="_selection_column-checkbox_i6bf14741-d0fa-11ee-81c4-29d002524ab5" + id="_selection_column-checkbox_htmlId" type="checkbox" />
@@ -1181,7 +1189,7 @@ exports[`AgentsTable component Renders correctly to match the snapshot with cust
-
- + + Show only outdated - - - Show only outdated - -
+
+ @@ -1808,7 +1820,7 @@ exports[`AgentsTable component Renders correctly to match the snapshot with no p aria-label="Select all rows" class="euiCheckbox__input" disabled="" - id="_selection_column-checkbox_i6bf14741-d0fa-11ee-81c4-29d002524ab5" + id="_selection_column-checkbox_htmlId" type="checkbox" />
@@ -1871,7 +1883,7 @@ exports[`AgentsTable component Renders correctly to match the snapshot with no p
({ appStateReducers: state => state, })); +jest.mock( + '../../../../../../node_modules/@elastic/eui/lib/services/accessibility/html_id_generator', + () => ({ + htmlIdGenerator: () => () => 'htmlId', + }), +); + const permissionsStore = { appStateReducers: { userAccount: { @@ -343,31 +350,6 @@ describe('AgentsTable component', () => { , ); - // Set table id to avoid snapshot changes - const tableId = '__table_d203a723-1198-11ee-ab9b-75fc624fc672'; - wrapper.find('table')[0]['attribs']['id'] = tableId; - - // Set switch id to avoid snapshot changes - const switchButtonId = - '_show_outdated_switch_button_ic14ef503-e547-11ee-ac6e-71376e7e3fc5'; - wrapper.find('.euiSwitch__button')[0]['attribs']['aria-labelledby'] = - switchButtonId; - wrapper.find('.euiSwitch__button')[0]['attribs']['id'] = switchButtonId; - const switchLabelId = - '_show_outdated_switch_button_ic14ef503-e547-11ee-ac6e-71376e7e3fc5'; - wrapper.find('.euiSwitch__label')[0]['attribs']['id'] = switchLabelId; - - // Set select all checkbox id to avoid snapshot changes - const checkBoxSelectId = - '_selection_column-checkbox_i6bf14741-d0fa-11ee-81c4-29d002524ab5'; - - //Mobile - wrapper.find('.euiCheckbox__input')[0]['attribs']['id'] = checkBoxSelectId; - wrapper.find('.euiCheckbox__label')[0]['attribs']['for'] = checkBoxSelectId; - - //Desktop - wrapper.find('.euiCheckbox__input')[1]['attribs']['id'] = checkBoxSelectId; - expect(wrapper).toMatchSnapshot(); expect( window.localStorage.getItem('wz-agents-overview-table-visible-fields'), @@ -386,31 +368,6 @@ describe('AgentsTable component', () => { , ); - // Set table id to avoid snapshot changes - const tableId = '__table_d203a723-1198-11ee-ab9b-75fc624fc672'; - wrapper.find('table')[0]['attribs']['id'] = tableId; - - // Set switch id to avoid snapshot changes - const switchButtonId = - '_show_outdated_switch_button_ic14ef503-e547-11ee-ac6e-71376e7e3fc5'; - wrapper.find('.euiSwitch__button')[0]['attribs']['aria-labelledby'] = - switchButtonId; - wrapper.find('.euiSwitch__button')[0]['attribs']['id'] = switchButtonId; - const switchLabelId = - '_show_outdated_switch_button_ic14ef503-e547-11ee-ac6e-71376e7e3fc5'; - wrapper.find('.euiSwitch__label')[0]['attribs']['id'] = switchLabelId; - - // Set select all checkbox id to avoid snapshot changes - const checkBoxSelectId = - '_selection_column-checkbox_i6bf14741-d0fa-11ee-81c4-29d002524ab5'; - - //Mobile - wrapper.find('.euiCheckbox__input')[0]['attribs']['id'] = checkBoxSelectId; - wrapper.find('.euiCheckbox__label')[0]['attribs']['for'] = checkBoxSelectId; - - //Desktop - wrapper.find('.euiCheckbox__input')[1]['attribs']['id'] = checkBoxSelectId; - expect(wrapper).toMatchSnapshot(); expect( window.localStorage.getItem('wz-agents-overview-table-visible-fields'), @@ -433,31 +390,6 @@ describe('AgentsTable component', () => { , ); - // Set table id to avoid snapshot changes - const tableId = '__table_d203a723-1198-11ee-ab9b-75fc624fc672'; - wrapper.find('table')[0]['attribs']['id'] = tableId; - - // Set switch id to avoid snapshot changes - const switchButtonId = - '_show_outdated_switch_button_ic14ef503-e547-11ee-ac6e-71376e7e3fc5'; - wrapper.find('.euiSwitch__button')[0]['attribs']['aria-labelledby'] = - switchButtonId; - wrapper.find('.euiSwitch__button')[0]['attribs']['id'] = switchButtonId; - const switchLabelId = - '_show_outdated_switch_button_ic14ef503-e547-11ee-ac6e-71376e7e3fc5'; - wrapper.find('.euiSwitch__label')[0]['attribs']['id'] = switchLabelId; - - // Set select all checkbox id to avoid snapshot changes - const checkBoxSelectId = - '_selection_column-checkbox_i6bf14741-d0fa-11ee-81c4-29d002524ab5'; - - //Mobile - wrapper.find('.euiCheckbox__input')[0]['attribs']['id'] = checkBoxSelectId; - wrapper.find('.euiCheckbox__label')[0]['attribs']['for'] = checkBoxSelectId; - - //Desktop - wrapper.find('.euiCheckbox__input')[1]['attribs']['id'] = checkBoxSelectId; - expect(wrapper).toMatchSnapshot(); expect( window.localStorage.getItem('wz-agents-overview-table-visible-fields'), diff --git a/plugins/main/public/components/endpoints-summary/table/agents-table.tsx b/plugins/main/public/components/endpoints-summary/table/agents-table.tsx index 16c4fa7325..1ccae446ce 100644 --- a/plugins/main/public/components/endpoints-summary/table/agents-table.tsx +++ b/plugins/main/public/components/endpoints-summary/table/agents-table.tsx @@ -19,6 +19,7 @@ import { EuiCallOut, EuiButton, EuiSwitch, + EuiToolTip, } from '@elastic/eui'; import { WzButtonPermissions } from '../../common/permissions/button'; import { withErrorBoundary } from '../../common/hocs'; @@ -211,6 +212,15 @@ export const AgentsTable = compose( ? agentList.totalItems : selectedItems.length; + const switchShowOnlyOutdated = ( + props.setShowOnlyOutdated(!props.showOnlyOutdated)} + /> + ); + const selectedtemsRenderer = ( {selectedItems.length ? ( @@ -241,12 +251,13 @@ export const AgentsTable = compose( ) : null} - props.setShowOnlyOutdated(!props.showOnlyOutdated)} - /> + {props.totalOutdated ? ( + switchShowOnlyOutdated + ) : ( + + {switchShowOnlyOutdated} + + )} ); diff --git a/plugins/main/public/components/endpoints-summary/table/upgrade-task-details-modal.tsx b/plugins/main/public/components/endpoints-summary/table/upgrade-task-details-modal.tsx index 46cab13394..63f16fd205 100644 --- a/plugins/main/public/components/endpoints-summary/table/upgrade-task-details-modal.tsx +++ b/plugins/main/public/components/endpoints-summary/table/upgrade-task-details-modal.tsx @@ -64,7 +64,17 @@ export const AgentUpgradesTaskDetailsModal = ({ }, { field: 'create_time', - name: 'Create', + name: ( + + Create{' '} + + + ), width: '230px', sortable: true, searchable: false, @@ -73,7 +83,17 @@ export const AgentUpgradesTaskDetailsModal = ({ }, { field: 'last_update_time', - name: 'Last update', + name: ( + + Last update{' '} + + + ), width: '230px', sortable: true, searchable: false, diff --git a/plugins/main/public/controllers/overview/components/overview-actions/agents-selection-table.js b/plugins/main/public/controllers/overview/components/overview-actions/agents-selection-table.js index 083782f380..149eae7f1b 100644 --- a/plugins/main/public/controllers/overview/components/overview-actions/agents-selection-table.js +++ b/plugins/main/public/controllers/overview/components/overview-actions/agents-selection-table.js @@ -186,7 +186,7 @@ export class AgentSelectionTable extends Component { {/* agent name (agent id) Unpin button right aligned, require justifyContent="flexEnd" in the EuiFlexGroup */} - + Date: Fri, 22 Mar 2024 12:40:47 -0300 Subject: [PATCH 31/31] Implement WzButton instead EuiSwitch plus EuiToolTip --- .../components/common/buttons/button.tsx | 51 ++++++++++--------- .../endpoints-summary/table/agents-table.tsx | 28 ++++------ 2 files changed, 37 insertions(+), 42 deletions(-) diff --git a/plugins/main/public/components/common/buttons/button.tsx b/plugins/main/public/components/common/buttons/button.tsx index a4ca9764f1..60e5143fc8 100644 --- a/plugins/main/public/components/common/buttons/button.tsx +++ b/plugins/main/public/components/common/buttons/button.tsx @@ -15,38 +15,39 @@ import { EuiButtonEmpty, EuiButtonIcon, EuiLink, - EuiToolTip + EuiToolTip, + EuiSwitch, } from '@elastic/eui'; -enum WzButtonType{ +enum WzButtonType { default = 'default', empty = 'empty', icon = 'icon', - link = 'link' + link = 'link', + switch = 'switch', } -interface WzButtonProps{ - buttonType?: WzButtonType - tooltip?: any - rest?: any -}; - -const WzButtons: {[key in WzButtonType]: React.FunctionComponent} = { - 'default': EuiButton, - 'empty': EuiButtonEmpty, - 'icon': EuiButtonIcon, - 'link': EuiLink, +interface WzButtonProps { + buttonType?: WzButtonType; + tooltip?: any; + rest?: any; } -export const WzButton = ({buttonType = WzButtonType.default, tooltip, ...rest}: WzButtonProps) => { +const WzButtons: { [key in WzButtonType]: React.FunctionComponent } = { + default: EuiButton, + empty: EuiButtonEmpty, + icon: EuiButtonIcon, + link: EuiLink, + switch: EuiSwitch, +}; + +export const WzButton = ({ + buttonType = WzButtonType.default, + tooltip, + ...rest +}: WzButtonProps) => { const Button = WzButtons[buttonType]; - - const button =