1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

fix: merge page url chunks with native URL()-api, simplified default page-params registration

Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
Roman 2020-12-07 13:54:08 +02:00
parent fcb18b6dd1
commit 0fd981866b
4 changed files with 44 additions and 40 deletions

View File

@ -1,10 +1,10 @@
import { Component, LensRendererExtension, Navigation } from "@k8slens/extensions"; import { Component, LensRendererExtension, Navigation } from "@k8slens/extensions";
import { CoffeeDoodle } from "react-open-doodles";
import React from "react"; import React from "react";
import path from "path"; import path from "path";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { CoffeeDoodle } from "react-open-doodles";
export const exampleIdPageParam = Navigation.createUrlParam<string>({ export const exampleId = Navigation.createUrlParam<string>({
name: "exampleId", name: "exampleId",
defaultValue: "demo", defaultValue: "demo",
}); });
@ -22,7 +22,7 @@ export class ExamplePage extends React.Component<{ extension: LensRendererExtens
}; };
render() { render() {
const exampleName = exampleIdPageParam.get(); const exampleName = exampleId.get();
const doodleStyle = { const doodleStyle = {
width: "200px" width: "200px"
}; };
@ -36,7 +36,7 @@ export class ExamplePage extends React.Component<{ extension: LensRendererExtens
<p>Location: <i>{location.href}</i></p> <p>Location: <i>{location.href}</i></p>
<p className="url-params-demo flex column gaps"> <p className="url-params-demo flex column gaps">
<a onClick={() => exampleIdPageParam.set("secret")}>Show secret button</a> <a onClick={() => exampleId.set("secret")}>Show secret button</a>
{exampleName === "secret" && ( {exampleName === "secret" && (
<Component.Button accent label="Deactivate" onClick={this.deactivate}/> <Component.Button accent label="Deactivate" onClick={this.deactivate}/>
)} )}

View File

@ -1,5 +1,5 @@
import { LensRendererExtension } from "@k8slens/extensions"; import { LensRendererExtension } from "@k8slens/extensions";
import { ExampleIcon, ExamplePage, exampleIdPageParam } from "./page"; import { ExampleIcon, ExamplePage } from "./page";
import React from "react"; import React from "react";
export default class ExampleExtension extends LensRendererExtension { export default class ExampleExtension extends LensRendererExtension {
@ -10,9 +10,11 @@ export default class ExampleExtension extends LensRendererExtension {
components: { components: {
Page: () => <ExamplePage extension={this}/>, Page: () => <ExamplePage extension={this}/>,
}, },
params: [ params: {
exampleIdPageParam, // 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: { target: {
pageId: "example", pageId: "example",
params: { params: {
// cause target page has registered a url-param with name "exampleId" == exampleNameUrlParam.name exampleId: "demo-sample-2"
// passing values to page to generate final link
exampleId: "demo-2"
}, },
}, },
}, },

View File

@ -43,15 +43,17 @@ export class ClusterPageMenuRegistry extends PageMenuRegistry<ClusterPageMenuReg
} }
getSubItems(parent: ClusterPageMenuRegistration) { getSubItems(parent: ClusterPageMenuRegistration) {
return this.getItems().filter((item) => { return this.getItems().filter((item) => (
return item.parentId === parent.id && item.target.extensionId === parent.target.extensionId; item.parentId === parent.id &&
}); item.target.extensionId === parent.target.extensionId
));
} }
getByPage({ id: pageId, extensionId }: RegisteredPage) { getByPage({ id: pageId, extensionId }: RegisteredPage) {
return this.getItems().find((item) => { return this.getItems().find((item) => (
return item.target.pageId == pageId && item.target.extensionId === extensionId; item.target.pageId == pageId &&
}); item.target.extensionId === extensionId
));
} }
} }

View File

@ -1,11 +1,9 @@
// Extensions-api -> Custom page registration // Extensions-api -> Custom page registration
import type React from "react"; import type React from "react";
import type { UrlParam } from "../../renderer/navigation/url-param";
import path from "path";
import { action } from "mobx"; import { action } from "mobx";
import { BaseRegistry } from "./base-registry"; import { BaseRegistry } from "./base-registry";
import { LensExtension, sanitizeExtensionName } from "../lens-extension"; import { LensExtension, sanitizeExtensionName } from "../lens-extension";
import { UrlParam } from "../../renderer/navigation/url-param";
import logger from "../../main/logger"; import logger from "../../main/logger";
export interface PageRegistration { export interface PageRegistration {
@ -17,19 +15,24 @@ export interface PageRegistration {
components: PageComponents; components: PageComponents;
/** /**
* Registered page params. * 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<string | UrlParam>;
} }
export interface PageComponents { export interface PageComponents {
Page: React.ComponentType<any>; Page: React.ComponentType<any>;
} }
export interface PageTarget<P = {}> { export interface PageTarget<P = PageTargetParams> {
extensionId?: string; extensionId?: string;
pageId?: string; pageId?: string;
params?: Record<string, any | any[]> & P; // default target page params params?: P;
}
export interface PageTargetParams<V = any> {
[paramName: string]: V;
} }
export interface RegisteredPage extends PageRegistration { export interface RegisteredPage extends PageRegistration {
@ -38,27 +41,26 @@ export interface RegisteredPage extends PageRegistration {
} }
export function getExtensionPageUrl(target: PageTarget): string { export function getExtensionPageUrl(target: PageTarget): string {
const { extensionId, pageId = "", params: targetParams = {} } = target; const { extensionId, pageId = "", params: targetPageParams = {} } = target;
let stringifiedParams = "";
const pagePath = ["/extension", sanitizeExtensionName(extensionId), pageId].join("/");
const pageUrl = new URL(pagePath, `http://localhost`);
// stringify params to matched target page // 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) { if (targetPage?.params) {
const searchParams = page.params.map(urlParam => { Object.entries(targetPage.params).forEach(([name, param]) => {
return urlParam.toSearchString({ const paramValue = targetPageParams[name];
value: targetParams[urlParam.name] ?? urlParam.getDefaultValue(), if (param instanceof UrlParam) {
mergeGlobals: false, pageUrl.searchParams.set(name, param.stringify(paramValue));
withPrefix: false, } else {
}); pageUrl.searchParams.set(name, String(paramValue ?? param));
}); }
})
if (searchParams.length > 0) {
stringifiedParams = `?${searchParams.join("&")}`;
}
} }
return path.posix.join("/extension", sanitizeExtensionName(extensionId), pageId, stringifiedParams); return pageUrl.href.replace(pageUrl.origin, "");
} }
export class PageRegistry extends BaseRegistry<RegisteredPage> { export class PageRegistry extends BaseRegistry<RegisteredPage> {