diff --git a/x-pack/plugins/uptime/e2e/page_objects/monitor_management.tsx b/x-pack/plugins/uptime/e2e/page_objects/monitor_management.tsx
index fd877708f2bce..384242bc9af70 100644
--- a/x-pack/plugins/uptime/e2e/page_objects/monitor_management.tsx
+++ b/x-pack/plugins/uptime/e2e/page_objects/monitor_management.tsx
@@ -96,9 +96,8 @@ export function monitorManagementPageProvider({
},
async selectLocations({ locations }: { locations: string[] }) {
- await this.clickByTestSubj('syntheticsServiceLocationsComboBox');
for (let i = 0; i < locations.length; i++) {
- await page.click(`text=${locations[i]}`);
+ await page.check(`text=${locations[i]}`);
}
},
diff --git a/x-pack/plugins/uptime/e2e/page_objects/utils.tsx b/x-pack/plugins/uptime/e2e/page_objects/utils.tsx
index 072d4497e856d..024609e2f69ef 100644
--- a/x-pack/plugins/uptime/e2e/page_objects/utils.tsx
+++ b/x-pack/plugins/uptime/e2e/page_objects/utils.tsx
@@ -38,6 +38,10 @@ export function utilsPageProvider({ page }: { page: Page }) {
await page.selectOption(`[data-test-subj=${dataTestSubj}]`, value);
},
+ async checkByTestSubj(dataTestSubj: string, value: string) {
+ await page.check(`[data-test-subj=${dataTestSubj}]`);
+ },
+
async clickByTestSubj(dataTestSubj: string) {
await page.click(`[data-test-subj=${dataTestSubj}]`);
},
diff --git a/x-pack/plugins/uptime/public/components/monitor_management/monitor_config/locations.test.tsx b/x-pack/plugins/uptime/public/components/monitor_management/monitor_config/locations.test.tsx
index 11caf092c93c7..ccc3e7b619c68 100644
--- a/x-pack/plugins/uptime/public/components/monitor_management/monitor_config/locations.test.tsx
+++ b/x-pack/plugins/uptime/public/components/monitor_management/monitor_config/locations.test.tsx
@@ -8,8 +8,7 @@
import React from 'react';
import { screen } from '@testing-library/react';
import { render } from '../../../lib/helper/rtl_helpers';
-import { ServiceLocations, LOCATIONS_LABEL } from './locations';
-import userEvent from '@testing-library/user-event';
+import { ServiceLocations } from './locations';
describe('', () => {
const setLocations = jest.fn();
@@ -52,47 +51,7 @@ describe('', () => {
{ state }
);
- expect(screen.getByText(LOCATIONS_LABEL)).toBeInTheDocument();
- expect(screen.queryByText('US Central')).not.toBeInTheDocument();
- });
-
- it('shows location options when clicked', async () => {
- render(
- ,
- { state }
- );
-
- userEvent.click(screen.getByRole('button'));
-
- expect(screen.getByText('US Central')).toBeInTheDocument();
- });
-
- it('prevents bad inputs', async () => {
- render(
- ,
- { state }
- );
-
- userEvent.click(screen.getByRole('button'));
- userEvent.type(screen.getByRole('textbox'), 'fake location');
-
- expect(screen.getByText("doesn't match any options")).toBeInTheDocument();
-
- userEvent.keyboard(`{enter}`);
-
- expect(screen.getByText('"fake location" is not a valid option')).toBeInTheDocument();
- });
-
- it('calls setLocations', async () => {
- render(
- ,
- { state }
- );
-
- userEvent.click(screen.getByRole('button'));
- userEvent.click(screen.getByText('US Central'));
-
- expect(setLocations).toBeCalledWith([location]);
+ expect(screen.queryByText('US Central')).toBeInTheDocument();
});
it('shows invalid error', async () => {
diff --git a/x-pack/plugins/uptime/public/components/monitor_management/monitor_config/locations.tsx b/x-pack/plugins/uptime/public/components/monitor_management/monitor_config/locations.tsx
index 2d261e169299a..1877cc4ade126 100644
--- a/x-pack/plugins/uptime/public/components/monitor_management/monitor_config/locations.tsx
+++ b/x-pack/plugins/uptime/public/components/monitor_management/monitor_config/locations.tsx
@@ -5,10 +5,10 @@
* 2.0.
*/
-import React, { useState } from 'react';
+import React, { useState, useEffect } from 'react';
import { useSelector } from 'react-redux';
import { i18n } from '@kbn/i18n';
-import { EuiComboBox, EuiComboBoxOptionOption, EuiFormRow } from '@elastic/eui';
+import { EuiCheckboxGroup, EuiFormRow } from '@elastic/eui';
import { monitorManagementListSelector } from '../../../state/selectors';
import { ServiceLocation } from '../../../../common/runtime_types';
@@ -20,51 +20,49 @@ interface Props {
export const ServiceLocations = ({ selectedLocations, setLocations, isInvalid }: Props) => {
const [error, setError] = useState(null);
+ const [checkboxIdToSelectedMap, setCheckboxIdToSelectedMap] = useState>(
+ {}
+ );
const { locations } = useSelector(monitorManagementListSelector);
- const onLocationChange = (
- selectedLocationOptions: Array>
- ) => {
- setLocations(selectedLocationOptions as ServiceLocation[]);
- setError(null);
- };
-
- const onSearchChange = (value: string, hasMatchingOptions?: boolean) => {
- setError(value.length === 0 || hasMatchingOptions ? null : getInvalidOptionError(value));
- };
-
- const onBlur = (event: unknown) => {
- const inputElement = (event as FocusEvent)?.target as HTMLInputElement;
- if (inputElement) {
- const { value } = inputElement;
- setError(value.length === 0 ? null : getInvalidOptionError(value));
+ const onLocationChange = (optionId: string) => {
+ const isSelected = !checkboxIdToSelectedMap[optionId];
+ const location = locations.find((loc) => loc.id === optionId);
+ if (isSelected) {
+ setLocations((prevLocations) => (location ? [...prevLocations, location] : prevLocations));
+ } else {
+ setLocations((prevLocations) => [...prevLocations].filter((loc) => loc.id !== optionId));
}
+ setError(null);
};
const errorMessage = error ?? (isInvalid ? VALIDATION_ERROR : null);
+ useEffect(() => {
+ const newCheckboxIdToSelectedMap = selectedLocations.reduce>(
+ (acc, location) => {
+ acc[location.id] = true;
+ return acc;
+ },
+ {}
+ );
+ setCheckboxIdToSelectedMap(newCheckboxIdToSelectedMap);
+ }, [selectedLocations]);
+
return (
- ({
+ ...location,
+ 'data-test-subj': `syntheticsServiceLocation--${location.id}`,
+ }))}
+ idToSelectedMap={checkboxIdToSelectedMap}
+ onChange={(id) => onLocationChange(id)}
/>
);
};
-const PLACEHOLDER_LABEL = i18n.translate(
- 'xpack.uptime.monitorManagement.serviceLocationsPlaceholderLabel',
- {
- defaultMessage: 'Select one or more locations to run your monitor.',
- }
-);
-
const VALIDATION_ERROR = i18n.translate(
'xpack.uptime.monitorManagement.serviceLocationsValidationError',
{
@@ -72,14 +70,6 @@ const VALIDATION_ERROR = i18n.translate(
}
);
-const getInvalidOptionError = (value: string) =>
- i18n.translate('xpack.uptime.monitorManagement.serviceLocationsOptionError', {
- defaultMessage: '"{value}" is not a valid option',
- values: {
- value,
- },
- });
-
export const LOCATIONS_LABEL = i18n.translate(
'xpack.uptime.monitorManagement.monitorLocationsLabel',
{