diff --git a/extensions/example-extension/page.tsx b/extensions/example-extension/page.tsx
index 66e55e354b..92824e5a22 100644
--- a/extensions/example-extension/page.tsx
+++ b/extensions/example-extension/page.tsx
@@ -26,6 +26,7 @@ export class ExamplePage extends React.Component<{ extension: LensRendererExtens
const doodleStyle = {
width: "200px"
};
+
return (
diff --git a/src/extensions/registries/__tests__/page-registry.test.ts b/src/extensions/registries/__tests__/page-registry.test.ts
index 647fbb2b4f..9b07eb439f 100644
--- a/src/extensions/registries/__tests__/page-registry.test.ts
+++ b/src/extensions/registries/__tests__/page-registry.test.ts
@@ -70,31 +70,31 @@ describe("globalPageRegistry", () => {
], ext);
});
- // describe("getByPageMenuTarget", () => {
- // it("matching to first registered page without id", () => {
- // const page = globalPageRegistry.getByPageMenuTarget({ extensionId: ext.name });
- //
- // expect(page.id).toEqual(undefined);
- // expect(page.extensionId).toEqual(ext.name);
- // expect(page.url).toEqual(getExtensionPageUrl({ extensionId: ext.name }));
- // });
- //
- // it("returns matching page", () => {
- // const page = globalPageRegistry.getByPageMenuTarget({
- // pageId: "test-page",
- // extensionId: ext.name
- // });
- //
- // expect(page.id).toEqual("test-page");
- // });
- //
- // it("returns null if target not found", () => {
- // const page = globalPageRegistry.getByPageMenuTarget({
- // pageId: "wrong-page",
- // extensionId: ext.name
- // });
- //
- // expect(page).toBeNull();
- // });
- // });
+ describe("getByPageMenuTarget", () => {
+ it("matching to first registered page without id", () => {
+ const page = globalPageRegistry.getByPageTarget({ extensionId: ext.name });
+
+ expect(page.id).toEqual(undefined);
+ expect(page.extensionId).toEqual(ext.name);
+ expect(page.url).toEqual(getExtensionPageUrl({ extensionId: ext.name }));
+ });
+
+ it("returns matching page", () => {
+ const page = globalPageRegistry.getByPageTarget({
+ pageId: "test-page",
+ extensionId: ext.name
+ });
+
+ expect(page.id).toEqual("test-page");
+ });
+
+ it("returns null if target not found", () => {
+ const page = globalPageRegistry.getByPageTarget({
+ pageId: "wrong-page",
+ extensionId: ext.name
+ });
+
+ expect(page).toBeNull();
+ });
+ });
});
diff --git a/src/extensions/registries/page-registry.ts b/src/extensions/registries/page-registry.ts
index 5e1ab3e811..aa0b4fbde9 100644
--- a/src/extensions/registries/page-registry.ts
+++ b/src/extensions/registries/page-registry.ts
@@ -37,12 +37,13 @@ export interface RegisteredPage extends PageRegistration {
url: string; // registered extension's page URL (without page params)
}
-export function getExtensionPageUrl
(target: PageTarget): string {
+export function getExtensionPageUrl(target: PageTarget): string {
const { extensionId, pageId = "", params: targetParams = {} } = target;
let stringifiedParams = "";
// stringify params to matched target page
const page = globalPageRegistry.getByPageTarget(target) || clusterPageRegistry.getByPageTarget(target);
+
if (page?.params) {
const searchParams = page.params.map(urlParam => {
return urlParam.toSearchString({
@@ -51,6 +52,7 @@ export function getExtensionPageUrl
(target: PageTarget): strin
withPrefix: false,
});
});
+
if (searchParams.length > 0) {
stringifiedParams = `?${searchParams.join("&")}`;
}
@@ -64,6 +66,7 @@ export class PageRegistry extends BaseRegistry {
add(pages: PageRegistration | PageRegistration[], extension: LensExtension) {
try {
const items = [pages].flat().map(page => this.registerPage(page, extension));
+
return super.add(items);
} catch (error) {
return Function; // no-op
@@ -74,6 +77,7 @@ export class PageRegistry extends BaseRegistry {
try {
const { id: pageId } = page;
const extensionId = ext.name;
+
return {
...page,
extensionId,
@@ -85,7 +89,7 @@ export class PageRegistry extends BaseRegistry {
}
getByPageTarget(target: PageTarget): RegisteredPage | null {
- return this.getItems().find(page => page.extensionId === target.extensionId && page.id === target.pageId);
+ return this.getItems().find(page => page.extensionId === target.extensionId && page.id === target.pageId) || null;
}
}
diff --git a/src/renderer/components/+custom-resources/crd-list.tsx b/src/renderer/components/+custom-resources/crd-list.tsx
index ce94b14478..6fcd74c848 100644
--- a/src/renderer/components/+custom-resources/crd-list.tsx
+++ b/src/renderer/components/+custom-resources/crd-list.tsx
@@ -36,6 +36,7 @@ export class CrdList extends React.Component {
onSelectGroup(group: string) {
const groups = new Set(this.groups);
+
if (groups.has(group)) {
groups.delete(group); // toggle selection
} else {
diff --git a/src/renderer/components/cluster-manager/clusters-menu.tsx b/src/renderer/components/cluster-manager/clusters-menu.tsx
index decea328de..4930a975d6 100644
--- a/src/renderer/components/cluster-manager/clusters-menu.tsx
+++ b/src/renderer/components/cluster-manager/clusters-menu.tsx
@@ -159,11 +159,13 @@ export class ClustersMenu extends React.Component {
{globalPageMenuRegistry.getItems().map(({ title, target, components: { Icon } }) => {
const registeredPage = globalPageRegistry.getByPageTarget(target);
+
if (!registeredPage){
return;
}
const pageUrl = getExtensionPageUrl(target);
const isActive = isActiveRoute(registeredPage.url);
+
return (
{
getTabLayoutRoutes(menu: ClusterPageMenuRegistration): TabLayoutRoute[] {
const routes: TabLayoutRoute[] = [];
+
if (!menu.id) {
return routes;
}
clusterPageMenuRegistry.getSubItems(menu).forEach((subMenu) => {
const subPage = clusterPageRegistry.getByPageTarget(subMenu.target);
+
if (subPage) {
const { extensionId, id: pageId } = subPage;
+
routes.push({
routePath: subPage.url,
url: getExtensionPageUrl({ extensionId, pageId, params: subMenu.target.params }),
@@ -103,6 +106,7 @@ export class Sidebar extends React.Component {
renderRegisteredMenus() {
return clusterPageMenuRegistry.getRootItems().map((menuItem) => {
const registeredPage = clusterPageRegistry.getByPageTarget(menuItem.target);
+
if (!registeredPage) {
return;
}
diff --git a/src/renderer/navigation/helpers.ts b/src/renderer/navigation/helpers.ts
index c2ffe848b8..71b7735589 100644
--- a/src/renderer/navigation/helpers.ts
+++ b/src/renderer/navigation/helpers.ts
@@ -7,7 +7,9 @@ import { navigation } from "./index";
export function navigate(location: LocationDescriptor) {
const currentLocation = navigation.getPath();
+
navigation.push(location);
+
if (currentLocation === navigation.getPath()) {
navigation.goBack(); // prevent sequences of same url in history
}
@@ -26,5 +28,6 @@ export function getMatchedClusterId(): string {
exact: true,
path: clusterViewRoute.path
});
+
return matched?.params.clusterId;
}
diff --git a/src/renderer/navigation/url-param.ts b/src/renderer/navigation/url-param.ts
index d138c46266..a601d25ddc 100644
--- a/src/renderer/navigation/url-param.ts
+++ b/src/renderer/navigation/url-param.ts
@@ -34,21 +34,27 @@ export class UrlParam {
parse(values: string[]): V {
const { parse, multiValues } = this.init;
+
if (!multiValues) values.splice(1); // reduce values to single item
const parsedValues = [parse ? parse(values) : values].flat();
+
return multiValues ? parsedValues : parsedValues[0] as any;
}
stringify(value: V = this.get()): string {
const { stringify, multiValues, multiValueSep, skipEmpty } = this.init;
+
if (skipEmpty && this.isEmpty(value)) {
return "";
}
+
if (multiValues) {
const values = [value].flat();
const stringValues = [stringify ? stringify(value) : values.map(String)].flat();
+
return stringValues.join(multiValueSep);
}
+
return [stringify ? stringify(value) : String(value)].flat()[0];
}
@@ -60,11 +66,13 @@ export class UrlParam {
if (skipEmpty && this.isEmpty(value)) {
return defaultValue;
}
+
return value;
}
set(value: V, { mergeGlobals = true, replaceHistory = false } = {}) {
const search = this.toSearchString({ mergeGlobals, value });
+
this.history.merge({ search }, replaceHistory);
}
@@ -89,11 +97,13 @@ export class UrlParam {
if (skipEmpty) {
searchParams.forEach((value: any, paramName) => {
if (this.isEmpty(value)) searchParams.delete(paramName);
- })
+ });
}
+
if (Array.from(searchParams).length > 0) {
return `${withPrefix ? "?" : ""}${searchParams}`;
}
+
return "";
}