PoC: first run

Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
Roman committed 2020-07-13 19:32:55 +03:00
1 parent 12472aab5b
commit 4e88715b8d
12 files changed
+116 -80

No files matched your search

+2 -3
View File
@@ -41,9 +41,8 @@ export class ClusterManager {
});
// auto-refresh status for active cluster
autorun(() => {
const { activeCluster } = clusterStore;
if (activeCluster && activeCluster.initialized) {
activeCluster.refreshStatus();
if (clusterStore.activeCluster) {
clusterStore.activeCluster.refreshStatus();
}
});
// listen ipc-events
+6 -3
View File
@@ -1,6 +1,6 @@
import type { ClusterId, ClusterModel, ClusterPreferences } from "../common/cluster-store"
import type { FeatureStatusMap } from "./feature"
import { action, observable, toJS } from "mobx";
import { action, observable, toJS, when } from "mobx";
import { apiKubePrefix } from "../common/vars";
import { ContextHandler } from "./context-handler"
import { AuthorizationV1Api, CoreV1Api, KubeConfig, V1ResourceAttributes } from "@kubernetes/client-node"
@@ -23,6 +23,8 @@ export class Cluster implements ClusterModel {
public contextHandler: ContextHandler;
protected kubeconfigManager: KubeconfigManager;
public whenReady = when(() => this.initialized);
@observable initialized = false;
@observable contextName: string;
@observable workspace: string;
@@ -63,14 +65,14 @@ export class Cluster implements ClusterModel {
this.webContentUrl = `http://${this.id}.localhost:${port}`;
this.kubeconfigManager = new KubeconfigManager(this);
this.initialized = true;
logger.info(`[✔] Cluster(${this.id}) init success`, {
logger.info(`✅ ️Cluster(${this.id}) init success`, {
serverUrl: this.apiUrl,
webContentUrl: this.webContentUrl,
kubeProxyUrl: this.kubeProxyUrl,
kubeAuthProxyUrl: this.kubeAuthProxyUrl,
});
} catch (err) {
logger.error(`[X] Cluster(${this.id}) init failed: ${err}`);
logger.error(`💣 Cluster(${this.id}) init failed: ${err}`);
}
}
@@ -82,6 +84,7 @@ export class Cluster implements ClusterModel {
@action
async refreshStatus() {
await this.whenReady;
const connectionStatus = await this.getConnectionStatus();
this.online = connectionStatus > ClusterStatus.Offline;
this.accessible = connectionStatus == ClusterStatus.AccessGranted;
+5 -3
View File
@@ -35,7 +35,7 @@ async function main() {
const workingDir = path.join(app.getPath("appData"), appName);
app.setName(appName);
app.setPath("userData", workingDir);
logger.info(`Start app from "${workingDir}"`)
logger.info(`🚀 Starting Lens from "${workingDir}"`)
tracker.event("app", "start");
const updater = new AppUpdater()
@@ -75,12 +75,13 @@ async function main() {
// create window manager and open app
windowManager = new WindowManager();
// windowManager.showSplash();
windowManager.showSplash();
}
// Events
app.on("ready", main);
// fixme: never happens, Cmd+W doesn't work
app.on('window-all-closed', function () {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
@@ -98,9 +99,10 @@ app.on("activate", () => {
logger.debug("app:activate");
})
app.on("will-quit", async (event) => {
event.preventDefault(); // To allow mixpanel sending to be executed
if (clusterManager) clusterManager.stop()
if (proxyServer) proxyServer.close()
app.exit(0);
app.exit();
})
+65 -39
View File
@@ -3,35 +3,52 @@ import { BrowserWindow, shell } from "electron"
import windowStateKeeper from "electron-window-state"
import type { ClusterId } from "../common/cluster-store";
import { clusterStore } from "../common/cluster-store";
import logger from "./logger";
export class WindowManager {
protected activeView: BrowserWindow;
protected views = new Map<ClusterId, BrowserWindow>();
protected disposers: CallableFunction[] = [];
protected splashWindow: BrowserWindow;
protected windowState: windowStateKeeper.State;
protected disposers = [
// auto-destroy views for removed clusters
reaction(() => clusterStore.removedClusters.toJS(), removedClusters => {
removedClusters.forEach(cluster => {
this.destroyView(cluster.id);
});
})
];
constructor() {
this.splashWindow = new BrowserWindow({
width: 500,
height: 300,
backgroundColor: "#1e2124",
center: true,
frame: false,
resizable: false,
show: false,
});
protected splashWindow = new BrowserWindow({
width: 500,
height: 300,
backgroundColor: "#1e2124",
center: true,
frame: false,
resizable: false,
show: false,
});
// Manage main window size and position with state persistence
this.windowState = windowStateKeeper({
defaultHeight: 900,
defaultWidth: 1440,
});
// Manage main window size and position with state persistence
protected windowState = windowStateKeeper({
defaultHeight: 900,
defaultWidth: 1440,
});
// init events and show active cluster view
this.bindEvents();
}
protected bindEvents() {
this.disposers.push(
// auto-destroy views for removed clusters
reaction(() => clusterStore.removedClusters.toJS(), removedClusters => {
removedClusters.forEach(cluster => {
this.destroyView(cluster.id);
});
}),
// auto-show active cluster view
reaction(() => clusterStore.activeClusterId, clusterId => {
this.activateView(clusterId);
}, {
fireImmediately: true,
})
)
}
async showSplash() {
await this.splashWindow.loadURL("static://splash.html")
@@ -49,36 +66,45 @@ export class WindowManager {
async activateView(clusterId: ClusterId) {
const cluster = clusterStore.getById(clusterId);
if (!cluster) {
throw new Error(`Can't load lens for non-existing cluster="${clusterId}"`);
logger.error(`Can't show a view for non-existing cluster(${clusterId})`);
return;
}
const activeView = this.activeView;
const isFresh = !this.getView(clusterId);
const view = this.initView(clusterId);
if (view !== activeView) {
if (isFresh) {
await view.loadURL(cluster.webContentUrl);
try {
const activeView = this.activeView;
const isFresh = !this.getView(clusterId);
const view = this.initView(clusterId);
if (view !== activeView) {
if (isFresh) {
await cluster.whenReady;
await view.loadURL(cluster.webContentUrl);
}
if (activeView) {
view.setBounds(activeView.getBounds()); // refresh position and swap windows
activeView.hide();
}
view.show();
this.hideSplash();
this.activeView = view;
}
if (activeView) {
view.setBounds(activeView.getBounds()); // refresh position for "invisible swap"
activeView.hide();
}
view.show();
this.activeView = view;
} catch (err) {
logger.error(`Activating cluster(${clusterId}) view has failed: ${err.stack}`);
}
}
protected initView(clusterId: ClusterId) {
let view = this.getView(clusterId);
if (!view) {
const { width, height, x, y } = this.windowState;
view = new BrowserWindow({
show: false,
x: this.windowState.x,
y: this.windowState.y,
width: this.windowState.width,
height: this.windowState.height,
x: x, y: y,
width: width,
height: height,
titleBarStyle: "hidden",
backgroundColor: "#1e2124",
webPreferences: {
nodeIntegration: true,
enableRemoteModule: true,
},
});
// open external links in default browser (target=_blank, window.open)