mirror of
https://github.com/elastic/kibana.git
synced 2025-04-25 02:09:32 -04:00
[Synthetics] Status overview embeddable (#188807)
## Summary Added status overview embeddable !! https://github.com/user-attachments/assets/27499ecf-549f-43a6-a16b-22a44db36814 --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
bc42310da5
commit
eb71438b9c
45 changed files with 738 additions and 337 deletions
|
@ -17,6 +17,7 @@
|
||||||
"embeddable",
|
"embeddable",
|
||||||
"discover",
|
"discover",
|
||||||
"dataViews",
|
"dataViews",
|
||||||
|
"dashboard",
|
||||||
"encryptedSavedObjects",
|
"encryptedSavedObjects",
|
||||||
"exploratoryView",
|
"exploratoryView",
|
||||||
"features",
|
"features",
|
||||||
|
@ -31,7 +32,9 @@
|
||||||
"triggersActionsUi",
|
"triggersActionsUi",
|
||||||
"usageCollection",
|
"usageCollection",
|
||||||
"bfetch",
|
"bfetch",
|
||||||
"unifiedSearch"
|
"uiActions",
|
||||||
|
"unifiedSearch",
|
||||||
|
"presentationUtil"
|
||||||
],
|
],
|
||||||
"optionalPlugins": [
|
"optionalPlugins": [
|
||||||
"cloud",
|
"cloud",
|
||||||
|
@ -53,7 +56,7 @@
|
||||||
"observability",
|
"observability",
|
||||||
"spaces",
|
"spaces",
|
||||||
"indexLifecycleManagement",
|
"indexLifecycleManagement",
|
||||||
"unifiedDocViewer"
|
"unifiedDocViewer",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const SYNTHETICS_OVERVIEW_EMBEDDABLE = 'SYNTHETICS_OVERVIEW_EMBEDDABLE';
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* 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 { CoreSetup } from '@kbn/core-lifecycle-browser';
|
||||||
|
|
||||||
|
import { ADD_PANEL_TRIGGER } from '@kbn/ui-actions-browser/src';
|
||||||
|
import { createStatusOverviewPanelAction } from './ui_actions/create_overview_panel_action';
|
||||||
|
import { ClientPluginsSetup, ClientPluginsStart } from '../../plugin';
|
||||||
|
import { SYNTHETICS_OVERVIEW_EMBEDDABLE } from './constants';
|
||||||
|
|
||||||
|
export const registerSyntheticsEmbeddables = (
|
||||||
|
core: CoreSetup<ClientPluginsStart, unknown>,
|
||||||
|
pluginsSetup: ClientPluginsSetup
|
||||||
|
) => {
|
||||||
|
pluginsSetup.embeddable.registerReactEmbeddableFactory(
|
||||||
|
SYNTHETICS_OVERVIEW_EMBEDDABLE,
|
||||||
|
async () => {
|
||||||
|
const { getStatusOverviewEmbeddableFactory } = await import(
|
||||||
|
'./status_overview/status_overview_embeddable_factory'
|
||||||
|
);
|
||||||
|
return getStatusOverviewEmbeddableFactory(core.getStartServices);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const { uiActions, cloud, serverless } = pluginsSetup;
|
||||||
|
|
||||||
|
// Initialize actions
|
||||||
|
const addOverviewPanelAction = createStatusOverviewPanelAction();
|
||||||
|
|
||||||
|
core.getStartServices().then(([_, pluginsStart]) => {
|
||||||
|
pluginsStart.dashboard.registerDashboardPanelPlacementSetting(
|
||||||
|
SYNTHETICS_OVERVIEW_EMBEDDABLE,
|
||||||
|
() => {
|
||||||
|
return { width: 10, height: 8 };
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assign triggers
|
||||||
|
// Only register these actions in stateful kibana, and the serverless observability project
|
||||||
|
if (Boolean((serverless && cloud?.serverless.projectType === 'observability') || !serverless)) {
|
||||||
|
uiActions.addTriggerAction(ADD_PANEL_TRIGGER, addOverviewPanelAction);
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* 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 React from 'react';
|
||||||
|
import { Subject } from 'rxjs';
|
||||||
|
import { OverviewStatus } from '../../synthetics/components/monitors_page/overview/overview/overview_status';
|
||||||
|
import { SyntheticsEmbeddableContext } from '../synthetics_embeddable_context';
|
||||||
|
|
||||||
|
export const StatusOverviewComponent = ({ reload$ }: { reload$: Subject<boolean> }) => {
|
||||||
|
return (
|
||||||
|
<SyntheticsEmbeddableContext>
|
||||||
|
<OverviewStatus reload$={reload$} />
|
||||||
|
</SyntheticsEmbeddableContext>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,99 @@
|
||||||
|
/*
|
||||||
|
* 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 { i18n } from '@kbn/i18n';
|
||||||
|
|
||||||
|
import React, { useEffect } from 'react';
|
||||||
|
import { DefaultEmbeddableApi, ReactEmbeddableFactory } from '@kbn/embeddable-plugin/public';
|
||||||
|
import {
|
||||||
|
initializeTitles,
|
||||||
|
useBatchedPublishingSubjects,
|
||||||
|
fetch$,
|
||||||
|
PublishesWritablePanelTitle,
|
||||||
|
PublishesPanelTitle,
|
||||||
|
SerializedTitles,
|
||||||
|
} from '@kbn/presentation-publishing';
|
||||||
|
import { BehaviorSubject, Subject } from 'rxjs';
|
||||||
|
import type { StartServicesAccessor } from '@kbn/core-lifecycle-browser';
|
||||||
|
import { SYNTHETICS_OVERVIEW_EMBEDDABLE } from '../constants';
|
||||||
|
import { ClientPluginsStart } from '../../../plugin';
|
||||||
|
import { StatusOverviewComponent } from './status_overview_component';
|
||||||
|
|
||||||
|
export const getOverviewPanelTitle = () =>
|
||||||
|
i18n.translate('xpack.synthetics.statusOverview.displayName', {
|
||||||
|
defaultMessage: 'Synthetics Status Overview',
|
||||||
|
});
|
||||||
|
|
||||||
|
export type OverviewEmbeddableState = SerializedTitles;
|
||||||
|
|
||||||
|
export type StatusOverviewApi = DefaultEmbeddableApi<OverviewEmbeddableState> &
|
||||||
|
PublishesWritablePanelTitle &
|
||||||
|
PublishesPanelTitle;
|
||||||
|
|
||||||
|
export const getStatusOverviewEmbeddableFactory = (
|
||||||
|
getStartServices: StartServicesAccessor<ClientPluginsStart>
|
||||||
|
) => {
|
||||||
|
const factory: ReactEmbeddableFactory<
|
||||||
|
OverviewEmbeddableState,
|
||||||
|
OverviewEmbeddableState,
|
||||||
|
StatusOverviewApi
|
||||||
|
> = {
|
||||||
|
type: SYNTHETICS_OVERVIEW_EMBEDDABLE,
|
||||||
|
deserializeState: (state) => {
|
||||||
|
return state.rawState as OverviewEmbeddableState;
|
||||||
|
},
|
||||||
|
buildEmbeddable: async (state, buildApi, uuid, parentApi) => {
|
||||||
|
const { titlesApi, titleComparators, serializeTitles } = initializeTitles(state);
|
||||||
|
const defaultTitle$ = new BehaviorSubject<string | undefined>(getOverviewPanelTitle());
|
||||||
|
const reload$ = new Subject<boolean>();
|
||||||
|
|
||||||
|
const api = buildApi(
|
||||||
|
{
|
||||||
|
...titlesApi,
|
||||||
|
defaultPanelTitle: defaultTitle$,
|
||||||
|
serializeState: () => {
|
||||||
|
return {
|
||||||
|
rawState: {
|
||||||
|
...serializeTitles(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...titleComparators,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const fetchSubscription = fetch$(api)
|
||||||
|
.pipe()
|
||||||
|
.subscribe((next) => {
|
||||||
|
reload$.next(next.isReload);
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
api,
|
||||||
|
Component: () => {
|
||||||
|
const [] = useBatchedPublishingSubjects();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
fetchSubscription.unsubscribe();
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
data-shared-item="" // TODO: Remove data-shared-item and data-rendering-count as part of https://github.com/elastic/kibana/issues/179376
|
||||||
|
>
|
||||||
|
<StatusOverviewComponent reload$={reload$} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return factory;
|
||||||
|
};
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* 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 React from 'react';
|
||||||
|
import { createBrowserHistory } from 'history';
|
||||||
|
import { EuiPanel } from '@elastic/eui';
|
||||||
|
import { Router } from '@kbn/shared-ux-router';
|
||||||
|
import { SyntheticsSharedContext } from '../synthetics/contexts/synthetics_shared_context';
|
||||||
|
import { SyntheticsEmbeddableStateContextProvider } from '../synthetics/contexts/synthetics_embeddable_context';
|
||||||
|
import { getSyntheticsAppProps } from '../synthetics/render_app';
|
||||||
|
import { SyntheticsSettingsContextProvider } from '../synthetics/contexts';
|
||||||
|
|
||||||
|
export const SyntheticsEmbeddableContext: React.FC<{ search?: string }> = ({
|
||||||
|
search,
|
||||||
|
children,
|
||||||
|
}) => {
|
||||||
|
const props = getSyntheticsAppProps();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SyntheticsSharedContext {...props}>
|
||||||
|
<SyntheticsEmbeddableStateContextProvider>
|
||||||
|
<Router history={createBrowserHistory()}>
|
||||||
|
<SyntheticsSettingsContextProvider {...props}>
|
||||||
|
<EuiPanel hasShadow={false}>{children}</EuiPanel>
|
||||||
|
</SyntheticsSettingsContextProvider>
|
||||||
|
</Router>
|
||||||
|
</SyntheticsEmbeddableStateContextProvider>
|
||||||
|
</SyntheticsSharedContext>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* 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 { i18n } from '@kbn/i18n';
|
||||||
|
import { apiIsPresentationContainer } from '@kbn/presentation-containers';
|
||||||
|
import {
|
||||||
|
IncompatibleActionError,
|
||||||
|
type UiActionsActionDefinition,
|
||||||
|
} from '@kbn/ui-actions-plugin/public';
|
||||||
|
import { EmbeddableApiContext } from '@kbn/presentation-publishing';
|
||||||
|
import { SYNTHETICS_OVERVIEW_EMBEDDABLE } from '../constants';
|
||||||
|
|
||||||
|
export const COMMON_SYNTHETICS_GROUPING = [
|
||||||
|
{
|
||||||
|
id: 'synthetics',
|
||||||
|
getDisplayName: () =>
|
||||||
|
i18n.translate('xpack.synthetics.common.constants.grouping.legacy', {
|
||||||
|
defaultMessage: 'Synthetics',
|
||||||
|
}),
|
||||||
|
getIconType: () => {
|
||||||
|
return 'online';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
export const ADD_SYNTHETICS_OVERVIEW_ACTION_ID = 'CREATE_SYNTHETICS_OVERVIEW_EMBEDDABLE';
|
||||||
|
|
||||||
|
export function createStatusOverviewPanelAction(): UiActionsActionDefinition<EmbeddableApiContext> {
|
||||||
|
return {
|
||||||
|
id: ADD_SYNTHETICS_OVERVIEW_ACTION_ID,
|
||||||
|
grouping: COMMON_SYNTHETICS_GROUPING,
|
||||||
|
order: 30,
|
||||||
|
getIconType: () => 'online',
|
||||||
|
isCompatible: async ({ embeddable }) => {
|
||||||
|
return apiIsPresentationContainer(embeddable);
|
||||||
|
},
|
||||||
|
execute: async ({ embeddable }) => {
|
||||||
|
if (!apiIsPresentationContainer(embeddable)) throw new IncompatibleActionError();
|
||||||
|
try {
|
||||||
|
embeddable.addNewPanel({
|
||||||
|
panelType: SYNTHETICS_OVERVIEW_EMBEDDABLE,
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
return Promise.reject();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getDisplayName: () =>
|
||||||
|
i18n.translate('xpack.synthetics.syntheticsEmbeddable.ariaLabel', {
|
||||||
|
defaultMessage: 'Synthetics Overview',
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
|
@ -14,6 +14,8 @@ import { useFetcher } from '@kbn/observability-shared-plugin/public';
|
||||||
import { useSessionStorage } from 'react-use';
|
import { useSessionStorage } from 'react-use';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import { isEmpty } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
|
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||||
|
import { ClientPluginsStart } from '../../../../../plugin';
|
||||||
import { selectDynamicSettings } from '../../../state/settings';
|
import { selectDynamicSettings } from '../../../state/settings';
|
||||||
import {
|
import {
|
||||||
selectSyntheticsAlerts,
|
selectSyntheticsAlerts,
|
||||||
|
@ -21,7 +23,7 @@ import {
|
||||||
} from '../../../state/alert_rules/selectors';
|
} from '../../../state/alert_rules/selectors';
|
||||||
import { selectMonitorListState } from '../../../state';
|
import { selectMonitorListState } from '../../../state';
|
||||||
import { getDynamicSettingsAction } from '../../../state/settings/actions';
|
import { getDynamicSettingsAction } from '../../../state/settings/actions';
|
||||||
import { useSyntheticsSettingsContext, useSyntheticsStartPlugins } from '../../../contexts';
|
import { useSyntheticsSettingsContext } from '../../../contexts';
|
||||||
import { ConfigKey } from '../../../../../../common/runtime_types';
|
import { ConfigKey } from '../../../../../../common/runtime_types';
|
||||||
|
|
||||||
export const AlertingCallout = ({ isAlertingEnabled }: { isAlertingEnabled?: boolean }) => {
|
export const AlertingCallout = ({ isAlertingEnabled }: { isAlertingEnabled?: boolean }) => {
|
||||||
|
@ -40,7 +42,8 @@ export const AlertingCallout = ({ isAlertingEnabled }: { isAlertingEnabled?: boo
|
||||||
loaded: monitorsLoaded,
|
loaded: monitorsLoaded,
|
||||||
} = useSelector(selectMonitorListState);
|
} = useSelector(selectMonitorListState);
|
||||||
|
|
||||||
const syntheticsLocators = useSyntheticsStartPlugins()?.share?.url.locators;
|
const syntheticsLocators = useKibana<ClientPluginsStart>().services.share?.url.locators;
|
||||||
|
|
||||||
const locator = syntheticsLocators?.get(syntheticsSettingsLocatorID);
|
const locator = syntheticsLocators?.get(syntheticsSettingsLocatorID);
|
||||||
|
|
||||||
const { data: url } = useFetcher(() => {
|
const { data: url } = useFetcher(() => {
|
||||||
|
|
|
@ -0,0 +1,139 @@
|
||||||
|
/*
|
||||||
|
* 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 React, { FC, useCallback } from 'react';
|
||||||
|
import { i18n } from '@kbn/i18n';
|
||||||
|
import {
|
||||||
|
EuiButtonIcon,
|
||||||
|
EuiContextMenuItem,
|
||||||
|
EuiContextMenuPanel,
|
||||||
|
EuiFlexGroup,
|
||||||
|
EuiFlexItem,
|
||||||
|
EuiPanel,
|
||||||
|
EuiPopover,
|
||||||
|
EuiProgress,
|
||||||
|
EuiTitle,
|
||||||
|
} from '@elastic/eui';
|
||||||
|
import {
|
||||||
|
LazySavedObjectSaveModalDashboard,
|
||||||
|
SaveModalDashboardProps,
|
||||||
|
withSuspense,
|
||||||
|
} from '@kbn/presentation-util-plugin/public';
|
||||||
|
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||||
|
import { SYNTHETICS_OVERVIEW_EMBEDDABLE } from '../../../../embeddables/constants';
|
||||||
|
import { ClientPluginsStart } from '../../../../../plugin';
|
||||||
|
|
||||||
|
const SavedObjectSaveModalDashboard = withSuspense(LazySavedObjectSaveModalDashboard);
|
||||||
|
|
||||||
|
export const EmbeddablePanelWrapper: FC<{
|
||||||
|
title: string;
|
||||||
|
loading?: boolean;
|
||||||
|
}> = ({ children, title, loading }) => {
|
||||||
|
const [isPopoverOpen, setIsPopoverOpen] = React.useState(false);
|
||||||
|
|
||||||
|
const [isDashboardAttachmentReady, setDashboardAttachmentReady] = React.useState(false);
|
||||||
|
|
||||||
|
const closePopover = () => {
|
||||||
|
setIsPopoverOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const { embeddable } = useKibana<ClientPluginsStart>().services;
|
||||||
|
|
||||||
|
const isSyntheticsApp = window.location.pathname.includes('/app/synthetics');
|
||||||
|
|
||||||
|
const handleAttachToDashboardSave: SaveModalDashboardProps['onSave'] = useCallback(
|
||||||
|
({ dashboardId, newTitle, newDescription }) => {
|
||||||
|
const stateTransfer = embeddable.getStateTransfer();
|
||||||
|
const embeddableInput = {};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
input: embeddableInput,
|
||||||
|
type: SYNTHETICS_OVERVIEW_EMBEDDABLE,
|
||||||
|
};
|
||||||
|
|
||||||
|
const path = dashboardId === 'new' ? '#/create' : `#/view/${dashboardId}`;
|
||||||
|
|
||||||
|
stateTransfer.navigateToWithEmbeddablePackage('dashboards', {
|
||||||
|
state,
|
||||||
|
path,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[embeddable]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<EuiPanel hasShadow={false} hasBorder>
|
||||||
|
{loading && <EuiProgress size="xs" color="accent" />}
|
||||||
|
<EuiFlexGroup>
|
||||||
|
<EuiFlexItem grow={true}>
|
||||||
|
<EuiTitle size="xs">
|
||||||
|
<h3>{title}</h3>
|
||||||
|
</EuiTitle>
|
||||||
|
</EuiFlexItem>
|
||||||
|
{isSyntheticsApp && (
|
||||||
|
<EuiFlexItem grow={false}>
|
||||||
|
<EuiPopover
|
||||||
|
button={
|
||||||
|
<EuiButtonIcon
|
||||||
|
color="text"
|
||||||
|
data-test-subj="syntheticsEmbeddablePanelWrapperButton"
|
||||||
|
iconType="boxesHorizontal"
|
||||||
|
onClick={() => setIsPopoverOpen(!isPopoverOpen)}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
isOpen={isPopoverOpen}
|
||||||
|
closePopover={closePopover}
|
||||||
|
>
|
||||||
|
<EuiContextMenuPanel
|
||||||
|
size="s"
|
||||||
|
items={[
|
||||||
|
<EuiContextMenuItem
|
||||||
|
key="share"
|
||||||
|
icon="dashboardApp"
|
||||||
|
onClick={() => {
|
||||||
|
setDashboardAttachmentReady(true);
|
||||||
|
closePopover();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{i18n.translate(
|
||||||
|
'xpack.synthetics.embeddablePanelWrapper.shareContextMenuItemLabel',
|
||||||
|
{ defaultMessage: 'Add to dashboard' }
|
||||||
|
)}
|
||||||
|
</EuiContextMenuItem>,
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</EuiPopover>
|
||||||
|
</EuiFlexItem>
|
||||||
|
)}
|
||||||
|
</EuiFlexGroup>
|
||||||
|
|
||||||
|
{children}
|
||||||
|
</EuiPanel>
|
||||||
|
{isDashboardAttachmentReady ? (
|
||||||
|
<SavedObjectSaveModalDashboard
|
||||||
|
objectType={i18n.translate(
|
||||||
|
'xpack.synthetics.item.actions.addToDashboard.objectTypeLabel',
|
||||||
|
{
|
||||||
|
defaultMessage: 'Status Overview',
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
documentInfo={{
|
||||||
|
title: i18n.translate('xpack.synthetics.item.actions.addToDashboard.attachmentTitle', {
|
||||||
|
defaultMessage: 'Status Overview',
|
||||||
|
}),
|
||||||
|
}}
|
||||||
|
canSaveByReference={false}
|
||||||
|
onClose={() => {
|
||||||
|
setDashboardAttachmentReady(false);
|
||||||
|
}}
|
||||||
|
onSave={handleAttachToDashboardSave}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
|
@ -7,20 +7,18 @@
|
||||||
|
|
||||||
import React, { useContext, useEffect } from 'react';
|
import React, { useContext, useEffect } from 'react';
|
||||||
import { EuiSuperDatePicker } from '@elastic/eui';
|
import { EuiSuperDatePicker } from '@elastic/eui';
|
||||||
|
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||||
|
import { ClientPluginsStart } from '../../../../../plugin';
|
||||||
import { useUrlParams } from '../../../hooks';
|
import { useUrlParams } from '../../../hooks';
|
||||||
import { CLIENT_DEFAULTS } from '../../../../../../common/constants';
|
import { CLIENT_DEFAULTS } from '../../../../../../common/constants';
|
||||||
import {
|
import { SyntheticsSettingsContext, SyntheticsRefreshContext } from '../../../contexts';
|
||||||
SyntheticsSettingsContext,
|
|
||||||
SyntheticsStartupPluginsContext,
|
|
||||||
SyntheticsRefreshContext,
|
|
||||||
} from '../../../contexts';
|
|
||||||
|
|
||||||
export const SyntheticsDatePicker = ({ fullWidth }: { fullWidth?: boolean }) => {
|
export const SyntheticsDatePicker = ({ fullWidth }: { fullWidth?: boolean }) => {
|
||||||
const [getUrlParams, updateUrl] = useUrlParams();
|
const [getUrlParams, updateUrl] = useUrlParams();
|
||||||
const { commonlyUsedRanges } = useContext(SyntheticsSettingsContext);
|
const { commonlyUsedRanges } = useContext(SyntheticsSettingsContext);
|
||||||
const { refreshApp } = useContext(SyntheticsRefreshContext);
|
const { refreshApp } = useContext(SyntheticsRefreshContext);
|
||||||
|
|
||||||
const { data } = useContext(SyntheticsStartupPluginsContext);
|
const { data } = useKibana<ClientPluginsStart>().services;
|
||||||
|
|
||||||
// read time from state and update the url
|
// read time from state and update the url
|
||||||
const sharedTimeState = data?.query.timefilter.timefilter.getTime();
|
const sharedTimeState = data?.query.timefilter.timefilter.getTime();
|
||||||
|
|
|
@ -12,9 +12,9 @@ import moment from 'moment';
|
||||||
import { AllSeries, createExploratoryViewUrl } from '@kbn/exploratory-view-plugin/public';
|
import { AllSeries, createExploratoryViewUrl } from '@kbn/exploratory-view-plugin/public';
|
||||||
import { euiStyled } from '@kbn/kibana-react-plugin/common';
|
import { euiStyled } from '@kbn/kibana-react-plugin/common';
|
||||||
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||||
|
import { ClientPluginsStart } from '../../../../../plugin';
|
||||||
import { SYNTHETICS_INDEX_PATTERN } from '../../../../../../common/constants';
|
import { SYNTHETICS_INDEX_PATTERN } from '../../../../../../common/constants';
|
||||||
import { JourneyStep } from '../../../../../../common/runtime_types';
|
import { JourneyStep } from '../../../../../../common/runtime_types';
|
||||||
import { useSyntheticsStartPlugins } from '../../../contexts';
|
|
||||||
|
|
||||||
export const getLast48Intervals = (activeStep: JourneyStep) => {
|
export const getLast48Intervals = (activeStep: JourneyStep) => {
|
||||||
const timestamp = activeStep['@timestamp'];
|
const timestamp = activeStep['@timestamp'];
|
||||||
|
@ -36,7 +36,7 @@ export function StepFieldTrend({
|
||||||
field: string;
|
field: string;
|
||||||
step: JourneyStep;
|
step: JourneyStep;
|
||||||
}) {
|
}) {
|
||||||
const { exploratoryView } = useSyntheticsStartPlugins();
|
const exploratoryView = useKibana<ClientPluginsStart>().services.exploratoryView;
|
||||||
|
|
||||||
const EmbeddableExpView = exploratoryView!.ExploratoryViewEmbeddable;
|
const EmbeddableExpView = exploratoryView!.ExploratoryViewEmbeddable;
|
||||||
|
|
||||||
|
|
|
@ -179,7 +179,7 @@ describe('GettingStartedPage', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// page is loaded
|
// page is loaded
|
||||||
expect(kibanaService.core.application.navigateToApp).toHaveBeenCalledWith('synthetics', {
|
expect(kibanaService.coreStart.application.navigateToApp).toHaveBeenCalledWith('synthetics', {
|
||||||
path: '/monitors',
|
path: '/monitors',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -56,14 +56,14 @@ export const useSimpleMonitor = ({ monitorData }: { monitorData?: SimpleFormData
|
||||||
}, [monitorData]);
|
}, [monitorData]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const { core, toasts } = kibanaService;
|
const { coreStart, toasts } = kibanaService;
|
||||||
const newMonitor = data as UpsertMonitorResponse;
|
const newMonitor = data as UpsertMonitorResponse;
|
||||||
const hasErrors = data && 'attributes' in data && data.attributes.errors?.length > 0;
|
const hasErrors = data && 'attributes' in data && data.attributes.errors?.length > 0;
|
||||||
if (hasErrors && !loading) {
|
if (hasErrors && !loading) {
|
||||||
showSyncErrors(
|
showSyncErrors(
|
||||||
(data as { attributes: { errors: ServiceLocationErrors } })?.attributes.errors ?? [],
|
(data as { attributes: { errors: ServiceLocationErrors } })?.attributes.errors ?? [],
|
||||||
serviceLocations,
|
serviceLocations,
|
||||||
core
|
coreStart
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ export const useMonitorSave = ({ monitorData }: { monitorData?: SyntheticsMonito
|
||||||
}, [monitorData]);
|
}, [monitorData]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const { core, toasts } = kibanaService;
|
const { coreStart, toasts } = kibanaService;
|
||||||
|
|
||||||
if (status === FETCH_STATUS.FAILURE && error) {
|
if (status === FETCH_STATUS.FAILURE && error) {
|
||||||
toasts.addError(
|
toasts.addError(
|
||||||
|
@ -64,7 +64,7 @@ export const useMonitorSave = ({ monitorData }: { monitorData?: SyntheticsMonito
|
||||||
<p data-test-subj="synthetcsMonitorSaveSubtext">
|
<p data-test-subj="synthetcsMonitorSaveSubtext">
|
||||||
{monitorId ? MONITOR_UPDATED_SUCCESS_LABEL_SUBTEXT : MONITOR_SUCCESS_LABEL_SUBTEXT}
|
{monitorId ? MONITOR_UPDATED_SUCCESS_LABEL_SUBTEXT : MONITOR_SUCCESS_LABEL_SUBTEXT}
|
||||||
</p>,
|
</p>,
|
||||||
core
|
coreStart
|
||||||
),
|
),
|
||||||
toastLifeTimeMs: 3000,
|
toastLifeTimeMs: 3000,
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,7 +18,7 @@ import {
|
||||||
export function useOverviewStatus({ scopeStatusByLocation }: { scopeStatusByLocation: boolean }) {
|
export function useOverviewStatus({ scopeStatusByLocation }: { scopeStatusByLocation: boolean }) {
|
||||||
const pageState = useSelector(selectOverviewPageState);
|
const pageState = useSelector(selectOverviewPageState);
|
||||||
|
|
||||||
const { status, error, loaded } = useSelector(selectOverviewStatus);
|
const { status, error, loaded, loading } = useSelector(selectOverviewStatus);
|
||||||
|
|
||||||
const { lastRefresh } = useSyntheticsRefreshContext();
|
const { lastRefresh } = useSyntheticsRefreshContext();
|
||||||
|
|
||||||
|
@ -37,5 +37,6 @@ export function useOverviewStatus({ scopeStatusByLocation }: { scopeStatusByLoca
|
||||||
return {
|
return {
|
||||||
status,
|
status,
|
||||||
error,
|
error,
|
||||||
|
loading,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ export const DeleteMonitor = ({
|
||||||
}, [configId, isDeleting]);
|
}, [configId, isDeleting]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const { core, toasts } = kibanaService;
|
const { coreStart, toasts } = kibanaService;
|
||||||
if (!isDeleting) {
|
if (!isDeleting) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ export const DeleteMonitor = ({
|
||||||
<p data-test-subj="uptimeDeleteMonitorFailure">
|
<p data-test-subj="uptimeDeleteMonitorFailure">
|
||||||
{labels.MONITOR_DELETE_FAILURE_LABEL}
|
{labels.MONITOR_DELETE_FAILURE_LABEL}
|
||||||
</p>,
|
</p>,
|
||||||
core
|
coreStart
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{ toastLifeTimeMs: 3000 }
|
{ toastLifeTimeMs: 3000 }
|
||||||
|
@ -72,7 +72,7 @@ export const DeleteMonitor = ({
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
</p>,
|
</p>,
|
||||||
core
|
coreStart
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{ toastLifeTimeMs: 3000 }
|
{ toastLifeTimeMs: 3000 }
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||||
* 2.0.
|
* 2.0.
|
||||||
*/
|
*/
|
||||||
import React, { useState, useRef, memo, useCallback } from 'react';
|
import React, { useState, useRef, memo, useCallback, useEffect } from 'react';
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
import { useSelector, useDispatch } from 'react-redux';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import {
|
import {
|
||||||
|
@ -15,11 +15,12 @@ import {
|
||||||
EuiButtonEmpty,
|
EuiButtonEmpty,
|
||||||
EuiText,
|
EuiText,
|
||||||
} from '@elastic/eui';
|
} from '@elastic/eui';
|
||||||
import { selectOverviewStatus } from '../../../../state/overview_status';
|
import { useOverviewStatus } from '../../hooks/use_overview_status';
|
||||||
import { useInfiniteScroll } from './use_infinite_scroll';
|
import { useInfiniteScroll } from './use_infinite_scroll';
|
||||||
import { GridItemsByGroup } from './grid_by_group/grid_items_by_group';
|
import { GridItemsByGroup } from './grid_by_group/grid_items_by_group';
|
||||||
import { GroupFields } from './grid_by_group/group_fields';
|
import { GroupFields } from './grid_by_group/group_fields';
|
||||||
import {
|
import {
|
||||||
|
fetchMonitorOverviewAction,
|
||||||
quietFetchOverviewAction,
|
quietFetchOverviewAction,
|
||||||
selectOverviewState,
|
selectOverviewState,
|
||||||
setFlyoutConfig,
|
setFlyoutConfig,
|
||||||
|
@ -33,7 +34,7 @@ import { NoMonitorsFound } from '../../common/no_monitors_found';
|
||||||
import { MonitorDetailFlyout } from './monitor_detail_flyout';
|
import { MonitorDetailFlyout } from './monitor_detail_flyout';
|
||||||
|
|
||||||
export const OverviewGrid = memo(() => {
|
export const OverviewGrid = memo(() => {
|
||||||
const { status } = useSelector(selectOverviewStatus);
|
const { status } = useOverviewStatus({ scopeStatusByLocation: true });
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: { monitors },
|
data: { monitors },
|
||||||
|
@ -49,6 +50,11 @@ export const OverviewGrid = memo(() => {
|
||||||
const intersectionRef = useRef(null);
|
const intersectionRef = useRef(null);
|
||||||
const { monitorsSortedByStatus } = useMonitorsSortedByStatus();
|
const { monitorsSortedByStatus } = useMonitorsSortedByStatus();
|
||||||
|
|
||||||
|
// fetch overview for all other page state changes
|
||||||
|
useEffect(() => {
|
||||||
|
dispatch(fetchMonitorOverviewAction.get(pageState));
|
||||||
|
}, [dispatch, pageState]);
|
||||||
|
|
||||||
const setFlyoutConfigCallback = useCallback(
|
const setFlyoutConfigCallback = useCallback(
|
||||||
(params: FlyoutParamProps) => dispatch(setFlyoutConfig(params)),
|
(params: FlyoutParamProps) => dispatch(setFlyoutConfig(params)),
|
||||||
[dispatch]
|
[dispatch]
|
||||||
|
|
|
@ -5,10 +5,13 @@
|
||||||
* 2.0.
|
* 2.0.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiSpacer, EuiStat, EuiTitle } from '@elastic/eui';
|
import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiStat } from '@elastic/eui';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
|
import { Subject } from 'rxjs';
|
||||||
|
import { useSyntheticsRefreshContext } from '../../../../contexts';
|
||||||
|
import { EmbeddablePanelWrapper } from '../../../common/components/embeddable_panel_wrapper';
|
||||||
import { clearOverviewStatusErrorAction } from '../../../../state/overview_status';
|
import { clearOverviewStatusErrorAction } from '../../../../state/overview_status';
|
||||||
import { kibanaService } from '../../../../../../utils/kibana_service';
|
import { kibanaService } from '../../../../../../utils/kibana_service';
|
||||||
import { useGetUrlParams } from '../../../../hooks/use_url_params';
|
import { useGetUrlParams } from '../../../../hooks/use_url_params';
|
||||||
|
@ -18,10 +21,16 @@ function title(t?: number) {
|
||||||
return t ?? '-';
|
return t ?? '-';
|
||||||
}
|
}
|
||||||
|
|
||||||
export function OverviewStatus() {
|
export function OverviewStatus({ reload$ }: { reload$?: Subject<boolean> }) {
|
||||||
const { statusFilter } = useGetUrlParams();
|
const { statusFilter } = useGetUrlParams();
|
||||||
|
|
||||||
const { status, error: statusError } = useOverviewStatus({ scopeStatusByLocation: true });
|
const { refreshApp } = useSyntheticsRefreshContext();
|
||||||
|
|
||||||
|
const {
|
||||||
|
status,
|
||||||
|
error: statusError,
|
||||||
|
loading,
|
||||||
|
} = useOverviewStatus({ scopeStatusByLocation: true });
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const [statusConfig, setStatusConfig] = useState({
|
const [statusConfig, setStatusConfig] = useState({
|
||||||
up: status?.up,
|
up: status?.up,
|
||||||
|
@ -30,6 +39,14 @@ export function OverviewStatus() {
|
||||||
disabledCount: status?.disabledCount,
|
disabledCount: status?.disabledCount,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const sub = reload$?.subscribe(() => {
|
||||||
|
refreshApp();
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => sub?.unsubscribe();
|
||||||
|
}, [refreshApp, reload$]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (statusError) {
|
if (statusError) {
|
||||||
dispatch(clearOverviewStatusErrorAction());
|
dispatch(clearOverviewStatusErrorAction());
|
||||||
|
@ -87,10 +104,7 @@ export function OverviewStatus() {
|
||||||
}, [status, statusFilter]);
|
}, [status, statusFilter]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EuiPanel hasShadow={false} hasBorder>
|
<EmbeddablePanelWrapper title={headingText} loading={loading}>
|
||||||
<EuiTitle size="xs">
|
|
||||||
<h3>{headingText}</h3>
|
|
||||||
</EuiTitle>
|
|
||||||
<EuiSpacer size="m" />
|
<EuiSpacer size="m" />
|
||||||
<EuiFlexGroup gutterSize="xl">
|
<EuiFlexGroup gutterSize="xl">
|
||||||
<EuiFlexItem grow={false}>
|
<EuiFlexItem grow={false}>
|
||||||
|
@ -136,7 +150,7 @@ export function OverviewStatus() {
|
||||||
</EuiFlexItem>
|
</EuiFlexItem>
|
||||||
)}
|
)}
|
||||||
</EuiFlexGroup>
|
</EuiFlexGroup>
|
||||||
</EuiPanel>
|
</EmbeddablePanelWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ export const DeleteParam = ({
|
||||||
if (!isDeleting) {
|
if (!isDeleting) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { core, toasts } = kibanaService;
|
const { coreStart, toasts } = kibanaService;
|
||||||
|
|
||||||
if (status === FETCH_STATUS.FAILURE) {
|
if (status === FETCH_STATUS.FAILURE) {
|
||||||
toasts.addDanger(
|
toasts.addDanger(
|
||||||
|
@ -61,7 +61,7 @@ export const DeleteParam = ({
|
||||||
values: { name },
|
values: { name },
|
||||||
})}
|
})}
|
||||||
</p>,
|
</p>,
|
||||||
core
|
coreStart
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{ toastLifeTimeMs: 3000 }
|
{ toastLifeTimeMs: 3000 }
|
||||||
|
@ -76,7 +76,7 @@ export const DeleteParam = ({
|
||||||
values: { name },
|
values: { name },
|
||||||
})}
|
})}
|
||||||
</p>,
|
</p>,
|
||||||
core
|
coreStart
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{ toastLifeTimeMs: 3000 }
|
{ toastLifeTimeMs: 3000 }
|
||||||
|
|
|
@ -5,8 +5,9 @@
|
||||||
* 2.0.
|
* 2.0.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { SyntheticsStartupPluginsContext } from '../../../../../contexts';
|
import { i18n } from '@kbn/i18n';
|
||||||
import { JourneyStep } from '../../../../../../../../common/runtime_types';
|
import { JourneyStep } from '../../../../../../../../common/runtime_types';
|
||||||
import { WaterfallContext } from '../context/waterfall_context';
|
import { WaterfallContext } from '../context/waterfall_context';
|
||||||
|
|
||||||
|
@ -25,9 +26,21 @@ const EmbeddableMock = ({
|
||||||
}) => (
|
}) => (
|
||||||
<div>
|
<div>
|
||||||
<h1>{title}</h1>
|
<h1>{title}</h1>
|
||||||
<div aria-label="append title">{appendTitle}</div>
|
<div
|
||||||
|
aria-label={i18n.translate('xpack.synthetics.embeddableMock.div.appendTitleLabel', {
|
||||||
|
defaultMessage: 'append title',
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{appendTitle}
|
||||||
|
</div>
|
||||||
<div>{reportType}</div>
|
<div>{reportType}</div>
|
||||||
<div aria-label="attributes">{JSON.stringify(attributes)}</div>
|
<div
|
||||||
|
aria-label={i18n.translate('xpack.synthetics.embeddableMock.div.attributesLabel', {
|
||||||
|
defaultMessage: 'attributes',
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{JSON.stringify(attributes)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -40,9 +53,8 @@ export const TestWrapper = ({
|
||||||
activeStep?: JourneyStep;
|
activeStep?: JourneyStep;
|
||||||
children: JSX.Element;
|
children: JSX.Element;
|
||||||
}) => (
|
}) => (
|
||||||
<SyntheticsStartupPluginsContext.Provider
|
<KibanaContextProvider
|
||||||
value={{
|
services={{
|
||||||
// @ts-expect-error incomplete implementation for test purposes
|
|
||||||
exploratoryView: {
|
exploratoryView: {
|
||||||
ExploratoryViewEmbeddable: jest.fn((props: any) => <EmbeddableMock {...props} />),
|
ExploratoryViewEmbeddable: jest.fn((props: any) => <EmbeddableMock {...props} />),
|
||||||
},
|
},
|
||||||
|
@ -55,5 +67,5 @@ export const TestWrapper = ({
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</WaterfallContext.Provider>
|
</WaterfallContext.Provider>
|
||||||
</SyntheticsStartupPluginsContext.Provider>
|
</KibanaContextProvider>
|
||||||
);
|
);
|
||||||
|
|
|
@ -38,7 +38,7 @@ export const BrowserTestRunResult = ({
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const { core, toasts } = kibanaService;
|
const { coreStart, toasts } = kibanaService;
|
||||||
if (retriesExceeded) {
|
if (retriesExceeded) {
|
||||||
toasts.addDanger(
|
toasts.addDanger(
|
||||||
{
|
{
|
||||||
|
@ -49,7 +49,7 @@ export const BrowserTestRunResult = ({
|
||||||
defaultMessage="Manual test run failed for {name}"
|
defaultMessage="Manual test run failed for {name}"
|
||||||
values={{ name }}
|
values={{ name }}
|
||||||
/>,
|
/>,
|
||||||
core
|
coreStart
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,7 +25,7 @@ export function SimpleTestResults({ name, testRunId, expectPings, onDone }: Prop
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (retriesExceeded) {
|
if (retriesExceeded) {
|
||||||
const { core, toasts } = kibanaService;
|
const { coreStart, toasts } = kibanaService;
|
||||||
|
|
||||||
toasts.addDanger(
|
toasts.addDanger(
|
||||||
{
|
{
|
||||||
|
@ -36,7 +36,7 @@ export function SimpleTestResults({ name, testRunId, expectPings, onDone }: Prop
|
||||||
defaultMessage="Manual test run failed for {name}"
|
defaultMessage="Manual test run failed for {name}"
|
||||||
values={{ name }}
|
values={{ name }}
|
||||||
/>,
|
/>,
|
||||||
core
|
coreStart
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,5 +7,3 @@
|
||||||
|
|
||||||
export * from './synthetics_refresh_context';
|
export * from './synthetics_refresh_context';
|
||||||
export * from './synthetics_settings_context';
|
export * from './synthetics_settings_context';
|
||||||
export * from './synthetics_theme_context';
|
|
||||||
export * from './synthetics_startup_plugins_context';
|
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* 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 React, { createContext, useContext, useMemo } from 'react';
|
||||||
|
import { History, createMemoryHistory } from 'history';
|
||||||
|
|
||||||
|
interface SyntheticsEmbeddableContext {
|
||||||
|
history: History;
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultContext: SyntheticsEmbeddableContext = {} as SyntheticsEmbeddableContext;
|
||||||
|
|
||||||
|
export const SyntheticsEmbeddableContext = createContext(defaultContext);
|
||||||
|
|
||||||
|
export const SyntheticsEmbeddableStateContextProvider: React.FC = ({ children }) => {
|
||||||
|
const value = useMemo(() => {
|
||||||
|
return { history: createMemoryHistory() };
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return <SyntheticsEmbeddableContext.Provider value={value} children={children} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useSyntheticsEmbeddableContext = () => useContext(SyntheticsEmbeddableContext);
|
|
@ -27,13 +27,13 @@ export interface CommonlyUsedDateRange {
|
||||||
export interface SyntheticsAppProps {
|
export interface SyntheticsAppProps {
|
||||||
basePath: string;
|
basePath: string;
|
||||||
canSave: boolean;
|
canSave: boolean;
|
||||||
core: CoreStart;
|
coreStart: CoreStart;
|
||||||
darkMode: boolean;
|
darkMode: boolean;
|
||||||
i18n: I18nStart;
|
i18n: I18nStart;
|
||||||
isApmAvailable: boolean;
|
isApmAvailable: boolean;
|
||||||
isInfraAvailable: boolean;
|
isInfraAvailable: boolean;
|
||||||
isLogsAvailable: boolean;
|
isLogsAvailable: boolean;
|
||||||
plugins: ClientPluginsSetup;
|
setupPlugins: ClientPluginsSetup;
|
||||||
startPlugins: ClientPluginsStart;
|
startPlugins: ClientPluginsStart;
|
||||||
setBadge: (badge?: ChromeBadge) => void;
|
setBadge: (badge?: ChromeBadge) => void;
|
||||||
renderGlobalHelpControls(): void;
|
renderGlobalHelpControls(): void;
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* 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 React from 'react';
|
||||||
|
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
|
||||||
|
import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common';
|
||||||
|
import { Provider as ReduxProvider } from 'react-redux';
|
||||||
|
import { RedirectAppLinks } from '@kbn/shared-ux-link-redirect-app';
|
||||||
|
import { SyntheticsRefreshContextProvider } from './synthetics_refresh_context';
|
||||||
|
import { SyntheticsDataViewContextProvider } from './synthetics_data_view_context';
|
||||||
|
import { SyntheticsAppProps } from './synthetics_settings_context';
|
||||||
|
import { storage, store } from '../state';
|
||||||
|
|
||||||
|
export const SyntheticsSharedContext: React.FC<SyntheticsAppProps> = ({
|
||||||
|
coreStart,
|
||||||
|
setupPlugins,
|
||||||
|
startPlugins,
|
||||||
|
children,
|
||||||
|
darkMode,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<KibanaContextProvider
|
||||||
|
services={{
|
||||||
|
...coreStart,
|
||||||
|
...setupPlugins,
|
||||||
|
storage,
|
||||||
|
data: startPlugins.data,
|
||||||
|
inspector: startPlugins.inspector,
|
||||||
|
triggersActionsUi: startPlugins.triggersActionsUi,
|
||||||
|
observability: startPlugins.observability,
|
||||||
|
observabilityShared: startPlugins.observabilityShared,
|
||||||
|
observabilityAIAssistant: startPlugins.observabilityAIAssistant,
|
||||||
|
exploratoryView: startPlugins.exploratoryView,
|
||||||
|
cases: startPlugins.cases,
|
||||||
|
spaces: startPlugins.spaces,
|
||||||
|
fleet: startPlugins.fleet,
|
||||||
|
share: startPlugins.share,
|
||||||
|
unifiedSearch: startPlugins.unifiedSearch,
|
||||||
|
embeddable: startPlugins.embeddable,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<EuiThemeProvider darkMode={darkMode}>
|
||||||
|
<ReduxProvider store={store}>
|
||||||
|
<SyntheticsRefreshContextProvider>
|
||||||
|
<SyntheticsDataViewContextProvider dataViews={startPlugins.dataViews}>
|
||||||
|
<RedirectAppLinks
|
||||||
|
coreStart={{
|
||||||
|
application: coreStart.application,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</RedirectAppLinks>
|
||||||
|
</SyntheticsDataViewContextProvider>
|
||||||
|
</SyntheticsRefreshContextProvider>
|
||||||
|
</ReduxProvider>
|
||||||
|
</EuiThemeProvider>
|
||||||
|
</KibanaContextProvider>
|
||||||
|
);
|
||||||
|
};
|
|
@ -1,19 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 React, { createContext, useContext, PropsWithChildren } from 'react';
|
|
||||||
import { ClientPluginsStart } from '../../../plugin';
|
|
||||||
|
|
||||||
export const SyntheticsStartupPluginsContext = createContext<Partial<ClientPluginsStart>>({});
|
|
||||||
|
|
||||||
export const SyntheticsStartupPluginsContextProvider: React.FC<
|
|
||||||
PropsWithChildren<Partial<ClientPluginsStart>>
|
|
||||||
> = ({ children, ...props }) => (
|
|
||||||
<SyntheticsStartupPluginsContext.Provider value={{ ...props }} children={children} />
|
|
||||||
);
|
|
||||||
|
|
||||||
export const useSyntheticsStartPlugins = () => useContext(SyntheticsStartupPluginsContext);
|
|
|
@ -1,97 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 { euiLightVars, euiDarkVars } from '@kbn/ui-theme';
|
|
||||||
import React, { createContext, useContext, useMemo, FC, PropsWithChildren } from 'react';
|
|
||||||
import { DARK_THEME, LIGHT_THEME, PartialTheme, Theme } from '@elastic/charts';
|
|
||||||
|
|
||||||
export interface SyntheticsAppColors {
|
|
||||||
danger: string;
|
|
||||||
dangerBehindText: string;
|
|
||||||
success: string;
|
|
||||||
gray: string;
|
|
||||||
range: string;
|
|
||||||
mean: string;
|
|
||||||
warning: string;
|
|
||||||
lightestShade: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SyntheticsThemeContextValues {
|
|
||||||
colors: SyntheticsAppColors;
|
|
||||||
chartTheme: {
|
|
||||||
baseTheme?: Theme;
|
|
||||||
theme?: PartialTheme;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* These are default values for the context. These defaults are typically
|
|
||||||
* overwritten by the Synthetics App upon its invocation.
|
|
||||||
*/
|
|
||||||
const defaultContext: SyntheticsThemeContextValues = {
|
|
||||||
colors: {
|
|
||||||
danger: euiLightVars.euiColorDanger,
|
|
||||||
dangerBehindText: euiDarkVars.euiColorVis9_behindText,
|
|
||||||
mean: euiLightVars.euiColorPrimary,
|
|
||||||
range: euiLightVars.euiFocusBackgroundColor,
|
|
||||||
success: euiLightVars.euiColorSuccess,
|
|
||||||
warning: euiLightVars.euiColorWarning,
|
|
||||||
gray: euiLightVars.euiColorLightShade,
|
|
||||||
lightestShade: euiLightVars.euiColorLightestShade,
|
|
||||||
},
|
|
||||||
chartTheme: {
|
|
||||||
baseTheme: LIGHT_THEME,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export const SyntheticsThemeContext = createContext(defaultContext);
|
|
||||||
|
|
||||||
interface ThemeContextProps {
|
|
||||||
darkMode: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const SyntheticsThemeContextProvider: FC<PropsWithChildren<ThemeContextProps>> = ({
|
|
||||||
darkMode,
|
|
||||||
children,
|
|
||||||
}) => {
|
|
||||||
let colors: SyntheticsAppColors;
|
|
||||||
if (darkMode) {
|
|
||||||
colors = {
|
|
||||||
danger: euiDarkVars.euiColorVis9,
|
|
||||||
dangerBehindText: euiDarkVars.euiColorVis9_behindText,
|
|
||||||
mean: euiDarkVars.euiColorPrimary,
|
|
||||||
gray: euiDarkVars.euiColorLightShade,
|
|
||||||
range: euiDarkVars.euiFocusBackgroundColor,
|
|
||||||
success: euiDarkVars.euiColorSuccess,
|
|
||||||
warning: euiDarkVars.euiColorWarning,
|
|
||||||
lightestShade: euiDarkVars.euiColorLightestShade,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
colors = {
|
|
||||||
danger: euiLightVars.euiColorVis9,
|
|
||||||
dangerBehindText: euiLightVars.euiColorVis9_behindText,
|
|
||||||
mean: euiLightVars.euiColorPrimary,
|
|
||||||
gray: euiLightVars.euiColorLightShade,
|
|
||||||
range: euiLightVars.euiFocusBackgroundColor,
|
|
||||||
success: euiLightVars.euiColorSuccess,
|
|
||||||
warning: euiLightVars.euiColorWarning,
|
|
||||||
lightestShade: euiLightVars.euiColorLightestShade,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
const value = useMemo(() => {
|
|
||||||
return {
|
|
||||||
colors,
|
|
||||||
chartTheme: {
|
|
||||||
baseTheme: darkMode ? DARK_THEME : LIGHT_THEME,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}, [colors, darkMode]);
|
|
||||||
|
|
||||||
return <SyntheticsThemeContext.Provider value={value} children={children} />;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useSyntheticsThemeContext = () => useContext(SyntheticsThemeContext);
|
|
|
@ -8,7 +8,8 @@
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { LocatorClient } from '@kbn/share-plugin/common/url_service/locators';
|
import { LocatorClient } from '@kbn/share-plugin/common/url_service/locators';
|
||||||
import { syntheticsEditMonitorLocatorID } from '@kbn/observability-plugin/common';
|
import { syntheticsEditMonitorLocatorID } from '@kbn/observability-plugin/common';
|
||||||
import { useSyntheticsStartPlugins } from '../contexts';
|
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||||
|
import { ClientPluginsStart } from '../../../plugin';
|
||||||
|
|
||||||
export function useEditMonitorLocator({
|
export function useEditMonitorLocator({
|
||||||
configId,
|
configId,
|
||||||
|
@ -18,7 +19,7 @@ export function useEditMonitorLocator({
|
||||||
locators?: LocatorClient;
|
locators?: LocatorClient;
|
||||||
}) {
|
}) {
|
||||||
const [editUrl, setEditUrl] = useState<string | undefined>(undefined);
|
const [editUrl, setEditUrl] = useState<string | undefined>(undefined);
|
||||||
const syntheticsLocators = useSyntheticsStartPlugins()?.share?.url.locators;
|
const syntheticsLocators = useKibana<ClientPluginsStart>().services.share?.url.locators;
|
||||||
const locator = (locators || syntheticsLocators)?.get(syntheticsEditMonitorLocatorID);
|
const locator = (locators || syntheticsLocators)?.get(syntheticsEditMonitorLocatorID);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
|
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { syntheticsMonitorDetailLocatorID } from '@kbn/observability-plugin/common';
|
import { syntheticsMonitorDetailLocatorID } from '@kbn/observability-plugin/common';
|
||||||
import { useSyntheticsStartPlugins } from '../contexts';
|
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||||
|
import { ClientPluginsStart } from '../../../plugin';
|
||||||
|
|
||||||
export function useMonitorDetailLocator({
|
export function useMonitorDetailLocator({
|
||||||
configId,
|
configId,
|
||||||
|
@ -17,7 +18,7 @@ export function useMonitorDetailLocator({
|
||||||
locationId?: string;
|
locationId?: string;
|
||||||
}) {
|
}) {
|
||||||
const [monitorUrl, setMonitorUrl] = useState<string | undefined>(undefined);
|
const [monitorUrl, setMonitorUrl] = useState<string | undefined>(undefined);
|
||||||
const locator = useSyntheticsStartPlugins()?.share?.url.locators.get(
|
const locator = useKibana<ClientPluginsStart>().services?.share?.url.locators.get(
|
||||||
syntheticsMonitorDetailLocatorID
|
syntheticsMonitorDetailLocatorID
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -19,19 +19,19 @@ import { store } from '../../../state';
|
||||||
import type { StatusRuleParams } from '../../../../../../common/rules/status_rule';
|
import type { StatusRuleParams } from '../../../../../../common/rules/status_rule';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
core: CoreStart;
|
coreStart: CoreStart;
|
||||||
plugins: ClientPluginsStart;
|
plugins: ClientPluginsStart;
|
||||||
params: RuleTypeParamsExpressionProps<StatusRuleParams>;
|
params: RuleTypeParamsExpressionProps<StatusRuleParams>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line import/no-default-export
|
// eslint-disable-next-line import/no-default-export
|
||||||
export default function MonitorStatusAlert({ core, plugins, params }: Props) {
|
export default function MonitorStatusAlert({ coreStart, plugins, params }: Props) {
|
||||||
kibanaService.core = core;
|
kibanaService.coreStart = coreStart;
|
||||||
const queryClient = new QueryClient();
|
const queryClient = new QueryClient();
|
||||||
return (
|
return (
|
||||||
<ReduxProvider store={store}>
|
<ReduxProvider store={store}>
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<KibanaContextProvider services={{ ...core, ...plugins }}>
|
<KibanaContextProvider services={{ ...coreStart, ...plugins }}>
|
||||||
<EuiText>
|
<EuiText>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id="xpack.synthetics.alertRule.monitorStatus.description"
|
id="xpack.synthetics.alertRule.monitorStatus.description"
|
||||||
|
|
|
@ -17,18 +17,18 @@ import { kibanaService } from '../../../../../utils/kibana_service';
|
||||||
import { store } from '../../../state';
|
import { store } from '../../../state';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
core: CoreStart;
|
coreStart: CoreStart;
|
||||||
plugins: ClientPluginsStart;
|
plugins: ClientPluginsStart;
|
||||||
ruleParams: RuleTypeParamsExpressionProps<TLSParams>['ruleParams'];
|
ruleParams: RuleTypeParamsExpressionProps<TLSParams>['ruleParams'];
|
||||||
setRuleParams: RuleTypeParamsExpressionProps<TLSParams>['setRuleParams'];
|
setRuleParams: RuleTypeParamsExpressionProps<TLSParams>['setRuleParams'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line import/no-default-export
|
// eslint-disable-next-line import/no-default-export
|
||||||
export default function TLSAlert({ core, plugins, ruleParams, setRuleParams }: Props) {
|
export default function TLSAlert({ coreStart, plugins, ruleParams, setRuleParams }: Props) {
|
||||||
kibanaService.core = core;
|
kibanaService.coreStart = coreStart;
|
||||||
return (
|
return (
|
||||||
<ReduxProvider store={store}>
|
<ReduxProvider store={store}>
|
||||||
<KibanaContextProvider services={{ ...core, ...plugins }}>
|
<KibanaContextProvider services={{ ...coreStart, ...plugins }}>
|
||||||
<TLSRuleComponent ruleParams={ruleParams} setRuleParams={setRuleParams} />
|
<TLSRuleComponent ruleParams={ruleParams} setRuleParams={setRuleParams} />
|
||||||
</KibanaContextProvider>
|
</KibanaContextProvider>
|
||||||
</ReduxProvider>
|
</ReduxProvider>
|
||||||
|
|
|
@ -33,7 +33,7 @@ export const initMonitorStatusAlertType: AlertTypeInitializer = ({
|
||||||
return `${docLinks.links.observability.syntheticsAlerting}`;
|
return `${docLinks.links.observability.syntheticsAlerting}`;
|
||||||
},
|
},
|
||||||
ruleParamsExpression: (paramProps: RuleTypeParamsExpressionProps<StatusRuleParams>) => (
|
ruleParamsExpression: (paramProps: RuleTypeParamsExpressionProps<StatusRuleParams>) => (
|
||||||
<MonitorStatusAlert core={core} plugins={plugins} params={paramProps} />
|
<MonitorStatusAlert coreStart={core} plugins={plugins} params={paramProps} />
|
||||||
),
|
),
|
||||||
validate: (_ruleParams: StatusRuleParams) => {
|
validate: (_ruleParams: StatusRuleParams) => {
|
||||||
return { errors: {} };
|
return { errors: {} };
|
||||||
|
|
|
@ -31,7 +31,7 @@ export const initTlsAlertType: AlertTypeInitializer = ({
|
||||||
},
|
},
|
||||||
ruleParamsExpression: (params: RuleTypeParamsExpressionProps<TLSParams>) => (
|
ruleParamsExpression: (params: RuleTypeParamsExpressionProps<TLSParams>) => (
|
||||||
<TLSAlert
|
<TLSAlert
|
||||||
core={core}
|
coreStart={core}
|
||||||
plugins={plugins}
|
plugins={plugins}
|
||||||
ruleParams={params.ruleParams}
|
ruleParams={params.ruleParams}
|
||||||
setRuleParams={params.setRuleParams}
|
setRuleParams={params.setRuleParams}
|
||||||
|
|
|
@ -8,21 +8,17 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import { i18n as i18nFormatter } from '@kbn/i18n';
|
import { i18n as i18nFormatter } from '@kbn/i18n';
|
||||||
import { AppMountParameters, CoreStart } from '@kbn/core/public';
|
import { AppMountParameters } from '@kbn/core-application-browser';
|
||||||
|
import { kibanaService } from '../../utils/kibana_service';
|
||||||
import { SyntheticsAppProps } from './contexts';
|
import { SyntheticsAppProps } from './contexts';
|
||||||
import { getIntegratedAppAvailability } from './utils/adapters';
|
import { getIntegratedAppAvailability } from './utils/adapters';
|
||||||
import { DEFAULT_TIMEPICKER_QUICK_RANGES, INTEGRATED_SOLUTIONS } from '../../../common/constants';
|
import { DEFAULT_TIMEPICKER_QUICK_RANGES, INTEGRATED_SOLUTIONS } from '../../../common/constants';
|
||||||
import { SyntheticsApp } from './synthetics_app';
|
import { SyntheticsApp } from './synthetics_app';
|
||||||
import { ClientPluginsSetup, ClientPluginsStart } from '../../plugin';
|
|
||||||
|
|
||||||
export function renderApp(
|
export const getSyntheticsAppProps = (): SyntheticsAppProps => {
|
||||||
core: CoreStart,
|
const { isDev, isServerless, coreStart, startPlugins, setupPlugins, appMountParameters } =
|
||||||
plugins: ClientPluginsSetup,
|
kibanaService;
|
||||||
startPlugins: ClientPluginsStart,
|
|
||||||
appMountParameters: AppMountParameters,
|
|
||||||
isDev: boolean,
|
|
||||||
isServerless: boolean
|
|
||||||
) {
|
|
||||||
const {
|
const {
|
||||||
application: { capabilities },
|
application: { capabilities },
|
||||||
chrome: { setBadge, setHelpExtension },
|
chrome: { setBadge, setHelpExtension },
|
||||||
|
@ -30,7 +26,7 @@ export function renderApp(
|
||||||
http: { basePath },
|
http: { basePath },
|
||||||
i18n,
|
i18n,
|
||||||
theme,
|
theme,
|
||||||
} = core;
|
} = kibanaService.coreStart;
|
||||||
|
|
||||||
const { apm, infrastructure, logs } = getIntegratedAppAvailability(
|
const { apm, infrastructure, logs } = getIntegratedAppAvailability(
|
||||||
capabilities,
|
capabilities,
|
||||||
|
@ -40,24 +36,22 @@ export function renderApp(
|
||||||
const canSave = (capabilities.uptime.save ?? false) as boolean; // TODO: Determine for synthetics
|
const canSave = (capabilities.uptime.save ?? false) as boolean; // TODO: Determine for synthetics
|
||||||
const darkMode = theme.getTheme().darkMode;
|
const darkMode = theme.getTheme().darkMode;
|
||||||
|
|
||||||
const props: SyntheticsAppProps = {
|
return {
|
||||||
isDev,
|
isDev,
|
||||||
plugins,
|
setupPlugins,
|
||||||
canSave,
|
canSave,
|
||||||
core,
|
coreStart,
|
||||||
i18n,
|
i18n,
|
||||||
startPlugins,
|
startPlugins,
|
||||||
basePath: basePath.get(),
|
basePath: basePath.get(),
|
||||||
darkMode,
|
darkMode,
|
||||||
commonlyUsedRanges: core.uiSettings.get(DEFAULT_TIMEPICKER_QUICK_RANGES),
|
commonlyUsedRanges: coreStart.uiSettings.get(DEFAULT_TIMEPICKER_QUICK_RANGES),
|
||||||
isApmAvailable: apm,
|
isApmAvailable: apm,
|
||||||
isInfraAvailable: infrastructure,
|
isInfraAvailable: infrastructure,
|
||||||
isLogsAvailable: logs,
|
isLogsAvailable: logs,
|
||||||
renderGlobalHelpControls: () =>
|
renderGlobalHelpControls: () =>
|
||||||
setHelpExtension({
|
setHelpExtension({
|
||||||
appName: i18nFormatter.translate('xpack.synthetics.header.appName', {
|
appName: SYNTHETICS_APP_NAME,
|
||||||
defaultMessage: 'Synthetics',
|
|
||||||
}),
|
|
||||||
links: [
|
links: [
|
||||||
{
|
{
|
||||||
linkType: 'documentation',
|
linkType: 'documentation',
|
||||||
|
@ -72,13 +66,21 @@ export function renderApp(
|
||||||
setBadge,
|
setBadge,
|
||||||
appMountParameters,
|
appMountParameters,
|
||||||
isServerless,
|
isServerless,
|
||||||
setBreadcrumbs: startPlugins.serverless?.setBreadcrumbs ?? core.chrome.setBreadcrumbs,
|
setBreadcrumbs: startPlugins.serverless?.setBreadcrumbs ?? coreStart.chrome.setBreadcrumbs,
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export function renderApp(appMountParameters: AppMountParameters) {
|
||||||
|
const props: SyntheticsAppProps = getSyntheticsAppProps();
|
||||||
|
|
||||||
ReactDOM.render(<SyntheticsApp {...props} />, appMountParameters.element);
|
ReactDOM.render(<SyntheticsApp {...props} />, appMountParameters.element);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
startPlugins.data.search.session.clear();
|
props.startPlugins.data.search.session.clear();
|
||||||
ReactDOM.unmountComponentAtNode(appMountParameters.element);
|
ReactDOM.unmountComponentAtNode(appMountParameters.element);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SYNTHETICS_APP_NAME = i18nFormatter.translate('xpack.synthetics.header.appName', {
|
||||||
|
defaultMessage: 'Synthetics',
|
||||||
|
});
|
||||||
|
|
|
@ -11,5 +11,5 @@ import { toMountPoint } from '@kbn/react-kibana-mount';
|
||||||
import { kibanaService } from '../../../../utils/kibana_service';
|
import { kibanaService } from '../../../../utils/kibana_service';
|
||||||
|
|
||||||
export function toastTitle({ title, testAttribute }: { title: string; testAttribute?: string }) {
|
export function toastTitle({ title, testAttribute }: { title: string; testAttribute?: string }) {
|
||||||
return toMountPoint(<p data-test-sub={testAttribute}>{title}</p>, kibanaService.core);
|
return toMountPoint(<p data-test-sub={testAttribute}>{title}</p>, kibanaService.coreStart);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,11 @@ import { createReducer } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
import { OverviewStatusState } from '../../../../../common/runtime_types';
|
import { OverviewStatusState } from '../../../../../common/runtime_types';
|
||||||
import { IHttpSerializedFetchError } from '..';
|
import { IHttpSerializedFetchError } from '..';
|
||||||
import { clearOverviewStatusErrorAction, fetchOverviewStatusAction } from './actions';
|
import {
|
||||||
|
clearOverviewStatusErrorAction,
|
||||||
|
fetchOverviewStatusAction,
|
||||||
|
quietFetchOverviewStatusAction,
|
||||||
|
} from './actions';
|
||||||
|
|
||||||
export interface OverviewStatusStateReducer {
|
export interface OverviewStatusStateReducer {
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
|
@ -29,6 +33,10 @@ export const overviewStatusReducer = createReducer(initialState, (builder) => {
|
||||||
builder
|
builder
|
||||||
.addCase(fetchOverviewStatusAction.get, (state) => {
|
.addCase(fetchOverviewStatusAction.get, (state) => {
|
||||||
state.status = null;
|
state.status = null;
|
||||||
|
state.loading = true;
|
||||||
|
})
|
||||||
|
.addCase(quietFetchOverviewStatusAction.get, (state) => {
|
||||||
|
state.loading = true;
|
||||||
})
|
})
|
||||||
.addCase(fetchOverviewStatusAction.success, (state, action) => {
|
.addCase(fetchOverviewStatusAction.success, (state, action) => {
|
||||||
state.status = {
|
state.status = {
|
||||||
|
@ -36,9 +44,11 @@ export const overviewStatusReducer = createReducer(initialState, (builder) => {
|
||||||
allConfigs: { ...action.payload.upConfigs, ...action.payload.downConfigs },
|
allConfigs: { ...action.payload.upConfigs, ...action.payload.downConfigs },
|
||||||
};
|
};
|
||||||
state.loaded = true;
|
state.loaded = true;
|
||||||
|
state.loading = false;
|
||||||
})
|
})
|
||||||
.addCase(fetchOverviewStatusAction.fail, (state, action) => {
|
.addCase(fetchOverviewStatusAction.fail, (state, action) => {
|
||||||
state.error = action.payload;
|
state.error = action.payload;
|
||||||
|
state.loading = false;
|
||||||
})
|
})
|
||||||
.addCase(clearOverviewStatusErrorAction, (state) => {
|
.addCase(clearOverviewStatusErrorAction, (state) => {
|
||||||
state.error = null;
|
state.error = null;
|
||||||
|
|
|
@ -8,5 +8,5 @@
|
||||||
import { SyntheticsAppState } from '../root_reducer';
|
import { SyntheticsAppState } from '../root_reducer';
|
||||||
|
|
||||||
export const selectOverviewStatus = ({
|
export const selectOverviewStatus = ({
|
||||||
overviewStatus: { status, error, loaded },
|
overviewStatus: { status, error, loaded, loading },
|
||||||
}: SyntheticsAppState) => ({ status, error, loaded });
|
}: SyntheticsAppState) => ({ status, error, loaded, loading });
|
||||||
|
|
|
@ -81,13 +81,13 @@ export function* setDynamicSettingsEffect() {
|
||||||
yield call(setDynamicSettings, { settings: action.payload });
|
yield call(setDynamicSettings, { settings: action.payload });
|
||||||
yield put(updateDefaultAlertingAction.get());
|
yield put(updateDefaultAlertingAction.get());
|
||||||
yield put(setDynamicSettingsAction.success(action.payload));
|
yield put(setDynamicSettingsAction.success(action.payload));
|
||||||
kibanaService.core.notifications.toasts.addSuccess(
|
kibanaService.coreSetup.notifications.toasts.addSuccess(
|
||||||
i18n.translate('xpack.synthetics.settings.saveSuccess', {
|
i18n.translate('xpack.synthetics.settings.saveSuccess', {
|
||||||
defaultMessage: 'Settings saved!',
|
defaultMessage: 'Settings saved!',
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
kibanaService.core.notifications.toasts.addError(err, {
|
kibanaService.coreSetup.notifications.toasts.addError(err, {
|
||||||
title: couldNotSaveSettingsText,
|
title: couldNotSaveSettingsText,
|
||||||
});
|
});
|
||||||
yield put(setDynamicSettingsAction.fail(err));
|
yield put(setDynamicSettingsAction.fail(err));
|
||||||
|
|
|
@ -67,7 +67,7 @@ export function fetchEffectFactory<T, R, S, F>(
|
||||||
if (typeof onFailure === 'function') {
|
if (typeof onFailure === 'function') {
|
||||||
onFailure?.(error);
|
onFailure?.(error);
|
||||||
} else if (typeof onFailure === 'string') {
|
} else if (typeof onFailure === 'string') {
|
||||||
kibanaService.core.notifications.toasts.addError(
|
kibanaService.coreSetup.notifications.toasts.addError(
|
||||||
{ ...error, message: serializedError.body?.message ?? error.message },
|
{ ...error, message: serializedError.body?.message ?? error.message },
|
||||||
{
|
{
|
||||||
title: onFailure,
|
title: onFailure,
|
||||||
|
@ -104,7 +104,7 @@ export function fetchEffectFactory<T, R, S, F>(
|
||||||
if (typeof onSuccess === 'function') {
|
if (typeof onSuccess === 'function') {
|
||||||
onSuccess(response as R);
|
onSuccess(response as R);
|
||||||
} else if (onSuccess && typeof onSuccess === 'string') {
|
} else if (onSuccess && typeof onSuccess === 'string') {
|
||||||
kibanaService.core.notifications.toasts.addSuccess(onSuccess);
|
kibanaService.coreSetup.notifications.toasts.addSuccess(onSuccess);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
@ -6,42 +6,30 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { Provider as ReduxProvider } from 'react-redux';
|
|
||||||
|
|
||||||
import { APP_WRAPPER_CLASS } from '@kbn/core/public';
|
import { APP_WRAPPER_CLASS } from '@kbn/core/public';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common';
|
|
||||||
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
|
|
||||||
import { InspectorContextProvider } from '@kbn/observability-shared-plugin/public';
|
import { InspectorContextProvider } from '@kbn/observability-shared-plugin/public';
|
||||||
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
|
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
|
||||||
import { KibanaThemeProvider } from '@kbn/react-kibana-context-theme';
|
import { KibanaThemeProvider } from '@kbn/react-kibana-context-theme';
|
||||||
import { RedirectAppLinks } from '@kbn/shared-ux-link-redirect-app';
|
|
||||||
import { Router } from '@kbn/shared-ux-router';
|
import { Router } from '@kbn/shared-ux-router';
|
||||||
|
|
||||||
|
import { SyntheticsSharedContext } from './contexts/synthetics_shared_context';
|
||||||
import { kibanaService } from '../../utils/kibana_service';
|
import { kibanaService } from '../../utils/kibana_service';
|
||||||
import { ActionMenu } from './components/common/header/action_menu';
|
import { ActionMenu } from './components/common/header/action_menu';
|
||||||
import { TestNowModeFlyoutContainer } from './components/test_now_mode/test_now_mode_flyout_container';
|
import { TestNowModeFlyoutContainer } from './components/test_now_mode/test_now_mode_flyout_container';
|
||||||
import {
|
import { SyntheticsAppProps, SyntheticsSettingsContextProvider } from './contexts';
|
||||||
SyntheticsAppProps,
|
|
||||||
SyntheticsRefreshContextProvider,
|
|
||||||
SyntheticsSettingsContextProvider,
|
|
||||||
SyntheticsStartupPluginsContextProvider,
|
|
||||||
SyntheticsThemeContextProvider,
|
|
||||||
} from './contexts';
|
|
||||||
import { SyntheticsDataViewContextProvider } from './contexts/synthetics_data_view_context';
|
|
||||||
import { PageRouter } from './routes';
|
import { PageRouter } from './routes';
|
||||||
import { setBasePath, storage, store } from './state';
|
import { setBasePath, store } from './state';
|
||||||
|
|
||||||
const Application = (props: SyntheticsAppProps) => {
|
const Application = (props: SyntheticsAppProps) => {
|
||||||
const {
|
const {
|
||||||
basePath,
|
basePath,
|
||||||
canSave,
|
canSave,
|
||||||
core,
|
coreStart,
|
||||||
darkMode,
|
startPlugins,
|
||||||
plugins,
|
|
||||||
renderGlobalHelpControls,
|
renderGlobalHelpControls,
|
||||||
setBadge,
|
setBadge,
|
||||||
startPlugins,
|
|
||||||
appMountParameters,
|
appMountParameters,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
|
@ -62,16 +50,17 @@ const Application = (props: SyntheticsAppProps) => {
|
||||||
);
|
);
|
||||||
}, [canSave, renderGlobalHelpControls, setBadge]);
|
}, [canSave, renderGlobalHelpControls, setBadge]);
|
||||||
|
|
||||||
kibanaService.core = core;
|
|
||||||
kibanaService.startPlugins = startPlugins;
|
|
||||||
kibanaService.theme = props.appMountParameters.theme$;
|
kibanaService.theme = props.appMountParameters.theme$;
|
||||||
|
|
||||||
store.dispatch(setBasePath(basePath));
|
store.dispatch(setBasePath(basePath));
|
||||||
|
|
||||||
|
const PresentationContextProvider =
|
||||||
|
startPlugins.presentationUtil?.ContextProvider ?? React.Fragment;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<KibanaRenderContextProvider {...core}>
|
<KibanaRenderContextProvider {...coreStart}>
|
||||||
<KibanaThemeProvider
|
<KibanaThemeProvider
|
||||||
theme={core.theme}
|
theme={coreStart.theme}
|
||||||
modify={{
|
modify={{
|
||||||
breakpoint: {
|
breakpoint: {
|
||||||
xxl: 1600,
|
xxl: 1600,
|
||||||
|
@ -79,54 +68,21 @@ const Application = (props: SyntheticsAppProps) => {
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ReduxProvider store={store}>
|
<SyntheticsSharedContext {...props}>
|
||||||
<KibanaContextProvider
|
<PresentationContextProvider>
|
||||||
services={{
|
<Router history={appMountParameters.history}>
|
||||||
...core,
|
<SyntheticsSettingsContextProvider {...props}>
|
||||||
...plugins,
|
<div className={APP_WRAPPER_CLASS} data-test-subj="syntheticsApp">
|
||||||
storage,
|
<InspectorContextProvider>
|
||||||
data: startPlugins.data,
|
<PageRouter />
|
||||||
inspector: startPlugins.inspector,
|
<ActionMenu appMountParameters={appMountParameters} />
|
||||||
triggersActionsUi: startPlugins.triggersActionsUi,
|
<TestNowModeFlyoutContainer />
|
||||||
observability: startPlugins.observability,
|
</InspectorContextProvider>
|
||||||
observabilityShared: startPlugins.observabilityShared,
|
</div>
|
||||||
observabilityAIAssistant: startPlugins.observabilityAIAssistant,
|
</SyntheticsSettingsContextProvider>
|
||||||
exploratoryView: startPlugins.exploratoryView,
|
</Router>
|
||||||
cases: startPlugins.cases,
|
</PresentationContextProvider>
|
||||||
spaces: startPlugins.spaces,
|
</SyntheticsSharedContext>
|
||||||
fleet: startPlugins.fleet,
|
|
||||||
unifiedSearch: startPlugins.unifiedSearch,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<SyntheticsDataViewContextProvider dataViews={startPlugins.dataViews}>
|
|
||||||
<Router history={appMountParameters.history}>
|
|
||||||
<EuiThemeProvider darkMode={darkMode}>
|
|
||||||
<SyntheticsRefreshContextProvider>
|
|
||||||
<SyntheticsSettingsContextProvider {...props}>
|
|
||||||
<SyntheticsThemeContextProvider darkMode={darkMode}>
|
|
||||||
<SyntheticsStartupPluginsContextProvider {...startPlugins}>
|
|
||||||
<div className={APP_WRAPPER_CLASS} data-test-subj="syntheticsApp">
|
|
||||||
<RedirectAppLinks
|
|
||||||
coreStart={{
|
|
||||||
application: core.application,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<InspectorContextProvider>
|
|
||||||
<PageRouter />
|
|
||||||
<ActionMenu appMountParameters={appMountParameters} />
|
|
||||||
<TestNowModeFlyoutContainer />
|
|
||||||
</InspectorContextProvider>
|
|
||||||
</RedirectAppLinks>
|
|
||||||
</div>
|
|
||||||
</SyntheticsStartupPluginsContextProvider>
|
|
||||||
</SyntheticsThemeContextProvider>
|
|
||||||
</SyntheticsSettingsContextProvider>
|
|
||||||
</SyntheticsRefreshContextProvider>
|
|
||||||
</EuiThemeProvider>
|
|
||||||
</Router>
|
|
||||||
</SyntheticsDataViewContextProvider>
|
|
||||||
</KibanaContextProvider>
|
|
||||||
</ReduxProvider>
|
|
||||||
</KibanaThemeProvider>
|
</KibanaThemeProvider>
|
||||||
</KibanaRenderContextProvider>
|
</KibanaRenderContextProvider>
|
||||||
);
|
);
|
||||||
|
|
|
@ -34,10 +34,7 @@ import { MountWithReduxProvider } from './helper_with_redux';
|
||||||
import { AppState } from '../../state';
|
import { AppState } from '../../state';
|
||||||
import { stringifyUrlParams } from '../url_params';
|
import { stringifyUrlParams } from '../url_params';
|
||||||
import { ClientPluginsStart } from '../../../../plugin';
|
import { ClientPluginsStart } from '../../../../plugin';
|
||||||
import {
|
import { SyntheticsRefreshContextProvider } from '../../contexts';
|
||||||
SyntheticsRefreshContextProvider,
|
|
||||||
SyntheticsStartupPluginsContextProvider,
|
|
||||||
} from '../../contexts';
|
|
||||||
import { kibanaService } from '../../../../utils/kibana_service';
|
import { kibanaService } from '../../../../utils/kibana_service';
|
||||||
|
|
||||||
type DeepPartial<T> = {
|
type DeepPartial<T> = {
|
||||||
|
@ -182,21 +179,14 @@ export function MockKibanaProvider<ExtraCore>({
|
||||||
}: MockKibanaProviderProps<ExtraCore>) {
|
}: MockKibanaProviderProps<ExtraCore>) {
|
||||||
const coreOptions = merge({}, mockCore(), core);
|
const coreOptions = merge({}, mockCore(), core);
|
||||||
|
|
||||||
kibanaService.core = coreOptions as any;
|
kibanaService.coreStart = coreOptions as any;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<KibanaContextProvider services={{ ...coreOptions }} {...kibanaProps}>
|
<KibanaContextProvider services={{ ...coreOptions }} {...kibanaProps}>
|
||||||
<SyntheticsRefreshContextProvider>
|
<SyntheticsRefreshContextProvider>
|
||||||
<SyntheticsStartupPluginsContextProvider
|
<EuiThemeProvider darkMode={false}>
|
||||||
data={(coreOptions as any).data}
|
<I18nProvider>{children}</I18nProvider>
|
||||||
observability={(coreOptions as any).observability}
|
</EuiThemeProvider>
|
||||||
observabilityShared={(coreOptions as any).observabilityShared}
|
|
||||||
exploratoryView={(coreOptions as any).exploratoryView}
|
|
||||||
>
|
|
||||||
<EuiThemeProvider darkMode={false}>
|
|
||||||
<I18nProvider>{children}</I18nProvider>
|
|
||||||
</EuiThemeProvider>
|
|
||||||
</SyntheticsStartupPluginsContextProvider>
|
|
||||||
</SyntheticsRefreshContextProvider>
|
</SyntheticsRefreshContextProvider>
|
||||||
</KibanaContextProvider>
|
</KibanaContextProvider>
|
||||||
);
|
);
|
||||||
|
|
|
@ -25,7 +25,7 @@ import type {
|
||||||
ExploratoryViewPublicSetup,
|
ExploratoryViewPublicSetup,
|
||||||
ExploratoryViewPublicStart,
|
ExploratoryViewPublicStart,
|
||||||
} from '@kbn/exploratory-view-plugin/public';
|
} from '@kbn/exploratory-view-plugin/public';
|
||||||
import { EmbeddableStart } from '@kbn/embeddable-plugin/public';
|
import { EmbeddableStart, EmbeddableSetup } from '@kbn/embeddable-plugin/public';
|
||||||
import {
|
import {
|
||||||
TriggersAndActionsUIPublicPluginSetup,
|
TriggersAndActionsUIPublicPluginSetup,
|
||||||
TriggersAndActionsUIPublicPluginStart,
|
TriggersAndActionsUIPublicPluginStart,
|
||||||
|
@ -50,12 +50,18 @@ import type {
|
||||||
ObservabilitySharedPluginSetup,
|
ObservabilitySharedPluginSetup,
|
||||||
ObservabilitySharedPluginStart,
|
ObservabilitySharedPluginStart,
|
||||||
} from '@kbn/observability-shared-plugin/public';
|
} from '@kbn/observability-shared-plugin/public';
|
||||||
|
|
||||||
import { LicenseManagementUIPluginSetup } from '@kbn/license-management-plugin/public/plugin';
|
import { LicenseManagementUIPluginSetup } from '@kbn/license-management-plugin/public/plugin';
|
||||||
import {
|
import {
|
||||||
ObservabilityAIAssistantPublicSetup,
|
ObservabilityAIAssistantPublicSetup,
|
||||||
ObservabilityAIAssistantPublicStart,
|
ObservabilityAIAssistantPublicStart,
|
||||||
} from '@kbn/observability-ai-assistant-plugin/public';
|
} from '@kbn/observability-ai-assistant-plugin/public';
|
||||||
import { ServerlessPluginSetup, ServerlessPluginStart } from '@kbn/serverless/public';
|
import { ServerlessPluginSetup, ServerlessPluginStart } from '@kbn/serverless/public';
|
||||||
|
import type { UiActionsSetup } from '@kbn/ui-actions-plugin/public';
|
||||||
|
import type { PresentationUtilPluginStart } from '@kbn/presentation-util-plugin/public';
|
||||||
|
import { DashboardStart, DashboardSetup } from '@kbn/dashboard-plugin/public';
|
||||||
|
import { registerSyntheticsEmbeddables } from './apps/embeddables/register_embeddables';
|
||||||
|
import { kibanaService } from './utils/kibana_service';
|
||||||
import { PLUGIN } from '../common/constants/plugin';
|
import { PLUGIN } from '../common/constants/plugin';
|
||||||
import { OVERVIEW_ROUTE } from '../common/constants/ui';
|
import { OVERVIEW_ROUTE } from '../common/constants/ui';
|
||||||
import { locators } from './apps/locators';
|
import { locators } from './apps/locators';
|
||||||
|
@ -72,7 +78,10 @@ export interface ClientPluginsSetup {
|
||||||
share: SharePluginSetup;
|
share: SharePluginSetup;
|
||||||
triggersActionsUi: TriggersAndActionsUIPublicPluginSetup;
|
triggersActionsUi: TriggersAndActionsUIPublicPluginSetup;
|
||||||
cloud?: CloudSetup;
|
cloud?: CloudSetup;
|
||||||
|
embeddable: EmbeddableSetup;
|
||||||
serverless?: ServerlessPluginSetup;
|
serverless?: ServerlessPluginSetup;
|
||||||
|
uiActions: UiActionsSetup;
|
||||||
|
dashboard: DashboardSetup;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ClientPluginsStart {
|
export interface ClientPluginsStart {
|
||||||
|
@ -102,6 +111,8 @@ export interface ClientPluginsStart {
|
||||||
usageCollection: UsageCollectionStart;
|
usageCollection: UsageCollectionStart;
|
||||||
serverless: ServerlessPluginStart;
|
serverless: ServerlessPluginStart;
|
||||||
licenseManagement?: LicenseManagementUIPluginSetup;
|
licenseManagement?: LicenseManagementUIPluginSetup;
|
||||||
|
presentationUtil: PresentationUtilPluginStart;
|
||||||
|
dashboard: DashboardStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SyntheticsPluginServices extends Partial<CoreStart> {
|
export interface SyntheticsPluginServices extends Partial<CoreStart> {
|
||||||
|
@ -123,12 +134,25 @@ export class SyntheticsPlugin
|
||||||
this._packageInfo = initContext.env.packageInfo;
|
this._packageInfo = initContext.env.packageInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setup(core: CoreSetup<ClientPluginsStart, unknown>, plugins: ClientPluginsSetup): void {
|
public setup(
|
||||||
|
coreSetup: CoreSetup<ClientPluginsStart, unknown>,
|
||||||
|
plugins: ClientPluginsSetup
|
||||||
|
): void {
|
||||||
locators.forEach((locator) => {
|
locators.forEach((locator) => {
|
||||||
plugins.share.url.locators.create(locator);
|
plugins.share.url.locators.create(locator);
|
||||||
});
|
});
|
||||||
|
|
||||||
registerSyntheticsRoutesWithNavigation(core, plugins);
|
registerSyntheticsRoutesWithNavigation(coreSetup, plugins);
|
||||||
|
|
||||||
|
coreSetup.getStartServices().then(([coreStart, clientPluginsStart]) => {
|
||||||
|
kibanaService.init({
|
||||||
|
coreSetup,
|
||||||
|
coreStart,
|
||||||
|
startPlugins: clientPluginsStart,
|
||||||
|
isDev: this.initContext.env.mode.dev,
|
||||||
|
isServerless: this._isServerless,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
const appKeywords = [
|
const appKeywords = [
|
||||||
'Synthetics',
|
'Synthetics',
|
||||||
|
@ -149,7 +173,7 @@ export class SyntheticsPlugin
|
||||||
];
|
];
|
||||||
|
|
||||||
// Register the Synthetics UI plugin
|
// Register the Synthetics UI plugin
|
||||||
core.application.register({
|
coreSetup.application.register({
|
||||||
id: 'synthetics',
|
id: 'synthetics',
|
||||||
euiIconType: 'logoObservability',
|
euiIconType: 'logoObservability',
|
||||||
order: 8400,
|
order: 8400,
|
||||||
|
@ -177,23 +201,20 @@ export class SyntheticsPlugin
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
mount: async (params: AppMountParameters) => {
|
mount: async (params: AppMountParameters) => {
|
||||||
const [coreStart, corePlugins] = await core.getStartServices();
|
kibanaService.appMountParameters = params;
|
||||||
|
|
||||||
const { renderApp } = await import('./apps/synthetics/render_app');
|
const { renderApp } = await import('./apps/synthetics/render_app');
|
||||||
return renderApp(
|
await coreSetup.getStartServices();
|
||||||
coreStart,
|
|
||||||
plugins,
|
return renderApp(params);
|
||||||
corePlugins,
|
|
||||||
params,
|
|
||||||
this.initContext.env.mode.dev,
|
|
||||||
this._isServerless
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
registerSyntheticsEmbeddables(coreSetup, plugins);
|
||||||
}
|
}
|
||||||
|
|
||||||
public start(coreStart: CoreStart, pluginsStart: ClientPluginsStart): void {
|
public start(coreStart: CoreStart, pluginsStart: ClientPluginsStart): void {
|
||||||
const { triggersActionsUi } = pluginsStart;
|
const { triggersActionsUi } = pluginsStart;
|
||||||
|
setStartServices(coreStart);
|
||||||
|
|
||||||
setStartServices(coreStart);
|
setStartServices(coreStart);
|
||||||
|
|
||||||
|
|
|
@ -6,43 +6,46 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Observable } from 'rxjs';
|
import type { Observable } from 'rxjs';
|
||||||
import type { CoreStart, CoreTheme } from '@kbn/core/public';
|
import type { CoreStart, CoreTheme, CoreSetup } from '@kbn/core/public';
|
||||||
import { ClientPluginsStart } from '../../plugin';
|
import { AppMountParameters } from '@kbn/core/public';
|
||||||
|
import { ClientPluginsSetup, ClientPluginsStart } from '../../plugin';
|
||||||
import { apiService } from '../api_service/api_service';
|
import { apiService } from '../api_service/api_service';
|
||||||
|
|
||||||
class KibanaService {
|
class KibanaService {
|
||||||
private static instance: KibanaService;
|
private static instance: KibanaService;
|
||||||
private _core!: CoreStart;
|
public coreStart!: CoreStart;
|
||||||
private _startPlugins!: ClientPluginsStart;
|
public coreSetup!: CoreSetup;
|
||||||
private _theme!: Observable<CoreTheme>;
|
public theme!: Observable<CoreTheme>;
|
||||||
|
public setupPlugins!: ClientPluginsSetup;
|
||||||
|
public isDev!: boolean;
|
||||||
|
public isServerless!: boolean;
|
||||||
|
public appMountParameters!: AppMountParameters;
|
||||||
|
public startPlugins!: ClientPluginsStart;
|
||||||
|
|
||||||
public get core() {
|
public init({
|
||||||
return this._core;
|
coreSetup,
|
||||||
}
|
coreStart,
|
||||||
|
startPlugins,
|
||||||
public set core(coreStart: CoreStart) {
|
isDev,
|
||||||
this._core = coreStart;
|
isServerless,
|
||||||
apiService.http = this._core.http;
|
}: {
|
||||||
}
|
coreSetup: CoreSetup;
|
||||||
|
coreStart: CoreStart;
|
||||||
public get startPlugins() {
|
startPlugins: ClientPluginsStart;
|
||||||
return this._startPlugins;
|
isDev: boolean;
|
||||||
}
|
isServerless: boolean;
|
||||||
|
}) {
|
||||||
public set startPlugins(startPlugins: ClientPluginsStart) {
|
this.coreSetup = coreSetup;
|
||||||
this._startPlugins = startPlugins;
|
this.coreStart = coreStart;
|
||||||
}
|
this.startPlugins = startPlugins;
|
||||||
|
this.theme = coreStart.uiSettings.get$('theme:darkMode');
|
||||||
public get theme() {
|
apiService.http = coreStart.http;
|
||||||
return this._theme;
|
this.isDev = isDev;
|
||||||
}
|
this.isServerless = isServerless;
|
||||||
|
|
||||||
public set theme(coreTheme: Observable<CoreTheme>) {
|
|
||||||
this._theme = coreTheme;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public get toasts() {
|
public get toasts() {
|
||||||
return this._core.notifications.toasts;
|
return this.coreStart.notifications.toasts;
|
||||||
}
|
}
|
||||||
|
|
||||||
private constructor() {}
|
private constructor() {}
|
||||||
|
|
|
@ -40,7 +40,6 @@
|
||||||
"@kbn/kibana-react-plugin",
|
"@kbn/kibana-react-plugin",
|
||||||
"@kbn/i18n-react",
|
"@kbn/i18n-react",
|
||||||
"@kbn/securitysolution-io-ts-utils",
|
"@kbn/securitysolution-io-ts-utils",
|
||||||
"@kbn/ui-theme",
|
|
||||||
"@kbn/es-query",
|
"@kbn/es-query",
|
||||||
"@kbn/stack-connectors-plugin",
|
"@kbn/stack-connectors-plugin",
|
||||||
"@kbn/rule-data-utils",
|
"@kbn/rule-data-utils",
|
||||||
|
@ -90,7 +89,15 @@
|
||||||
"@kbn/react-kibana-mount",
|
"@kbn/react-kibana-mount",
|
||||||
"@kbn/react-kibana-context-render",
|
"@kbn/react-kibana-context-render",
|
||||||
"@kbn/react-kibana-context-theme",
|
"@kbn/react-kibana-context-theme",
|
||||||
"@kbn/search-types"
|
"@kbn/search-types",
|
||||||
|
"@kbn/core-lifecycle-browser",
|
||||||
|
"@kbn/ui-actions-browser",
|
||||||
|
"@kbn/presentation-publishing",
|
||||||
|
"@kbn/presentation-containers",
|
||||||
|
"@kbn/ui-actions-plugin",
|
||||||
|
"@kbn/presentation-util-plugin",
|
||||||
|
"@kbn/core-application-browser",
|
||||||
|
"@kbn/dashboard-plugin"
|
||||||
],
|
],
|
||||||
"exclude": ["target/**/*"]
|
"exclude": ["target/**/*"]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue