From 0f8e8c22375fe8e80f8bb311568d9d7cbb69ad1c Mon Sep 17 00:00:00 2001 From: Lauri Nevala Date: Tue, 10 Nov 2020 09:02:32 +0200 Subject: [PATCH 1/9] Expose CRD api to extensions (#1297) Signed-off-by: Lauri Nevala --- src/extensions/renderer-api/k8s-api.ts | 1 + src/renderer/api/endpoints/index.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/src/extensions/renderer-api/k8s-api.ts b/src/extensions/renderer-api/k8s-api.ts index eb118bd7b3..5271bd7915 100644 --- a/src/extensions/renderer-api/k8s-api.ts +++ b/src/extensions/renderer-api/k8s-api.ts @@ -29,3 +29,4 @@ export { Role, roleApi } from "../../renderer/api/endpoints"; export { RoleBinding, roleBindingApi } from "../../renderer/api/endpoints"; export { ClusterRole, clusterRoleApi } from "../../renderer/api/endpoints"; export { ClusterRoleBinding, clusterRoleBindingApi } from "../../renderer/api/endpoints"; +export { CustomResourceDefinition, crdApi } from "../../renderer/api/endpoints"; diff --git a/src/renderer/api/endpoints/index.ts b/src/renderer/api/endpoints/index.ts index 3d69068e30..337d193043 100644 --- a/src/renderer/api/endpoints/index.ts +++ b/src/renderer/api/endpoints/index.ts @@ -5,6 +5,7 @@ export * from "./cluster.api" export * from "./cluster-role.api" export * from "./cluster-role-binding.api" export * from "./configmap.api" +export * from "./crd.api" export * from "./cron-job.api" export * from "./daemon-set.api" export * from "./deployment.api" From b7fde0c6a6ca6db0cd9e11aa784b670abce0ea1b Mon Sep 17 00:00:00 2001 From: Lauri Nevala Date: Tue, 10 Nov 2020 09:46:50 +0200 Subject: [PATCH 2/9] Fix KubeObjectDetails example in common capabilities (#1299) Signed-off-by: Lauri Nevala --- docs/extensions/capabilities/common-capabilities.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/extensions/capabilities/common-capabilities.md b/docs/extensions/capabilities/common-capabilities.md index ee8745df08..a56f7d8804 100644 --- a/docs/extensions/capabilities/common-capabilities.md +++ b/docs/extensions/capabilities/common-capabilities.md @@ -245,7 +245,7 @@ import { LensRendererExtension } from "@k8slens/extensions"; import { CustomKindDetails, CustomKindDetailsProps } from "./src/custom-kind-details" export default class ExampleExtension extends LensRendererExtension { - kubeObjectMenuItems = [ + kubeObjectDetailItems = [ { kind: "CustomKind", apiVersions: ["custom.acme.org/v1"], From de8522951275f38cac152ce0e002668130345a91 Mon Sep 17 00:00:00 2001 From: Mario Sarcher Date: Tue, 10 Nov 2020 09:36:28 +0100 Subject: [PATCH 3/9] Generate API Reference documentation using typedocs and gh-actions Signed-off-by: Mario Sarcher --- .github/workflows/main.yml | 18 +++++++++++-- .gitignore | 1 + docs/extensions/api/README.md | 3 --- mkdocs.yml | 2 +- package.json | 5 +++- yarn.lock | 50 ++++++++++++++++++++++++++++++++--- 6 files changed, 69 insertions(+), 10 deletions(-) delete mode 100644 docs/extensions/api/README.md diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b9b41ddd58..fb91a82103 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -8,6 +8,9 @@ jobs: build: name: Deploy docs runs-on: ubuntu-latest + strategy: + matrix: + node-version: [12.x] steps: - name: Set up Python 3.7 uses: actions/setup-python@v2 @@ -31,8 +34,19 @@ jobs: git config --local user.email "action@github.com" git config --local user.name "GitHub Action" git pull - - + + - name: Using Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + + - name: Generate Extensions API Reference using typedocs + run: | + yarn install + yarn typedocs-extensions-api + for filename in docs/extensions/api/**/*.md; do [ -e "$filename" ] || continue; sed -i '1s/^/---\ntitle: API Reference\n---\n/' $filename; done + + - name: mkdocs deploy latest run: | mike deploy --push latest diff --git a/.gitignore b/.gitignore index c6f54c7dea..8a1a574c2c 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ src/extensions/*/*.d.ts types/extension-api.d.ts types/extension-renderer-api.d.ts extensions/*/dist +docs/extensions/api \ No newline at end of file diff --git a/docs/extensions/api/README.md b/docs/extensions/api/README.md deleted file mode 100644 index e751aa7a19..0000000000 --- a/docs/extensions/api/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Lens Extension API Reference - -TBD diff --git a/mkdocs.yml b/mkdocs.yml index 021287ac94..e2b3b17d34 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -35,7 +35,7 @@ nav: - Testing Extensions: extensions/testing-and-publishing/testing.md - Publishing Extensions: extensions/testing-and-publishing/publishing.md - Bundling Extensions: extensions/testing-and-publishing/bundling.md - - API Reference: extensions/api/README.md + - API Reference: extensions/api/modules/_src_extensions_extension_api_.md - Contributing: - Overview: contributing/README.md - Development: contributing/development.md diff --git a/package.json b/package.json index 15bf712c1e..c0758e4aa0 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,8 @@ "download:helm": "yarn run ts-node build/download_helm.ts", "build:tray-icons": "yarn run ts-node build/build_tray_icon.ts", "lint": "eslint $@ --ext js,ts,tsx --max-warnings=0 src/", - "mkdocs-serve-local": "docker build -t mkdocs-serve-local:latest mkdocs/ && docker run --rm -it -p 8000:8000 -v ${PWD}:/docs mkdocs-serve-local:latest" + "mkdocs-serve-local": "yarn typedocs-extensions-api && docker build -t mkdocs-serve-local:latest mkdocs/ && docker run --rm -it -p 8000:8000 -v ${PWD}:/docs mkdocs-serve-local:latest", + "typedocs-extensions-api": "npx typedoc --plugin typedoc-plugin-markdown --readme none --name @k8slens/extensions --ignoreCompilerErrors --out docs/extensions/api --mode modules --excludePrivate --includes src/ src/extensions/extension-api.ts" }, "config": { "bundledKubectlVersion": "1.17.11", @@ -381,6 +382,8 @@ "ts-jest": "^26.1.0", "ts-loader": "^7.0.5", "ts-node": "^8.10.2", + "typedoc": "^0.19.2", + "typedoc-plugin-markdown": "^3.0.11", "type-fest": "^0.18.0", "typeface-roboto": "^0.0.75", "typescript": "^4.0.2", diff --git a/yarn.lock b/yarn.lock index 1207cd0729..c145c32e43 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7168,6 +7168,11 @@ he@^1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +highlight.js@^10.2.0: + version "10.3.2" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.3.2.tgz#135fd3619a00c3cbb8b4cd6dbc78d56bfcbc46f1" + integrity sha512-3jRT7OUYsVsKvukNKZCtnvRcFyCJqSEIuIMsEybAXRiFSwpt65qjPd/Pr+UOdYt7WJlt+lj3+ypUsHiySBp/Jw== + history@^4.10.1, history@^4.9.0: version "4.10.1" resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3" @@ -9317,7 +9322,7 @@ lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.1 resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== -lodash@^4.15.0, lodash@^4.17.19: +lodash@^4.15.0, lodash@^4.17.19, lodash@^4.17.20: version "4.17.20" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== @@ -9402,6 +9407,11 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" +lunr@^2.3.9: + version "2.3.9" + resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" + integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== + lz-string@^1.4.4: version "1.4.4" resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26" @@ -9499,6 +9509,11 @@ marked@^1.1.0: resolved "https://registry.yarnpkg.com/marked/-/marked-1.1.0.tgz#62504ad4d11550c942935ccc5e39d64e5a4c4e50" integrity sha512-EkE7RW6KcXfMHy2PA7Jg0YJE1l8UPEZE8k45tylzmZM30/r1M1MUXWQfJlrSbsTeh7m/XTwHbWUENvAJZpp1YA== +marked@^1.1.1: + version "1.2.3" + resolved "https://registry.yarnpkg.com/marked/-/marked-1.2.3.tgz#58817ba348a7c9398cb94d40d12e0d08df83af57" + integrity sha512-RQuL2i6I6Gn+9n81IDNGbL0VHnta4a+8ZhqvryXEniTb/hQNtf3i26hi1XWUhzb9BgVyWHKR3UO8MaHtKoYibw== + matcher@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/matcher/-/matcher-3.0.0.tgz#bd9060f4c5b70aa8041ccc6f80368760994f30ca" @@ -9740,7 +9755,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= -minimatch@^3.0.4, minimatch@~3.0.2: +minimatch@^3.0.0, minimatch@^3.0.4, minimatch@~3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -12921,7 +12936,7 @@ shell-env@^3.0.0: execa "^1.0.0" strip-ansi "^5.2.0" -shelljs@^0.8.2: +shelljs@^0.8.2, shelljs@^0.8.4: version "0.8.4" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.4.tgz#de7684feeb767f8716b326078a8a00875890e3c2" integrity sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ== @@ -14196,6 +14211,35 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= +typedoc-default-themes@^0.11.4: + version "0.11.4" + resolved "https://registry.yarnpkg.com/typedoc-default-themes/-/typedoc-default-themes-0.11.4.tgz#1bc55b7c8d1132844616ff6f570e1e2cd0eb7343" + integrity sha512-Y4Lf+qIb9NTydrexlazAM46SSLrmrQRqWiD52593g53SsmUFioAsMWt8m834J6qsp+7wHRjxCXSZeiiW5cMUdw== + +typedoc-plugin-markdown@^3.0.11: + version "3.0.11" + resolved "https://registry.yarnpkg.com/typedoc-plugin-markdown/-/typedoc-plugin-markdown-3.0.11.tgz#358c32f4a0086c1dd2da7f56c4b46ade8a63204b" + integrity sha512-/BE/PqnIVbQJ525czM+T3CVaA1gVN9X1Le100z8TV/Lze8LZVkuAUiHRIgw9BKYFm9IQaB88W55k4EV6uUVwYQ== + dependencies: + handlebars "^4.7.6" + +typedoc@^0.19.2: + version "0.19.2" + resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.19.2.tgz#842a63a581f4920f76b0346bb80eb2a49afc2c28" + integrity sha512-oDEg1BLEzi1qvgdQXc658EYgJ5qJLVSeZ0hQ57Eq4JXy6Vj2VX4RVo18qYxRWz75ifAaYuYNBUCnbhjd37TfOg== + dependencies: + fs-extra "^9.0.1" + handlebars "^4.7.6" + highlight.js "^10.2.0" + lodash "^4.17.20" + lunr "^2.3.9" + marked "^1.1.1" + minimatch "^3.0.0" + progress "^2.0.3" + semver "^7.3.2" + shelljs "^0.8.4" + typedoc-default-themes "^0.11.4" + typeface-roboto@^0.0.75: version "0.0.75" resolved "https://registry.yarnpkg.com/typeface-roboto/-/typeface-roboto-0.0.75.tgz#98d5ba35ec234bbc7172374c8297277099cc712b" From b2f3cdd0d29b1a462670f819b4a47ac1edfaca92 Mon Sep 17 00:00:00 2001 From: Alex Andreev Date: Tue, 10 Nov 2020 12:36:06 +0300 Subject: [PATCH 4/9] Keeping Icon focus state only for keyboard (#1234) * Passing toolbar prop into action menus Signed-off-by: Alex Andreev * Toggling .mouse-intent Signed-off-by: Alex Andreev * Icon focus restyling Signed-off-by: Alex Andreev * Adding what-input dependency Signed-off-by: Alex Andreev --- package.json | 1 + src/renderer/components/app.tsx | 4 +++- src/renderer/components/drawer/drawer.scss | 1 + src/renderer/components/icon/icon.scss | 15 ++++++++++++--- .../components/kube-object/kube-object-menu.tsx | 5 +++-- src/renderer/components/layout/main-layout.tsx | 1 + yarn.lock | 5 +++++ 7 files changed, 26 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index c0758e4aa0..ad7a4a80c8 100644 --- a/package.json +++ b/package.json @@ -392,6 +392,7 @@ "webpack-cli": "^3.3.11", "webpack-dev-server": "^3.11.0", "webpack-node-externals": "^1.7.2", + "what-input": "^5.2.10", "xterm": "^4.6.0", "xterm-addon-fit": "^0.4.0" } diff --git a/src/renderer/components/app.tsx b/src/renderer/components/app.tsx index 5ad908a528..a5ebe554d1 100755 --- a/src/renderer/components/app.tsx +++ b/src/renderer/components/app.tsx @@ -38,7 +38,8 @@ import { webFrame } from "electron"; import { clusterPageRegistry } from "../../extensions/registries/page-registry"; import { DynamicPage } from "../../extensions/dynamic-page"; import { extensionLoader } from "../../extensions/extension-loader"; -import { appEventBus } from "../../common/event-bus" +import { appEventBus } from "../../common/event-bus"; +import whatInput from 'what-input'; @observer export class App extends React.Component { @@ -57,6 +58,7 @@ export class App extends React.Component { window.addEventListener("online", () => { window.location.reload() }) + whatInput.ask() // Start to monitor user input device } get startURL() { diff --git a/src/renderer/components/drawer/drawer.scss b/src/renderer/components/drawer/drawer.scss index 72a2f10eb1..488a890f2c 100644 --- a/src/renderer/components/drawer/drawer.scss +++ b/src/renderer/components/drawer/drawer.scss @@ -3,6 +3,7 @@ --size: 50%; --full-size: 75%; --spacing: #{$padding * 3}; + --icon-focus-color: white; position: absolute; background: $contentColor; diff --git a/src/renderer/components/icon/icon.scss b/src/renderer/components/icon/icon.scss index 253423bd4c..e581ccbbdc 100644 --- a/src/renderer/components/icon/icon.scss +++ b/src/renderer/components/icon/icon.scss @@ -5,6 +5,7 @@ --big-size: 32px; --color-active: #{$iconActiveColor}; --bgc-active: #{$iconActiveBackground}; + --focus-color: var(--icon-focus-color, #{$lensBlue}); display: inline-flex; flex-shrink: 0; @@ -106,7 +107,7 @@ &.active { color: var(--color-active); - box-shadow: 0 0 0 3px $iconActiveBackground; + box-shadow: 0 0 0 2px $iconActiveBackground; background-color: $iconActiveBackground; } @@ -115,8 +116,16 @@ transition: 250ms color, 250ms opacity, 150ms background-color, 150ms box-shadow; border-radius: 50%; - &.focusable:focus { - @extend .active; + &.focusable:focus:not(:hover) { + box-shadow: 0 0 0 2px var(--focus-color); + + [data-whatintent='mouse'] & { + box-shadow: none; + + &.active { + box-shadow: 0 0 0 2px $iconActiveBackground; + } + } } &:hover { diff --git a/src/renderer/components/kube-object/kube-object-menu.tsx b/src/renderer/components/kube-object/kube-object-menu.tsx index fa008f1bac..0333bf6f9c 100644 --- a/src/renderer/components/kube-object/kube-object-menu.tsx +++ b/src/renderer/components/kube-object/kube-object-menu.tsx @@ -57,11 +57,11 @@ export class KubeObjectMenu extends React.Component { render() { const { remove, update, renderRemoveMessage, isEditable, isRemovable } = this; - const { className, object, editable, removable, ...menuProps } = this.props; + const { className, object, editable, removable, toolbar, ...menuProps } = this.props; if (!object) return null; const menuItems = kubeObjectMenuRegistry.getItemsForKind(object.kind, object.apiVersion).map((item, index) => { - return + return }) return ( { updateAction={isEditable ? update : undefined} removeAction={isRemovable ? remove : undefined} removeConfirmationMessage={renderRemoveMessage} + toolbar={toolbar} {...menuProps} > {menuItems} diff --git a/src/renderer/components/layout/main-layout.tsx b/src/renderer/components/layout/main-layout.tsx index 67c6c08bce..e66fed3d17 100755 --- a/src/renderer/components/layout/main-layout.tsx +++ b/src/renderer/components/layout/main-layout.tsx @@ -38,6 +38,7 @@ export class MainLayout extends React.Component { (sidebarWidth) => this.storage.merge({ sidebarWidth }) ); + toggleSidebar = () => { this.isPinned = !this.isPinned; this.isAccessible = false; diff --git a/yarn.lock b/yarn.lock index c145c32e43..b6a0e4add1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14850,6 +14850,11 @@ wgxpath@~1.0.0: resolved "https://registry.yarnpkg.com/wgxpath/-/wgxpath-1.0.0.tgz#eef8a4b9d558cc495ad3a9a2b751597ecd9af690" integrity sha1-7vikudVYzEla06mit1FZfs2a9pA= +what-input@^5.2.10: + version "5.2.10" + resolved "https://registry.yarnpkg.com/what-input/-/what-input-5.2.10.tgz#f79f5b65cf95d75e55e6d580bb0a6b98174cad4e" + integrity sha512-7AQoIMGq7uU8esmKniOtZG3A+pzlwgeyFpkS3f/yzRbxknSL68tvn5gjE6bZ4OMFxCPjpaBd2udUTqlZ0HwrXQ== + whatwg-encoding@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" From 3eeb395a783960407dd74e562b30c18bec11505b Mon Sep 17 00:00:00 2001 From: chh <1474479+chenhunghan@users.noreply.github.com> Date: Tue, 10 Nov 2020 18:13:01 +0800 Subject: [PATCH 5/9] Remove hard-source-webpack-plugin (#1305) Signed-off-by: Hung-Han (Henry) Chen <1474479+chenhunghan@users.noreply.github.com> --- package.json | 4 +--- webpack.main.ts | 2 -- webpack.renderer.ts | 2 -- yarn.lock | 53 +++++---------------------------------------- 4 files changed, 6 insertions(+), 55 deletions(-) diff --git a/package.json b/package.json index ad7a4a80c8..2d6d20b8a0 100644 --- a/package.json +++ b/package.json @@ -281,7 +281,6 @@ "@types/electron-window-state": "^2.0.34", "@types/fs-extra": "^9.0.1", "@types/hapi": "^18.0.3", - "@types/hard-source-webpack-plugin": "^1.0.1", "@types/hoist-non-react-statics": "^3.3.1", "@types/html-webpack-plugin": "^3.2.3", "@types/http-proxy": "^1.17.4", @@ -343,7 +342,6 @@ "file-loader": "^6.0.0", "flex.box": "^3.4.4", "fork-ts-checker-webpack-plugin": "^5.0.0", - "hard-source-webpack-plugin": "^0.13.1", "hoist-non-react-statics": "^3.3.2", "html-webpack-plugin": "^4.3.0", "identity-obj-proxy": "^3.0.0", @@ -382,9 +380,9 @@ "ts-jest": "^26.1.0", "ts-loader": "^7.0.5", "ts-node": "^8.10.2", + "type-fest": "^0.18.0", "typedoc": "^0.19.2", "typedoc-plugin-markdown": "^3.0.11", - "type-fest": "^0.18.0", "typeface-roboto": "^0.0.75", "typescript": "^4.0.2", "url-loader": "^4.1.0", diff --git a/webpack.main.ts b/webpack.main.ts index 29e724d711..c388466cdc 100755 --- a/webpack.main.ts +++ b/webpack.main.ts @@ -4,7 +4,6 @@ import ForkTsCheckerPlugin from "fork-ts-checker-webpack-plugin" import { isDevelopment, isProduction, mainDir, buildDir } from "./src/common/vars"; import nodeExternals from "webpack-node-externals"; import ProgressBarPlugin from "progress-bar-webpack-plugin"; -import HardSourceWebpackPlugin from 'hard-source-webpack-plugin'; export default function (): webpack.Configuration { console.info('WEBPACK:main', require("./src/common/vars")) @@ -48,7 +47,6 @@ export default function (): webpack.Configuration { plugins: [ new ProgressBarPlugin(), new ForkTsCheckerPlugin(), - isDevelopment && new HardSourceWebpackPlugin(), ].filter(Boolean) } } diff --git a/webpack.renderer.ts b/webpack.renderer.ts index 27fe6eb039..ea2b5f622c 100755 --- a/webpack.renderer.ts +++ b/webpack.renderer.ts @@ -6,7 +6,6 @@ import MiniCssExtractPlugin from "mini-css-extract-plugin"; import TerserPlugin from "terser-webpack-plugin"; import ForkTsCheckerPlugin from "fork-ts-checker-webpack-plugin" import ProgressBarPlugin from "progress-bar-webpack-plugin"; -import HardSourceWebpackPlugin from 'hard-source-webpack-plugin'; import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin' export default [ @@ -187,7 +186,6 @@ export function webpackLensRenderer({ showVars = true } = {}): webpack.Configura filename: "[name].css", }), - isDevelopment && new HardSourceWebpackPlugin(), isDevelopment && new webpack.HotModuleReplacementPlugin(), isDevelopment && new ReactRefreshWebpackPlugin(), diff --git a/yarn.lock b/yarn.lock index b6a0e4add1..7a237053b6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1967,13 +1967,6 @@ "@types/podium" "*" "@types/shot" "*" -"@types/hard-source-webpack-plugin@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@types/hard-source-webpack-plugin/-/hard-source-webpack-plugin-1.0.1.tgz#4aecca35bafb7939bcf318bbf5a2710c3163cdd4" - integrity sha512-5eTPERZQj5RZLADk5o2Ip/XRLwgxOUeKzlIM3+czrhwA9pnVJAUYOm2fovbxkrIEQhuozQwc17fyH1ZXnSR/8g== - dependencies: - "@types/webpack" "*" - "@types/history@*", "@types/history@^4.7.3": version "4.7.6" resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.6.tgz#ed8fc802c45b8e8f54419c2d054e55c9ea344356" @@ -5204,7 +5197,7 @@ detect-file@^1.0.0: resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= -detect-indent@^5.0.0, detect-indent@~5.0.0: +detect-indent@~5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" integrity sha1-OHHMCmoALow+Wzz38zYmRnXwa50= @@ -6359,7 +6352,7 @@ finalhandler@~1.1.2: statuses "~1.5.0" unpipe "~1.0.0" -find-cache-dir@^2.0.0, find-cache-dir@^2.1.0: +find-cache-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== @@ -7035,25 +7028,6 @@ har-validator@~5.1.3: ajv "^6.5.5" har-schema "^2.0.0" -hard-source-webpack-plugin@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/hard-source-webpack-plugin/-/hard-source-webpack-plugin-0.13.1.tgz#a99071e25b232f1438a5bc3c99f10a3869e4428e" - integrity sha512-r9zf5Wq7IqJHdVAQsZ4OP+dcUSvoHqDMxJlIzaE2J0TZWn3UjMMrHqwDHR8Jr/pzPfG7XxSe36E7Y8QGNdtuAw== - dependencies: - chalk "^2.4.1" - find-cache-dir "^2.0.0" - graceful-fs "^4.1.11" - lodash "^4.15.0" - mkdirp "^0.5.1" - node-object-hash "^1.2.0" - parse-json "^4.0.0" - pkg-dir "^3.0.0" - rimraf "^2.6.2" - semver "^5.6.0" - tapable "^1.0.0-beta.5" - webpack-sources "^1.0.1" - write-json-file "^2.3.0" - harmony-reflect@^1.4.6: version "1.6.1" resolved "https://registry.yarnpkg.com/harmony-reflect/-/harmony-reflect-1.6.1.tgz#c108d4f2bb451efef7a37861fdbdae72c9bdefa9" @@ -9322,7 +9296,7 @@ lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.1 resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== -lodash@^4.15.0, lodash@^4.17.19, lodash@^4.17.20: +lodash@^4.17.19, lodash@^4.17.20: version "4.17.20" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== @@ -10165,11 +10139,6 @@ node-notifier@^7.0.0: uuid "^7.0.3" which "^2.0.2" -node-object-hash@^1.2.0: - version "1.4.2" - resolved "https://registry.yarnpkg.com/node-object-hash/-/node-object-hash-1.4.2.tgz#385833d85b229902b75826224f6077be969a9e94" - integrity sha512-UdS4swXs85fCGWWf6t6DMGgpN/vnlKeSGEQ7hJcrs7PBFoxoKLmibc3QRb7fwiYsjdL7PX8iI/TMSlZ90dgHhQ== - node-pty@^0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.9.0.tgz#8f9bcc0d1c5b970a3184ffd533d862c7eb6590a6" @@ -13688,7 +13657,7 @@ table@^5.2.3: slice-ansi "^2.1.0" string-width "^3.0.0" -tapable@^1.0.0, tapable@^1.0.0-beta.5, tapable@^1.1.3: +tapable@^1.0.0, tapable@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== @@ -14787,7 +14756,7 @@ webpack-node-externals@^1.7.2: resolved "https://registry.yarnpkg.com/webpack-node-externals/-/webpack-node-externals-1.7.2.tgz#6e1ee79ac67c070402ba700ef033a9b8d52ac4e3" integrity sha512-ajerHZ+BJKeCLviLUUmnyd5B4RavLF76uv3cs6KNuO8W+HuQaEs0y0L7o40NQxdPy5w0pcv8Ew7yPUAQG0UdCg== -webpack-sources@^1.0.1, webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3: +webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== @@ -15034,18 +15003,6 @@ write-file-atomic@^3.0.0, write-file-atomic@^3.0.3: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" -write-json-file@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-2.3.0.tgz#2b64c8a33004d54b8698c76d585a77ceb61da32f" - integrity sha1-K2TIozAE1UuGmMdtWFp3zrYdoy8= - dependencies: - detect-indent "^5.0.0" - graceful-fs "^4.1.2" - make-dir "^1.0.0" - pify "^3.0.0" - sort-keys "^2.0.0" - write-file-atomic "^2.0.0" - write@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" From 05188ef3cc0af0b58c091add4398a6a3162966f6 Mon Sep 17 00:00:00 2001 From: Lauri Nevala Date: Tue, 10 Nov 2020 12:46:40 +0200 Subject: [PATCH 6/9] Do not expose registries to extensions (#1304) Signed-off-by: Lauri Nevala --- src/extensions/core-api/index.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/extensions/core-api/index.ts b/src/extensions/core-api/index.ts index 3882763681..1a2c59759a 100644 --- a/src/extensions/core-api/index.ts +++ b/src/extensions/core-api/index.ts @@ -9,7 +9,6 @@ import * as App from "./app" import * as EventBus from "./event-bus" import * as Store from "./stores" import * as Util from "./utils" -import * as Registry from "../registries" import * as ClusterFeature from "./cluster-feature" // TODO: allow to expose windowManager.navigate() as Navigation.navigate() in runtime @@ -21,5 +20,4 @@ export { ClusterFeature, Store, Util, - Registry, } From dd90dcb7f03b4234a05e64797205d79d0dc72b04 Mon Sep 17 00:00:00 2001 From: Alex Andreev Date: Tue, 10 Nov 2020 15:16:16 +0300 Subject: [PATCH 7/9] Removing !important statements from theme variables (#1303) * Removing !important statements from theme vars Signed-off-by: Alex Andreev * Wait for user store to load Signed-off-by: Alex Andreev * Fix this reference Signed-off-by: Alex Andreev * Aligning test with resetTheme() fixes Signed-off-by: Alex Andreev --- src/common/__tests__/user-store.test.ts | 5 +++-- src/common/user-store.ts | 3 ++- src/renderer/components/app.scss | 1 - src/renderer/theme.store.ts | 5 +++-- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/common/__tests__/user-store.test.ts b/src/common/__tests__/user-store.test.ts index e361397565..593992415f 100644 --- a/src/common/__tests__/user-store.test.ts +++ b/src/common/__tests__/user-store.test.ts @@ -57,11 +57,12 @@ describe("user store tests", () => { expect(us.preferences.colorTheme).toBe('light') }) - it("correctly resets theme to default value", () => { + it("correctly resets theme to default value", async () => { const us = UserStore.getInstance(); + us.isLoaded = true; us.preferences.colorTheme = "some other theme"; - us.resetTheme(); + await us.resetTheme(); expect(us.preferences.colorTheme).toBe(UserStore.defaultTheme); }) diff --git a/src/common/user-store.ts b/src/common/user-store.ts index b03616c1d2..6a988d4004 100644 --- a/src/common/user-store.ts +++ b/src/common/user-store.ts @@ -88,7 +88,8 @@ export class UserStore extends BaseStore { } @action - resetTheme() { + async resetTheme() { + await this.whenLoaded; this.preferences.colorTheme = UserStore.defaultTheme; } diff --git a/src/renderer/components/app.scss b/src/renderer/components/app.scss index 5d3b65f5e9..b7c492c9f5 100755 --- a/src/renderer/components/app.scss +++ b/src/renderer/components/app.scss @@ -23,7 +23,6 @@ --font-weight-thin: 300; --font-weight-normal: 400; --font-weight-bold: 500; - --mainBackground: #1e2124; --main-layout-header: 40px; --drag-region-height: 22px } diff --git a/src/renderer/theme.store.ts b/src/renderer/theme.store.ts index e96bc1f873..4b8dc5fffd 100644 --- a/src/renderer/theme.store.ts +++ b/src/renderer/theme.store.ts @@ -48,6 +48,7 @@ export class ThemeStore { await this.loadTheme(themeId); this.applyTheme(); } catch (err) { + logger.error(err); userStore.resetTheme(); } }, { @@ -79,7 +80,7 @@ export class ThemeStore { } return existingTheme; } catch (err) { - logger.error(`Can't load theme "${themeId}": ${err}`); + throw new Error(`Can't load theme "${themeId}": ${err}`); } } @@ -90,7 +91,7 @@ export class ThemeStore { document.head.prepend(this.styles); } const cssVars = Object.entries(theme.colors).map(([cssName, color]) => { - return `--${cssName}: ${color} !important;` + return `--${cssName}: ${color};`; }); this.styles.textContent = `:root {\n${cssVars.join("\n")}}`; // Adding universal theme flag which can be used in component styles From a78bbb5f6cbbfb60c6840fdd1fa7904565edae00 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Tue, 10 Nov 2020 10:10:19 -0500 Subject: [PATCH 8/9] Fix rendering of boolean values in CRDs (#1087) * Fix rendering of boolean values in CRDs - add optional special casing for boolean values in DrawerItems and TableRows since React (imo annoying fashion) does not render boolean values by default. - add a spinner on the sidebar for when the CRD menu is expeanded but the entries have not been loaded yet. - Add ability to double click a Badge to expand, also make it so that Badges highligh all text on first click. Signed-off-by: Sebastian Malton --- src/common/utils/saveToAppFiles.ts | 3 +- src/renderer/api/api-manager.ts | 2 +- src/renderer/api/endpoints/crd.api.ts | 7 +- .../crd-resource-details.tsx | 102 ++++++++++-------- .../+custom-resources/crd-resources.tsx | 13 +-- .../components/drawer/drawer-item.tsx | 15 +-- .../item-object-list/item-list-layout.tsx | 18 ++-- src/renderer/components/layout/sidebar.tsx | 35 +++--- src/renderer/components/spinner/spinner.scss | 8 +- src/renderer/components/spinner/spinner.tsx | 14 +-- src/renderer/components/table/table-cell.tsx | 11 +- .../utils/__tests__/display-booleans.test.tsx | 18 ++++ src/renderer/utils/display-booleans.ts | 15 +++ src/renderer/utils/index.ts | 1 + tsconfig.json | 6 +- 15 files changed, 167 insertions(+), 101 deletions(-) create mode 100644 src/renderer/utils/__tests__/display-booleans.test.tsx create mode 100644 src/renderer/utils/display-booleans.ts diff --git a/src/common/utils/saveToAppFiles.ts b/src/common/utils/saveToAppFiles.ts index 9092767ccf..e6fab1cfa9 100644 --- a/src/common/utils/saveToAppFiles.ts +++ b/src/common/utils/saveToAppFiles.ts @@ -1,7 +1,8 @@ // Save file to electron app directory (e.g. "/Users/$USER/Library/Application Support/Lens" for MacOS) import path from "path"; import { app, remote } from "electron"; -import { ensureDirSync, writeFileSync, WriteFileOptions } from "fs-extra"; +import { ensureDirSync, writeFileSync } from "fs-extra"; +import { WriteFileOptions } from "fs" export function saveToAppFiles(filePath: string, contents: any, options?: WriteFileOptions): string { const absPath = path.resolve((app || remote.app).getPath("userData"), filePath); diff --git a/src/renderer/api/api-manager.ts b/src/renderer/api/api-manager.ts index 0b066f37e1..a0d90f4a13 100644 --- a/src/renderer/api/api-manager.ts +++ b/src/renderer/api/api-manager.ts @@ -14,7 +14,7 @@ export class ApiManager { return this.apis.get(pathOrCallback) || this.apis.get(KubeApi.parseApi(pathOrCallback).apiBase); } - return Array.from(this.apis.values()).find(pathOrCallback); + return Array.from(this.apis.values()).find(pathOrCallback ?? ((api: KubeApi) => true)); } registerApi(apiBase: string, api: KubeApi) { diff --git a/src/renderer/api/endpoints/crd.api.ts b/src/renderer/api/endpoints/crd.api.ts index 7744276e74..7b561041f7 100644 --- a/src/renderer/api/endpoints/crd.api.ts +++ b/src/renderer/api/endpoints/crd.api.ts @@ -9,7 +9,7 @@ type AdditionalPrinterColumnsCommon = { description: string; } -type AdditionalPrinterColumnsV1 = AdditionalPrinterColumnsCommon & { +export type AdditionalPrinterColumnsV1 = AdditionalPrinterColumnsCommon & { jsonPath: string; } @@ -120,9 +120,9 @@ export class CustomResourceDefinition extends KubeObject { return JSON.stringify(this.spec.conversion); } - getPrinterColumns(ignorePriority = true) { + getPrinterColumns(ignorePriority = true): AdditionalPrinterColumnsV1[] { const columns = this.spec.versions.find(a => this.getVersion() == a.name)?.additionalPrinterColumns - ?? this.spec.additionalPrinterColumns?.map(({JSONPath, ...rest}) => ({ ...rest, jsonPath: JSONPath })) // map to V1 shape + ?? this.spec.additionalPrinterColumns?.map(({ JSONPath, ...rest }) => ({ ...rest, jsonPath: JSONPath })) // map to V1 shape ?? []; return columns .filter(column => column.name != "Age") @@ -149,4 +149,3 @@ export class CustomResourceDefinition extends KubeObject { export const crdApi = new VersionedKubeApi({ objectConstructor: CustomResourceDefinition }); - diff --git a/src/renderer/components/+custom-resources/crd-resource-details.tsx b/src/renderer/components/+custom-resources/crd-resource-details.tsx index 4525240396..883fba2fd4 100644 --- a/src/renderer/components/+custom-resources/crd-resource-details.tsx +++ b/src/renderer/components/+custom-resources/crd-resource-details.tsx @@ -12,67 +12,83 @@ import { KubeObjectDetailsProps } from "../kube-object"; import { crdStore } from "./crd.store"; import { KubeObjectMeta } from "../kube-object/kube-object-meta"; import { Input } from "../input"; -import { CustomResourceDefinition } from "../../api/endpoints/crd.api"; +import { AdditionalPrinterColumnsV1, CustomResourceDefinition } from "../../api/endpoints/crd.api"; interface Props extends KubeObjectDetailsProps { } -function CrdColumnValue({ value }: { value: any[] | {} | string }) { +function convertSpecValue(value: any): any { if (Array.isArray(value)) { - return <>{value.map((item, index) => )} + return value.map(convertSpecValue) } - if (typeof(value) === 'object') return ( - - ); - return {value}; + + if (typeof value === "object") { + return ( + + ) + } + + return value } + @observer export class CrdResourceDetails extends React.Component { @computed get crd() { return crdStore.getByObject(this.props.object); } + renderAdditionalColumns(crd: CustomResourceDefinition, columns: AdditionalPrinterColumnsV1[]) { + return columns.map(({ name, jsonPath: jp }) => ( + + {convertSpecValue(jsonPath.value(crd, jp.slice(1)))} + + )) + } + + renderStatus(crd: CustomResourceDefinition, columns: AdditionalPrinterColumnsV1[]) { + const showStatus = !columns.find(column => column.name == "Status") && crd.status?.conditions; + if (!showStatus) { + return null + } + + const conditions = crd.status.conditions + .filter(({ type, reason }) => type || reason) + .map(({ type, reason, message, status }) => ({ kind: type || reason, message, status })) + .map(({ kind, message, status }, index) => ( + + )) + + return ( + Status} className="status" labelsOnly> + {conditions} + + ) + } + render() { - const { object } = this.props; - const { crd } = this; - if (!object || !crd) return null; + const { props: { object }, crd } = this; + if (!object || !crd) { + return null; + } + const className = cssNames("CrdResourceDetails", crd.getResourceKind()); const extraColumns = crd.getPrinterColumns(); - const showStatus = !extraColumns.find(column => column.name == "Status") && object.status?.conditions; + return (
- - {extraColumns.map(column => { - const { name } = column; - const value = jsonPath.query(object, (column.jsonPath).slice(1)); - return ( - - - - ) - })} - {showStatus && ( - Status} className="status" labelsOnly> - {object.status.conditions.map((condition, index) => { - const { type, reason, message, status } = condition; - const kind = type || reason; - if (!kind) return null; - return ( - - ); - })} - - )} + + {this.renderAdditionalColumns(object, extraColumns)} + {this.renderStatus(object, extraColumns)}
) } diff --git a/src/renderer/components/+custom-resources/crd-resources.tsx b/src/renderer/components/+custom-resources/crd-resources.tsx index 3a7d726b59..e36fef532d 100644 --- a/src/renderer/components/+custom-resources/crd-resources.tsx +++ b/src/renderer/components/+custom-resources/crd-resources.tsx @@ -56,11 +56,11 @@ export class CrdResources extends React.Component { [sortBy.age]: (item: KubeObject) => item.metadata.creationTimestamp, } extraColumns.forEach(column => { - sortingCallbacks[column.name] = (item: KubeObject) => jsonPath.query(item, column.jsonPath.slice(1)) + sortingCallbacks[column.name] = (item: KubeObject) => jsonPath.value(item, column.jsonPath.slice(1)) }) - const ListView = KubeObjectListLayout; + return ( - { renderTableContents={(crdInstance: KubeObject) => [ crdInstance.getName(), isNamespaced && crdInstance.getNs(), - ...extraColumns.map(column => { - return jsonPath.query(crdInstance, (column.jsonPath).slice(1)) - }), + ...extraColumns.map(column => ({ + renderBoolean: true, + children: jsonPath.value(crdInstance, column.jsonPath.slice(1)), + })), crdInstance.getAge(), ]} /> diff --git a/src/renderer/components/drawer/drawer-item.tsx b/src/renderer/components/drawer/drawer-item.tsx index da38dd4a46..e50619fe5d 100644 --- a/src/renderer/components/drawer/drawer-item.tsx +++ b/src/renderer/components/drawer/drawer-item.tsx @@ -1,6 +1,6 @@ import "./drawer-item.scss"; import React from "react"; -import { cssNames } from "../../utils"; +import { cssNames, displayBooleans } from "../../utils"; export interface DrawerItemProps extends React.HTMLAttributes { name: React.ReactNode; @@ -8,18 +8,21 @@ export interface DrawerItemProps extends React.HTMLAttributes { title?: string; labelsOnly?: boolean; hidden?: boolean; + renderBoolean?: boolean; // show "true" or "false" for all of the children elements are "typeof boolean" } export class DrawerItem extends React.Component { render() { - const { name, title, labelsOnly, children, hidden, ...elemProps } = this.props - let { className } = this.props; + const { name, title, labelsOnly, children, hidden, className, renderBoolean, ...elemProps } = this.props if (hidden) return null - className = cssNames("DrawerItem", className, { labelsOnly }); + + const classNames = cssNames("DrawerItem", className, { labelsOnly }); + const content = displayBooleans(renderBoolean, children) + return ( -
+
{name} - {children} + {content}
) } diff --git a/src/renderer/components/item-object-list/item-list-layout.tsx b/src/renderer/components/item-object-list/item-list-layout.tsx index 0ff8201e05..fa99b3405b 100644 --- a/src/renderer/components/item-object-list/item-list-layout.tsx +++ b/src/renderer/components/item-object-list/item-list-layout.tsx @@ -235,7 +235,7 @@ export class ItemListLayout extends React.Component { cellProps.className = cssNames(cellProps.className, headCell.className); } } - return + return }) } {renderItemMenu && ( @@ -277,7 +277,7 @@ export class ItemListLayout extends React.Component { if (!isReady || !filters.length || hideFilters || !userSettings.showAppliedFilters) { return; } - return + return } renderNoItems() { @@ -297,7 +297,7 @@ export class ItemListLayout extends React.Component { ) } - return + return } renderHeaderContent(placeholders: IHeaderPlaceholders): ReactNode { @@ -344,12 +344,12 @@ export class ItemListLayout extends React.Component { title:
{title}
, info: this.renderInfo(), filters: <> - {!isClusterScoped && } + {!isClusterScoped && } + }} /> , - search: , + search: , } let header = this.renderHeaderContent(placeholders); if (customizeHeader) { @@ -381,7 +381,7 @@ export class ItemListLayout extends React.Component { return (
{!isReady && ( - + )} {isReady && ( { onClick={prevDefault(() => store.toggleSelectionAll(items))} /> )} - {renderTableHeader.map((cellProps, index) => )} - {renderItemMenu && } + {renderTableHeader.map((cellProps, index) => )} + {renderItemMenu && } )} { diff --git a/src/renderer/components/layout/sidebar.tsx b/src/renderer/components/layout/sidebar.tsx index 4619e48de7..8bce1a32c8 100644 --- a/src/renderer/components/layout/sidebar.tsx +++ b/src/renderer/components/layout/sidebar.tsx @@ -27,8 +27,9 @@ import { crdStore } from "../+custom-resources/crd.store"; import { CrdList, crdResourcesRoute, crdRoute, crdURL } from "../+custom-resources"; import { CustomResources } from "../+custom-resources/custom-resources"; import { navigation } from "../../navigation"; -import { isAllowedResource } from "../../../common/rbac" import { clusterPageRegistry } from "../../../extensions/registries/page-registry"; +import { isAllowedResource } from "../../../common/rbac"; +import { Spinner } from "../spinner"; const SidebarContext = React.createContext({ pinned: false }); type SidebarContextValue = { @@ -50,6 +51,10 @@ export class Sidebar extends React.Component { } renderCustomResources() { + if (crdStore.isLoading) { + return + } + return Object.entries(crdStore.groups).map(([group, crds]) => { const submenus = crds.map((crd) => { return { @@ -80,7 +85,7 @@ export class Sidebar extends React.Component {
- +
Lens
{ isHidden={!isAllowedResource("nodes")} url={clusterURL()} text={Cluster} - icon={} + icon={} /> Nodes} - icon={} + icon={} /> { routePath={workloadsRoute.path} subMenus={Workloads.tabRoutes} text={Workloads} - icon={} + icon={} /> { routePath={configRoute.path} subMenus={Config.tabRoutes} text={Configuration} - icon={} + icon={} /> { routePath={networkRoute.path} subMenus={Network.tabRoutes} text={Network} - icon={} + icon={} /> { url={storageURL({ query })} routePath={storageRoute.path} subMenus={Storage.tabRoutes} - icon={} + icon={} text={Storage} /> } + icon={} text={Namespaces} /> { isHidden={!isAllowedResource("events")} url={eventsURL({ query })} routePath={eventRoute.path} - icon={} + icon={} text={Events} /> { url={appsURL({ query })} subMenus={Apps.tabRoutes} routePath={appsRoute.path} - icon={} + icon={} text={Apps} /> { url={usersManagementURL({ query })} routePath={usersManagementRoute.path} subMenus={UserManagement.tabRoutes} - icon={} + icon={} text={Access Control} /> { url={crdURL()} subMenus={CustomResources.tabRoutes} routePath={crdRoute.path} - icon={} + icon={} text={Custom Resources} > {this.renderCustomResources()} @@ -194,7 +199,7 @@ export class Sidebar extends React.Component { url={url} routePath={path} text={title} - icon={} + icon={} /> ) })} @@ -257,7 +262,7 @@ class SidebarNavItem extends React.Component {
{icon} {text} - +
    {subMenus.map(({ title, url }) => ( diff --git a/src/renderer/components/spinner/spinner.scss b/src/renderer/components/spinner/spinner.scss index 802ef27bfc..b8843b542d 100644 --- a/src/renderer/components/spinner/spinner.scss +++ b/src/renderer/components/spinner/spinner.scss @@ -34,6 +34,12 @@ margin-top: calc(var(--spinner-size) / -2); } + &.centerHorizontal { + position: absolute; + left: 50%; + margin-left: calc(var(--spinner-size) / -2); + } + @keyframes rotate { 0% { transform: rotate(0deg); @@ -60,4 +66,4 @@ @include spinner-color(#4285F4); } } -} \ No newline at end of file +} diff --git a/src/renderer/components/spinner/spinner.tsx b/src/renderer/components/spinner/spinner.tsx index 771784a905..0edb2665b1 100644 --- a/src/renderer/components/spinner/spinner.tsx +++ b/src/renderer/components/spinner/spinner.tsx @@ -6,23 +6,19 @@ import { cssNames } from "../../utils"; export interface SpinnerProps extends React.HTMLProps { singleColor?: boolean; center?: boolean; + centerHorizontal?: boolean; } export class Spinner extends React.Component { - private elem: HTMLElement; - static defaultProps = { singleColor: true, center: false, }; render() { - const { center, singleColor, ...props } = this.props; - let { className } = this.props; - className = cssNames('Spinner', className, { - singleColor: singleColor, - center: center, - }); - return
    this.elem = e}/>; + const { center, singleColor, centerHorizontal, className, ...props } = this.props; + const classNames = cssNames('Spinner', className, { singleColor, center, centerHorizontal }); + + return
    ; } } diff --git a/src/renderer/components/table/table-cell.tsx b/src/renderer/components/table/table-cell.tsx index a56f144bc0..d278ad41d8 100644 --- a/src/renderer/components/table/table-cell.tsx +++ b/src/renderer/components/table/table-cell.tsx @@ -2,7 +2,7 @@ import "./table-cell.scss"; import type { TableSortBy, TableSortParams } from "./table"; import React, { ReactNode } from "react"; -import { autobind, cssNames } from "../../utils"; +import { autobind, cssNames, displayBooleans } from "../../utils"; import { Icon } from "../icon"; import { Checkbox } from "../checkbox"; @@ -13,6 +13,7 @@ export interface TableCellProps extends React.DOMAttributes { title?: ReactNode; checkbox?: boolean; // render cell with a checkbox isChecked?: boolean; // mark checkbox as checked or not + renderBoolean?: boolean; // show "true" or "false" for all of the children elements are "typeof boolean" sortBy?: TableSortBy; // column name, must be same as key in sortable object
_sorting?: Partial; //
sorting state, don't use this prop outside (!) _sort?(sortBy: TableSortBy): void; //
sort function, don't use this prop outside (!) @@ -52,20 +53,20 @@ export class TableCell extends React.Component { const { checkbox, isChecked } = this.props; const showCheckbox = isChecked !== undefined; if (checkbox && showCheckbox) { - return + return } } render() { - const { className, checkbox, isChecked, sortBy, _sort, _sorting, _nowrap, children, title, ...cellProps } = this.props; + const { className, checkbox, isChecked, sortBy, _sort, _sorting, _nowrap, children, title, renderBoolean: displayBoolean, ...cellProps } = this.props; const classNames = cssNames("TableCell", className, { checkbox: checkbox, nowrap: _nowrap, sorting: this.isSortable, }); - const content = title || children; + const content = displayBooleans(displayBoolean, title || children) return ( -
+
{this.renderCheckbox()} {_nowrap ?
{content}
: content} {this.renderSortIcon()} diff --git a/src/renderer/utils/__tests__/display-booleans.test.tsx b/src/renderer/utils/__tests__/display-booleans.test.tsx new file mode 100644 index 0000000000..29fdd0574b --- /dev/null +++ b/src/renderer/utils/__tests__/display-booleans.test.tsx @@ -0,0 +1,18 @@ +import React from "react" +import { displayBooleans } from "../display-booleans" + +describe("displayBooleans tests", () => { + it("should not do anything to div's if shouldShow is false", () => { + expect(displayBooleans(false,
)).toStrictEqual(
) + }) + + it("should not do anything to booleans's if shouldShow is false", () => { + expect(displayBooleans(false, true)).toStrictEqual(true) + expect(displayBooleans(false, false)).toStrictEqual(false) + }) + + it("should stringify booleans when shouldShow is true", () => { + expect(displayBooleans(true, true)).toStrictEqual("true") + expect(displayBooleans(true, false)).toStrictEqual("false") + }) +}) diff --git a/src/renderer/utils/display-booleans.ts b/src/renderer/utils/display-booleans.ts new file mode 100644 index 0000000000..c50b7cdf9b --- /dev/null +++ b/src/renderer/utils/display-booleans.ts @@ -0,0 +1,15 @@ +import React from "react" + +export function displayBooleans(shouldShow: boolean, from: React.ReactNode): React.ReactNode { + if (shouldShow) { + if (typeof from === "boolean") { + return from.toString() + } + + if (Array.isArray(from)) { + return from.map(node => displayBooleans(shouldShow, node)) + } + } + + return from +} diff --git a/src/renderer/utils/index.ts b/src/renderer/utils/index.ts index d8c9d692c4..0c2df22c91 100755 --- a/src/renderer/utils/index.ts +++ b/src/renderer/utils/index.ts @@ -18,3 +18,4 @@ export * from "./isReactNode" export * from "./convertMemory" export * from "./convertCpu" export * from "./metricUnitsToNumber" +export * from "./display-booleans" diff --git a/tsconfig.json b/tsconfig.json index 5a61e2ca3e..9cfbd543a8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,7 +4,11 @@ "jsx": "react", "target": "ES2017", "module": "ESNext", - "lib": ["ESNext", "DOM", "DOM.Iterable"], + "lib": [ + "ESNext", + "DOM", + "DOM.Iterable" + ], "moduleResolution": "Node", "sourceMap": true, "strict": false, From cb57e4ed7d11d7ccf2e8e1917a2c61c1d78c7629 Mon Sep 17 00:00:00 2001 From: Jari Kolehmainen Date: Tue, 10 Nov 2020 19:21:48 +0200 Subject: [PATCH 9/9] Release v4.0.0-alpha.5 (#1311) Signed-off-by: Jari Kolehmainen --- package.json | 2 +- static/RELEASE_NOTES.md | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 2d6d20b8a0..62bb57f232 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "kontena-lens", "productName": "Lens", "description": "Lens - The Kubernetes IDE", - "version": "4.0.0-alpha.4", + "version": "4.0.0-alpha.5", "main": "static/build/main.js", "copyright": "© 2020, Mirantis, Inc.", "license": "MIT", diff --git a/static/RELEASE_NOTES.md b/static/RELEASE_NOTES.md index 8012c2c35c..64c57a673a 100644 --- a/static/RELEASE_NOTES.md +++ b/static/RELEASE_NOTES.md @@ -2,15 +2,17 @@ Here you can find description of changes we've built into each release. While we try our best to make each upgrade automatic and as smooth as possible, there may be some cases where you might need to do something to ensure the application works smoothly. So please read through the release highlights! -## 4.0.0-alpha.4 (current version) +## 4.0.0-alpha.5 (current version) - Extension API - Improved pod logs +- Mechanism for users to specify accessible namespaces - Tray icon - Add last-status information for container - Add LoadBalancer information to Ingress view - Move tracker to an extension - Add support page (as an extension) +- Ability to restart deployment - Status bar visual fixes - Fix proxy upgrade socket timeouts - Fix UI staleness after network issues