mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
support-page extension -- part 2
Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
1 parent
822d9b4974
commit
ef66f67b39
38 files changed
+281
-168
No files matched your search
@@ -21,11 +21,6 @@ export const rendererDir = path.join(contextDir, "src/renderer");
|
||||
export const htmlTemplate = path.resolve(rendererDir, "template.html");
|
||||
export const sassCommonVars = path.resolve(rendererDir, "components/vars.scss");
|
||||
|
||||
// Extensions
|
||||
export const extensionsLibName = `${appName}-extensions.api`
|
||||
export const extensionsRendererLibName = `${appName}-extensions-renderer.api`
|
||||
export const extensionsDir = path.join(contextDir, "src/extensions");
|
||||
|
||||
// Special runtime paths
|
||||
defineGlobal("__static", {
|
||||
get() {
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
// Lens-extensions api developer's kit
|
||||
export type { LensExtensionRuntimeEnv } from "./lens-runtime";
|
||||
|
||||
export type { LensExtensionMainRuntimeEnv } from "./lens-runtime";
|
||||
export * from "./lens-main-extension"
|
||||
|
||||
// APIs
|
||||
import * as EventBus from "./main-api/event-bus"
|
||||
import * as Store from "./main-api/stores"
|
||||
import * as Util from "./main-api/utils"
|
||||
import * as Registry from "./main-api/registries"
|
||||
|
||||
export {
|
||||
EventBus,
|
||||
Store,
|
||||
Util
|
||||
Util,
|
||||
Registry,
|
||||
}
|
||||
@@ -1,13 +1,17 @@
|
||||
import type { ExtensionId, LensExtension, ExtensionManifest, ExtensionModel } from "./lens-extension"
|
||||
import type { LensMainExtension } from "./lens-main-extension"
|
||||
import type { LensRendererExtension } from "./lens-renderer-extension"
|
||||
import { broadcastIpc } from "../common/ipc"
|
||||
import type { LensExtensionRuntimeEnv } from "./lens-runtime"
|
||||
import type { LensExtensionMainRuntimeEnv } from "./lens-runtime"
|
||||
import type { LensExtensionRendererRuntimeEnv } from "./lens-renderer-runtime"
|
||||
import path from "path"
|
||||
import { broadcastIpc } from "../common/ipc"
|
||||
import { observable, reaction, toJS, } from "mobx"
|
||||
import logger from "../main/logger"
|
||||
import { app, remote, ipcRenderer } from "electron"
|
||||
import { pageRegistry } from "./page-registry";
|
||||
import { appPreferenceRegistry } from "./app-preference-registry"
|
||||
import { menuRegistry } from "./menu-registry";
|
||||
import { statusBarRegistry } from "./status-bar-registry";
|
||||
|
||||
export interface InstalledExtension extends ExtensionModel {
|
||||
manifestPath: string;
|
||||
@@ -35,14 +39,14 @@ export class ExtensionLoader {
|
||||
}
|
||||
}
|
||||
|
||||
loadOnClusterRenderer(getLensRuntimeEnv: () => LensExtensionRuntimeEnv) {
|
||||
loadOnClusterRenderer(getLensRuntimeEnv: () => LensExtensionRendererRuntimeEnv) {
|
||||
logger.info('[EXTENSIONS-LOADER]: load on cluster renderer')
|
||||
this.autoloadExtensions(getLensRuntimeEnv, (instance: LensRendererExtension) => {
|
||||
instance.registerPages(pageRegistry)
|
||||
})
|
||||
}
|
||||
|
||||
loadOnMainRenderer(getLensRuntimeEnv: () => LensExtensionRuntimeEnv) {
|
||||
loadOnMainRenderer(getLensRuntimeEnv: () => LensExtensionRendererRuntimeEnv) {
|
||||
logger.info('[EXTENSIONS-LOADER]: load on main renderer')
|
||||
this.autoloadExtensions(getLensRuntimeEnv, (instance: LensRendererExtension) => {
|
||||
instance.registerPages(pageRegistry)
|
||||
@@ -50,14 +54,15 @@ export class ExtensionLoader {
|
||||
})
|
||||
}
|
||||
|
||||
loadOnMain(getLensRuntimeEnv: () => LensExtensionRuntimeEnv) {
|
||||
loadOnMain(getLensRuntimeEnv: () => LensExtensionMainRuntimeEnv) {
|
||||
logger.info('[EXTENSIONS-LOADER]: load on main')
|
||||
this.autoloadExtensions(getLensRuntimeEnv, (instance: LensExtension) => {
|
||||
// todo
|
||||
this.autoloadExtensions(getLensRuntimeEnv, (instance: LensMainExtension) => {
|
||||
instance.registerAppMenus(menuRegistry);
|
||||
instance.registerStatusBarIcon(statusBarRegistry);
|
||||
})
|
||||
}
|
||||
|
||||
protected autoloadExtensions(getLensRuntimeEnv: () => LensExtensionRuntimeEnv, callback: (instance: LensExtension) => void) {
|
||||
protected autoloadExtensions(getLensRuntimeEnv: () => object, callback: (instance: LensExtension) => void) {
|
||||
return reaction(() => this.extensions.toJS(), (installedExtensions) => {
|
||||
for(const [id, ext] of installedExtensions) {
|
||||
let instance = this.instances.get(ext.manifestPath)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Lens-extensions api developer's kit
|
||||
export type { LensExtensionRuntimeEnv } from "./lens-renderer-runtime"
|
||||
export type { LensExtensionRendererRuntimeEnv } from "./lens-renderer-runtime"
|
||||
|
||||
// APIs
|
||||
export * from "./lens-extension"
|
||||
@@ -10,11 +10,13 @@ import * as EventBus from "./main-api/event-bus"
|
||||
import * as K8sApi from "./renderer-api/k8s-api"
|
||||
import * as Registry from "./renderer-api/registries"
|
||||
import * as Util from "./main-api/utils"
|
||||
import * as CommonVars from "../common/vars";
|
||||
|
||||
export {
|
||||
Component,
|
||||
EventBus,
|
||||
K8sApi,
|
||||
Registry,
|
||||
Util
|
||||
Util,
|
||||
CommonVars,
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
import type { LensExtensionRuntimeEnv } from "./lens-runtime";
|
||||
import { readJsonSync } from "fs-extra";
|
||||
import { action, observable, toJS } from "mobx";
|
||||
import logger from "../main/logger";
|
||||
@@ -34,7 +33,7 @@ export class LensExtension implements ExtensionModel {
|
||||
@observable manifest: ExtensionManifest;
|
||||
@observable manifestPath: string;
|
||||
@observable isEnabled = false;
|
||||
@observable.ref runtime: LensExtensionRuntimeEnv;
|
||||
@observable.ref runtime: any;
|
||||
|
||||
constructor(model: ExtensionModel, manifest: ExtensionManifest) {
|
||||
this.importModel(model, manifest);
|
||||
@@ -56,7 +55,7 @@ export class LensExtension implements ExtensionModel {
|
||||
// mock
|
||||
}
|
||||
|
||||
async enable(runtime: LensExtensionRuntimeEnv) {
|
||||
async enable(runtime: any) {
|
||||
this.isEnabled = true;
|
||||
this.runtime = runtime;
|
||||
logger.info(`[EXTENSION]: enabled ${this.name}@${this.version}`);
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
import { LensExtension } from "./lens-extension"
|
||||
import type { MenuRegistry } from "./menu-registry";
|
||||
import type { StatusBarRegistry } from "./status-bar-registry";
|
||||
|
||||
export class LensMainExtension extends LensExtension {
|
||||
async registerAppMenus() {
|
||||
registerAppMenus(registry: MenuRegistry) {
|
||||
//
|
||||
}
|
||||
|
||||
async registerPrometheusProviders(registry: any) {
|
||||
registerStatusBarIcon(registry: StatusBarRegistry) {
|
||||
//
|
||||
}
|
||||
|
||||
registerPrometheusProviders(registry: any) {
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,12 @@
|
||||
import logger from "../main/logger";
|
||||
import { navigate } from "../renderer/navigation";
|
||||
|
||||
export interface LensExtensionRuntimeEnv {
|
||||
export interface LensExtensionRendererRuntimeEnv {
|
||||
logger: typeof logger;
|
||||
navigate: typeof navigate;
|
||||
}
|
||||
|
||||
export function getLensRuntime(): LensExtensionRuntimeEnv {
|
||||
export function getLensRuntimeRenderer(): LensExtensionRendererRuntimeEnv {
|
||||
return {
|
||||
logger,
|
||||
navigate
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
import logger from "../main/logger";
|
||||
|
||||
export interface LensExtensionRuntimeEnv {
|
||||
export interface LensExtensionMainRuntimeEnv {
|
||||
logger: typeof logger;
|
||||
}
|
||||
|
||||
export function getLensRuntime(): LensExtensionRuntimeEnv {
|
||||
export function getLensRuntime(): LensExtensionMainRuntimeEnv {
|
||||
return {
|
||||
logger
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export { MenuRegistry, MenuRegistration } from "../menu-registry";
|
||||
@@ -0,0 +1,16 @@
|
||||
// Extensions API -> Global menu customize
|
||||
|
||||
import { observable } from "mobx";
|
||||
|
||||
export interface MenuRegistration {
|
||||
data?: any;
|
||||
}
|
||||
|
||||
export class MenuRegistry {
|
||||
items = observable<MenuRegistration>([], { deep: false });
|
||||
|
||||
add(item: MenuRegistration) {
|
||||
}
|
||||
}
|
||||
|
||||
export const menuRegistry = new MenuRegistry();
|
||||
@@ -7,38 +7,37 @@ import { IconProps } from "../renderer/components/icon";
|
||||
import { IClassName } from "../renderer/utils";
|
||||
import { TabRoute } from "../renderer/components/layout/tab-layout";
|
||||
|
||||
export enum DynamicPageType {
|
||||
export enum PageRegistryType {
|
||||
GLOBAL = "lens-scope",
|
||||
CLUSTER = "cluster-view-scope",
|
||||
}
|
||||
|
||||
export interface PageRegistration extends RouteProps {
|
||||
type: PageRegistryType;
|
||||
components: PageComponents;
|
||||
className?: IClassName;
|
||||
url?: string; // initial url to be used for building menus and tabs, otherwise "path" applied by default
|
||||
path: string; // route-path
|
||||
title: React.ReactNode; // used in sidebar's & tabs-layout
|
||||
type: DynamicPageType;
|
||||
components: PageComponents;
|
||||
title?: React.ReactNode; // used in sidebar's & tabs-layout if provided
|
||||
subPages?: (PageRegistration & TabRoute)[];
|
||||
}
|
||||
|
||||
export interface PageComponents {
|
||||
Page: React.ComponentType<any>;
|
||||
MenuIcon: React.ComponentType<IconProps>;
|
||||
MenuIcon?: React.ComponentType<IconProps>;
|
||||
}
|
||||
|
||||
export class PageRegistry {
|
||||
protected pages = observable.array<PageRegistration>([], { deep: false });
|
||||
|
||||
@computed get globalPages() {
|
||||
return this.pages.filter(page => page.type === DynamicPageType.GLOBAL);
|
||||
return this.pages.filter(page => page.type === PageRegistryType.GLOBAL);
|
||||
}
|
||||
|
||||
@computed get clusterPages() {
|
||||
return this.pages.filter(page => page.type === DynamicPageType.CLUSTER);
|
||||
return this.pages.filter(page => page.type === PageRegistryType.CLUSTER);
|
||||
}
|
||||
|
||||
// todo: verify paths to avoid collision with existing pages
|
||||
// fixme: validate route paths to avoid collisions
|
||||
add(params: PageRegistration) {
|
||||
this.pages.push(params);
|
||||
return () => {
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
// TODO: add more common re-usable UI components + refactor interfaces (Props -> ComponentProps)
|
||||
|
||||
export * from "../../renderer/components/icon"
|
||||
export * from "../../renderer/components/checkbox"
|
||||
export * from "../../renderer/components/tooltip"
|
||||
export * from "../../renderer/components/button"
|
||||
export * from "../../renderer/components/tabs"
|
||||
export * from "../../renderer/components/badge"
|
||||
export { KubeObjectMeta } from "../../renderer/components/kube-object/kube-object-meta";
|
||||
export { MenuItem, SubMenu } from "../../renderer/components/menu";
|
||||
export { StatusBrick } from "../../renderer/components/status-brick";
|
||||
export { terminalStore, createTerminalTab } from "../../renderer/components/dock/terminal.store";
|
||||
export { createPodLogsTab } from "../../renderer/components/dock/pod-logs.store";
|
||||
export * from "../../renderer/components/layout/page-layout"
|
||||
@@ -1,2 +1,2 @@
|
||||
export { DynamicPageType, PageRegistry } from "../page-registry"
|
||||
export { AppPreferenceRegistry } from "../app-preference-registry"
|
||||
export { PageRegistryType, PageRegistry, PageRegistration, PageComponents } from "../page-registry"
|
||||
export { AppPreferenceRegistry, AppPreferenceComponents, AppPreferenceRegistration } from "../app-preference-registry"
|
||||
@@ -0,0 +1,15 @@
|
||||
// Extensions API -> Status bar customizations
|
||||
|
||||
import { observable } from "mobx";
|
||||
|
||||
export interface StatusBarRegistration {
|
||||
}
|
||||
|
||||
export class StatusBarRegistry {
|
||||
items = observable<StatusBarRegistration>([], { deep: false });
|
||||
|
||||
add(item: StatusBarRegistration) {
|
||||
}
|
||||
}
|
||||
|
||||
export const statusBarRegistry = new StatusBarRegistry();
|
||||
@@ -1,2 +0,0 @@
|
||||
export * from "./support.route"
|
||||
export * from "./support"
|
||||
@@ -1,8 +0,0 @@
|
||||
import { RouteProps } from "react-router";
|
||||
import { buildURL } from "../../navigation";
|
||||
|
||||
export const supportRoute: RouteProps = {
|
||||
path: "/support"
|
||||
}
|
||||
|
||||
export const supportURL = buildURL(supportRoute.path)
|
||||
@@ -1,3 +0,0 @@
|
||||
// TODO: figure out how to consume extra styles from extensions
|
||||
.Support {
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
import "./support.scss"
|
||||
|
||||
import React from "react"
|
||||
import { observer } from "mobx-react"
|
||||
import { Trans } from "@lingui/macro"
|
||||
import { issuesTrackerUrl, slackUrl } from "../../../common/vars";
|
||||
import { PageLayout } from "../layout/page-layout";
|
||||
|
||||
@observer
|
||||
export class Support extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<PageLayout showOnTop className="Support" header={<h2>Support</h2>}>
|
||||
<h2><Trans>Community Slack Channel</Trans></h2>
|
||||
<p>
|
||||
<Trans>Ask a question, see what's being discussed, join the conversation <a className="supportLink" href={slackUrl} target="_blank">here</a></Trans>{" "}
|
||||
</p>
|
||||
|
||||
<h2><Trans>Report an Issue</Trans></h2>
|
||||
<p>
|
||||
<Trans>Review existing issues or open a new one <a className="supportLink" href={issuesTrackerUrl} target="_blank">here</a></Trans>
|
||||
</p>
|
||||
|
||||
{/*<h2><Trans>Commercial Support</Trans></h2>*/}
|
||||
</PageLayout>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -38,8 +38,8 @@ import { webFrame } from "electron";
|
||||
import { pageRegistry } from "../../extensions/page-registry";
|
||||
import { DynamicPage } from "../../extensions/dynamic-page";
|
||||
import { extensionLoader } from "../../extensions/extension-loader";
|
||||
import { getLensRuntime } from "../../extensions/lens-runtime";
|
||||
import { appEventBus } from "../../common/event-bus"
|
||||
import { getLensRuntimeRenderer } from "../../extensions/lens-renderer-runtime";
|
||||
import { appEventBus } from "../../common/event-bus"
|
||||
|
||||
@observer
|
||||
export class App extends React.Component {
|
||||
@@ -51,7 +51,7 @@ export class App extends React.Component {
|
||||
|
||||
await clusterIpc.setFrameId.invokeFromRenderer(clusterId, frameId);
|
||||
await getHostedCluster().whenReady; // cluster.activate() is done at this point
|
||||
extensionLoader.loadOnClusterRenderer(getLensRuntime)
|
||||
extensionLoader.loadOnClusterRenderer(getLensRuntimeRenderer)
|
||||
appEventBus.emit({name: "cluster", action: "open", params: {
|
||||
clusterId: clusterId
|
||||
}})
|
||||
@@ -83,7 +83,7 @@ export class App extends React.Component {
|
||||
<Route component={UserManagement} {...usersManagementRoute}/>
|
||||
<Route component={Apps} {...appsRoute}/>
|
||||
{pageRegistry.clusterPages.map(page => {
|
||||
return <Route {...page} key={page.path} render={() => <DynamicPage page={page}/>}/>
|
||||
return <Route {...page} key={String(page.path)} render={() => <DynamicPage page={page}/>}/>
|
||||
})}
|
||||
<Redirect exact from="/" to={this.startURL}/>
|
||||
<Route component={NotFound}/>
|
||||
|
||||
@@ -5,7 +5,6 @@ import { observer } from "mobx-react";
|
||||
import { Icon } from "../icon";
|
||||
import { WorkspaceMenu } from "../+workspaces/workspace-menu";
|
||||
import { workspaceStore } from "../../../common/workspace-store";
|
||||
import { supportURL } from "../+support/support.route";
|
||||
import { navigate } from "../../navigation";
|
||||
|
||||
@observer
|
||||
@@ -24,7 +23,7 @@ export class BottomBar extends React.Component {
|
||||
material="support"
|
||||
tooltip="Support"
|
||||
className="support-icon box right"
|
||||
onClick={() => navigate(supportURL())}
|
||||
onClick={() => navigate("/support")}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -7,7 +7,6 @@ import { ClustersMenu } from "./clusters-menu";
|
||||
import { BottomBar } from "./bottom-bar";
|
||||
import { LandingPage, landingRoute, landingURL } from "../+landing-page";
|
||||
import { Preferences, preferencesRoute } from "../+preferences";
|
||||
import { Support, supportRoute } from "../+support";
|
||||
import { Workspaces, workspacesRoute } from "../+workspaces";
|
||||
import { AddCluster, addClusterRoute } from "../+add-cluster";
|
||||
import { ClusterView } from "./cluster-view";
|
||||
@@ -60,13 +59,12 @@ export class ClusterManager extends React.Component {
|
||||
<Switch>
|
||||
<Route component={LandingPage} {...landingRoute} />
|
||||
<Route component={Preferences} {...preferencesRoute} />
|
||||
<Route component={Support} {...supportRoute} />
|
||||
<Route component={Workspaces} {...workspacesRoute} />
|
||||
<Route component={AddCluster} {...addClusterRoute} />
|
||||
<Route component={ClusterView} {...clusterViewRoute} />
|
||||
<Route component={ClusterSettings} {...clusterSettingsRoute} />
|
||||
{pageRegistry.globalPages.map(({ path, components: { Page } }) => {
|
||||
return <Route key={path} path={path} component={Page}/>
|
||||
{pageRegistry.globalPages.map(({ path, url = String(path), components: { Page } }) => {
|
||||
return <Route key={url} path={path} component={Page}/>
|
||||
})}
|
||||
<Redirect exact to={this.startUrl} />
|
||||
</Switch>
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
> .dynamic-pages {
|
||||
> .extensions {
|
||||
&:not(:empty) {
|
||||
padding-top: $spacing;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import { ClusterId, clusterStore } from "../../../common/cluster-store";
|
||||
import { workspaceStore } from "../../../common/workspace-store";
|
||||
import { ClusterIcon } from "../cluster-icon";
|
||||
import { Icon } from "../icon";
|
||||
import { cssNames, IClassName, autobind } from "../../utils";
|
||||
import { autobind, cssNames, IClassName } from "../../utils";
|
||||
import { Badge } from "../badge";
|
||||
import { navigate } from "../../navigation";
|
||||
import { addClusterURL } from "../+add-cluster";
|
||||
@@ -21,7 +21,7 @@ import { Tooltip } from "../tooltip";
|
||||
import { ConfirmDialog } from "../confirm-dialog";
|
||||
import { clusterIpc } from "../../../common/cluster-ipc";
|
||||
import { clusterViewURL } from "./cluster-view.route";
|
||||
import { DragDropContext, Droppable, Draggable, DropResult, DroppableProvided, DraggableProvided } from "react-beautiful-dnd";
|
||||
import { DragDropContext, Draggable, DraggableProvided, Droppable, DroppableProvided, DropResult } from "react-beautiful-dnd";
|
||||
import { pageRegistry } from "../../../extensions/page-registry";
|
||||
|
||||
interface Props {
|
||||
@@ -155,9 +155,10 @@ export class ClustersMenu extends React.Component<Props> {
|
||||
<Badge className="counter" label={newContexts.size} tooltip={<Trans>new</Trans>} />
|
||||
)}
|
||||
</div>
|
||||
<div className="dynamic-pages">
|
||||
{pageRegistry.globalPages.map(({ path, components: { MenuIcon } }) => {
|
||||
return <MenuIcon key={path} onClick={() => navigate(path)}/>
|
||||
<div className="extensions">
|
||||
{pageRegistry.globalPages.map(({ path, url = String(path), components: { MenuIcon } }) => {
|
||||
if (!MenuIcon) return;
|
||||
return <MenuIcon key={url} onClick={() => navigate(url)}/>
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -80,7 +80,7 @@ export class Sidebar extends React.Component<Props> {
|
||||
<div className={cssNames("Sidebar flex column", className, { pinned: isPinned })}>
|
||||
<div className="header flex align-center">
|
||||
<NavLink exact to="/" className="box grow">
|
||||
<Icon svg="logo-full" className="logo-icon" />
|
||||
<Icon svg="logo-full" className="logo-icon"/>
|
||||
<div className="logo-text">Lens</div>
|
||||
</NavLink>
|
||||
<Icon
|
||||
@@ -97,14 +97,14 @@ export class Sidebar extends React.Component<Props> {
|
||||
isHidden={!isAllowedResource("nodes")}
|
||||
url={clusterURL()}
|
||||
text={<Trans>Cluster</Trans>}
|
||||
icon={<Icon svg="kube" />}
|
||||
icon={<Icon svg="kube"/>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
id="nodes"
|
||||
isHidden={!isAllowedResource("nodes")}
|
||||
url={nodesURL()}
|
||||
text={<Trans>Nodes</Trans>}
|
||||
icon={<Icon svg="nodes" />}
|
||||
icon={<Icon svg="nodes"/>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
id="workloads"
|
||||
@@ -113,7 +113,7 @@ export class Sidebar extends React.Component<Props> {
|
||||
routePath={workloadsRoute.path}
|
||||
subMenus={Workloads.tabRoutes}
|
||||
text={<Trans>Workloads</Trans>}
|
||||
icon={<Icon svg="workloads" />}
|
||||
icon={<Icon svg="workloads"/>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
id="config"
|
||||
@@ -122,7 +122,7 @@ export class Sidebar extends React.Component<Props> {
|
||||
routePath={configRoute.path}
|
||||
subMenus={Config.tabRoutes}
|
||||
text={<Trans>Configuration</Trans>}
|
||||
icon={<Icon material="list" />}
|
||||
icon={<Icon material="list"/>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
id="networks"
|
||||
@@ -131,7 +131,7 @@ export class Sidebar extends React.Component<Props> {
|
||||
routePath={networkRoute.path}
|
||||
subMenus={Network.tabRoutes}
|
||||
text={<Trans>Network</Trans>}
|
||||
icon={<Icon material="device_hub" />}
|
||||
icon={<Icon material="device_hub"/>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
id="storage"
|
||||
@@ -139,14 +139,14 @@ export class Sidebar extends React.Component<Props> {
|
||||
url={storageURL({ query })}
|
||||
routePath={storageRoute.path}
|
||||
subMenus={Storage.tabRoutes}
|
||||
icon={<Icon svg="storage" />}
|
||||
icon={<Icon svg="storage"/>}
|
||||
text={<Trans>Storage</Trans>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
id="namespaces"
|
||||
isHidden={!isAllowedResource("namespaces")}
|
||||
url={namespacesURL()}
|
||||
icon={<Icon material="layers" />}
|
||||
icon={<Icon material="layers"/>}
|
||||
text={<Trans>Namespaces</Trans>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
@@ -154,7 +154,7 @@ export class Sidebar extends React.Component<Props> {
|
||||
isHidden={!isAllowedResource("events")}
|
||||
url={eventsURL({ query })}
|
||||
routePath={eventRoute.path}
|
||||
icon={<Icon material="access_time" />}
|
||||
icon={<Icon material="access_time"/>}
|
||||
text={<Trans>Events</Trans>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
@@ -162,7 +162,7 @@ export class Sidebar extends React.Component<Props> {
|
||||
url={appsURL({ query })}
|
||||
subMenus={Apps.tabRoutes}
|
||||
routePath={appsRoute.path}
|
||||
icon={<Icon material="apps" />}
|
||||
icon={<Icon material="apps"/>}
|
||||
text={<Trans>Apps</Trans>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
@@ -170,7 +170,7 @@ export class Sidebar extends React.Component<Props> {
|
||||
url={usersManagementURL({ query })}
|
||||
routePath={usersManagementRoute.path}
|
||||
subMenus={UserManagement.tabRoutes}
|
||||
icon={<Icon material="security" />}
|
||||
icon={<Icon material="security"/>}
|
||||
text={<Trans>Access Control</Trans>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
@@ -179,17 +179,17 @@ export class Sidebar extends React.Component<Props> {
|
||||
url={crdURL()}
|
||||
subMenus={CustomResources.tabRoutes}
|
||||
routePath={crdRoute.path}
|
||||
icon={<Icon material="extension" />}
|
||||
icon={<Icon material="extension"/>}
|
||||
text={<Trans>Custom Resources</Trans>}
|
||||
>
|
||||
{this.renderCustomResources()}
|
||||
</SidebarNavItem>
|
||||
{pageRegistry.clusterPages.map(({ path, title, components: { MenuIcon } }) => {
|
||||
{pageRegistry.clusterPages.map(({ path, title, url = String(path), components: { MenuIcon } }) => {
|
||||
if (!MenuIcon) return;
|
||||
return (
|
||||
<SidebarNavItem
|
||||
key={path}
|
||||
id={`extension-${path}`}
|
||||
url={path}
|
||||
key={url} id={`sidebar_item_${url}`}
|
||||
url={url}
|
||||
routePath={path}
|
||||
text={title}
|
||||
icon={<MenuIcon/>}
|
||||
@@ -255,7 +255,7 @@ class SidebarNavItem extends React.Component<SidebarNavItemProps> {
|
||||
<div className={cssNames("nav-item", { active: isActive })} onClick={this.toggleSubMenu}>
|
||||
{icon}
|
||||
<span className="link-text">{text}</span>
|
||||
<Icon className="expand-icon" material={this.isExpanded ? "keyboard_arrow_up" : "keyboard_arrow_down"} />
|
||||
<Icon className="expand-icon" material={this.isExpanded ? "keyboard_arrow_up" : "keyboard_arrow_down"}/>
|
||||
</div>
|
||||
<ul className={cssNames("sub-menu", { active: isActive })}>
|
||||
{subMenus.map(({ title, url }) => (
|
||||
|
||||
@@ -12,12 +12,12 @@ import { WhatsNew, whatsNewRoute } from "./components/+whats-new";
|
||||
import { Notifications } from "./components/notifications";
|
||||
import { ConfirmDialog } from "./components/confirm-dialog";
|
||||
import { extensionLoader } from "../extensions/extension-loader";
|
||||
import { getLensRuntime } from "../extensions/lens-runtime";
|
||||
import { getLensRuntimeRenderer } from "../extensions/lens-renderer-runtime";
|
||||
|
||||
@observer
|
||||
export class LensApp extends React.Component {
|
||||
static async init() {
|
||||
extensionLoader.loadOnMainRenderer(getLensRuntime)
|
||||
extensionLoader.loadOnMainRenderer(getLensRuntimeRenderer)
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
Reference in new issue
Block a user