Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Uptime] Add basic ui monitor management table, basic monitor editing, and basic location selection #120038

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
477bc2d
add basic ui monitor management table
dominiqueclarke Nov 30, 2021
345bdca
Creating io-ts types for synthetics monitors.
awahab07 Dec 1, 2021
817ca34
add runtime types
dominiqueclarke Dec 1, 2021
bae54f0
adjust types in components
dominiqueclarke Dec 1, 2021
57d9a31
Merge github.com:awahab07/kibana into feature/ui-monitor-management-t…
dominiqueclarke Dec 1, 2021
38920a4
merge types branch
dominiqueclarke Dec 1, 2021
0c5fb14
add monitor editing and deleting
dominiqueclarke Dec 2, 2021
d8398c0
add management link
shahzad31 Dec 2, 2021
c07c535
add monitor btn
shahzad31 Dec 2, 2021
0ea58b3
Merge branch 'main' of github.com:elastic/kibana into feature/ui-moni…
shahzad31 Dec 2, 2021
15da066
fix conflicts
shahzad31 Dec 2, 2021
0b38f9a
fix conflicts
shahzad31 Dec 2, 2021
2bf2d1d
hide
shahzad31 Dec 2, 2021
97e214b
add tags component
dominiqueclarke Dec 2, 2021
249004d
merge master
dominiqueclarke Dec 2, 2021
7ec8895
add locations
dominiqueclarke Dec 3, 2021
aa046cc
add pagination
dominiqueclarke Dec 6, 2021
c2eb04c
adjust types
dominiqueclarke Dec 6, 2021
17ac5c1
merge master
dominiqueclarke Dec 6, 2021
3f844f3
add unit tests
dominiqueclarke Dec 7, 2021
4abe36d
update tests
dominiqueclarke Dec 7, 2021
9bed87c
adjust types and i18n
dominiqueclarke Dec 8, 2021
abe0b3d
fix types
shahzad31 Dec 8, 2021
7cb6e78
eslint
shahzad31 Dec 8, 2021
c6cafb3
update i18n
dominiqueclarke Dec 8, 2021
8ca4162
merge master
dominiqueclarke Dec 8, 2021
33573de
update i18n
dominiqueclarke Dec 8, 2021
337c637
update monitor types
dominiqueclarke Dec 8, 2021
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: 2 additions & 0 deletions x-pack/plugins/uptime/common/constants/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ export const MONITOR_ADD_ROUTE = '/add-monitor';

export const MONITOR_EDIT_ROUTE = '/edit-monitor/:monitorId';

export const MONITOR_MANAGEMENT = '/manage-monitors';

export const OVERVIEW_ROUTE = '/';

export const SETTINGS_ROUTE = '/settings';
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/uptime/common/runtime_types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ export * from './monitor';
export * from './ping';
export * from './snapshot';
export * from './network_events';
export * from './monitor_management';
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export enum ConfigKey {
METADATA = '__ui',
MONITOR_TYPE = 'type',
NAME = 'name',
LOCATIONS = 'locations',
PARAMS = 'params',
PASSWORD = 'password',
PROXY_URL = 'proxy_url',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
* 2.0.
*/

export * from './state';
export * from './config_key';
export * from './monitor_configs';
export * from './monitor_meta_data';
export * from './monitor_types';
export * from './locations';
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import * as t from 'io-ts';

const LocationGeoCodec = t.interface({
lat: t.number,
lon: t.number,
});

export const ManifestLocationCodec = t.interface({
url: t.string,
geo: t.interface({
name: t.string,
location: LocationGeoCodec,
}),
status: t.string,
});

export const ServiceLocationCodec = t.interface({
id: t.string,
label: t.string,
geo: LocationGeoCodec,
url: t.string,
});

export const ServiceLocationsCodec = t.array(ServiceLocationCodec);

export type ServiceLocation = t.TypeOf<typeof ServiceLocationCodec>;
export type ServiceLocations = t.TypeOf<typeof ServiceLocationsCodec>;
export type ManifestLocation = t.TypeOf<typeof ManifestLocationCodec>;
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
} from './monitor_configs';
import { MetadataCodec } from './monitor_meta_data';
import { TLSVersionCodec, VerificationModeCodec } from './monitor_configs';
import { ServiceLocationsCodec } from './locations';

const Schedule = t.interface({
number: t.string,
Expand Down Expand Up @@ -53,6 +54,7 @@ export const CommonFieldsCodec = t.interface({
[ConfigKey.APM_SERVICE_NAME]: t.string,
[ConfigKey.TIMEOUT]: t.string,
[ConfigKey.TAGS]: t.array(t.string),
[ConfigKey.LOCATIONS]: ServiceLocationsCodec,
});

export type CommonFields = t.TypeOf<typeof CommonFieldsCodec>;
Expand Down Expand Up @@ -194,3 +196,20 @@ export const MonitorFieldsCodec = t.intersection([
]);

export type MonitorFields = t.TypeOf<typeof MonitorFieldsCodec>;

export const MonitorManagementListResultCodec = t.type({
monitors: t.array(t.interface({ id: t.string, attributes: MonitorFieldsCodec })),
page: t.number,
perPage: t.number,
total: t.union([t.number, t.null]),
});

export type MonitorManagementListResult = Omit<
t.TypeOf<typeof MonitorManagementListResultCodec>,
'monitors'
> & {
monitors: Array<{
id: string;
attributes: Partial<MonitorFields>;
}>;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import * as t from 'io-ts';

export const FetchMonitorManagementListQueryArgsType = t.partial({
page: t.number,
perPage: t.number,
});

export type FetchMonitorManagementListQueryArgs = t.TypeOf<
typeof FetchMonitorManagementListQueryArgsType
>;
32 changes: 2 additions & 30 deletions x-pack/plugins/uptime/common/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

import { SimpleSavedObject } from 'kibana/public';
import { MonitorFields } from '../runtime_types/monitor_management';

/** Represents the average monitor duration ms at a point in time. */
export interface MonitorDurationAveragePoint {
Expand All @@ -31,33 +32,4 @@ export interface MonitorIdParam {
monitorId: string;
}

export type SyntheticsMonitorSavedObject = SimpleSavedObject<{
name: string;
runOnce?: boolean;
urls?: string[];
tags?: string[];
locations: string[];
schedule: string;
type: 'http' | 'tcp' | 'icmp' | 'browser';
source?: {
inline: {
script: string;
};
};
}>;

interface LocationGeo {
lat: number;
lon: number;
}

export interface ManifestLocation {
url: string;
geo: {
name: string;
location: LocationGeo;
};
status: string;
}

export type ServiceLocations = Array<{ id: string; label: string; geo: LocationGeo; url: string }>;
export type SyntheticsMonitorSavedObject = SimpleSavedObject<MonitorFields>;
5 changes: 4 additions & 1 deletion x-pack/plugins/uptime/public/apps/uptime_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,10 @@ const Application = (props: UptimeAppProps) => {
<InspectorContextProvider>
<UptimeAlertsFlyoutWrapper />
<PageRouter config={config} />
<ActionMenu appMountParameters={appMountParameters} />
<ActionMenu
appMountParameters={appMountParameters}
config={config}
/>
</InspectorContextProvider>
</RedirectAppLinks>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,16 @@ import React from 'react';
import { HeaderMenuPortal } from '../../../../../observability/public';
import { AppMountParameters } from '../../../../../../../src/core/public';
import { ActionMenuContent } from './action_menu_content';
import { UptimeConfig } from '../../../../common/config';

export const ActionMenu = ({ appMountParameters }: { appMountParameters: AppMountParameters }) => (
export const ActionMenu = ({
appMountParameters,
config,
}: {
appMountParameters: AppMountParameters;
config: UptimeConfig;
}) => (
<HeaderMenuPortal setHeaderActionMenu={appMountParameters.setHeaderActionMenu}>
<ActionMenuContent />
<ActionMenuContent config={config} />
</HeaderMenuPortal>
);
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { ActionMenuContent } from './action_menu_content';

describe('ActionMenuContent', () => {
it('renders alerts dropdown', async () => {
const { getByLabelText, getByText } = render(<ActionMenuContent />);
const { getByLabelText, getByText } = render(<ActionMenuContent config={{}} />);

const alertsDropdown = getByLabelText('Open alerts and rules context menu');
fireEvent.click(alertsDropdown);
Expand All @@ -24,15 +24,15 @@ describe('ActionMenuContent', () => {
});

it('renders settings link', () => {
const { getByRole, getByText } = render(<ActionMenuContent />);
const { getByRole, getByText } = render(<ActionMenuContent config={{}} />);

const settingsAnchor = getByRole('link', { name: 'Navigate to the Uptime settings page' });
expect(settingsAnchor.getAttribute('href')).toBe('/settings');
expect(getByText('Settings'));
});

it('renders exploratory view link', () => {
const { getByLabelText, getByText } = render(<ActionMenuContent />);
const { getByLabelText, getByText } = render(<ActionMenuContent config={{}} />);

const analyzeAnchor = getByLabelText(
'Navigate to the "Explore Data" view to visualize Synthetics/User data'
Expand All @@ -43,7 +43,7 @@ describe('ActionMenuContent', () => {
});

it('renders Add Data link', () => {
const { getByLabelText, getByText } = render(<ActionMenuContent />);
const { getByLabelText, getByText } = render(<ActionMenuContent config={{}} />);

const addDataAnchor = getByLabelText('Navigate to a tutorial about adding Uptime data');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'
import { useUptimeSettingsContext } from '../../../contexts/uptime_settings_context';
import { useGetUrlParams } from '../../../hooks';
import { ToggleAlertFlyoutButton } from '../../overview/alerts/alerts_containers';
import { SETTINGS_ROUTE } from '../../../../common/constants';
import { MONITOR_MANAGEMENT, SETTINGS_ROUTE } from '../../../../common/constants';
import { stringifyUrlParams } from '../../../lib/helper/stringify_url_params';
import { InspectorHeaderLink } from './inspector_header_link';
import { monitorStatusSelector } from '../../../state/selectors';
import { UptimeConfig } from '../../../../common/config';

const ADD_DATA_LABEL = i18n.translate('xpack.uptime.addDataButtonLabel', {
defaultMessage: 'Add data',
Expand All @@ -34,7 +35,7 @@ const ANALYZE_MESSAGE = i18n.translate('xpack.uptime.analyzeDataButtonLabel.mess
'Explore Data allows you to select and filter result data in any dimension and look for the cause or impact of performance problems.',
});

export function ActionMenuContent(): React.ReactElement {
export function ActionMenuContent({ config }: { config: UptimeConfig }): React.ReactElement {
const kibana = useKibana();
const { basePath } = useUptimeSettingsContext();
const params = useGetUrlParams();
Expand Down Expand Up @@ -68,6 +69,24 @@ export function ActionMenuContent(): React.ReactElement {

return (
<EuiHeaderLinks gutterSize="xs">
{config.ui?.unsafe?.monitorManagement?.enabled && (
<EuiHeaderLink
aria-label={i18n.translate('xpack.uptime.page_header.manageLink.label', {
defaultMessage: 'Navigate to the Uptime monitor management page',
})}
color="text"
data-test-subj="management-page-link"
href={history.createHref({
pathname: MONITOR_MANAGEMENT,
})}
>
<FormattedMessage
id="xpack.uptime.page_header.manageLink"
defaultMessage="Monitor management"
/>
</EuiHeaderLink>
)}

<EuiHeaderLink
aria-label={i18n.translate('xpack.uptime.page_header.settingsLink.label', {
defaultMessage: 'Navigate to the Uptime settings page',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ describe('<BrowserAdvancedFields />', () => {

const syntheticsArgs = getByLabelText('Synthetics args');
const screenshots = getByLabelText('Screenshot options') as HTMLInputElement;

expect(screenshots.value).toEqual(defaultConfig[ConfigKey.SCREENSHOTS]);
expect(syntheticsArgs).toBeInTheDocument();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { CommonFields, ConfigKey, ScheduleUnit, DataStream } from '../types';

export const defaultValues: CommonFields = {
[ConfigKey.MONITOR_TYPE]: DataStream.HTTP,
[ConfigKey.LOCATIONS]: [],
[ConfigKey.ENABLED]: true,
[ConfigKey.SCHEDULE]: {
number: '3',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export type CommonFormatMap = Record<keyof CommonFields | ConfigKey.NAME, Format

export const commonFormatters: CommonFormatMap = {
[ConfigKey.NAME]: null,
[ConfigKey.LOCATIONS]: null,
[ConfigKey.MONITOR_TYPE]: null,
[ConfigKey.ENABLED]: null,
[ConfigKey.SCHEDULE]: (fields) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export const commonNormalizers: CommonNormalizerMap = {
[ConfigKey.NAME]: (fields) => fields?.[ConfigKey.NAME]?.value ?? '',
[ConfigKey.ENABLED]: getCommonNormalizer(ConfigKey.ENABLED),
[ConfigKey.MONITOR_TYPE]: getCommonNormalizer(ConfigKey.MONITOR_TYPE),
[ConfigKey.LOCATIONS]: getCommonNormalizer(ConfigKey.LOCATIONS),
[ConfigKey.SCHEDULE]: (fields) => {
const value = fields?.[ConfigKey.SCHEDULE]?.value;
if (value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
*/

import React, { createContext, useContext, useMemo, useState } from 'react';
import { ServiceLocations } from '../../../../common/runtime_types/monitor_management';
import { DataStream } from '../types';

interface IPolicyConfigContext {
setMonitorType: React.Dispatch<React.SetStateAction<DataStream>>;
setName: React.Dispatch<React.SetStateAction<string>>;
setLocations: React.Dispatch<React.SetStateAction<string[]>>;
setLocations: React.Dispatch<React.SetStateAction<ServiceLocations>>;
setIsTLSEnabled: React.Dispatch<React.SetStateAction<boolean>>;
setIsZipUrlTLSEnabled: React.Dispatch<React.SetStateAction<boolean>>;
monitorType: DataStream;
Expand All @@ -23,17 +24,17 @@ interface IPolicyConfigContext {
isEditable?: boolean;
defaultName?: string;
name?: string;
defaultLocations?: string[];
locations?: string[];
defaultLocations?: ServiceLocations;
locations?: ServiceLocations;
}

interface IPolicyConfigContextProvider {
export interface IPolicyConfigContextProvider {
children: React.ReactNode;
defaultMonitorType?: DataStream;
defaultIsTLSEnabled?: boolean;
defaultIsZipUrlTLSEnabled?: boolean;
defaultName?: string;
defaultLocations?: string[];
defaultLocations?: ServiceLocations;
isEditable?: boolean;
}

Expand All @@ -46,7 +47,7 @@ const defaultContext: IPolicyConfigContext = {
setName: (_name: React.SetStateAction<string>) => {
throw new Error('setName was not initialized, set it when you invoke the context');
},
setLocations: (_locations: React.SetStateAction<string[]>) => {
setLocations: (_locations: React.SetStateAction<ServiceLocations>) => {
throw new Error('setLocations was not initialized, set it when you invoke the context');
},
setIsTLSEnabled: (_isTLSEnabled: React.SetStateAction<boolean>) => {
Expand Down Expand Up @@ -79,7 +80,7 @@ export function PolicyConfigContextProvider<ExtraFields = unknown>({
}: IPolicyConfigContextProvider) {
const [monitorType, setMonitorType] = useState<DataStream>(defaultMonitorType);
const [name, setName] = useState<string>(defaultName);
const [locations, setLocations] = useState<string[]>(defaultLocations);
const [locations, setLocations] = useState<ServiceLocations>(defaultLocations);
const [isTLSEnabled, setIsTLSEnabled] = useState<boolean>(defaultIsTLSEnabled);
const [isZipUrlTLSEnabled, setIsZipUrlTLSEnabled] = useState<boolean>(defaultIsZipUrlTLSEnabled);

Expand Down
Loading