Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
31f87a9
WIP many renders reduced
kqualters-elastic Feb 14, 2025
803256a
Move PluginTemplateWrapper further up
kqualters-elastic Feb 20, 2025
62854d0
WIP no idea how redirects ever worked
kqualters-elastic Mar 4, 2025
180856a
Merge branch 'main' into app-rendering-alot
kqualters-elastic Mar 4, 2025
9b67416
Good state
kqualters-elastic Mar 4, 2025
ba83fc1
Fix missing export
kqualters-elastic Mar 6, 2025
b1713b1
Merge remote-tracking branch 'upstream/main' into fix-wrappers-via-ro…
kqualters-elastic Mar 6, 2025
1465410
Fix types/update snapshots
kqualters-elastic Mar 6, 2025
0c4b45c
Merge remote-tracking branch 'upstream/main' into fix-wrappers-via-ro…
kqualters-elastic Mar 6, 2025
e587246
Remove testing package.json changes
kqualters-elastic Mar 6, 2025
3a79dee
Undo yarn.lock change
kqualters-elastic Mar 6, 2025
ed80b7b
Keep timeline rendered while in security solution
kqualters-elastic Mar 7, 2025
45fab95
Merge remote-tracking branch 'upstream/main' into fix-wrappers-via-ro…
kqualters-elastic Apr 1, 2025
3800a96
Clean up tour observables
kqualters-elastic Apr 2, 2025
264b539
Fix failing tests
kqualters-elastic Apr 2, 2025
b9dbe98
Undo some shared-ux template changes
kqualters-elastic Apr 2, 2025
2ac2a3e
Merge remote-tracking branch 'upstream/main' into fix-wrappers-via-ro…
kqualters-elastic Apr 2, 2025
9c317b1
[CI] Auto-commit changed files from 'node scripts/yarn_deduplicate'
kibanamachine Apr 2, 2025
3d66d15
Remove pointless change
kqualters-elastic Apr 2, 2025
e5c88e7
Merge branch 'main' into fix-wrappers-via-routes
Apr 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { ThrowIfError } from '@kbn/shared-ux-error-boundary';
import type { Mounter } from '../types';
import { AppNotFound } from './app_not_found_screen';

interface Props {
export interface AppContainerProps {
/** Path application is mounted on without the global basePath */
appPath: string;
appId: string;
Expand All @@ -40,7 +40,7 @@ interface Props {
showPlainSpinner?: boolean;
}

export const AppContainer: FC<Props> = ({
export const AppContainer: FC<AppContainerProps> = ({
mounter,
appId,
appPath,
Expand All @@ -51,7 +51,7 @@ export const AppContainer: FC<Props> = ({
setIsMounting,
theme$,
showPlainSpinner,
}: Props) => {
}: AppContainerProps) => {
const [error, setError] = useState<Error | null>(null);
const [showSpinner, setShowSpinner] = useState(true);
const [appNotFound, setAppNotFound] = useState(false);
Expand Down
122 changes: 87 additions & 35 deletions src/core/packages/application/browser-internal/src/ui/app_router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { KibanaErrorBoundary, KibanaErrorBoundaryProvider } from '@kbn/shared-ux
import type { AnalyticsServiceStart } from '@kbn/core-analytics-browser';
import type { Mounter } from '../types';
import { AppContainer } from './app_container';
import type { AppContainerProps } from './app_container';
import { CoreScopedHistory } from '../scoped_history';

interface Props {
Expand All @@ -39,6 +40,51 @@ interface Params {
appId: string;
}

const MountedRoute: FunctionComponent<AppContainerProps> = React.memo(
({
appPath,
appStatus,
createScopedHistory,
appId,
mounter,
setAppLeaveHandler,
setAppActionMenu,
setIsMounting,
theme$,
showPlainSpinner,
}) => {
const appContainerProps = useMemo(() => {
return {
appId,
appPath,
appStatus,
createScopedHistory,
mounter,
setAppLeaveHandler,
setAppActionMenu,
setIsMounting,
theme$,
showPlainSpinner,
};
}, [
appPath,
appStatus,
createScopedHistory,
appId,
mounter,
setAppLeaveHandler,
setAppActionMenu,
setIsMounting,
theme$,
showPlainSpinner,
]);

return <AppContainer {...appContainerProps} />;
}
);

MountedRoute.displayName = 'MountedRoute';

export const AppRouter: FunctionComponent<Props> = ({
history,
analytics,
Expand All @@ -58,34 +104,44 @@ export const AppRouter: FunctionComponent<Props> = ({

const showPlainSpinner = useObservable(hasCustomBranding$ ?? EMPTY, false);

const routes = useMemo(() => {
return [...mounters].map(([appId, mounter]) => (
<Route
key={mounter.appRoute}
path={mounter.appRoute}
exact={mounter.exactRoute}
render={({ match: { path } }) => (
<MountedRoute
appPath={path}
appStatus={appStatuses.get(appId) ?? AppStatus.inaccessible}
createScopedHistory={createScopedHistory}
appId={appId}
mounter={mounter}
setAppLeaveHandler={setAppLeaveHandler}
setAppActionMenu={setAppActionMenu}
setIsMounting={setIsMounting}
theme$={theme$}
showPlainSpinner={showPlainSpinner}
/>
)}
/>
));
}, [
mounters,
setAppLeaveHandler,
setAppActionMenu,
setIsMounting,
theme$,
showPlainSpinner,
appStatuses,
createScopedHistory,
]);
return (
<KibanaErrorBoundaryProvider analytics={analytics}>
<KibanaErrorBoundary>
<Router history={history}>
<Routes>
{[...mounters].map(([appId, mounter]) => (
<Route
key={mounter.appRoute}
path={mounter.appRoute}
exact={mounter.exactRoute}
render={({ match: { path } }) => (
<AppContainer
appPath={path}
appStatus={appStatuses.get(appId) ?? AppStatus.inaccessible}
createScopedHistory={createScopedHistory}
{...{
appId,
mounter,
setAppLeaveHandler,
setAppActionMenu,
setIsMounting,
theme$,
showPlainSpinner,
}}
/>
)}
/>
))}
{routes}
{/* handler for legacy apps and used as a catch-all to display 404 page on not existing /app/appId apps*/}
<Route
path="/app/:appId"
Expand All @@ -95,22 +151,18 @@ export const AppRouter: FunctionComponent<Props> = ({
url,
},
}: RouteComponentProps<Params>) => {
// the id/mounter retrieval can be removed once #76348 is addressed
const [id, mounter] = mounters.has(appId) ? [appId, mounters.get(appId)] : [];
return (
<AppContainer
<MountedRoute
appPath={url}
appId={id ?? appId}
appId={mounters.has(appId) ? appId : ''}
appStatus={appStatuses.get(appId) ?? AppStatus.inaccessible}
createScopedHistory={createScopedHistory}
{...{
mounter,
setAppLeaveHandler,
setAppActionMenu,
setIsMounting,
theme$,
showPlainSpinner,
}}
mounter={mounters.has(appId) ? mounters.get(appId) : undefined}
setAppLeaveHandler={setAppLeaveHandler}
setAppActionMenu={setAppActionMenu}
setIsMounting={setIsMounting}
theme$={theme$}
showPlainSpinner={showPlainSpinner}
/>
);
}}
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import React, { FC } from 'react';
import React, { FC, memo } from 'react';
import { EuiPageTemplate } from '@elastic/eui';

import {
Expand All @@ -18,50 +18,46 @@ import { KibanaPageTemplateProps } from '@kbn/shared-ux-page-kibana-template-typ

import { KibanaPageTemplateInner, KibanaPageTemplateWithSolutionNav } from './page_template_inner';

export const _KibanaPageTemplate: FC<KibanaPageTemplateProps> = ({
className,
children,
solutionNav,
noDataConfig,
...rest
}) => {
/**
* If passing the custom template of `noDataConfig`
*/
if (noDataConfig && solutionNav) {
return (
<NoDataConfigPageWithSolutionNavBar
data-test-subj={rest['data-test-subj']}
className={className}
noDataConfig={noDataConfig}
solutionNav={solutionNav}
/>
);
}
export const _KibanaPageTemplate: FC<Omit<KibanaPageTemplateProps, 'ref'>> = memo(
({ className, children, solutionNav, noDataConfig, ...rest }) => {
/**
* If passing the custom template of `noDataConfig`
*/
if (noDataConfig && solutionNav) {
return (
<NoDataConfigPageWithSolutionNavBar
data-test-subj={rest['data-test-subj']}
className={className}
noDataConfig={noDataConfig}
solutionNav={solutionNav}
/>
);
}

if (noDataConfig) {
return (
<NoDataConfigPage
data-test-subj={rest['data-test-subj']}
className={className}
noDataConfig={noDataConfig}
/>
);
}
if (noDataConfig) {
return (
<NoDataConfigPage
data-test-subj={rest['data-test-subj']}
className={className}
noDataConfig={noDataConfig}
/>
);
}

if (solutionNav) {
return (
<KibanaPageTemplateWithSolutionNav
className={className}
solutionNav={solutionNav}
children={children}
{...rest}
/>
);
}
if (solutionNav) {
return (
<KibanaPageTemplateWithSolutionNav
className={className}
solutionNav={solutionNav}
children={children}
{...rest}
/>
);
}

return <KibanaPageTemplateInner className={className} children={children} {...rest} />;
};
return <KibanaPageTemplateInner className={className} children={children} {...rest} />;
}
);

/**
* Kibana-specific wrapper of EuiPageTemplate and it's namespaced components
Expand Down
Loading