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:
RomanandAlex Andreev authored and GitHub committed 2020-09-09 16:19:02 +03:00
1 parent f1b03990ea
commit 5daf53e6cb
19 files changed
+184 -85

No files matched your search

+2
View File
@@ -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);
}
+4
View File
@@ -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>
-6
View File
@@ -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}>