From 0fd981866b48b8c7e89057d06b92c50574f90420 Mon Sep 17 00:00:00 2001 From: Roman Date: Mon, 7 Dec 2020 13:54:08 +0200 Subject: [PATCH] fix: merge page url chunks with native URL()-api, simplified default page-params registration Signed-off-by: Roman --- extensions/example-extension/page.tsx | 8 ++-- extensions/example-extension/renderer.tsx | 14 +++--- .../registries/page-menu-registry.ts | 14 +++--- src/extensions/registries/page-registry.ts | 48 ++++++++++--------- 4 files changed, 44 insertions(+), 40 deletions(-) diff --git a/extensions/example-extension/page.tsx b/extensions/example-extension/page.tsx index a5dfc81e59..a74482e990 100644 --- a/extensions/example-extension/page.tsx +++ b/extensions/example-extension/page.tsx @@ -1,10 +1,10 @@ import { Component, LensRendererExtension, Navigation } from "@k8slens/extensions"; -import { CoffeeDoodle } from "react-open-doodles"; import React from "react"; import path from "path"; import { observer } from "mobx-react"; +import { CoffeeDoodle } from "react-open-doodles"; -export const exampleIdPageParam = Navigation.createUrlParam({ +export const exampleId = Navigation.createUrlParam({ name: "exampleId", defaultValue: "demo", }); @@ -22,7 +22,7 @@ export class ExamplePage extends React.Component<{ extension: LensRendererExtens }; render() { - const exampleName = exampleIdPageParam.get(); + const exampleName = exampleId.get(); const doodleStyle = { width: "200px" }; @@ -36,7 +36,7 @@ export class ExamplePage extends React.Component<{ extension: LensRendererExtens

Location: {location.href}

- exampleIdPageParam.set("secret")}>Show secret button + exampleId.set("secret")}>Show secret button {exampleName === "secret" && ( )} diff --git a/extensions/example-extension/renderer.tsx b/extensions/example-extension/renderer.tsx index 5b00993dd6..78fb369f6f 100644 --- a/extensions/example-extension/renderer.tsx +++ b/extensions/example-extension/renderer.tsx @@ -1,5 +1,5 @@ import { LensRendererExtension } from "@k8slens/extensions"; -import { ExampleIcon, ExamplePage, exampleIdPageParam } from "./page"; +import { ExampleIcon, ExamplePage } from "./page"; import React from "react"; export default class ExampleExtension extends LensRendererExtension { @@ -10,9 +10,11 @@ export default class ExampleExtension extends LensRendererExtension { components: { Page: () => , }, - params: [ - exampleIdPageParam, - ] + params: { + // setup param "exampleId" with default value "demo" + // could be also {[paramName: string]: UrlParam} for advanced use-cases (custom parse/stringify) + exampleId: "demo" + } } ]; @@ -25,9 +27,7 @@ export default class ExampleExtension extends LensRendererExtension { target: { pageId: "example", params: { - // cause target page has registered a url-param with name "exampleId" == exampleNameUrlParam.name - // passing values to page to generate final link - exampleId: "demo-2" + exampleId: "demo-sample-2" }, }, }, diff --git a/src/extensions/registries/page-menu-registry.ts b/src/extensions/registries/page-menu-registry.ts index 67760111a7..17ff094670 100644 --- a/src/extensions/registries/page-menu-registry.ts +++ b/src/extensions/registries/page-menu-registry.ts @@ -43,15 +43,17 @@ export class ClusterPageMenuRegistry extends PageMenuRegistry { - return item.parentId === parent.id && item.target.extensionId === parent.target.extensionId; - }); + return this.getItems().filter((item) => ( + item.parentId === parent.id && + item.target.extensionId === parent.target.extensionId + )); } getByPage({ id: pageId, extensionId }: RegisteredPage) { - return this.getItems().find((item) => { - return item.target.pageId == pageId && item.target.extensionId === extensionId; - }); + return this.getItems().find((item) => ( + item.target.pageId == pageId && + item.target.extensionId === extensionId + )); } } diff --git a/src/extensions/registries/page-registry.ts b/src/extensions/registries/page-registry.ts index aa0b4fbde9..404325f983 100644 --- a/src/extensions/registries/page-registry.ts +++ b/src/extensions/registries/page-registry.ts @@ -1,11 +1,9 @@ // Extensions-api -> Custom page registration import type React from "react"; -import type { UrlParam } from "../../renderer/navigation/url-param"; - -import path from "path"; import { action } from "mobx"; import { BaseRegistry } from "./base-registry"; import { LensExtension, sanitizeExtensionName } from "../lens-extension"; +import { UrlParam } from "../../renderer/navigation/url-param"; import logger from "../../main/logger"; export interface PageRegistration { @@ -17,19 +15,24 @@ export interface PageRegistration { components: PageComponents; /** * Registered page params. - * Used to generate page url when provided in getExtensionPageUrl()-helper. + * Used to generate final page url when provided in getExtensionPageUrl()-helper. + * Advanced usage: provide `UrlParam` as values to customize parsing/stringification from/to URL. */ - params?: UrlParam[]; + params?: PageTargetParams; } export interface PageComponents { Page: React.ComponentType; } -export interface PageTarget

{ +export interface PageTarget

{ extensionId?: string; pageId?: string; - params?: Record & P; // default target page params + params?: P; +} + +export interface PageTargetParams { + [paramName: string]: V; } export interface RegisteredPage extends PageRegistration { @@ -38,27 +41,26 @@ export interface RegisteredPage extends PageRegistration { } export function getExtensionPageUrl(target: PageTarget): string { - const { extensionId, pageId = "", params: targetParams = {} } = target; - let stringifiedParams = ""; + const { extensionId, pageId = "", params: targetPageParams = {} } = target; + + const pagePath = ["/extension", sanitizeExtensionName(extensionId), pageId].join("/"); + const pageUrl = new URL(pagePath, `http://localhost`); // stringify params to matched target page - const page = globalPageRegistry.getByPageTarget(target) || clusterPageRegistry.getByPageTarget(target); + const targetPage = globalPageRegistry.getByPageTarget(target) || clusterPageRegistry.getByPageTarget(target); - if (page?.params) { - const searchParams = page.params.map(urlParam => { - return urlParam.toSearchString({ - value: targetParams[urlParam.name] ?? urlParam.getDefaultValue(), - mergeGlobals: false, - withPrefix: false, - }); - }); - - if (searchParams.length > 0) { - stringifiedParams = `?${searchParams.join("&")}`; - } + if (targetPage?.params) { + Object.entries(targetPage.params).forEach(([name, param]) => { + const paramValue = targetPageParams[name]; + if (param instanceof UrlParam) { + pageUrl.searchParams.set(name, param.stringify(paramValue)); + } else { + pageUrl.searchParams.set(name, String(paramValue ?? param)); + } + }) } - return path.posix.join("/extension", sanitizeExtensionName(extensionId), pageId, stringifiedParams); + return pageUrl.href.replace(pageUrl.origin, ""); } export class PageRegistry extends BaseRegistry {