1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00
Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
Roman 2020-08-06 15:43:38 +03:00
parent e5138e7c5d
commit d04c8d3045
11 changed files with 121 additions and 73 deletions

View File

@ -156,11 +156,6 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
this.activeClusterId = newClusters.has(activeCluster) ? activeCluster : null;
this.clusters.replace(newClusters);
this.removedClusters.replace(removedClusters);
// "auto-select" first cluster if available
if (!this.activeClusterId && newClusters.size) {
this.activeClusterId = Array.from(newClusters.values())[0].id;
}
}
toJSON(): ClusterStoreModel {

View File

@ -1,4 +1,4 @@
import { action, computed, observable, reaction, toJS } from "mobx";
import { action, computed, observable, toJS } from "mobx";
import { BaseStore } from "./base-store";
import { clusterStore } from "./cluster-store"
@ -22,15 +22,6 @@ export class WorkspaceStore extends BaseStore<WorkspaceStoreModel> {
super({
configName: "lens-workspace-store",
});
// switch to first available cluster in current workspace
reaction(() => this.currentWorkspaceId, workspaceId => {
const clusters = clusterStore.getByWorkspaceId(workspaceId);
const activeClusterInWorkspace = clusters.some(cluster => cluster.id === clusterStore.activeClusterId);
if (!activeClusterInWorkspace) {
clusterStore.activeClusterId = clusters.length ? clusters[0].id : null;
}
})
}
@observable currentWorkspaceId = WorkspaceStore.defaultId;

View File

@ -67,11 +67,6 @@ export class Cluster implements ClusterModel {
@observable allowedNamespaces: string[] = [];
@observable allowedResources: string[] = [];
@computed get host() {
const proxyHost = new URL(this.kubeProxyUrl).host;
return `${this.id}.${proxyHost}`
}
constructor(model: ClusterModel) {
this.updateModel(model);
}
@ -223,7 +218,7 @@ export class Cluster implements ClusterModel {
json: true,
timeout: 5000,
headers: {
Host: this.host, // provide cluster-id for ClusterManager.getClusterForRequest()
Host: `${this.id}.${new URL(this.kubeProxyUrl).host}`, // required in ClusterManager.getClusterForRequest()
...(options.headers || {}),
},
})

View File

@ -27,6 +27,7 @@ export class WindowManager {
webPreferences: {
nodeIntegration: true,
enableRemoteModule: true,
webviewTag: true,
},
});
this.windowState.manage(this.mainView);

View File

@ -1,32 +1,34 @@
import "./cluster-manager.scss"
import React from "react";
import { Redirect, Route, Switch } from "react-router";
import { observer } from "mobx-react";
import { ClustersMenu } from "./clusters-menu";
import { BottomBar } from "./bottom-bar";
import { cssNames, IClassName } from "../../utils";
import { ClusterId } from "../../../common/cluster-store";
import { Route, Switch } from "react-router";
import { LandingPage, landingRoute } from "../+landing-page";
import { LandingPage, landingRoute, landingURL } from "../+landing-page";
import { Preferences, preferencesRoute } from "../+preferences";
import { Workspaces, workspacesRoute } from "../+workspaces";
import { AddCluster, addClusterRoute } from "../+add-cluster";
import { ClusterStatus } from "./cluster-status";
import { clusterStatusRoute } from "./cluster-status.route";
interface Props {
className?: IClassName;
contentClass?: IClassName;
}
import { ClusterView } from "./cluster-view";
import { clusterViewRoute, clusterViewURL } from "./cluster-view.route";
import { clusterStore } from "../../../common/cluster-store";
@observer
export class ClusterManager extends React.Component<Props> {
activateView(clusterId: ClusterId) {
export class ClusterManager extends React.Component {
get startUrl() {
const { activeClusterId } = clusterStore;
if (activeClusterId) {
return clusterViewURL({
params: {
clusterId: activeClusterId
}
})
}
return landingURL()
}
render() {
const { className } = this.props;
return (
<div className={cssNames("ClusterManager", className)}>
<div className="ClusterManager">
<div id="draggable-top"/>
<div id="lens-view">
<Switch>
@ -34,8 +36,8 @@ export class ClusterManager extends React.Component<Props> {
<Route component={Preferences} {...preferencesRoute}/>
<Route component={Workspaces} {...workspacesRoute}/>
<Route component={AddCluster} {...addClusterRoute}/>
<Route component={ClusterStatus} {...clusterStatusRoute}/>
<Route render={() => <p>Lens</p>}/>
<Route component={ClusterView} {...clusterViewRoute}/>
<Redirect exact from="/" to={this.startUrl}/>
</Switch>
</div>
<ClustersMenu/>

View File

@ -1,8 +0,0 @@
import { RouteProps } from "react-router";
import { buildURL } from "../../navigation";
export const clusterStatusRoute: RouteProps = {
path: "/cluster-status"
}
export const clusterStatusURL = buildURL(clusterStatusRoute.path)

View File

@ -2,37 +2,37 @@ import type { KubeAuthProxyLog } from "../../../main/kube-auth-proxy";
import "./cluster-status.scss"
import React from "react";
import { disposeOnUnmount, observer } from "mobx-react";
import { observer } from "mobx-react";
import { ipcRenderer } from "electron";
import { autorun, computed, observable } from "mobx";
import { computed, observable } from "mobx";
import { clusterIpc } from "../../../common/cluster-ipc";
import { Icon } from "../icon";
import { Button } from "../button";
import { cssNames } from "../../utils";
import { navigate } from "../../navigation";
import { Cluster } from "../../../main/cluster";
import { ClusterId, clusterStore } from "../../../common/cluster-store";
interface Props {
clusterId: ClusterId;
}
@observer
export class ClusterStatus extends React.Component {
export class ClusterStatus extends React.Component<Props> {
@observable authOutput: KubeAuthProxyLog[] = [];
@observable isReconnecting = false;
// fixme
@computed get clusterId() {
return this.props.clusterId;
}
@computed get cluster(): Cluster {
return null;
return clusterStore.getById(this.clusterId);
}
@computed get hasErrors(): boolean {
return this.authOutput.some(({ error }) => error) || !!this.cluster.failureReason;
}
@disposeOnUnmount
autoRedirectToMain = autorun(() => {
if (this.cluster.accessible && !this.hasErrors) {
navigate("/");
}
})
async componentDidMount() {
if (this.cluster.disconnected) {
return;
@ -48,11 +48,11 @@ export class ClusterStatus extends React.Component {
}
componentWillUnmount() {
ipcRenderer.removeAllListeners(`kube-auth:${this.cluster.id}`);
ipcRenderer.removeAllListeners(`kube-auth:${this.clusterId}`);
}
async refreshClusterState() {
return clusterIpc.activate.invokeFromRenderer();
return clusterIpc.activate.invokeFromRenderer(this.clusterId);
}
reconnect = async () => {

View File

@ -0,0 +1,22 @@
import { matchPath, RouteProps } from "react-router";
import { buildURL, navigation } from "../../navigation";
export interface IClusterViewRouteParams {
clusterId: string;
}
export const clusterViewRoute: RouteProps = {
path: "/cluster/:clusterId"
}
export const clusterViewURL = buildURL<IClusterViewRouteParams>(clusterViewRoute.path)
export function getMatchedClusterId(): string {
const matched = matchPath<IClusterViewRouteParams>(navigation.location.pathname, {
...clusterViewRoute,
exact: true,
})
if (matched) {
return matched.params.clusterId;
}
}

View File

@ -0,0 +1,10 @@
.ClusterView {
width: 100%;
height: 100%;
border: 0;
//display: none;
&.loaded {
display: block;
}
}

View File

@ -0,0 +1,46 @@
import React from "react";
import { autorun, computed, observable } from "mobx";
import { disposeOnUnmount, observer } from "mobx-react";
import { ClusterId, clusterStore } from "../../../common/cluster-store";
import { getMatchedClusterId } from "./cluster-view.route";
import { Cluster } from "../../../main/cluster";
@observer
export class ClusterView extends React.Component {
static views = observable.map<ClusterId, /*HTMLIFrameElement*/ any>()
static isLoaded = observable.map<ClusterId, boolean>()
@computed get cluster() {
return clusterStore.getById(getMatchedClusterId())
}
@computed get clusterView() {
return ClusterView.views.get(this.cluster?.id)
}
componentDidMount() {
disposeOnUnmount(this, [
autorun(() => this.activateView(this.cluster))
])
}
activateView = (cluster: Cluster) => {
if (!cluster || ClusterView.views.has(cluster.id)) {
return;
}
const view = document.createElement("webview");
view.className = "ClusterView"
view.src = `${location.protocol}://${cluster.id}.${location.host}`
view.onload = () => console.log('CLUSTER VIEW READY!', cluster);
document.body.appendChild(view);
ClusterView.views.set(cluster.id, view);
}
render() {
const { cluster } = this;
if (cluster && cluster.accessible) {
}
return "";
}
}

View File

@ -20,7 +20,7 @@ import { landingURL } from "../+landing-page";
import { Tooltip } from "../tooltip";
import { ConfirmDialog } from "../confirm-dialog";
import { clusterIpc } from "../../../common/cluster-ipc";
import { clusterStatusURL } from "./cluster-status.route";
import { clusterViewURL, getMatchedClusterId } from "./cluster-view.route";
// fixme: allow to rearrange clusters with drag&drop
@ -32,12 +32,9 @@ interface Props {
export class ClustersMenu extends React.Component<Props> {
@observable showHint = true;
showCluster = (clusterId: ClusterId) => {
if (clusterStore.activeClusterId === clusterId) {
navigate("/"); // redirect to index
} else {
clusterStore.activeClusterId = clusterId;
}
activateCluster = (clusterId: ClusterId) => {
clusterStore.activeClusterId = clusterId;
navigate(clusterViewURL({ params: { clusterId } }))
}
addCluster = () => {
@ -57,9 +54,6 @@ export class ClustersMenu extends React.Component<Props> {
label: _i18n._(t`Disconnect`),
click: async () => {
await clusterIpc.disconnect.invokeFromRenderer(cluster.id);
if (cluster.id === clusterStore.activeClusterId) {
navigate(clusterStatusURL());
}
}
}))
}
@ -110,8 +104,8 @@ export class ClustersMenu extends React.Component<Props> {
key={cluster.id}
showErrors={true}
cluster={cluster}
isActive={cluster.id === clusterStore.activeClusterId}
onClick={() => this.showCluster(cluster.id)}
isActive={cluster.id === getMatchedClusterId()}
onClick={() => this.activateCluster(cluster.id)}
onContextMenu={() => this.showContextMenu(cluster)}
/>
)