Merge branch 'master' into electron-11.4.3
Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
@ -40,7 +40,7 @@ jobs:
|
||||
git clone "https://${GH_TOKEN}@github.com/lensapp/lens-ide.git" .lens-ide-overlay
|
||||
rm -rf .lens-ide-overlay/.git
|
||||
cp -r .lens-ide-overlay/* ./
|
||||
cp build/package.json.patch . && patch package.json package.json.patch
|
||||
jq -s '.[0] * .[1]' package.json package.ide.json > package.custom.json && mv package.custom.json package.json
|
||||
displayName: Customize config
|
||||
env:
|
||||
GH_TOKEN: $(LENS_IDE_GH_TOKEN)
|
||||
@ -62,6 +62,7 @@ jobs:
|
||||
WIN_CSC_KEY_PASSWORD: $(WIN_CSC_KEY_PASSWORD)
|
||||
AWS_ACCESS_KEY_ID: $(AWS_ACCESS_KEY_ID)
|
||||
AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY)
|
||||
BUILD_NUMBER: $(Build.BuildNumber)
|
||||
- job: macOS
|
||||
pool:
|
||||
vmImage: macOS-10.14
|
||||
@ -89,7 +90,7 @@ jobs:
|
||||
git clone "https://${GH_TOKEN}@github.com/lensapp/lens-ide.git" .lens-ide-overlay
|
||||
rm -rf .lens-ide-overlay/.git
|
||||
cp -r .lens-ide-overlay/* ./
|
||||
cp build/package.json.patch . && patch package.json package.json.patch
|
||||
jq -s '.[0] * .[1]' package.json package.ide.json > package.custom.json && mv package.custom.json package.json
|
||||
displayName: Customize config
|
||||
env:
|
||||
GH_TOKEN: $(LENS_IDE_GH_TOKEN)
|
||||
@ -113,6 +114,7 @@ jobs:
|
||||
CSC_KEY_PASSWORD: $(CSC_KEY_PASSWORD)
|
||||
AWS_ACCESS_KEY_ID: $(AWS_ACCESS_KEY_ID)
|
||||
AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY)
|
||||
BUILD_NUMBER: $(Build.BuildNumber)
|
||||
- job: Linux
|
||||
pool:
|
||||
vmImage: ubuntu-16.04
|
||||
@ -140,7 +142,7 @@ jobs:
|
||||
git clone "https://${GH_TOKEN}@github.com/lensapp/lens-ide.git" .lens-ide-overlay
|
||||
rm -rf .lens-ide-overlay/.git
|
||||
cp -r .lens-ide-overlay/* ./
|
||||
cp build/package.json.patch . && patch package.json package.json.patch
|
||||
jq -s '.[0] * .[1]' package.json package.ide.json > package.custom.json && mv package.custom.json package.json
|
||||
displayName: Customize config
|
||||
env:
|
||||
GH_TOKEN: $(LENS_IDE_GH_TOKEN)
|
||||
@ -170,8 +172,4 @@ jobs:
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: $(AWS_ACCESS_KEY_ID)
|
||||
AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY)
|
||||
- script: make publish-npm
|
||||
displayName: Publish npm package
|
||||
condition: "and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/'))"
|
||||
env:
|
||||
NPM_TOKEN: $(NPM_TOKEN)
|
||||
BUILD_NUMBER: $(Build.BuildNumber)
|
||||
|
||||
@ -15,3 +15,7 @@ updates:
|
||||
versioning-strategy:
|
||||
lockfile-only: false
|
||||
increase: true
|
||||
ignore:
|
||||
- dependency-name: *
|
||||
update-types:
|
||||
- version-update:semver-major
|
||||
|
||||
34
.eslintrc.js
@ -1,3 +1,24 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OpenLens Authors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
const packageJson = require("./package.json");
|
||||
|
||||
module.exports = {
|
||||
@ -27,9 +48,12 @@ module.exports = {
|
||||
sourceType: "module",
|
||||
},
|
||||
plugins: [
|
||||
"unused-imports"
|
||||
"header",
|
||||
"unused-imports",
|
||||
"react-hooks"
|
||||
],
|
||||
rules: {
|
||||
"header/header": [2, "./license-header"],
|
||||
"indent": ["error", 2, {
|
||||
"SwitchCase": 1,
|
||||
}],
|
||||
@ -72,6 +96,7 @@ module.exports = {
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
],
|
||||
plugins: [
|
||||
"header",
|
||||
"unused-imports"
|
||||
],
|
||||
parserOptions: {
|
||||
@ -79,6 +104,7 @@ module.exports = {
|
||||
sourceType: "module",
|
||||
},
|
||||
rules: {
|
||||
"header/header": [2, "./license-header"],
|
||||
"no-invalid-this": "off",
|
||||
"@typescript-eslint/no-invalid-this": ["error"],
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
@ -127,6 +153,7 @@ module.exports = {
|
||||
],
|
||||
parser: "@typescript-eslint/parser",
|
||||
plugins: [
|
||||
"header",
|
||||
"unused-imports"
|
||||
],
|
||||
extends: [
|
||||
@ -139,6 +166,7 @@ module.exports = {
|
||||
jsx: true,
|
||||
},
|
||||
rules: {
|
||||
"header/header": [2, "./license-header"],
|
||||
"no-invalid-this": "off",
|
||||
"@typescript-eslint/no-invalid-this": ["error"],
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
@ -183,7 +211,9 @@ module.exports = {
|
||||
{ "blankLine": "always", "prev": "*", "next": "class" },
|
||||
{ "blankLine": "always", "prev": ["const", "let", "var"], "next": "*" },
|
||||
{ "blankLine": "any", "prev": ["const", "let", "var"], "next": ["const", "let", "var"]},
|
||||
]
|
||||
],
|
||||
"react-hooks/rules-of-hooks": "error",
|
||||
"react-hooks/exhaustive-deps": "off"
|
||||
},
|
||||
}
|
||||
]
|
||||
|
||||
5
.github/PULL_REQUEST_TEMPLATE/default.md
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
Fixes #
|
||||
|
||||
**Description of changes:**
|
||||
|
||||
-
|
||||
13
.github/PULL_REQUEST_TEMPLATE/release.md
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
## Changes since v
|
||||
|
||||
## 🚀 Features
|
||||
|
||||
*
|
||||
|
||||
## 🐛 Bug Fixes
|
||||
|
||||
*
|
||||
|
||||
## 🧰 Maintenance
|
||||
|
||||
*
|
||||
10
.github/release-drafter.yml
vendored
@ -18,13 +18,3 @@ template: |
|
||||
## Changes since $PREVIOUS_TAG
|
||||
|
||||
$CHANGES
|
||||
|
||||
### Download
|
||||
|
||||
- Lens v$RESOLVED_VERSION - Linux
|
||||
- [AppImage](https://github.com/lensapp/lens/releases/download/v$RESOLVED_VERSION/Lens-$RESOLVED_VERSION.x86_64.AppImage)
|
||||
- [DEB](https://github.com/lensapp/lens/releases/download/v$RESOLVED_VERSION/Lens-$RESOLVED_VERSION.amd64.deb)
|
||||
- [RPM](https://github.com/lensapp/lens/releases/download/v$RESOLVED_VERSION/Lens-$RESOLVED_VERSION.x86_64.rpm)
|
||||
- [Snapcraft](https://snapcraft.io/kontena-lens)
|
||||
- [Lens v$RESOLVED_VERSION - MacOS](https://github.com/lensapp/lens/releases/download/v$RESOLVED_VERSION/Lens-$RESOLVED_VERSION.dmg)
|
||||
- [Lens v$RESOLVED_VERSION - Windows](https://github.com/lensapp/lens/releases/download/v$RESOLVED_VERSION/Lens-Setup-$RESOLVED_VERSION.exe)
|
||||
|
||||
26
.github/workflows/license-header.yml
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
name: Check License Header
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
jobs:
|
||||
css:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Golang
|
||||
uses: actions/setup-go@v2
|
||||
- name: Install addlicense
|
||||
run: |
|
||||
export PATH=${PATH}:`go env GOPATH`/bin
|
||||
go get -v -u github.com/google/addlicense
|
||||
- name: Check license headers
|
||||
run: |
|
||||
set -e
|
||||
export PATH=${PATH}:`go env GOPATH`/bin
|
||||
|
||||
addlicense -check -l mit -c "OpenLens Authors" src/**/*.?css
|
||||
35
.github/workflows/publish-master-npm.yml
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
name: Publish NPM Package `master`
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
jobs:
|
||||
publish:
|
||||
name: Publish NPM Package `master`
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
${{ github.event.pull_request.merged == true && contains(github.event.pull_request.labels.*.name, 'area/extension') }}
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x]
|
||||
steps:
|
||||
- name: Checkout Release
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Using Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Generate NPM package
|
||||
run: |
|
||||
make build-npm
|
||||
|
||||
- name: publish new release
|
||||
run: |
|
||||
make publish-npm
|
||||
env:
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
NPM_RELEASE_TAG: master
|
||||
33
.github/workflows/publish-release-npm.yml
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
name: Publish NPM Package Release
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
jobs:
|
||||
publish:
|
||||
name: Publish NPM Package Release
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x]
|
||||
steps:
|
||||
- name: Checkout Release
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Using Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Generate NPM package
|
||||
run: |
|
||||
make build-npm
|
||||
|
||||
- name: publish new release
|
||||
if: contains(github.ref, 'refs/tags/v')
|
||||
run: |
|
||||
make publish-npm
|
||||
env:
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
49
Makefile
@ -3,6 +3,7 @@ CMD_ARGS = $(filter-out $@,$(MAKECMDGOALS))
|
||||
%:
|
||||
@:
|
||||
|
||||
NPM_RELEASE_TAG ?= latest
|
||||
EXTENSIONS_DIR = ./extensions
|
||||
extensions = $(foreach dir, $(wildcard $(EXTENSIONS_DIR)/*), ${dir})
|
||||
extension_node_modules = $(foreach dir, $(wildcard $(EXTENSIONS_DIR)/*), ${dir}/node_modules)
|
||||
@ -14,13 +15,13 @@ else
|
||||
DETECTED_OS := $(shell uname)
|
||||
endif
|
||||
|
||||
binaries/client: node_modules
|
||||
yarn download-bins
|
||||
|
||||
node_modules: yarn.lock
|
||||
yarn install --frozen-lockfile --network-timeout=100000
|
||||
yarn check --verify-tree --integrity
|
||||
|
||||
binaries/client: node_modules
|
||||
yarn download-bins
|
||||
|
||||
static/build/LensDev.html: node_modules
|
||||
yarn compile:renderer
|
||||
|
||||
@ -37,17 +38,20 @@ dev: binaries/client build-extensions static/build/LensDev.html
|
||||
lint:
|
||||
yarn lint
|
||||
|
||||
.PHONY: release-version
|
||||
release-version:
|
||||
npm version $(CMD_ARGS) --git-tag-version false
|
||||
|
||||
.PHONY: tag-release
|
||||
tag-release:
|
||||
scripts/tag-release.sh
|
||||
|
||||
.PHONY: test
|
||||
test: binaries/client
|
||||
yarn run jest $(or $(CMD_ARGS), "src")
|
||||
|
||||
.PHONY: integration-linux
|
||||
integration-linux: binaries/client build-extension-types build-extensions
|
||||
# ifdef XDF_CONFIG_HOME
|
||||
# rm -rf ${XDG_CONFIG_HOME}/.config/Lens
|
||||
# else
|
||||
# rm -rf ${HOME}/.config/Lens
|
||||
# endif
|
||||
yarn build:linux
|
||||
yarn integration
|
||||
|
||||
@ -65,21 +69,26 @@ integration-win: binaries/client build-extension-types build-extensions
|
||||
|
||||
.PHONY: build
|
||||
build: node_modules binaries/client build-extensions
|
||||
yarn run npm:fix-build-version
|
||||
yarn run compile
|
||||
ifeq "$(DETECTED_OS)" "Windows"
|
||||
./node_modules/.bin/electron-builder --publish onTag --x64 --ia32
|
||||
yarn run electron-builder --publish onTag --x64 --ia32
|
||||
else
|
||||
./node_modules/.bin/electron-builder --publish onTag
|
||||
yarn run electron-builder --publish onTag
|
||||
endif
|
||||
|
||||
$(extension_node_modules):
|
||||
cd $(@:/node_modules=) && npm install --no-audit --no-fund
|
||||
$(extension_node_modules): node_modules
|
||||
cd $(@:/node_modules=) && ../../node_modules/.bin/npm install --no-audit --no-fund
|
||||
|
||||
$(extension_dists): src/extensions/npm/extensions/dist
|
||||
cd $(@:/dist=) && npm run build
|
||||
cd $(@:/dist=) && ../../node_modules/.bin/npm run build
|
||||
|
||||
.PHONY: clean-old-extensions
|
||||
clean-old-extensions:
|
||||
find ./extensions -mindepth 1 -maxdepth 1 -type d '!' -exec test -e '{}/package.json' \; -exec rm -rf {} \;
|
||||
|
||||
.PHONY: build-extensions
|
||||
build-extensions: node_modules $(extension_node_modules) $(extension_dists)
|
||||
build-extensions: node_modules clean-old-extensions $(extension_node_modules) $(extension_dists)
|
||||
|
||||
.PHONY: test-extensions
|
||||
test-extensions: $(extension_node_modules)
|
||||
@ -93,7 +102,7 @@ copy-extension-themes:
|
||||
src/extensions/npm/extensions/__mocks__:
|
||||
cp -r __mocks__ src/extensions/npm/extensions/
|
||||
|
||||
src/extensions/npm/extensions/dist:
|
||||
src/extensions/npm/extensions/dist: node_modules
|
||||
yarn compile:extension-types
|
||||
|
||||
.PHONY: build-npm
|
||||
@ -101,12 +110,13 @@ build-npm: build-extension-types copy-extension-themes src/extensions/npm/extens
|
||||
yarn npm:fix-package-version
|
||||
|
||||
.PHONY: build-extension-types
|
||||
build-extension-types: src/extensions/npm/extensions/dist
|
||||
build-extension-types: node_modules src/extensions/npm/extensions/dist
|
||||
|
||||
.PHONY: publish-npm
|
||||
publish-npm: build-npm
|
||||
npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}"
|
||||
cd src/extensions/npm/extensions && npm publish --access=public
|
||||
publish-npm: node_modules build-npm
|
||||
./node_modules/.bin/npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}"
|
||||
cd src/extensions/npm/extensions && npm publish --access=public --tag=$(NPM_RELEASE_TAG)
|
||||
git restore src/extensions/npm/extensions/package.json
|
||||
|
||||
.PHONY: docs
|
||||
docs:
|
||||
@ -116,6 +126,7 @@ docs:
|
||||
clean-extensions:
|
||||
$(foreach dir, $(wildcard $(EXTENSIONS_DIR)/*), rm -rf $(dir)/dist)
|
||||
$(foreach dir, $(wildcard $(EXTENSIONS_DIR)/*), rm -rf $(dir)/node_modules)
|
||||
$(foreach dir, $(wildcard $(EXTENSIONS_DIR)/*), rm $(dir)/*.tgz || true)
|
||||
|
||||
.PHONY: clean-npm
|
||||
clean-npm:
|
||||
|
||||
@ -2,10 +2,20 @@
|
||||
|
||||
Lens releases are built by CICD automatically on git tags. The typical release process flow is the following:
|
||||
|
||||
1. Create a release branch `release/v{version}` from `master` branch or from existing release branch (for example, `release/v3.5`) on patch releases.
|
||||
2. Update changelog in `static/RELEASE_NOTES.md` and bump version in `package.json`.
|
||||
3. Create PR and put change log in description field.
|
||||
4. After the PR is accepted, create a tag from release branch.
|
||||
5. Push tag to GitHub.
|
||||
6. Publish automatically created GitHub release.
|
||||
7. Merge the release PR after the release is published and delete the release branch from GitHub.
|
||||
1. From a clean and up to date `master` run `make release-version <version-type>` where `<version-type>` is one of the following:
|
||||
- `major`
|
||||
- `minor`
|
||||
- `patch`
|
||||
- `premajor`
|
||||
- `preminor`
|
||||
- `prepatch`
|
||||
- `prerelease [--preid=<prerelease-id>]`
|
||||
- where `<prerelease-id>` is generally one of:
|
||||
- `alpha`
|
||||
- `beta`
|
||||
- `rc`
|
||||
1. Create PR (git should have printed a link to GitHub in the console) with the contents of all the accepted PRs since the last release.
|
||||
1. After the PR is accepted and passes CI. Go to the same branch and run `make tag-release`
|
||||
1. Once CI passes again go to the releases tab on GitHub, create a new release from the tag that was created, make sure that the change log is the same as that of the PR.
|
||||
1. Merge the release PR after the release is published. GitHub should delete the branch once it is merged.
|
||||
1. If you have just released a new major or minor version then create a new `vMAJOR.MINOR` branch from that same tag and push it to master. This will be the target for future patch releases and shouldn't be deleted.
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
module.exports = {
|
||||
Trans: ({ children }: { children: React.ReactNode }) => children,
|
||||
t: (message: string) => message
|
||||
};
|
||||
@ -1,4 +1,24 @@
|
||||
module.exports = {
|
||||
/**
|
||||
* Copyright (c) 2021 OpenLens Authors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
export default {
|
||||
require: jest.fn(),
|
||||
match: jest.fn(),
|
||||
app: {
|
||||
|
||||
@ -1 +1,22 @@
|
||||
module.exports = {};
|
||||
/**
|
||||
* Copyright (c) 2021 OpenLens Authors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
export default {};
|
||||
|
||||
@ -1 +1,21 @@
|
||||
module.exports = {};
|
||||
/**
|
||||
* Copyright (c) 2021 OpenLens Authors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
export default {};
|
||||
|
||||
@ -1,5 +1,23 @@
|
||||
// Generate tray icons from SVG to PNG + different sizes and colors (B&W)
|
||||
// Command: `yarn build:tray-icons`
|
||||
/**
|
||||
* Copyright (c) 2021 OpenLens Authors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
import path from "path";
|
||||
import sharp from "sharp";
|
||||
import jsdom from "jsdom";
|
||||
|
||||
@ -1,3 +1,23 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OpenLens Authors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
import { helmCli } from "../src/main/helm/helm-cli";
|
||||
|
||||
helmCli.ensureBinary();
|
||||
|
||||
@ -1,3 +1,23 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OpenLens Authors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
import packageInfo from "../package.json";
|
||||
import fs from "fs";
|
||||
import request from "request";
|
||||
@ -5,6 +25,7 @@ import md5File from "md5-file";
|
||||
import requestPromise from "request-promise-native";
|
||||
import { ensureDir, pathExists } from "fs-extra";
|
||||
import path from "path";
|
||||
import { noop } from "../src/common/utils";
|
||||
|
||||
class KubectlDownloader {
|
||||
public kubectlVersion: string;
|
||||
@ -26,7 +47,7 @@ class KubectlDownloader {
|
||||
method: "HEAD",
|
||||
uri: this.url,
|
||||
resolveWithFullResponse: true
|
||||
}).catch((error) => { console.log(error); });
|
||||
}).catch(console.error);
|
||||
|
||||
if (response.headers["etag"]) {
|
||||
return response.headers["etag"].replace(/"/g, "");
|
||||
@ -42,7 +63,7 @@ class KubectlDownloader {
|
||||
const hash = md5File.sync(this.path);
|
||||
const etag = await this.urlEtag();
|
||||
|
||||
if(hash == etag) {
|
||||
if (hash == etag) {
|
||||
console.log("Kubectl md5sum matches the remote etag");
|
||||
|
||||
return true;
|
||||
@ -56,13 +77,10 @@ class KubectlDownloader {
|
||||
}
|
||||
|
||||
public async downloadKubectl() {
|
||||
const exists = await this.checkBinary();
|
||||
|
||||
if(exists) {
|
||||
console.log("Already exists and is valid");
|
||||
|
||||
return;
|
||||
if (await this.checkBinary()) {
|
||||
return console.log("Already exists and is valid");
|
||||
}
|
||||
|
||||
await ensureDir(path.dirname(this.path), 0o755);
|
||||
|
||||
const file = fs.createWriteStream(this.path);
|
||||
@ -76,18 +94,16 @@ class KubectlDownloader {
|
||||
|
||||
stream.on("complete", () => {
|
||||
console.log("kubectl binary download finished");
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
file.end(() => {});
|
||||
file.end(noop);
|
||||
});
|
||||
|
||||
stream.on("error", (error) => {
|
||||
console.log(error);
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
fs.unlink(this.path, () => {});
|
||||
throw(error);
|
||||
fs.unlink(this.path, noop);
|
||||
throw error;
|
||||
});
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
file.on("close", () => {
|
||||
console.log("kubectl binary download closed");
|
||||
fs.chmod(this.path, 0o755, (err) => {
|
||||
@ -116,4 +132,3 @@ downloads.forEach((dlOpts) => {
|
||||
console.log(`Downloading: ${JSON.stringify(dlOpts)}`);
|
||||
downloader.downloadKubectl().then(() => downloader.checkBinary().then(() => console.log("Download complete")));
|
||||
});
|
||||
|
||||
|
||||
@ -1,3 +1,23 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OpenLens Authors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
const { notarize } = require("electron-notarize");
|
||||
|
||||
exports.default = async function notarizing(context) {
|
||||
|
||||
55
build/set_build_version.ts
Normal file
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OpenLens Authors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
import appInfo from "../package.json";
|
||||
import semver from "semver";
|
||||
import fastGlob from "fast-glob";
|
||||
|
||||
const packagePath = path.join(__dirname, "../package.json");
|
||||
const versionInfo = semver.parse(appInfo.version);
|
||||
const buildNumber = process.env.BUILD_NUMBER || "1";
|
||||
let buildChannel = "alpha";
|
||||
|
||||
if (versionInfo.prerelease) {
|
||||
if (versionInfo.prerelease.includes("alpha")) {
|
||||
buildChannel = "alpha";
|
||||
} else {
|
||||
buildChannel = "beta";
|
||||
}
|
||||
appInfo.version = `${versionInfo.major}.${versionInfo.minor}.${versionInfo.patch}-${buildChannel}.${versionInfo.prerelease[1]}.${buildNumber}`;
|
||||
} else {
|
||||
appInfo.version = `${appInfo.version}-latest.${buildNumber}`;
|
||||
}
|
||||
|
||||
|
||||
fs.writeFileSync(packagePath, `${JSON.stringify(appInfo, null, 2)}\n`);
|
||||
|
||||
const extensionManifests = fastGlob.sync(["extensions/*/package.json"]);
|
||||
|
||||
for (const manifestPath of extensionManifests) {
|
||||
const packagePath = path.join(__dirname, "..", manifestPath);
|
||||
|
||||
import(packagePath).then((packageInfo) => {
|
||||
packageInfo.default.version = `${versionInfo.raw}.${Date.now()}`;
|
||||
fs.writeFileSync(packagePath, `${JSON.stringify(packageInfo.default, null, 2)}\n`);
|
||||
});
|
||||
}
|
||||
@ -1,9 +1,41 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OpenLens Authors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
import packageInfo from "../src/extensions/npm/extensions/package.json";
|
||||
import appInfo from "../package.json";
|
||||
import { SemVer } from "semver";
|
||||
import { execSync } from "child_process";
|
||||
|
||||
const packagePath = path.join(__dirname, "../src/extensions/npm/extensions/package.json");
|
||||
const { NPM_RELEASE_TAG = "latest" } = process.env;
|
||||
const version = new SemVer(appInfo.version);
|
||||
|
||||
packageInfo.version = appInfo.version;
|
||||
fs.writeFileSync(packagePath, `${JSON.stringify(packageInfo, null, 2)}\n`);
|
||||
if (NPM_RELEASE_TAG !== "latest") {
|
||||
const gitRef = execSync("git rev-parse --short HEAD", {
|
||||
encoding: "utf-8",
|
||||
});
|
||||
|
||||
version.inc("prerelease", `git.${gitRef.trim()}`);
|
||||
}
|
||||
|
||||
packageInfo.version = version.format();
|
||||
|
||||
fs.writeFileSync(path.join(__dirname, "../src/extensions/npm/extensions/package.json"), `${JSON.stringify(packageInfo, null, 2)}\n`);
|
||||
|
||||
@ -1 +1 @@
|
||||
docs.k8slens.dev
|
||||
api-docs.k8slens.dev
|
||||
|
||||
@ -1,21 +1,46 @@
|
||||
# Overview
|
||||
# Lens Extension API
|
||||
|
||||
Lens is the most powerful Kubernetes IDE on the market. It is a standalone application, and it is available on macOS, Windows, and Linux. Some of the benefits of using Lens include:
|
||||
Customize and enhance the Lens experience with the Lens Extension API.
|
||||
Use the extension API to create menus or page content.
|
||||
The same extension API was used to create many of Lens's core features.
|
||||
To install your first extension you should goto the [extension page](lens://app/extensions) in lens.
|
||||
|
||||
* Confidence that your clusters are properly setup and configured.
|
||||
* Increased visibility, real time statistics, log streams, and hands-on troubleshooting capabilities.
|
||||
* The ability to work with your clusters quickly and easily, radically improving productivity and the speed of business.
|
||||
This documentation describes:
|
||||
|
||||
Watch this introductory video to see Lens in action:
|
||||
* How to build, run, test, and publish an extension.
|
||||
* How to take full advantage of the Lens Extension API.
|
||||
* Where to find [guides](extensions/guides/README.md) and [code samples](https://github.com/lensapp/lens-extension-samples) to help get you started.
|
||||
|
||||
[](https://www.youtube.com/watch?v=eeDwdVXattc)
|
||||
## What Extensions Can Do
|
||||
|
||||
**Note:** Use CTRL+click (on Windows and Linux) or CMD+click (on MacOS) to open the above in a new tab
|
||||
Here are some examples of what you can achieve with the Extension API:
|
||||
|
||||
* Add custom components & views in the UI - Extending the Lens Workbench
|
||||
|
||||
For an overview of the Lens Extension API, refer to the [Common Capabilities](extensions/capabilities/common-capabilities.md) page. [Extension Guides Overview](extensions/guides/README.md) also includes a list of code samples and guides that illustrate various ways of using the Lens Extension API.
|
||||
|
||||
## How to Build Extensions
|
||||
|
||||
Here is what each section of the Lens Extension API docs can help you with:
|
||||
|
||||
* **Getting Started** teaches fundamental concepts for building extensions with the Hello World sample.
|
||||
* **Extension Capabilities** dissects Lens's Extension API into smaller categories and points you to more detailed topics.
|
||||
* **Extension Guides** includes guides and code samples that explain specific usages of Lens Extension API.
|
||||
* **Testing and Publishing** includes in-depth guides on various extension development topics, such as testing and publishing extensions.
|
||||
* **API Reference** contains exhaustive references for the Lens Extension API, Contribution Points, and many other topics.
|
||||
|
||||
## What's New
|
||||
|
||||
Just like Lens itself, the extension API updates on a monthly cadence, rolling out new features with every release.
|
||||
|
||||
Keep up with Lens and the Lens Extension API by reviewing the [release notes](https://github.com/lensapp/lens/releases).
|
||||
|
||||
## Looking for Help
|
||||
|
||||
If you have questions for extension development, try asking on the [Lens Dev Slack](http://k8slens.slack.com/). It's a public chatroom for Lens developers, where Lens team members chime in from time to time.
|
||||
|
||||
To provide feedback on the documentation or issues with the Lens Extension API, create new issues at [lensapp/lens](https://github.com/lensapp/lens/issues). Please use the labels `area/documentation` and/or `area/extension`.
|
||||
|
||||
## Downloading Lens
|
||||
|
||||
[Download Lens](https://github.com/lensapp/lens/releases) for macOS, Windows, or Linux.
|
||||
|
||||
## Quick Start
|
||||
|
||||
Get up and running quickly by learning to [add clusters](clusters/adding-clusters.md).
|
||||
|
||||
@ -1,22 +0,0 @@
|
||||
# Adding Clusters
|
||||
|
||||
Add clusters by clicking the **Add Cluster** button in the left-side menu.
|
||||
|
||||
1. Click the **Add Cluster** button (indicated with a '+' icon). Or [click here](lens://app/cluster).
|
||||
2. Enter the path to your kubeconfig file. You'll need to have a kubeconfig file for the cluster you want to add. You can either browse for the path from the file system or or enter it directly.
|
||||
|
||||
Selected [cluster contexts](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/#context) are added as a separate item in the left-side cluster menu to allow you to operate easily on multiple clusters and/or contexts.
|
||||
|
||||
**NOTE**: Any cluster that you added manually will not be merged into your kubeconfig file.
|
||||
|
||||

|
||||
|
||||
For more information on kubeconfig see [Kubernetes docs](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/).
|
||||
|
||||
To see your currently-enabled config with `kubectl`, enter `kubectl config view --minify --raw` in your terminal.
|
||||
|
||||
When connecting to a cluster, make sure you have a valid and working kubeconfig for the cluster. Following lists known "gotchas" in some authentication types used in kubeconfig with Lens app.
|
||||
|
||||
## Exec auth plugins
|
||||
|
||||
When using [exec auth](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#configuration) plugins make sure the paths that are used to call any binaries are full paths as Lens app might not be able to call binaries with relative paths. Make also sure that you pass all needed information either as arguments or env variables in the config, Lens app might not have all login shell env variables set automatically.
|
||||
|
Before Width: | Height: | Size: 611 KiB |
|
Before Width: | Height: | Size: 284 KiB |
|
Before Width: | Height: | Size: 315 KiB |
|
Before Width: | Height: | Size: 311 KiB |
|
Before Width: | Height: | Size: 338 KiB |
|
Before Width: | Height: | Size: 170 KiB |
|
Before Width: | Height: | Size: 262 KiB |
|
Before Width: | Height: | Size: 90 KiB |
@ -1,12 +0,0 @@
|
||||
# Removing Clusters
|
||||
|
||||
Remove Lens clusters using the context menu that appears when you right-click the cluster in the left-side menu that you want to remove.
|
||||
|
||||
To remove a cluster from your cluster list:
|
||||
|
||||
1. Right-click the name of the cluster in the left-side menu that you want to remove.
|
||||
2. Click **Remove**.
|
||||
|
||||
**NOTE**: This will only remove the cluster from your Lens cluster list. It will not affect your actual Kubernetes cluster or its configuration.
|
||||
|
||||

|
||||
@ -1,75 +0,0 @@
|
||||
# Settings
|
||||
|
||||
It is easy to configure Lens Clusters to your liking through its various settings.
|
||||
|
||||
1. Right-click the name of the cluster in the left-side menu that you want to open the settings for.
|
||||
2. Click **Settings**.
|
||||
|
||||

|
||||
|
||||
## Status
|
||||
|
||||
Overview of the cluster status
|
||||
|
||||
### Cluster Status
|
||||
|
||||
Cluster status information including the detected distribution, kernel version, API endpoint, and online status
|
||||
|
||||

|
||||
|
||||
## General
|
||||
|
||||
General cluster settings
|
||||
|
||||
### Cluster Name
|
||||
|
||||
The cluster name is inheritated by default from the kubeconfig file. Change the cluster name to another value by updating it here. Note that doing so does not update your kubeconfig file.
|
||||
|
||||
### Workspace
|
||||
|
||||
This is the Lens workspace that the cluster is associated with. Change workspaces by selecting a different workspace from the dropdown menu. Create a new workspace by clicking **workspace** in "Define cluster workspace" above the dropdown menu. This option will take you the workspaces editor. Create a new workspace and then navigate back to cluster settings.
|
||||
|
||||
### Cluster Icon
|
||||
|
||||
Lens randomly generates an icon to associate with each newly-created cluster. Use this setting to choose your own icon.
|
||||
|
||||
### HTTP Proxy
|
||||
|
||||
Some users will need to define an HTTP proxy for communicating with the Kubernetes API. Use this setting to do so.
|
||||
|
||||
### Prometheus
|
||||
|
||||
Lens can be configured to query a Prometheus server installed in the cluster. Select a query format by choosing either to auto-detect or from the following configurations:
|
||||
|
||||
* Lens
|
||||
* Helm Operator
|
||||
* Prometheus Operator
|
||||
* Stacklight
|
||||
|
||||
To learn more about custom Prometheus configurations, please refer to this [guide](https://github.com/lensapp/lens/blob/master/troubleshooting/custom-prometheus.md).
|
||||
|
||||
### Working Directory
|
||||
|
||||
Use this field to set the terminal working directory. The default is `$HOME`.
|
||||
|
||||

|
||||
|
||||
## Features
|
||||
|
||||
Additional Lens features that can be installed by the user
|
||||
|
||||
### Metrics
|
||||
|
||||
Enable timeseries data visualization (Prometheus stack) for your cluster. Install this only if you don't have existing Prometheus stack installed.
|
||||
|
||||
### User Mode
|
||||
|
||||
User Mode feature enables non-admin users to see namespaces they have access to. This is achieved by configuring RBAC rules so that every authenticated user is granted to list namespaces.
|
||||
|
||||

|
||||
|
||||
## Removal
|
||||
|
||||
Use this setting to remove the current cluster.
|
||||
|
||||

|
||||
@ -1,17 +0,0 @@
|
||||
# Contributing
|
||||
|
||||
There are multiple ways you can contribute to Lens. Even if you are not a developer, you can still contribute. We are always looking for assistance with creating or updating documentation, testing the application, reporting, and troubleshooting issues.
|
||||
|
||||
Here are some ways you can contribute!
|
||||
|
||||
* [Development](./development.md) – Help make Lens better.
|
||||
* [Maintaining the Project](./maintainers.md) – Become a community maintainer and help us maintain the project.
|
||||
* [Extension Development](../extensions) – Add integrations via Lens Extensions.
|
||||
* [Documentation](./documentation.md) – Help improve Lens documentation.
|
||||
* [Promotion](./promotion.md) – Show your support, be an ambassador to Lens, write blogs, and make videos!
|
||||
|
||||
If you are an influencer, blogger, or journalist, feel free to [spread the word](./promotion.md)!
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project adheres to the [Contributor Covenant](https://www.contributor-covenant.org/) code of conduct. By participating and contributing to Lens, you are expected to uphold this code. Please report unacceptable behaviour to info@k8slens.dev.
|
||||
@ -1,43 +0,0 @@
|
||||
# Development
|
||||
|
||||
Thank you for taking the time to make a contribution to Lens. The following document is a set of guidelines and instructions for contributing to Lens.
|
||||
|
||||
When contributing to this repository, please consider first discussing the change you wish to make by opening an issue.
|
||||
|
||||
## Recommended Reading:
|
||||
|
||||
- [TypeScript](https://www.typescriptlang.org/docs/home.html) (front-end/back-end)
|
||||
- [ReactJS](https://reactjs.org/docs/getting-started.html) (front-end, ui)
|
||||
- [MobX](https://mobx.js.org/) (app-state-management, back-end/front-end)
|
||||
- [ElectronJS](https://www.electronjs.org/docs) (chrome/node)
|
||||
- [NodeJS](https://nodejs.org/dist/latest-v12.x/docs/api/) (api docs)
|
||||
|
||||
## Local Development Environment
|
||||
|
||||
> Prerequisites: Nodejs v12, make, yarn
|
||||
|
||||
* `make dev` - builds and starts the app
|
||||
* `make clean` - cleanup local environment build artifacts
|
||||
|
||||
### Developing on Windows
|
||||
|
||||
On Windows we only support [Git Bash](https://gitforwindows.org/) (or similar shell) for running commands.
|
||||
|
||||
## Github Workflow
|
||||
|
||||
We Use [Github Flow](https://guides.github.com/introduction/flow/index.html), so all code changes are tracked via Pull Requests.
|
||||
A detailed guide on the recommended workflow can be found below:
|
||||
|
||||
* [Github Workflow](./github_workflow.md)
|
||||
|
||||
## Code Testing
|
||||
|
||||
All submitted PRs go through a set of tests and reviews. You can run most of these tests *before* a PR is submitted.
|
||||
In fact, we recommend it, because it will save on many possible review iterations and automated tests.
|
||||
The testing guidelines can be found here:
|
||||
|
||||
* [Contributor's Guide to Testing](./testing.md)
|
||||
|
||||
## License
|
||||
|
||||
By contributing, you agree that your contributions will be licensed as described in [LICENSE](https://github.com/lensapp/lens/blob/master/LICENSE).
|
||||
@ -1,33 +0,0 @@
|
||||
# Documentation
|
||||
|
||||
We are glad to see you're interested in contributing to the Lens documentation. If this is the first Open Source project you've contributed to, we strongly suggest reading GitHub's excellent guide: [How to Contribute to Open Source](https://opensource.guide/how-to-contribute).
|
||||
|
||||
## Finding Documentation Issues to Work On
|
||||
|
||||
You can find a list of open documentation-related issues [here](https://github.com/lensapp/lens/issues?q=is%3Aopen+is%3Aissue+label%3Aarea%2Fdocumentation). When you find something you would like to work on:
|
||||
|
||||
1. Express your interest to start working on an issue via comments.
|
||||
2. One of the maintainers will assign the issue for you.
|
||||
3. You can start working on the issue. When you're done, simply submit a pull request.
|
||||
|
||||
## Requirements for Documentation Pull Requests
|
||||
|
||||
When you create a new pull request, we expect some requirements to be met.
|
||||
|
||||
* Follow this naming convention for Pull Requests:
|
||||
* When adding new documentation, add `New Documentation:` before the title. E.g. `New Documentation: Getting Started`
|
||||
* When fixing documentation, add `Fix Documentation:` before the title. E.g. `Fix Documentation: Getting Started`
|
||||
* When updating documentation, add `Update Documentation:` before the title. E.g. `Update Documentation: Getting Started`
|
||||
* If your Pull Request closes an issue, you must write `Closes #ISSUE_NUMBER` where the ISSUE_NUMBER is the number in the end of the link url or the relevent issue. This will link your pull request to the issue, and when it is merged, the issue will close.
|
||||
* For each pull request made, we run tests to check if there are any broken links, the markdown formatting is valid, and the linter is passing.
|
||||
|
||||
|
||||
## Testing Documentation Site Locally
|
||||
|
||||
Run a local instance of `mkdocs` in a docker container for developing the Lens Documentation.
|
||||
|
||||
> Prerequisites: docker, yarn
|
||||
|
||||
* `make docs` - local build and serve of mkdocs with auto update enabled
|
||||
|
||||
Go to [localhost:8000](http://127.0.0.1:8000).
|
||||
@ -1,148 +0,0 @@
|
||||
# Github Workflow
|
||||
|
||||
<!-- TOC -->
|
||||
- [Fork The Project](#fork-the-project)
|
||||
- [Adding the Forked Remote](#adding-the-forked-remote)
|
||||
- [Create & Rebase Your Feature Branch](#create--rebase-your-feature-branch)
|
||||
- [Commit & Push](#commit--push)
|
||||
- [Open a Pull Request](#open-a-pull-request)
|
||||
- [Get a code review](#get-a-code-review)
|
||||
- [Squash commits](#squash-commits)
|
||||
- [Push Your Final Changes](#push-your-final-changes)
|
||||
|
||||
<!-- /TOC -->
|
||||
This guide assumes you have already cloned the upstream repo to your system via git clone.
|
||||
|
||||
## Fork The Project
|
||||
|
||||
1. Go to [http://github.com/lensapp/lens](http://github.com/lensapp/lens)
|
||||
2. On the top, right-hand side, click on "fork" and select your username for the fork destination.
|
||||
|
||||
## Adding the Forked Remote
|
||||
|
||||
```
|
||||
export GITHUB_USER={ your github's username }
|
||||
|
||||
cd $WORKDIR/lens
|
||||
git remote add $GITHUB_USER git@github.com:${GITHUB_USER}/lens.git
|
||||
|
||||
# Prevent push to Upstream
|
||||
git remote set-url --push origin no_push
|
||||
|
||||
# Set your fork remote as a default push target
|
||||
git push --set-upstream $GITHUB_USER master
|
||||
```
|
||||
|
||||
Your remotes should look something like this:
|
||||
|
||||
```
|
||||
➜ git remote -v
|
||||
origin https://github.com/lensapp/lens (fetch)
|
||||
origin no_push (push)
|
||||
my_fork git@github.com:{ github_username }/lens.git (fetch)
|
||||
my_fork git@github.com:{ github_username }/lens.git (push)
|
||||
```
|
||||
|
||||
## Create & Rebase Your Feature Branch
|
||||
|
||||
Create a feature branch:
|
||||
|
||||
```
|
||||
git branch -b my_feature_branch
|
||||
```
|
||||
|
||||
Rebase your branch:
|
||||
|
||||
```
|
||||
git fetch origin
|
||||
|
||||
git rebase origin/master
|
||||
Current branch my_feature_branch is up to date.
|
||||
```
|
||||
|
||||
Please don't use `git pull` instead of the above `fetch / rebase`. `git pull` does a merge, which leaves merge commits. These make the commit history messy and violate the principle that commits ought to be individually understandable and useful.
|
||||
|
||||
## Commit & Push
|
||||
|
||||
Commit and sign your changes:
|
||||
|
||||
```
|
||||
git commit -m "my commit title" --signoff
|
||||
```
|
||||
|
||||
You can go back and edit/build/test some more, then `commit --amend` in a few cycles.
|
||||
|
||||
When ready, push your changes to your fork's repository:
|
||||
|
||||
```
|
||||
git push --set-upstream my_fork my_feature_branch
|
||||
```
|
||||
|
||||
## Open a Pull Request
|
||||
|
||||
See [Github Docs](https://docs.github.com/en/free-pro-team@latest/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request-from-a-fork).
|
||||
|
||||
### Get a code review
|
||||
|
||||
Once your pull request has been opened it will be assigned to one or more reviewers, and will go through a series of smoke tests.
|
||||
|
||||
Commit changes made in response to review comments should be added to the same branch on your fork.
|
||||
|
||||
Very small PRs are easy to review. Very large PRs are very difficult to review.
|
||||
|
||||
### Squashing Commits
|
||||
Commits on your branch should represent meaningful milestones or units of work.
|
||||
Small commits that contain typo fixes, rebases, review feedbacks, etc should be squashed.
|
||||
|
||||
To do that, it's best to perform an [interactive rebase](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History):
|
||||
|
||||
#### Example
|
||||
If you PR has 3 commits, count backwards from your last commit using `HEAD~3`:
|
||||
```
|
||||
git rebase -i HEAD~3
|
||||
```
|
||||
Output would be similar to this:
|
||||
```
|
||||
pick f7f3f6d Changed some code
|
||||
pick 310154e fixed some typos
|
||||
pick a5f4a0d made some review changes
|
||||
|
||||
# Rebase 710f0f8..a5f4a0d onto 710f0f8
|
||||
#
|
||||
# Commands:
|
||||
# p, pick <commit> = use commit
|
||||
# r, reword <commit> = use commit, but edit the commit message
|
||||
# e, edit <commit> = use commit, but stop for amending
|
||||
# s, squash <commit> = use commit, but meld into previous commit
|
||||
# f, fixup <commit> = like "squash", but discard this commit's log message
|
||||
# x, exec <command> = run command (the rest of the line) using shell
|
||||
# b, break = stop here (continue rebase later with 'git rebase --continue')
|
||||
# d, drop <commit> = remove commit
|
||||
# l, label <label> = label current HEAD with a name
|
||||
# t, reset <label> = reset HEAD to a label
|
||||
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
|
||||
# . create a merge commit using the original merge commit's
|
||||
# . message (or the oneline, if no original merge commit was
|
||||
# . specified). Use -c <commit> to reword the commit message.
|
||||
#
|
||||
# These lines can be re-ordered; they are executed from top to bottom.
|
||||
#
|
||||
# However, if you remove everything, the rebase will be aborted.
|
||||
#
|
||||
# Note that empty commits are commented out
|
||||
```
|
||||
Use a command line text editor to change the word `pick` to `fixup` for the commits you want to squash, then save your changes and continue the rebase:
|
||||
|
||||
Per the output above, you can see that:
|
||||
```
|
||||
fixup <commit> = like "squash", but discard this commit's log message
|
||||
```
|
||||
Which means that when rebased, the commit message "fixed some typos" will be removed, and squashed with the parent commit.
|
||||
|
||||
### Push Your Final Changes
|
||||
|
||||
Once done, you can push the final commits to your branch:
|
||||
```
|
||||
git push --force
|
||||
```
|
||||
You can run multiple iteration of `rebase`/`push -f`, if needed.
|
||||
@ -1,17 +0,0 @@
|
||||
# Maintainers
|
||||
|
||||
We are looking for community maintainers for the Lens project. Maintainers will be added to a special team with write permissions. These permissions consist of opening, closing, tagging, and editing issues and pull requests, as well as creating and deleting non-protected branches.
|
||||
|
||||
The responsibilities of a community maintainer are listed below.
|
||||
|
||||
## Issues Triage
|
||||
|
||||
* **Labeling Issues:** Label issues accordingly.
|
||||
* **Finding Duplicates:** Finding and closing duplicate issues.
|
||||
* **Doing First Level Contact:** Getting more information on the issues (like version number or asking for clarification) if needed.
|
||||
* **Closing Irrelevant Issues:** Closing issues that are determined irrelevant, no longer needed, not relevant to the project and/or don't follow the issues guidelines.
|
||||
|
||||
## Help with Contributions
|
||||
|
||||
* **Help Manage Pull Requests:** Help the author of the pull request with any problems.
|
||||
* **Contributing:** Create pull requests to help maintain and drive the project forward.
|
||||
@ -1,27 +0,0 @@
|
||||
# Promotion
|
||||
|
||||
Help promote Lens! If you are not a developer (or even if you are), you can still contribute to the project – a lot – by helping us to promote it. As we are a free and open source project, the community is our most important asset. Here are some ways that you can help the project continue to grow.
|
||||
|
||||
## Follow, Like, Recommend, Favorite, Vote and Star Us
|
||||
|
||||
There are many sites where you can vote, recommend, favorite, and star us.
|
||||
|
||||
* [Twitter](https://twitter.com/k8slens) - Like, comment and retweet our posts, and follow us on Twitter.
|
||||
* [Medium](https://medium.com/k8slens) - Give claps to our articles and follow us on Medium.
|
||||
* [GitHub](https://github.com/lensapp/lens) - Become a stargazer on GitHub.
|
||||
* [StackShare](https://stackshare.io/lens) - Indicate you are using Lens and follow us on StackShare.
|
||||
* [Reddit](https://www.reddit.com/search/?q=lens%20kubernetes&sort=new) - Upvote and be a Lens ambassador by participating in relevant discussions on Reddit.
|
||||
* [Hacker News](https://hn.algolia.com/?dateRange=all&page=0&prefix=false&query=lens%20kubernetes&sort=byDate&type=story) - Upvote and be a Lens ambassador by participating in relevant discussions on Hacker News.
|
||||
|
||||
## Write Blogs or Make Videos About Us
|
||||
|
||||
Here are some nice blog posts and videos about our project for you to get some inspiration:
|
||||
|
||||
* [Onboard AWS EKS Cluster on Lens(Kubernetes IDE)](https://dev.to/himwad05/onboard-aws-eks-cluster-on-lens-kubernetes-ide-492l)
|
||||
* [Using Lens to Manage All Your Kubernetes Cluster](https://medium.com/@magicmagnate/using-lens-to-manage-all-your-kubernetes-cluster-c1ef88fdb476)
|
||||
* [Kontena Lens - Beautiful Kubernetes UI](https://www.youtube.com/watch?v=YGgaiGdYfdI)
|
||||
* [Gerenciando Kubernetes com Lens e Octant](https://www.youtube.com/watch?v=h9ZqDelJLQQ)
|
||||
* [Walkthrough of Kubernetes IDE - Lens](https://www.youtube.com/watch?v=602aHZSdEfY)
|
||||
* [LENS - Interfaz Gráfica para Kubernetes en 1 PASO.](https://www.youtube.com/watch?v=DFMKcR4BqwM)
|
||||
|
||||
Psst... If you have created some content around Lens, let us know!
|
||||
@ -1,45 +0,0 @@
|
||||
## Testing Your Code
|
||||
|
||||
Lens uses github actions to run automated tests on any PR, before merging.
|
||||
However, a PR will not be reviewed before all tests are green, so to save time and prevent your PR from going stale, it is best to test it before submitting the PR.
|
||||
|
||||
### Run Local Verifications
|
||||
|
||||
Please run the following style and formatting commands and fix/check-in any changes:
|
||||
|
||||
#### 1. Linting
|
||||
|
||||
We use [ESLing](https://eslint.org/) for style verification.
|
||||
In the repository's root directory, simply run:
|
||||
|
||||
```
|
||||
make lint
|
||||
```
|
||||
|
||||
#### 3. Pre-submit Flight Checks
|
||||
|
||||
In the repository root directory, make sure that:
|
||||
|
||||
* `make build` runs successfully.
|
||||
* `make test` runs successfully.
|
||||
* `make integration` runs successfully (some tests require minikube running).
|
||||
|
||||
Please note that this last test is prone to "flakiness", so it might fail on occasion. If it fails constantly, take a deeper look at your code to find the source of the problem.
|
||||
|
||||
If you find that all tests passed, you may open a pull request upstream.
|
||||
|
||||
### Opening A Pull Request
|
||||
|
||||
#### Draft Mode
|
||||
|
||||
You may open a pull request in [draft mode](https://github.blog/2019-02-14-introducing-draft-pull-requests).
|
||||
All automated tests will still run against the PR, but the PR will not be assigned for review.
|
||||
Once a PR is ready for review, transition it from Draft mode, and code owners will be notified.
|
||||
|
||||
#### Pre-Requisites for PR Merge
|
||||
|
||||
In order for a PR to be merged, the following conditions should exist:
|
||||
1. The PR has passed all the automated tests (style, build & conformance tests).
|
||||
2. PR commits have been signed with the `--signoff` option.
|
||||
3. PR was reviewed and approved by a code owner.
|
||||
4. PR is rebased against upstream's master branch.
|
||||
@ -1,12 +1 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block analytics %}
|
||||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-90E1JB4HW4"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'G-90E1JB4HW4');
|
||||
</script>
|
||||
{% endblock %}
|
||||
@ -1,46 +0,0 @@
|
||||
# Lens Extension API
|
||||
|
||||
Customize and enhance the Lens experience with the Lens Extension API.
|
||||
Use the extension API to create menus or page content.
|
||||
The same extension API was used to create many of Lens's core features.
|
||||
To install your first extension you should goto the [extension page](lens://app/extensions) in lens.
|
||||
|
||||
This documentation describes:
|
||||
|
||||
* How to build, run, test, and publish an extension.
|
||||
* How to take full advantage of the Lens Extension API.
|
||||
* Where to find [guides](guides/README.md) and [code samples](https://github.com/lensapp/lens-extension-samples) to help get you started.
|
||||
|
||||
## What Extensions Can Do
|
||||
|
||||
Here are some examples of what you can achieve with the Extension API:
|
||||
|
||||
* Add custom components & views in the UI - Extending the Lens Workbench
|
||||
|
||||
For an overview of the Lens Extension API, refer to the [Common Capabilities](capabilities/common-capabilities.md) page. [Extension Guides Overview](guides/README.md) also includes a list of code samples and guides that illustrate various ways of using the Lens Extension API.
|
||||
|
||||
## How to Build Extensions
|
||||
|
||||
Here is what each section of the Lens Extension API docs can help you with:
|
||||
|
||||
* **Getting Started** teaches fundamental concepts for building extensions with the Hello World sample.
|
||||
* **Extension Capabilities** dissects Lens's Extension API into smaller categories and points you to more detailed topics.
|
||||
* **Extension Guides** includes guides and code samples that explain specific usages of Lens Extension API.
|
||||
* **Testing and Publishing** includes in-depth guides on various extension development topics, such as testing and publishing extensions.
|
||||
* **API Reference** contains exhaustive references for the Lens Extension API, Contribution Points, and many other topics.
|
||||
|
||||
## What's New
|
||||
|
||||
Just like Lens itself, the extension API updates on a monthly cadence, rolling out new features with every release.
|
||||
|
||||
Keep up with Lens and the Lens Extension API by reviewing the [release notes](https://github.com/lensapp/lens/releases).
|
||||
|
||||
## Looking for Help
|
||||
|
||||
If you have questions for extension development, try asking on the [Lens Dev Slack](http://k8slens.slack.com/). It's a public chatroom for Lens developers, where Lens team members chime in from time to time.
|
||||
|
||||
To provide feedback on the documentation or issues with the Lens Extension API, create new issues at [lensapp/lens](https://github.com/lensapp/lens/issues). Please use the labels `area/documentation` and/or `area/extension`.
|
||||
|
||||
## Downloading Lens
|
||||
|
||||
[Download Lens](https://github.com/lensapp/lens/releases) for macOS, Windows, or Linux.
|
||||
@ -1,131 +0,0 @@
|
||||
# Theme Color Reference
|
||||
You can use theme-based CSS Variables to style an extension according to the active theme.
|
||||
|
||||
## Base Colors
|
||||
- `--blue`: blue color.
|
||||
- `--magenta`: magenta color.
|
||||
- `--golden`: gold/yellow color.
|
||||
- `--halfGray`: gray with some apacity applied.
|
||||
- `--primary`: Lens brand (blue) color.
|
||||
- `--colorSuccess`: successfull operations color.
|
||||
- `--colorOk`: successfull operations (bright version) color.
|
||||
- `--colorInfo`: informational, in-progress color.
|
||||
- `--colorError`: critical error color.
|
||||
- `--colorSoftError`: error color.
|
||||
- `--colorWarning`: warning color.
|
||||
- `--colorVague`: soft gray color for notices, hints etc.
|
||||
- `--colorTerminated`: terminated, closed, stale color.
|
||||
- `--boxShadow`: semi-transparent box-shadow color.
|
||||
|
||||
## Text Colors
|
||||
- `--textColorPrimary`: foreground text color.
|
||||
- `--textColorSecondary`: foreground text color for different paragraps, parts of text.
|
||||
- `--textColorAccent`: foreground text color to highlight its parts.
|
||||
|
||||
## Border Colors
|
||||
- `--borderColor`: border color.
|
||||
- `--borderFaintColor`: fainted (lighter or darker, which depends on the theme) border color.
|
||||
|
||||
## Layout Colors
|
||||
- `--mainBackground`: main background color for the app.
|
||||
- `--contentColor`: background color for panels contains some data.
|
||||
- `--layoutBackground`: background color for layout parts.
|
||||
- `--layoutTabsBackground`: background color for general tabs.
|
||||
- `--layoutTabsActiveColor`: foreground color for general tabs.
|
||||
- `--layoutTabsLineColor`: background color for lines under general tabs.
|
||||
|
||||
## Sidebar Colors
|
||||
- `--sidebarLogoBackground`: background color behind logo in sidebar.
|
||||
- `--sidebarActiveColor`: foreground color for active menu items in sidebar.
|
||||
- `--sidebarSubmenuActiveColor`: foreground color for active submenu items in sidebar.
|
||||
- `--sidebarBackground`: background color for sidebar.
|
||||
|
||||
## Button Colors
|
||||
- `--buttonPrimaryBackground`: button background color for primary actions.
|
||||
- `--buttonDefaultBackground`: default button background color.
|
||||
- `--buttonLightBackground`: light button background color.
|
||||
- `--buttonAccentBackground`: accent button background color.
|
||||
- `--buttonDisabledBackground`: disabled button background color.
|
||||
|
||||
## Table Colors
|
||||
- `--tableBgcStripe`: background color for odd rows in table.
|
||||
- `--tableBgcSelected`: background color for selected row in table.
|
||||
- `--tableHeaderBackground`: background color for table header.
|
||||
- `--tableHeaderBorderWidth`: border width under table header.
|
||||
- `--tableHeaderBorderColor`: border color for line under table header.
|
||||
- `--tableHeaderColor`: foreground color for table header.
|
||||
- `--tableSelectedRowColor`: foreground color for selected row in table.
|
||||
|
||||
## Dock Colors
|
||||
- `--dockHeadBackground`: background color for dock's header.
|
||||
- `--dockInfoBackground`: background color for dock's info panel.
|
||||
- `--dockInfoBorderColor`: border color for dock's info panel.
|
||||
|
||||
## Helm Chart Colors
|
||||
- `--helmLogoBackground`: background color for chart logo.
|
||||
- `--helmImgBackground`: background color for chart image.
|
||||
- `--helmStableRepo`: background color for stable repo.
|
||||
- `--helmIncubatorRepo`: background color for incubator repo.
|
||||
- `--helmDescriptionHr`: Helm chart description separator line color.
|
||||
- `--helmDescriptionBlockqouteColor`: Helm chart description blockquote color.
|
||||
- `--helmDescriptionBlockqouteBorder`: Helm chart description blockquote border color.
|
||||
- `--helmDescriptionBlockquoteBackground`: Helm chart description blockquote background color.
|
||||
- `--helmDescriptionHeaders`: Helm chart description headers color.
|
||||
- `--helmDescriptionH6`: Helm chart description header foreground color.
|
||||
- `--helmDescriptionTdBorder`: Helm chart description table cell border color.
|
||||
- `--helmDescriptionTrBackground`: Helm chart description table row background color.
|
||||
- `--helmDescriptionCodeBackground`: Helm chart description code background color.
|
||||
- `--helmDescriptionPreBackground`: Helm chart description pre background color.
|
||||
- `--helmDescriptionPreColor`: Helm chart description pre foreground color.
|
||||
|
||||
## Terminal Colors
|
||||
- `--terminalBackground`: Terminal background color.
|
||||
- `--terminalForeground`: Terminal foreground color.
|
||||
- `--terminalCursor`: Terminal cursor color.
|
||||
- `--terminalCursorAccent`: Terminal cursor accent color.
|
||||
- `--terminalSelection`: Terminal selection background color.
|
||||
- `--terminalBlack`: Terminal black color.
|
||||
- `--terminalRed`: Terminal red color.
|
||||
- `--terminalGreen`: Terminal green color.
|
||||
- `--terminalYellow`: Terminal yellow color.
|
||||
- `--terminalBlue`: Terminal blue color.
|
||||
- `--terminalMagenta`: Terminal magenta color.
|
||||
- `--terminalCyan`: Terminal cyan color.
|
||||
- `--terminalWhite`: Terminal white color.
|
||||
- `--terminalBrightBlack`: Terminal bright black color.
|
||||
- `--terminalBrightRed`: Terminal bright red color.
|
||||
- `--terminalBrightGreen`: Terminal bright green color.
|
||||
- `--terminalBrightYellow`: Terminal bright yellow color.
|
||||
- `--terminalBrightBlue`: Terminal bright blue color.
|
||||
- `--terminalBrightMagenta`: Terminal bright magenta color.
|
||||
- `--terminalBrightCyan`: Terminal bright cyan color.
|
||||
- `--terminalBrightWhite`: Terminal bright white color.
|
||||
|
||||
## Dialog Colors
|
||||
- `--dialogHeaderBackground`: background color for dialog header.
|
||||
- `--dialogFooterBackground`: background color for dialog footer.
|
||||
|
||||
## Detail Panel (Drawer) Colors
|
||||
- `--drawerTitleText`: drawer title foreground color.
|
||||
- `--drawerSubtitleBackground`: drawer subtitle foreground color.
|
||||
- `--drawerItemNameColor`: foreground color for item name in drawer.
|
||||
- `--drawerItemValueColor`: foreground color for item value in drawer.
|
||||
|
||||
## Misc Colors
|
||||
- `--logsBackground`: background color for pod logs.
|
||||
- `--clusterMenuBackground`: background color for cluster menu.
|
||||
- `--clusterMenuBorderColor`: border color for cluster menu.
|
||||
- `--clusterSettingsBackground`: background color for cluster settings.
|
||||
- `--addClusterIconColor`: add cluster button background color.
|
||||
- `--iconActiveColor`: active cluster icon foreground color.
|
||||
- `--iconActiveBackground`: active cluster icon background color.
|
||||
- `--filterAreaBackground`: page filter area (where selected namespaces are lister) background color.
|
||||
- `--chartStripesColor`: bar chart zebra stripes background color.
|
||||
- `--chartCapacityColor`: background color for capacity values in bar charts.
|
||||
- `--pieChartDefaultColor`: default background color for pie chart values.
|
||||
- `--selectOptionHoveredColor`: foregrond color for selected element in dropdown list.
|
||||
- `--lineProgressBackground`: background color for progress line.
|
||||
- `--radioActiveBackground`: background color for active radio buttons.
|
||||
- `--menuActiveBackground`: background color for active menu items.
|
||||
|
||||
In most cases you would only need base, text and some of the layout colors.
|
||||
@ -14,9 +14,9 @@ In order to see logs from this extension, you need to start Lens from the comman
|
||||
This extension can register a custom callback that is executed when an extension is activated (started).
|
||||
|
||||
``` javascript
|
||||
import { LensMainExtension } from "@k8slens/extensions"
|
||||
import { Main } from "@k8slens/extensions"
|
||||
|
||||
export default class ExampleMainExtension extends LensMainExtension {
|
||||
export default class ExampleMainExtension extends Main.LensExtension {
|
||||
async onActivate() {
|
||||
console.log("hello world")
|
||||
}
|
||||
@ -28,9 +28,9 @@ export default class ExampleMainExtension extends LensMainExtension {
|
||||
This extension can register a custom callback that is executed when an extension is deactivated (stopped).
|
||||
|
||||
``` javascript
|
||||
import { LensMainExtension } from "@k8slens/extensions"
|
||||
import { Main } from "@k8slens/extensions"
|
||||
|
||||
export default class ExampleMainExtension extends LensMainExtension {
|
||||
export default class ExampleMainExtension extends Main.LensExtension {
|
||||
async onDeactivate() {
|
||||
console.log("bye bye")
|
||||
}
|
||||
@ -44,15 +44,15 @@ This extension can register custom app menus that will be displayed on OS native
|
||||
Example:
|
||||
|
||||
```typescript
|
||||
import { LensMainExtension, windowManager } from "@k8slens/extensions"
|
||||
import { Main } from "@k8slens/extensions"
|
||||
|
||||
export default class ExampleMainExtension extends LensMainExtension {
|
||||
export default class ExampleMainExtension extends Main.LensExtension {
|
||||
appMenus = [
|
||||
{
|
||||
parentId: "help",
|
||||
label: "Example item",
|
||||
click() {
|
||||
windowManager.navigate("https://k8slens.dev");
|
||||
Main.Navigation.navigate("https://k8slens.dev");
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -69,9 +69,9 @@ In order to see logs from this extension you need to check them via **View** > *
|
||||
This extension can register a custom callback that is executed when an extension is activated (started).
|
||||
|
||||
``` javascript
|
||||
import { LensRendererExtension } from "@k8slens/extensions"
|
||||
import { Renderer } from "@k8slens/extensions"
|
||||
|
||||
export default class ExampleExtension extends LensRendererExtension {
|
||||
export default class ExampleExtension extends Renderer.LensExtension {
|
||||
async onActivate() {
|
||||
console.log("hello world")
|
||||
}
|
||||
@ -83,9 +83,9 @@ export default class ExampleExtension extends LensRendererExtension {
|
||||
This extension can register a custom callback that is executed when an extension is deactivated (stopped).
|
||||
|
||||
``` javascript
|
||||
import { LensRendererExtension } from "@k8slens/extensions"
|
||||
import { Renderer } from "@k8slens/extensions"
|
||||
|
||||
export default class ExampleMainExtension extends LensRendererExtension {
|
||||
export default class ExampleMainExtension extends Renderer.LensExtension {
|
||||
async onDeactivate() {
|
||||
console.log("bye bye")
|
||||
}
|
||||
@ -99,10 +99,16 @@ The global page is a full-screen page that hides all other content from a window
|
||||
|
||||
```typescript
|
||||
import React from "react"
|
||||
import { Component, LensRendererExtension } from "@k8slens/extensions"
|
||||
import { Renderer } from "@k8slens/extensions"
|
||||
import { ExamplePage } from "./src/example-page"
|
||||
|
||||
export default class ExampleRendererExtension extends LensRendererExtension {
|
||||
const {
|
||||
Component: {
|
||||
Icon,
|
||||
}
|
||||
} = Renderer;
|
||||
|
||||
export default class ExampleRendererExtension extends Renderer.LensExtension {
|
||||
globalPages = [
|
||||
{
|
||||
id: "example",
|
||||
@ -117,7 +123,7 @@ export default class ExampleRendererExtension extends LensRendererExtension {
|
||||
title: "Example page", // used in icon's tooltip
|
||||
target: { pageId: "example" }
|
||||
components: {
|
||||
Icon: () => <Component.Icon material="arrow"/>,
|
||||
Icon: () => <Icon material="arrow"/>,
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -131,12 +137,12 @@ It is responsible for storing a state for custom preferences.
|
||||
|
||||
```typescript
|
||||
import React from "react"
|
||||
import { LensRendererExtension } from "@k8slens/extensions"
|
||||
import { Renderer } from "@k8slens/extensions"
|
||||
import { myCustomPreferencesStore } from "./src/my-custom-preferences-store"
|
||||
import { MyCustomPreferenceHint, MyCustomPreferenceInput } from "./src/my-custom-preference"
|
||||
|
||||
|
||||
export default class ExampleRendererExtension extends LensRendererExtension {
|
||||
export default class ExampleRendererExtension extends Renderer.LensExtension {
|
||||
appPreferences = [
|
||||
{
|
||||
title: "My Custom Preference",
|
||||
@ -156,10 +162,10 @@ These pages are visible in a cluster menu when a cluster is opened.
|
||||
|
||||
```typescript
|
||||
import React from "react"
|
||||
import { LensRendererExtension } from "@k8slens/extensions";
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
import { ExampleIcon, ExamplePage } from "./src/page"
|
||||
|
||||
export default class ExampleExtension extends LensRendererExtension {
|
||||
export default class ExampleExtension extends Renderer.LensExtension {
|
||||
clusterPages = [
|
||||
{
|
||||
id: "extension-example", // optional
|
||||
@ -190,10 +196,10 @@ These features are visible in the "Cluster Settings" page.
|
||||
|
||||
```typescript
|
||||
import React from "react"
|
||||
import { LensRendererExtension } from "@k8slens/extensions"
|
||||
import { Renderer } from "@k8slens/extensions"
|
||||
import { MyCustomFeature } from "./src/my-custom-feature"
|
||||
|
||||
export default class ExampleExtension extends LensRendererExtension {
|
||||
export default class ExampleExtension extends Renderer.LensExtension {
|
||||
clusterFeatures = [
|
||||
{
|
||||
title: "My Custom Feature",
|
||||
@ -219,15 +225,21 @@ This extension can register custom icons and text to a status bar area.
|
||||
|
||||
```typescript
|
||||
import React from "react";
|
||||
import { Component, LensRendererExtension, Navigation } from "@k8slens/extensions";
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
|
||||
export default class ExampleExtension extends LensRendererExtension {
|
||||
const {
|
||||
Component: {
|
||||
Icon,
|
||||
}
|
||||
} = Renderer;
|
||||
|
||||
export default class ExampleExtension extends Renderer.LensExtension {
|
||||
statusBarItems = [
|
||||
{
|
||||
components: {
|
||||
Item: (
|
||||
<div className="flex align-center gaps hover-highlight" onClick={() => this.navigate("/example-page")} >
|
||||
<Component.Icon material="favorite" />
|
||||
<Icon material="favorite" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -243,10 +255,10 @@ This extension can register custom menu items (actions) for specified Kubernetes
|
||||
|
||||
```typescript
|
||||
import React from "react"
|
||||
import { LensRendererExtension } from "@k8slens/extensions";
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
import { CustomMenuItem, CustomMenuItemProps } from "./src/custom-menu-item"
|
||||
|
||||
export default class ExampleExtension extends LensRendererExtension {
|
||||
export default class ExampleExtension extends Renderer.LensExtension {
|
||||
kubeObjectMenuItems = [
|
||||
{
|
||||
kind: "Node",
|
||||
@ -266,10 +278,10 @@ This extension can register custom details (content) for specified Kubernetes ki
|
||||
|
||||
```typescript
|
||||
import React from "react"
|
||||
import { LensRendererExtension } from "@k8slens/extensions";
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
import { CustomKindDetails, CustomKindDetailsProps } from "./src/custom-kind-details"
|
||||
|
||||
export default class ExampleExtension extends LensRendererExtension {
|
||||
export default class ExampleExtension extends Renderer.LensExtension {
|
||||
kubeObjectDetailItems = [
|
||||
{
|
||||
kind: "CustomKind",
|
||||
|
||||
@ -103,8 +103,6 @@ For example:
|
||||
}
|
||||
```
|
||||
|
||||
A complete list of theme colors can be found in the [Color Reference](../color-reference).
|
||||
|
||||
### Theme Switching
|
||||
|
||||
When the light theme is active, the `<body>` element gets a "theme-light" class, or: `<body class="theme-light">`.
|
||||
@ -116,14 +114,14 @@ There is a way of detect active theme and its changes in JS. [MobX observer func
|
||||
```js
|
||||
import React from "react"
|
||||
import { observer } from "mobx-react"
|
||||
import { App, Component, Theme } from "@k8slens/extensions";
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
|
||||
@observer
|
||||
export class SupportPage extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div className="SupportPage">
|
||||
<h1>Active theme is {Theme.getActiveTheme().name}</h1>
|
||||
<h1>Active theme is {Renderer.Theme.getActiveTheme().name}</h1>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -96,11 +96,11 @@ It also registers the `MenuItem` component that displays the `ExampleIcon` React
|
||||
These React components are defined in the additional `./src/page.tsx` file.
|
||||
|
||||
``` typescript
|
||||
import { LensRendererExtension } from "@k8slens/extensions";
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
import { ExampleIcon, ExamplePage } from "./page"
|
||||
import React from "react"
|
||||
|
||||
export default class ExampleExtension extends LensRendererExtension {
|
||||
export default class ExampleExtension extends Renderer.LensExtension {
|
||||
clusterPages = [
|
||||
{
|
||||
id: "extension-example",
|
||||
|
||||
@ -46,7 +46,7 @@ cmd /c mklink /D helloworld-sample lens-extension-samples\helloworld-sample
|
||||
|
||||
Without administrator rights, you need to copy the extensions sample directory into `C:\Users\<user>\.k8slens\extensions`:
|
||||
|
||||
```
|
||||
```sh
|
||||
Copy-Item 'lens-extension-samples\helloworld-sample' 'C:\Users\<user>\.k8slens\extensions\helloworld-sample'
|
||||
```
|
||||
|
||||
@ -78,7 +78,7 @@ npm run dev
|
||||
You must restart Lens for the extension to load.
|
||||
After this initial restart, reload Lens and it will automatically pick up changes any time the extension rebuilds.
|
||||
|
||||
With Lens running, either connect to an existing cluster or [create a new one](../../clusters/adding-clusters.md).
|
||||
With Lens running, either connect to an existing cluster or create a new one - refer to the latest [Lens Documentation](https://docs.k8slens.dev/latest/clusters/adding-clusters) for details on how to add a cluster in Lens IDE.
|
||||
You will see the "Hello World" page in the left-side cluster menu.
|
||||
|
||||
## Develop the Extension
|
||||
|
||||
@ -24,14 +24,14 @@ Each guide or code sample includes the following:
|
||||
| [KubeObjectListLayout](kube-object-list-layout.md) | |
|
||||
| [Working with mobx](working-with-mobx.md) | |
|
||||
| [Protocol Handlers](protocol-handlers.md) | |
|
||||
| [Sending Data between main and renderer](ipc.md) | |
|
||||
|
||||
## Samples
|
||||
|
||||
| Sample | APIs |
|
||||
| ----- | ----- |
|
||||
[hello-world](https://github.com/lensapp/lens-extension-samples/tree/master/helloworld-sample) | LensMainExtension <br> LensRendererExtension <br> Component.Icon <br> Component.IconProps |
|
||||
[minikube](https://github.com/lensapp/lens-extension-samples/tree/master/minikube-sample) | LensMainExtension <br> Store.ClusterStore <br> Store.workspaceStore |
|
||||
[styling-css-modules-sample](https://github.com/lensapp/lens-extension-samples/tree/master/styling-css-modules-sample) | LensMainExtension <br> LensRendererExtension <br> Component.Icon <br> Component.IconProps |
|
||||
[styling-emotion-sample](https://github.com/lensapp/lens-extension-samples/tree/master/styling-emotion-sample) | LensMainExtension <br> LensRendererExtension <br> Component.Icon <br> Component.IconProps |
|
||||
[styling-sass-sample](https://github.com/lensapp/lens-extension-samples/tree/master/styling-sass-sample) | LensMainExtension <br> LensRendererExtension <br> Component.Icon <br> Component.IconProps |
|
||||
[custom-resource-page](https://github.com/lensapp/lens-extension-samples/tree/master/custom-resource-page) | LensRendererExtension <br> K8sApi.KubeApi <br> K8sApi.KubeObjectStore <br> Component.KubeObjectListLayout <br> Component.KubeObjectDetailsProps <br> Component.IconProps |
|
||||
[hello-world](https://github.com/lensapp/lens-extension-samples/tree/master/helloworld-sample) | LensMainExtension <br> LensRendererExtension <br> Renderer.Component.Icon <br> Renderer.Component.IconProps |
|
||||
[styling-css-modules-sample](https://github.com/lensapp/lens-extension-samples/tree/master/styling-css-modules-sample) | LensMainExtension <br> LensRendererExtension <br> Renderer.Component.Icon <br> Renderer.Component.IconProps |
|
||||
[styling-emotion-sample](https://github.com/lensapp/lens-extension-samples/tree/master/styling-emotion-sample) | LensMainExtension <br> LensRendererExtension <br> Renderer.Component.Icon <br> Renderer.Component.IconProps |
|
||||
[styling-sass-sample](https://github.com/lensapp/lens-extension-samples/tree/master/styling-sass-sample) | LensMainExtension <br> LensRendererExtension <br> Renderer.Component.Icon <br> Renderer.Component.IconProps |
|
||||
[custom-resource-page](https://github.com/lensapp/lens-extension-samples/tree/master/custom-resource-page) | LensRendererExtension <br> Renderer.K8sApi.KubeApi <br> Renderer.K8sApi.KubeObjectStore <br> Renderer.Component.KubeObjectListLayout <br> Renderer.Component.KubeObjectDetailsProps <br> Renderer.Component.IconProps |
|
||||
|
||||
@ -70,6 +70,6 @@ To debug your extension, please see our instructions on [Testing Extensions](../
|
||||
To dive deeper, consider looking at [Common Capabilities](../capabilities/common-capabilities.md), [Styling](../capabilities/styling.md), or [Extension Anatomy](anatomy.md).
|
||||
|
||||
If you find problems with the Lens Extension Generator, or have feature requests, you are welcome to raise an [issue](https://github.com/lensapp/generator-lens-ext/issues).
|
||||
You can find the Lens contribution guidelines [here](../../contributing/README.md).
|
||||
You can find the latest Lens contribution guidelines [here](https://docs.k8slens.dev/latest/contributing).
|
||||
|
||||
The Generator source code is hosted at [Github](https://github.com/lensapp/generator-lens-ext).
|
||||
|
||||
132
docs/extensions/guides/ipc.md
Normal file
@ -0,0 +1,132 @@
|
||||
# Inter Process Communication
|
||||
|
||||
A Lens Extension can utilize IPC to send information between the `renderer` and `main` processes.
|
||||
This is useful when wanting to communicate directly within your extension.
|
||||
|
||||
For example, if a user logs into a service that your extension is a facade for and `main` needs to know some information so that you can start syncing items to the `Catalog`, this would be a good way to send that information along.
|
||||
|
||||
IPC channels are sectioned off per extension.
|
||||
Meaning that each extension can only communicate with itself.
|
||||
|
||||
## Types of Communication
|
||||
|
||||
There are two flavours of communication that are provided:
|
||||
|
||||
- Event based (IPC)
|
||||
- Request based (RPC)
|
||||
|
||||
### Event Based or IPC
|
||||
|
||||
This is the same as an [Event Emitter](https://nodejs.org/api/events.html#events_class_eventemitter) but is not limited to just one Javascript process.
|
||||
This is a good option when you need to report that something has happened but you don't need a response.
|
||||
|
||||
This is a fully two-way form of communication.
|
||||
Both `main` and `renderer` can do this sort of IPC.
|
||||
|
||||
### Request Based or RPC
|
||||
|
||||
This is more like a Remote Procedure Call (RPC) or Send-Receive-Reply (SRR).
|
||||
With this sort of communication the caller needs to wait for the result from the other side.
|
||||
This is accomplished by `await`-ing the returned `Promise<any>`.
|
||||
|
||||
This is a unidirectional form of communication.
|
||||
Only `renderer` can initiate this kind of request, and only `main` can receive and respond to this kind of request.
|
||||
|
||||
## Registering IPC Handlers and Listeners
|
||||
|
||||
The general terminology is as follows:
|
||||
|
||||
- A "handler" is the function that responds to a "Request Based IPC" event.
|
||||
- A "listener" is the function that is called when a "Event Based IPC" event is emitted.
|
||||
|
||||
To register either a handler or a listener, you should do something like the following:
|
||||
|
||||
`main.ts`:
|
||||
```typescript
|
||||
import { Main } from "@k8slens/extensions";
|
||||
import { IpcMain } from "./helpers/main";
|
||||
|
||||
export class ExampleExtensionMain extends Main.LensExtension {
|
||||
onActivate() {
|
||||
IpcMain.createInstance(this);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This file shows that you need to create an instance of the store to be able to use IPC.
|
||||
Lens will automatically clean up that store and all the handlers on deactivation and uninstall.
|
||||
|
||||
---
|
||||
|
||||
`helpers/main.ts`:
|
||||
```typescript
|
||||
import { Main } from "@k8slens/extensions";
|
||||
|
||||
export class IpcMain extends Main.Ipc {
|
||||
constructor(extension: Main.LensExtension) {
|
||||
super(extension);
|
||||
|
||||
this.listen("initialize", onInitialize);
|
||||
}
|
||||
}
|
||||
|
||||
function onInitialize(event: Types.IpcMainEvent, id: string) {
|
||||
console.log(`starting to initialize: ${id}`);
|
||||
}
|
||||
```
|
||||
|
||||
In other files, it is not necessary to pass around any instances.
|
||||
You should be able to just call `IpcMain.getInstance()` anywhere it is needed in your extension.
|
||||
|
||||
---
|
||||
|
||||
`renderer.ts`:
|
||||
```typescript
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
import { IpcRenderer } from "./helpers/renderer";
|
||||
|
||||
export class ExampleExtensionRenderer extends Renderer.LensExtension {
|
||||
onActivate() {
|
||||
const ipc = IpcRenderer.createInstance(this);
|
||||
|
||||
setTimeout(() => ipc.broadcast("initialize", "an-id"), 5000);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
It is also needed to create an instance to broadcast messages too.
|
||||
|
||||
---
|
||||
|
||||
`helpers/renderer.ts`:
|
||||
```typescript
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
|
||||
export class IpcRenderer extends Renderer.Ipc {}
|
||||
```
|
||||
|
||||
It is necessary to create child classes of these `abstract class`'s in your extension before you can use them.
|
||||
|
||||
---
|
||||
|
||||
As this example shows: the channel names *must* be the same.
|
||||
It should also be noted that "listeners" and "handlers" are specific to either `renderer` or `main`.
|
||||
There is no behind the scenes transfer of these functions.
|
||||
|
||||
To register a "handler" call `IpcMain.getInstance().handle(...)`.
|
||||
The cleanup of these handlers is handled by Lens itself.
|
||||
|
||||
The `listen()` methods on `Main.Ipc` and `Renderer.Ipc` return a `Disposer`, or more specifically, a `() => void`.
|
||||
This can be optionally called to remove the listener early.
|
||||
|
||||
Calling either `IpcRenderer.getInstance().broadcast(...)` or `IpcMain.getInstance().broadcast(...)` sends an event to all `renderer` frames and to `main`.
|
||||
Because of this, no matter where you broadcast from, all listeners in `main` and `renderer` will be notified.
|
||||
|
||||
### Allowed Values
|
||||
|
||||
This IPC mechanism utilizes the [Structured Clone Algorithm](developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm) for serialization.
|
||||
This means that more types than what are JSON serializable can be used, but not all the information will be passed through.
|
||||
|
||||
## Using Request Based Communication
|
||||
|
||||
If you are meaning to do a request based call from `renderer`, you should do `const res = await IpcRenderer.getInstance().invoke(<channel>, ...<args>));` instead.
|
||||
@ -18,7 +18,7 @@ First thing we need to do with our extension is to register new menu item in the
|
||||
We will do this in our extension class `CrdSampleExtension` that is derived `LensRendererExtension` class:
|
||||
|
||||
```typescript
|
||||
export default class CrdSampleExtension extends LensRendererExtension {
|
||||
export default class CrdSampleExtension extends Renderer.LensExtension {
|
||||
}
|
||||
```
|
||||
|
||||
@ -27,11 +27,21 @@ This object will register a menu item with "Certificates" text.
|
||||
It will also use `CertificateIcon` component to render an icon and navigate to cluster page that is having `certificates` page id.
|
||||
|
||||
```typescript
|
||||
export function CertificateIcon(props: Component.IconProps) {
|
||||
return <Component.Icon {...props} material="security" tooltip="Certificates"/>
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
|
||||
type IconProps = Renderer.Component.IconProps;
|
||||
|
||||
const {
|
||||
Component: {
|
||||
Icon,
|
||||
},
|
||||
} = Renderer;
|
||||
|
||||
export function CertificateIcon(props: IconProps) {
|
||||
return <Icon {...props} material="security" tooltip="Certificates"/>
|
||||
}
|
||||
|
||||
export default class CrdSampleExtension extends LensRendererExtension {
|
||||
export default class CrdSampleExtension extends Renderer.LensExtension {
|
||||
|
||||
clusterPageMenus = [
|
||||
{
|
||||
@ -48,7 +58,7 @@ export default class CrdSampleExtension extends LensRendererExtension {
|
||||
Then we need to register `PageRegistration` object with `certificates` id and define `CertificatePage` component to render certificates.
|
||||
|
||||
```typescript
|
||||
export default class CrdSampleExtension extends LensRendererExtension {
|
||||
export default class CrdSampleExtension extends Renderer.LensExtension {
|
||||
...
|
||||
|
||||
clusterPages = [{
|
||||
@ -65,18 +75,29 @@ export default class CrdSampleExtension extends LensRendererExtension {
|
||||
|
||||
In the previous step we defined `CertificatePage` component to render certificates.
|
||||
In this step we will actually implement that.
|
||||
`CertificatePage` is a React component that will render `Component.KubeObjectListLayout` component to list `Certificate` CRD objects.
|
||||
`CertificatePage` is a React component that will render `Renderer.Component.KubeObjectListLayout` component to list `Certificate` CRD objects.
|
||||
|
||||
### Get CRD objects
|
||||
|
||||
In order to list CRD objects, we need first fetch those from Kubernetes API.
|
||||
Lens Extensions API provides easy mechanism to do this.
|
||||
We just need to define `Certificate` class derived from `K8sApi.KubeObject`, `CertificatesApi`derived from `K8sApi.KubeApi` and `CertificatesStore` derived from `K8sApi.KubeObjectStore`.
|
||||
We just need to define `Certificate` class derived from `Renderer.K8sApi.KubeObject`, `CertificatesApi`derived from `Renderer.K8sApi.KubeApi` and `CertificatesStore` derived from `Renderer.K8sApi.KubeObjectStore`.
|
||||
|
||||
`Certificate` class defines properties found in the CRD object:
|
||||
|
||||
```typescript
|
||||
export class Certificate extends K8sApi.KubeObject {
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
|
||||
const {
|
||||
K8sApi: {
|
||||
KubeObject,
|
||||
KubeObjectStore,
|
||||
KubeApi,
|
||||
apiManager,
|
||||
},
|
||||
} = Renderer;
|
||||
|
||||
export class Certificate extends KubeObject {
|
||||
static kind = "Certificate"
|
||||
static namespaced = true
|
||||
static apiBase = "/apis/cert-manager.io/v1alpha2/certificates"
|
||||
@ -121,8 +142,8 @@ export class Certificate extends K8sApi.KubeObject {
|
||||
With `CertificatesApi` class we are able to manage `Certificate` objects in Kubernetes API:
|
||||
|
||||
```typescript
|
||||
export class CertificatesApi extends K8sApi.KubeApi<Certificate> {
|
||||
}
|
||||
export class CertificatesApi extends KubeApi<Certificate> {}
|
||||
|
||||
export const certificatesApi = new CertificatesApi({
|
||||
objectConstructor: Certificate
|
||||
});
|
||||
@ -131,7 +152,7 @@ export const certificatesApi = new CertificatesApi({
|
||||
`CertificateStore` defines storage for `Certificate` objects
|
||||
|
||||
```typescript
|
||||
export class CertificatesStore extends K8sApi.KubeObjectStore<Certificate> {
|
||||
export class CertificatesStore extends KubeObjectStore<Certificate> {
|
||||
api = certificatesApi
|
||||
}
|
||||
|
||||
@ -141,7 +162,7 @@ export const certificatesStore = new CertificatesStore();
|
||||
And, finally, we register this store to Lens's API manager.
|
||||
|
||||
```typescript
|
||||
K8sApi.apiManager.registerStore(certificatesStore);
|
||||
apiManager.registerStore(certificatesStore);
|
||||
```
|
||||
|
||||
|
||||
@ -153,23 +174,32 @@ Then we need to fetch those and render them in the UI.
|
||||
First we define `CertificatePage` class that extends `React.Component`.
|
||||
|
||||
```typescript
|
||||
import { Component, LensRendererExtension } from "@k8slens/extensions";
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
import React from "react";
|
||||
import { certificatesStore } from "../certificate-store";
|
||||
import { Certificate } from "../certificate"
|
||||
|
||||
export class CertificatePage extends React.Component<{ extension: LensRendererExtension }> {
|
||||
export class CertificatePage extends React.Component<{ extension: Renderer.LensExtension }> {
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Next we will implement `render` method that will display certificates in a list.
|
||||
To do that, we just need to add `Component.KubeObjectListLayout` component inside `Component.TabLayout` component in render method.
|
||||
To define which objects the list is showing, we need to pass `certificateStore` object to `Component.KubeObjectListLayout` in `store` property.
|
||||
`Component.KubeObjectListLayout` will fetch automatically items from the given store when component is mounted.
|
||||
To do that, we just need to add `Renderer.Component.KubeObjectListLayout` component inside `Renderer.Component.TabLayout` component in render method.
|
||||
To define which objects the list is showing, we need to pass `certificateStore` object to `Renderer.Component.KubeObjectListLayout` in `store` property.
|
||||
`Renderer.Component.KubeObjectListLayout` will fetch automatically items from the given store when component is mounted.
|
||||
Also, we can define needed sorting callbacks and search filters for the list:
|
||||
|
||||
```typescript
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
|
||||
const {
|
||||
Component: {
|
||||
TabLayout,
|
||||
KubeObjectListLayout,
|
||||
},
|
||||
} = Renderer;
|
||||
|
||||
enum sortBy {
|
||||
name = "name",
|
||||
namespace = "namespace",
|
||||
@ -181,8 +211,8 @@ export class CertificatePage extends React.Component<{ extension: LensRendererEx
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Component.TabLayout>
|
||||
<Component.KubeObjectListLayout
|
||||
<TabLayout>
|
||||
<KubeObjectListLayout
|
||||
className="Certicates" store={certificatesStore}
|
||||
sortingCallbacks={{
|
||||
[sortBy.name]: (certificate: Certificate) => certificate.getName(),
|
||||
@ -204,7 +234,7 @@ export class CertificatePage extends React.Component<{ extension: LensRendererEx
|
||||
certificate.spec.issuerRef.name
|
||||
]}
|
||||
/>
|
||||
</Component.TabLayout>
|
||||
</TabLayout>
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -219,7 +249,7 @@ First, we need to register our custom component to render details for the specif
|
||||
We will do this again in `CrdSampleExtension` class:
|
||||
|
||||
```typescript
|
||||
export default class CrdSampleExtension extends LensRendererExtension {
|
||||
export default class CrdSampleExtension extends Renderer.LensExtension {
|
||||
//...
|
||||
|
||||
kubeObjectDetailItems = [{
|
||||
@ -235,14 +265,22 @@ export default class CrdSampleExtension extends LensRendererExtension {
|
||||
Here we defined that `CertificateDetails` component will render the resource details.
|
||||
So, next we need to implement that component.
|
||||
Lens will inject `Certificate` object into our component so we just need to render some information out of it.
|
||||
We can use `Component.DrawerItem` component from Lens Extensions API to give the same look and feel as Lens is using elsewhere:
|
||||
We can use `Renderer.Component.DrawerItem` component from Lens Extensions API to give the same look and feel as Lens is using elsewhere:
|
||||
|
||||
```typescript
|
||||
import { Component, K8sApi } from "@k8slens/extensions";
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
import React from "react";
|
||||
import { Certificate } from "../certificate";
|
||||
|
||||
export interface CertificateDetailsProps extends Component.KubeObjectDetailsProps<Certificate>{
|
||||
const {
|
||||
Component: {
|
||||
KubeObjectDetailsProps,
|
||||
DrawerItem,
|
||||
Badge,
|
||||
}
|
||||
} = Renderer;
|
||||
|
||||
export interface CertificateDetailsProps extends KubeObjectDetailsProps<Certificate>{
|
||||
}
|
||||
|
||||
export class CertificateDetails extends React.Component<CertificateDetailsProps> {
|
||||
@ -252,29 +290,29 @@ export class CertificateDetails extends React.Component<CertificateDetailsProps>
|
||||
if (!certificate) return null;
|
||||
return (
|
||||
<div className="Certificate">
|
||||
<Component.DrawerItem name="Created">
|
||||
<DrawerItem name="Created">
|
||||
{certificate.getAge(true, false)} ago ({certificate.metadata.creationTimestamp })
|
||||
</Component.DrawerItem>
|
||||
<Component.DrawerItem name="DNS Names">
|
||||
</DrawerItem>
|
||||
<DrawerItem name="DNS Names">
|
||||
{certificate.spec.dnsNames.join(",")}
|
||||
</Component.DrawerItem>
|
||||
<Component.DrawerItem name="Secret">
|
||||
</DrawerItem>
|
||||
<DrawerItem name="Secret">
|
||||
{certificate.spec.secretName}
|
||||
</Component.DrawerItem>
|
||||
<Component.DrawerItem name="Status" className="status" labelsOnly>
|
||||
</DrawerItem>
|
||||
<DrawerItem name="Status" className="status" labelsOnly>
|
||||
{certificate.status.conditions.map((condition, index) => {
|
||||
const { type, reason, message, status } = condition;
|
||||
const kind = type || reason;
|
||||
if (!kind) return null;
|
||||
return (
|
||||
<Component.Badge
|
||||
<Badge
|
||||
key={kind + index} label={kind}
|
||||
className={"success "+kind.toLowerCase()}
|
||||
tooltip={message}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Component.DrawerItem>
|
||||
</DrawerItem>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -11,9 +11,9 @@ The Main Extension API allows you to access, configure, and customize Lens data,
|
||||
To create a main extension simply extend the `LensMainExtension` class:
|
||||
|
||||
```typescript
|
||||
import { LensMainExtension } from "@k8slens/extensions";
|
||||
import { Main } from "@k8slens/extensions";
|
||||
|
||||
export default class ExampleExtensionMain extends LensMainExtension {
|
||||
export default class ExampleExtensionMain extends Main.LensExtension {
|
||||
onActivate() {
|
||||
console.log('custom main process extension code started');
|
||||
}
|
||||
@ -39,34 +39,6 @@ The example above logs messages when the extension is enabled and disabled.
|
||||
To see standard output from the main process there must be a console connected to it.
|
||||
Achieve this by starting Lens from the command prompt.
|
||||
|
||||
The following example is a little more interesting.
|
||||
It accesses some Lens state data, and it periodically logs the name of the cluster that is currently active in Lens.
|
||||
|
||||
```typescript
|
||||
import { LensMainExtension, Store } from "@k8slens/extensions";
|
||||
|
||||
export default class ActiveClusterExtensionMain extends LensMainExtension {
|
||||
|
||||
timer: NodeJS.Timeout
|
||||
|
||||
onActivate() {
|
||||
console.log("Cluster logger activated");
|
||||
this.timer = setInterval(() => {
|
||||
if (!Store.ClusterStore.getInstance().active) {
|
||||
console.log("No active cluster");
|
||||
return;
|
||||
}
|
||||
console.log("active cluster is", Store.ClusterStore.getInstance().active.contextName)
|
||||
}, 5000)
|
||||
}
|
||||
|
||||
onDeactivate() {
|
||||
clearInterval(this.timer)
|
||||
console.log("Cluster logger deactivated");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
For more details on accessing Lens state data, please see the [Stores](../stores) guide.
|
||||
|
||||
### `appMenus`
|
||||
@ -76,9 +48,9 @@ Note that this is the only UI feature that the Main Extension API allows you to
|
||||
The following example demonstrates adding an item to the **Help** menu.
|
||||
|
||||
``` typescript
|
||||
import { LensMainExtension } from "@k8slens/extensions";
|
||||
import { Main } from "@k8slens/extensions";
|
||||
|
||||
export default class SamplePageMainExtension extends LensMainExtension {
|
||||
export default class SamplePageMainExtension extends Main.LensExtension {
|
||||
appMenus = [
|
||||
{
|
||||
parentId: "help",
|
||||
@ -102,4 +74,4 @@ Valid values include: `"file"`, `"edit"`, `"view"`, and `"help"`.
|
||||
* `click()` is called when the menu item is selected.
|
||||
In this example, we simply log a message.
|
||||
However, you would typically have this navigate to a specific page or perform another operation.
|
||||
Note that pages are associated with the [`LensRendererExtension`](renderer-extension.md) class and can be defined in the process of extending it.
|
||||
Note that pages are associated with the [`Renderer.LensExtension`](renderer-extension.md) class and can be defined in the process of extending it.
|
||||
|
||||
@ -18,13 +18,13 @@ In other words, which handler is selected in either process is independent from
|
||||
Example of registering a handler:
|
||||
|
||||
```typescript
|
||||
import { LensMainExtension, Interface } from "@k8slens/extensions";
|
||||
import { Main, Common } from "@k8slens/extensions";
|
||||
|
||||
function rootHandler(params: Iterface.ProtocolRouteParams) {
|
||||
function rootHandler(params: Common.Types.ProtocolRouteParams) {
|
||||
console.log("routed to ExampleExtension", params);
|
||||
}
|
||||
|
||||
export default class ExampleExtensionMain extends LensMainExtension {
|
||||
export default class ExampleExtensionMain extends Main.LensExtension {
|
||||
protocolHandlers = [
|
||||
pathSchema: "/",
|
||||
handler: rootHandler,
|
||||
|
||||
@ -10,7 +10,6 @@ The custom Lens UI elements that you can add include:
|
||||
* [Cluster page menus](#clusterpagemenus)
|
||||
* [Global pages](#globalpages)
|
||||
* [Global page menus](#globalpagemenus)
|
||||
* [Cluster features](#clusterfeatures)
|
||||
* [App preferences](#apppreferences)
|
||||
* [Status bar items](#statusbaritems)
|
||||
* [KubeObject menu items](#kubeobjectmenuitems)
|
||||
@ -25,9 +24,9 @@ All UI elements are based on React components.
|
||||
To create a renderer extension, extend the `LensRendererExtension` class:
|
||||
|
||||
```typescript
|
||||
import { LensRendererExtension } from "@k8slens/extensions";
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
|
||||
export default class ExampleExtensionMain extends LensRendererExtension {
|
||||
export default class ExampleExtensionMain extends Renderer.LensExtension {
|
||||
onActivate() {
|
||||
console.log('custom renderer process extension code started');
|
||||
}
|
||||
@ -62,11 +61,11 @@ Use your extension to access Kubernetes resources in the active cluster with [`C
|
||||
Add a cluster page definition to a `LensRendererExtension` subclass with the following example:
|
||||
|
||||
```typescript
|
||||
import { LensRendererExtension } from "@k8slens/extensions";
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
import { ExampleIcon, ExamplePage } from "./page"
|
||||
import React from "react"
|
||||
|
||||
export default class ExampleExtension extends LensRendererExtension {
|
||||
export default class ExampleExtension extends Renderer.LensExtension {
|
||||
clusterPages = [
|
||||
{
|
||||
id: "hello",
|
||||
@ -89,7 +88,7 @@ It offers flexibility in defining the appearance and behavior of your page.
|
||||
`ExamplePage` in the example above can be defined in `page.tsx`:
|
||||
|
||||
```typescript
|
||||
import { LensRendererExtension } from "@k8slens/extensions";
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
import React from "react"
|
||||
|
||||
export class ExamplePage extends React.Component<{ extension: LensRendererExtension }> {
|
||||
@ -117,11 +116,11 @@ Use `clusterPageMenus`, covered in the next section, to add cluster pages to the
|
||||
By expanding on the above example, you can add a cluster page menu item to the `ExampleExtension` definition:
|
||||
|
||||
```typescript
|
||||
import { LensRendererExtension } from "@k8slens/extensions";
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
import { ExampleIcon, ExamplePage } from "./page"
|
||||
import React from "react"
|
||||
|
||||
export default class ExampleExtension extends LensRendererExtension {
|
||||
export default class ExampleExtension extends Renderer.LensExtension {
|
||||
clusterPages = [
|
||||
{
|
||||
id: "hello",
|
||||
@ -158,14 +157,20 @@ When users click **Hello World**, the cluster dashboard will show the contents o
|
||||
This example requires the definition of another React-based component, `ExampleIcon`, which has been added to `page.tsx`, as follows:
|
||||
|
||||
```typescript
|
||||
import { LensRendererExtension, Component } from "@k8slens/extensions";
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
import React from "react"
|
||||
|
||||
export function ExampleIcon(props: Component.IconProps) {
|
||||
return <Component.Icon {...props} material="pages" tooltip={"Hi!"}/>
|
||||
type IconProps = Renderer.Component.IconProps;
|
||||
|
||||
const {
|
||||
Component: { Icon },
|
||||
} = Renderer;
|
||||
|
||||
export function ExampleIcon(props: IconProps) {
|
||||
return <Icon {...props} material="pages" tooltip={"Hi!"}/>
|
||||
}
|
||||
|
||||
export class ExamplePage extends React.Component<{ extension: LensRendererExtension }> {
|
||||
export class ExamplePage extends React.Component<{ extension: Renderer.LensExtension }> {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
@ -177,8 +182,8 @@ export class ExamplePage extends React.Component<{ extension: LensRendererExtens
|
||||
```
|
||||
|
||||
Lens includes various built-in components available for extension developers to use.
|
||||
One of these is the `Component.Icon`, introduced in `ExampleIcon`, which you can use to access any of the [icons](https://material.io/resources/icons/) available at [Material Design](https://material.io).
|
||||
The properties that `Component.Icon` uses are defined as follows:
|
||||
One of these is the `Renderer.Component.Icon`, introduced in `ExampleIcon`, which you can use to access any of the [icons](https://material.io/resources/icons/) available at [Material Design](https://material.io).
|
||||
The properties that `Renderer.Component.Icon` uses are defined as follows:
|
||||
|
||||
* `material` takes the name of the icon you want to use.
|
||||
* `tooltip` sets the text you want to appear when a user hovers over the icon.
|
||||
@ -188,11 +193,11 @@ The following example groups two sub menu items under one parent menu item:
|
||||
|
||||
|
||||
```typescript
|
||||
import { LensRendererExtension } from "@k8slens/extensions";
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
import { ExampleIcon, ExamplePage } from "./page"
|
||||
import React from "react"
|
||||
|
||||
export default class ExampleExtension extends LensRendererExtension {
|
||||
export default class ExampleExtension extends Renderer.LensExtension {
|
||||
clusterPages = [
|
||||
{
|
||||
id: "hello",
|
||||
@ -262,11 +267,11 @@ Unlike cluster pages, users can trigger global pages even when there is no activ
|
||||
The following example defines a `LensRendererExtension` subclass with a single global page definition:
|
||||
|
||||
```typescript
|
||||
import { LensRendererExtension } from '@k8slens/extensions';
|
||||
import { Renderer } from '@k8slens/extensions';
|
||||
import { HelpPage } from './page';
|
||||
import React from 'react';
|
||||
|
||||
export default class HelpExtension extends LensRendererExtension {
|
||||
export default class HelpExtension extends Renderer.LensExtension {
|
||||
globalPages = [
|
||||
{
|
||||
id: "help",
|
||||
@ -289,7 +294,7 @@ It offers flexibility in defining the appearance and behavior of your page.
|
||||
`HelpPage` in the example above can be defined in `page.tsx`:
|
||||
|
||||
```typescript
|
||||
import { LensRendererExtension } from "@k8slens/extensions";
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
import React from "react"
|
||||
|
||||
export class HelpPage extends React.Component<{ extension: LensRendererExtension }> {
|
||||
@ -321,11 +326,11 @@ Global pages can be made available in the following ways:
|
||||
By expanding on the above example, you can add a global page menu item to the `HelpExtension` definition:
|
||||
|
||||
```typescript
|
||||
import { LensRendererExtension } from "@k8slens/extensions";
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
import { HelpIcon, HelpPage } from "./page"
|
||||
import React from "react"
|
||||
|
||||
export default class HelpExtension extends LensRendererExtension {
|
||||
export default class HelpExtension extends Renderer.LensExtension {
|
||||
globalPages = [
|
||||
{
|
||||
id: "help",
|
||||
@ -363,14 +368,20 @@ This example requires the definition of another React-based component, `HelpIcon
|
||||
Update `page.tsx` from the example above with the `HelpIcon` definition, as follows:
|
||||
|
||||
```typescript
|
||||
import { LensRendererExtension, Component } from "@k8slens/extensions";
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
import React from "react"
|
||||
|
||||
export function HelpIcon(props: Component.IconProps) {
|
||||
return <Component.Icon {...props} material="help"/>
|
||||
type IconProps = Renderer.Component.IconProps;
|
||||
|
||||
const {
|
||||
Component: { Icon },
|
||||
} = Renderer;
|
||||
|
||||
export function HelpIcon(props: IconProps) {
|
||||
return <Icon {...props} material="help"/>
|
||||
}
|
||||
|
||||
export class HelpPage extends React.Component<{ extension: LensRendererExtension }> {
|
||||
export class HelpPage extends React.Component<{ extension: Renderer.LensExtension }> {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
@ -382,8 +393,8 @@ export class HelpPage extends React.Component<{ extension: LensRendererExtension
|
||||
```
|
||||
|
||||
Lens includes various built-in components available for extension developers to use.
|
||||
One of these is the `Component.Icon`, introduced in `HelpIcon`, which you can use to access any of the [icons](https://material.io/resources/icons/) available at [Material Design](https://material.io).
|
||||
The property that `Component.Icon` uses is defined as follows:
|
||||
One of these is the `Renderer.Component.Icon`, introduced in `HelpIcon`, which you can use to access any of the [icons](https://material.io/resources/icons/) available at [Material Design](https://material.io).
|
||||
The property that `Renderer.Component.Icon` uses is defined as follows:
|
||||
|
||||
* `material` takes the name of the icon you want to use.
|
||||
|
||||
@ -402,11 +413,11 @@ They can be installed and uninstalled by the Lens user from the cluster **Settin
|
||||
The following example shows how to add a cluster feature as part of a `LensRendererExtension`:
|
||||
|
||||
```typescript
|
||||
import { LensRendererExtension } from "@k8slens/extensions"
|
||||
import { Renderer } from "@k8slens/extensions"
|
||||
import { ExampleFeature } from "./src/example-feature"
|
||||
import React from "react"
|
||||
|
||||
export default class ExampleFeatureExtension extends LensRendererExtension {
|
||||
export default class ExampleFeatureExtension extends Renderer.LensExtension {
|
||||
clusterFeatures = [
|
||||
{
|
||||
title: "Example Feature",
|
||||
@ -463,45 +474,69 @@ Consider using the following properties with `updateStatus()`:
|
||||
The following shows a very simple implementation of a `ClusterFeature`:
|
||||
|
||||
```typescript
|
||||
import { ClusterFeature, Store, K8sApi } from "@k8slens/extensions";
|
||||
import { Renderer, Common } from "@k8slens/extensions";
|
||||
import * as path from "path";
|
||||
|
||||
export class ExampleFeature extends ClusterFeature.Feature {
|
||||
const {
|
||||
K8sApi: {
|
||||
ResourceStack,
|
||||
forCluster,
|
||||
StorageClass,
|
||||
Namespace,
|
||||
}
|
||||
} = Renderer;
|
||||
|
||||
async install(cluster: Store.Cluster): Promise<void> {
|
||||
type ResourceStack = Renderer.K8sApi.ResourceStack;
|
||||
type Pod = Renderer.K8sApi.Pod;
|
||||
type KubernetesCluster = Common.Catalog.KubernetesCluster;
|
||||
|
||||
super.applyResources(cluster, path.join(__dirname, "../resources/"));
|
||||
export interface MetricsStatus {
|
||||
installed: boolean;
|
||||
canUpgrade: boolean;
|
||||
}
|
||||
|
||||
export class ExampleFeature {
|
||||
protected stack: ResourceStack;
|
||||
|
||||
constructor(protected cluster: KubernetesCluster) {
|
||||
this.stack = new ResourceStack(cluster, this.name);
|
||||
}
|
||||
|
||||
async upgrade(cluster: Store.Cluster): Promise<void> {
|
||||
return this.install(cluster);
|
||||
install(): Promise<string> {
|
||||
return this.stack.kubectlApplyFolder(path.join(__dirname, "../resources/"));
|
||||
}
|
||||
|
||||
async updateStatus(cluster: Store.Cluster): Promise<ClusterFeature.FeatureStatus> {
|
||||
upgrade(): Promise<string> {
|
||||
return this.install(config);
|
||||
}
|
||||
|
||||
async getStatus(): Promise<MetricsStatus> {
|
||||
const status: MetricsStatus = { installed: false, canUpgrade: false};
|
||||
|
||||
try {
|
||||
const pod = K8sApi.forCluster(cluster, K8sApi.Pod);
|
||||
const pod = forCluster(cluster, Pod);
|
||||
const examplePod = await pod.get({name: "example-pod", namespace: "default"});
|
||||
|
||||
if (examplePod?.kind) {
|
||||
this.status.installed = true;
|
||||
this.status.currentVersion = examplePod.spec.containers[0].image.split(":")[1];
|
||||
this.status.canUpgrade = true; // a real implementation would perform a check here that is relevant to the specific feature
|
||||
status.installed = true;
|
||||
status.currentVersion = examplePod.spec.containers[0].image.split(":")[1];
|
||||
status.canUpgrade = true; // a real implementation would perform a check here that is relevant to the specific feature
|
||||
} else {
|
||||
this.status.installed = false;
|
||||
this.status.canUpgrade = false;
|
||||
status.installed = false;
|
||||
status.canUpgrade = false;
|
||||
}
|
||||
} catch(e) {
|
||||
if (e?.error?.code === 404) {
|
||||
this.status.installed = false;
|
||||
this.status.canUpgrade = false;
|
||||
status.installed = false;
|
||||
status.canUpgrade = false;
|
||||
}
|
||||
}
|
||||
|
||||
return this.status;
|
||||
return status;
|
||||
}
|
||||
|
||||
async uninstall(cluster: Store.Cluster): Promise<void> {
|
||||
const podApi = K8sApi.forCluster(cluster, K8sApi.Pod);
|
||||
await podApi.delete({name: "example-pod", namespace: "default"});
|
||||
async uninstall(): Promise<string> {
|
||||
return this.stack.kubectlDeleteFolder(this.resourceFolder);
|
||||
}
|
||||
}
|
||||
```
|
||||
@ -540,12 +575,12 @@ You can use Lens extensions to add custom preferences to the Preferences page, p
|
||||
The following example demonstrates adding a custom preference:
|
||||
|
||||
```typescript
|
||||
import { LensRendererExtension } from "@k8slens/extensions";
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
import { ExamplePreferenceHint, ExamplePreferenceInput } from "./src/example-preference";
|
||||
import { observable } from "mobx";
|
||||
import React from "react";
|
||||
|
||||
export default class ExampleRendererExtension extends LensRendererExtension {
|
||||
export default class ExampleRendererExtension extends Renderer.LensExtension {
|
||||
|
||||
@observable preference = { enabled: false };
|
||||
|
||||
@ -579,10 +614,16 @@ This is how `ExampleRendererExtension` handles the state of the preference input
|
||||
In this example `ExamplePreferenceInput`, `ExamplePreferenceHint`, and `ExamplePreferenceProps` are defined in `./src/example-preference.tsx` as follows:
|
||||
|
||||
```typescript
|
||||
import { Component } from "@k8slens/extensions";
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
import { observer } from "mobx-react";
|
||||
import React from "react";
|
||||
|
||||
const {
|
||||
Component: {
|
||||
Checkbox,
|
||||
},
|
||||
} = Renderer;
|
||||
|
||||
export class ExamplePreferenceProps {
|
||||
preference: {
|
||||
enabled: boolean;
|
||||
@ -595,7 +636,7 @@ export class ExamplePreferenceInput extends React.Component<ExamplePreferencePro
|
||||
render() {
|
||||
const { preference } = this.props;
|
||||
return (
|
||||
<Component.Checkbox
|
||||
<Checkbox
|
||||
label="I understand appPreferences"
|
||||
value={preference.enabled}
|
||||
onChange={v => { preference.enabled = v; }}
|
||||
@ -613,7 +654,7 @@ export class ExamplePreferenceHint extends React.Component {
|
||||
}
|
||||
```
|
||||
|
||||
`ExamplePreferenceInput` implements a simple checkbox using Lens's `Component.Checkbox` using the following properties:
|
||||
`ExamplePreferenceInput` implements a simple checkbox using Lens's `Renderer.Component.Checkbox` using the following properties:
|
||||
|
||||
* `label` sets the text that displays next to the checkbox.
|
||||
* `value` is initially set to `preference.enabled`.
|
||||
@ -646,11 +687,11 @@ The following example adds a `statusBarItems` definition and a `globalPages` def
|
||||
It configures the status bar item to navigate to the global page upon activation (normally a mouse click):
|
||||
|
||||
```typescript
|
||||
import { LensRendererExtension } from '@k8slens/extensions';
|
||||
import { Renderer } from '@k8slens/extensions';
|
||||
import { HelpIcon, HelpPage } from "./page"
|
||||
import React from 'react';
|
||||
|
||||
export default class HelpExtension extends LensRendererExtension {
|
||||
export default class HelpExtension extends Renderer.LensExtension {
|
||||
globalPages = [
|
||||
{
|
||||
id: "help",
|
||||
@ -704,16 +745,19 @@ The following example shows how to add a `kubeObjectMenuItems` for namespace res
|
||||
|
||||
```typescript
|
||||
import React from "react"
|
||||
import { LensRendererExtension } from "@k8slens/extensions";
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
import { NamespaceMenuItem } from "./src/namespace-menu-item"
|
||||
|
||||
export default class ExampleExtension extends LensRendererExtension {
|
||||
type KubeObjectMenuProps = Renderer.Component.KubeObjectMenuProps;
|
||||
type Namespace = Renderer.K8sApi.Namespace;
|
||||
|
||||
export default class ExampleExtension extends Renderer.LensExtension {
|
||||
kubeObjectMenuItems = [
|
||||
{
|
||||
kind: "Namespace",
|
||||
apiVersions: ["v1"],
|
||||
components: {
|
||||
MenuItem: (props: Component.KubeObjectMenuProps<K8sApi.Namespace>) => <NamespaceMenuItem {...props} />
|
||||
MenuItem: (props: KubeObjectMenuProps<Namespace>) => <NamespaceMenuItem {...props} />
|
||||
}
|
||||
}
|
||||
];
|
||||
@ -735,16 +779,28 @@ In this example a `NamespaceMenuItem` object is returned.
|
||||
|
||||
```typescript
|
||||
import React from "react";
|
||||
import { Component, K8sApi, Navigation} from "@k8slens/extensions";
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
|
||||
export function NamespaceMenuItem(props: Component.KubeObjectMenuProps<K8sApi.Namespace>) {
|
||||
const {
|
||||
Component: {
|
||||
terminalStore,
|
||||
MenuItem,
|
||||
Icon,
|
||||
},
|
||||
Navigation,
|
||||
} = Renderer;
|
||||
|
||||
type KubeObjectMenuProps = Renderer.Component.KubeObjectMenuProps;
|
||||
type Namespace = Renderer.K8sApi.Namespace;
|
||||
|
||||
export function NamespaceMenuItem(props: KubeObjectMenuProps<Namespace>) {
|
||||
const { object: namespace, toolbar } = props;
|
||||
if (!namespace) return null;
|
||||
|
||||
const namespaceName = namespace.getName();
|
||||
|
||||
const sendToTerminal = (command: string) => {
|
||||
Component.terminalStore.sendCommand(command, {
|
||||
terminalStore.sendCommand(command, {
|
||||
enter: true,
|
||||
newTab: true,
|
||||
});
|
||||
@ -756,21 +812,21 @@ export function NamespaceMenuItem(props: Component.KubeObjectMenuProps<K8sApi.Na
|
||||
};
|
||||
|
||||
return (
|
||||
<Component.MenuItem onClick={getPods}>
|
||||
<Component.Icon material="speaker_group" interactive={toolbar} title="Get pods in terminal"/>
|
||||
<span className="title">Get Pods</span>
|
||||
</Component.MenuItem>
|
||||
<MenuItem onClick={getPods}>
|
||||
<Icon material="speaker_group" interactive={toolbar} title="Get pods in terminal"/>
|
||||
<span className="title">Get Pods</span>
|
||||
</MenuItem>
|
||||
);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
`NamespaceMenuItem` returns a `Component.MenuItem` which defines the menu item's appearance and its behavior when activated via the `onClick` property.
|
||||
`NamespaceMenuItem` returns a `Renderer.Component.MenuItem` which defines the menu item's appearance and its behavior when activated via the `onClick` property.
|
||||
In the example, `getPods()` opens a terminal tab and runs `kubectl` to get a list of pods running in the current namespace.
|
||||
|
||||
The name of the namespace is retrieved from `props` passed into `NamespaceMenuItem()`.
|
||||
`namespace` is the `props.object`, which is of type `K8sApi.Namespace`.
|
||||
`K8sApi.Namespace` is the API for accessing namespaces.
|
||||
`namespace` is the `props.object`, which is of type `Renderer.K8sApi.Namespace`.
|
||||
`Renderer.K8sApi.Namespace` is the API for accessing namespaces.
|
||||
The current namespace in this example is simply given by `namespace.getName()`.
|
||||
Thus, `kubeObjectMenuItems` afford convenient access to the specific resource selected by the user.
|
||||
|
||||
@ -784,18 +840,22 @@ These custom details appear on the details page for a specific resource, such as
|
||||
The following example shows how to use `kubeObjectDetailItems` to add a tabulated list of pods to the Namespace resource details page:
|
||||
|
||||
```typescript
|
||||
import React from "react"
|
||||
import { LensRendererExtension } from "@k8slens/extensions";
|
||||
import { NamespaceDetailsItem } from "./src/namespace-details-item"
|
||||
import React from "react";
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
import { NamespaceDetailsItem } from "./src/namespace-details-item";
|
||||
|
||||
export default class ExampleExtension extends LensRendererExtension {
|
||||
type KubeObjectMenuProps = Renderer.Component.KubeObjectMenuProps;
|
||||
type KubeObjectDetailsProps = Renderer.Component.KubeObjectDetailsProps;
|
||||
type Namespace = Renderer.K8sApi.Namespace;
|
||||
|
||||
export default class ExampleExtension extends Renderer.LensExtension {
|
||||
kubeObjectDetailItems = [
|
||||
{
|
||||
kind: "Namespace",
|
||||
apiVersions: ["v1"],
|
||||
priority: 10,
|
||||
components: {
|
||||
Details: (props: Component.KubeObjectDetailsProps<K8sApi.Namespace>) => <NamespaceDetailsItem {...props} />
|
||||
Details: (props: KubeObjectDetailsProps<Namespace>) => <NamespaceDetailsItem {...props} />
|
||||
}
|
||||
}
|
||||
];
|
||||
@ -815,25 +875,39 @@ In this example a `NamespaceDetailsItem` object is returned.
|
||||
`NamespaceDetailsItem` is defined in `./src/namespace-details-item.tsx`:
|
||||
|
||||
``` typescript
|
||||
import { Component, K8sApi } from "@k8slens/extensions";
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
import { PodsDetailsList } from "./pods-details-list";
|
||||
import React from "react";
|
||||
import { observable } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
|
||||
@observer
|
||||
export class NamespaceDetailsItem extends React.Component<Component.KubeObjectDetailsProps<K8sApi.Namespace>> {
|
||||
const {
|
||||
K8sApi: {
|
||||
podsApi,
|
||||
},
|
||||
Component: {
|
||||
DrawerTitle,
|
||||
},
|
||||
} = Renderer;
|
||||
|
||||
@observable private pods: K8sApi.Pod[];
|
||||
type KubeObjectMenuProps = Renderer.Component.KubeObjectMenuProps;
|
||||
type Namespace = Renderer.K8sApi.Namespace;
|
||||
type Pod = Renderer.K8sApi.Pod;
|
||||
|
||||
@observer
|
||||
export class NamespaceDetailsItem extends React.Component<KubeObjectDetailsProps<Namespace>> {
|
||||
@observable private pods: Pod[];
|
||||
|
||||
async componentDidMount() {
|
||||
this.pods = await K8sApi.podsApi.list({namespace: this.props.object.getName()});
|
||||
const namespace = this.props.object.getName();
|
||||
|
||||
this.pods = await podsApi.list({ namespace });
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Component.DrawerTitle title="Pods" />
|
||||
<DrawerTitle title="Pods" />
|
||||
<PodsDetailsList pods={this.pods}/>
|
||||
</div>
|
||||
)
|
||||
@ -841,14 +915,14 @@ export class NamespaceDetailsItem extends React.Component<Component.KubeObjectDe
|
||||
}
|
||||
```
|
||||
|
||||
Since `NamespaceDetailsItem` extends `React.Component<Component.KubeObjectDetailsProps<K8sApi.Namespace>>`, it can access the current namespace object (type `K8sApi.Namespace`) through `this.props.object`.
|
||||
Since `NamespaceDetailsItem` extends `React.Component<KubeObjectDetailsProps<Namespace>>`, it can access the current namespace object (type `Namespace`) through `this.props.object`.
|
||||
You can query this object for many details about the current namespace.
|
||||
In the example above, `componentDidMount()` gets the namespace's name using the `K8sApi.Namespace` `getName()` method.
|
||||
In the example above, `componentDidMount()` gets the namespace's name using the `Namespace` `getName()` method.
|
||||
Use the namespace's name to limit the list of pods only to those in the relevant namespace.
|
||||
To get this list of pods, this example uses the Kubernetes pods API `K8sApi.podsApi.list()` method.
|
||||
The `K8sApi.podsApi` is automatically configured for the active cluster.
|
||||
To get this list of pods, this example uses the Kubernetes pods API `podsApi.list()` method.
|
||||
The `podsApi` is automatically configured for the active cluster.
|
||||
|
||||
Note that `K8sApi.podsApi.list()` is an asynchronous method.
|
||||
Note that `podsApi.list()` is an asynchronous method.
|
||||
Getting the pods list should occur prior to rendering the `NamespaceDetailsItem`.
|
||||
It is a common technique in React development to await async calls in `componentDidMount()`.
|
||||
However, `componentDidMount()` is called right after the first call to `render()`.
|
||||
@ -857,51 +931,59 @@ Like in the [`appPreferences` guide](#apppreferences), [`mobx`](https://mobx.js.
|
||||
This is done simply by marking the `pods` field as an `observable` and the `NamespaceDetailsItem` class itself as an `observer`.
|
||||
|
||||
Finally, the `NamespaceDetailsItem` renders using the `render()` method.
|
||||
Details are placed in drawers, and using `Component.DrawerTitle` provides a separator from details above this one.
|
||||
Multiple details in a drawer can be placed in `<Component.DrawerItem>` elements for further separation, if desired.
|
||||
Details are placed in drawers, and using `Renderer.Component.DrawerTitle` provides a separator from details above this one.
|
||||
Multiple details in a drawer can be placed in `<Renderer.Component.DrawerItem>` elements for further separation, if desired.
|
||||
The rest of this example's details are defined in `PodsDetailsList`, found in `./pods-details-list.tsx`:
|
||||
|
||||
``` typescript
|
||||
import React from "react";
|
||||
import { Component, K8sApi } from "@k8slens/extensions";
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
|
||||
const {
|
||||
Component: {
|
||||
TableHead,
|
||||
TableRow,
|
||||
TableCell,
|
||||
Table,
|
||||
},
|
||||
} = Renderer;
|
||||
|
||||
type Pod = Renderer.K8sApi.Pod;
|
||||
|
||||
interface Props {
|
||||
pods: K8sApi.Pod[];
|
||||
pods?: Pod[];
|
||||
}
|
||||
|
||||
export class PodsDetailsList extends React.Component<Props> {
|
||||
|
||||
getTableRow(index: number) {
|
||||
const {pods} = this.props;
|
||||
return (
|
||||
<Component.TableRow key={index} nowrap>
|
||||
<Component.TableCell className="podName">{pods[index].getName()}</Component.TableCell>
|
||||
<Component.TableCell className="podAge">{pods[index].getAge()}</Component.TableCell>
|
||||
<Component.TableCell className="podStatus">{pods[index].getStatus()}</Component.TableCell>
|
||||
</Component.TableRow>
|
||||
)
|
||||
}
|
||||
getTableRow = (pod: Pod) => {
|
||||
return (
|
||||
<TableRow key={index} nowrap>
|
||||
<TableCell className="podName">{pods[index].getName()}</TableCell>
|
||||
<TableCell className="podAge">{pods[index].getAge()}</TableCell>
|
||||
<TableCell className="podStatus">{pods[index].getStatus()}</TableCell>
|
||||
</TableRow>
|
||||
)
|
||||
};
|
||||
|
||||
render() {
|
||||
const {pods} = this.props
|
||||
if (!pods?.length) {
|
||||
return null;
|
||||
}
|
||||
const { pods } = this.props
|
||||
|
||||
if (!pods?.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div >
|
||||
<Component.Table>
|
||||
<Component.TableHead>
|
||||
<Component.TableCell className="podName">Name</Component.TableCell>
|
||||
<Component.TableCell className="podAge">Age</Component.TableCell>
|
||||
<Component.TableCell className="podStatus">Status</Component.TableCell>
|
||||
</Component.TableHead>
|
||||
{
|
||||
pods.map((pod, index) => this.getTableRow(index))
|
||||
}
|
||||
</Component.Table>
|
||||
</div>
|
||||
)
|
||||
return (
|
||||
<div>
|
||||
<Table>
|
||||
<TableHead>
|
||||
<TableCell className="podName">Name</TableCell>
|
||||
<TableCell className="podAge">Age</TableCell>
|
||||
<TableCell className="podStatus">Status</TableCell>
|
||||
</TableHead>
|
||||
{ pods.map(this.getTableRow) }
|
||||
</Table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
@ -910,9 +992,9 @@ export class PodsDetailsList extends React.Component<Props> {
|
||||
|
||||

|
||||
|
||||
Obtain the name, age, and status for each pod using the `K8sApi.Pod` methods.
|
||||
Construct the table using the `Component.Table` and related elements.
|
||||
Obtain the name, age, and status for each pod using the `Renderer.K8sApi.Pod` methods.
|
||||
Construct the table using the `Renderer.Component.Table` and related elements.
|
||||
|
||||
For each pod the name, age, and status are obtained using the `K8sApi.Pod` methods.
|
||||
The table is constructed using the `Component.Table` and related elements.
|
||||
See [`Component` documentation](https://docs.k8slens.dev/master/extensions/api/modules/_renderer_api_components_/) for further details.
|
||||
For each pod the name, age, and status are obtained using the `Renderer.K8sApi.Pod` methods.
|
||||
The table is constructed using the `Renderer.Component.Table` and related elements.
|
||||
See [Component documentation](https://docs.k8slens.dev/latest/extensions/api/modules/_renderer_api_components_/) for further details.
|
||||
|
||||
@ -24,14 +24,14 @@ This is so that your data is kept up to date and not persisted longer than expec
|
||||
The following example code creates a store for the `appPreferences` guide example:
|
||||
|
||||
``` typescript
|
||||
import { Store } from "@k8slens/extensions";
|
||||
import { observable, toJS } from "mobx";
|
||||
import { Common } from "@k8slens/extensions";
|
||||
import { observable, makeObservable } from "mobx";
|
||||
|
||||
export type ExamplePreferencesModel = {
|
||||
enabled: boolean;
|
||||
};
|
||||
|
||||
export class ExamplePreferencesStore extends Store.ExtensionStore<ExamplePreferencesModel> {
|
||||
export class ExamplePreferencesStore extends Common.Store.ExtensionStore<ExamplePreferencesModel> {
|
||||
|
||||
@observable enabled = false;
|
||||
|
||||
@ -42,6 +42,7 @@ export class ExamplePreferencesStore extends Store.ExtensionStore<ExamplePrefere
|
||||
enabled: false
|
||||
}
|
||||
});
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
protected fromStore({ enabled }: ExamplePreferencesModel): void {
|
||||
@ -49,11 +50,9 @@ export class ExamplePreferencesStore extends Store.ExtensionStore<ExamplePrefere
|
||||
}
|
||||
|
||||
toJSON(): ExamplePreferencesModel {
|
||||
return toJS({
|
||||
return {
|
||||
enabled: this.enabled
|
||||
}, {
|
||||
recurseEverything: true
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
```
|
||||
@ -73,7 +72,6 @@ The `enabled` field of the `ExamplePreferencesStore` is set to the value from th
|
||||
The `toJSON()` method is complementary to `fromStore()`.
|
||||
It is called when the store is being saved.
|
||||
`toJSON()` must provide a JSON serializable object, facilitating its storage in JSON format.
|
||||
The `toJS()` function from [`mobx`](https://mobx.js.org/README.html) is convenient for this purpose, and is used here.
|
||||
|
||||
Finally, `ExamplePreferencesStore` is created by calling `ExamplePreferencesStore.getInstanceOrCreate()`, and exported for use by other parts of the extension.
|
||||
Note that `ExamplePreferencesStore` is a singleton.
|
||||
@ -89,10 +87,10 @@ The following example code, modified from the [`appPreferences`](../renderer-ext
|
||||
This can be done in `./main.ts`:
|
||||
|
||||
``` typescript
|
||||
import { LensMainExtension } from "@k8slens/extensions";
|
||||
import { Main } from "@k8slens/extensions";
|
||||
import { ExamplePreferencesStore } from "./src/example-preference-store";
|
||||
|
||||
export default class ExampleMainExtension extends LensMainExtension {
|
||||
export default class ExampleMainExtension extends Main.LensExtension {
|
||||
async onActivate() {
|
||||
await ExamplePreferencesStore.getInstanceOrCreate().loadExtension(this);
|
||||
}
|
||||
@ -104,12 +102,12 @@ Similarly, `ExamplePreferencesStore` must load in the renderer process where the
|
||||
This can be done in `./renderer.ts`:
|
||||
|
||||
``` typescript
|
||||
import { LensRendererExtension } from "@k8slens/extensions";
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
import { ExamplePreferenceHint, ExamplePreferenceInput } from "./src/example-preference";
|
||||
import { ExamplePreferencesStore } from "./src/example-preference-store";
|
||||
import React from "react";
|
||||
|
||||
export default class ExampleRendererExtension extends LensRendererExtension {
|
||||
export default class ExampleRendererExtension extends Renderer.LensExtension {
|
||||
|
||||
async onActivate() {
|
||||
await ExamplePreferencesStore.getInstanceOrCreate().loadExtension(this);
|
||||
@ -132,17 +130,23 @@ Again, `ExamplePreferencesStore.getInstanceOrCreate().loadExtension(this)` is ca
|
||||
`ExamplePreferenceInput` is defined in `./src/example-preference.tsx`:
|
||||
|
||||
``` typescript
|
||||
import { Component } from "@k8slens/extensions";
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
import { observer } from "mobx-react";
|
||||
import React from "react";
|
||||
import { ExamplePreferencesStore } from "./example-preference-store";
|
||||
|
||||
const {
|
||||
Component: {
|
||||
Checkbox,
|
||||
},
|
||||
} = Renderer;
|
||||
|
||||
@observer
|
||||
export class ExamplePreferenceInput extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Component.Checkbox
|
||||
<Checkbox
|
||||
label="I understand appPreferences"
|
||||
value={ExamplePreferencesStore.getInstace().enabled}
|
||||
onChange={v => { ExamplePreferencesStore.getInstace().enabled = v; }}
|
||||
|
||||
@ -14,7 +14,13 @@ My component `GlobalPageMenuIcon`
|
||||
|
||||
```typescript
|
||||
import React from "react"
|
||||
import { Component: { Icon } } from "@k8slens/extensions";
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
|
||||
const {
|
||||
Component: {
|
||||
Icon,
|
||||
},
|
||||
} = Renderer;
|
||||
|
||||
const GlobalPageMenuIcon = ({ navigate }: { navigate?: () => void }): JSX.Element => (
|
||||
<Icon
|
||||
|
||||
@ -1,18 +1,7 @@
|
||||
# Extension API Reference
|
||||
|
||||
## Modules
|
||||
|
||||
* [App](modules/_core_api_app_.md)
|
||||
* [ClusterFeature](modules/_core_api_cluster_feature_.md)
|
||||
* [EventBus](modules/_core_api_event_bus_.md)
|
||||
* [Store](modules/_core_api_stores_.md)
|
||||
* [Util](modules/_core_api_utils_.md)
|
||||
* [Component](modules/_renderer_api_components_.md)
|
||||
* [K8sApi](modules/_renderer_api_k8s_api_.md)
|
||||
* [Navigation](modules/_renderer_api_navigation_.md)
|
||||
|
||||
## Classes
|
||||
|
||||
* [LensMainExtension](classes/lensmainextension.md)
|
||||
* [LensRendererExtension](classes/lensrendererextension.md)
|
||||
## APIs
|
||||
|
||||
- [Common](modules/common.md)
|
||||
- [Main](modules/main.md)
|
||||
- [Renderer](modules/renderer.md)
|
||||
|
||||
@ -1,66 +0,0 @@
|
||||
# FAQ
|
||||
|
||||
### What operating systems does Lens support?
|
||||
|
||||
Lens supports MacOS, Windows and Linux operating systems. For Linux there are Snap and AppImage versions. For MacOS there are DMG and Homebrew options.
|
||||
|
||||
### Lens application is not opening, what might be wrong?
|
||||
|
||||
When Lens is started, it will start HTTP proxy server on the background and requires that operating system allows to start listening to some free port. You can see the port allocated for Lens from application logs. Lens expects also that `localhost` DNS points to `127.0.0.1` address.
|
||||
|
||||
### Why can't I add any clusters?
|
||||
|
||||
When adding new clusters, a valid Kubeconfig file is required. Please check that all contexts present in Kubeconfig file are valid.
|
||||
|
||||
### Why Cluster dashboard is not opening?
|
||||
|
||||
To see Cluster dashboard properly, Kubernetes cluster must be reachable either directly from your computer or via HTTP proxy. You can configure HTTP proxy in Cluster Settigns. Also, provided credentials in Kubeconfig must be valid. If Kubeconfig uses `exec` command, the binary must be available in global PATH or absolute path must be used. Lens application can't see PATH modifications made by any shell init scripts. There might be also some issues on the Snap version if the exec binary is installed also from Snap and requires additional symlinking, please see [#699](https://github.com/lensapp/lens/issues/699).
|
||||
|
||||
### Why I don't see anything on Cluster dashboard?
|
||||
|
||||
Users will see on Cluster dashboard only those resources that they are allowed to see (RBAC). Lens requires that user has access at least to one namespace. Lens tries first fetch namespaces from Kubernetes API. If user is not allowed to list namespaces, allowed namespaces can be configured in Cluster settings or in Kubeconfig.
|
||||
|
||||
### Why I don't see any metrics or some of the metrics are not working?
|
||||
|
||||
In order to display cluster metrics, Lens requires that Prometheus is running in the cluster. You can install Prometheus in Cluster settings if needed.
|
||||
|
||||
Lens tries to detect Prometheus installation automatically. If it fails to detect the installation properly, you can configure Prometheus service address in Cluster settings. If some of the metrics are not displayed correctly, you can see queries that Lens is using [here](https://github.com/lensapp/lens/tree/master/src/main/prometheus) and adapt your prometheus configuration to support those queries. Please refer [Prometheus documentation](https://prometheus.io/docs/prometheus/latest/configuration/configuration/) or your Prometheus installer documentation how to do this.
|
||||
|
||||
### Kubectl is not working in Lens terminal, what should I do?
|
||||
|
||||
Lens tries to download correct Kubectl version for the cluster and use that in Lens terminal. Some operating systems (namely Windows) might have restrictions set that prevent downloading and executing binaries from the default location that Lens is using. You can change the directory where Lens downloads the binaries in App Preferences. It's also possible to change the Download mirror to use Azure if default Google is not reachable from your network. If downloading Kubectl is not option for you, you can define path to pre-installed Kubectl on your machine and Lens will use that binary instead.
|
||||
|
||||
### How can I configure Helm repositories?
|
||||
|
||||
Lens comes with bundled Helm 3 binary and Lens will add by default `bitnami` repository if no other repositories are configured. You can add more repositories from Artifact HUB in App preferences. At this moment it is not possible to add private repositories. Those and other public repositories can be added manually via command line.
|
||||
|
||||
### Where can I find application logs?
|
||||
|
||||
Lens will store application logs to following locations depending on your operating system:
|
||||
- MacOS: ~/Library/Logs/Lens/
|
||||
- Windows: %USERPROFILE%\AppData\Roaming\Lens\logs\
|
||||
- Linux: ~/.config/Lens/logs/
|
||||
|
||||
### How can I see more verbose logs?
|
||||
|
||||
You can start Lens application on debug mode from the command line to see more verbose logs. To start application on debug mode, please provide `DEBUG=true` environment variable and before starting the application, for example: `DEBUG=TRUE /Applications/Lens.app/Contents/MacOS/Lens`
|
||||
|
||||
### Why Lens window rendering is broken?
|
||||
|
||||
MacOS users can encouter visual bug with fuzzy lines appeared while [connected to external 4K display](https://www.forbes.com/sites/gordonkelly/2020/06/11/apple-macos-macbook-pro-google-chrome-display-problem/?sh=331ac27967b4). Same thing can happen with any of Electron applications or Chrome itself.
|
||||
|
||||

|
||||
|
||||
As a temporary workaround there is a possibility to disable Chromium GPU acceleration. To do this for Lens, you need to provide `LENS_DISABLE_GPU=true` env variable and relaunch app.
|
||||
|
||||
First, open `.bash_profile` file from your terminal
|
||||
|
||||
```
|
||||
open -a TextEdit.app ~/.bash_profile
|
||||
```
|
||||
|
||||
Then, add this line
|
||||
|
||||
```
|
||||
export LENS_DISABLE_GPU=true
|
||||
```
|
||||
@ -1,77 +0,0 @@
|
||||
# Getting Started
|
||||
|
||||
Lens is lightweight and simple to install. You'll be up and running in just a few minutes.
|
||||
|
||||
|
||||
## System Requirements
|
||||
|
||||
Review the [System Requirements](../supporting/requirements.md) to check if your computer configuration is supported.
|
||||
|
||||
|
||||
## macOS
|
||||
|
||||
1. [Download Lens](https://github.com/lensapp/lens/releases) for macOS.
|
||||
2. Open the browser's download list and locate the downloaded archive.
|
||||
3. Select the 'magnifying glass' icon to open the archive in Finder.
|
||||
4. Double-click `Lens-{version}.dmg` and drag `Lens.app` to the `Applications` folder, making it available in the macOS Launchpad.
|
||||
5. Add Lens to your Dock by right-clicking on the icon to bring up the context menu and choosing **Options**, **Keep in Dock**.
|
||||
|
||||
|
||||
## Windows
|
||||
|
||||
1. Download the [Lens installer](https://github.com/lensapp/lens/releases) for Windows.
|
||||
2. Once it is downloaded, run the installer `Lens-Setup-{version}.exe`. This will only take a minute.
|
||||
3. By default, Lens is installed under `C:\users\{username}\AppData\Local\Programs\Lens`.
|
||||
|
||||
|
||||
## Linux
|
||||
|
||||
See the [Download Lens](https://github.com/lensapp/lens/releases) page for a complete list of available installation options.
|
||||
|
||||
After installing Lens manually (not using a package manager file such as `.deb` or `.rpm`) the following will need to be done to allow protocol handling.
|
||||
This assumes that your linux distribution uses `xdg-open` and the `xdg-*` suite of programs for determining which application can handle custom URIs.
|
||||
|
||||
1. Create a file called `lens.desktop` in either `~/.local/share/applications/` or `/usr/share/applications` (if you have permissions and are installing Lens for all users).
|
||||
1. That file should have the following contents, with `<path/to/executable>` being the absolute path to where you have installed the unpacked `Lens` executable:
|
||||
```
|
||||
[Desktop Entry]
|
||||
Name=Lens
|
||||
Exec=<path/to/executable> %U
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Icon=lens
|
||||
StartupWMClass=Lens
|
||||
Comment=Lens - The Kubernetes IDE
|
||||
MimeType=x-scheme-handler/lens;
|
||||
Categories=Network;
|
||||
```
|
||||
1. Then run the following command:
|
||||
```
|
||||
xdg-settings set default-url-scheme-handler lens lens.desktop
|
||||
```
|
||||
1. If that succeeds (exits with code `0`) then your Lens install should be set up to handle `lens://` URIs.
|
||||
|
||||
### Snap
|
||||
|
||||
Lens is officially distributed as a Snap package in the [Snap Store](https://snapcraft.io/store):
|
||||
|
||||
[](https://snapcraft.io/kontena-lens)
|
||||
|
||||
You can install it by running:
|
||||
|
||||
```bash
|
||||
sudo snap install kontena-lens --classic
|
||||
```
|
||||
|
||||
## Update Cadence
|
||||
|
||||
Lens releases a new version each month with new features and important bug fixes. Lens supports auto updating and you will be prompted to install the new release when it becomes available!
|
||||
|
||||
To stay current with the Lens features, you can review the [release notes](https://github.com/lensapp/lens/releases).
|
||||
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Launch Lens](lens://app/landing)
|
||||
- [Add clusters](../clusters/adding-clusters.md)
|
||||
- [Watch introductory videos](./introductory-videos.md)
|
||||
|
Before Width: | Height: | Size: 131 KiB |
|
Before Width: | Height: | Size: 124 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
@ -1,36 +0,0 @@
|
||||
# Introductory Videos
|
||||
|
||||
Continue your Lens journey with this set of introductory videos! These videos are meant to quickly familiarize you with Lens' various powerful features.
|
||||
|
||||
<ul class="video-list">
|
||||
<li class="video">
|
||||
<a target="_blank" href="https://youtu.be/mc-BzPDKfkQ">
|
||||
<img src="https://img.youtube.com/vi/mc-BzPDKfkQ/mqdefault.jpg" alt aria-hidden="true" class="thumb"/>
|
||||
<div class="info">
|
||||
<h3 class="title">Getting started</h3>
|
||||
<p class="description">Get Lens Kubernetes IDE Running in 5 Minutes</p>
|
||||
<span class="duration"><span class="sr-only">Duration </span>35<span class="sr-only"> minutes</span></span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="video">
|
||||
<a target="_blank" href="https://youtu.be/epw_MjxjMYI">
|
||||
<img src="https://img.youtube.com/vi/epw_MjxjMYI/mqdefault.jpg" alt aria-hidden="true" class="thumb"/>
|
||||
<div class="info">
|
||||
<h3 class="title">Introducing Lens</h3>
|
||||
<p class="description">Lens Kubernetes IDE overview</p>
|
||||
<span class="duration"><span class="sr-only">Duration </span>2<span class="sr-only"> minutes</span></span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="video">
|
||||
<a target="_blank" href="https://youtu.be/fqneoWCgJdw">
|
||||
<img src="https://img.youtube.com/vi/fqneoWCgJdw/mqdefault.jpg" alt aria-hidden="true" class="thumb"/>
|
||||
<div class="info">
|
||||
<h3 class="title">Demo of Mirantis Lens</h3>
|
||||
<p class="description">The Best IDE For Kubernetes</p>
|
||||
<span class="duration"><span class="sr-only">Duration </span>10<span class="sr-only"> minutes</span></span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
@ -1,26 +0,0 @@
|
||||
# Preferences
|
||||
|
||||
## Color Themes
|
||||
|
||||
The Color Themes option in Lens preferences lets you set the colors in the Lens user interface to suit your liking.
|
||||
|
||||
1. Go to **File** > **Preferences** (**Lens** > **Preferences** on Mac). Or follow [this link](lens://app/preferences?highlight=appearance).
|
||||
2. Select your preferred theme from the **Color Theme** dropdown.
|
||||

|
||||
|
||||
|
||||
## Telemetry & Usage Tracking
|
||||
|
||||
Lens collects telemetry data, which is used to help us understand how to improve the product. For example, this usage data helps us to debug issues and to prioritize new features. While we appreciate the insights this data provides, we also know that not everyone wants to send usage data. Please see our [privacy statement](https://www.mirantis.com/company/privacy-policy/) to learn more.
|
||||
|
||||
|
||||
### Disable Telemetry Reporting
|
||||
|
||||
If you don't wish to send usage data to Mirantis, you can disable the "Telemetry & Usage Tracking" in the Lens preferences.
|
||||
|
||||
1. Go to **File** > **Preferences** (**Lens** > **Preferences** on Mac). Or follow [this link](lens://app/preferences?highlight=telemetry-tracking).
|
||||
2. Scroll down to **Telemetry & Usage Tracking**
|
||||
3. Uncheck **Allow Telemetry & Usage Tracking**.
|
||||
|
||||
This will silence all telemetry events from Lens going forward. Telemetry information may have been collected and sent up until the point when you disable this setting.
|
||||

|
||||
@ -1,21 +0,0 @@
|
||||
# Using Helm Charts
|
||||
|
||||
Lens has integration to Helm making it easy to install and manage Helm charts and releases in Apps section.
|
||||
|
||||

|
||||
|
||||
## Managing Helm Repositories
|
||||
|
||||
Used Helm repositories are possible to configure in the [Preferences](/getting-started/preferences). Lens app will fetch available Helm repositories from the [Artifact HUB](https://artifacthub.io/) and automatically add `bitnami` repository by default if no other repositories are already configured. If any other repositories are needed to add, those can be added manually via command line. **Note!** Configured Helm repositories are added globally to user's computer, so other processes can see those as well.
|
||||
|
||||
|
||||
## Installing a Helm Chart
|
||||
|
||||
Lens will list all charts from configured Helm repositries on Apps section. To install a chart, you need to select a chart and click "Install" button. Lens will open the chart in the editor where you can select a chart version, target namespace and give optionally a name for the release and configure values for the release. Finally, by clicking "Install" button Lens will deploy the chart into the cluster.
|
||||
|
||||
## Updating a Helm Release
|
||||
|
||||
To update a Helm release, you can open the release details and modify the release values and click "Save" button. To upgrade or downgrade the release, click "Upgrade" button in the release details. In the release editor you can select a new chart version and edit the release values if needed and then click "Upgrade" or "Upgrade and Close" button.
|
||||
|
||||
## Deleting a Helm Release
|
||||
To delete existing Helm release open the release details and click trash can icon on the top of the panel. Deletion removes all Kubernetes resources created by the Helm release. **Note!** If the release included any persistent volumes, those are required to remove manually!
|
||||
|
Before Width: | Height: | Size: 1.1 MiB |
@ -5,13 +5,38 @@
|
||||
|
||||
:root > * {
|
||||
/* Footer */
|
||||
--md-footer-bg-color: #3d90ce;
|
||||
--md-footer-bg-color: #e8e8e8;
|
||||
--md-footer-bg-color--dark: #cccdcf;
|
||||
--md-footer-fg-color: #3d90ce;
|
||||
--md-footer-fg-color--light: #fff;
|
||||
|
||||
/* Background */
|
||||
--md-default-bg-color: #f1f1f1;
|
||||
}
|
||||
|
||||
[data-md-color-scheme="slate"] {
|
||||
/* Footer */
|
||||
--md-footer-bg-color: #2e3136;
|
||||
--md-footer-bg-color--dark: #262b2f;
|
||||
--md-footer-fg-color: #3d90ce;
|
||||
--md-footer-fg-color--light: #fff;
|
||||
|
||||
/* Background */
|
||||
--md-default-bg-color: #1e2124;
|
||||
}
|
||||
|
||||
.md-version__list {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.md-header-nav__title {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.md-header__title {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
ul.video-list {
|
||||
counter-reset: section;
|
||||
list-style: none;
|
||||
|
||||
@ -1,16 +0,0 @@
|
||||
# Support
|
||||
|
||||
Here you will find different ways of getting support for Lens IDE.
|
||||
|
||||
## Community Support
|
||||
|
||||
* [Community Slack](https://join.slack.com/t/k8slens/shared_invite/enQtOTc5NjAyNjYyOTk4LWU1NDQ0ZGFkOWJkNTRhYTc2YjVmZDdkM2FkNGM5MjhiYTRhMDU2NDQ1MzIyMDA4ZGZlNmExOTc0N2JmY2M3ZGI) - Request for support and help from the Lens community via Slack.
|
||||
* [Github Issues](https://github.com/lensapp/lens/issues) - Submit your issues and feature requests to Lens IDE via Github.
|
||||
|
||||
## Commercial Support & Services
|
||||
|
||||
If you are interested in paid support options, professional services or training, please see the offerings from the following vendors:
|
||||
|
||||
* [Mirantis](https://www.mirantis.com/software/lens/) offers commercial support for officially released versions of Lens IDE on MacOS, Windows and Linux operating systems. In addition, Mirantis offers professional services to create proprietary / custom Lens IDE extensions and custom `msi` packaging to meet enterprise IT policies for software distribution and configuration. Training is also available.
|
||||
|
||||
If you'd like to get your business listed in here, please contact us via email [info@k8slens.dev](mailto:info@k8slens.dev)
|
||||
@ -1,26 +0,0 @@
|
||||
# Requirements for Lens
|
||||
|
||||
## Hardware
|
||||
|
||||
Lens is a small download (< 300 MB) and has a disk footprint of 600 MB. Lens is lightweight and should easily run on today's hardware.
|
||||
|
||||
We recommend:
|
||||
|
||||
* 2 GHz or faster processor
|
||||
* 1 GB of RAM
|
||||
|
||||
## Platforms
|
||||
|
||||
Lens has been tested on the following platforms:
|
||||
|
||||
* macOS
|
||||
* Windows
|
||||
* Linux
|
||||
|
||||
### Additional Windows requirements
|
||||
|
||||
...
|
||||
|
||||
### Additional Linux Requirements
|
||||
|
||||
...
|
||||
1
extensions/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
*/*.tgz
|
||||
741
extensions/kube-object-event-status/package-lock.json
generated
@ -6,7 +6,691 @@
|
||||
"dependencies": {
|
||||
"@k8slens/extensions": {
|
||||
"version": "file:../../src/extensions/npm/extensions",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@material-ui/core": "*",
|
||||
"@types/node": "*",
|
||||
"@types/react-select": "*",
|
||||
"conf": "^7.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": {
|
||||
"version": "7.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz",
|
||||
"integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
}
|
||||
},
|
||||
"@emotion/hash": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
|
||||
"integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==",
|
||||
"dev": true
|
||||
},
|
||||
"@emotion/memoize": {
|
||||
"version": "0.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.5.tgz",
|
||||
"integrity": "sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@emotion/serialize": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.2.tgz",
|
||||
"integrity": "sha512-95MgNJ9+/ajxU7QIAruiOAdYNjxZX7G2mhgrtDWswA21VviYIRP1R5QilZ/bDY42xiKsaktP4egJb3QdYQZi1A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@emotion/hash": "^0.8.0",
|
||||
"@emotion/memoize": "^0.7.4",
|
||||
"@emotion/unitless": "^0.7.5",
|
||||
"@emotion/utils": "^1.0.0",
|
||||
"csstype": "^3.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"csstype": {
|
||||
"version": "3.0.8",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.8.tgz",
|
||||
"integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@emotion/unitless": {
|
||||
"version": "0.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
|
||||
"integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==",
|
||||
"dev": true
|
||||
},
|
||||
"@emotion/utils": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.0.0.tgz",
|
||||
"integrity": "sha512-mQC2b3XLDs6QCW+pDQDiyO/EdGZYOygE8s5N5rrzjSI4M3IejPE/JPndCBwRT9z982aqQNi6beWs1UeayrQxxA==",
|
||||
"dev": true
|
||||
},
|
||||
"@material-ui/core": {
|
||||
"version": "4.11.4",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.11.4.tgz",
|
||||
"integrity": "sha512-oqb+lJ2Dl9HXI9orc6/aN8ZIAMkeThufA5iZELf2LQeBn2NtjVilF5D2w7e9RpntAzDb4jK5DsVhkfOvFY/8fg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.4.4",
|
||||
"@material-ui/styles": "^4.11.4",
|
||||
"@material-ui/system": "^4.11.3",
|
||||
"@material-ui/types": "5.1.0",
|
||||
"@material-ui/utils": "^4.11.2",
|
||||
"@types/react-transition-group": "^4.2.0",
|
||||
"clsx": "^1.0.4",
|
||||
"hoist-non-react-statics": "^3.3.2",
|
||||
"popper.js": "1.16.1-lts",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-is": "^16.8.0 || ^17.0.0",
|
||||
"react-transition-group": "^4.4.0"
|
||||
}
|
||||
},
|
||||
"@material-ui/styles": {
|
||||
"version": "4.11.4",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.4.tgz",
|
||||
"integrity": "sha512-KNTIZcnj/zprG5LW0Sao7zw+yG3O35pviHzejMdcSGCdWbiO8qzRgOYL8JAxAsWBKOKYwVZxXtHWaB5T2Kvxew==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.4.4",
|
||||
"@emotion/hash": "^0.8.0",
|
||||
"@material-ui/types": "5.1.0",
|
||||
"@material-ui/utils": "^4.11.2",
|
||||
"clsx": "^1.0.4",
|
||||
"csstype": "^2.5.2",
|
||||
"hoist-non-react-statics": "^3.3.2",
|
||||
"jss": "^10.5.1",
|
||||
"jss-plugin-camel-case": "^10.5.1",
|
||||
"jss-plugin-default-unit": "^10.5.1",
|
||||
"jss-plugin-global": "^10.5.1",
|
||||
"jss-plugin-nested": "^10.5.1",
|
||||
"jss-plugin-props-sort": "^10.5.1",
|
||||
"jss-plugin-rule-value-function": "^10.5.1",
|
||||
"jss-plugin-vendor-prefixer": "^10.5.1",
|
||||
"prop-types": "^15.7.2"
|
||||
}
|
||||
},
|
||||
"@material-ui/system": {
|
||||
"version": "4.11.3",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.11.3.tgz",
|
||||
"integrity": "sha512-SY7otguNGol41Mu2Sg6KbBP1ZRFIbFLHGK81y4KYbsV2yIcaEPOmsCK6zwWlp+2yTV3J/VwT6oSBARtGIVdXPw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.4.4",
|
||||
"@material-ui/utils": "^4.11.2",
|
||||
"csstype": "^2.5.2",
|
||||
"prop-types": "^15.7.2"
|
||||
}
|
||||
},
|
||||
"@material-ui/types": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/types/-/types-5.1.0.tgz",
|
||||
"integrity": "sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A==",
|
||||
"dev": true
|
||||
},
|
||||
"@material-ui/utils": {
|
||||
"version": "4.11.2",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.2.tgz",
|
||||
"integrity": "sha512-Uul8w38u+PICe2Fg2pDKCaIG7kOyhowZ9vjiC1FsVwPABTW8vPPKfF6OvxRq3IiBaI1faOJmgdvMG7rMJARBhA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.4.4",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-is": "^16.8.0 || ^17.0.0"
|
||||
}
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "15.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-15.6.1.tgz",
|
||||
"integrity": "sha512-7EIraBEyRHEe7CH+Fm1XvgqU6uwZN8Q7jppJGcqjROMT29qhAuuOxYB1uEY5UMYQKEmA5D+5tBnhdaPXSsLONA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/prop-types": {
|
||||
"version": "15.7.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz",
|
||||
"integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/react": {
|
||||
"version": "17.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.8.tgz",
|
||||
"integrity": "sha512-3sx4c0PbXujrYAKwXxNONXUtRp9C+hE2di0IuxFyf5BELD+B+AXL8G7QrmSKhVwKZDbv0igiAjQAMhXj8Yg3aw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/prop-types": "*",
|
||||
"@types/scheduler": "*",
|
||||
"csstype": "^3.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"csstype": {
|
||||
"version": "3.0.8",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.8.tgz",
|
||||
"integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"version": "17.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.5.tgz",
|
||||
"integrity": "sha512-ikqukEhH4H9gr4iJCmQVNzTB307kROe3XFfHAOTxOXPOw7lAoEXnM5KWTkzeANGL5Ce6ABfiMl/zJBYNi7ObmQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/react-select": {
|
||||
"version": "4.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-select/-/react-select-4.0.15.tgz",
|
||||
"integrity": "sha512-GPyBFYGMVFCtF4eg9riodEco+s2mflR10Nd5csx69+bcdvX6Uo9H/jgrIqovBU9yxBppB9DS66OwD6xxgVqOYQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@emotion/serialize": "^1.0.0",
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"@types/react-transition-group": "*"
|
||||
}
|
||||
},
|
||||
"@types/react-transition-group": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.1.tgz",
|
||||
"integrity": "sha512-vIo69qKKcYoJ8wKCJjwSgCTM+z3chw3g18dkrDfVX665tMH7tmbDxEAnPdey4gTlwZz5QuHGzd+hul0OVZDqqQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/scheduler": {
|
||||
"version": "0.16.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.1.tgz",
|
||||
"integrity": "sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA==",
|
||||
"dev": true
|
||||
},
|
||||
"ajv": {
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
}
|
||||
},
|
||||
"atomically": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/atomically/-/atomically-1.7.0.tgz",
|
||||
"integrity": "sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==",
|
||||
"dev": true
|
||||
},
|
||||
"clsx": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz",
|
||||
"integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==",
|
||||
"dev": true
|
||||
},
|
||||
"conf": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/conf/-/conf-7.1.2.tgz",
|
||||
"integrity": "sha512-r8/HEoWPFn4CztjhMJaWNAe5n+gPUCSaJ0oufbqDLFKsA1V8JjAG7G+p0pgoDFAws9Bpk2VtVLLXqOBA7WxLeg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "^6.12.2",
|
||||
"atomically": "^1.3.1",
|
||||
"debounce-fn": "^4.0.0",
|
||||
"dot-prop": "^5.2.0",
|
||||
"env-paths": "^2.2.0",
|
||||
"json-schema-typed": "^7.0.3",
|
||||
"make-dir": "^3.1.0",
|
||||
"onetime": "^5.1.0",
|
||||
"pkg-up": "^3.1.0",
|
||||
"semver": "^7.3.2"
|
||||
}
|
||||
},
|
||||
"css-vendor": {
|
||||
"version": "2.0.8",
|
||||
"resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.8.tgz",
|
||||
"integrity": "sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.8.3",
|
||||
"is-in-browser": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"csstype": {
|
||||
"version": "2.6.17",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.17.tgz",
|
||||
"integrity": "sha512-u1wmTI1jJGzCJzWndZo8mk4wnPTZd1eOIYTYvuEyOQGfmDl3TrabCCfKnOC86FZwW/9djqTl933UF/cS425i9A==",
|
||||
"dev": true
|
||||
},
|
||||
"debounce-fn": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/debounce-fn/-/debounce-fn-4.0.0.tgz",
|
||||
"integrity": "sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mimic-fn": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"dom-helpers": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
|
||||
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.8.7",
|
||||
"csstype": "^3.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"csstype": {
|
||||
"version": "3.0.8",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.8.tgz",
|
||||
"integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"dot-prop": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz",
|
||||
"integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-obj": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"env-paths": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
|
||||
"integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
|
||||
"dev": true
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"dev": true
|
||||
},
|
||||
"fast-json-stable-stringify": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
|
||||
"dev": true
|
||||
},
|
||||
"find-up": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
|
||||
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"locate-path": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"hoist-non-react-statics": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
|
||||
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"react-is": "^16.7.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"hyphenate-style-name": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz",
|
||||
"integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==",
|
||||
"dev": true
|
||||
},
|
||||
"indefinite-observable": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/indefinite-observable/-/indefinite-observable-2.0.1.tgz",
|
||||
"integrity": "sha512-G8vgmork+6H9S8lUAg1gtXEj2JxIQTo0g2PbFiYOdjkziSI0F7UYBiVwhZRuixhBCNGczAls34+5HJPyZysvxQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"symbol-observable": "1.2.0"
|
||||
}
|
||||
},
|
||||
"is-in-browser": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz",
|
||||
"integrity": "sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU=",
|
||||
"dev": true
|
||||
},
|
||||
"is-obj": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
|
||||
"integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
|
||||
"dev": true
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
||||
"dev": true
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||
"dev": true
|
||||
},
|
||||
"json-schema-typed": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-7.0.3.tgz",
|
||||
"integrity": "sha512-7DE8mpG+/fVw+dTpjbxnx47TaMnDfOI1jwft9g1VybltZCduyRQPJPvc+zzKY9WPHxhPWczyFuYa6I8Mw4iU5A==",
|
||||
"dev": true
|
||||
},
|
||||
"jss": {
|
||||
"version": "10.6.0",
|
||||
"resolved": "https://registry.npmjs.org/jss/-/jss-10.6.0.tgz",
|
||||
"integrity": "sha512-n7SHdCozmxnzYGXBHe0NsO0eUf9TvsHVq2MXvi4JmTn3x5raynodDVE/9VQmBdWFyyj9HpHZ2B4xNZ7MMy7lkw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.3.1",
|
||||
"csstype": "^3.0.2",
|
||||
"indefinite-observable": "^2.0.1",
|
||||
"is-in-browser": "^1.1.3",
|
||||
"tiny-warning": "^1.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"csstype": {
|
||||
"version": "3.0.8",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.8.tgz",
|
||||
"integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"jss-plugin-camel-case": {
|
||||
"version": "10.6.0",
|
||||
"resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.6.0.tgz",
|
||||
"integrity": "sha512-JdLpA3aI/npwj3nDMKk308pvnhoSzkW3PXlbgHAzfx0yHWnPPVUjPhXFtLJzgKZge8lsfkUxvYSQ3X2OYIFU6A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.3.1",
|
||||
"hyphenate-style-name": "^1.0.3",
|
||||
"jss": "10.6.0"
|
||||
}
|
||||
},
|
||||
"jss-plugin-default-unit": {
|
||||
"version": "10.6.0",
|
||||
"resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.6.0.tgz",
|
||||
"integrity": "sha512-7y4cAScMHAxvslBK2JRK37ES9UT0YfTIXWgzUWD5euvR+JR3q+o8sQKzBw7GmkQRfZijrRJKNTiSt1PBsLI9/w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.3.1",
|
||||
"jss": "10.6.0"
|
||||
}
|
||||
},
|
||||
"jss-plugin-global": {
|
||||
"version": "10.6.0",
|
||||
"resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.6.0.tgz",
|
||||
"integrity": "sha512-I3w7ji/UXPi3VuWrTCbHG9rVCgB4yoBQLehGDTmsnDfXQb3r1l3WIdcO8JFp9m0YMmyy2CU7UOV6oPI7/Tmu+w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.3.1",
|
||||
"jss": "10.6.0"
|
||||
}
|
||||
},
|
||||
"jss-plugin-nested": {
|
||||
"version": "10.6.0",
|
||||
"resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.6.0.tgz",
|
||||
"integrity": "sha512-fOFQWgd98H89E6aJSNkEh2fAXquC9aZcAVjSw4q4RoQ9gU++emg18encR4AT4OOIFl4lQwt5nEyBBRn9V1Rk8g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.3.1",
|
||||
"jss": "10.6.0",
|
||||
"tiny-warning": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"jss-plugin-props-sort": {
|
||||
"version": "10.6.0",
|
||||
"resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.6.0.tgz",
|
||||
"integrity": "sha512-oMCe7hgho2FllNc60d9VAfdtMrZPo9n1Iu6RNa+3p9n0Bkvnv/XX5San8fTPujrTBScPqv9mOE0nWVvIaohNuw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.3.1",
|
||||
"jss": "10.6.0"
|
||||
}
|
||||
},
|
||||
"jss-plugin-rule-value-function": {
|
||||
"version": "10.6.0",
|
||||
"resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.6.0.tgz",
|
||||
"integrity": "sha512-TKFqhRTDHN1QrPTMYRlIQUOC2FFQb271+AbnetURKlGvRl/eWLswcgHQajwuxI464uZk91sPiTtdGi7r7XaWfA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.3.1",
|
||||
"jss": "10.6.0",
|
||||
"tiny-warning": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"jss-plugin-vendor-prefixer": {
|
||||
"version": "10.6.0",
|
||||
"resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.6.0.tgz",
|
||||
"integrity": "sha512-doJ7MouBXT1lypLLctCwb4nJ6lDYqrTfVS3LtXgox42Xz0gXusXIIDboeh6UwnSmox90QpVnub7au8ybrb0krQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.3.1",
|
||||
"css-vendor": "^2.0.8",
|
||||
"jss": "10.6.0"
|
||||
}
|
||||
},
|
||||
"locate-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
|
||||
"integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-locate": "^3.0.0",
|
||||
"path-exists": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"loose-envify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||
}
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"make-dir": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
|
||||
"integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"semver": "^6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"mimic-fn": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz",
|
||||
"integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==",
|
||||
"dev": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
|
||||
"dev": true
|
||||
},
|
||||
"onetime": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
|
||||
"integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mimic-fn": "^2.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"mimic-fn": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
|
||||
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"p-limit": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
|
||||
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-try": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"p-locate": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
|
||||
"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-limit": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"p-try": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
||||
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
|
||||
"dev": true
|
||||
},
|
||||
"path-exists": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
|
||||
"integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
|
||||
"dev": true
|
||||
},
|
||||
"pkg-up": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz",
|
||||
"integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"find-up": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"popper.js": {
|
||||
"version": "1.16.1-lts",
|
||||
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1-lts.tgz",
|
||||
"integrity": "sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA==",
|
||||
"dev": true
|
||||
},
|
||||
"prop-types": {
|
||||
"version": "15.7.2",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
|
||||
"integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"react-is": "^16.8.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"punycode": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
|
||||
"dev": true
|
||||
},
|
||||
"react-is": {
|
||||
"version": "17.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
||||
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
|
||||
"dev": true
|
||||
},
|
||||
"react-transition-group": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.1.tgz",
|
||||
"integrity": "sha512-Djqr7OQ2aPUiYurhPalTrVy9ddmFCCzwhqQmtN+J3+3DzLO209Fdr70QrN8Z3DsglWql6iY1lDWAfpFiBtuKGw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"dom-helpers": "^5.0.1",
|
||||
"loose-envify": "^1.4.0",
|
||||
"prop-types": "^15.6.2"
|
||||
}
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.13.7",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
|
||||
"integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==",
|
||||
"dev": true
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.3.5",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
||||
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lru-cache": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"symbol-observable": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
|
||||
"integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==",
|
||||
"dev": true
|
||||
},
|
||||
"tiny-warning": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
|
||||
"integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==",
|
||||
"dev": true
|
||||
},
|
||||
"uri-js": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@webassemblyjs/ast": {
|
||||
"version": "1.9.0",
|
||||
@ -1661,12 +2345,6 @@
|
||||
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
|
||||
"dev": true
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
||||
"dev": true
|
||||
},
|
||||
"json-parse-better-errors": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
|
||||
@ -1721,15 +2399,6 @@
|
||||
"path-exists": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"loose-envify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||
}
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
|
||||
@ -1896,12 +2565,6 @@
|
||||
"minimist": "^1.2.5"
|
||||
}
|
||||
},
|
||||
"mobx": {
|
||||
"version": "5.15.7",
|
||||
"resolved": "https://registry.npmjs.org/mobx/-/mobx-5.15.7.tgz",
|
||||
"integrity": "sha512-wyM3FghTkhmC+hQjyPGGFdpehrcX1KOXsDuERhfK2YbJemkUhEB+6wzEN639T21onxlfYBmriA1PFnvxTUhcKw==",
|
||||
"dev": true
|
||||
},
|
||||
"move-concurrently": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
|
||||
@ -2213,17 +2876,6 @@
|
||||
"integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
|
||||
"dev": true
|
||||
},
|
||||
"prop-types": {
|
||||
"version": "15.7.2",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
|
||||
"integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"react-is": "^16.8.1"
|
||||
}
|
||||
},
|
||||
"prr": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
|
||||
@ -2322,23 +2974,6 @@
|
||||
"safe-buffer": "^5.1.0"
|
||||
}
|
||||
},
|
||||
"react": {
|
||||
"version": "16.14.0",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz",
|
||||
"integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"prop-types": "^15.6.2"
|
||||
}
|
||||
},
|
||||
"react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||
"dev": true
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "2.3.7",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
|
||||
@ -2919,9 +3554,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"typescript": {
|
||||
"version": "4.0.5",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.5.tgz",
|
||||
"integrity": "sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==",
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.2.tgz",
|
||||
"integrity": "sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==",
|
||||
"dev": true
|
||||
},
|
||||
"union-value": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "kube-object-event-status",
|
||||
"version": "0.1.0",
|
||||
"version": "0.0.1",
|
||||
"description": "Adds kube object status from events",
|
||||
"renderer": "dist/renderer.js",
|
||||
"lens": {
|
||||
@ -8,17 +8,18 @@
|
||||
"styles": []
|
||||
},
|
||||
"scripts": {
|
||||
"build": "webpack --config webpack.config.js",
|
||||
"dev": "npm run build --watch",
|
||||
"build": "webpack && npm pack",
|
||||
"dev": "webpack --watch",
|
||||
"test": "echo NO TESTS"
|
||||
},
|
||||
"files": [
|
||||
"dist/**/*"
|
||||
],
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@k8slens/extensions": "file:../../src/extensions/npm/extensions",
|
||||
"ts-loader": "^8.0.4",
|
||||
"typescript": "^4.0.3",
|
||||
"webpack": "^4.44.2",
|
||||
"mobx": "^5.15.5",
|
||||
"react": "^16.13.1"
|
||||
"typescript": "^4.3.2",
|
||||
"webpack": "^4.44.2"
|
||||
}
|
||||
}
|
||||
|
||||
25
extensions/kube-object-event-status/package/package.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "kube-object-event-status",
|
||||
"version": "0.1.0",
|
||||
"description": "Adds kube object status from events",
|
||||
"renderer": "dist/renderer.js",
|
||||
"lens": {
|
||||
"metadata": {},
|
||||
"styles": []
|
||||
},
|
||||
"scripts": {
|
||||
"build": "webpack && npm pack",
|
||||
"dev": "webpack --watch",
|
||||
"test": "echo NO TESTS"
|
||||
},
|
||||
"files": [
|
||||
"dist/**/*"
|
||||
],
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@k8slens/extensions": "file:../../src/extensions/npm/extensions",
|
||||
"ts-loader": "^8.0.4",
|
||||
"typescript": "^4.0.3",
|
||||
"webpack": "^4.44.2"
|
||||
}
|
||||
}
|
||||
@ -1,42 +1,63 @@
|
||||
import { LensRendererExtension, K8sApi } from "@k8slens/extensions";
|
||||
/**
|
||||
* Copyright (c) 2021 OpenLens Authors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
import { resolveStatus, resolveStatusForCronJobs, resolveStatusForPods } from "./src/resolver";
|
||||
|
||||
export default class EventResourceStatusRendererExtension extends LensRendererExtension {
|
||||
export default class EventResourceStatusRendererExtension extends Renderer.LensExtension {
|
||||
kubeObjectStatusTexts = [
|
||||
{
|
||||
kind: "Pod",
|
||||
apiVersions: ["v1"],
|
||||
resolve: (pod: K8sApi.Pod) => resolveStatusForPods(pod)
|
||||
resolve: (pod: Renderer.K8sApi.Pod) => resolveStatusForPods(pod)
|
||||
},
|
||||
{
|
||||
kind: "ReplicaSet",
|
||||
apiVersions: ["v1"],
|
||||
resolve: (replicaSet: K8sApi.ReplicaSet) => resolveStatus(replicaSet)
|
||||
resolve: (replicaSet: Renderer.K8sApi.ReplicaSet) => resolveStatus(replicaSet)
|
||||
},
|
||||
{
|
||||
kind: "Deployment",
|
||||
apiVersions: ["apps/v1"],
|
||||
resolve: (deployment: K8sApi.Deployment) => resolveStatus(deployment)
|
||||
resolve: (deployment: Renderer.K8sApi.Deployment) => resolveStatus(deployment)
|
||||
},
|
||||
{
|
||||
kind: "StatefulSet",
|
||||
apiVersions: ["apps/v1"],
|
||||
resolve: (statefulSet: K8sApi.StatefulSet) => resolveStatus(statefulSet)
|
||||
resolve: (statefulSet: Renderer.K8sApi.StatefulSet) => resolveStatus(statefulSet)
|
||||
},
|
||||
{
|
||||
kind: "DaemonSet",
|
||||
apiVersions: ["apps/v1"],
|
||||
resolve: (daemonSet: K8sApi.DaemonSet) => resolveStatus(daemonSet)
|
||||
resolve: (daemonSet: Renderer.K8sApi.DaemonSet) => resolveStatus(daemonSet)
|
||||
},
|
||||
{
|
||||
kind: "Job",
|
||||
apiVersions: ["batch/v1"],
|
||||
resolve: (job: K8sApi.Job) => resolveStatus(job)
|
||||
resolve: (job: Renderer.K8sApi.Job) => resolveStatus(job)
|
||||
},
|
||||
{
|
||||
kind: "CronJob",
|
||||
apiVersions: ["batch/v1"],
|
||||
resolve: (cronJob: K8sApi.CronJob) => resolveStatusForCronJobs(cronJob)
|
||||
resolve: (cronJob: Renderer.K8sApi.CronJob) => resolveStatusForCronJobs(cronJob)
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@ -1,8 +1,37 @@
|
||||
import { K8sApi } from "@k8slens/extensions";
|
||||
/**
|
||||
* Copyright (c) 2021 OpenLens Authors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
export function resolveStatus(object: K8sApi.KubeObject): K8sApi.KubeObjectStatus {
|
||||
const eventStore = K8sApi.apiManager.getStore(K8sApi.eventApi);
|
||||
const events = (eventStore as K8sApi.EventStore).getEventsByObject(object);
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
|
||||
const { apiManager, eventApi, KubeObjectStatusLevel } = Renderer.K8sApi;
|
||||
|
||||
type KubeObject = Renderer.K8sApi.KubeObject;
|
||||
type Pod = Renderer.K8sApi.Pod;
|
||||
type CronJob = Renderer.K8sApi.CronJob;
|
||||
type KubeObjectStatus = Renderer.K8sApi.KubeObjectStatus;
|
||||
type EventStore = Renderer.K8sApi.EventStore;
|
||||
|
||||
export function resolveStatus(object: KubeObject): KubeObjectStatus {
|
||||
const eventStore = apiManager.getStore(eventApi);
|
||||
const events = (eventStore as EventStore).getEventsByObject(object);
|
||||
const warnings = events.filter(evt => evt.isWarning());
|
||||
|
||||
if (!events.length || !warnings.length) {
|
||||
@ -11,18 +40,18 @@ export function resolveStatus(object: K8sApi.KubeObject): K8sApi.KubeObjectStatu
|
||||
const event = [...warnings, ...events][0]; // get latest event
|
||||
|
||||
return {
|
||||
level: K8sApi.KubeObjectStatusLevel.WARNING,
|
||||
level: KubeObjectStatusLevel.WARNING,
|
||||
text: `${event.message}`,
|
||||
timestamp: event.metadata.creationTimestamp
|
||||
};
|
||||
}
|
||||
|
||||
export function resolveStatusForPods(pod: K8sApi.Pod): K8sApi.KubeObjectStatus {
|
||||
export function resolveStatusForPods(pod: Pod): KubeObjectStatus {
|
||||
if (!pod.hasIssues()) {
|
||||
return null;
|
||||
}
|
||||
const eventStore = K8sApi.apiManager.getStore(K8sApi.eventApi);
|
||||
const events = (eventStore as K8sApi.EventStore).getEventsByObject(pod);
|
||||
const eventStore = apiManager.getStore(eventApi);
|
||||
const events = (eventStore as EventStore).getEventsByObject(pod);
|
||||
const warnings = events.filter(evt => evt.isWarning());
|
||||
|
||||
if (!events.length || !warnings.length) {
|
||||
@ -31,15 +60,15 @@ export function resolveStatusForPods(pod: K8sApi.Pod): K8sApi.KubeObjectStatus {
|
||||
const event = [...warnings, ...events][0]; // get latest event
|
||||
|
||||
return {
|
||||
level: K8sApi.KubeObjectStatusLevel.WARNING,
|
||||
level: KubeObjectStatusLevel.WARNING,
|
||||
text: `${event.message}`,
|
||||
timestamp: event.metadata.creationTimestamp
|
||||
};
|
||||
}
|
||||
|
||||
export function resolveStatusForCronJobs(cronJob: K8sApi.CronJob): K8sApi.KubeObjectStatus {
|
||||
const eventStore = K8sApi.apiManager.getStore(K8sApi.eventApi);
|
||||
let events = (eventStore as K8sApi.EventStore).getEventsByObject(cronJob);
|
||||
export function resolveStatusForCronJobs(cronJob: CronJob): KubeObjectStatus {
|
||||
const eventStore = apiManager.getStore(eventApi);
|
||||
let events = (eventStore as EventStore).getEventsByObject(cronJob);
|
||||
const warnings = events.filter(evt => evt.isWarning());
|
||||
|
||||
if (cronJob.isNeverRun()) {
|
||||
@ -52,7 +81,7 @@ export function resolveStatusForCronJobs(cronJob: K8sApi.CronJob): K8sApi.KubeOb
|
||||
const event = [...warnings, ...events][0]; // get latest event
|
||||
|
||||
return {
|
||||
level: K8sApi.KubeObjectStatusLevel.WARNING,
|
||||
level: KubeObjectStatusLevel.WARNING,
|
||||
text: `${event.message}`,
|
||||
timestamp: event.metadata.creationTimestamp
|
||||
};
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"experimentalDecorators": true,
|
||||
"useDefineForClassFields": true,
|
||||
"jsx": "react"
|
||||
},
|
||||
"include": [
|
||||
|
||||
@ -1,3 +1,23 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OpenLens Authors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
const path = require("path");
|
||||
|
||||
module.exports = [
|
||||
@ -6,6 +26,9 @@ module.exports = [
|
||||
context: __dirname,
|
||||
target: "electron-renderer",
|
||||
mode: "production",
|
||||
optimization: {
|
||||
minimize: false
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
@ -19,7 +42,8 @@ module.exports = [
|
||||
{
|
||||
"@k8slens/extensions": "var global.LensExtensions",
|
||||
"react": "var global.React",
|
||||
"mobx": "var global.Mobx"
|
||||
"mobx": "var global.Mobx",
|
||||
"mobx-react": "var global.MobxReact"
|
||||
}
|
||||
],
|
||||
resolve: {
|
||||
|
||||
1741
extensions/metrics-cluster-feature/package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "lens-metrics-cluster-feature",
|
||||
"version": "0.1.0",
|
||||
"version": "0.0.1",
|
||||
"description": "Lens metrics cluster feature",
|
||||
"renderer": "dist/renderer.js",
|
||||
"lens": {
|
||||
@ -8,18 +8,21 @@
|
||||
"styles": []
|
||||
},
|
||||
"scripts": {
|
||||
"build": "webpack --config webpack.config.js",
|
||||
"dev": "npm run build --watch",
|
||||
"test": "jest --passWithNoTests --env=jsdom src $@"
|
||||
"build": "webpack && npm pack",
|
||||
"dev": "webpack --watch",
|
||||
"test": "jest --passWithNoTests --env=jsdom src $@",
|
||||
"clean": "rm -rf dist/ && rm *.tgz"
|
||||
},
|
||||
"files": [
|
||||
"dist/**/*",
|
||||
"resources/**/*"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@k8slens/extensions": "file:../../src/extensions/npm/extensions",
|
||||
"jest": "^26.6.3",
|
||||
"mobx": "^5.15.5",
|
||||
"react": "^16.13.1",
|
||||
"semver": "^7.3.2",
|
||||
"ts-loader": "^8.0.4",
|
||||
"typescript": "^4.0.3",
|
||||
"typescript": "^4.3.2",
|
||||
"webpack": "^4.44.2"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,55 +1,42 @@
|
||||
import { LensRendererExtension, Interface, Component, Catalog} from "@k8slens/extensions";
|
||||
import { MetricsFeature } from "./src/metrics-feature";
|
||||
/**
|
||||
* Copyright (c) 2021 OpenLens Authors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
export default class ClusterMetricsFeatureExtension extends LensRendererExtension {
|
||||
onActivate() {
|
||||
const category = Catalog.catalogCategories.getForGroupKind<Catalog.KubernetesClusterCategory>("entity.k8slens.dev", "KubernetesCluster");
|
||||
import React from "react";
|
||||
import { Common, Renderer } from "@k8slens/extensions";
|
||||
import { MetricsSettings } from "./src/metrics-settings";
|
||||
|
||||
if (!category) {
|
||||
return;
|
||||
}
|
||||
|
||||
category.on("contextMenuOpen", this.clusterContextMenuOpen.bind(this));
|
||||
}
|
||||
|
||||
async clusterContextMenuOpen(cluster: Catalog.KubernetesCluster, ctx: Interface.CatalogEntityContextMenuContext) {
|
||||
if (!cluster.status.active) {
|
||||
return;
|
||||
}
|
||||
|
||||
const metricsFeature = new MetricsFeature();
|
||||
|
||||
await metricsFeature.updateStatus(cluster);
|
||||
|
||||
if (metricsFeature.status.installed) {
|
||||
if (metricsFeature.status.canUpgrade) {
|
||||
ctx.menuItems.unshift({
|
||||
icon: "refresh",
|
||||
title: "Upgrade Lens Metrics stack",
|
||||
onClick: async () => {
|
||||
metricsFeature.upgrade(cluster);
|
||||
}
|
||||
});
|
||||
export default class ClusterMetricsFeatureExtension extends Renderer.LensExtension {
|
||||
entitySettings = [
|
||||
{
|
||||
apiVersions: ["entity.k8slens.dev/v1alpha1"],
|
||||
kind: "KubernetesCluster",
|
||||
title: "Lens Metrics",
|
||||
priority: 5,
|
||||
components: {
|
||||
View: ({ entity = null }: { entity: Common.Catalog.KubernetesCluster}) => {
|
||||
return (
|
||||
<MetricsSettings cluster={entity} />
|
||||
);
|
||||
}
|
||||
}
|
||||
ctx.menuItems.unshift({
|
||||
icon: "toggle_off",
|
||||
title: "Uninstall Lens Metrics stack",
|
||||
onClick: async () => {
|
||||
await metricsFeature.uninstall(cluster);
|
||||
|
||||
Component.Notifications.info(`Lens Metrics has been removed from ${cluster.metadata.name}`, { timeout: 10_000 });
|
||||
}
|
||||
});
|
||||
} else {
|
||||
ctx.menuItems.unshift({
|
||||
icon: "toggle_on",
|
||||
title: "Install Lens Metrics stack",
|
||||
onClick: async () => {
|
||||
metricsFeature.install(cluster);
|
||||
|
||||
Component.Notifications.info(`Lens Metrics is now installed to ${cluster.metadata.name}`, { timeout: 10_000 });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
@ -2,3 +2,5 @@ apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: lens-metrics
|
||||
annotations:
|
||||
extensionVersion: "{{ version }}"
|
||||
@ -1,3 +1,4 @@
|
||||
{{#if prometheus.enabled}}
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
@ -14,3 +15,4 @@ spec:
|
||||
protocol: TCP
|
||||
port: 80
|
||||
targetPort: 9090
|
||||
{{/if}}
|
||||
@ -1,3 +1,4 @@
|
||||
{{#if prometheus.enabled}}
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
@ -46,14 +47,14 @@ spec:
|
||||
serviceAccountName: prometheus
|
||||
initContainers:
|
||||
- name: chown
|
||||
image: docker.io/alpine:3.9
|
||||
image: docker.io/alpine:3.12
|
||||
command: ["chown", "-R", "65534:65534", "/var/lib/prometheus"]
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /var/lib/prometheus
|
||||
containers:
|
||||
- name: prometheus
|
||||
image: quay.io/prometheus/prometheus:v2.19.3
|
||||
image: quay.io/prometheus/prometheus:v2.27.1
|
||||
args:
|
||||
- --web.listen-address=0.0.0.0:9090
|
||||
- --config.file=/etc/prometheus/prometheus.yaml
|
||||
@ -114,3 +115,4 @@ spec:
|
||||
requests:
|
||||
storage: {{persistence.size}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
@ -41,7 +41,7 @@ spec:
|
||||
hostPID: true
|
||||
containers:
|
||||
- name: node-exporter
|
||||
image: quay.io/prometheus/node-exporter:v1.0.1
|
||||
image: quay.io/prometheus/node-exporter:v1.1.2
|
||||
args:
|
||||
- --path.procfs=/host/proc
|
||||
- --path.sysfs=/host/sys
|
||||
|
||||
@ -23,23 +23,15 @@ spec:
|
||||
operator: In
|
||||
values:
|
||||
- linux
|
||||
- key: kubernetes.io/arch
|
||||
operator: In
|
||||
values:
|
||||
- amd64
|
||||
- matchExpressions:
|
||||
- key: beta.kubernetes.io/os
|
||||
operator: In
|
||||
values:
|
||||
- linux
|
||||
- key: beta.kubernetes.io/arch
|
||||
operator: In
|
||||
values:
|
||||
- amd64
|
||||
serviceAccountName: kube-state-metrics
|
||||
containers:
|
||||
- name: kube-state-metrics
|
||||
image: quay.io/coreos/kube-state-metrics:v1.9.7
|
||||
image: k8s.gcr.io/kube-state-metrics/kube-state-metrics:v2.0.0
|
||||
ports:
|
||||
- name: metrics
|
||||
containerPort: 8080
|
||||
@ -52,7 +44,7 @@ spec:
|
||||
resources:
|
||||
requests:
|
||||
cpu: 10m
|
||||
memory: 150Mi
|
||||
memory: 32Mi
|
||||
limits:
|
||||
cpu: 200m
|
||||
memory: 150Mi
|
||||
|
||||
@ -1,9 +1,37 @@
|
||||
import { ClusterFeature, Catalog, K8sApi } from "@k8slens/extensions";
|
||||
/**
|
||||
* Copyright (c) 2021 OpenLens Authors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { Renderer, Common } from "@k8slens/extensions";
|
||||
import semver from "semver";
|
||||
import * as path from "path";
|
||||
|
||||
const { ResourceStack, forCluster, StorageClass, Namespace } = Renderer.K8sApi;
|
||||
|
||||
type ResourceStack = Renderer.K8sApi.ResourceStack;
|
||||
|
||||
export interface MetricsConfiguration {
|
||||
// Placeholder for Metrics config structure
|
||||
prometheus: {
|
||||
enabled: boolean;
|
||||
};
|
||||
persistence: {
|
||||
enabled: boolean;
|
||||
storageClass: string;
|
||||
@ -22,78 +50,72 @@ export interface MetricsConfiguration {
|
||||
alertManagers: string[];
|
||||
replicas: number;
|
||||
storageClass: string;
|
||||
version?: string;
|
||||
}
|
||||
|
||||
export class MetricsFeature extends ClusterFeature.Feature {
|
||||
name = "metrics";
|
||||
latestVersion = "v2.19.3-lens1";
|
||||
export interface MetricsStatus {
|
||||
installed: boolean;
|
||||
canUpgrade: boolean;
|
||||
}
|
||||
|
||||
templateContext: MetricsConfiguration = {
|
||||
persistence: {
|
||||
enabled: false,
|
||||
storageClass: null,
|
||||
size: "20G",
|
||||
},
|
||||
nodeExporter: {
|
||||
enabled: true,
|
||||
},
|
||||
retention: {
|
||||
time: "2d",
|
||||
size: "5GB",
|
||||
},
|
||||
kubeStateMetrics: {
|
||||
enabled: true,
|
||||
},
|
||||
alertManagers: null,
|
||||
replicas: 1,
|
||||
storageClass: null,
|
||||
};
|
||||
export class MetricsFeature {
|
||||
name = "lens-metrics";
|
||||
latestVersion = "v2.26.0-lens1";
|
||||
|
||||
async install(cluster: Catalog.KubernetesCluster): Promise<void> {
|
||||
protected stack: ResourceStack;
|
||||
|
||||
constructor(protected cluster: Common.Catalog.KubernetesCluster) {
|
||||
this.stack = new ResourceStack(cluster, this.name);
|
||||
}
|
||||
|
||||
get resourceFolder() {
|
||||
return path.join(__dirname, "../resources/");
|
||||
}
|
||||
|
||||
async install(config: MetricsConfiguration): Promise<string> {
|
||||
// Check if there are storageclasses
|
||||
const storageClassApi = K8sApi.forCluster(cluster, K8sApi.StorageClass);
|
||||
const storageClassApi = forCluster(this.cluster, StorageClass);
|
||||
const scs = await storageClassApi.list();
|
||||
|
||||
this.templateContext.persistence.enabled = scs.some(sc => (
|
||||
config.persistence.enabled = scs.some(sc => (
|
||||
sc.metadata?.annotations?.["storageclass.kubernetes.io/is-default-class"] === "true" ||
|
||||
sc.metadata?.annotations?.["storageclass.beta.kubernetes.io/is-default-class"] === "true"
|
||||
));
|
||||
|
||||
super.applyResources(cluster, path.join(__dirname, "../resources/"));
|
||||
config.version = this.latestVersion;
|
||||
|
||||
return this.stack.kubectlApplyFolder(this.resourceFolder, config, ["--prune"]);
|
||||
}
|
||||
|
||||
async upgrade(cluster: Catalog.KubernetesCluster): Promise<void> {
|
||||
return this.install(cluster);
|
||||
async upgrade(config: MetricsConfiguration): Promise<string> {
|
||||
return this.install(config);
|
||||
}
|
||||
|
||||
async updateStatus(cluster: Catalog.KubernetesCluster): Promise<ClusterFeature.FeatureStatus> {
|
||||
async getStatus(): Promise<MetricsStatus> {
|
||||
const status: MetricsStatus = { installed: false, canUpgrade: false};
|
||||
|
||||
try {
|
||||
const statefulSet = K8sApi.forCluster(cluster, K8sApi.StatefulSet);
|
||||
const prometheus = await statefulSet.get({name: "prometheus", namespace: "lens-metrics"});
|
||||
const namespaceApi = forCluster(this.cluster, Namespace);
|
||||
const namespace = await namespaceApi.get({name: "lens-metrics"});
|
||||
|
||||
if (prometheus?.kind) {
|
||||
this.status.installed = true;
|
||||
this.status.currentVersion = prometheus.spec.template.spec.containers[0].image.split(":")[1];
|
||||
this.status.canUpgrade = semver.lt(this.status.currentVersion, this.latestVersion, true);
|
||||
if (namespace?.kind) {
|
||||
const currentVersion = namespace.metadata.annotations?.extensionVersion || "0.0.0";
|
||||
|
||||
status.installed = true;
|
||||
status.canUpgrade = semver.lt(currentVersion, this.latestVersion, true);
|
||||
} else {
|
||||
this.status.installed = false;
|
||||
status.installed = false;
|
||||
}
|
||||
} catch(e) {
|
||||
if (e?.error?.code === 404) {
|
||||
this.status.installed = false;
|
||||
status.installed = false;
|
||||
}
|
||||
}
|
||||
|
||||
return this.status;
|
||||
return status;
|
||||
}
|
||||
|
||||
async uninstall(cluster: Catalog.KubernetesCluster): Promise<void> {
|
||||
const namespaceApi = K8sApi.forCluster(cluster, K8sApi.Namespace);
|
||||
const clusterRoleBindingApi = K8sApi.forCluster(cluster, K8sApi.ClusterRoleBinding);
|
||||
const clusterRoleApi = K8sApi.forCluster(cluster, K8sApi.ClusterRole);
|
||||
|
||||
await namespaceApi.delete({name: "lens-metrics"});
|
||||
await clusterRoleBindingApi.delete({name: "lens-prometheus"});
|
||||
await clusterRoleApi.delete({name: "lens-prometheus"});
|
||||
async uninstall(config: MetricsConfiguration): Promise<string> {
|
||||
return this.stack.kubectlDeleteFolder(this.resourceFolder, config);
|
||||
}
|
||||
}
|
||||
|
||||
293
extensions/metrics-cluster-feature/src/metrics-settings.tsx
Normal file
@ -0,0 +1,293 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OpenLens Authors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
import React from "react";
|
||||
import { Common, Renderer } from "@k8slens/extensions";
|
||||
import { observer } from "mobx-react";
|
||||
import { computed, observable, makeObservable } from "mobx";
|
||||
import { MetricsFeature, MetricsConfiguration } from "./metrics-feature";
|
||||
|
||||
const {
|
||||
K8sApi: {
|
||||
forCluster, StatefulSet, DaemonSet, Deployment,
|
||||
},
|
||||
Component: {
|
||||
SubTitle, FormSwitch, Switcher, Button,
|
||||
}
|
||||
} = Renderer;
|
||||
|
||||
interface Props {
|
||||
cluster: Common.Catalog.KubernetesCluster;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class MetricsSettings extends React.Component<Props> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
@observable featureStates = {
|
||||
prometheus: false,
|
||||
kubeStateMetrics: false,
|
||||
nodeExporter: false
|
||||
};
|
||||
@observable canUpgrade = false;
|
||||
@observable upgrading = false;
|
||||
@observable changed = false;
|
||||
@observable inProgress = false;
|
||||
|
||||
config: MetricsConfiguration = {
|
||||
prometheus: {
|
||||
enabled: false
|
||||
},
|
||||
persistence: {
|
||||
enabled: false,
|
||||
storageClass: null,
|
||||
size: "20G",
|
||||
},
|
||||
nodeExporter: {
|
||||
enabled: false,
|
||||
},
|
||||
retention: {
|
||||
time: "2d",
|
||||
size: "5GB",
|
||||
},
|
||||
kubeStateMetrics: {
|
||||
enabled: false,
|
||||
},
|
||||
alertManagers: null,
|
||||
replicas: 1,
|
||||
storageClass: null,
|
||||
};
|
||||
feature: MetricsFeature;
|
||||
|
||||
@computed get isTogglable() {
|
||||
if (this.inProgress) return false;
|
||||
if (!this.props.cluster.status.active) return false;
|
||||
if (this.canUpgrade) return false;
|
||||
if (!this.isActiveMetricsProvider) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
get metricsProvider() {
|
||||
return this.props.cluster.spec?.metrics?.prometheus?.type || "";
|
||||
}
|
||||
|
||||
get isActiveMetricsProvider() {
|
||||
return (!this.metricsProvider || this.metricsProvider === "lens");
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
this.feature = new MetricsFeature(this.props.cluster);
|
||||
|
||||
await this.updateFeatureStates();
|
||||
}
|
||||
|
||||
async updateFeatureStates() {
|
||||
const status = await this.feature.getStatus();
|
||||
|
||||
this.canUpgrade = status.canUpgrade;
|
||||
|
||||
if (this.canUpgrade) {
|
||||
this.changed = true;
|
||||
}
|
||||
|
||||
const statefulSet = forCluster(this.props.cluster, StatefulSet);
|
||||
|
||||
try {
|
||||
await statefulSet.get({name: "prometheus", namespace: "lens-metrics"});
|
||||
this.featureStates.prometheus = true;
|
||||
} catch(e) {
|
||||
if (e?.error?.code === 404) {
|
||||
this.featureStates.prometheus = false;
|
||||
} else {
|
||||
this.featureStates.prometheus = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
const deployment = forCluster(this.props.cluster, Deployment);
|
||||
|
||||
try {
|
||||
await deployment.get({name: "kube-state-metrics", namespace: "lens-metrics"});
|
||||
this.featureStates.kubeStateMetrics = true;
|
||||
} catch(e) {
|
||||
if (e?.error?.code === 404) {
|
||||
this.featureStates.kubeStateMetrics = false;
|
||||
} else {
|
||||
this.featureStates.kubeStateMetrics = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
const daemonSet = forCluster(this.props.cluster, DaemonSet);
|
||||
|
||||
try {
|
||||
await daemonSet.get({name: "node-exporter", namespace: "lens-metrics"});
|
||||
this.featureStates.nodeExporter = true;
|
||||
} catch(e) {
|
||||
if (e?.error?.code === 404) {
|
||||
this.featureStates.nodeExporter = false;
|
||||
} else {
|
||||
this.featureStates.nodeExporter = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async save() {
|
||||
this.config.prometheus.enabled = !!this.featureStates.prometheus;
|
||||
this.config.kubeStateMetrics.enabled = !!this.featureStates.kubeStateMetrics;
|
||||
this.config.nodeExporter.enabled = !!this.featureStates.nodeExporter;
|
||||
|
||||
this.inProgress = true;
|
||||
|
||||
try {
|
||||
if (!this.config.prometheus.enabled && !this.config.kubeStateMetrics.enabled && !this.config.nodeExporter.enabled) {
|
||||
await this.feature.uninstall(this.config);
|
||||
} else {
|
||||
await this.feature.install(this.config);
|
||||
}
|
||||
} finally {
|
||||
this.inProgress = false;
|
||||
this.changed = false;
|
||||
|
||||
await this.updateFeatureStates();
|
||||
}
|
||||
}
|
||||
|
||||
async togglePrometheus(enabled: boolean) {
|
||||
this.featureStates.prometheus = enabled;
|
||||
this.changed = true;
|
||||
}
|
||||
|
||||
async toggleKubeStateMetrics(enabled: boolean) {
|
||||
this.featureStates.kubeStateMetrics = enabled;
|
||||
this.changed = true;
|
||||
}
|
||||
|
||||
async toggleNodeExporter(enabled: boolean) {
|
||||
this.featureStates.nodeExporter = enabled;
|
||||
this.changed = true;
|
||||
}
|
||||
|
||||
@computed get buttonLabel() {
|
||||
const allDisabled = !this.featureStates.kubeStateMetrics && !this.featureStates.nodeExporter && !this.featureStates.prometheus;
|
||||
|
||||
if (this.inProgress && this.canUpgrade) return "Upgrading ...";
|
||||
if (this.inProgress && allDisabled) return "Uninstalling ...";
|
||||
if (this.inProgress) return "Applying ...";
|
||||
if (this.canUpgrade) return "Upgrade";
|
||||
|
||||
if (this.changed && allDisabled) {
|
||||
return "Uninstall";
|
||||
}
|
||||
|
||||
return "Apply";
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
{ !this.props.cluster.status.active && (
|
||||
<section>
|
||||
<p style={ {color: "var(--colorError)"} }>
|
||||
Lens Metrics settings requires established connection to the cluster.
|
||||
</p>
|
||||
</section>
|
||||
)}
|
||||
{ !this.isActiveMetricsProvider && (
|
||||
<section>
|
||||
<p style={ {color: "var(--colorError)"} }>
|
||||
Other metrics provider is currently active. See "Metrics" tab for details.
|
||||
</p>
|
||||
</section>
|
||||
)}
|
||||
<section>
|
||||
<SubTitle title="Prometheus" />
|
||||
<FormSwitch
|
||||
control={
|
||||
<Switcher
|
||||
disabled={this.featureStates.kubeStateMetrics === undefined || !this.isTogglable}
|
||||
checked={!!this.featureStates.prometheus && this.props.cluster.status.active}
|
||||
onChange={v => this.togglePrometheus(v.target.checked)}
|
||||
name="prometheus"
|
||||
/>
|
||||
}
|
||||
label="Enable bundled Prometheus metrics stack"
|
||||
/>
|
||||
<small className="hint">
|
||||
Enable timeseries data visualization (Prometheus stack) for your cluster.
|
||||
</small>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<SubTitle title="Kube State Metrics" />
|
||||
<FormSwitch
|
||||
control={
|
||||
<Switcher
|
||||
disabled={this.featureStates.kubeStateMetrics === undefined || !this.isTogglable}
|
||||
checked={!!this.featureStates.kubeStateMetrics && this.props.cluster.status.active}
|
||||
onChange={v => this.toggleKubeStateMetrics(v.target.checked)}
|
||||
name="node-exporter"
|
||||
/>
|
||||
}
|
||||
label="Enable bundled kube-state-metrics stack"
|
||||
/>
|
||||
<small className="hint">
|
||||
Enable Kubernetes API object metrics for your cluster.
|
||||
Enable this only if you don't have existing kube-state-metrics stack installed.
|
||||
</small>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<SubTitle title="Node Exporter" />
|
||||
<FormSwitch
|
||||
control={
|
||||
<Switcher
|
||||
disabled={this.featureStates.nodeExporter === undefined || !this.isTogglable}
|
||||
checked={!!this.featureStates.nodeExporter && this.props.cluster.status.active}
|
||||
onChange={v => this.toggleNodeExporter(v.target.checked)}
|
||||
name="node-exporter"
|
||||
/>
|
||||
}
|
||||
label="Enable bundled node-exporter stack"
|
||||
/>
|
||||
<small className="hint">
|
||||
Enable node level metrics for your cluster.
|
||||
Enable this only if you don't have existing node-exporter stack installed.
|
||||
</small>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<Button
|
||||
label={this.buttonLabel}
|
||||
waiting={this.inProgress}
|
||||
onClick={() => this.save()}
|
||||
primary
|
||||
disabled={!this.changed} />
|
||||
|
||||
{this.canUpgrade && (<small className="hint">
|
||||
An update is available for enabled metrics components.
|
||||
</small>)}
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -13,11 +13,12 @@
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"experimentalDecorators": true,
|
||||
"useDefineForClassFields": true,
|
||||
"jsx": "react"
|
||||
},
|
||||
"include": [
|
||||
"./*.ts",
|
||||
"./*.tsx"
|
||||
"./**/*.ts",
|
||||
"./**/*.tsx"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
|
||||
@ -1,3 +1,23 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OpenLens Authors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
const path = require("path");
|
||||
|
||||
module.exports = [
|
||||
@ -6,6 +26,9 @@ module.exports = [
|
||||
context: __dirname,
|
||||
target: "electron-renderer",
|
||||
mode: "production",
|
||||
optimization: {
|
||||
minimize: false
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
@ -19,7 +42,8 @@ module.exports = [
|
||||
{
|
||||
"@k8slens/extensions": "var global.LensExtensions",
|
||||
"react": "var global.React",
|
||||
"mobx": "var global.Mobx"
|
||||
"mobx": "var global.Mobx",
|
||||
"mobx-react": "var global.MobxReact"
|
||||
}
|
||||
],
|
||||
resolve: {
|
||||
|
||||
755
extensions/node-menu/package-lock.json
generated
@ -626,7 +626,691 @@
|
||||
},
|
||||
"@k8slens/extensions": {
|
||||
"version": "file:../../src/extensions/npm/extensions",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@material-ui/core": "*",
|
||||
"@types/node": "*",
|
||||
"@types/react-select": "*",
|
||||
"conf": "^7.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": {
|
||||
"version": "7.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz",
|
||||
"integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
}
|
||||
},
|
||||
"@emotion/hash": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
|
||||
"integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==",
|
||||
"dev": true
|
||||
},
|
||||
"@emotion/memoize": {
|
||||
"version": "0.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.5.tgz",
|
||||
"integrity": "sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@emotion/serialize": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.2.tgz",
|
||||
"integrity": "sha512-95MgNJ9+/ajxU7QIAruiOAdYNjxZX7G2mhgrtDWswA21VviYIRP1R5QilZ/bDY42xiKsaktP4egJb3QdYQZi1A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@emotion/hash": "^0.8.0",
|
||||
"@emotion/memoize": "^0.7.4",
|
||||
"@emotion/unitless": "^0.7.5",
|
||||
"@emotion/utils": "^1.0.0",
|
||||
"csstype": "^3.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"csstype": {
|
||||
"version": "3.0.8",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.8.tgz",
|
||||
"integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@emotion/unitless": {
|
||||
"version": "0.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
|
||||
"integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==",
|
||||
"dev": true
|
||||
},
|
||||
"@emotion/utils": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.0.0.tgz",
|
||||
"integrity": "sha512-mQC2b3XLDs6QCW+pDQDiyO/EdGZYOygE8s5N5rrzjSI4M3IejPE/JPndCBwRT9z982aqQNi6beWs1UeayrQxxA==",
|
||||
"dev": true
|
||||
},
|
||||
"@material-ui/core": {
|
||||
"version": "4.11.4",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.11.4.tgz",
|
||||
"integrity": "sha512-oqb+lJ2Dl9HXI9orc6/aN8ZIAMkeThufA5iZELf2LQeBn2NtjVilF5D2w7e9RpntAzDb4jK5DsVhkfOvFY/8fg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.4.4",
|
||||
"@material-ui/styles": "^4.11.4",
|
||||
"@material-ui/system": "^4.11.3",
|
||||
"@material-ui/types": "5.1.0",
|
||||
"@material-ui/utils": "^4.11.2",
|
||||
"@types/react-transition-group": "^4.2.0",
|
||||
"clsx": "^1.0.4",
|
||||
"hoist-non-react-statics": "^3.3.2",
|
||||
"popper.js": "1.16.1-lts",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-is": "^16.8.0 || ^17.0.0",
|
||||
"react-transition-group": "^4.4.0"
|
||||
}
|
||||
},
|
||||
"@material-ui/styles": {
|
||||
"version": "4.11.4",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.4.tgz",
|
||||
"integrity": "sha512-KNTIZcnj/zprG5LW0Sao7zw+yG3O35pviHzejMdcSGCdWbiO8qzRgOYL8JAxAsWBKOKYwVZxXtHWaB5T2Kvxew==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.4.4",
|
||||
"@emotion/hash": "^0.8.0",
|
||||
"@material-ui/types": "5.1.0",
|
||||
"@material-ui/utils": "^4.11.2",
|
||||
"clsx": "^1.0.4",
|
||||
"csstype": "^2.5.2",
|
||||
"hoist-non-react-statics": "^3.3.2",
|
||||
"jss": "^10.5.1",
|
||||
"jss-plugin-camel-case": "^10.5.1",
|
||||
"jss-plugin-default-unit": "^10.5.1",
|
||||
"jss-plugin-global": "^10.5.1",
|
||||
"jss-plugin-nested": "^10.5.1",
|
||||
"jss-plugin-props-sort": "^10.5.1",
|
||||
"jss-plugin-rule-value-function": "^10.5.1",
|
||||
"jss-plugin-vendor-prefixer": "^10.5.1",
|
||||
"prop-types": "^15.7.2"
|
||||
}
|
||||
},
|
||||
"@material-ui/system": {
|
||||
"version": "4.11.3",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.11.3.tgz",
|
||||
"integrity": "sha512-SY7otguNGol41Mu2Sg6KbBP1ZRFIbFLHGK81y4KYbsV2yIcaEPOmsCK6zwWlp+2yTV3J/VwT6oSBARtGIVdXPw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.4.4",
|
||||
"@material-ui/utils": "^4.11.2",
|
||||
"csstype": "^2.5.2",
|
||||
"prop-types": "^15.7.2"
|
||||
}
|
||||
},
|
||||
"@material-ui/types": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/types/-/types-5.1.0.tgz",
|
||||
"integrity": "sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A==",
|
||||
"dev": true
|
||||
},
|
||||
"@material-ui/utils": {
|
||||
"version": "4.11.2",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.2.tgz",
|
||||
"integrity": "sha512-Uul8w38u+PICe2Fg2pDKCaIG7kOyhowZ9vjiC1FsVwPABTW8vPPKfF6OvxRq3IiBaI1faOJmgdvMG7rMJARBhA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.4.4",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-is": "^16.8.0 || ^17.0.0"
|
||||
}
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "15.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-15.6.1.tgz",
|
||||
"integrity": "sha512-7EIraBEyRHEe7CH+Fm1XvgqU6uwZN8Q7jppJGcqjROMT29qhAuuOxYB1uEY5UMYQKEmA5D+5tBnhdaPXSsLONA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/prop-types": {
|
||||
"version": "15.7.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz",
|
||||
"integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/react": {
|
||||
"version": "17.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.8.tgz",
|
||||
"integrity": "sha512-3sx4c0PbXujrYAKwXxNONXUtRp9C+hE2di0IuxFyf5BELD+B+AXL8G7QrmSKhVwKZDbv0igiAjQAMhXj8Yg3aw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/prop-types": "*",
|
||||
"@types/scheduler": "*",
|
||||
"csstype": "^3.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"csstype": {
|
||||
"version": "3.0.8",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.8.tgz",
|
||||
"integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"version": "17.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.5.tgz",
|
||||
"integrity": "sha512-ikqukEhH4H9gr4iJCmQVNzTB307kROe3XFfHAOTxOXPOw7lAoEXnM5KWTkzeANGL5Ce6ABfiMl/zJBYNi7ObmQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/react-select": {
|
||||
"version": "4.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-select/-/react-select-4.0.15.tgz",
|
||||
"integrity": "sha512-GPyBFYGMVFCtF4eg9riodEco+s2mflR10Nd5csx69+bcdvX6Uo9H/jgrIqovBU9yxBppB9DS66OwD6xxgVqOYQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@emotion/serialize": "^1.0.0",
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"@types/react-transition-group": "*"
|
||||
}
|
||||
},
|
||||
"@types/react-transition-group": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.1.tgz",
|
||||
"integrity": "sha512-vIo69qKKcYoJ8wKCJjwSgCTM+z3chw3g18dkrDfVX665tMH7tmbDxEAnPdey4gTlwZz5QuHGzd+hul0OVZDqqQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/scheduler": {
|
||||
"version": "0.16.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.1.tgz",
|
||||
"integrity": "sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA==",
|
||||
"dev": true
|
||||
},
|
||||
"ajv": {
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
}
|
||||
},
|
||||
"atomically": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/atomically/-/atomically-1.7.0.tgz",
|
||||
"integrity": "sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==",
|
||||
"dev": true
|
||||
},
|
||||
"clsx": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz",
|
||||
"integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==",
|
||||
"dev": true
|
||||
},
|
||||
"conf": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/conf/-/conf-7.1.2.tgz",
|
||||
"integrity": "sha512-r8/HEoWPFn4CztjhMJaWNAe5n+gPUCSaJ0oufbqDLFKsA1V8JjAG7G+p0pgoDFAws9Bpk2VtVLLXqOBA7WxLeg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "^6.12.2",
|
||||
"atomically": "^1.3.1",
|
||||
"debounce-fn": "^4.0.0",
|
||||
"dot-prop": "^5.2.0",
|
||||
"env-paths": "^2.2.0",
|
||||
"json-schema-typed": "^7.0.3",
|
||||
"make-dir": "^3.1.0",
|
||||
"onetime": "^5.1.0",
|
||||
"pkg-up": "^3.1.0",
|
||||
"semver": "^7.3.2"
|
||||
}
|
||||
},
|
||||
"css-vendor": {
|
||||
"version": "2.0.8",
|
||||
"resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.8.tgz",
|
||||
"integrity": "sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.8.3",
|
||||
"is-in-browser": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"csstype": {
|
||||
"version": "2.6.17",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.17.tgz",
|
||||
"integrity": "sha512-u1wmTI1jJGzCJzWndZo8mk4wnPTZd1eOIYTYvuEyOQGfmDl3TrabCCfKnOC86FZwW/9djqTl933UF/cS425i9A==",
|
||||
"dev": true
|
||||
},
|
||||
"debounce-fn": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/debounce-fn/-/debounce-fn-4.0.0.tgz",
|
||||
"integrity": "sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mimic-fn": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"dom-helpers": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
|
||||
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.8.7",
|
||||
"csstype": "^3.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"csstype": {
|
||||
"version": "3.0.8",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.8.tgz",
|
||||
"integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"dot-prop": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz",
|
||||
"integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-obj": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"env-paths": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
|
||||
"integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
|
||||
"dev": true
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"dev": true
|
||||
},
|
||||
"fast-json-stable-stringify": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
|
||||
"dev": true
|
||||
},
|
||||
"find-up": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
|
||||
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"locate-path": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"hoist-non-react-statics": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
|
||||
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"react-is": "^16.7.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"hyphenate-style-name": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz",
|
||||
"integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==",
|
||||
"dev": true
|
||||
},
|
||||
"indefinite-observable": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/indefinite-observable/-/indefinite-observable-2.0.1.tgz",
|
||||
"integrity": "sha512-G8vgmork+6H9S8lUAg1gtXEj2JxIQTo0g2PbFiYOdjkziSI0F7UYBiVwhZRuixhBCNGczAls34+5HJPyZysvxQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"symbol-observable": "1.2.0"
|
||||
}
|
||||
},
|
||||
"is-in-browser": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz",
|
||||
"integrity": "sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU=",
|
||||
"dev": true
|
||||
},
|
||||
"is-obj": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
|
||||
"integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
|
||||
"dev": true
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
||||
"dev": true
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||
"dev": true
|
||||
},
|
||||
"json-schema-typed": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-7.0.3.tgz",
|
||||
"integrity": "sha512-7DE8mpG+/fVw+dTpjbxnx47TaMnDfOI1jwft9g1VybltZCduyRQPJPvc+zzKY9WPHxhPWczyFuYa6I8Mw4iU5A==",
|
||||
"dev": true
|
||||
},
|
||||
"jss": {
|
||||
"version": "10.6.0",
|
||||
"resolved": "https://registry.npmjs.org/jss/-/jss-10.6.0.tgz",
|
||||
"integrity": "sha512-n7SHdCozmxnzYGXBHe0NsO0eUf9TvsHVq2MXvi4JmTn3x5raynodDVE/9VQmBdWFyyj9HpHZ2B4xNZ7MMy7lkw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.3.1",
|
||||
"csstype": "^3.0.2",
|
||||
"indefinite-observable": "^2.0.1",
|
||||
"is-in-browser": "^1.1.3",
|
||||
"tiny-warning": "^1.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"csstype": {
|
||||
"version": "3.0.8",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.8.tgz",
|
||||
"integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"jss-plugin-camel-case": {
|
||||
"version": "10.6.0",
|
||||
"resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.6.0.tgz",
|
||||
"integrity": "sha512-JdLpA3aI/npwj3nDMKk308pvnhoSzkW3PXlbgHAzfx0yHWnPPVUjPhXFtLJzgKZge8lsfkUxvYSQ3X2OYIFU6A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.3.1",
|
||||
"hyphenate-style-name": "^1.0.3",
|
||||
"jss": "10.6.0"
|
||||
}
|
||||
},
|
||||
"jss-plugin-default-unit": {
|
||||
"version": "10.6.0",
|
||||
"resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.6.0.tgz",
|
||||
"integrity": "sha512-7y4cAScMHAxvslBK2JRK37ES9UT0YfTIXWgzUWD5euvR+JR3q+o8sQKzBw7GmkQRfZijrRJKNTiSt1PBsLI9/w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.3.1",
|
||||
"jss": "10.6.0"
|
||||
}
|
||||
},
|
||||
"jss-plugin-global": {
|
||||
"version": "10.6.0",
|
||||
"resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.6.0.tgz",
|
||||
"integrity": "sha512-I3w7ji/UXPi3VuWrTCbHG9rVCgB4yoBQLehGDTmsnDfXQb3r1l3WIdcO8JFp9m0YMmyy2CU7UOV6oPI7/Tmu+w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.3.1",
|
||||
"jss": "10.6.0"
|
||||
}
|
||||
},
|
||||
"jss-plugin-nested": {
|
||||
"version": "10.6.0",
|
||||
"resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.6.0.tgz",
|
||||
"integrity": "sha512-fOFQWgd98H89E6aJSNkEh2fAXquC9aZcAVjSw4q4RoQ9gU++emg18encR4AT4OOIFl4lQwt5nEyBBRn9V1Rk8g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.3.1",
|
||||
"jss": "10.6.0",
|
||||
"tiny-warning": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"jss-plugin-props-sort": {
|
||||
"version": "10.6.0",
|
||||
"resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.6.0.tgz",
|
||||
"integrity": "sha512-oMCe7hgho2FllNc60d9VAfdtMrZPo9n1Iu6RNa+3p9n0Bkvnv/XX5San8fTPujrTBScPqv9mOE0nWVvIaohNuw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.3.1",
|
||||
"jss": "10.6.0"
|
||||
}
|
||||
},
|
||||
"jss-plugin-rule-value-function": {
|
||||
"version": "10.6.0",
|
||||
"resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.6.0.tgz",
|
||||
"integrity": "sha512-TKFqhRTDHN1QrPTMYRlIQUOC2FFQb271+AbnetURKlGvRl/eWLswcgHQajwuxI464uZk91sPiTtdGi7r7XaWfA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.3.1",
|
||||
"jss": "10.6.0",
|
||||
"tiny-warning": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"jss-plugin-vendor-prefixer": {
|
||||
"version": "10.6.0",
|
||||
"resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.6.0.tgz",
|
||||
"integrity": "sha512-doJ7MouBXT1lypLLctCwb4nJ6lDYqrTfVS3LtXgox42Xz0gXusXIIDboeh6UwnSmox90QpVnub7au8ybrb0krQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.3.1",
|
||||
"css-vendor": "^2.0.8",
|
||||
"jss": "10.6.0"
|
||||
}
|
||||
},
|
||||
"locate-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
|
||||
"integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-locate": "^3.0.0",
|
||||
"path-exists": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"loose-envify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||
}
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"make-dir": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
|
||||
"integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"semver": "^6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"mimic-fn": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz",
|
||||
"integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==",
|
||||
"dev": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
|
||||
"dev": true
|
||||
},
|
||||
"onetime": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
|
||||
"integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mimic-fn": "^2.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"mimic-fn": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
|
||||
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"p-limit": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
|
||||
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-try": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"p-locate": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
|
||||
"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-limit": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"p-try": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
||||
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
|
||||
"dev": true
|
||||
},
|
||||
"path-exists": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
|
||||
"integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
|
||||
"dev": true
|
||||
},
|
||||
"pkg-up": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz",
|
||||
"integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"find-up": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"popper.js": {
|
||||
"version": "1.16.1-lts",
|
||||
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1-lts.tgz",
|
||||
"integrity": "sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA==",
|
||||
"dev": true
|
||||
},
|
||||
"prop-types": {
|
||||
"version": "15.7.2",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
|
||||
"integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"react-is": "^16.8.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"punycode": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
|
||||
"dev": true
|
||||
},
|
||||
"react-is": {
|
||||
"version": "17.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
||||
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
|
||||
"dev": true
|
||||
},
|
||||
"react-transition-group": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.1.tgz",
|
||||
"integrity": "sha512-Djqr7OQ2aPUiYurhPalTrVy9ddmFCCzwhqQmtN+J3+3DzLO209Fdr70QrN8Z3DsglWql6iY1lDWAfpFiBtuKGw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"dom-helpers": "^5.0.1",
|
||||
"loose-envify": "^1.4.0",
|
||||
"prop-types": "^15.6.2"
|
||||
}
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.13.7",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
|
||||
"integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==",
|
||||
"dev": true
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.3.5",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
||||
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lru-cache": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"symbol-observable": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
|
||||
"integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==",
|
||||
"dev": true
|
||||
},
|
||||
"tiny-warning": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
|
||||
"integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==",
|
||||
"dev": true
|
||||
},
|
||||
"uri-js": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@sinonjs/commons": {
|
||||
"version": "1.8.1",
|
||||
@ -2934,9 +3618,9 @@
|
||||
}
|
||||
},
|
||||
"hosted-git-info": {
|
||||
"version": "2.8.8",
|
||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
|
||||
"integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
|
||||
"version": "2.8.9",
|
||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
|
||||
"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
|
||||
"dev": true
|
||||
},
|
||||
"html-encoding-sniffer": {
|
||||
@ -4026,9 +4710,9 @@
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.20",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
||||
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.sortby": {
|
||||
@ -4037,15 +4721,6 @@
|
||||
"integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=",
|
||||
"dev": true
|
||||
},
|
||||
"loose-envify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||
}
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
|
||||
@ -4247,12 +4922,6 @@
|
||||
"minimist": "^1.2.5"
|
||||
}
|
||||
},
|
||||
"mobx": {
|
||||
"version": "5.15.7",
|
||||
"resolved": "https://registry.npmjs.org/mobx/-/mobx-5.15.7.tgz",
|
||||
"integrity": "sha512-wyM3FghTkhmC+hQjyPGGFdpehrcX1KOXsDuERhfK2YbJemkUhEB+6wzEN639T21onxlfYBmriA1PFnvxTUhcKw==",
|
||||
"dev": true
|
||||
},
|
||||
"move-concurrently": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
|
||||
@ -4793,25 +5462,6 @@
|
||||
"sisteransi": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"prop-types": {
|
||||
"version": "15.7.2",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
|
||||
"integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"react-is": "^16.8.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"prr": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
|
||||
@ -4922,17 +5572,6 @@
|
||||
"safe-buffer": "^5.1.0"
|
||||
}
|
||||
},
|
||||
"react": {
|
||||
"version": "16.14.0",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz",
|
||||
"integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"prop-types": "^15.6.2"
|
||||
}
|
||||
},
|
||||
"react-is": {
|
||||
"version": "17.0.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.1.tgz",
|
||||
@ -6175,9 +6814,9 @@
|
||||
}
|
||||
},
|
||||
"typescript": {
|
||||
"version": "4.0.5",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.5.tgz",
|
||||
"integrity": "sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==",
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.2.tgz",
|
||||
"integrity": "sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==",
|
||||
"dev": true
|
||||
},
|
||||
"union-value": {
|
||||
@ -6895,9 +7534,9 @@
|
||||
}
|
||||
},
|
||||
"ws": {
|
||||
"version": "7.4.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.0.tgz",
|
||||
"integrity": "sha512-kyFwXuV/5ymf+IXhS6f0+eAFvydbaBW3zjpT6hUdAh/hbVjTIB5EHBGi0bPoCLSK2wcuz3BrEkB9LrYv1Nm4NQ==",
|
||||
"version": "7.4.6",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
|
||||
"integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
|
||||
"dev": true
|
||||
},
|
||||
"xml-name-validator": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "lens-node-menu",
|
||||
"version": "0.1.0",
|
||||
"version": "0.0.1",
|
||||
"description": "Lens node menu",
|
||||
"renderer": "dist/renderer.js",
|
||||
"lens": {
|
||||
@ -8,18 +8,19 @@
|
||||
"styles": []
|
||||
},
|
||||
"scripts": {
|
||||
"build": "webpack --config webpack.config.js",
|
||||
"dev": "npm run build --watch",
|
||||
"build": "webpack && npm pack",
|
||||
"dev": "webpack --watch",
|
||||
"test": "jest --passWithNoTests --env=jsdom src $@"
|
||||
},
|
||||
"files": [
|
||||
"dist/**/*"
|
||||
],
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@k8slens/extensions": "file:../../src/extensions/npm/extensions",
|
||||
"jest": "^26.6.3",
|
||||
"mobx": "^5.15.5",
|
||||
"react": "^16.13.1",
|
||||
"ts-loader": "^8.0.4",
|
||||
"typescript": "^4.0.3",
|
||||
"typescript": "^4.3.2",
|
||||
"webpack": "^4.44.2"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,29 @@
|
||||
import { LensRendererExtension } from "@k8slens/extensions";
|
||||
/**
|
||||
* Copyright (c) 2021 OpenLens Authors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
import React from "react";
|
||||
import { NodeMenu, NodeMenuProps } from "./src/node-menu";
|
||||
|
||||
export default class NodeMenuRendererExtension extends LensRendererExtension {
|
||||
export default class NodeMenuRendererExtension extends Renderer.LensExtension {
|
||||
kubeObjectMenuItems = [
|
||||
{
|
||||
kind: "Node",
|
||||
|
||||
@ -1,7 +1,42 @@
|
||||
import React from "react";
|
||||
import { Component, K8sApi, Navigation} from "@k8slens/extensions";
|
||||
/**
|
||||
* Copyright (c) 2021 OpenLens Authors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
export interface NodeMenuProps extends Component.KubeObjectMenuProps<K8sApi.Node> {
|
||||
import React from "react";
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
|
||||
type Node = Renderer.K8sApi.Node;
|
||||
|
||||
const {
|
||||
Component: {
|
||||
terminalStore,
|
||||
createTerminalTab,
|
||||
ConfirmDialog,
|
||||
MenuItem,
|
||||
Icon,
|
||||
},
|
||||
Navigation
|
||||
} = Renderer;
|
||||
|
||||
|
||||
export interface NodeMenuProps extends Renderer.Component.KubeObjectMenuProps<Node> {
|
||||
}
|
||||
|
||||
export function NodeMenu(props: NodeMenuProps) {
|
||||
@ -11,7 +46,7 @@ export function NodeMenu(props: NodeMenuProps) {
|
||||
const nodeName = node.getName();
|
||||
|
||||
const sendToTerminal = (command: string) => {
|
||||
Component.terminalStore.sendCommand(command, {
|
||||
terminalStore.sendCommand(command, {
|
||||
enter: true,
|
||||
newTab: true,
|
||||
});
|
||||
@ -19,7 +54,7 @@ export function NodeMenu(props: NodeMenuProps) {
|
||||
};
|
||||
|
||||
const shell = () => {
|
||||
Component.createTerminalTab({
|
||||
createTerminalTab({
|
||||
title: `Node: ${nodeName}`,
|
||||
node: nodeName,
|
||||
});
|
||||
@ -37,7 +72,7 @@ export function NodeMenu(props: NodeMenuProps) {
|
||||
const drain = () => {
|
||||
const command = `kubectl drain ${nodeName} --delete-local-data --ignore-daemonsets --force`;
|
||||
|
||||
Component.ConfirmDialog.open({
|
||||
ConfirmDialog.open({
|
||||
ok: () => sendToTerminal(command),
|
||||
labelOk: `Drain Node`,
|
||||
message: (
|
||||
@ -50,26 +85,26 @@ export function NodeMenu(props: NodeMenuProps) {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Component.MenuItem onClick={shell}>
|
||||
<Component.Icon svg="ssh" interactive={toolbar} title="Node shell"/>
|
||||
<MenuItem onClick={shell}>
|
||||
<Icon svg="ssh" interactive={toolbar} title="Node shell"/>
|
||||
<span className="title">Shell</span>
|
||||
</Component.MenuItem>
|
||||
</MenuItem>
|
||||
{!node.isUnschedulable() && (
|
||||
<Component.MenuItem onClick={cordon}>
|
||||
<Component.Icon material="pause_circle_filled" title="Cordon" interactive={toolbar}/>
|
||||
<MenuItem onClick={cordon}>
|
||||
<Icon material="pause_circle_filled" title="Cordon" interactive={toolbar}/>
|
||||
<span className="title">Cordon</span>
|
||||
</Component.MenuItem>
|
||||
</MenuItem>
|
||||
)}
|
||||
{node.isUnschedulable() && (
|
||||
<Component.MenuItem onClick={unCordon}>
|
||||
<Component.Icon material="play_circle_filled" title="Uncordon" interactive={toolbar}/>
|
||||
<MenuItem onClick={unCordon}>
|
||||
<Icon material="play_circle_filled" title="Uncordon" interactive={toolbar}/>
|
||||
<span className="title">Uncordon</span>
|
||||
</Component.MenuItem>
|
||||
</MenuItem>
|
||||
)}
|
||||
<Component.MenuItem onClick={drain}>
|
||||
<Component.Icon material="delete_sweep" title="Drain" interactive={toolbar}/>
|
||||
<MenuItem onClick={drain}>
|
||||
<Icon material="delete_sweep" title="Drain" interactive={toolbar}/>
|
||||
<span className="title">Drain</span>
|
||||
</Component.MenuItem>
|
||||
</MenuItem>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"experimentalDecorators": true,
|
||||
"useDefineForClassFields": true,
|
||||
"jsx": "react"
|
||||
},
|
||||
"include": [
|
||||
|
||||
@ -1,3 +1,23 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OpenLens Authors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
const path = require("path");
|
||||
|
||||
module.exports = [
|
||||
@ -6,6 +26,9 @@ module.exports = [
|
||||
context: __dirname,
|
||||
target: "electron-renderer",
|
||||
mode: "production",
|
||||
optimization: {
|
||||
minimize: false
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
@ -19,7 +42,8 @@ module.exports = [
|
||||
{
|
||||
"@k8slens/extensions": "var global.LensExtensions",
|
||||
"react": "var global.React",
|
||||
"mobx": "var global.Mobx"
|
||||
"mobx": "var global.Mobx",
|
||||
"mobx-react": "var global.MobxReact"
|
||||
}
|
||||
],
|
||||
resolve: {
|
||||
|
||||
69
extensions/pod-menu/package-lock.json
generated
@ -3571,9 +3571,9 @@
|
||||
}
|
||||
},
|
||||
"hosted-git-info": {
|
||||
"version": "2.8.8",
|
||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
|
||||
"integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
|
||||
"version": "2.8.9",
|
||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
|
||||
"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
|
||||
"dev": true
|
||||
},
|
||||
"html-encoding-sniffer": {
|
||||
@ -4663,9 +4663,9 @@
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.20",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
||||
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.sortby": {
|
||||
@ -4674,15 +4674,6 @@
|
||||
"integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=",
|
||||
"dev": true
|
||||
},
|
||||
"loose-envify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||
}
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
|
||||
@ -4884,12 +4875,6 @@
|
||||
"minimist": "^1.2.5"
|
||||
}
|
||||
},
|
||||
"mobx": {
|
||||
"version": "5.15.7",
|
||||
"resolved": "https://registry.npmjs.org/mobx/-/mobx-5.15.7.tgz",
|
||||
"integrity": "sha512-wyM3FghTkhmC+hQjyPGGFdpehrcX1KOXsDuERhfK2YbJemkUhEB+6wzEN639T21onxlfYBmriA1PFnvxTUhcKw==",
|
||||
"dev": true
|
||||
},
|
||||
"move-concurrently": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
|
||||
@ -5430,25 +5415,6 @@
|
||||
"sisteransi": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"prop-types": {
|
||||
"version": "15.7.2",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
|
||||
"integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"react-is": "^16.8.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"prr": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
|
||||
@ -5559,17 +5525,6 @@
|
||||
"safe-buffer": "^5.1.0"
|
||||
}
|
||||
},
|
||||
"react": {
|
||||
"version": "16.14.0",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz",
|
||||
"integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"prop-types": "^15.6.2"
|
||||
}
|
||||
},
|
||||
"react-is": {
|
||||
"version": "17.0.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.1.tgz",
|
||||
@ -6812,9 +6767,9 @@
|
||||
}
|
||||
},
|
||||
"typescript": {
|
||||
"version": "4.0.5",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.5.tgz",
|
||||
"integrity": "sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==",
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.2.tgz",
|
||||
"integrity": "sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==",
|
||||
"dev": true
|
||||
},
|
||||
"union-value": {
|
||||
@ -7532,9 +7487,9 @@
|
||||
}
|
||||
},
|
||||
"ws": {
|
||||
"version": "7.4.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.0.tgz",
|
||||
"integrity": "sha512-kyFwXuV/5ymf+IXhS6f0+eAFvydbaBW3zjpT6hUdAh/hbVjTIB5EHBGi0bPoCLSK2wcuz3BrEkB9LrYv1Nm4NQ==",
|
||||
"version": "7.4.6",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
|
||||
"integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
|
||||
"dev": true
|
||||
},
|
||||
"xml-name-validator": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "lens-pod-menu",
|
||||
"version": "0.1.0",
|
||||
"version": "0.0.1",
|
||||
"description": "Lens pod menu",
|
||||
"renderer": "dist/renderer.js",
|
||||
"lens": {
|
||||
@ -8,18 +8,19 @@
|
||||
"styles": []
|
||||
},
|
||||
"scripts": {
|
||||
"build": "webpack --config webpack.config.js",
|
||||
"dev": "npm run build --watch",
|
||||
"build": "webpack && npm pack",
|
||||
"dev": "webpack --watch",
|
||||
"test": "jest --passWithNoTests --env=jsdom src $@"
|
||||
},
|
||||
"files": [
|
||||
"dist/**/*"
|
||||
],
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@k8slens/extensions": "file:../../src/extensions/npm/extensions",
|
||||
"jest": "^26.6.3",
|
||||
"mobx": "^5.15.5",
|
||||
"react": "^16.13.1",
|
||||
"ts-loader": "^8.0.4",
|
||||
"typescript": "^4.0.3",
|
||||
"typescript": "^4.3.2",
|
||||
"webpack": "^4.44.2"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,39 @@
|
||||
import { LensRendererExtension } from "@k8slens/extensions";
|
||||
/**
|
||||
* Copyright (c) 2021 OpenLens Authors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { Renderer } from "@k8slens/extensions";
|
||||
import { PodAttachMenu, PodAttachMenuProps } from "./src/attach-menu";
|
||||
import { PodShellMenu, PodShellMenuProps } from "./src/shell-menu";
|
||||
import { PodLogsMenu, PodLogsMenuProps } from "./src/logs-menu";
|
||||
import React from "react";
|
||||
|
||||
export default class PodMenuRendererExtension extends LensRendererExtension {
|
||||
export default class PodMenuRendererExtension extends Renderer.LensExtension {
|
||||
kubeObjectMenuItems = [
|
||||
{
|
||||
kind: "Pod",
|
||||
apiVersions: ["v1"],
|
||||
components: {
|
||||
MenuItem: (props: PodAttachMenuProps) => <PodAttachMenu {...props} />
|
||||
}
|
||||
},
|
||||
{
|
||||
kind: "Pod",
|
||||
apiVersions: ["v1"],
|
||||
|
||||
101
extensions/pod-menu/src/attach-menu.tsx
Normal file
@ -0,0 +1,101 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OpenLens Authors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
import React from "react";
|
||||
import { Renderer, Common } from "@k8slens/extensions";
|
||||
|
||||
type Pod = Renderer.K8sApi.Pod;
|
||||
|
||||
const {
|
||||
Component: {
|
||||
createTerminalTab,
|
||||
terminalStore,
|
||||
MenuItem,
|
||||
Icon,
|
||||
SubMenu,
|
||||
StatusBrick,
|
||||
},
|
||||
Navigation,
|
||||
} = Renderer;
|
||||
const {
|
||||
Util,
|
||||
} = Common;
|
||||
|
||||
export interface PodAttachMenuProps extends Renderer.Component.KubeObjectMenuProps<Pod> {
|
||||
}
|
||||
|
||||
export class PodAttachMenu extends React.Component<PodAttachMenuProps> {
|
||||
async attachToPod(container?: string) {
|
||||
const { object: pod } = this.props;
|
||||
const containerParam = container ? `-c ${container}` : "";
|
||||
let command = `kubectl attach -i -t -n ${pod.getNs()} ${pod.getName()} ${containerParam}`;
|
||||
|
||||
if (window.navigator.platform !== "Win32") {
|
||||
command = `exec ${command}`;
|
||||
}
|
||||
|
||||
const shell = createTerminalTab({
|
||||
title: `Pod: ${pod.getName()} (namespace: ${pod.getNs()}) [Attached]`
|
||||
});
|
||||
|
||||
terminalStore.sendCommand(command, {
|
||||
enter: true,
|
||||
tabId: shell.id
|
||||
});
|
||||
|
||||
Navigation.hideDetails();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { object, toolbar } = this.props;
|
||||
const containers = object.getRunningContainers();
|
||||
|
||||
if (!containers.length) return null;
|
||||
|
||||
return (
|
||||
<MenuItem onClick={Util.prevDefault(() => this.attachToPod(containers[0].name))}>
|
||||
<Icon material="pageview" interactive={toolbar} title="Attach to Pod"/>
|
||||
<span className="title">Attach Pod</span>
|
||||
{containers.length > 1 && (
|
||||
<>
|
||||
<Icon className="arrow" material="keyboard_arrow_right"/>
|
||||
<SubMenu>
|
||||
{
|
||||
containers.map(container => {
|
||||
const { name } = container;
|
||||
|
||||
return (
|
||||
<MenuItem key={name} onClick={Util.prevDefault(() => this.attachToPod(name))} className="flex align-center">
|
||||
<StatusBrick/>
|
||||
<span>{name}</span>
|
||||
</MenuItem>
|
||||
);
|
||||
})
|
||||
}
|
||||
</SubMenu>
|
||||
</>
|
||||
)}
|
||||
</MenuItem>
|
||||
);
|
||||
}
|
||||
}
|
||||