Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion x-pack/plugins/fleet/cypress/e2e/agents/agent_list.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ describe('View agents list', () => {
deleteAgentDocs(true);
cleanupAgentPolicies();
setupFleetServer();
setUISettings('hideAgentActivityTour', true);
setUISettings('hideAnnouncements', true);

cy.getKibanaVersion().then((version) => {
docs = createAgentDocs(version);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,31 @@ import { EuiButtonEmpty, EuiText, EuiTourStep } from '@elastic/eui';
import React, { useEffect, useState } from 'react';
import { FormattedMessage } from '@kbn/i18n-react';

import type { TOUR_STORAGE_CONFIG } from '../../../../constants';
import { TOUR_STORAGE_KEYS } from '../../../../constants';
import { useStartServices } from '../../../../hooks';

export const AgentActivityButton: React.FC<{
onClickAgentActivity: () => void;
showAgentActivityTour: { isOpen: boolean };
}> = ({ onClickAgentActivity, showAgentActivityTour }) => {
const { uiSettings } = useStartServices();
const { storage, uiSettings } = useStartServices();

const [agentActivityTourState, setAgentActivityTourState] = useState(showAgentActivityTour);

const isTourHidden = uiSettings.get('hideAgentActivityTour', false);
const isTourHidden =
uiSettings.get('hideAnnouncements', false) ||
(
storage.get(TOUR_STORAGE_KEYS.AGENT_ACTIVITY) as
| TOUR_STORAGE_CONFIG['AGENT_ACTIVITY']
| undefined
)?.active === false;

const setTourAsHidden = () => uiSettings.set('hideAgentActivityTour', true);
const setTourAsHidden = () => {
storage.set(TOUR_STORAGE_KEYS.AGENT_ACTIVITY, {
active: false,
} as TOUR_STORAGE_CONFIG['AGENT_ACTIVITY']);
};

useEffect(() => {
setAgentActivityTourState(showAgentActivityTour);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,21 @@ import { __IntlProvider as IntlProvider } from '@kbn/i18n-react';
import { AgentStatusFilter } from './agent_status_filter';

const PARTIAL_TOUR_TEXT = 'Some agents have become inactive and have been hidden';
const mockStorage: Record<any, any> = {};

jest.mock('../../../../../../hooks', () => {
return {
useStartServices: jest.fn(() => ({
uiSettings: {
get: jest.fn(() => false),
},
storage: {
get: jest.fn((key) => mockStorage[key]),
set: jest.fn((key, val) => (mockStorage[key] = val)),
},
})),
};
});

const renderComponent = (props: React.ComponentProps<typeof AgentStatusFilter>) => {
return render(
Expand All @@ -20,18 +35,7 @@ const renderComponent = (props: React.ComponentProps<typeof AgentStatusFilter>)
);
};

const mockLocalStorage: Record<any, any> = {};
describe('AgentStatusFilter', () => {
beforeEach(() => {
Object.defineProperty(window, 'localStorage', {
value: {
getItem: jest.fn((key) => mockLocalStorage[key]),
setItem: jest.fn((key, val) => (mockLocalStorage[key] = val)),
},
writable: true,
});
});

it('Renders all statuses', () => {
const { getByText } = renderComponent({
selectedStatus: [],
Expand Down Expand Up @@ -70,12 +74,12 @@ describe('AgentStatusFilter', () => {

expect(getByText('999')).toBeInTheDocument();

expect(mockLocalStorage['fleet.inactiveAgentsCalloutHasBeenDismissed']).toBe('true');
expect(mockStorage['fleet.inactiveAgentsTour']).toEqual({ active: false });
});
});

it('Should not show tour if previously been dismissed', async () => {
mockLocalStorage['fleet.inactiveAgentsCalloutHasBeenDismissed'] = 'true';
mockStorage['fleet.inactiveAgentsTour'] = { active: false };

const { getByText } = renderComponent({
selectedStatus: [],
Expand All @@ -89,7 +93,7 @@ describe('AgentStatusFilter', () => {
});

it('Should should show difference between last seen inactive agents and total agents', async () => {
mockLocalStorage['fleet.lastSeenInactiveAgentsCount'] = '100';
mockStorage['fleet.lastSeenInactiveAgentsCount'] = '100';

const { getByText, getByTestId } = renderComponent({
selectedStatus: [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,31 @@

import { useState, useEffect } from 'react';

const LOCAL_STORAGE_KEY = 'fleet.inactiveAgentsCalloutHasBeenDismissed';
import type { TOUR_STORAGE_CONFIG } from '../../../../../../constants';
import { TOUR_STORAGE_KEYS } from '../../../../../../constants';
import { useStartServices } from '../../../../../../hooks';

export const useInactiveAgentsCalloutHasBeenDismissed = (): [boolean, (val: boolean) => void] => {
const { uiSettings, storage } = useStartServices();

const [inactiveAgentsCalloutHasBeenDismissed, setInactiveAgentsCalloutHasBeenDismissed] =
useState(false);

useEffect(() => {
const storageValue = localStorage.getItem(LOCAL_STORAGE_KEY);
if (storageValue) {
setInactiveAgentsCalloutHasBeenDismissed(Boolean(storageValue));
}
}, []);
setInactiveAgentsCalloutHasBeenDismissed(
uiSettings.get('hideAnnouncements', false) ||
(
storage.get(TOUR_STORAGE_KEYS.INACTIVE_AGENTS) as
| TOUR_STORAGE_CONFIG['INACTIVE_AGENTS']
| undefined
)?.active === false
);
}, [storage, uiSettings]);

const updateInactiveAgentsCalloutHasBeenDismissed = (newValue: boolean) => {
localStorage.setItem(LOCAL_STORAGE_KEY, newValue.toString());
storage.set(TOUR_STORAGE_KEYS.INACTIVE_AGENTS, {
active: false,
} as TOUR_STORAGE_CONFIG['INACTIVE_AGENTS']);
setInactiveAgentsCalloutHasBeenDismissed(newValue);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,22 @@

import { useState, useEffect } from 'react';

import { useStartServices } from '../../../../../../hooks';

const LOCAL_STORAGE_KEY = 'fleet.lastSeenInactiveAgentsCount';

export const useLastSeenInactiveAgentsCount = (): [number, (val: number) => void] => {
const { storage } = useStartServices();
const [lastSeenInactiveAgentsCount, setLastSeenInactiveAgentsCount] = useState(0);
useEffect(() => {
const storageValue = localStorage.getItem(LOCAL_STORAGE_KEY);
const storageValue = storage.get(LOCAL_STORAGE_KEY);
if (storageValue) {
setLastSeenInactiveAgentsCount(parseInt(storageValue, 10));
}
}, []);
}, [storage]);

const updateLastSeenInactiveAgentsCount = (inactiveAgents: number) => {
localStorage.setItem(LOCAL_STORAGE_KEY, inactiveAgents.toString());
storage.set(LOCAL_STORAGE_KEY, inactiveAgents.toString());
setLastSeenInactiveAgentsCount(inactiveAgents);
};

Expand Down
29 changes: 22 additions & 7 deletions x-pack/plugins/fleet/public/components/add_agent_help_popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import { useTheme } from 'styled-components';

import type { EuiTheme } from '@kbn/kibana-react-plugin/common';

import type { TOUR_STORAGE_CONFIG } from '../constants';
import { TOUR_STORAGE_KEYS } from '../constants';
import { useStartServices } from '../hooks';

export const AddAgentHelpPopover = ({
Expand All @@ -28,19 +30,31 @@ export const AddAgentHelpPopover = ({
offset?: number;
closePopover: NoArgCallback<void>;
}) => {
const { docLinks, uiSettings } = useStartServices();
const { docLinks, uiSettings, storage } = useStartServices();
const theme = useTheme() as EuiTheme;
const optionalProps: { offset?: number } = {};
const hideAnnouncements: boolean = useMemo(
() => uiSettings.get('hideAnnouncements'),
[uiSettings]
);
const hideAddAgentTour: boolean = useMemo(() => {
return (
uiSettings.get('hideAnnouncements', false) ||
(
storage.get(TOUR_STORAGE_KEYS.ADD_AGENT_POPOVER) as
| TOUR_STORAGE_CONFIG['ADD_AGENT_POPOVER']
| undefined
)?.active === false
);
}, [storage, uiSettings]);

const onFinish = () => {
storage.set(TOUR_STORAGE_KEYS.ADD_AGENT_POPOVER, {
active: false,
} as TOUR_STORAGE_CONFIG['ADD_AGENT_POPOVER']);
};

if (offset !== undefined) {
optionalProps.offset = offset; // offset being present in props sets it to 0 so only add if specified
}

return hideAnnouncements ? (
return hideAddAgentTour ? (
button
) : (
<EuiTourStep
Expand All @@ -67,7 +81,7 @@ export const AddAgentHelpPopover = ({
zIndex={theme.eui.euiZLevel1 - 1} // put popover behind any modals that happen to be open
isStepOpen={isOpen}
minWidth={300}
onFinish={() => {}}
onFinish={onFinish}
step={1}
stepsTotal={1}
title={
Expand All @@ -82,6 +96,7 @@ export const AddAgentHelpPopover = ({
footerAction={
<EuiLink
onClick={() => {
onFinish();
closePopover();
}}
>
Expand Down
18 changes: 18 additions & 0 deletions x-pack/plugins/fleet/public/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,21 @@ export const DURATION_APM_SETTINGS_VARS = {
TAIL_SAMPLING_INTERVAL: 'tail_sampling_interval',
WRITE_TIMEOUT: 'write_timeout',
};

export const TOUR_STORAGE_KEYS = {
AGENT_ACTIVITY: 'fleet.agentActivityTour',
ADD_AGENT_POPOVER: 'fleet.addAgentPopoverTour',
INACTIVE_AGENTS: 'fleet.inactiveAgentsTour',
};

export interface TOUR_STORAGE_CONFIG {
AGENT_ACTIVITY: {
active: boolean;
};
ADD_AGENT_POPOVER: {
active: boolean;
};
INACTIVE_AGENTS: {
active: boolean;
};
}