[User Experience] Move ux app to new nav (#101005) (#101575)

This commit is contained in:
Shahzad 2021-06-08 15:15:48 +02:00 committed by GitHub
parent 919eb94814
commit 4970fa3106
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 111 additions and 88 deletions

0
.github/CODEOWNERS vendored Normal file
View file

View file

@ -43,6 +43,7 @@ export const renderApp = ({
config,
core: coreStart,
plugins: pluginsSetup,
observability: pluginsStart.observability,
observabilityRuleTypeRegistry,
};

View file

@ -12,8 +12,8 @@ import React from 'react';
import ReactDOM from 'react-dom';
import { Route, Router } from 'react-router-dom';
import { DefaultTheme, ThemeProvider } from 'styled-components';
import { i18n } from '@kbn/i18n';
import type { ObservabilityRuleTypeRegistry } from '../../../observability/public';
import { euiStyled } from '../../../../../src/plugins/kibana_react/common';
import {
KibanaContextProvider,
RedirectAppLinks,
@ -24,21 +24,16 @@ import { ScrollToTopOnPathChange } from '../components/app/Main/ScrollToTopOnPat
import { RumHome, UX_LABEL } from '../components/app/RumDashboard/RumHome';
import { ApmPluginContext } from '../context/apm_plugin/apm_plugin_context';
import { UrlParamsProvider } from '../context/url_params_context/url_params_context';
import { useBreadcrumbs } from '../hooks/use_breadcrumbs';
import { ConfigSchema } from '../index';
import { ApmPluginSetupDeps, ApmPluginStartDeps } from '../plugin';
import { createCallApmApi } from '../services/rest/createCallApmApi';
import { px, units } from '../style/variables';
import { createStaticIndexPattern } from '../services/rest/index_pattern';
import { UXActionMenu } from '../components/app/RumDashboard/ActionMenu';
import { redirectTo } from '../components/routing/redirect_to';
import { useBreadcrumbs } from '../../../observability/public';
import { useApmPluginContext } from '../context/apm_plugin/use_apm_plugin_context';
const CsmMainContainer = euiStyled.div`
padding: ${px(units.plus)};
height: 100%;
`;
export const rumRoutes: APMRouteDefinition[] = [
export const uxRoutes: APMRouteDefinition[] = [
{
exact: true,
path: '/',
@ -47,10 +42,20 @@ export const rumRoutes: APMRouteDefinition[] = [
},
];
function CsmApp() {
function UxApp() {
const [darkMode] = useUiSetting$<boolean>('theme:darkMode');
useBreadcrumbs(rumRoutes);
const { core } = useApmPluginContext();
const basePath = core.http.basePath.get();
useBreadcrumbs([
{ text: UX_LABEL, href: basePath + '/app/ux' },
{
text: i18n.translate('xpack.apm.ux.overview', {
defaultMessage: 'Overview',
}),
},
]);
return (
<ThemeProvider
@ -60,20 +65,20 @@ function CsmApp() {
darkMode,
})}
>
<CsmMainContainer data-test-subj="csmMainContainer" role="main">
<div data-test-subj="csmMainContainer" role="main">
<Route component={ScrollToTopOnPathChange} />
<RumHome />
</CsmMainContainer>
</div>
</ThemeProvider>
);
}
export function CsmAppRoot({
export function UXAppRoot({
appMountParameters,
core,
deps,
config,
corePlugins: { embeddable, maps },
corePlugins: { embeddable, maps, observability },
observabilityRuleTypeRegistry,
}: {
appMountParameters: AppMountParameters;
@ -91,6 +96,7 @@ export function CsmAppRoot({
config,
core,
plugins,
observability,
observabilityRuleTypeRegistry,
};
@ -101,7 +107,7 @@ export function CsmAppRoot({
<i18nCore.Context>
<Router history={history}>
<UrlParamsProvider>
<CsmApp />
<UxApp />
<UXActionMenu appMountParameters={appMountParameters} />
</UrlParamsProvider>
</Router>
@ -142,7 +148,7 @@ export const renderApp = ({
});
ReactDOM.render(
<CsmAppRoot
<UXAppRoot
appMountParameters={appMountParameters}
core={core}
deps={deps}

View file

@ -30,7 +30,7 @@ export const CsmSharedContext = createContext(defaultContext);
export function CsmSharedContextProvider({
children,
}: {
children: JSX.Element[];
children: JSX.Element;
}) {
const [newData, setNewData] = useState<SharedData>({ totalPageViews: 0 });

View file

@ -6,14 +6,10 @@
*/
import React from 'react';
import { EuiFlexItem } from '@elastic/eui';
import { EnvironmentFilter } from '../../../shared/EnvironmentFilter';
import { ServiceNameFilter } from '../URLFilter/ServiceNameFilter';
import { useFetcher } from '../../../../hooks/use_fetcher';
import { RUM_AGENT_NAMES } from '../../../../../common/agent_name';
import { useUrlParams } from '../../../../context/url_params_context/use_url_params';
import { UserPercentile } from '../UserPercentile';
import { useBreakPoints } from '../../../../hooks/use_break_points';
export function MainFilters() {
const {
@ -39,25 +35,11 @@ export function MainFilters() {
);
const rumServiceNames = data?.rumServices ?? [];
const { isSmall } = useBreakPoints();
// on mobile we want it to take full width
const envStyle = isSmall ? {} : { maxWidth: 200 };
return (
<>
<EuiFlexItem grow={false}>
<ServiceNameFilter
loading={status !== 'success'}
serviceNames={rumServiceNames}
/>
</EuiFlexItem>
<EuiFlexItem grow={false} style={envStyle}>
<EnvironmentFilter />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<UserPercentile />
</EuiFlexItem>
</>
<ServiceNameFilter
loading={status !== 'success'}
serviceNames={rumServiceNames}
/>
);
}

View file

@ -5,33 +5,58 @@
* 2.0.
*/
import { EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui';
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import React from 'react';
import { i18n } from '@kbn/i18n';
import { RumOverview } from '../RumDashboard';
import { CsmSharedContextProvider } from './CsmSharedContext';
import { MainFilters } from './Panels/MainFilters';
import { DatePicker } from '../../shared/DatePicker';
import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context';
import { EnvironmentFilter } from '../../shared/EnvironmentFilter';
import { UserPercentile } from './UserPercentile';
import { useBreakPoints } from '../../../hooks/use_break_points';
export const UX_LABEL = i18n.translate('xpack.apm.ux.title', {
defaultMessage: 'User Experience',
});
export function RumHome() {
const { observability } = useApmPluginContext();
const PageTemplateComponent = observability.navigation.PageTemplate;
const { isSmall } = useBreakPoints();
const envStyle = isSmall ? {} : { maxWidth: 200 };
return (
<CsmSharedContextProvider>
<EuiFlexGroup wrap justifyContent={'flexEnd'} responsive={true}>
<EuiFlexItem>
<EuiTitle>
<h1 className="eui-textNoWrap">{UX_LABEL}</h1>
</EuiTitle>
</EuiFlexItem>
<MainFilters />
<EuiFlexItem grow={false}>
<DatePicker />
</EuiFlexItem>
</EuiFlexGroup>
<RumOverview />
<PageTemplateComponent
pageHeader={{
pageTitle: UX_LABEL,
rightSideItems: [
<DatePicker />,
<div style={envStyle}>
<EnvironmentFilter />
</div>,
<UserPercentile />,
<MainFilters />,
],
}}
>
<RumOverview />
</PageTemplateComponent>
</CsmSharedContextProvider>
);
}
export function UxHomeHeaderItems() {
return (
<EuiFlexGroup wrap justifyContent={'flexEnd'} responsive={true}>
<MainFilters />
<EuiFlexItem grow={false}>
<DatePicker />
</EuiFlexItem>
</EuiFlexGroup>
);
}

View file

@ -25,19 +25,16 @@ export function RumOverview() {
}, []);
return (
<>
<EuiSpacer size="m" />
<EuiFlexGroup>
<EuiFlexItem grow={1}>
<LocalUIFilters {...localUIFiltersConfig} showCount={true}>
<URLFilter />
<EuiSpacer size="s" />
</LocalUIFilters>
</EuiFlexItem>
<EuiFlexItem grow={7}>
<RumDashboard />
</EuiFlexItem>
</EuiFlexGroup>
</>
<EuiFlexGroup>
<EuiFlexItem grow={1}>
<LocalUIFilters {...localUIFiltersConfig} showCount={true}>
<URLFilter />
<EuiSpacer size="s" />
</LocalUIFilters>
</EuiFlexItem>
<EuiFlexItem grow={7}>
<RumDashboard />
</EuiFlexItem>
</EuiFlexGroup>
);
}

View file

@ -11,6 +11,7 @@ import type { ObservabilityRuleTypeRegistry } from '../../../../observability/pu
import { ConfigSchema } from '../..';
import { ApmPluginSetupDeps } from '../../plugin';
import { MapsStartApi } from '../../../../maps/public';
import { ObservabilityPublicStart } from '../../../../observability/public';
export interface ApmPluginContextValue {
appMountParameters: AppMountParameters;
@ -18,6 +19,7 @@ export interface ApmPluginContextValue {
core: CoreStart;
plugins: ApmPluginSetupDeps & { maps?: MapsStartApi };
observabilityRuleTypeRegistry: ObservabilityRuleTypeRegistry;
observability: ObservabilityPublicStart;
}
export const ApmPluginContext = createContext({} as ApmPluginContextValue);

View file

@ -67,8 +67,8 @@ export interface ApmPluginStartDeps {
licensing: void;
maps?: MapsStartApi;
ml?: MlPluginStart;
observability: ObservabilityPublicStart;
triggersActionsUi: TriggersAndActionsUIPublicPluginStart;
observability: ObservabilityPublicStart;
}
export class ApmPlugin implements Plugin<ApmPluginSetup, ApmPluginStart> {
@ -150,6 +150,26 @@ export class ApmPlugin implements Plugin<ApmPluginSetup, ApmPluginStart> {
},
});
plugins.observability.navigation.registerSections(
of([
{
label: 'User Experience',
sortKey: 201,
entries: [
{
label: i18n.translate('xpack.apm.ux.overview.heading', {
defaultMessage: 'Overview',
}),
app: 'ux',
path: '/',
matchFullPath: true,
ignoreTrailingSlash: true,
},
],
},
])
);
core.application.register({
id: 'apm',
title: 'APM',
@ -231,7 +251,7 @@ export class ApmPlugin implements Plugin<ApmPluginSetup, ApmPluginStart> {
async mount(appMountParameters: AppMountParameters<unknown>) {
// Load application bundle and Get start service
const [{ renderApp }, [coreStart, corePlugins]] = await Promise.all([
import('./application/csmApp'),
import('./application/uxApp'),
core.getStartServices(),
]);

View file

@ -5,8 +5,8 @@
* 2.0.
*/
import { usePluginContext } from './use_plugin_context';
import { UI_SETTINGS } from '../../../../../src/plugins/data/public';
import { useKibana } from '../../../../../src/plugins/kibana_react/public';
export { UI_SETTINGS };
@ -14,6 +14,8 @@ type SettingKeys = keyof typeof UI_SETTINGS;
type SettingValues = typeof UI_SETTINGS[SettingKeys];
export function useKibanaUISettings<T>(key: SettingValues): T {
const { core } = usePluginContext();
return core.uiSettings.get<T>(key);
const {
services: { uiSettings },
} = useKibana();
return uiSettings!.get<T>(key);
}

View file

@ -57,6 +57,7 @@ export { useFetcher, FETCH_STATUS } from './hooks/use_fetcher';
export * from './typings';
export { useChartTheme } from './hooks/use_chart_theme';
export { useBreadcrumbs } from './hooks/use_breadcrumbs';
export { useTheme } from './hooks/use_theme';
export { getApmTraceUrl } from './utils/get_apm_trace_url';
export { createExploratoryViewUrl } from './components/shared/exploratory_view/configurations/utils';

View file

@ -7,8 +7,7 @@
import React, { useEffect } from 'react';
import { Provider as ReduxProvider } from 'react-redux';
import { Router } from 'react-router-dom';
import styled from 'styled-components';
import { EuiPage, EuiErrorBoundary } from '@elastic/eui';
import { EuiErrorBoundary } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { I18nStart, ChromeBreadcrumb, CoreStart, AppMountParameters } from 'kibana/public';
import {
@ -62,18 +61,6 @@ export interface UptimeAppProps {
appMountParameters: AppMountParameters;
}
const StyledPage = styled(EuiPage)`
display: flex;
flex-grow: 1;
flex-shrink: 0;
flex-basis: auto;
flex-direction: column;
> * {
flex-shrink: 0;
}
`;
const Application = (props: UptimeAppProps) => {
const {
basePath,
@ -131,7 +118,7 @@ const Application = (props: UptimeAppProps) => {
<UptimeSettingsContextProvider {...props}>
<UptimeThemeContextProvider darkMode={darkMode}>
<UptimeStartupPluginsContextProvider {...startPlugins}>
<StyledPage data-test-subj="uptimeApp">
<div data-test-subj="uptimeApp">
<RedirectAppLinks application={core.application}>
<main>
<UptimeAlertsFlyoutWrapper />
@ -139,7 +126,7 @@ const Application = (props: UptimeAppProps) => {
<ActionMenu appMountParameters={appMountParameters} />
</main>
</RedirectAppLinks>
</StyledPage>
</div>
</UptimeStartupPluginsContextProvider>
</UptimeThemeContextProvider>
</UptimeSettingsContextProvider>