mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
Display a link to platinum license upgrade on the service map. Also add `useKibanaUrl` and `useLicense` hooks. Make the `LicenseContext` (which is used in a couple class components and on page load) use the license observable from the NP plugin. Add missing export of `useObservable` to kibana_react.
This commit is contained in:
parent
94391c15fe
commit
cbc3f24f69
9 changed files with 144 additions and 87 deletions
|
@ -148,7 +148,9 @@ export class ServiceIntegrations extends React.Component<Props, State> {
|
|||
panels={[
|
||||
{
|
||||
id: 0,
|
||||
items: this.getPanelItems(license.features.ml?.is_available)
|
||||
items: this.getPanelItems(
|
||||
license?.getFeature('ml').isAvailable
|
||||
)
|
||||
}
|
||||
]}
|
||||
/>
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
EuiEmptyPrompt,
|
||||
EuiButton,
|
||||
EuiPanel,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem
|
||||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { useKibanaUrl } from '../../../hooks/useKibanaUrl';
|
||||
|
||||
export function PlatinumLicensePrompt() {
|
||||
// Set the height to give it some top margin
|
||||
const style = { height: '60vh' };
|
||||
|
||||
const licensePageUrl = useKibanaUrl(
|
||||
'/app/kibana',
|
||||
'/management/elasticsearch/license_management/home'
|
||||
);
|
||||
|
||||
return (
|
||||
<EuiFlexGroup
|
||||
alignItems="center"
|
||||
justifyContent="spaceAround"
|
||||
style={style}
|
||||
>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiPanel grow={false} hasShadow={true}>
|
||||
<EuiEmptyPrompt
|
||||
actions={[
|
||||
<EuiButton fill={true} href={licensePageUrl}>
|
||||
{i18n.translate(
|
||||
'xpack.apm.serviceMap.licensePromptButtonText',
|
||||
{
|
||||
defaultMessage: 'Start 30-day Platinum trial'
|
||||
}
|
||||
)}
|
||||
</EuiButton>
|
||||
]}
|
||||
body={
|
||||
<p>
|
||||
{i18n.translate('xpack.apm.serviceMap.licensePromptBody', {
|
||||
defaultMessage:
|
||||
"In order to access Service Maps, you must be subscribed to an Elastic Platinum license. With it, you'll have the ability to visualize your entire application stack along with your APM data."
|
||||
})}
|
||||
</p>
|
||||
}
|
||||
title={
|
||||
<h2>
|
||||
{i18n.translate('xpack.apm.serviceMap.licensePromptTitle', {
|
||||
defaultMessage: 'Service maps is available in Platinum.'
|
||||
})}
|
||||
</h2>
|
||||
}
|
||||
/>
|
||||
</EuiPanel>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
|
@ -4,12 +4,14 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import theme from '@elastic/eui/dist/eui_theme_light.json';
|
||||
import { useUrlParams } from '../../../hooks/useUrlParams';
|
||||
import React from 'react';
|
||||
import { useFetcher } from '../../../hooks/useFetcher';
|
||||
import { Cytoscape } from './Cytoscape';
|
||||
import { useLicense } from '../../../hooks/useLicense';
|
||||
import { useUrlParams } from '../../../hooks/useUrlParams';
|
||||
import { Controls } from './Controls';
|
||||
import { Cytoscape } from './Cytoscape';
|
||||
import { PlatinumLicensePrompt } from './PlatinumLicensePrompt';
|
||||
|
||||
interface ServiceMapProps {
|
||||
serviceName?: string;
|
||||
|
@ -53,8 +55,11 @@ export function ServiceMap({ serviceName }: ServiceMapProps) {
|
|||
);
|
||||
|
||||
const elements = Array.isArray(data) ? data : [];
|
||||
const license = useLicense();
|
||||
const isValidPlatinumLicense =
|
||||
license?.isActive && license?.type === 'platinum';
|
||||
|
||||
return (
|
||||
return isValidPlatinumLicense ? (
|
||||
<Cytoscape
|
||||
elements={elements}
|
||||
serviceName={serviceName}
|
||||
|
@ -62,5 +67,7 @@ export function ServiceMap({ serviceName }: ServiceMapProps) {
|
|||
>
|
||||
<Controls />
|
||||
</Cytoscape>
|
||||
) : (
|
||||
<PlatinumLicensePrompt />
|
||||
);
|
||||
}
|
||||
|
|
|
@ -170,7 +170,7 @@ export class TransactionCharts extends Component<TransactionChartProps> {
|
|||
</EuiFlexItem>
|
||||
<LicenseContext.Consumer>
|
||||
{license =>
|
||||
this.renderMLHeader(license.features.ml?.is_available)
|
||||
this.renderMLHeader(license?.getFeature('ml').isAvailable)
|
||||
}
|
||||
</LicenseContext.Consumer>
|
||||
</EuiFlexGroup>
|
||||
|
|
|
@ -3,33 +3,27 @@
|
|||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { FETCH_STATUS, useFetcher } from '../../hooks/useFetcher';
|
||||
import { loadLicense, LicenseApiResponse } from '../../services/rest/xpack';
|
||||
import { InvalidLicenseNotification } from './InvalidLicenseNotification';
|
||||
import { useObservable } from 'react-use';
|
||||
import { ILicense } from '../../../../../../plugins/licensing/public';
|
||||
import { useApmPluginContext } from '../../hooks/useApmPluginContext';
|
||||
import { InvalidLicenseNotification } from './InvalidLicenseNotification';
|
||||
|
||||
const initialLicense: LicenseApiResponse = {
|
||||
features: {},
|
||||
license: {
|
||||
is_active: false
|
||||
}
|
||||
};
|
||||
export const LicenseContext = React.createContext(initialLicense);
|
||||
export const LicenseContext = React.createContext<ILicense | undefined>(
|
||||
undefined
|
||||
);
|
||||
|
||||
export const LicenseProvider: React.FC = ({ children }) => {
|
||||
const { http } = useApmPluginContext().core;
|
||||
const { data = initialLicense, status } = useFetcher(
|
||||
() => loadLicense(http),
|
||||
[http]
|
||||
);
|
||||
const hasValidLicense = data.license.is_active;
|
||||
export function LicenseProvider({ children }: { children: React.ReactChild }) {
|
||||
const { license$ } = useApmPluginContext().plugins.licensing;
|
||||
const license = useObservable(license$);
|
||||
const hasInvalidLicense = !license?.isActive;
|
||||
|
||||
// if license is invalid show an error message
|
||||
if (status === FETCH_STATUS.SUCCESS && !hasValidLicense) {
|
||||
if (hasInvalidLicense) {
|
||||
return <InvalidLicenseNotification />;
|
||||
}
|
||||
|
||||
// render rest of application and pass down license via context
|
||||
return <LicenseContext.Provider value={data} children={children} />;
|
||||
};
|
||||
return <LicenseContext.Provider value={license} children={children} />;
|
||||
}
|
||||
|
|
19
x-pack/legacy/plugins/apm/public/hooks/useKibanaUrl.ts
Normal file
19
x-pack/legacy/plugins/apm/public/hooks/useKibanaUrl.ts
Normal file
|
@ -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;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import url from 'url';
|
||||
import { useApmPluginContext } from './useApmPluginContext';
|
||||
|
||||
export function useKibanaUrl(
|
||||
/** The path to the plugin */ path: string,
|
||||
/** The hash path */ hash: string
|
||||
) {
|
||||
const { core } = useApmPluginContext();
|
||||
return url.format({
|
||||
pathname: core.http.basePath.prepend(path),
|
||||
hash
|
||||
});
|
||||
}
|
12
x-pack/legacy/plugins/apm/public/hooks/useLicense.ts
Normal file
12
x-pack/legacy/plugins/apm/public/hooks/useLicense.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { useContext } from 'react';
|
||||
import { LicenseContext } from '../context/LicenseContext';
|
||||
|
||||
export function useLicense() {
|
||||
return useContext(LicenseContext);
|
||||
}
|
|
@ -6,35 +6,36 @@
|
|||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Router, Route, Switch } from 'react-router-dom';
|
||||
import { Route, Router, Switch } from 'react-router-dom';
|
||||
import styled from 'styled-components';
|
||||
import { metadata } from 'ui/metadata';
|
||||
import { HomePublicPluginSetup } from '../../../../../../src/plugins/home/public';
|
||||
import {
|
||||
CoreStart,
|
||||
Plugin,
|
||||
CoreSetup,
|
||||
PluginInitializerContext,
|
||||
PackageInfo
|
||||
CoreStart,
|
||||
PackageInfo,
|
||||
Plugin,
|
||||
PluginInitializerContext
|
||||
} from '../../../../../../src/core/public';
|
||||
import { DataPublicPluginSetup } from '../../../../../../src/plugins/data/public';
|
||||
import { history } from '../utils/history';
|
||||
import { LocationProvider } from '../context/LocationContext';
|
||||
import { UrlParamsProvider } from '../context/UrlParamsContext';
|
||||
import { px, unit, units } from '../style/variables';
|
||||
import { LoadingIndicatorProvider } from '../context/LoadingIndicatorContext';
|
||||
import { LicenseProvider } from '../context/LicenseContext';
|
||||
import { UpdateBreadcrumbs } from '../components/app/Main/UpdateBreadcrumbs';
|
||||
import { HomePublicPluginSetup } from '../../../../../../src/plugins/home/public';
|
||||
import { LicensingPluginSetup } from '../../../../../plugins/licensing/public';
|
||||
import { routes } from '../components/app/Main/route_config';
|
||||
import { ScrollToTopOnPathChange } from '../components/app/Main/ScrollToTopOnPathChange';
|
||||
import { UpdateBreadcrumbs } from '../components/app/Main/UpdateBreadcrumbs';
|
||||
import { ApmPluginContext } from '../context/ApmPluginContext';
|
||||
import { LicenseProvider } from '../context/LicenseContext';
|
||||
import { LoadingIndicatorProvider } from '../context/LoadingIndicatorContext';
|
||||
import { LocationProvider } from '../context/LocationContext';
|
||||
import { MatchedRouteProvider } from '../context/MatchedRouteContext';
|
||||
import { UrlParamsProvider } from '../context/UrlParamsContext';
|
||||
import { createStaticIndexPattern } from '../services/rest/index_pattern';
|
||||
import { setHelpExtension } from './setHelpExtension';
|
||||
import { setReadonlyBadge } from './updateBadge';
|
||||
import { px, unit, units } from '../style/variables';
|
||||
import { history } from '../utils/history';
|
||||
import { featureCatalogueEntry } from './featureCatalogueEntry';
|
||||
import { getConfigFromInjectedMetadata } from './getConfigFromInjectedMetadata';
|
||||
import { setHelpExtension } from './setHelpExtension';
|
||||
import { toggleAppLinkInNav } from './toggleAppLinkInNav';
|
||||
import { ApmPluginContext } from '../context/ApmPluginContext';
|
||||
import { setReadonlyBadge } from './updateBadge';
|
||||
|
||||
export const REACT_APP_ROOT_ID = 'react-apm-root';
|
||||
|
||||
|
@ -64,6 +65,7 @@ export type ApmPluginStart = void;
|
|||
export interface ApmPluginSetupDeps {
|
||||
data: DataPublicPluginSetup;
|
||||
home: HomePublicPluginSetup;
|
||||
licensing: LicensingPluginSetup;
|
||||
}
|
||||
|
||||
export interface ConfigSchema {
|
||||
|
|
|
@ -1,45 +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;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { HttpStart } from 'kibana/public';
|
||||
import { callApi } from './callApi';
|
||||
|
||||
export interface LicenseApiResponse {
|
||||
license: {
|
||||
is_active: boolean;
|
||||
};
|
||||
features: {
|
||||
beats_management?: Record<string, unknown>;
|
||||
graph?: Record<string, unknown>;
|
||||
grokdebugger?: Record<string, unknown>;
|
||||
index_management?: Record<string, unknown>;
|
||||
logstash?: Record<string, unknown>;
|
||||
ml?: {
|
||||
is_available: boolean;
|
||||
license_type: number;
|
||||
has_expired: boolean;
|
||||
enable_links: boolean;
|
||||
show_links: boolean;
|
||||
};
|
||||
reporting?: Record<string, unknown>;
|
||||
rollup?: Record<string, unknown>;
|
||||
searchprofiler?: Record<string, unknown>;
|
||||
security?: Record<string, unknown>;
|
||||
spaces?: Record<string, unknown>;
|
||||
tilemap?: Record<string, unknown>;
|
||||
watcher?: {
|
||||
is_available: boolean;
|
||||
enable_links: boolean;
|
||||
show_links: boolean;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export async function loadLicense(http: HttpStart) {
|
||||
return callApi<LicenseApiResponse>(http, {
|
||||
pathname: `/api/xpack/v1/info`
|
||||
});
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue