Merge pull request #33389 from backstage/rugvip/nfs-header-page-migration
plugins: migrate NFS pages to HeaderPage
This commit is contained in:
@@ -41,6 +41,7 @@ class NavItemBag implements NavContentNavItems {
|
||||
readonly #items: NavContentNavItem[];
|
||||
readonly #index: Map<string, NavContentNavItem>;
|
||||
readonly #taken: Set<string>;
|
||||
#restItems: NavContentNavItem[] | undefined;
|
||||
|
||||
constructor(items: NavContentNavItem[], taken?: Iterable<string>) {
|
||||
this.#items = items;
|
||||
@@ -50,14 +51,27 @@ class NavItemBag implements NavContentNavItems {
|
||||
|
||||
take(id: string): NavContentNavItem | undefined {
|
||||
const item = this.#index.get(id);
|
||||
if (item) {
|
||||
if (item && !this.#taken.has(id)) {
|
||||
this.#taken.add(id);
|
||||
if (this.#restItems) {
|
||||
const index = this.#restItems.findIndex(
|
||||
restItem => restItem.node.spec.id === id,
|
||||
);
|
||||
if (index !== -1) {
|
||||
this.#restItems.splice(index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
rest(): NavContentNavItem[] {
|
||||
return this.#items.filter(item => !this.#taken.has(item.node.spec.id));
|
||||
if (!this.#restItems) {
|
||||
this.#restItems = this.#items.filter(
|
||||
item => !this.#taken.has(item.node.spec.id),
|
||||
);
|
||||
}
|
||||
return this.#restItems;
|
||||
}
|
||||
|
||||
clone(): NavContentNavItems {
|
||||
@@ -65,19 +79,32 @@ class NavItemBag implements NavContentNavItems {
|
||||
}
|
||||
|
||||
withComponent(Component: (props: NavContentNavItem) => JSX.Element) {
|
||||
let renderedItems: JSX.Element[] | undefined;
|
||||
|
||||
return {
|
||||
take: (id: string) => {
|
||||
const item = this.take(id);
|
||||
return item ? <Component {...item} /> : null;
|
||||
if (item && renderedItems) {
|
||||
const index = renderedItems.findIndex(
|
||||
renderedItem => renderedItem.key === item.node.spec.id,
|
||||
);
|
||||
if (index !== -1) {
|
||||
renderedItems.splice(index, 1);
|
||||
}
|
||||
}
|
||||
return item ? <Component key={item.node.spec.id} {...item} /> : null;
|
||||
},
|
||||
rest: (options?: { sortBy?: 'title' }) => {
|
||||
const items = this.rest();
|
||||
if (options?.sortBy === 'title') {
|
||||
items.sort((a, b) => a.title.localeCompare(b.title));
|
||||
if (!renderedItems) {
|
||||
if (options?.sortBy === 'title') {
|
||||
items.sort((a, b) => a.title.localeCompare(b.title));
|
||||
}
|
||||
renderedItems = items.map(item => (
|
||||
<Component key={item.node.spec.id} {...item} />
|
||||
));
|
||||
}
|
||||
return items.map(item => (
|
||||
<Component key={item.node.spec.id} {...item} />
|
||||
));
|
||||
return renderedItems;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import {
|
||||
import { PluginHeader } from '@backstage/ui';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import { useMemo } from 'react';
|
||||
import { useResolvedPath } from 'react-router-dom';
|
||||
|
||||
export const Progress = SwappableComponentBlueprint.make({
|
||||
name: 'core-progress',
|
||||
@@ -75,31 +76,35 @@ export const PageLayout = SwappableComponentBlueprint.make({
|
||||
component: SwappablePageLayout,
|
||||
loader: () => (props: PageLayoutProps) => {
|
||||
const { title, icon, noHeader, headerActions, tabs, children } = props;
|
||||
const tabsWithMatchStrategy = useMemo(
|
||||
// TODO(Rugvip): Different solution to this path handling would be good
|
||||
const parentPath = useResolvedPath('.').pathname.replace(/\/$/, '');
|
||||
const resolvedTabs = useMemo(
|
||||
() =>
|
||||
tabs?.map(tab => ({
|
||||
...tab,
|
||||
href: tab.href.startsWith('/')
|
||||
? tab.href
|
||||
: `${parentPath}/${tab.href}`.replace(/\/{2,}/g, '/'),
|
||||
matchStrategy: 'prefix' as const,
|
||||
})),
|
||||
[tabs],
|
||||
[tabs, parentPath],
|
||||
);
|
||||
|
||||
if (tabsWithMatchStrategy) {
|
||||
return (
|
||||
<>
|
||||
{!noHeader && (
|
||||
<PluginHeader
|
||||
title={title}
|
||||
icon={icon}
|
||||
tabs={tabsWithMatchStrategy}
|
||||
customActions={headerActions}
|
||||
/>
|
||||
)}
|
||||
{children}
|
||||
</>
|
||||
);
|
||||
if (noHeader) {
|
||||
return <>{children}</>;
|
||||
}
|
||||
return <>{children}</>;
|
||||
|
||||
return (
|
||||
<>
|
||||
<PluginHeader
|
||||
title={title}
|
||||
icon={icon}
|
||||
tabs={resolvedTabs}
|
||||
customActions={headerActions}
|
||||
/>
|
||||
{children}
|
||||
</>
|
||||
);
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user