mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[Stack Monitoring] Add overview page first version (#110486)
* Add header to page template * add external config provider and overview content * REmove unnecessary todos * Remove non working section from header Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
192556ef63
commit
50a95ff78a
8 changed files with 195 additions and 38 deletions
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import { createContext } from 'react';
|
||||
|
||||
export interface ExternalConfig {
|
||||
minIntervalSeconds: number;
|
||||
showLicenseExpiration: boolean;
|
||||
showCgroupMetricsElasticsearch: boolean;
|
||||
showCgroupMetricsLogstash: boolean;
|
||||
renderReactApp: boolean;
|
||||
}
|
||||
|
||||
export const ExternalConfigContext = createContext({} as ExternalConfig);
|
|
@ -16,6 +16,7 @@ interface GlobalStateProviderProps {
|
|||
|
||||
interface State {
|
||||
cluster_uuid?: string;
|
||||
ccs?: any;
|
||||
}
|
||||
|
||||
export const GlobalStateContext = createContext({} as State);
|
||||
|
|
|
@ -15,7 +15,7 @@ export function useClusters(clusterUuid?: string | null, ccs?: any, codePaths?:
|
|||
const [min] = useState(bounds.min.toISOString());
|
||||
const [max] = useState(bounds.max.toISOString());
|
||||
|
||||
const [clusters, setClusters] = useState([]);
|
||||
const [clusters, setClusters] = useState([] as any);
|
||||
const [loaded, setLoaded] = useState<boolean | null>(false);
|
||||
|
||||
let url = '../api/monitoring/v1/clusters';
|
||||
|
|
|
@ -11,17 +11,23 @@ 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 { ClusterOverview } from './pages/cluster/overview_page';
|
||||
import { MonitoringStartPluginDependencies } from '../types';
|
||||
import { GlobalStateProvider } from './global_state_context';
|
||||
import { ExternalConfigContext, ExternalConfig } from './external_config_context';
|
||||
import { createPreserveQueryHistory } from './preserve_query_history';
|
||||
import { RouteInit } from './route_init';
|
||||
|
||||
export const renderApp = (
|
||||
core: CoreStart,
|
||||
plugins: MonitoringStartPluginDependencies,
|
||||
{ element }: AppMountParameters
|
||||
{ element }: AppMountParameters,
|
||||
externalConfig: ExternalConfig
|
||||
) => {
|
||||
ReactDOM.render(<MonitoringApp core={core} plugins={plugins} />, element);
|
||||
ReactDOM.render(
|
||||
<MonitoringApp core={core} plugins={plugins} externalConfig={externalConfig} />,
|
||||
element
|
||||
);
|
||||
|
||||
return () => {
|
||||
ReactDOM.unmountComponentAtNode(element);
|
||||
|
@ -31,38 +37,46 @@ export const renderApp = (
|
|||
const MonitoringApp: React.FC<{
|
||||
core: CoreStart;
|
||||
plugins: MonitoringStartPluginDependencies;
|
||||
}> = ({ core, plugins }) => {
|
||||
externalConfig: ExternalConfig;
|
||||
}> = ({ core, plugins, externalConfig }) => {
|
||||
const history = createPreserveQueryHistory();
|
||||
|
||||
return (
|
||||
<KibanaContextProvider services={{ ...core, ...plugins }}>
|
||||
<GlobalStateProvider query={plugins.data.query} toasts={core.notifications.toasts}>
|
||||
<Router history={history}>
|
||||
<Switch>
|
||||
<Route path="/no-data" component={NoData} />
|
||||
<Route path="/loading" component={LoadingPage} />
|
||||
<RouteInit
|
||||
path="/license"
|
||||
component={License}
|
||||
codePaths={['all']}
|
||||
fetchAllClusters={false}
|
||||
/>
|
||||
<RouteInit path="/home" component={Home} codePaths={['all']} fetchAllClusters={false} />
|
||||
<RouteInit
|
||||
path="/overview"
|
||||
component={ClusterOverview}
|
||||
codePaths={['all']}
|
||||
fetchAllClusters={false}
|
||||
/>
|
||||
<Redirect
|
||||
to={{
|
||||
pathname: '/loading',
|
||||
search: history.location.search,
|
||||
}}
|
||||
/>
|
||||
</Switch>
|
||||
</Router>
|
||||
</GlobalStateProvider>
|
||||
<ExternalConfigContext.Provider value={externalConfig}>
|
||||
<GlobalStateProvider query={plugins.data.query} toasts={core.notifications.toasts}>
|
||||
<Router history={history}>
|
||||
<Switch>
|
||||
<Route path="/no-data" component={NoData} />
|
||||
<Route path="/loading" component={LoadingPage} />
|
||||
<RouteInit
|
||||
path="/license"
|
||||
component={License}
|
||||
codePaths={['all']}
|
||||
fetchAllClusters={false}
|
||||
/>
|
||||
<RouteInit
|
||||
path="/home"
|
||||
component={Home}
|
||||
codePaths={['all']}
|
||||
fetchAllClusters={false}
|
||||
/>
|
||||
<RouteInit
|
||||
path="/overview"
|
||||
component={ClusterOverview}
|
||||
codePaths={['all']}
|
||||
fetchAllClusters={false}
|
||||
/>
|
||||
<Redirect
|
||||
to={{
|
||||
pathname: '/loading',
|
||||
search: history.location.search,
|
||||
}}
|
||||
/>
|
||||
</Switch>
|
||||
</Router>
|
||||
</GlobalStateProvider>
|
||||
</ExternalConfigContext.Provider>
|
||||
</KibanaContextProvider>
|
||||
);
|
||||
};
|
||||
|
@ -75,10 +89,6 @@ const Home: React.FC<{}> = () => {
|
|||
return <div>Home page (Cluster listing)</div>;
|
||||
};
|
||||
|
||||
const ClusterOverview: React.FC<{}> = () => {
|
||||
return <div>Cluster overview page</div>;
|
||||
};
|
||||
|
||||
const License: React.FC<{}> = () => {
|
||||
return <div>License page</div>;
|
||||
};
|
||||
|
|
|
@ -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, { useContext } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { CODE_PATH_ALL } from '../../../../common/constants';
|
||||
import { PageTemplate } from '../page_template';
|
||||
import { useClusters } from '../../hooks/use_clusters';
|
||||
import { GlobalStateContext } from '../../global_state_context';
|
||||
import { TabMenuItem } from '../page_template';
|
||||
import { PageLoading } from '../../../components';
|
||||
import { Overview } from '../../../components/cluster/overview';
|
||||
import { ExternalConfigContext } from '../../external_config_context';
|
||||
|
||||
const CODE_PATHS = [CODE_PATH_ALL];
|
||||
|
||||
export const ClusterOverview: React.FC<{}> = () => {
|
||||
// TODO: check how many requests with useClusters
|
||||
const state = useContext(GlobalStateContext);
|
||||
const externalConfig = useContext(ExternalConfigContext);
|
||||
const { clusters, loaded } = useClusters(state.cluster_uuid, state.ccs, CODE_PATHS);
|
||||
let tabs: TabMenuItem[] = [];
|
||||
|
||||
const title = i18n.translate('xpack.monitoring.cluster.overviewTitle', {
|
||||
defaultMessage: 'Overview',
|
||||
});
|
||||
|
||||
const pageTitle = i18n.translate('xpack.monitoring.cluster.overview.pageTitle', {
|
||||
defaultMessage: 'Cluster overview',
|
||||
});
|
||||
|
||||
if (loaded) {
|
||||
tabs = [
|
||||
{
|
||||
id: 'clusterName',
|
||||
label: clusters[0].cluster_name,
|
||||
disabled: false,
|
||||
description: clusters[0].cluster_name,
|
||||
onClick: () => {},
|
||||
testSubj: 'clusterName',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return (
|
||||
<PageTemplate title={title} pageTitle={pageTitle} tabs={tabs}>
|
||||
{loaded ? (
|
||||
<Overview
|
||||
cluster={clusters[0]}
|
||||
alerts={[]}
|
||||
setupMode={{}}
|
||||
showLicenseExpiration={externalConfig.showLicenseExpiration}
|
||||
/>
|
||||
) : (
|
||||
<PageLoading />
|
||||
)}
|
||||
</PageTemplate>
|
||||
);
|
||||
};
|
|
@ -5,16 +5,74 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiTab, EuiTabs, EuiTitle } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
import { useTitle } from '../hooks/use_title';
|
||||
|
||||
export interface TabMenuItem {
|
||||
id: string;
|
||||
label: string;
|
||||
description: string;
|
||||
disabled: boolean;
|
||||
onClick: () => void;
|
||||
testSubj: string;
|
||||
}
|
||||
interface PageTemplateProps {
|
||||
title: string;
|
||||
pageTitle?: string;
|
||||
children: React.ReactNode;
|
||||
tabs?: TabMenuItem[];
|
||||
}
|
||||
|
||||
export const PageTemplate = ({ title, children }: PageTemplateProps) => {
|
||||
export const PageTemplate = ({ title, pageTitle, tabs, children }: PageTemplateProps) => {
|
||||
useTitle('', title);
|
||||
|
||||
return <div>{children}</div>;
|
||||
return (
|
||||
<div className="app-container">
|
||||
<EuiFlexGroup gutterSize="l" justifyContent="spaceBetween" responsive>
|
||||
<EuiFlexItem>
|
||||
<EuiFlexGroup
|
||||
gutterSize="none"
|
||||
justifyContent="spaceEvenly"
|
||||
direction="column"
|
||||
responsive
|
||||
>
|
||||
<EuiFlexItem>
|
||||
<div id="setupModeNav">{/* HERE GOES THE SETUP BUTTON */}</div>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem className="monTopNavSecondItem">
|
||||
{pageTitle && (
|
||||
<div data-test-subj="monitoringPageTitle">
|
||||
<EuiTitle size="xs">
|
||||
<h1>{pageTitle}</h1>
|
||||
</EuiTitle>
|
||||
</div>
|
||||
)}
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem>{/* HERE GOES THE TIMEPICKER */}</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
{tabs && (
|
||||
<EuiTabs>
|
||||
{tabs.map((item, idx) => {
|
||||
return (
|
||||
<EuiTab
|
||||
key={idx}
|
||||
disabled={item.disabled}
|
||||
onClick={item.onClick}
|
||||
title={item.label}
|
||||
data-test-subj={item.testSubj}
|
||||
>
|
||||
{item.label}
|
||||
</EuiTab>
|
||||
);
|
||||
})}
|
||||
</EuiTabs>
|
||||
)}
|
||||
<div>{children}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
8
x-pack/plugins/monitoring/public/components/cluster/overview/index.d.ts
vendored
Normal file
8
x-pack/plugins/monitoring/public/components/cluster/overview/index.d.ts
vendored
Normal file
|
@ -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 Overview: FunctionComponent<Props>;
|
|
@ -127,7 +127,7 @@ export class MonitoringPlugin
|
|||
const config = Object.fromEntries(externalConfig);
|
||||
if (config.renderReactApp) {
|
||||
const { renderApp } = await import('./application');
|
||||
return renderApp(coreStart, pluginsStart, params);
|
||||
return renderApp(coreStart, pluginsStart, params, config);
|
||||
} else {
|
||||
const monitoringApp = new AngularApp(deps);
|
||||
const removeHistoryListener = params.history.listen((location) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue