mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
example-extension reworks -- part 2
Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
parent
f5cea39c64
commit
89bc526e4d
@ -1,4 +1,4 @@
|
||||
import { Icon, LensExtension } from "@lens/extensions"; // fixme: map to generated types from "extension-api.d.ts"
|
||||
import { DynamicPageType, Icon, LensExtension } from "@lens/extensions"; // fixme: map to generated types from "extension-api.d.ts"
|
||||
import React from "react";
|
||||
import path from "path";
|
||||
|
||||
@ -8,10 +8,11 @@ export default class ExampleExtension extends LensExtension {
|
||||
onActivate() {
|
||||
console.log('EXAMPLE EXTENSION: ACTIVATE', this.getMeta())
|
||||
this.unRegisterPage = this.runtime.dynamicPages.register({
|
||||
type: "cluster-view",
|
||||
type: DynamicPageType.CLUSTER,
|
||||
path: "/extension-example",
|
||||
menuTitle: "Example Extension",
|
||||
components: {
|
||||
Main: ExtensionPage,
|
||||
Page: ExtensionPage,
|
||||
MenuIcon: ExtensionIcon,
|
||||
}
|
||||
})
|
||||
@ -27,7 +28,7 @@ export function ExtensionIcon(props: {} /*IconProps |*/) {
|
||||
return <Icon {...props} material="camera" tooltip={path.basename(__filename)}/>
|
||||
}
|
||||
|
||||
// todo: provide extension instance and runtime params (via context or props)
|
||||
// todo: provide extension-instance and lens-runtime (context/props/extension-js-scope)
|
||||
export class ExtensionPage extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
|
||||
@ -3,6 +3,7 @@ export type { LensRuntimeRendererEnv } from "./lens-runtime";
|
||||
|
||||
// APIs
|
||||
export * from "./extension"
|
||||
export { DynamicPageType } from "./register-page";
|
||||
|
||||
// Common UI components
|
||||
export * from "../renderer/components/icon"
|
||||
|
||||
@ -1,18 +1,14 @@
|
||||
// Lens runtime for injecting to extension on activation
|
||||
import { apiManager } from "../renderer/api/api-manager";
|
||||
// Lens renderer runtime params available to the extension after activation
|
||||
import logger from "../main/logger";
|
||||
import { dynamicPages } from "../renderer/components/cluster-manager/register-page";
|
||||
import { dynamicPages } from "./register-page";
|
||||
|
||||
export interface LensRuntimeRendererEnv {
|
||||
apiManager: typeof apiManager;
|
||||
logger: typeof logger;
|
||||
dynamicPages: typeof dynamicPages
|
||||
}
|
||||
|
||||
// todo: expose more public runtime apis: stores, managers, etc.
|
||||
export function getLensRuntime(): LensRuntimeRendererEnv {
|
||||
return {
|
||||
apiManager,
|
||||
logger,
|
||||
dynamicPages,
|
||||
}
|
||||
|
||||
@ -1,12 +1,18 @@
|
||||
// Dynamic pages
|
||||
// Extensions-api -> Dynamic pages
|
||||
|
||||
import React from "react";
|
||||
import { computed, observable } from "mobx";
|
||||
import type { IconProps } from "../icon";
|
||||
import React from "react";
|
||||
import type { IconProps } from "../renderer/components/icon";
|
||||
|
||||
export enum DynamicPageType {
|
||||
GLOBAL = "lens-scope",
|
||||
CLUSTER = "cluster-view-scope",
|
||||
}
|
||||
|
||||
export interface PageRegistration {
|
||||
path: string;
|
||||
type: "global" | "cluster-view";
|
||||
path: string; // route-path
|
||||
menuTitle: string;
|
||||
type: DynamicPageType;
|
||||
components: PageComponents;
|
||||
}
|
||||
|
||||
@ -19,13 +25,14 @@ export class PagesStore {
|
||||
protected pages = observable.array<PageRegistration>([], { deep: false });
|
||||
|
||||
@computed get globalPages() {
|
||||
return this.pages.filter(page => page.type === "global");
|
||||
return this.pages.filter(page => page.type === DynamicPageType.GLOBAL);
|
||||
}
|
||||
|
||||
@computed get clusterPages() {
|
||||
return this.pages.filter(page => page.type === "cluster-view");
|
||||
return this.pages.filter(page => page.type === DynamicPageType.CLUSTER);
|
||||
}
|
||||
|
||||
// todo: verify paths to avoid collision with existing pages
|
||||
register(params: PageRegistration) {
|
||||
this.pages.push(params);
|
||||
return () => {
|
||||
@ -10,6 +10,7 @@ import { i18nStore } from "./i18n";
|
||||
import { themeStore } from "./theme.store";
|
||||
import { App } from "./components/app";
|
||||
import { LensApp } from "./lens-app";
|
||||
import { getLensRuntime } from "../extensions/lens-runtime";
|
||||
|
||||
type AppComponent = React.ComponentType & {
|
||||
init?(): void;
|
||||
@ -32,6 +33,7 @@ export async function bootstrap(App: AppComponent) {
|
||||
// init app's dependencies if any
|
||||
if (App.init) {
|
||||
await App.init();
|
||||
extensionStore.autoEnableOnLoad(getLensRuntime);
|
||||
}
|
||||
render(<App/>, rootElem);
|
||||
}
|
||||
|
||||
@ -35,6 +35,7 @@ import { getHostedCluster, getHostedClusterId } from "../../common/cluster-store
|
||||
import logger from "../../main/logger";
|
||||
import { clusterIpc } from "../../common/cluster-ipc";
|
||||
import { webFrame } from "electron";
|
||||
import { dynamicPages } from "../../extensions/register-page";
|
||||
|
||||
@observer
|
||||
export class App extends React.Component {
|
||||
@ -71,6 +72,9 @@ export class App extends React.Component {
|
||||
<Route component={CustomResources} {...crdRoute}/>
|
||||
<Route component={UserManagement} {...usersManagementRoute}/>
|
||||
<Route component={Apps} {...appsRoute}/>
|
||||
{dynamicPages.clusterPages.map(({ path, components: { Page } }) => {
|
||||
return <Route key={path} path={path} component={Page}/>
|
||||
})}
|
||||
<Redirect exact from="/" to={this.startURL}/>
|
||||
<Route component={NotFound}/>
|
||||
</Switch>
|
||||
|
||||
@ -15,7 +15,7 @@ import { Extensions, extensionsRoute } from "../+extensions";
|
||||
import { clusterViewRoute, clusterViewURL, getMatchedCluster, getMatchedClusterId } from "./cluster-view.route";
|
||||
import { clusterStore } from "../../../common/cluster-store";
|
||||
import { hasLoadedView, initView, lensViews, refreshViews } from "./lens-views";
|
||||
import { dynamicPages } from "./register-page";
|
||||
import { dynamicPages } from "../../../extensions/register-page";
|
||||
|
||||
@observer
|
||||
export class ClusterManager extends React.Component {
|
||||
|
||||
@ -21,7 +21,7 @@ import { ConfirmDialog } from "../confirm-dialog";
|
||||
import { clusterIpc } from "../../../common/cluster-ipc";
|
||||
import { clusterViewURL, getMatchedClusterId } from "./cluster-view.route";
|
||||
import { DragDropContext, Draggable, DraggableProvided, Droppable, DroppableProvided, DropResult } from "react-beautiful-dnd";
|
||||
import { dynamicPages } from "./register-page";
|
||||
import { dynamicPages } from "../../../extensions/register-page";
|
||||
|
||||
interface Props {
|
||||
className?: IClassName;
|
||||
@ -150,9 +150,7 @@ export class ClustersMenu extends React.Component<Props> {
|
||||
</div>
|
||||
<div className="dynamic-pages">
|
||||
{dynamicPages.globalPages.map(({ path, components: { MenuIcon } }) => {
|
||||
if (MenuIcon) {
|
||||
return <MenuIcon key={path} onClick={() => navigate(path)}/>
|
||||
}
|
||||
return <MenuIcon key={path} onClick={() => navigate(path)}/>
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -28,6 +28,7 @@ import { CrdList, crdResourcesRoute, crdRoute, crdURL } from "../+custom-resourc
|
||||
import { CustomResources } from "../+custom-resources/custom-resources";
|
||||
import { navigation } from "../../navigation";
|
||||
import { isAllowedResource } from "../../../common/rbac"
|
||||
import { dynamicPages } from "../../../extensions/register-page";
|
||||
|
||||
const SidebarContext = React.createContext<SidebarContextValue>({ pinned: false });
|
||||
type SidebarContextValue = {
|
||||
@ -183,6 +184,18 @@ export class Sidebar extends React.Component<Props> {
|
||||
>
|
||||
{this.renderCustomResources()}
|
||||
</SidebarNavItem>
|
||||
{dynamicPages.clusterPages.map(({ path, menuTitle, components: { MenuIcon } }) => {
|
||||
return (
|
||||
<SidebarNavItem
|
||||
key={path}
|
||||
id={`extension-${path}`}
|
||||
url={path}
|
||||
routePath={path}
|
||||
text={menuTitle}
|
||||
icon={<MenuIcon/>}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</SidebarContext.Provider>
|
||||
|
||||
@ -11,15 +11,9 @@ import { ErrorBoundary } from "./components/error-boundary";
|
||||
import { WhatsNew, whatsNewRoute } from "./components/+whats-new";
|
||||
import { Notifications } from "./components/notifications";
|
||||
import { ConfirmDialog } from "./components/confirm-dialog";
|
||||
import { extensionStore } from "../extensions/extension-store";
|
||||
import { getLensRuntime } from "../extensions/lens-runtime";
|
||||
|
||||
@observer
|
||||
export class LensApp extends React.Component {
|
||||
componentDidMount() {
|
||||
extensionStore.autoEnableOnLoad(getLensRuntime);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<I18nProvider i18n={_i18n}>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user