mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -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",
|
||||
"discover",
|
||||
"dataViews",
|
||||
"dashboard",
|
||||
"encryptedSavedObjects",
|
||||
"exploratoryView",
|
||||
"features",
|
||||
|
@ -31,7 +32,9 @@
|
|||
"triggersActionsUi",
|
||||
"usageCollection",
|
||||
"bfetch",
|
||||
"unifiedSearch"
|
||||
"uiActions",
|
||||
"unifiedSearch",
|
||||
"presentationUtil"
|
||||
],
|
||||
"optionalPlugins": [
|
||||
"cloud",
|
||||
|
@ -53,7 +56,7 @@
|
|||
"observability",
|
||||
"spaces",
|
||||
"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 { i18n } from '@kbn/i18n';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||
import { ClientPluginsStart } from '../../../../../plugin';
|
||||
import { selectDynamicSettings } from '../../../state/settings';
|
||||
import {
|
||||
selectSyntheticsAlerts,
|
||||
|
@ -21,7 +23,7 @@ import {
|
|||
} from '../../../state/alert_rules/selectors';
|
||||
import { selectMonitorListState } from '../../../state';
|
||||
import { getDynamicSettingsAction } from '../../../state/settings/actions';
|
||||
import { useSyntheticsSettingsContext, useSyntheticsStartPlugins } from '../../../contexts';
|
||||
import { useSyntheticsSettingsContext } from '../../../contexts';
|
||||
import { ConfigKey } from '../../../../../../common/runtime_types';
|
||||
|
||||
export const AlertingCallout = ({ isAlertingEnabled }: { isAlertingEnabled?: boolean }) => {
|
||||
|
@ -40,7 +42,8 @@ export const AlertingCallout = ({ isAlertingEnabled }: { isAlertingEnabled?: boo
|
|||
loaded: monitorsLoaded,
|
||||
} = useSelector(selectMonitorListState);
|
||||
|
||||
const syntheticsLocators = useSyntheticsStartPlugins()?.share?.url.locators;
|
||||
const syntheticsLocators = useKibana<ClientPluginsStart>().services.share?.url.locators;
|
||||
|
||||
const locator = syntheticsLocators?.get(syntheticsSettingsLocatorID);
|
||||
|
||||
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 { EuiSuperDatePicker } from '@elastic/eui';
|
||||
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||
import { ClientPluginsStart } from '../../../../../plugin';
|
||||
import { useUrlParams } from '../../../hooks';
|
||||
import { CLIENT_DEFAULTS } from '../../../../../../common/constants';
|
||||
import {
|
||||
SyntheticsSettingsContext,
|
||||
SyntheticsStartupPluginsContext,
|
||||
SyntheticsRefreshContext,
|
||||
} from '../../../contexts';
|
||||
import { SyntheticsSettingsContext, SyntheticsRefreshContext } from '../../../contexts';
|
||||
|
||||
export const SyntheticsDatePicker = ({ fullWidth }: { fullWidth?: boolean }) => {
|
||||
const [getUrlParams, updateUrl] = useUrlParams();
|
||||
const { commonlyUsedRanges } = useContext(SyntheticsSettingsContext);
|
||||
const { refreshApp } = useContext(SyntheticsRefreshContext);
|
||||
|
||||
const { data } = useContext(SyntheticsStartupPluginsContext);
|
||||
const { data } = useKibana<ClientPluginsStart>().services;
|
||||
|
||||
// read time from state and update the url
|
||||
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 { euiStyled } from '@kbn/kibana-react-plugin/common';
|
||||
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||
import { ClientPluginsStart } from '../../../../../plugin';
|
||||
import { SYNTHETICS_INDEX_PATTERN } from '../../../../../../common/constants';
|
||||
import { JourneyStep } from '../../../../../../common/runtime_types';
|
||||
import { useSyntheticsStartPlugins } from '../../../contexts';
|
||||
|
||||
export const getLast48Intervals = (activeStep: JourneyStep) => {
|
||||
const timestamp = activeStep['@timestamp'];
|
||||
|
@ -36,7 +36,7 @@ export function StepFieldTrend({
|
|||
field: string;
|
||||
step: JourneyStep;
|
||||
}) {
|
||||
const { exploratoryView } = useSyntheticsStartPlugins();
|
||||
const exploratoryView = useKibana<ClientPluginsStart>().services.exploratoryView;
|
||||
|
||||
const EmbeddableExpView = exploratoryView!.ExploratoryViewEmbeddable;
|
||||
|
||||
|
|
|
@ -179,7 +179,7 @@ describe('GettingStartedPage', () => {
|
|||
});
|
||||
|
||||
// page is loaded
|
||||
expect(kibanaService.core.application.navigateToApp).toHaveBeenCalledWith('synthetics', {
|
||||
expect(kibanaService.coreStart.application.navigateToApp).toHaveBeenCalledWith('synthetics', {
|
||||
path: '/monitors',
|
||||
});
|
||||
});
|
||||
|
|
|
@ -56,14 +56,14 @@ export const useSimpleMonitor = ({ monitorData }: { monitorData?: SimpleFormData
|
|||
}, [monitorData]);
|
||||
|
||||
useEffect(() => {
|
||||
const { core, toasts } = kibanaService;
|
||||
const { coreStart, toasts } = kibanaService;
|
||||
const newMonitor = data as UpsertMonitorResponse;
|
||||
const hasErrors = data && 'attributes' in data && data.attributes.errors?.length > 0;
|
||||
if (hasErrors && !loading) {
|
||||
showSyncErrors(
|
||||
(data as { attributes: { errors: ServiceLocationErrors } })?.attributes.errors ?? [],
|
||||
serviceLocations,
|
||||
core
|
||||
coreStart
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ export const useMonitorSave = ({ monitorData }: { monitorData?: SyntheticsMonito
|
|||
}, [monitorData]);
|
||||
|
||||
useEffect(() => {
|
||||
const { core, toasts } = kibanaService;
|
||||
const { coreStart, toasts } = kibanaService;
|
||||
|
||||
if (status === FETCH_STATUS.FAILURE && error) {
|
||||
toasts.addError(
|
||||
|
@ -64,7 +64,7 @@ export const useMonitorSave = ({ monitorData }: { monitorData?: SyntheticsMonito
|
|||
<p data-test-subj="synthetcsMonitorSaveSubtext">
|
||||
{monitorId ? MONITOR_UPDATED_SUCCESS_LABEL_SUBTEXT : MONITOR_SUCCESS_LABEL_SUBTEXT}
|
||||
</p>,
|
||||
core
|
||||
coreStart
|
||||
),
|
||||
toastLifeTimeMs: 3000,
|
||||
});
|
||||
|
|
|
@ -18,7 +18,7 @@ import {
|
|||
export function useOverviewStatus({ scopeStatusByLocation }: { scopeStatusByLocation: boolean }) {
|
||||
const pageState = useSelector(selectOverviewPageState);
|
||||
|
||||
const { status, error, loaded } = useSelector(selectOverviewStatus);
|
||||
const { status, error, loaded, loading } = useSelector(selectOverviewStatus);
|
||||
|
||||
const { lastRefresh } = useSyntheticsRefreshContext();
|
||||
|
||||
|
@ -37,5 +37,6 @@ export function useOverviewStatus({ scopeStatusByLocation }: { scopeStatusByLoca
|
|||
return {
|
||||
status,
|
||||
error,
|
||||
loading,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ export const DeleteMonitor = ({
|
|||
}, [configId, isDeleting]);
|
||||
|
||||
useEffect(() => {
|
||||
const { core, toasts } = kibanaService;
|
||||
const { coreStart, toasts } = kibanaService;
|
||||
if (!isDeleting) {
|
||||
return;
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ export const DeleteMonitor = ({
|
|||
<p data-test-subj="uptimeDeleteMonitorFailure">
|
||||
{labels.MONITOR_DELETE_FAILURE_LABEL}
|
||||
</p>,
|
||||
core
|
||||
coreStart
|
||||
),
|
||||
},
|
||||
{ toastLifeTimeMs: 3000 }
|
||||
|
@ -72,7 +72,7 @@ export const DeleteMonitor = ({
|
|||
}
|
||||
)}
|
||||
</p>,
|
||||
core
|
||||
coreStart
|
||||
),
|
||||
},
|
||||
{ toastLifeTimeMs: 3000 }
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 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 { i18n } from '@kbn/i18n';
|
||||
import {
|
||||
|
@ -15,11 +15,12 @@ import {
|
|||
EuiButtonEmpty,
|
||||
EuiText,
|
||||
} from '@elastic/eui';
|
||||
import { selectOverviewStatus } from '../../../../state/overview_status';
|
||||
import { useOverviewStatus } from '../../hooks/use_overview_status';
|
||||
import { useInfiniteScroll } from './use_infinite_scroll';
|
||||
import { GridItemsByGroup } from './grid_by_group/grid_items_by_group';
|
||||
import { GroupFields } from './grid_by_group/group_fields';
|
||||
import {
|
||||
fetchMonitorOverviewAction,
|
||||
quietFetchOverviewAction,
|
||||
selectOverviewState,
|
||||
setFlyoutConfig,
|
||||
|
@ -33,7 +34,7 @@ import { NoMonitorsFound } from '../../common/no_monitors_found';
|
|||
import { MonitorDetailFlyout } from './monitor_detail_flyout';
|
||||
|
||||
export const OverviewGrid = memo(() => {
|
||||
const { status } = useSelector(selectOverviewStatus);
|
||||
const { status } = useOverviewStatus({ scopeStatusByLocation: true });
|
||||
|
||||
const {
|
||||
data: { monitors },
|
||||
|
@ -49,6 +50,11 @@ export const OverviewGrid = memo(() => {
|
|||
const intersectionRef = useRef(null);
|
||||
const { monitorsSortedByStatus } = useMonitorsSortedByStatus();
|
||||
|
||||
// fetch overview for all other page state changes
|
||||
useEffect(() => {
|
||||
dispatch(fetchMonitorOverviewAction.get(pageState));
|
||||
}, [dispatch, pageState]);
|
||||
|
||||
const setFlyoutConfigCallback = useCallback(
|
||||
(params: FlyoutParamProps) => dispatch(setFlyoutConfig(params)),
|
||||
[dispatch]
|
||||
|
|
|
@ -5,10 +5,13 @@
|
|||
* 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 React, { useEffect, useState } from 'react';
|
||||
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 { kibanaService } from '../../../../../../utils/kibana_service';
|
||||
import { useGetUrlParams } from '../../../../hooks/use_url_params';
|
||||
|
@ -18,10 +21,16 @@ function title(t?: number) {
|
|||
return t ?? '-';
|
||||
}
|
||||
|
||||
export function OverviewStatus() {
|
||||
export function OverviewStatus({ reload$ }: { reload$?: Subject<boolean> }) {
|
||||
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 [statusConfig, setStatusConfig] = useState({
|
||||
up: status?.up,
|
||||
|
@ -30,6 +39,14 @@ export function OverviewStatus() {
|
|||
disabledCount: status?.disabledCount,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const sub = reload$?.subscribe(() => {
|
||||
refreshApp();
|
||||
});
|
||||
|
||||
return () => sub?.unsubscribe();
|
||||
}, [refreshApp, reload$]);
|
||||
|
||||
useEffect(() => {
|
||||
if (statusError) {
|
||||
dispatch(clearOverviewStatusErrorAction());
|
||||
|
@ -87,10 +104,7 @@ export function OverviewStatus() {
|
|||
}, [status, statusFilter]);
|
||||
|
||||
return (
|
||||
<EuiPanel hasShadow={false} hasBorder>
|
||||
<EuiTitle size="xs">
|
||||
<h3>{headingText}</h3>
|
||||
</EuiTitle>
|
||||
<EmbeddablePanelWrapper title={headingText} loading={loading}>
|
||||
<EuiSpacer size="m" />
|
||||
<EuiFlexGroup gutterSize="xl">
|
||||
<EuiFlexItem grow={false}>
|
||||
|
@ -136,7 +150,7 @@ export function OverviewStatus() {
|
|||
</EuiFlexItem>
|
||||
)}
|
||||
</EuiFlexGroup>
|
||||
</EuiPanel>
|
||||
</EmbeddablePanelWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ export const DeleteParam = ({
|
|||
if (!isDeleting) {
|
||||
return;
|
||||
}
|
||||
const { core, toasts } = kibanaService;
|
||||
const { coreStart, toasts } = kibanaService;
|
||||
|
||||
if (status === FETCH_STATUS.FAILURE) {
|
||||
toasts.addDanger(
|
||||
|
@ -61,7 +61,7 @@ export const DeleteParam = ({
|
|||
values: { name },
|
||||
})}
|
||||
</p>,
|
||||
core
|
||||
coreStart
|
||||
),
|
||||
},
|
||||
{ toastLifeTimeMs: 3000 }
|
||||
|
@ -76,7 +76,7 @@ export const DeleteParam = ({
|
|||
values: { name },
|
||||
})}
|
||||
</p>,
|
||||
core
|
||||
coreStart
|
||||
),
|
||||
},
|
||||
{ toastLifeTimeMs: 3000 }
|
||||
|
|
|
@ -5,8 +5,9 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import React from 'react';
|
||||
import { SyntheticsStartupPluginsContext } from '../../../../../contexts';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { JourneyStep } from '../../../../../../../../common/runtime_types';
|
||||
import { WaterfallContext } from '../context/waterfall_context';
|
||||
|
||||
|
@ -25,9 +26,21 @@ const EmbeddableMock = ({
|
|||
}) => (
|
||||
<div>
|
||||
<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 aria-label="attributes">{JSON.stringify(attributes)}</div>
|
||||
<div
|
||||
aria-label={i18n.translate('xpack.synthetics.embeddableMock.div.attributesLabel', {
|
||||
defaultMessage: 'attributes',
|
||||
})}
|
||||
>
|
||||
{JSON.stringify(attributes)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
|
@ -40,9 +53,8 @@ export const TestWrapper = ({
|
|||
activeStep?: JourneyStep;
|
||||
children: JSX.Element;
|
||||
}) => (
|
||||
<SyntheticsStartupPluginsContext.Provider
|
||||
value={{
|
||||
// @ts-expect-error incomplete implementation for test purposes
|
||||
<KibanaContextProvider
|
||||
services={{
|
||||
exploratoryView: {
|
||||
ExploratoryViewEmbeddable: jest.fn((props: any) => <EmbeddableMock {...props} />),
|
||||
},
|
||||
|
@ -55,5 +67,5 @@ export const TestWrapper = ({
|
|||
>
|
||||
{children}
|
||||
</WaterfallContext.Provider>
|
||||
</SyntheticsStartupPluginsContext.Provider>
|
||||
</KibanaContextProvider>
|
||||
);
|
||||
|
|
|
@ -38,7 +38,7 @@ export const BrowserTestRunResult = ({
|
|||
});
|
||||
|
||||
useEffect(() => {
|
||||
const { core, toasts } = kibanaService;
|
||||
const { coreStart, toasts } = kibanaService;
|
||||
if (retriesExceeded) {
|
||||
toasts.addDanger(
|
||||
{
|
||||
|
@ -49,7 +49,7 @@ export const BrowserTestRunResult = ({
|
|||
defaultMessage="Manual test run failed for {name}"
|
||||
values={{ name }}
|
||||
/>,
|
||||
core
|
||||
coreStart
|
||||
),
|
||||
},
|
||||
{
|
||||
|
|
|
@ -25,7 +25,7 @@ export function SimpleTestResults({ name, testRunId, expectPings, onDone }: Prop
|
|||
|
||||
useEffect(() => {
|
||||
if (retriesExceeded) {
|
||||
const { core, toasts } = kibanaService;
|
||||
const { coreStart, toasts } = kibanaService;
|
||||
|
||||
toasts.addDanger(
|
||||
{
|
||||
|
@ -36,7 +36,7 @@ export function SimpleTestResults({ name, testRunId, expectPings, onDone }: Prop
|
|||
defaultMessage="Manual test run failed for {name}"
|
||||
values={{ name }}
|
||||
/>,
|
||||
core
|
||||
coreStart
|
||||
),
|
||||
},
|
||||
{
|
||||
|
|
|
@ -7,5 +7,3 @@
|
|||
|
||||
export * from './synthetics_refresh_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 {
|
||||
basePath: string;
|
||||
canSave: boolean;
|
||||
core: CoreStart;
|
||||
coreStart: CoreStart;
|
||||
darkMode: boolean;
|
||||
i18n: I18nStart;
|
||||
isApmAvailable: boolean;
|
||||
isInfraAvailable: boolean;
|
||||
isLogsAvailable: boolean;
|
||||
plugins: ClientPluginsSetup;
|
||||
setupPlugins: ClientPluginsSetup;
|
||||
startPlugins: ClientPluginsStart;
|
||||
setBadge: (badge?: ChromeBadge) => 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 { LocatorClient } from '@kbn/share-plugin/common/url_service/locators';
|
||||
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({
|
||||
configId,
|
||||
|
@ -18,7 +19,7 @@ export function useEditMonitorLocator({
|
|||
locators?: LocatorClient;
|
||||
}) {
|
||||
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);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
|
||||
import { useEffect, useState } from 'react';
|
||||
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({
|
||||
configId,
|
||||
|
@ -17,7 +18,7 @@ export function useMonitorDetailLocator({
|
|||
locationId?: string;
|
||||
}) {
|
||||
const [monitorUrl, setMonitorUrl] = useState<string | undefined>(undefined);
|
||||
const locator = useSyntheticsStartPlugins()?.share?.url.locators.get(
|
||||
const locator = useKibana<ClientPluginsStart>().services?.share?.url.locators.get(
|
||||
syntheticsMonitorDetailLocatorID
|
||||
);
|
||||
|
||||
|
|
|
@ -19,19 +19,19 @@ import { store } from '../../../state';
|
|||
import type { StatusRuleParams } from '../../../../../../common/rules/status_rule';
|
||||
|
||||
interface Props {
|
||||
core: CoreStart;
|
||||
coreStart: CoreStart;
|
||||
plugins: ClientPluginsStart;
|
||||
params: RuleTypeParamsExpressionProps<StatusRuleParams>;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function MonitorStatusAlert({ core, plugins, params }: Props) {
|
||||
kibanaService.core = core;
|
||||
export default function MonitorStatusAlert({ coreStart, plugins, params }: Props) {
|
||||
kibanaService.coreStart = coreStart;
|
||||
const queryClient = new QueryClient();
|
||||
return (
|
||||
<ReduxProvider store={store}>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<KibanaContextProvider services={{ ...core, ...plugins }}>
|
||||
<KibanaContextProvider services={{ ...coreStart, ...plugins }}>
|
||||
<EuiText>
|
||||
<FormattedMessage
|
||||
id="xpack.synthetics.alertRule.monitorStatus.description"
|
||||
|
|
|
@ -17,18 +17,18 @@ import { kibanaService } from '../../../../../utils/kibana_service';
|
|||
import { store } from '../../../state';
|
||||
|
||||
interface Props {
|
||||
core: CoreStart;
|
||||
coreStart: CoreStart;
|
||||
plugins: ClientPluginsStart;
|
||||
ruleParams: RuleTypeParamsExpressionProps<TLSParams>['ruleParams'];
|
||||
setRuleParams: RuleTypeParamsExpressionProps<TLSParams>['setRuleParams'];
|
||||
}
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function TLSAlert({ core, plugins, ruleParams, setRuleParams }: Props) {
|
||||
kibanaService.core = core;
|
||||
export default function TLSAlert({ coreStart, plugins, ruleParams, setRuleParams }: Props) {
|
||||
kibanaService.coreStart = coreStart;
|
||||
return (
|
||||
<ReduxProvider store={store}>
|
||||
<KibanaContextProvider services={{ ...core, ...plugins }}>
|
||||
<KibanaContextProvider services={{ ...coreStart, ...plugins }}>
|
||||
<TLSRuleComponent ruleParams={ruleParams} setRuleParams={setRuleParams} />
|
||||
</KibanaContextProvider>
|
||||
</ReduxProvider>
|
||||
|
|
|
@ -33,7 +33,7 @@ export const initMonitorStatusAlertType: AlertTypeInitializer = ({
|
|||
return `${docLinks.links.observability.syntheticsAlerting}`;
|
||||
},
|
||||
ruleParamsExpression: (paramProps: RuleTypeParamsExpressionProps<StatusRuleParams>) => (
|
||||
<MonitorStatusAlert core={core} plugins={plugins} params={paramProps} />
|
||||
<MonitorStatusAlert coreStart={core} plugins={plugins} params={paramProps} />
|
||||
),
|
||||
validate: (_ruleParams: StatusRuleParams) => {
|
||||
return { errors: {} };
|
||||
|
|
|
@ -31,7 +31,7 @@ export const initTlsAlertType: AlertTypeInitializer = ({
|
|||
},
|
||||
ruleParamsExpression: (params: RuleTypeParamsExpressionProps<TLSParams>) => (
|
||||
<TLSAlert
|
||||
core={core}
|
||||
coreStart={core}
|
||||
plugins={plugins}
|
||||
ruleParams={params.ruleParams}
|
||||
setRuleParams={params.setRuleParams}
|
||||
|
|
|
@ -8,21 +8,17 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
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 { getIntegratedAppAvailability } from './utils/adapters';
|
||||
import { DEFAULT_TIMEPICKER_QUICK_RANGES, INTEGRATED_SOLUTIONS } from '../../../common/constants';
|
||||
import { SyntheticsApp } from './synthetics_app';
|
||||
import { ClientPluginsSetup, ClientPluginsStart } from '../../plugin';
|
||||
|
||||
export function renderApp(
|
||||
core: CoreStart,
|
||||
plugins: ClientPluginsSetup,
|
||||
startPlugins: ClientPluginsStart,
|
||||
appMountParameters: AppMountParameters,
|
||||
isDev: boolean,
|
||||
isServerless: boolean
|
||||
) {
|
||||
export const getSyntheticsAppProps = (): SyntheticsAppProps => {
|
||||
const { isDev, isServerless, coreStart, startPlugins, setupPlugins, appMountParameters } =
|
||||
kibanaService;
|
||||
|
||||
const {
|
||||
application: { capabilities },
|
||||
chrome: { setBadge, setHelpExtension },
|
||||
|
@ -30,7 +26,7 @@ export function renderApp(
|
|||
http: { basePath },
|
||||
i18n,
|
||||
theme,
|
||||
} = core;
|
||||
} = kibanaService.coreStart;
|
||||
|
||||
const { apm, infrastructure, logs } = getIntegratedAppAvailability(
|
||||
capabilities,
|
||||
|
@ -40,24 +36,22 @@ export function renderApp(
|
|||
const canSave = (capabilities.uptime.save ?? false) as boolean; // TODO: Determine for synthetics
|
||||
const darkMode = theme.getTheme().darkMode;
|
||||
|
||||
const props: SyntheticsAppProps = {
|
||||
return {
|
||||
isDev,
|
||||
plugins,
|
||||
setupPlugins,
|
||||
canSave,
|
||||
core,
|
||||
coreStart,
|
||||
i18n,
|
||||
startPlugins,
|
||||
basePath: basePath.get(),
|
||||
darkMode,
|
||||
commonlyUsedRanges: core.uiSettings.get(DEFAULT_TIMEPICKER_QUICK_RANGES),
|
||||
commonlyUsedRanges: coreStart.uiSettings.get(DEFAULT_TIMEPICKER_QUICK_RANGES),
|
||||
isApmAvailable: apm,
|
||||
isInfraAvailable: infrastructure,
|
||||
isLogsAvailable: logs,
|
||||
renderGlobalHelpControls: () =>
|
||||
setHelpExtension({
|
||||
appName: i18nFormatter.translate('xpack.synthetics.header.appName', {
|
||||
defaultMessage: 'Synthetics',
|
||||
}),
|
||||
appName: SYNTHETICS_APP_NAME,
|
||||
links: [
|
||||
{
|
||||
linkType: 'documentation',
|
||||
|
@ -72,13 +66,21 @@ export function renderApp(
|
|||
setBadge,
|
||||
appMountParameters,
|
||||
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);
|
||||
|
||||
return () => {
|
||||
startPlugins.data.search.session.clear();
|
||||
props.startPlugins.data.search.session.clear();
|
||||
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';
|
||||
|
||||
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 { IHttpSerializedFetchError } from '..';
|
||||
import { clearOverviewStatusErrorAction, fetchOverviewStatusAction } from './actions';
|
||||
import {
|
||||
clearOverviewStatusErrorAction,
|
||||
fetchOverviewStatusAction,
|
||||
quietFetchOverviewStatusAction,
|
||||
} from './actions';
|
||||
|
||||
export interface OverviewStatusStateReducer {
|
||||
loading: boolean;
|
||||
|
@ -29,6 +33,10 @@ export const overviewStatusReducer = createReducer(initialState, (builder) => {
|
|||
builder
|
||||
.addCase(fetchOverviewStatusAction.get, (state) => {
|
||||
state.status = null;
|
||||
state.loading = true;
|
||||
})
|
||||
.addCase(quietFetchOverviewStatusAction.get, (state) => {
|
||||
state.loading = true;
|
||||
})
|
||||
.addCase(fetchOverviewStatusAction.success, (state, action) => {
|
||||
state.status = {
|
||||
|
@ -36,9 +44,11 @@ export const overviewStatusReducer = createReducer(initialState, (builder) => {
|
|||
allConfigs: { ...action.payload.upConfigs, ...action.payload.downConfigs },
|
||||
};
|
||||
state.loaded = true;
|
||||
state.loading = false;
|
||||
})
|
||||
.addCase(fetchOverviewStatusAction.fail, (state, action) => {
|
||||
state.error = action.payload;
|
||||
state.loading = false;
|
||||
})
|
||||
.addCase(clearOverviewStatusErrorAction, (state) => {
|
||||
state.error = null;
|
||||
|
|
|
@ -8,5 +8,5 @@
|
|||
import { SyntheticsAppState } from '../root_reducer';
|
||||
|
||||
export const selectOverviewStatus = ({
|
||||
overviewStatus: { status, error, loaded },
|
||||
}: SyntheticsAppState) => ({ status, error, loaded });
|
||||
overviewStatus: { status, error, loaded, loading },
|
||||
}: SyntheticsAppState) => ({ status, error, loaded, loading });
|
||||
|
|
|
@ -81,13 +81,13 @@ export function* setDynamicSettingsEffect() {
|
|||
yield call(setDynamicSettings, { settings: action.payload });
|
||||
yield put(updateDefaultAlertingAction.get());
|
||||
yield put(setDynamicSettingsAction.success(action.payload));
|
||||
kibanaService.core.notifications.toasts.addSuccess(
|
||||
kibanaService.coreSetup.notifications.toasts.addSuccess(
|
||||
i18n.translate('xpack.synthetics.settings.saveSuccess', {
|
||||
defaultMessage: 'Settings saved!',
|
||||
})
|
||||
);
|
||||
} catch (err) {
|
||||
kibanaService.core.notifications.toasts.addError(err, {
|
||||
kibanaService.coreSetup.notifications.toasts.addError(err, {
|
||||
title: couldNotSaveSettingsText,
|
||||
});
|
||||
yield put(setDynamicSettingsAction.fail(err));
|
||||
|
|
|
@ -67,7 +67,7 @@ export function fetchEffectFactory<T, R, S, F>(
|
|||
if (typeof onFailure === 'function') {
|
||||
onFailure?.(error);
|
||||
} else if (typeof onFailure === 'string') {
|
||||
kibanaService.core.notifications.toasts.addError(
|
||||
kibanaService.coreSetup.notifications.toasts.addError(
|
||||
{ ...error, message: serializedError.body?.message ?? error.message },
|
||||
{
|
||||
title: onFailure,
|
||||
|
@ -104,7 +104,7 @@ export function fetchEffectFactory<T, R, S, F>(
|
|||
if (typeof onSuccess === 'function') {
|
||||
onSuccess(response as R);
|
||||
} else if (onSuccess && typeof onSuccess === 'string') {
|
||||
kibanaService.core.notifications.toasts.addSuccess(onSuccess);
|
||||
kibanaService.coreSetup.notifications.toasts.addSuccess(onSuccess);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
|
|
|
@ -6,42 +6,30 @@
|
|||
*/
|
||||
|
||||
import React, { useEffect } from 'react';
|
||||
import { Provider as ReduxProvider } from 'react-redux';
|
||||
|
||||
import { APP_WRAPPER_CLASS } from '@kbn/core/public';
|
||||
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 { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
|
||||
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 { SyntheticsSharedContext } from './contexts/synthetics_shared_context';
|
||||
import { kibanaService } from '../../utils/kibana_service';
|
||||
import { ActionMenu } from './components/common/header/action_menu';
|
||||
import { TestNowModeFlyoutContainer } from './components/test_now_mode/test_now_mode_flyout_container';
|
||||
import {
|
||||
SyntheticsAppProps,
|
||||
SyntheticsRefreshContextProvider,
|
||||
SyntheticsSettingsContextProvider,
|
||||
SyntheticsStartupPluginsContextProvider,
|
||||
SyntheticsThemeContextProvider,
|
||||
} from './contexts';
|
||||
import { SyntheticsDataViewContextProvider } from './contexts/synthetics_data_view_context';
|
||||
import { SyntheticsAppProps, SyntheticsSettingsContextProvider } from './contexts';
|
||||
import { PageRouter } from './routes';
|
||||
import { setBasePath, storage, store } from './state';
|
||||
import { setBasePath, store } from './state';
|
||||
|
||||
const Application = (props: SyntheticsAppProps) => {
|
||||
const {
|
||||
basePath,
|
||||
canSave,
|
||||
core,
|
||||
darkMode,
|
||||
plugins,
|
||||
coreStart,
|
||||
startPlugins,
|
||||
renderGlobalHelpControls,
|
||||
setBadge,
|
||||
startPlugins,
|
||||
appMountParameters,
|
||||
} = props;
|
||||
|
||||
|
@ -62,16 +50,17 @@ const Application = (props: SyntheticsAppProps) => {
|
|||
);
|
||||
}, [canSave, renderGlobalHelpControls, setBadge]);
|
||||
|
||||
kibanaService.core = core;
|
||||
kibanaService.startPlugins = startPlugins;
|
||||
kibanaService.theme = props.appMountParameters.theme$;
|
||||
|
||||
store.dispatch(setBasePath(basePath));
|
||||
|
||||
const PresentationContextProvider =
|
||||
startPlugins.presentationUtil?.ContextProvider ?? React.Fragment;
|
||||
|
||||
return (
|
||||
<KibanaRenderContextProvider {...core}>
|
||||
<KibanaRenderContextProvider {...coreStart}>
|
||||
<KibanaThemeProvider
|
||||
theme={core.theme}
|
||||
theme={coreStart.theme}
|
||||
modify={{
|
||||
breakpoint: {
|
||||
xxl: 1600,
|
||||
|
@ -79,54 +68,21 @@ const Application = (props: SyntheticsAppProps) => {
|
|||
},
|
||||
}}
|
||||
>
|
||||
<ReduxProvider store={store}>
|
||||
<KibanaContextProvider
|
||||
services={{
|
||||
...core,
|
||||
...plugins,
|
||||
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,
|
||||
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>
|
||||
<SyntheticsSharedContext {...props}>
|
||||
<PresentationContextProvider>
|
||||
<Router history={appMountParameters.history}>
|
||||
<SyntheticsSettingsContextProvider {...props}>
|
||||
<div className={APP_WRAPPER_CLASS} data-test-subj="syntheticsApp">
|
||||
<InspectorContextProvider>
|
||||
<PageRouter />
|
||||
<ActionMenu appMountParameters={appMountParameters} />
|
||||
<TestNowModeFlyoutContainer />
|
||||
</InspectorContextProvider>
|
||||
</div>
|
||||
</SyntheticsSettingsContextProvider>
|
||||
</Router>
|
||||
</PresentationContextProvider>
|
||||
</SyntheticsSharedContext>
|
||||
</KibanaThemeProvider>
|
||||
</KibanaRenderContextProvider>
|
||||
);
|
||||
|
|
|
@ -34,10 +34,7 @@ import { MountWithReduxProvider } from './helper_with_redux';
|
|||
import { AppState } from '../../state';
|
||||
import { stringifyUrlParams } from '../url_params';
|
||||
import { ClientPluginsStart } from '../../../../plugin';
|
||||
import {
|
||||
SyntheticsRefreshContextProvider,
|
||||
SyntheticsStartupPluginsContextProvider,
|
||||
} from '../../contexts';
|
||||
import { SyntheticsRefreshContextProvider } from '../../contexts';
|
||||
import { kibanaService } from '../../../../utils/kibana_service';
|
||||
|
||||
type DeepPartial<T> = {
|
||||
|
@ -182,21 +179,14 @@ export function MockKibanaProvider<ExtraCore>({
|
|||
}: MockKibanaProviderProps<ExtraCore>) {
|
||||
const coreOptions = merge({}, mockCore(), core);
|
||||
|
||||
kibanaService.core = coreOptions as any;
|
||||
kibanaService.coreStart = coreOptions as any;
|
||||
|
||||
return (
|
||||
<KibanaContextProvider services={{ ...coreOptions }} {...kibanaProps}>
|
||||
<SyntheticsRefreshContextProvider>
|
||||
<SyntheticsStartupPluginsContextProvider
|
||||
data={(coreOptions as any).data}
|
||||
observability={(coreOptions as any).observability}
|
||||
observabilityShared={(coreOptions as any).observabilityShared}
|
||||
exploratoryView={(coreOptions as any).exploratoryView}
|
||||
>
|
||||
<EuiThemeProvider darkMode={false}>
|
||||
<I18nProvider>{children}</I18nProvider>
|
||||
</EuiThemeProvider>
|
||||
</SyntheticsStartupPluginsContextProvider>
|
||||
<EuiThemeProvider darkMode={false}>
|
||||
<I18nProvider>{children}</I18nProvider>
|
||||
</EuiThemeProvider>
|
||||
</SyntheticsRefreshContextProvider>
|
||||
</KibanaContextProvider>
|
||||
);
|
||||
|
|
|
@ -25,7 +25,7 @@ import type {
|
|||
ExploratoryViewPublicSetup,
|
||||
ExploratoryViewPublicStart,
|
||||
} from '@kbn/exploratory-view-plugin/public';
|
||||
import { EmbeddableStart } from '@kbn/embeddable-plugin/public';
|
||||
import { EmbeddableStart, EmbeddableSetup } from '@kbn/embeddable-plugin/public';
|
||||
import {
|
||||
TriggersAndActionsUIPublicPluginSetup,
|
||||
TriggersAndActionsUIPublicPluginStart,
|
||||
|
@ -50,12 +50,18 @@ import type {
|
|||
ObservabilitySharedPluginSetup,
|
||||
ObservabilitySharedPluginStart,
|
||||
} from '@kbn/observability-shared-plugin/public';
|
||||
|
||||
import { LicenseManagementUIPluginSetup } from '@kbn/license-management-plugin/public/plugin';
|
||||
import {
|
||||
ObservabilityAIAssistantPublicSetup,
|
||||
ObservabilityAIAssistantPublicStart,
|
||||
} from '@kbn/observability-ai-assistant-plugin/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 { OVERVIEW_ROUTE } from '../common/constants/ui';
|
||||
import { locators } from './apps/locators';
|
||||
|
@ -72,7 +78,10 @@ export interface ClientPluginsSetup {
|
|||
share: SharePluginSetup;
|
||||
triggersActionsUi: TriggersAndActionsUIPublicPluginSetup;
|
||||
cloud?: CloudSetup;
|
||||
embeddable: EmbeddableSetup;
|
||||
serverless?: ServerlessPluginSetup;
|
||||
uiActions: UiActionsSetup;
|
||||
dashboard: DashboardSetup;
|
||||
}
|
||||
|
||||
export interface ClientPluginsStart {
|
||||
|
@ -102,6 +111,8 @@ export interface ClientPluginsStart {
|
|||
usageCollection: UsageCollectionStart;
|
||||
serverless: ServerlessPluginStart;
|
||||
licenseManagement?: LicenseManagementUIPluginSetup;
|
||||
presentationUtil: PresentationUtilPluginStart;
|
||||
dashboard: DashboardStart;
|
||||
}
|
||||
|
||||
export interface SyntheticsPluginServices extends Partial<CoreStart> {
|
||||
|
@ -123,12 +134,25 @@ export class SyntheticsPlugin
|
|||
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) => {
|
||||
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 = [
|
||||
'Synthetics',
|
||||
|
@ -149,7 +173,7 @@ export class SyntheticsPlugin
|
|||
];
|
||||
|
||||
// Register the Synthetics UI plugin
|
||||
core.application.register({
|
||||
coreSetup.application.register({
|
||||
id: 'synthetics',
|
||||
euiIconType: 'logoObservability',
|
||||
order: 8400,
|
||||
|
@ -177,23 +201,20 @@ export class SyntheticsPlugin
|
|||
},
|
||||
],
|
||||
mount: async (params: AppMountParameters) => {
|
||||
const [coreStart, corePlugins] = await core.getStartServices();
|
||||
|
||||
kibanaService.appMountParameters = params;
|
||||
const { renderApp } = await import('./apps/synthetics/render_app');
|
||||
return renderApp(
|
||||
coreStart,
|
||||
plugins,
|
||||
corePlugins,
|
||||
params,
|
||||
this.initContext.env.mode.dev,
|
||||
this._isServerless
|
||||
);
|
||||
await coreSetup.getStartServices();
|
||||
|
||||
return renderApp(params);
|
||||
},
|
||||
});
|
||||
|
||||
registerSyntheticsEmbeddables(coreSetup, plugins);
|
||||
}
|
||||
|
||||
public start(coreStart: CoreStart, pluginsStart: ClientPluginsStart): void {
|
||||
const { triggersActionsUi } = pluginsStart;
|
||||
setStartServices(coreStart);
|
||||
|
||||
setStartServices(coreStart);
|
||||
|
||||
|
|
|
@ -6,43 +6,46 @@
|
|||
*/
|
||||
|
||||
import type { Observable } from 'rxjs';
|
||||
import type { CoreStart, CoreTheme } from '@kbn/core/public';
|
||||
import { ClientPluginsStart } from '../../plugin';
|
||||
import type { CoreStart, CoreTheme, CoreSetup } from '@kbn/core/public';
|
||||
import { AppMountParameters } from '@kbn/core/public';
|
||||
import { ClientPluginsSetup, ClientPluginsStart } from '../../plugin';
|
||||
import { apiService } from '../api_service/api_service';
|
||||
|
||||
class KibanaService {
|
||||
private static instance: KibanaService;
|
||||
private _core!: CoreStart;
|
||||
private _startPlugins!: ClientPluginsStart;
|
||||
private _theme!: Observable<CoreTheme>;
|
||||
public coreStart!: CoreStart;
|
||||
public coreSetup!: CoreSetup;
|
||||
public theme!: Observable<CoreTheme>;
|
||||
public setupPlugins!: ClientPluginsSetup;
|
||||
public isDev!: boolean;
|
||||
public isServerless!: boolean;
|
||||
public appMountParameters!: AppMountParameters;
|
||||
public startPlugins!: ClientPluginsStart;
|
||||
|
||||
public get core() {
|
||||
return this._core;
|
||||
}
|
||||
|
||||
public set core(coreStart: CoreStart) {
|
||||
this._core = coreStart;
|
||||
apiService.http = this._core.http;
|
||||
}
|
||||
|
||||
public get startPlugins() {
|
||||
return this._startPlugins;
|
||||
}
|
||||
|
||||
public set startPlugins(startPlugins: ClientPluginsStart) {
|
||||
this._startPlugins = startPlugins;
|
||||
}
|
||||
|
||||
public get theme() {
|
||||
return this._theme;
|
||||
}
|
||||
|
||||
public set theme(coreTheme: Observable<CoreTheme>) {
|
||||
this._theme = coreTheme;
|
||||
public init({
|
||||
coreSetup,
|
||||
coreStart,
|
||||
startPlugins,
|
||||
isDev,
|
||||
isServerless,
|
||||
}: {
|
||||
coreSetup: CoreSetup;
|
||||
coreStart: CoreStart;
|
||||
startPlugins: ClientPluginsStart;
|
||||
isDev: boolean;
|
||||
isServerless: boolean;
|
||||
}) {
|
||||
this.coreSetup = coreSetup;
|
||||
this.coreStart = coreStart;
|
||||
this.startPlugins = startPlugins;
|
||||
this.theme = coreStart.uiSettings.get$('theme:darkMode');
|
||||
apiService.http = coreStart.http;
|
||||
this.isDev = isDev;
|
||||
this.isServerless = isServerless;
|
||||
}
|
||||
|
||||
public get toasts() {
|
||||
return this._core.notifications.toasts;
|
||||
return this.coreStart.notifications.toasts;
|
||||
}
|
||||
|
||||
private constructor() {}
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
"@kbn/kibana-react-plugin",
|
||||
"@kbn/i18n-react",
|
||||
"@kbn/securitysolution-io-ts-utils",
|
||||
"@kbn/ui-theme",
|
||||
"@kbn/es-query",
|
||||
"@kbn/stack-connectors-plugin",
|
||||
"@kbn/rule-data-utils",
|
||||
|
@ -90,7 +89,15 @@
|
|||
"@kbn/react-kibana-mount",
|
||||
"@kbn/react-kibana-context-render",
|
||||
"@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/**/*"]
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue