1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Merge branch 'vue_react_migration' into views_management_refactoring

This commit is contained in:
Lauri Nevala 2020-08-18 12:37:43 +03:00 committed by GitHub
commit fe42219e10
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 250 additions and 9 deletions

View File

@ -2416,6 +2416,10 @@ msgstr "There are no logs available."
msgid "This field is required" msgid "This field is required"
msgstr "This field is required" msgstr "This field is required"
#: src/renderer/components/input/input.validators.ts:39
msgid "A System Name must be lowercase DNS labels separated by dots. DNS labels are alphanumerics and dashes enclosed by alphanumerics."
msgstr "A System Name must be lowercase DNS labels separated by dots. DNS labels are alphanumerics and dashes enclosed by alphanumerics."
#: src/renderer/components/cluster-manager/clusters-menu.tsx:104 #: src/renderer/components/cluster-manager/clusters-menu.tsx:104
msgid "This is the quick launch menu." msgid "This is the quick launch menu."
msgstr "This is the quick launch menu." msgstr "This is the quick launch menu."

View File

@ -2399,6 +2399,10 @@ msgstr ""
msgid "This field is required" msgid "This field is required"
msgstr "" msgstr ""
#: src/renderer/components/input/input.validators.ts:39
msgid "A System Name must be lowercase DNS labels separated by dots. DNS labels are alphanumerics and dashes enclosed by alphanumerics."
msgstr ""
#: src/renderer/components/cluster-manager/clusters-menu.tsx:104 #: src/renderer/components/cluster-manager/clusters-menu.tsx:104
msgid "This is the quick launch menu." msgid "This is the quick launch menu."
msgstr "" msgstr ""

View File

@ -2417,6 +2417,10 @@ msgstr "Логи отсутствуют."
msgid "This field is required" msgid "This field is required"
msgstr "Это обязательное поле" msgstr "Это обязательное поле"
#: src/renderer/components/input/input.validators.ts:39
msgid "A System Name must be lowercase DNS labels separated by dots. DNS labels are alphanumerics and dashes enclosed by alphanumerics."
msgstr "Это поле может содержать только латинские буквы в нижнем регистре, номера и дефис."
#: src/renderer/components/cluster-manager/clusters-menu.tsx:104 #: src/renderer/components/cluster-manager/clusters-menu.tsx:104
msgid "This is the quick launch menu." msgid "This is the quick launch menu."
msgstr "" msgstr ""

View File

@ -135,8 +135,4 @@ export class BaseStore<T = any> extends Singleton {
recurseEverything: true, recurseEverything: true,
}) })
} }
* [Symbol.iterator]() {
yield* Object.entries(this.toJSON());
}
} }

View File

@ -1,11 +1,10 @@
import { app, remote } from "electron"; import { app, remote } from "electron";
import { KubeConfig, V1Node, V1Pod } from "@kubernetes/client-node" import { KubeConfig, V1Node, V1Pod } from "@kubernetes/client-node"
import { ensureDirSync, readFile, writeFileSync } from "fs-extra"; import fse, { ensureDirSync, readFile, writeFileSync } from "fs-extra";
import path from "path" import path from "path"
import os from "os" import os from "os"
import yaml from "js-yaml" import yaml from "js-yaml"
import logger from "../main/logger"; import logger from "../main/logger";
import fse from "fs-extra"
function resolveTilde(filePath: string) { function resolveTilde(filePath: string) {
if (filePath[0] === "~" && (filePath[1] === "/" || filePath.length === 1)) { if (filePath[0] === "~" && (filePath[1] === "/" || filePath.length === 1)) {
@ -135,8 +134,6 @@ export function podHasIssues(pod: V1Pod) {
) )
} }
// Logic adapted from dashboard
// see: https://github.com/kontena/kontena-k8s-dashboard/blob/7d8f9cb678cc817a22dd1886c5e79415b212b9bf/client/api/endpoints/nodes.api.ts#L147
export function getNodeWarningConditions(node: V1Node) { export function getNodeWarningConditions(node: V1Node) {
return node.status.conditions.filter(c => return node.status.conditions.filter(c =>
c.status.toLowerCase() === "true" && c.type !== "Ready" && c.type !== "HostUpgrades" c.status.toLowerCase() === "true" && c.type !== "Ready" && c.type !== "HostUpgrades"

View File

@ -3,6 +3,7 @@ import ua from "universal-analytics"
import { machineIdSync } from "node-machine-id" import { machineIdSync } from "node-machine-id"
import Singleton from "./utils/singleton"; import Singleton from "./utils/singleton";
import { userStore } from "./user-store" import { userStore } from "./user-store"
import logger from "../main/logger";
export class Tracker extends Singleton { export class Tracker extends Singleton {
static readonly GA_ID = "UA-159377374-1" static readonly GA_ID = "UA-159377374-1"
@ -40,7 +41,7 @@ export class Tracker extends Singleton {
...otherParams, ...otherParams,
}).send() }).send()
} catch (err) { } catch (err) {
console.error(`Failed to track "${eventCategory}:${eventAction}"`, err) logger.error(`Failed to track "${eventCategory}:${eventAction}"`, err)
} }
} }
} }

View File

@ -0,0 +1,102 @@
import mockFs from "mock-fs"
jest.mock("electron", () => {
return {
app: {
getVersion: () => '99.99.99',
getPath: () => 'tmp',
getLocale: () => 'en'
}
}
})
import { UserStore } from "./user-store"
import { SemVer } from "semver"
import electron from "electron"
describe("user store tests", () => {
describe("for an empty config", () => {
beforeEach(() => {
UserStore.resetInstance()
mockFs({ tmp: { 'config.json': "{}" } })
})
afterEach(() => {
mockFs.restore()
})
it("allows setting and retrieving lastSeenAppVersion", () => {
const us = UserStore.getInstance<UserStore>();
us.lastSeenAppVersion = "1.2.3";
expect(us.lastSeenAppVersion).toBe("1.2.3");
})
it("allows adding and listing seen contexts", () => {
const us = UserStore.getInstance<UserStore>();
us.seenContexts.add('foo')
expect(us.seenContexts.size).toBe(1)
us.seenContexts.add('foo')
us.seenContexts.add('bar')
expect(us.seenContexts.size).toBe(2) // check 'foo' isn't added twice
expect(us.seenContexts.has('foo')).toBe(true)
expect(us.seenContexts.has('bar')).toBe(true)
})
it("allows setting and getting preferences", () => {
const us = UserStore.getInstance<UserStore>();
us.preferences.httpsProxy = 'abcd://defg';
expect(us.preferences.httpsProxy).toBe('abcd://defg')
expect(us.preferences.colorTheme).toBe(UserStore.defaultTheme)
us.preferences.colorTheme = "light";
expect(us.preferences.colorTheme).toBe('light')
})
it("correctly resets theme to default value", () => {
const us = UserStore.getInstance<UserStore>();
us.preferences.colorTheme = "some other theme";
us.resetTheme();
expect(us.preferences.colorTheme).toBe(UserStore.defaultTheme);
})
it("correctly calculates if the last seen version is an old release", () => {
const us = UserStore.getInstance<UserStore>();
expect(us.isNewVersion).toBe(true);
us.lastSeenAppVersion = (new SemVer(electron.app.getVersion())).inc("major").format();
expect(us.isNewVersion).toBe(false);
})
})
describe("migrations", () => {
beforeEach(() => {
UserStore.resetInstance()
mockFs({
'tmp': {
'config.json': JSON.stringify({
user: { username: 'foobar' },
preferences: { colorTheme: 'light' },
lastSeenAppVersion: '1.2.3'
})
}
})
})
afterEach(() => {
mockFs.restore()
})
it("sets last seen app version to 0.0.0", () => {
const us = UserStore.getInstance<UserStore>();
expect(us.lastSeenAppVersion).toBe('0.0.0')
})
})
})

View File

@ -51,6 +51,10 @@ export class WorkspaceStore extends BaseStore<WorkspaceStoreModel> {
@action @action
setActive(id = WorkspaceStore.defaultId) { setActive(id = WorkspaceStore.defaultId) {
if (!this.getById(id)) {
throw new Error(`workspace ${id} doesn't exist`);
}
this.currentWorkspaceId = id; this.currentWorkspaceId = id;
} }

View File

@ -0,0 +1,128 @@
import mockFs from "mock-fs"
jest.mock("electron", () => {
return {
app: {
getVersion: () => '99.99.99',
getPath: () => 'tmp',
getLocale: () => 'en'
}
}
})
import { WorkspaceStore } from "./workspace-store"
describe("workspace store tests", () => {
describe("for an empty config", () => {
beforeEach(async () => {
WorkspaceStore.resetInstance()
mockFs({ tmp: { 'lens-workspace-store.json': "{}" } })
await WorkspaceStore.getInstance<WorkspaceStore>().load();
})
afterEach(() => {
mockFs.restore()
})
it("default workspace should always exist", () => {
const ws = WorkspaceStore.getInstance<WorkspaceStore>();
expect(ws.workspaces.size).toBe(1);
expect(ws.getById(WorkspaceStore.defaultId)).not.toBe(null);
})
it("cannot remove the default workspace", () => {
const ws = WorkspaceStore.getInstance<WorkspaceStore>();
expect(() => ws.removeWorkspace(WorkspaceStore.defaultId)).toThrowError("Cannot remove");
})
it("can update default workspace name", () => {
const ws = WorkspaceStore.getInstance<WorkspaceStore>();
ws.saveWorkspace({
id: WorkspaceStore.defaultId,
name: "foobar",
});
expect(ws.currentWorkspace.name).toBe("foobar");
})
it("can add workspaces", () => {
const ws = WorkspaceStore.getInstance<WorkspaceStore>();
ws.saveWorkspace({
id: "123",
name: "foobar",
});
expect(ws.getById("123").name).toBe("foobar");
})
it("cannot set a non-existent workspace to be active", () => {
const ws = WorkspaceStore.getInstance<WorkspaceStore>();
expect(() => ws.setActive("abc")).toThrow("doesn't exist");
})
it("can set a existent workspace to be active", () => {
const ws = WorkspaceStore.getInstance<WorkspaceStore>();
ws.saveWorkspace({
id: "abc",
name: "foobar",
});
expect(() => ws.setActive("abc")).not.toThrowError();
})
it("can remove a workspace", () => {
const ws = WorkspaceStore.getInstance<WorkspaceStore>();
ws.saveWorkspace({
id: "123",
name: "foobar",
});
ws.saveWorkspace({
id: "1234",
name: "foobar 1",
});
ws.removeWorkspace("123");
expect(ws.workspaces.size).toBe(2);
})
})
describe("for a non-empty config", () => {
beforeEach(async () => {
WorkspaceStore.resetInstance()
mockFs({
tmp: {
'lens-workspace-store.json': JSON.stringify({
currentWorkspace: "abc",
workspaces: [{
id: "abc",
name: "test"
}, {
id: "default",
name: "default"
}]
})
}
})
await WorkspaceStore.getInstance<WorkspaceStore>().load();
})
afterEach(() => {
mockFs.restore()
})
it("doesn't revert to default workspace", async () => {
const ws = WorkspaceStore.getInstance<WorkspaceStore>();
expect(ws.currentWorkspaceId).toBe("abc");
})
})
})

View File

@ -1,6 +1,7 @@
import "./cluster-settings.scss"; import "./cluster-settings.scss";
import React from "react"; import React from "react";
import { Link } from "react-router-dom";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { Features } from "./features"; import { Features } from "./features";
import { Removal } from "./removal"; import { Removal } from "./removal";