Skip to content

Commit

Permalink
The check update button does not show the date of the last scan (#6328)
Browse files Browse the repository at this point in the history
* Fix date of the last scan(check update)

* Fix menu overlapping with notification of updates

* Fix test

* Update changelog

* Use service

* Fix published date

* Fix test

---------

Co-authored-by: Federico Rodriguez <federico.rodriguez@wazuh.com>
  • Loading branch information
yenienserrano and asteriscos authored Jan 18, 2024
1 parent 21fa7f7 commit c4d8f1b
Show file tree
Hide file tree
Showing 15 changed files with 123 additions and 69 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ All notable changes to the Wazuh app project will be documented in this file.
### Added

- Support for Wazuh 4.8.0
- Added the ability to check if there are available updates from the UI. [#6093](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6093) [#6256](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6256)
- Added the ability to check if there are available updates from the UI. [#6093](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6093) [#6256](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6256) [#6328](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6328)
- Added remember server address check [#5791](https://github.com/wazuh/wazuh-dashboard-plugins/pull/5791)
- Added the ssl_agent_ca configuration to the SSL Settings form [#6083](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6083)
- Added global vulnerabilities dashboards [#5896](https://github.com/wazuh/wazuh-dashboard-plugins/pull/5896) [#6179](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6179) [#6173](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6173) [#6147](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6147) [#6231](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6231) [#6246](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6246) [#6321](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6321) [#6338] (https://github.com/wazuh/wazuh-dashboard-plugins/pull/6338)
Expand Down
5 changes: 3 additions & 2 deletions plugins/main/opensearch_dashboards.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"opensearchDashboardsReact",
"opensearchDashboardsUtils",
"opensearchDashboardsLegacy",
"wazuhCheckUpdates"
"wazuhCheckUpdates",
"wazuhCore"
],
"optionalPlugins": [
"security",
Expand All @@ -29,4 +30,4 @@
],
"server": true,
"ui": true
}
}
20 changes: 8 additions & 12 deletions plugins/main/public/components/settings/api/api-table.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,11 @@ import { compose } from 'redux';
import { UI_ERROR_SEVERITIES } from '../../../react-services/error-orchestrator/types';
import { UI_LOGGER_LEVELS } from '../../../../common/constants';
import { getErrorOrchestrator } from '../../../react-services/common-services';
import { getWazuhCheckUpdatesPlugin } from '../../../kibana-services';
import {
getWazuhCheckUpdatesPlugin,
getWazuhCorePlugin,
} from '../../../kibana-services';
import { AvailableUpdatesFlyout } from './available-updates-flyout';
import { formatUIDate } from '../../../react-services/time-service';

export const ApiTable = compose(
withErrorBoundary,
Expand All @@ -47,13 +49,10 @@ export const ApiTable = compose(
constructor(props) {
super(props);

const { getAvailableUpdates } = getWazuhCheckUpdatesPlugin();

this.state = {
apiEntries: [],
refreshingEntries: false,
availableUpdates: {},
getAvailableUpdates,
refreshingAvailableUpdates: true,
apiAvailableUpdateDetails: undefined,
};
Expand All @@ -62,9 +61,8 @@ export const ApiTable = compose(
async getApisAvailableUpdates(forceUpdate = false) {
try {
this.setState({ refreshingAvailableUpdates: true });
const availableUpdates = await this.state.getAvailableUpdates(
forceUpdate,
);
const availableUpdates =
await getWazuhCheckUpdatesPlugin().getAvailableUpdates(forceUpdate);
this.setState({ availableUpdates });
} catch (error) {
const options = {
Expand Down Expand Up @@ -553,10 +551,8 @@ export const ApiTable = compose(
title='Last check'
content={
this.state.availableUpdates?.last_check_date
? formatUIDate(
new Date(
this.state.availableUpdates.last_check_date,
),
? getWazuhCorePlugin().utils.formatUIDate(
this.state.availableUpdates.last_check_date,
)
: '-'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,29 @@ jest.mock(
'../../../../../../../node_modules/@elastic/eui/lib/services/accessibility/html_id_generator',
() => ({
htmlIdGenerator: () => () => 'htmlId',
})
}),
);

jest.mock('../../../../react-services/time-service', () => ({
formatUIDate: jest.fn().mockReturnValue('Sep 25, 2023 @ 14:03:40.816'),
jest.mock('../../../../kibana-services', () => ({
getWazuhCorePlugin: jest.fn().mockReturnValue({
utils: {
formatUIDate: jest.fn().mockReturnValue('Sep 25, 2023 @ 14:03:40.816'),
},
}),
}));

jest.mock('../../../../../../../src/plugins/opensearch_dashboards_react/public', () => ({
Markdown: jest.fn().mockReturnValue(<div>Description</div>),
}));
jest.mock(
'../../../../../../../src/plugins/opensearch_dashboards_react/public',
() => ({
Markdown: jest.fn().mockReturnValue(<div>Description</div>),
}),
);

describe('UpdateDetail component', () => {
test('should return the UpdateDetail component', async () => {
const { container, getByText, getByRole } = render(
<UpdateDetail
type="Last available minor"
type='Last available minor'
update={{
description:
'## Manager\r\n\r\n### Fixed\r\n\r\n- Fixed a crash when overwrite rules are triggered...',
Expand All @@ -35,7 +42,7 @@ describe('UpdateDetail component', () => {
tag: 'v4.8.0',
title: 'Wazuh v4.8.0',
}}
/>
/>,
);

expect(container).toMatchSnapshot();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React from 'react';
import { Update } from '../../../../../../wazuh-check-updates/common/types';
import { formatUIDate } from '../../../../react-services/time-service';
import { Markdown } from '../../../../../../../src/plugins/opensearch_dashboards_react/public';
import {
EuiAccordion,
Expand All @@ -12,6 +11,7 @@ import {
EuiBadge,
EuiTitle,
} from '@elastic/eui';
import { getWazuhCorePlugin } from '../../../../kibana-services';

interface UpdateDetailProps {
update: Partial<Update>;
Expand All @@ -25,7 +25,9 @@ export const UpdateDetail = ({ update, type }: UpdateDetailProps) => {
semver?.major &&
(semver?.minor || semver?.minor === 0) &&
(semver?.patch || semver?.patch === 0);
const minorVersion = hasVersions ? `${semver.major}.${semver.minor}` : undefined;
const minorVersion = hasVersions
? `${semver.major}.${semver.minor}`
: undefined;
const releaseNotesUrl = hasVersions
? `https://documentation.wazuh.com/current/release-notes/release-${semver.major}-${semver.minor}-${semver.patch}.html`
: undefined;
Expand All @@ -36,29 +38,30 @@ export const UpdateDetail = ({ update, type }: UpdateDetailProps) => {
return title && tag ? (
<EuiAccordion
id={tag}
className="euiAccordionForm"
buttonClassName="euiAccordionForm__button"
className='euiAccordionForm'
buttonClassName='euiAccordionForm__button'
buttonContent={
<EuiFlexGroup alignItems="center" responsive={false}>
<EuiFlexGroup alignItems='center' responsive={false}>
<EuiFlexItem grow={false}>
<EuiTitle size="s" className="euiAccordionForm__title">
<EuiTitle size='s' className='euiAccordionForm__title'>
<h3>{title}</h3>
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiBadge color="hollow">{type}</EuiBadge>
<EuiBadge color='hollow'>{type}</EuiBadge>
</EuiFlexItem>
</EuiFlexGroup>
}
paddingSize="l"
paddingSize='l'
>
{published_date ? (
<>
<EuiDescriptionList
listItems={[
{
title: 'Published',
description: formatUIDate(new Date(published_date)),
description:
getWazuhCorePlugin().utils.formatUIDate(published_date),
},
]}
/>
Expand All @@ -69,20 +72,22 @@ export const UpdateDetail = ({ update, type }: UpdateDetailProps) => {
<>
<EuiFlexGroup responsive={false} wrap>
<EuiFlexItem grow={false} style={{ maxWidth: 'max-content' }}>
<EuiLink href={releaseNotesUrl} target="_blank" external>
<EuiLink href={releaseNotesUrl} target='_blank' external>
Release notes
</EuiLink>
</EuiFlexItem>
<EuiFlexItem grow={false} style={{ maxWidth: 'max-content' }}>
<EuiLink href={upgradeGuideUrl} target="_blank" external>
<EuiLink href={upgradeGuideUrl} target='_blank' external>
Upgrade guide
</EuiLink>
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer />
</>
) : null}
{description ? <Markdown markdown={description} openLinksInNewTab /> : null}
{description ? (
<Markdown markdown={description} openLinksInNewTab />
) : null}
</EuiAccordion>
) : null;
};
2 changes: 2 additions & 0 deletions plugins/main/public/kibana-services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ export const [getWzCurrentAppID, setWzCurrentAppID] =
createGetterSetter<NavigationPublicPluginStart>('WzCurrentAppID');
export const [getWazuhCheckUpdatesPlugin, setWazuhCheckUpdatesPlugin] =
createGetterSetter<WazuhCheckUpdatesPluginStart>('WazuhCheckUpdatesPlugin');
export const [getWazuhCorePlugin, setWazuhCorePlugin] =
createGetterSetter<WazuhCheckUpdatesPluginStart>('WazuhCorePlugin');
export const [getHeaderActionMenuMounter, setHeaderActionMenuMounter] =
createGetterSetter<AppMountParameters['setHeaderActionMenu']>(
'headerActionMenuMounter',
Expand Down
2 changes: 2 additions & 0 deletions plugins/main/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
setWzCurrentAppID,
setWazuhCheckUpdatesPlugin,
setHeaderActionMenuMounter,
setWazuhCorePlugin,
} from './kibana-services';
import {
AppPluginStartDependencies,
Expand Down Expand Up @@ -225,6 +226,7 @@ export class WazuhPlugin
setOverlays(core.overlays);
setErrorOrchestrator(ErrorOrchestratorService);
setWazuhCheckUpdatesPlugin(plugins.wazuhCheckUpdates);
setWazuhCorePlugin(plugins.wazuhCore);
return {};
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
.euiBody--hasFlyout {
.wz-check-updates-bottom-bar {
margin-left: 320px;
}

&.euiBody-hasOverlayMask {
.wz-check-updates-bottom-bar {
margin-left: 0px;
}
}
}
.wz-check-updates-bottom-bar {
margin-left: 320px;
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ jest.mock('../plugin-services', () => ({
},
},
}),
getWazuhCore: jest.fn().mockReturnValue({
hooks: {
useDockedSideNav: () => false,
},
}),
}));

jest.mock('react-use/lib/useObservable', () => () => {});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import React, { useEffect, useState } from 'react';
import { FormattedMessage, I18nProvider } from '@osd/i18n/react';
import { useUserPreferences } from '../hooks';
import { areThereNewUpdates } from '../utils';
import { getCore } from '../plugin-services';
import { getCore, getWazuhCore } from '../plugin-services';
import { AvailableUpdates } from '../../../wazuh-check-updates/common/types';
import { getAvailableUpdates } from '../services';
import { RedirectAppLinks } from '../../../../src/plugins/opensearch_dashboards_react/public';
Expand All @@ -22,6 +22,8 @@ export const UpdatesNotification = () => {
const [isDismissed, setIsDismissed] = useState(false);
const [dismissFutureUpdates, setDismissFutureUpdates] = useState(false);

const sideNavDocked = getWazuhCore().hooks.useDockedSideNav();

const {
userPreferences,
error: userPreferencesError,
Expand Down Expand Up @@ -57,7 +59,7 @@ export const UpdatesNotification = () => {

const mustNotifyUser = areThereNewUpdates(
availableUpdates?.apis_available_updates,
userPreferences.last_dismissed_updates
userPreferences.last_dismissed_updates,
);

const handleOnChangeDismiss = (checked: boolean) => {
Expand All @@ -67,7 +69,7 @@ export const UpdatesNotification = () => {
const handleOnClose = () => {
updateUserPreferences({
last_dismissed_updates: availableUpdates?.apis_available_updates?.map(
(apiAvailableUpdates) => {
apiAvailableUpdates => {
const {
api_id,
last_available_major,
Expand All @@ -80,7 +82,7 @@ export const UpdatesNotification = () => {
last_minor: last_available_minor?.tag,
last_patch: last_available_patch?.tag,
};
}
},
),
...(dismissFutureUpdates ? { hide_update_notifications: true } : {}),
});
Expand All @@ -89,55 +91,66 @@ export const UpdatesNotification = () => {

return mustNotifyUser ? (
<I18nProvider>
<EuiBottomBar className="wz-check-updates-bottom-bar">
<EuiFlexGroup justifyContent="spaceBetween" alignItems="center" gutterSize="m">
<EuiBottomBar
className={sideNavDocked ? 'wz-check-updates-bottom-bar' : ''}
>
<EuiFlexGroup
justifyContent='spaceBetween'
alignItems='center'
gutterSize='m'
>
<EuiFlexItem grow={false}>
<EuiFlexGroup gutterSize="m" alignItems="center">
<EuiFlexGroup gutterSize='m' alignItems='center'>
<EuiFlexItem grow={false} style={{ maxWidth: 'max-content' }}>
<EuiText>
<FormattedMessage
id="wazuhCheckUpdates.updatesNotification.message"
defaultMessage="New release is available!"
id='wazuhCheckUpdates.updatesNotification.message'
defaultMessage='New release is available!'
/>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false} style={{ maxWidth: 'max-content' }}>
<RedirectAppLinks application={getCore().application}>
<EuiButtonEmpty
color="ghost"
color='ghost'
href={getCore().application.getUrlForApp('server-apis', {
path: '#/settings?tab=api',
})}
>
<FormattedMessage
id="wazuhCheckUpdates.updatesNotification.linkText"
defaultMessage="Go to the API configuration page for details"
id='wazuhCheckUpdates.updatesNotification.linkText'
defaultMessage='Go to the API configuration page for details'
/>
</EuiButtonEmpty>
</RedirectAppLinks>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiFlexGroup gutterSize="m" alignItems="center">
<EuiFlexGroup gutterSize='m' alignItems='center'>
<EuiFlexItem grow={false}>
<EuiCheckbox
id="check-dismiss-in-notification"
id='check-dismiss-in-notification'
label={
<FormattedMessage
id="wazuhCheckUpdates.updatesNotification.dismissCheckText"
defaultMessage="Disable updates notifications"
id='wazuhCheckUpdates.updatesNotification.dismissCheckText'
defaultMessage='Disable updates notifications'
/>
}
checked={dismissFutureUpdates}
onChange={(e) => handleOnChangeDismiss(e.target.checked)}
onChange={e => handleOnChangeDismiss(e.target.checked)}
/>
</EuiFlexItem>
<EuiFlexItem grow={false} style={{ maxWidth: 'max-content' }}>
<EuiButton fill size="s" iconType="cross" onClick={() => handleOnClose()}>
<EuiButton
fill
size='s'
iconType='cross'
onClick={() => handleOnClose()}
>
<FormattedMessage
id="wazuhCheckUpdates.updatesNotification.closeButtonText"
defaultMessage="Dismiss"
id='wazuhCheckUpdates.updatesNotification.closeButtonText'
defaultMessage='Dismiss'
/>
</EuiButton>
</EuiFlexItem>
Expand Down
1 change: 1 addition & 0 deletions plugins/wazuh-core/public/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { useDockedSideNav } from './use-docked-side-nav';
Loading

0 comments on commit c4d8f1b

Please sign in to comment.