mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
add no-unused and react/recommended to eslint (#1523)
* add no-unused-vars and no-unused-imports * added quotes: double, and remove ignore pattern * move itif and describeif into utils Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
1 parent
10eb082854
commit
7451869c25
199 files changed
+1178
-807
No files matched your search
@@ -146,7 +146,7 @@ describe("create clusters", () => {
|
||||
}
|
||||
}));
|
||||
|
||||
mockedRequest.mockImplementationOnce(((uri: any, _options: any) => {
|
||||
mockedRequest.mockImplementationOnce(((uri: any) => {
|
||||
expect(uri).toBe(`http://localhost:${port}/api-kube/version`);
|
||||
return Promise.resolve({ gitVersion: "1.2.3" });
|
||||
}) as any);
|
||||
|
||||
@@ -31,10 +31,10 @@ import { Cluster } from "../cluster";
|
||||
import { KubeAuthProxy } from "../kube-auth-proxy";
|
||||
import { getFreePort } from "../port";
|
||||
import { broadcastMessage } from "../../common/ipc";
|
||||
import { ChildProcess, spawn, SpawnOptions } from "child_process";
|
||||
import { ChildProcess, spawn } from "child_process";
|
||||
import { bundledKubectlPath, Kubectl } from "../kubectl";
|
||||
import { mock, MockProxy } from 'jest-mock-extended';
|
||||
import { waitUntilUsed } from 'tcp-port-used';
|
||||
import { mock, MockProxy } from "jest-mock-extended";
|
||||
import { waitUntilUsed } from "tcp-port-used";
|
||||
import { Readable } from "stream";
|
||||
|
||||
const mockBroadcastIpc = broadcastMessage as jest.MockedFunction<typeof broadcastMessage>;
|
||||
@@ -81,7 +81,7 @@ describe("kube auth proxy tests", () => {
|
||||
listeners[`stdout/${event}`] = listener;
|
||||
return mockedCP.stdout;
|
||||
});
|
||||
mockSpawn.mockImplementationOnce((command: string, args: readonly string[], options: SpawnOptions): ChildProcess => {
|
||||
mockSpawn.mockImplementationOnce((command: string): ChildProcess => {
|
||||
expect(command).toBe(bundledKubectlPath());
|
||||
return mockedCP;
|
||||
});
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ import { ContextHandler } from "./context-handler";
|
||||
import { AuthorizationV1Api, CoreV1Api, KubeConfig, V1ResourceAttributes } from "@kubernetes/client-node";
|
||||
import { Kubectl } from "./kubectl";
|
||||
import { KubeconfigManager } from "./kubeconfig-manager";
|
||||
import { getNodeWarningConditions, loadConfig, podHasIssues } from "../common/kube-helpers";
|
||||
import { loadConfig } from "../common/kube-helpers";
|
||||
import request, { RequestPromiseOptions } from "request-promise-native";
|
||||
import { apiResources } from "../common/rbac";
|
||||
import logger from "./logger";
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
* The dependency is not bundled to the production build.
|
||||
*/
|
||||
export const installDeveloperTools = async () => {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
const { default: devToolsInstaller, REACT_DEVELOPER_TOOLS } = await import('electron-devtools-installer');
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
const { default: devToolsInstaller, REACT_DEVELOPER_TOOLS } = await import("electron-devtools-installer");
|
||||
|
||||
return devToolsInstaller([REACT_DEVELOPER_TOOLS]);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ export function exitApp() {
|
||||
appEventBus.emit({ name: "service", action: "close" });
|
||||
windowManager.hide();
|
||||
clusterManager.stop();
|
||||
logger.info('SERVICE:QUIT');
|
||||
logger.info("SERVICE:QUIT");
|
||||
setTimeout(() => {
|
||||
app.exit();
|
||||
}, 1000);
|
||||
|
||||
@@ -36,10 +36,10 @@ export class HelmChartManager {
|
||||
public async getReadme(name: string, version = "") {
|
||||
const helm = await helmCli.binaryPath();
|
||||
if(version && version != "") {
|
||||
const { stdout, stderr} = await promiseExec(`"${helm}" show readme ${this.repo.name}/${name} --version ${version}`).catch((error) => { throw(error.stderr);});
|
||||
const { stdout } = await promiseExec(`"${helm}" show readme ${this.repo.name}/${name} --version ${version}`).catch((error) => { throw(error.stderr);});
|
||||
return stdout;
|
||||
} else {
|
||||
const { stdout, stderr} = await promiseExec(`"${helm}" show readme ${this.repo.name}/${name}`).catch((error) => { throw(error.stderr);});
|
||||
const { stdout } = await promiseExec(`"${helm}" show readme ${this.repo.name}/${name}`).catch((error) => { throw(error.stderr);});
|
||||
return stdout;
|
||||
}
|
||||
}
|
||||
@@ -47,11 +47,11 @@ export class HelmChartManager {
|
||||
public async getValues(name: string, version = "") {
|
||||
const helm = await helmCli.binaryPath();
|
||||
if(version && version != "") {
|
||||
const { stdout, stderr} = await promiseExec(`"${helm}" show values ${this.repo.name}/${name} --version ${version}`).catch((error) => { throw(error.stderr);});
|
||||
const { stdout } = await promiseExec(`"${helm}" show values ${this.repo.name}/${name} --version ${version}`).catch((error) => { throw(error.stderr);});
|
||||
|
||||
return stdout;
|
||||
} else {
|
||||
const { stdout, stderr} = await promiseExec(`"${helm}" show values ${this.repo.name}/${name}`).catch((error) => { throw(error.stderr);});
|
||||
const { stdout } = await promiseExec(`"${helm}" show values ${this.repo.name}/${name}`).catch((error) => { throw(error.stderr);});
|
||||
|
||||
return stdout;
|
||||
}
|
||||
@@ -59,12 +59,12 @@ export class HelmChartManager {
|
||||
|
||||
protected async cachedYaml(): Promise<CachedYaml> {
|
||||
if (!(this.repo.name in this.cache)) {
|
||||
const cacheFile = await fs.promises.readFile(this.repo.cacheFilePath, 'utf-8');
|
||||
const cacheFile = await fs.promises.readFile(this.repo.cacheFilePath, "utf-8");
|
||||
const data = yaml.safeLoad(cacheFile);
|
||||
for(const key in data["entries"]) {
|
||||
data["entries"][key].forEach((version: any) => {
|
||||
version['repo'] = this.repo.name;
|
||||
version['created'] = Date.parse(version.created).toString();
|
||||
version["repo"] = this.repo.name;
|
||||
version["created"] = Date.parse(version.created).toString();
|
||||
});
|
||||
}
|
||||
this.cache[this.repo.name] = Buffer.from(JSON.stringify(data));
|
||||
|
||||
@@ -34,8 +34,8 @@ export class HelmReleaseManager {
|
||||
generateName = "--generate-name";
|
||||
name = "";
|
||||
}
|
||||
const { stdout, stderr } = await promiseExec(`"${helm}" install ${name} ${chart} --version ${version} -f ${fileName} --namespace ${namespace} --kubeconfig ${pathToKubeconfig} ${generateName}`).catch((error) => { throw(error.stderr);});
|
||||
const releaseName = stdout.split("\n")[0].split(' ')[1].trim();
|
||||
const { stdout } = await promiseExec(`"${helm}" install ${name} ${chart} --version ${version} -f ${fileName} --namespace ${namespace} --kubeconfig ${pathToKubeconfig} ${generateName}`).catch((error) => { throw(error.stderr);});
|
||||
const releaseName = stdout.split("\n")[0].split(" ")[1].trim();
|
||||
return {
|
||||
log: stdout,
|
||||
release: {
|
||||
@@ -54,7 +54,7 @@ export class HelmReleaseManager {
|
||||
await fs.promises.writeFile(fileName, yaml.safeDump(values));
|
||||
|
||||
try {
|
||||
const { stdout, stderr } = await promiseExec(`"${helm}" upgrade ${name} ${chart} --version ${version} -f ${fileName} --namespace ${namespace} --kubeconfig ${cluster.getProxyKubeconfigPath()}`).catch((error) => { throw(error.stderr);});
|
||||
const { stdout } = await promiseExec(`"${helm}" upgrade ${name} ${chart} --version ${version} -f ${fileName} --namespace ${namespace} --kubeconfig ${cluster.getProxyKubeconfigPath()}`).catch((error) => { throw(error.stderr);});
|
||||
return {
|
||||
log: stdout,
|
||||
release: this.getRelease(name, namespace, cluster)
|
||||
@@ -66,7 +66,7 @@ export class HelmReleaseManager {
|
||||
|
||||
public async getRelease(name: string, namespace: string, cluster: Cluster) {
|
||||
const helm = await helmCli.binaryPath();
|
||||
const {stdout, stderr} = await promiseExec(`"${helm}" status ${name} --output json --namespace ${namespace} --kubeconfig ${cluster.getProxyKubeconfigPath()}`).catch((error) => { throw(error.stderr);});
|
||||
const { stdout } = await promiseExec(`"${helm}" status ${name} --output json --namespace ${namespace} --kubeconfig ${cluster.getProxyKubeconfigPath()}`).catch((error) => { throw(error.stderr);});
|
||||
const release = JSON.parse(stdout);
|
||||
release.resources = await this.getResources(name, namespace, cluster);
|
||||
return release;
|
||||
@@ -74,26 +74,26 @@ export class HelmReleaseManager {
|
||||
|
||||
public async deleteRelease(name: string, namespace: string, pathToKubeconfig: string) {
|
||||
const helm = await helmCli.binaryPath();
|
||||
const { stdout, stderr } = await promiseExec(`"${helm}" delete ${name} --namespace ${namespace} --kubeconfig ${pathToKubeconfig}`).catch((error) => { throw(error.stderr);});
|
||||
const { stdout } = await promiseExec(`"${helm}" delete ${name} --namespace ${namespace} --kubeconfig ${pathToKubeconfig}`).catch((error) => { throw(error.stderr);});
|
||||
|
||||
return stdout;
|
||||
}
|
||||
|
||||
public async getValues(name: string, namespace: string, pathToKubeconfig: string) {
|
||||
const helm = await helmCli.binaryPath();
|
||||
const { stdout, stderr } = await promiseExec(`"${helm}" get values ${name} --all --output yaml --namespace ${namespace} --kubeconfig ${pathToKubeconfig}`).catch((error) => { throw(error.stderr);});
|
||||
const { stdout, } = await promiseExec(`"${helm}" get values ${name} --all --output yaml --namespace ${namespace} --kubeconfig ${pathToKubeconfig}`).catch((error) => { throw(error.stderr);});
|
||||
return stdout;
|
||||
}
|
||||
|
||||
public async getHistory(name: string, namespace: string, pathToKubeconfig: string) {
|
||||
const helm = await helmCli.binaryPath();
|
||||
const {stdout, stderr} = await promiseExec(`"${helm}" history ${name} --output json --namespace ${namespace} --kubeconfig ${pathToKubeconfig}`).catch((error) => { throw(error.stderr);});
|
||||
const { stdout } = await promiseExec(`"${helm}" history ${name} --output json --namespace ${namespace} --kubeconfig ${pathToKubeconfig}`).catch((error) => { throw(error.stderr);});
|
||||
return JSON.parse(stdout);
|
||||
}
|
||||
|
||||
public async rollback(name: string, namespace: string, revision: number, pathToKubeconfig: string) {
|
||||
const helm = await helmCli.binaryPath();
|
||||
const {stdout, stderr} = await promiseExec(`"${helm}" rollback ${name} ${revision} --namespace ${namespace} --kubeconfig ${pathToKubeconfig}`).catch((error) => { throw(error.stderr);});
|
||||
const { stdout } = await promiseExec(`"${helm}" rollback ${name} ${revision} --namespace ${namespace} --kubeconfig ${pathToKubeconfig}`).catch((error) => { throw(error.stderr);});
|
||||
return stdout;
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ export class HelmReleaseManager {
|
||||
const helm = await helmCli.binaryPath();
|
||||
const kubectl = await cluster.kubeCtl.getPath();
|
||||
const pathToKubeconfig = cluster.getProxyKubeconfigPath();
|
||||
const { stdout } = await promiseExec(`"${helm}" get manifest ${name} --namespace ${namespace} --kubeconfig ${pathToKubeconfig} | "${kubectl}" get -n ${namespace} --kubeconfig ${pathToKubeconfig} -f - -o=json`).catch((error) => {
|
||||
const { stdout } = await promiseExec(`"${helm}" get manifest ${name} --namespace ${namespace} --kubeconfig ${pathToKubeconfig} | "${kubectl}" get -n ${namespace} --kubeconfig ${pathToKubeconfig} -f - -o=json`).catch(() => {
|
||||
return { stdout: JSON.stringify({items: []})};
|
||||
});
|
||||
return stdout;
|
||||
|
||||
@@ -77,7 +77,7 @@ export class HelmRepoManager extends Singleton {
|
||||
}
|
||||
try {
|
||||
const repoConfigFile = this.helmEnv.HELM_REPOSITORY_CONFIG;
|
||||
const { repositories }: HelmRepoConfig = await readFile(repoConfigFile, 'utf8')
|
||||
const { repositories }: HelmRepoConfig = await readFile(repoConfigFile, "utf8")
|
||||
.then((yamlContent: string) => yaml.safeLoad(yamlContent))
|
||||
.catch(() => ({
|
||||
repositories: []
|
||||
@@ -121,7 +121,7 @@ export class HelmRepoManager extends Singleton {
|
||||
public async removeRepo({ name, url }: HelmRepo): Promise<string> {
|
||||
logger.info(`[HELM]: removing repo "${name}" from ${url}`);
|
||||
const helm = await helmCli.binaryPath();
|
||||
const { stdout, stderr } = await promiseExec(`"${helm}" repo remove ${name}`).catch((error) => {
|
||||
const { stdout } = await promiseExec(`"${helm}" repo remove ${name}`).catch((error) => {
|
||||
throw(error.stderr);
|
||||
});
|
||||
return stdout;
|
||||
|
||||
@@ -85,7 +85,7 @@ class HelmService {
|
||||
for (const key in entries) {
|
||||
entries[key] = entries[key].filter((entry: any) => {
|
||||
if (Array.isArray(entry)) {
|
||||
return entry[0]['deprecated'] != true;
|
||||
return entry[0]["deprecated"] != true;
|
||||
}
|
||||
return entry["deprecated"] != true;
|
||||
});
|
||||
|
||||
+3
-2
@@ -77,6 +77,7 @@ app.on("ready", async () => {
|
||||
|
||||
// run proxy
|
||||
try {
|
||||
// eslint-disable-next-line unused-imports/no-unused-vars-ts
|
||||
proxyServer = LensProxy.create(proxyPort, clusterManager);
|
||||
} catch (error) {
|
||||
logger.error(`Could not start proxy (127.0.0:${proxyPort}): ${error.message}`);
|
||||
@@ -108,7 +109,7 @@ app.on("ready", async () => {
|
||||
});
|
||||
|
||||
app.on("activate", (event, hasVisibleWindows) => {
|
||||
logger.info('APP:ACTIVATE', { hasVisibleWindows });
|
||||
logger.info("APP:ACTIVATE", { hasVisibleWindows });
|
||||
if (!hasVisibleWindows) {
|
||||
windowManager.initMainWindow();
|
||||
}
|
||||
@@ -116,7 +117,7 @@ app.on("activate", (event, hasVisibleWindows) => {
|
||||
|
||||
// Quit app on Cmd+Q (MacOS)
|
||||
app.on("will-quit", (event) => {
|
||||
logger.info('APP:QUIT');
|
||||
logger.info("APP:QUIT");
|
||||
appEventBus.emit({name: "app", action: "close"});
|
||||
event.preventDefault(); // prevent app's default shutdown (e.g. required for telemetry, etc.)
|
||||
clusterManager?.stop(); // close cluster connections
|
||||
|
||||
@@ -60,7 +60,7 @@ export class KubeAuthProxy {
|
||||
this.exit();
|
||||
});
|
||||
|
||||
this.proxyProcess.stdout.on('data', (data) => {
|
||||
this.proxyProcess.stdout.on("data", (data) => {
|
||||
let logItem = data.toString();
|
||||
if (logItem.startsWith("Starting to serve on")) {
|
||||
logItem = "Authentication proxy started\n";
|
||||
@@ -68,7 +68,7 @@ export class KubeAuthProxy {
|
||||
this.sendIpcLogMessage({ data: logItem });
|
||||
});
|
||||
|
||||
this.proxyProcess.stderr.on('data', (data) => {
|
||||
this.proxyProcess.stderr.on("data", (data) => {
|
||||
this.lastError = this.parseError(data.toString());
|
||||
this.sendIpcLogMessage({ data: data.toString(), error: true });
|
||||
});
|
||||
|
||||
@@ -41,7 +41,7 @@ export class KubeconfigManager {
|
||||
* This way any user of the config does not need to know anything about the auth etc. details.
|
||||
*/
|
||||
protected async createProxyKubeconfig(): Promise<string> {
|
||||
const { configDir, cluster, contextHandler } = this;
|
||||
const { configDir, cluster } = this;
|
||||
const { contextName, kubeConfigPath, id } = cluster;
|
||||
const tempFile = path.join(configDir, `kubeconfig-${id}`);
|
||||
const kubeConfig = loadConfig(kubeConfigPath);
|
||||
@@ -81,7 +81,7 @@ export class KubeconfigManager {
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info('Deleting temporary kubeconfig: ' + this.tempFile);
|
||||
logger.info("Deleting temporary kubeconfig: " + this.tempFile);
|
||||
await fs.unlink(this.tempFile);
|
||||
this.tempFile = undefined;
|
||||
}
|
||||
|
||||
+7
-3
@@ -123,6 +123,10 @@ export class Kubectl {
|
||||
}
|
||||
|
||||
public async getPath(bundled = false): Promise<string> {
|
||||
if (bundled) {
|
||||
return this.getBundledPath();
|
||||
}
|
||||
|
||||
if (userStore.preferences?.downloadKubectlBinaries === false) {
|
||||
return this.getPathFromPreferences();
|
||||
}
|
||||
@@ -167,7 +171,7 @@ export class Kubectl {
|
||||
return true;
|
||||
}
|
||||
let version: string = output.clientVersion.gitVersion;
|
||||
if (version[0] === 'v') {
|
||||
if (version[0] === "v") {
|
||||
version = version.slice(1);
|
||||
}
|
||||
if (version === this.kubectlVersion) {
|
||||
@@ -274,7 +278,7 @@ export class Kubectl {
|
||||
const kubectlPath = userStore.preferences?.downloadKubectlBinaries ? this.dirname : path.dirname(this.getPathFromPreferences());
|
||||
const helmPath = helmCli.getBinaryDir();
|
||||
const fsPromises = fs.promises;
|
||||
const bashScriptPath = path.join(this.dirname, '.bash_set_path');
|
||||
const bashScriptPath = path.join(this.dirname, ".bash_set_path");
|
||||
|
||||
let bashScript = "" + initScriptVersionString;
|
||||
bashScript += "tempkubeconfig=\"$KUBECONFIG\"\n";
|
||||
@@ -297,7 +301,7 @@ export class Kubectl {
|
||||
bashScript += "unset tempkubeconfig\n";
|
||||
await fsPromises.writeFile(bashScriptPath, bashScript.toString(), { mode: 0o644 });
|
||||
|
||||
const zshScriptPath = path.join(this.dirname, '.zlogin');
|
||||
const zshScriptPath = path.join(this.dirname, ".zlogin");
|
||||
|
||||
let zshScript = "" + initScriptVersionString;
|
||||
|
||||
|
||||
@@ -121,12 +121,12 @@ export class LensBinary {
|
||||
}
|
||||
|
||||
protected async untarBinary() {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
return new Promise<void>(resolve => {
|
||||
this.logger.debug(`Extracting ${this.originalBinaryName} binary`);
|
||||
tar.x({
|
||||
file: this.tarPath,
|
||||
cwd: this.dirname
|
||||
}).then((_ => {
|
||||
}).then((() => {
|
||||
resolve();
|
||||
}));
|
||||
});
|
||||
|
||||
@@ -88,23 +88,23 @@ export class LensProxy {
|
||||
proxySocket.setTimeout(0);
|
||||
socket.setTimeout(0);
|
||||
|
||||
proxySocket.on('data', function (chunk) {
|
||||
proxySocket.on("data", function (chunk) {
|
||||
socket.write(chunk);
|
||||
});
|
||||
proxySocket.on('end', function () {
|
||||
proxySocket.on("end", function () {
|
||||
socket.end();
|
||||
});
|
||||
proxySocket.on('error', function (err) {
|
||||
proxySocket.on("error", function () {
|
||||
socket.write("HTTP/" + req.httpVersion + " 500 Connection error\r\n\r\n");
|
||||
socket.end();
|
||||
});
|
||||
socket.on('data', function (chunk) {
|
||||
socket.on("data", function (chunk) {
|
||||
proxySocket.write(chunk);
|
||||
});
|
||||
socket.on('end', function () {
|
||||
socket.on("end", function () {
|
||||
proxySocket.end();
|
||||
});
|
||||
socket.on('error', function () {
|
||||
socket.on("error", function () {
|
||||
proxySocket.end();
|
||||
});
|
||||
}
|
||||
|
||||
+55
-55
@@ -65,31 +65,31 @@ export function buildMenu(windowManager: WindowManager) {
|
||||
showAbout(browserWindow);
|
||||
}
|
||||
},
|
||||
{ type: 'separator' },
|
||||
{ type: "separator" },
|
||||
{
|
||||
label: 'Preferences',
|
||||
accelerator: 'CmdOrCtrl+,',
|
||||
label: "Preferences",
|
||||
accelerator: "CmdOrCtrl+,",
|
||||
click() {
|
||||
navigate(preferencesURL());
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Extensions',
|
||||
accelerator: 'CmdOrCtrl+Shift+E',
|
||||
label: "Extensions",
|
||||
accelerator: "CmdOrCtrl+Shift+E",
|
||||
click() {
|
||||
navigate(extensionsURL());
|
||||
}
|
||||
},
|
||||
{ type: 'separator' },
|
||||
{ role: 'services' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'hide' },
|
||||
{ role: 'hideOthers' },
|
||||
{ role: 'unhide' },
|
||||
{ type: 'separator' },
|
||||
{ type: "separator" },
|
||||
{ role: "services" },
|
||||
{ type: "separator" },
|
||||
{ role: "hide" },
|
||||
{ role: "hideOthers" },
|
||||
{ role: "unhide" },
|
||||
{ type: "separator" },
|
||||
{
|
||||
label: 'Quit',
|
||||
accelerator: 'Cmd+Q',
|
||||
label: "Quit",
|
||||
accelerator: "Cmd+Q",
|
||||
click() {
|
||||
exitApp();
|
||||
}
|
||||
@@ -101,16 +101,16 @@ export function buildMenu(windowManager: WindowManager) {
|
||||
label: "File",
|
||||
submenu: [
|
||||
{
|
||||
label: 'Add Cluster',
|
||||
accelerator: 'CmdOrCtrl+Shift+A',
|
||||
label: "Add Cluster",
|
||||
accelerator: "CmdOrCtrl+Shift+A",
|
||||
click() {
|
||||
navigate(addClusterURL());
|
||||
}
|
||||
},
|
||||
...activeClusterOnly([
|
||||
{
|
||||
label: 'Cluster Settings',
|
||||
accelerator: 'CmdOrCtrl+Shift+S',
|
||||
label: "Cluster Settings",
|
||||
accelerator: "CmdOrCtrl+Shift+S",
|
||||
click() {
|
||||
navigate(clusterSettingsURL({
|
||||
params: {
|
||||
@@ -121,32 +121,32 @@ export function buildMenu(windowManager: WindowManager) {
|
||||
}
|
||||
]),
|
||||
...ignoreOnMac([
|
||||
{ type: 'separator' },
|
||||
{ type: "separator" },
|
||||
{
|
||||
label: 'Preferences',
|
||||
accelerator: 'Ctrl+,',
|
||||
label: "Preferences",
|
||||
accelerator: "Ctrl+,",
|
||||
click() {
|
||||
navigate(preferencesURL());
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Extensions',
|
||||
accelerator: 'Ctrl+Shift+E',
|
||||
label: "Extensions",
|
||||
accelerator: "Ctrl+Shift+E",
|
||||
click() {
|
||||
navigate(extensionsURL());
|
||||
}
|
||||
}
|
||||
]),
|
||||
{ type: 'separator' },
|
||||
{ type: "separator" },
|
||||
{
|
||||
role: 'close',
|
||||
role: "close",
|
||||
label: "Close Window"
|
||||
},
|
||||
...ignoreOnMac([
|
||||
{ type: 'separator' },
|
||||
{ type: "separator" },
|
||||
{
|
||||
label: 'Exit',
|
||||
accelerator: 'Alt+F4',
|
||||
label: "Exit",
|
||||
accelerator: "Alt+F4",
|
||||
click() {
|
||||
exitApp();
|
||||
}
|
||||
@@ -156,56 +156,56 @@ export function buildMenu(windowManager: WindowManager) {
|
||||
};
|
||||
|
||||
const editMenu: MenuItemConstructorOptions = {
|
||||
label: 'Edit',
|
||||
label: "Edit",
|
||||
submenu: [
|
||||
{ role: 'undo' },
|
||||
{ role: 'redo' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'cut' },
|
||||
{ role: 'copy' },
|
||||
{ role: 'paste' },
|
||||
{ role: 'delete' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'selectAll' },
|
||||
{ role: "undo" },
|
||||
{ role: "redo" },
|
||||
{ type: "separator" },
|
||||
{ role: "cut" },
|
||||
{ role: "copy" },
|
||||
{ role: "paste" },
|
||||
{ role: "delete" },
|
||||
{ type: "separator" },
|
||||
{ role: "selectAll" },
|
||||
]
|
||||
};
|
||||
|
||||
const viewMenu: MenuItemConstructorOptions = {
|
||||
label: 'View',
|
||||
label: "View",
|
||||
submenu: [
|
||||
{
|
||||
label: 'Back',
|
||||
accelerator: 'CmdOrCtrl+[',
|
||||
label: "Back",
|
||||
accelerator: "CmdOrCtrl+[",
|
||||
click() {
|
||||
webContents.getFocusedWebContents()?.goBack();
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Forward',
|
||||
accelerator: 'CmdOrCtrl+]',
|
||||
label: "Forward",
|
||||
accelerator: "CmdOrCtrl+]",
|
||||
click() {
|
||||
webContents.getFocusedWebContents()?.goForward();
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Reload',
|
||||
accelerator: 'CmdOrCtrl+R',
|
||||
label: "Reload",
|
||||
accelerator: "CmdOrCtrl+R",
|
||||
click() {
|
||||
windowManager.reload();
|
||||
}
|
||||
},
|
||||
{ role: 'toggleDevTools' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'resetZoom' },
|
||||
{ role: 'zoomIn' },
|
||||
{ role: 'zoomOut' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'togglefullscreen' }
|
||||
{ role: "toggleDevTools" },
|
||||
{ type: "separator" },
|
||||
{ role: "resetZoom" },
|
||||
{ role: "zoomIn" },
|
||||
{ role: "zoomOut" },
|
||||
{ type: "separator" },
|
||||
{ role: "togglefullscreen" }
|
||||
]
|
||||
};
|
||||
|
||||
const helpMenu: MenuItemConstructorOptions = {
|
||||
role: 'help',
|
||||
role: "help",
|
||||
submenu: [
|
||||
{
|
||||
label: "What's new?",
|
||||
@@ -265,7 +265,7 @@ export function buildMenu(windowManager: WindowManager) {
|
||||
if (isTestEnv) {
|
||||
// this is a workaround for the test environment (spectron) not being able to directly access
|
||||
// the application menus (https://github.com/electron-userland/spectron/issues/21)
|
||||
ipcMain.on('test-menu-item-click', (event: IpcMainEvent, ...names: string[]) => {
|
||||
ipcMain.on("test-menu-item-click", (event: IpcMainEvent, ...names: string[]) => {
|
||||
let menu: Menu = Menu.getApplicationMenu();
|
||||
const parentLabels: string[] = [];
|
||||
let menuItem: MenuItem;
|
||||
@@ -286,7 +286,7 @@ export function buildMenu(windowManager: WindowManager) {
|
||||
}
|
||||
|
||||
const { enabled, visible, click } = menuItem;
|
||||
if (enabled === false || visible === false || typeof click !== 'function') {
|
||||
if (enabled === false || visible === false || typeof click !== "function") {
|
||||
logger.info(`[MENU:test-menu-item-click] Menu item ${menuPath} not clickable`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ export class NodeShellSession extends ShellSession {
|
||||
const shell = await this.kubectl.getPath();
|
||||
let args = [];
|
||||
if (this.createNodeShellPod(this.podId, this.nodeName)) {
|
||||
await this.waitForRunningPod(this.podId).catch((error) => {
|
||||
await this.waitForRunningPod(this.podId).catch(() => {
|
||||
this.exit(1001);
|
||||
});
|
||||
}
|
||||
@@ -108,7 +108,7 @@ export class NodeShellSession extends ShellSession {
|
||||
|
||||
const req = await watch.watch(`/api/v1/namespaces/kube-system/pods`, {},
|
||||
// callback is called for each received object.
|
||||
(_type, obj) => {
|
||||
(type, obj) => {
|
||||
if (obj.metadata.name == podId && obj.status.phase === "Running") {
|
||||
resolve(true);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { EventEmitter } from 'events';
|
||||
import { EventEmitter } from "events";
|
||||
import { getFreePort } from "./port";
|
||||
|
||||
let newPort = 0;
|
||||
@@ -8,7 +8,7 @@ jest.mock("net", () => {
|
||||
createServer() {
|
||||
return new class MockServer extends EventEmitter {
|
||||
listen = jest.fn(() => {
|
||||
this.emit('listening');
|
||||
this.emit("listening");
|
||||
return this;
|
||||
});
|
||||
address = () => {
|
||||
|
||||
@@ -24,7 +24,7 @@ export class PrometheusLens implements PrometheusProvider {
|
||||
|
||||
public getQueries(opts: PrometheusQueryOpts): PrometheusQuery {
|
||||
switch(opts.category) {
|
||||
case 'cluster':
|
||||
case "cluster":
|
||||
return {
|
||||
memoryUsage: `
|
||||
sum(
|
||||
@@ -43,7 +43,7 @@ export class PrometheusLens implements PrometheusProvider {
|
||||
fsSize: `sum(node_filesystem_size_bytes{kubernetes_node=~"${opts.nodes}", mountpoint="/"}) by (kubernetes_node)`,
|
||||
fsUsage: `sum(node_filesystem_size_bytes{kubernetes_node=~"${opts.nodes}", mountpoint="/"} - node_filesystem_avail_bytes{kubernetes_node=~"${opts.nodes}", mountpoint="/"}) by (kubernetes_node)`
|
||||
};
|
||||
case 'nodes':
|
||||
case "nodes":
|
||||
return {
|
||||
memoryUsage: `sum (node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) by (kubernetes_node)`,
|
||||
memoryCapacity: `sum(kube_node_status_capacity{resource="memory"}) by (node)`,
|
||||
@@ -52,7 +52,7 @@ export class PrometheusLens implements PrometheusProvider {
|
||||
fsSize: `sum(node_filesystem_size_bytes{mountpoint="/"}) by (kubernetes_node)`,
|
||||
fsUsage: `sum(node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_avail_bytes{mountpoint="/"}) by (kubernetes_node)`
|
||||
};
|
||||
case 'pods':
|
||||
case "pods":
|
||||
return {
|
||||
cpuUsage: `sum(rate(container_cpu_usage_seconds_total{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`,
|
||||
cpuRequests: `sum(kube_pod_container_resource_requests{pod=~"${opts.pods}",resource="cpu",namespace="${opts.namespace}"}) by (${opts.selector})`,
|
||||
@@ -64,12 +64,12 @@ export class PrometheusLens implements PrometheusProvider {
|
||||
networkReceive: `sum(rate(container_network_receive_bytes_total{pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`,
|
||||
networkTransmit: `sum(rate(container_network_transmit_bytes_total{pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`
|
||||
};
|
||||
case 'pvc':
|
||||
case "pvc":
|
||||
return {
|
||||
diskUsage: `sum(kubelet_volume_stats_used_bytes{persistentvolumeclaim="${opts.pvc}"}) by (persistentvolumeclaim, namespace)`,
|
||||
diskCapacity: `sum(kubelet_volume_stats_capacity_bytes{persistentvolumeclaim="${opts.pvc}"}) by (persistentvolumeclaim, namespace)`
|
||||
};
|
||||
case 'ingress':
|
||||
case "ingress":
|
||||
const bytesSent = (ingress: string, statuses: string) =>
|
||||
`sum(rate(nginx_ingress_controller_bytes_sent_sum{ingress="${ingress}", status=~"${statuses}"}[${this.rateAccuracy}])) by (ingress)`;
|
||||
return {
|
||||
|
||||
@@ -32,7 +32,7 @@ export class PrometheusOperator implements PrometheusProvider {
|
||||
|
||||
public getQueries(opts: PrometheusQueryOpts): PrometheusQuery {
|
||||
switch(opts.category) {
|
||||
case 'cluster':
|
||||
case "cluster":
|
||||
return {
|
||||
memoryUsage: `
|
||||
sum(
|
||||
@@ -51,7 +51,7 @@ export class PrometheusOperator implements PrometheusProvider {
|
||||
fsSize: `sum(node_filesystem_size_bytes{mountpoint="/"} * on (pod,namespace) group_left(node) kube_pod_info{node=~"${opts.nodes}"})`,
|
||||
fsUsage: `sum(node_filesystem_size_bytes{mountpoint="/"} * on (pod,namespace) group_left(node) kube_pod_info{node=~"${opts.nodes}"} - node_filesystem_avail_bytes{mountpoint="/"} * on (pod,namespace) group_left(node) kube_pod_info{node=~"${opts.nodes}"})`
|
||||
};
|
||||
case 'nodes':
|
||||
case "nodes":
|
||||
return {
|
||||
memoryUsage: `sum((node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) * on (pod,namespace) group_left(node) kube_pod_info) by (node)`,
|
||||
memoryCapacity: `sum(kube_node_status_capacity{resource="memory"}) by (node)`,
|
||||
@@ -60,7 +60,7 @@ export class PrometheusOperator implements PrometheusProvider {
|
||||
fsSize: `sum(node_filesystem_size_bytes{mountpoint="/"} * on (pod,namespace) group_left(node) kube_pod_info) by (node)`,
|
||||
fsUsage: `sum((node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_avail_bytes{mountpoint="/"}) * on (pod,namespace) group_left(node) kube_pod_info) by (node)`
|
||||
};
|
||||
case 'pods':
|
||||
case "pods":
|
||||
return {
|
||||
cpuUsage: `sum(rate(container_cpu_usage_seconds_total{container!="POD",container!="",image!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`,
|
||||
cpuRequests: `sum(kube_pod_container_resource_requests{pod=~"${opts.pods}",resource="cpu",namespace="${opts.namespace}"}) by (${opts.selector})`,
|
||||
@@ -72,12 +72,12 @@ export class PrometheusOperator implements PrometheusProvider {
|
||||
networkReceive: `sum(rate(container_network_receive_bytes_total{pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`,
|
||||
networkTransmit: `sum(rate(container_network_transmit_bytes_total{pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`
|
||||
};
|
||||
case 'pvc':
|
||||
case "pvc":
|
||||
return {
|
||||
diskUsage: `sum(kubelet_volume_stats_used_bytes{persistentvolumeclaim="${opts.pvc}"}) by (persistentvolumeclaim, namespace)`,
|
||||
diskCapacity: `sum(kubelet_volume_stats_capacity_bytes{persistentvolumeclaim="${opts.pvc}"}) by (persistentvolumeclaim, namespace)`
|
||||
};
|
||||
case 'ingress':
|
||||
case "ingress":
|
||||
const bytesSent = (ingress: string, statuses: string) =>
|
||||
`sum(rate(nginx_ingress_controller_bytes_sent_sum{ingress="${ingress}", status=~"${statuses}"}[${this.rateAccuracy}])) by (ingress)`;
|
||||
return {
|
||||
|
||||
@@ -24,7 +24,7 @@ export class PrometheusStacklight implements PrometheusProvider {
|
||||
|
||||
public getQueries(opts: PrometheusQueryOpts): PrometheusQuery {
|
||||
switch(opts.category) {
|
||||
case 'cluster':
|
||||
case "cluster":
|
||||
return {
|
||||
memoryUsage: `
|
||||
sum(
|
||||
@@ -43,7 +43,7 @@ export class PrometheusStacklight implements PrometheusProvider {
|
||||
fsSize: `sum(node_filesystem_size_bytes{node=~"${opts.nodes}", mountpoint="/"}) by (node)`,
|
||||
fsUsage: `sum(node_filesystem_size_bytes{node=~"${opts.nodes}", mountpoint="/"} - node_filesystem_avail_bytes{node=~"${opts.nodes}", mountpoint="/"}) by (node)`
|
||||
};
|
||||
case 'nodes':
|
||||
case "nodes":
|
||||
return {
|
||||
memoryUsage: `sum (node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) by (node)`,
|
||||
memoryCapacity: `sum(kube_node_status_capacity{resource="memory"}) by (node)`,
|
||||
@@ -52,7 +52,7 @@ export class PrometheusStacklight implements PrometheusProvider {
|
||||
fsSize: `sum(node_filesystem_size_bytes{mountpoint="/"}) by (node)`,
|
||||
fsUsage: `sum(node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_avail_bytes{mountpoint="/"}) by (node)`
|
||||
};
|
||||
case 'pods':
|
||||
case "pods":
|
||||
return {
|
||||
cpuUsage: `sum(rate(container_cpu_usage_seconds_total{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`,
|
||||
cpuRequests: `sum(kube_pod_container_resource_requests{pod=~"${opts.pods}",resource="cpu",namespace="${opts.namespace}"}) by (${opts.selector})`,
|
||||
@@ -64,12 +64,12 @@ export class PrometheusStacklight implements PrometheusProvider {
|
||||
networkReceive: `sum(rate(container_network_receive_bytes_total{pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`,
|
||||
networkTransmit: `sum(rate(container_network_transmit_bytes_total{pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`
|
||||
};
|
||||
case 'pvc':
|
||||
case "pvc":
|
||||
return {
|
||||
diskUsage: `sum(kubelet_volume_stats_used_bytes{persistentvolumeclaim="${opts.pvc}"}) by (persistentvolumeclaim, namespace)`,
|
||||
diskCapacity: `sum(kubelet_volume_stats_capacity_bytes{persistentvolumeclaim="${opts.pvc}"}) by (persistentvolumeclaim, namespace)`
|
||||
};
|
||||
case 'ingress':
|
||||
case "ingress":
|
||||
const bytesSent = (ingress: string, statuses: string) =>
|
||||
`sum(rate(nginx_ingress_controller_bytes_sent_sum{ingress="${ingress}", status=~"${statuses}"}[${this.rateAccuracy}])) by (ingress)`;
|
||||
return {
|
||||
|
||||
@@ -75,7 +75,7 @@ export class ResourceApplier {
|
||||
delete resource.metadata?.resourceVersion;
|
||||
const annotations = resource.metadata?.annotations;
|
||||
if (annotations) {
|
||||
delete annotations['kubectl.kubernetes.io/last-applied-configuration'];
|
||||
delete annotations["kubectl.kubernetes.io/last-applied-configuration"];
|
||||
}
|
||||
return resource;
|
||||
}
|
||||
|
||||
+4
-4
@@ -100,11 +100,11 @@ export class Router {
|
||||
try {
|
||||
const filename = path.basename(req.url);
|
||||
// redirect requests to [appName].js, [appName].html /sockjs-node/ to webpack-dev-server (for hot-reload support)
|
||||
const toWebpackDevServer = filename.includes(appName) || filename.includes('hot-update') || req.url.includes('sockjs-node');
|
||||
const toWebpackDevServer = filename.includes(appName) || filename.includes("hot-update") || req.url.includes("sockjs-node");
|
||||
if (isDevelopment && toWebpackDevServer) {
|
||||
const redirectLocation = `http://localhost:${webpackDevServerPort}` + req.url;
|
||||
res.statusCode = 307;
|
||||
res.setHeader('Location', redirectLocation);
|
||||
res.setHeader("Location", redirectLocation);
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
@@ -126,8 +126,8 @@ export class Router {
|
||||
protected addRoutes() {
|
||||
// Static assets
|
||||
this.router.add(
|
||||
{ method: 'get', path: '/{path*}' },
|
||||
({ params, response, path, raw: { req } }: LensApiRequest) => {
|
||||
{ method: "get", path: "/{path*}" },
|
||||
({ params, response, raw: { req } }: LensApiRequest) => {
|
||||
this.handleStaticFile(params.path, response, req);
|
||||
});
|
||||
|
||||
|
||||
@@ -6,36 +6,36 @@ import { CoreV1Api, V1Secret } from "@kubernetes/client-node";
|
||||
function generateKubeConfig(username: string, secret: V1Secret, cluster: Cluster) {
|
||||
const tokenData = Buffer.from(secret.data["token"], "base64");
|
||||
return {
|
||||
'apiVersion': 'v1',
|
||||
'kind': 'Config',
|
||||
'clusters': [
|
||||
"apiVersion": "v1",
|
||||
"kind": "Config",
|
||||
"clusters": [
|
||||
{
|
||||
'name': cluster.contextName,
|
||||
'cluster': {
|
||||
'server': cluster.apiUrl,
|
||||
'certificate-authority-data': secret.data["ca.crt"]
|
||||
"name": cluster.contextName,
|
||||
"cluster": {
|
||||
"server": cluster.apiUrl,
|
||||
"certificate-authority-data": secret.data["ca.crt"]
|
||||
}
|
||||
}
|
||||
],
|
||||
'users': [
|
||||
"users": [
|
||||
{
|
||||
'name': username,
|
||||
'user': {
|
||||
'token': tokenData.toString("utf8"),
|
||||
"name": username,
|
||||
"user": {
|
||||
"token": tokenData.toString("utf8"),
|
||||
}
|
||||
}
|
||||
],
|
||||
'contexts': [
|
||||
"contexts": [
|
||||
{
|
||||
'name': cluster.contextName,
|
||||
'context': {
|
||||
'user': username,
|
||||
'cluster': cluster.contextName,
|
||||
'namespace': secret.metadata.namespace,
|
||||
"name": cluster.contextName,
|
||||
"context": {
|
||||
"user": username,
|
||||
"cluster": cluster.contextName,
|
||||
"namespace": secret.metadata.namespace,
|
||||
}
|
||||
}
|
||||
],
|
||||
'current-context': cluster.contextName
|
||||
"current-context": cluster.contextName
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ class ApiWatcher {
|
||||
class WatchRoute extends LensApi {
|
||||
|
||||
public async routeWatch(request: LensApiRequest) {
|
||||
const { params, response, cluster} = request;
|
||||
const { response, cluster} = request;
|
||||
const apis: string[] = request.query.getAll("api");
|
||||
const watchers: ApiWatcher[] = [];
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ export class ShellSession extends EventEmitter {
|
||||
case "powershell.exe":
|
||||
return ["-NoExit", "-command", `& {Set-Location $Env:USERPROFILE; $Env:PATH="${this.helmBinDir};${this.kubectlPathDir};$Env:PATH"}`];
|
||||
case "bash":
|
||||
return ["--init-file", path.join(this.kubectlBinDir, '.bash_set_path')];
|
||||
return ["--init-file", path.join(this.kubectlBinDir, ".bash_set_path")];
|
||||
case "fish":
|
||||
return ["--login", "--init-command", `export PATH="${this.helmBinDir}:${this.kubectlPathDir}:$PATH"; export KUBECONFIG="${this.kubeconfigPath}"`];
|
||||
case "zsh":
|
||||
@@ -156,7 +156,7 @@ export class ShellSession extends EventEmitter {
|
||||
this.shellProcess.resize(resizeMsgObj["Width"], resizeMsgObj["Height"]);
|
||||
break;
|
||||
case "9":
|
||||
this.emit('newToken', message);
|
||||
this.emit("newToken", message);
|
||||
break;
|
||||
}
|
||||
});
|
||||
@@ -164,7 +164,7 @@ export class ShellSession extends EventEmitter {
|
||||
|
||||
protected exit(code = 1000) {
|
||||
if (this.websocket.readyState == this.websocket.OPEN) this.websocket.close(code);
|
||||
this.emit('exit');
|
||||
this.emit("exit");
|
||||
}
|
||||
|
||||
protected closeWebsocketOnProcessExit() {
|
||||
|
||||
@@ -25,7 +25,7 @@ export async function shellSync() {
|
||||
const env: Env = JSON.parse(JSON.stringify(envVars));
|
||||
if (!env.LANG) {
|
||||
// the LANG env var expects an underscore instead of electron's dash
|
||||
env.LANG = `${app.getLocale().replace('-', '_')}.UTF-8`;
|
||||
env.LANG = `${app.getLocale().replace("-", "_")}.UTF-8`;
|
||||
} else if (!env.LANG.endsWith(".UTF-8")) {
|
||||
env.LANG += ".UTF-8";
|
||||
}
|
||||
|
||||
+4
-4
@@ -66,7 +66,7 @@ export function createTrayMenu(windowManager: WindowManager): Menu {
|
||||
showAbout(browserWindow);
|
||||
},
|
||||
},
|
||||
{ type: 'separator' },
|
||||
{ type: "separator" },
|
||||
{
|
||||
label: "Open Lens",
|
||||
async click() {
|
||||
@@ -91,7 +91,7 @@ export function createTrayMenu(windowManager: WindowManager): Menu {
|
||||
submenu: clusters.map(cluster => {
|
||||
const { id: clusterId, name: label, online, workspace } = cluster;
|
||||
return {
|
||||
label: `${online ? '✓' : '\x20'.repeat(3)/*offset*/}${label}`,
|
||||
label: `${online ? "✓" : "\x20".repeat(3)/*offset*/}${label}`,
|
||||
toolTip: clusterId,
|
||||
async click() {
|
||||
workspaceStore.setActive(workspace);
|
||||
@@ -115,9 +115,9 @@ export function createTrayMenu(windowManager: WindowManager): Menu {
|
||||
}
|
||||
},
|
||||
},
|
||||
{ type: 'separator' },
|
||||
{ type: "separator" },
|
||||
{
|
||||
label: 'Quit App',
|
||||
label: "Quit App",
|
||||
click() {
|
||||
exitApp();
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user