mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
register status-bar element, base class for extension's registry
Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
parent
59ca12ff31
commit
6572fad1c8
@ -1,6 +1,7 @@
|
||||
import { LensRendererExtension, Registry } from "@k8slens/extensions";
|
||||
import { Support } from "./src/support";
|
||||
import React from "react";
|
||||
import { Component, LensRendererExtension, Navigation, Registry } from "@k8slens/extensions";
|
||||
import { supportPageRoute, supportPageURL } from "./src/support.route";
|
||||
import { Support } from "./src/support";
|
||||
|
||||
export default class SupportPageRendererExtension extends LensRendererExtension {
|
||||
async onActivate() {
|
||||
@ -19,4 +20,18 @@ export default class SupportPageRendererExtension extends LensRendererExtension
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
registerStatusBarIcon(registry: Registry.StatusBarRegistry) {
|
||||
this.disposers.push(
|
||||
registry.add({
|
||||
icon: (
|
||||
<Component.Icon
|
||||
material="support"
|
||||
tooltip="Support"
|
||||
onClick={() => Navigation.navigate(supportPageURL())}
|
||||
/>
|
||||
)
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,33 +34,33 @@ export class ExtensionLoader {
|
||||
}
|
||||
}
|
||||
|
||||
loadOnClusterRenderer() {
|
||||
logger.info('[EXTENSIONS-LOADER]: load on cluster renderer')
|
||||
this.autoloadExtensions((instance: LensRendererExtension) => {
|
||||
instance.registerPages(pageRegistry)
|
||||
})
|
||||
}
|
||||
|
||||
loadOnMainRenderer() {
|
||||
logger.info('[EXTENSIONS-LOADER]: load on main renderer')
|
||||
this.autoloadExtensions((instance: LensRendererExtension) => {
|
||||
instance.registerPages(pageRegistry)
|
||||
instance.registerAppPreferences(appPreferenceRegistry)
|
||||
})
|
||||
}
|
||||
|
||||
loadOnMain() {
|
||||
logger.info('[EXTENSIONS-LOADER]: load on main')
|
||||
this.autoloadExtensions((instance: LensMainExtension) => {
|
||||
instance.registerAppMenus(menuRegistry);
|
||||
instance.registerStatusBarIcon(statusBarRegistry);
|
||||
})
|
||||
}
|
||||
|
||||
loadOnClusterManagerRenderer() {
|
||||
logger.info('[EXTENSIONS-LOADER]: load on main renderer (cluster manager)')
|
||||
this.autoloadExtensions((instance: LensRendererExtension) => {
|
||||
instance.registerPages(pageRegistry)
|
||||
instance.registerAppPreferences(appPreferenceRegistry)
|
||||
instance.registerStatusBarIcon(statusBarRegistry)
|
||||
})
|
||||
}
|
||||
|
||||
loadOnClusterRenderer() {
|
||||
logger.info('[EXTENSIONS-LOADER]: load on cluster renderer (dashboard)')
|
||||
this.autoloadExtensions((instance: LensRendererExtension) => {
|
||||
instance.registerPages(pageRegistry)
|
||||
})
|
||||
}
|
||||
|
||||
protected autoloadExtensions(callback: (instance: LensExtension) => void) {
|
||||
return reaction(() => this.extensions.toJS(), (installedExtensions) => {
|
||||
for (const [id, ext] of installedExtensions) {
|
||||
let instance = this.instances.get(ext.manifestPath)
|
||||
let instance = this.instances.get(ext.name)
|
||||
if (!instance) {
|
||||
const extensionModule = this.requireExtension(ext)
|
||||
if (!extensionModule) {
|
||||
@ -70,7 +70,7 @@ export class ExtensionLoader {
|
||||
instance = new LensExtensionClass({ ...ext.manifest, manifestPath: ext.manifestPath, id: ext.manifestPath }, ext.manifest);
|
||||
instance.enable();
|
||||
callback(instance)
|
||||
this.instances.set(ext.id, instance)
|
||||
this.instances.set(ext.name, instance)
|
||||
}
|
||||
}
|
||||
}, {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { LensExtension } from "./lens-extension"
|
||||
import type { PageRegistry } from "./registries/page-registry"
|
||||
import type { AppPreferenceRegistry } from "./registries/app-preference-registry";
|
||||
import type { StatusBarRegistry } from "./registries";
|
||||
|
||||
export class LensRendererExtension extends LensExtension {
|
||||
registerPages(registry: PageRegistry) {
|
||||
@ -10,4 +11,8 @@ export class LensRendererExtension extends LensExtension {
|
||||
registerAppPreferences(registry: AppPreferenceRegistry) {
|
||||
return
|
||||
}
|
||||
|
||||
registerStatusBarIcon(registry: StatusBarRegistry) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { observable } from "mobx"
|
||||
import React from "react"
|
||||
import type React from "react"
|
||||
import { BaseRegistry } from "./base-registry";
|
||||
|
||||
export interface AppPreferenceComponents {
|
||||
Hint: React.ComponentType<any>;
|
||||
@ -11,17 +11,7 @@ export interface AppPreferenceRegistration {
|
||||
components: AppPreferenceComponents;
|
||||
}
|
||||
|
||||
export class AppPreferenceRegistry {
|
||||
preferences = observable.array<AppPreferenceRegistration>([], { deep: false });
|
||||
|
||||
add(preference: AppPreferenceRegistration) {
|
||||
this.preferences.push(preference)
|
||||
return () => {
|
||||
this.preferences.replace(
|
||||
this.preferences.filter(c => c !== preference)
|
||||
)
|
||||
};
|
||||
}
|
||||
export class AppPreferenceRegistry extends BaseRegistry<AppPreferenceRegistration> {
|
||||
}
|
||||
|
||||
export const appPreferenceRegistry = new AppPreferenceRegistry()
|
||||
|
||||
17
src/extensions/registries/base-registry.ts
Normal file
17
src/extensions/registries/base-registry.ts
Normal file
@ -0,0 +1,17 @@
|
||||
// Base class for extensions-api registries
|
||||
import { observable } from "mobx";
|
||||
|
||||
export class BaseRegistry<T = any> {
|
||||
protected items = observable<T>([], { deep: false });
|
||||
|
||||
getItems(): T[] {
|
||||
return this.items.toJS();
|
||||
}
|
||||
|
||||
add(item: T) {
|
||||
this.items.push(item);
|
||||
return () => {
|
||||
this.items.remove(item); // works because of {deep: false};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,24 +1,14 @@
|
||||
// Extensions API -> Global menu customize
|
||||
// Extensions API -> Global menu customizations
|
||||
|
||||
import { observable } from "mobx";
|
||||
import { MenuItemConstructorOptions } from "electron";
|
||||
import type { MenuTopId } from "../../main/menu";
|
||||
import type { MenuItemConstructorOptions } from "electron";
|
||||
import { BaseRegistry } from "./base-registry";
|
||||
|
||||
export interface MenuRegistration extends MenuItemConstructorOptions {
|
||||
parentId?: MenuTopId;
|
||||
}
|
||||
|
||||
export class MenuRegistry {
|
||||
protected items = observable.array([], { deep: false });
|
||||
|
||||
getItems(): MenuRegistration[] {
|
||||
return this.items.toJS();
|
||||
}
|
||||
|
||||
add(item: MenuRegistration) {
|
||||
this.items.push(item);
|
||||
return () => this.items.remove(item)
|
||||
}
|
||||
export class MenuRegistry extends BaseRegistry<MenuRegistration> {
|
||||
}
|
||||
|
||||
export const menuRegistry = new MenuRegistry();
|
||||
|
||||
@ -5,7 +5,8 @@ import type { RouteProps } from "react-router";
|
||||
import type { IconProps } from "../../renderer/components/icon";
|
||||
import type { IClassName } from "../../renderer/utils";
|
||||
import type { TabRoute } from "../../renderer/components/layout/tab-layout";
|
||||
import { computed, observable } from "mobx";
|
||||
import { BaseRegistry } from "./base-registry";
|
||||
import { computed } from "mobx";
|
||||
|
||||
export enum PageRegistryType {
|
||||
GLOBAL = "lens-scope",
|
||||
@ -26,21 +27,13 @@ export interface PageComponents {
|
||||
MenuIcon?: React.ComponentType<IconProps>;
|
||||
}
|
||||
|
||||
export class PageRegistry {
|
||||
protected pages = observable.array<PageRegistration>([], { deep: false });
|
||||
|
||||
export class PageRegistry extends BaseRegistry<PageRegistration> {
|
||||
@computed get globalPages() {
|
||||
return this.pages.filter(page => page.type === PageRegistryType.GLOBAL);
|
||||
return this.items.filter(page => page.type === PageRegistryType.GLOBAL);
|
||||
}
|
||||
|
||||
@computed get clusterPages() {
|
||||
return this.pages.filter(page => page.type === PageRegistryType.CLUSTER);
|
||||
}
|
||||
|
||||
// fixme: validate route paths to avoid collisions
|
||||
add(pageInit: PageRegistration) {
|
||||
this.pages.push(pageInit);
|
||||
return () => this.pages.remove(pageInit); // works because of {deep: false};
|
||||
return this.items.filter(page => page.type === PageRegistryType.CLUSTER);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,15 +1,13 @@
|
||||
// Extensions API -> Status bar customizations
|
||||
|
||||
import { observable } from "mobx";
|
||||
import React from "react";
|
||||
import { BaseRegistry } from "./base-registry";
|
||||
|
||||
export interface StatusBarRegistration {
|
||||
icon?: React.ReactNode;
|
||||
}
|
||||
|
||||
export class StatusBarRegistry {
|
||||
items = observable<StatusBarRegistration>([], { deep: false });
|
||||
|
||||
add(item: StatusBarRegistration) {
|
||||
}
|
||||
export class StatusBarRegistry extends BaseRegistry<StatusBarRegistration> {
|
||||
}
|
||||
|
||||
export const statusBarRegistry = new StatusBarRegistry();
|
||||
|
||||
@ -103,7 +103,6 @@ export class Preferences extends React.Component {
|
||||
|
||||
render() {
|
||||
const { preferences } = userStore;
|
||||
const extensionPreferences = appPreferenceRegistry.preferences;
|
||||
const header = <h2><Trans>Preferences</Trans></h2>;
|
||||
return (
|
||||
<PageLayout showOnTop className="Preferences" header={header}>
|
||||
@ -170,7 +169,7 @@ export class Preferences extends React.Component {
|
||||
</small>
|
||||
|
||||
<div className="extensions flex column gaps">
|
||||
{extensionPreferences.map(({ title, components: { Hint, Input } }, index) => {
|
||||
{appPreferenceRegistry.getItems().map(({ title, components: { Hint, Input } }, index) => {
|
||||
return (
|
||||
<div key={index} className="preference">
|
||||
<h2>{title}</h2>
|
||||
|
||||
@ -5,7 +5,7 @@ import { observer } from "mobx-react";
|
||||
import { Icon } from "../icon";
|
||||
import { WorkspaceMenu } from "../+workspaces/workspace-menu";
|
||||
import { workspaceStore } from "../../../common/workspace-store";
|
||||
import { navigate } from "../../navigation";
|
||||
import { statusBarRegistry } from "../../../extensions/registries";
|
||||
|
||||
@observer
|
||||
export class BottomBar extends React.Component {
|
||||
@ -13,18 +13,19 @@ export class BottomBar extends React.Component {
|
||||
const { currentWorkspace } = workspaceStore;
|
||||
return (
|
||||
<div className="BottomBar flex gaps">
|
||||
<div id="current-workspace" className="flex gaps align-center box">
|
||||
<div id="current-workspace" className="flex gaps align-center">
|
||||
<Icon small material="layers"/>
|
||||
<span className="workspace-name">{currentWorkspace.name}</span>
|
||||
</div>
|
||||
<WorkspaceMenu htmlFor="current-workspace"/>
|
||||
<Icon
|
||||
small
|
||||
material="support"
|
||||
tooltip="Support"
|
||||
className="support-icon box right"
|
||||
onClick={() => navigate("/support")}
|
||||
<WorkspaceMenu
|
||||
htmlFor="current-workspace"
|
||||
/>
|
||||
<div className="extensions box grow flex gaps justify-flex-end">
|
||||
{statusBarRegistry.getItems().map(({ icon }, index) => {
|
||||
if (!icon) return;
|
||||
return <React.Fragment key={index}>{icon}</React.Fragment>
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@ import { extensionLoader } from "../extensions/extension-loader";
|
||||
@observer
|
||||
export class LensApp extends React.Component {
|
||||
static async init() {
|
||||
extensionLoader.loadOnMainRenderer();
|
||||
extensionLoader.loadOnClusterManagerRenderer();
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user