mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Extensions-api: initial hello-world example (#817)
Signed-off-by: Roman <ixrock@gmail.com> Co-authored-by: Alex Andreev <alex.andreev.email@gmail.com>
This commit is contained in:
1 parent
f1b03990ea
commit
5daf53e6cb
19 files changed
+184
-85
No files matched your search
@@ -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,6 +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 "../../../extensions/register-page";
|
||||
|
||||
@observer
|
||||
export class ClusterManager extends React.Component {
|
||||
@@ -62,6 +63,9 @@ export class ClusterManager extends React.Component {
|
||||
<Route component={ClusterView} {...clusterViewRoute}/>
|
||||
<Route component={ClusterSettings} {...clusterSettingsRoute}/>
|
||||
<Route component={Extensions} {...extensionsRoute}/>
|
||||
{dynamicPages.globalPages.map(({ path, components: { Page } }) => {
|
||||
return <Route key={path} path={path} component={Page}/>
|
||||
})}
|
||||
<Redirect exact to={this.startUrl}/>
|
||||
</Switch>
|
||||
</main>
|
||||
|
||||
@@ -10,7 +10,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";
|
||||
@@ -20,8 +20,8 @@ import { Tooltip } from "../tooltip";
|
||||
import { ConfirmDialog } from "../confirm-dialog";
|
||||
import { clusterIpc } from "../../../common/cluster-ipc";
|
||||
import { clusterViewURL, getMatchedClusterId } from "./cluster-view.route";
|
||||
import { DragDropContext, Droppable, Draggable, DropResult, DroppableProvided, DraggableProvided } from "react-beautiful-dnd";
|
||||
import { dynamicPages } from "./register-page";
|
||||
import { DragDropContext, Draggable, DraggableProvided, Droppable, DroppableProvided, DropResult } from "react-beautiful-dnd";
|
||||
import { dynamicPages } from "../../../extensions/register-page";
|
||||
|
||||
interface Props {
|
||||
className?: IClassName;
|
||||
@@ -143,15 +143,14 @@ export class ClustersMenu extends React.Component<Props> {
|
||||
<Tooltip targetId="add-cluster-icon">
|
||||
<Trans>Add Cluster</Trans>
|
||||
</Tooltip>
|
||||
<Icon big material="add" id="add-cluster-icon" />
|
||||
<Icon big material="add" id="add-cluster-icon"/>
|
||||
{newContexts.size > 0 && (
|
||||
<Badge className="counter" label={newContexts.size} tooltip={<Trans>new</Trans>} />
|
||||
<Badge className="counter" label={newContexts.size} tooltip={<Trans>new</Trans>}/>
|
||||
)}
|
||||
</div>
|
||||
<div className="dynamic-pages">
|
||||
{Array.from(dynamicPages.all).map(([path, { MenuIcon }]) => {
|
||||
if (!MenuIcon) return;
|
||||
return <MenuIcon onClick={() => navigate(path)}/>
|
||||
{dynamicPages.globalPages.map(({ path, components: { MenuIcon } }) => {
|
||||
return <MenuIcon key={path} onClick={() => navigate(path)}/>
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
// Dynamic pages
|
||||
|
||||
import React from "react";
|
||||
import { observable } from "mobx";
|
||||
import type { IconProps } from "../icon";
|
||||
|
||||
export interface PageComponents {
|
||||
Main: React.ComponentType<any>;
|
||||
MenuIcon: React.ComponentType<IconProps>;
|
||||
}
|
||||
|
||||
export class PagesStore {
|
||||
all = observable.map<string, PageComponents>();
|
||||
|
||||
getComponents(path: string): PageComponents | null {
|
||||
return this.all.get(path);
|
||||
}
|
||||
|
||||
register(path: string, components: PageComponents) {
|
||||
this.all.set(path, components);
|
||||
}
|
||||
|
||||
unregister(path: string) {
|
||||
this.all.delete(path);
|
||||
}
|
||||
}
|
||||
|
||||
export const dynamicPages = new PagesStore();
|
||||
@@ -17,7 +17,7 @@ export interface TabRoute extends RouteProps {
|
||||
url: string;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
export interface MainLayoutProps {
|
||||
className?: any;
|
||||
tabs?: TabRoute[];
|
||||
footer?: React.ReactNode;
|
||||
@@ -27,7 +27,7 @@ interface Props {
|
||||
}
|
||||
|
||||
@observer
|
||||
export class MainLayout extends React.Component<Props> {
|
||||
export class MainLayout extends React.Component<MainLayoutProps> {
|
||||
public storage = createStorage("main_layout", { pinnedSidebar: true });
|
||||
|
||||
@observable isPinned = this.storage.get().pinnedSidebar;
|
||||
|
||||
@@ -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}>
|
||||
|
||||
Reference in new issue
Block a user