mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
1 parent
ef3962f8b5
commit
323a4c141e
18 files changed
+319
-379
No files matched your search
@@ -1,5 +1,5 @@
|
||||
import "./app.scss";
|
||||
import React, { Fragment } from "react";
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { i18nStore } from "../i18n";
|
||||
import { configStore } from "../config.store";
|
||||
@@ -34,11 +34,10 @@ import { LandingPage, landingRoute, landingURL } from "./+landing-page";
|
||||
import { clusterStore } from "../../common/cluster-store";
|
||||
import { ClusterSettings, clusterSettingsRoute } from "./+cluster-settings";
|
||||
import { Workspaces, workspacesRoute } from "./+workspaces";
|
||||
import { ErrorBoundary } from "./error-boundary";
|
||||
|
||||
@observer
|
||||
export class App extends React.Component {
|
||||
static rootElem = document.getElementById('app');
|
||||
|
||||
static async init() {
|
||||
await i18nStore.init();
|
||||
await configStore.init();
|
||||
@@ -57,27 +56,25 @@ export class App extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Fragment>
|
||||
<ErrorBoundary>
|
||||
<Switch>
|
||||
<Switch>
|
||||
<Route component={LandingPage} {...landingRoute}/>
|
||||
<Route component={AddCluster} {...addClusterRoute}/>
|
||||
<Route component={Workspaces} {...workspacesRoute}/>
|
||||
<Route component={ClusterSettings} {...clusterSettingsRoute}/>
|
||||
<Route component={Cluster} {...clusterRoute}/>
|
||||
<Route component={Nodes} {...nodesRoute}/>
|
||||
<Route component={Workloads} {...workloadsRoute}/>
|
||||
<Route component={Config} {...configRoute}/>
|
||||
<Route component={Network} {...networkRoute}/>
|
||||
<Route component={Storage} {...storageRoute}/>
|
||||
<Route component={Namespaces} {...namespacesRoute}/>
|
||||
<Route component={Events} {...eventRoute}/>
|
||||
<Route component={CustomResources} {...crdRoute}/>
|
||||
<Route component={UserManagement} {...usersManagementRoute}/>
|
||||
<Route component={Apps} {...appsRoute}/>
|
||||
<Redirect exact from="/" to={this.startURL}/>
|
||||
<Route component={NotFound}/>
|
||||
</Switch>
|
||||
<Route component={LandingPage} {...landingRoute}/>
|
||||
<Route component={AddCluster} {...addClusterRoute}/>
|
||||
<Route component={Workspaces} {...workspacesRoute}/>
|
||||
<Route component={ClusterSettings} {...clusterSettingsRoute}/>
|
||||
<Route component={Cluster} {...clusterRoute}/>
|
||||
<Route component={Nodes} {...nodesRoute}/>
|
||||
<Route component={Workloads} {...workloadsRoute}/>
|
||||
<Route component={Config} {...configRoute}/>
|
||||
<Route component={Network} {...networkRoute}/>
|
||||
<Route component={Storage} {...storageRoute}/>
|
||||
<Route component={Namespaces} {...namespacesRoute}/>
|
||||
<Route component={Events} {...eventRoute}/>
|
||||
<Route component={CustomResources} {...crdRoute}/>
|
||||
<Route component={UserManagement} {...usersManagementRoute}/>
|
||||
<Route component={Apps} {...appsRoute}/>
|
||||
<Redirect exact from="/" to={this.startURL}/>
|
||||
<Route component={NotFound}/>
|
||||
</Switch>
|
||||
<KubeObjectDetails/>
|
||||
<Notifications/>
|
||||
@@ -86,7 +83,7 @@ export class App extends React.Component {
|
||||
<AddRoleBindingDialog/>
|
||||
<PodLogsDialog/>
|
||||
<DeploymentScaleDialog/>
|
||||
</Fragment>
|
||||
</ErrorBoundary>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,40 @@
|
||||
import "./cluster-manager.scss"
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { computed } from "mobx";
|
||||
import { App } from "../app";
|
||||
import { ClusterStatus } from "./cluster-status";
|
||||
import { ClustersMenu } from "./clusters-menu";
|
||||
import { BottomBar } from "./bottom-bar";
|
||||
import { App } from "../app";
|
||||
import { cssNames, IClassName } from "../../utils";
|
||||
import { invokeIpc } from "../../../common/ipc";
|
||||
import { ClusterIpcChannel } from "../../../main/cluster";
|
||||
import { clusterStore } from "../../../common/cluster-store";
|
||||
|
||||
interface Props {
|
||||
className?: IClassName;
|
||||
contentClass?: IClassName;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class ClusterManager extends React.Component<Props> {
|
||||
@computed get isReady() {
|
||||
return clusterStore.activeCluster?.isReady
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
await invokeIpc(ClusterIpcChannel.INIT)
|
||||
await App.init();
|
||||
}
|
||||
|
||||
export class ClusterManager extends React.Component {
|
||||
render() {
|
||||
const { className, contentClass } = this.props;
|
||||
return (
|
||||
<div className="ClusterManager">
|
||||
<div className={cssNames("ClusterManager", className)}>
|
||||
<div id="draggable-top"/>
|
||||
<div id="lens-view">
|
||||
<App/>
|
||||
<div id="lens-view" className={cssNames("flex", contentClass)}>
|
||||
{this.isReady && <App/>}
|
||||
{!this.isReady && <ClusterStatus/>}
|
||||
</div>
|
||||
<ClustersMenu/>
|
||||
<BottomBar/>
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
.ClusterStatus {
|
||||
--flex-gap: #{$padding * 2};
|
||||
|
||||
min-width: 350px;
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
|
||||
pre {
|
||||
@include custom-scrollbar;
|
||||
max-width: 70vw;
|
||||
max-height: 40vh;
|
||||
//text-align: left;
|
||||
}
|
||||
|
||||
.Icon {
|
||||
--size: 70px;
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,32 @@
|
||||
import "./cluster-manager.scss"
|
||||
import type { KubeAuthProxyResponse } from "../../../main/kube-auth-proxy";
|
||||
import { Cluster, ClusterIpcEvent } from "../../../main/cluster";
|
||||
import "./cluster-status.scss"
|
||||
import React from "react";
|
||||
import type { KubeAuthProxyResponse } from "../../../main/kube-auth-proxy";
|
||||
import { ClusterIpcChannel } from "../../../main/cluster";
|
||||
import { invokeIpc } from "../../../common/ipc";
|
||||
import { clusterStore } from "../../../common/cluster-store";
|
||||
import { ipcRenderer } from "electron";
|
||||
import { computed, observable } from "mobx";
|
||||
import { observable } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import { Icon } from "../icon";
|
||||
import { Button } from "../button";
|
||||
import { Trans } from "@lingui/macro";
|
||||
|
||||
interface Props {
|
||||
cluster: Cluster;
|
||||
}
|
||||
import { cssNames } from "../../utils";
|
||||
|
||||
@observer
|
||||
export class ClusterStatus extends React.Component<Props> {
|
||||
@observable authProxyOutput = "Connecting ...\n"
|
||||
export class ClusterStatus extends React.Component {
|
||||
@observable authOutput: string[] = [];
|
||||
|
||||
@computed get clusterId() {
|
||||
return this.props.cluster.id;
|
||||
get cluster() {
|
||||
return clusterStore.activeCluster;
|
||||
}
|
||||
|
||||
get clusterId() {
|
||||
return clusterStore.activeClusterId;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
ipcRenderer.on(`kube-auth:${this.clusterId}`, (evt, authResponse: KubeAuthProxyResponse) => {
|
||||
this.authProxyOutput += authResponse.data;
|
||||
this.authOutput = ["Connecting ...\n"];
|
||||
ipcRenderer.on(`kube-auth:${this.clusterId}`, (evt, { data, stream }: KubeAuthProxyResponse) => {
|
||||
this.authOutput.push(`[${stream}]: ${data}`);
|
||||
})
|
||||
}
|
||||
|
||||
@@ -31,22 +34,32 @@ export class ClusterStatus extends React.Component<Props> {
|
||||
ipcRenderer.removeAllListeners(`kube-auth:${this.clusterId}`);
|
||||
}
|
||||
|
||||
reconnectCluster = () => {
|
||||
ipcRenderer.send(ClusterIpcEvent.RECONNECT, this.clusterId);
|
||||
reconnect = () => {
|
||||
this.authOutput = ["Reconnecting ...\n"];
|
||||
invokeIpc(ClusterIpcChannel.RECONNECT, this.clusterId);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { authProxyOutput } = this;
|
||||
const { contextName, online } = this.props.cluster;
|
||||
const { authOutput, cluster } = this;
|
||||
const isError = cluster?.accessible === false;
|
||||
return (
|
||||
<div className="ClusterStatus flex column">
|
||||
<Icon sticker className="status-icon" material={online ? "https" : "cloud_off"}/>
|
||||
<h2>{contextName}</h2>
|
||||
<pre className="kube-auth-stdout">{authProxyOutput}</pre>
|
||||
<Button
|
||||
primary label={<Trans>Reconnect</Trans>}
|
||||
onClick={this.reconnectCluster}
|
||||
/>
|
||||
<div className="ClusterStatus flex column gaps">
|
||||
{!isError && <Icon material="cloud_queue"/>}
|
||||
{isError && <Icon material="cloud_off" className="error"/>}
|
||||
<h2>{cluster?.contextName}</h2>
|
||||
<pre className="kube-auth-out">
|
||||
{authOutput.map((data, index) => {
|
||||
const error = data.startsWith("[stderr]");
|
||||
return <p key={index} className={cssNames({ error })}>{data}</p>
|
||||
})}
|
||||
</pre>
|
||||
{isError && (
|
||||
<Button
|
||||
primary className="box center"
|
||||
label="Reconnect"
|
||||
onClick={this.reconnect}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ export class ClustersMenu extends React.Component<Props> {
|
||||
label: _i18n._(t`Settings`),
|
||||
click: () => navigate(clusterSettingsURL())
|
||||
}));
|
||||
if (cluster.initialized) {
|
||||
if (cluster.online) {
|
||||
menu.append(new MenuItem({
|
||||
label: _i18n._(t`Disconnect`),
|
||||
click: () => {
|
||||
|
||||
Reference in new issue
Block a user