diff --git a/x-pack/plugins/monitoring/public/application/index.tsx b/x-pack/plugins/monitoring/public/application/index.tsx
index e15ad995ca161..19a367977ffc8 100644
--- a/x-pack/plugins/monitoring/public/application/index.tsx
+++ b/x-pack/plugins/monitoring/public/application/index.tsx
@@ -11,6 +11,7 @@ import ReactDOM from 'react-dom';
import { Route, Switch, Redirect, Router } from 'react-router-dom';
import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public';
import { LoadingPage } from './pages/loading_page';
+import { LicensePage } from './pages/license_page';
import { ClusterOverview } from './pages/cluster/overview_page';
import { MonitoringStartPluginDependencies } from '../types';
import { GlobalStateProvider } from './global_state_context';
@@ -53,7 +54,7 @@ const MonitoringApp: React.FC<{
@@ -91,7 +92,3 @@ const NoData: React.FC<{}> = () => {
const Home: React.FC<{}> = () => {
return
Home page (Cluster listing)
;
};
-
-const License: React.FC<{}> = () => {
- return License page
;
-};
diff --git a/x-pack/plugins/monitoring/public/application/pages/license_page.tsx b/x-pack/plugins/monitoring/public/application/pages/license_page.tsx
new file mode 100644
index 0000000000000..3a46840e7d30c
--- /dev/null
+++ b/x-pack/plugins/monitoring/public/application/pages/license_page.tsx
@@ -0,0 +1,124 @@
+/*
+ * 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, { useContext, useState, useCallback, useEffect } from 'react';
+import { i18n } from '@kbn/i18n';
+import moment from 'moment-timezone';
+import { PageTemplate } from './page_template';
+import { License } from '../../components';
+import { GlobalStateContext } from '../global_state_context';
+import { CODE_PATH_LICENSE, STANDALONE_CLUSTER_CLUSTER_UUID } from '../../../common/constants';
+import { useKibana } from '../../../../../../src/plugins/kibana_react/public';
+import { MonitoringTimeContainer } from './use_monitoring_time';
+
+const CODE_PATHS = [CODE_PATH_LICENSE];
+
+export const LicensePage: React.FC<{}> = () => {
+ const title = i18n.translate('xpack.monitoring.license.licenseRouteTitle', {
+ defaultMessage: 'License',
+ });
+
+ const { setIsDisabled } = useContext(MonitoringTimeContainer.Context);
+ useEffect(() => {
+ setIsDisabled(true);
+ return () => {
+ setIsDisabled(false);
+ };
+ }, [setIsDisabled]);
+
+ const state = useContext(GlobalStateContext);
+ const clusterUuid = state.cluster_uuid;
+ const ccs = state.ccs;
+ const [clusters, setClusters] = useState([] as any);
+
+ const { services } = useKibana<{ data: any }>();
+ const timezone = services.uiSettings?.get('dateFormat:tz');
+ const uploadLicensePath = services.application?.getUrlForApp('management', {
+ path: 'stack/license_management/upload_license',
+ });
+
+ const getPageData = useCallback(async () => {
+ const bounds = services.data?.query.timefilter.timefilter.getBounds();
+ let url = '../api/monitoring/v1/clusters';
+ if (clusterUuid) {
+ url += `/${clusterUuid}`;
+ }
+
+ try {
+ const response = await services.http?.fetch(url, {
+ method: 'POST',
+ body: JSON.stringify({
+ ccs,
+ timeRange: {
+ min: bounds.min.toISOString(),
+ max: bounds.max.toISOString(),
+ },
+ codePaths: CODE_PATHS,
+ }),
+ });
+
+ setClusters(formatClusters(response));
+ } catch (err) {
+ // TODO handle error
+ }
+ }, [ccs, clusterUuid, services.data?.query.timefilter.timefilter, services.http]);
+
+ return (
+
+ {licenseComponent(clusters, timezone, uploadLicensePath)}
+
+ );
+};
+
+function licenseComponent(
+ clusters: any,
+ timezone: string,
+ uploadLicensePath: string | undefined
+): any {
+ if (clusters.length) {
+ const cluster = clusters[0];
+ const isPrimaryCluster = cluster.isPrimary;
+ const license = cluster.license;
+ let expiryDate = license?.expiry_date_in_millis;
+
+ if (expiryDate !== undefined) {
+ expiryDate = formatDateTimeLocal(expiryDate, timezone);
+ }
+
+ const isExpired = Date.now() > expiryDate;
+
+ return (
+
+ );
+ } else {
+ return null;
+ }
+}
+
+// From x-pack/plugins/monitoring/common/formatting.ts with corrected typing
+// TODO open github issue to correct other usages
+export function formatDateTimeLocal(date: number | Date, timezone: string | null) {
+ return moment.tz(date, timezone || moment.tz.guess()).format('LL LTS');
+}
+
+function formatClusters(clusters: any) {
+ return clusters.map(formatCluster);
+}
+
+function formatCluster(cluster: any) {
+ if (cluster.cluster_uuid === STANDALONE_CLUSTER_CLUSTER_UUID) {
+ cluster.cluster_name = 'Standalone Cluster';
+ }
+ return cluster;
+}
diff --git a/x-pack/plugins/monitoring/public/application/pages/use_monitoring_time.tsx b/x-pack/plugins/monitoring/public/application/pages/use_monitoring_time.tsx
index 0359ddf792f10..8a343a5c61cd6 100644
--- a/x-pack/plugins/monitoring/public/application/pages/use_monitoring_time.tsx
+++ b/x-pack/plugins/monitoring/public/application/pages/use_monitoring_time.tsx
@@ -34,6 +34,7 @@ export const useMonitoringTime = () => {
const [refreshInterval, setRefreshInterval] = useState(value || DEFAULT_REFRESH_INTERVAL_VALUE);
const [isPaused, setIsPaused] = useState(pause || DEFAULT_REFRESH_INTERVAL_PAUSE);
const [currentTimerange, setTimeRange] = useState(defaultTimeRange);
+ const [isDisabled, setIsDisabled] = useState(false);
const handleTimeChange = useCallback(
(start: string, end: string) => {
@@ -50,6 +51,8 @@ export const useMonitoringTime = () => {
refreshInterval,
setIsPaused,
isPaused,
+ setIsDisabled,
+ isDisabled,
};
};
diff --git a/x-pack/plugins/monitoring/public/components/index.d.ts b/x-pack/plugins/monitoring/public/components/index.d.ts
index d027298c81c4c..fc1a81cc4dba2 100644
--- a/x-pack/plugins/monitoring/public/components/index.d.ts
+++ b/x-pack/plugins/monitoring/public/components/index.d.ts
@@ -6,3 +6,4 @@
*/
export const PageLoading: FunctionComponent;
+export const License: FunctionComponent;
diff --git a/x-pack/plugins/monitoring/public/components/shared/toolbar.tsx b/x-pack/plugins/monitoring/public/components/shared/toolbar.tsx
index aa942e0764d29..9a77b07b96a6e 100644
--- a/x-pack/plugins/monitoring/public/components/shared/toolbar.tsx
+++ b/x-pack/plugins/monitoring/public/components/shared/toolbar.tsx
@@ -30,6 +30,7 @@ export const MonitoringToolbar: React.FC = ({ pageTitle,
refreshInterval,
setIsPaused,
isPaused,
+ isDisabled,
} = useContext(MonitoringTimeContainer.Context);
const state = useContext(GlobalStateContext);
@@ -85,6 +86,7 @@ export const MonitoringToolbar: React.FC = ({ pageTitle,