mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Merge branch 'master' into add-envFrom-secretRef-to-IPodContainer
This commit is contained in:
commit
4f489fbb97
2
Makefile
2
Makefile
@ -12,7 +12,7 @@ endif
|
|||||||
binaries/client:
|
binaries/client:
|
||||||
yarn download-bins
|
yarn download-bins
|
||||||
|
|
||||||
node_modules:
|
node_modules: yarn.lock
|
||||||
yarn install --frozen-lockfile
|
yarn install --frozen-lockfile
|
||||||
yarn check --verify-tree --integrity
|
yarn check --verify-tree --integrity
|
||||||
|
|
||||||
|
|||||||
656
extensions/pod-menu/package-lock.json
generated
656
extensions/pod-menu/package-lock.json
generated
@ -626,7 +626,644 @@
|
|||||||
},
|
},
|
||||||
"@k8slens/extensions": {
|
"@k8slens/extensions": {
|
||||||
"version": "file:../../src/extensions/npm/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.12.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz",
|
||||||
|
"integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==",
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
"@material-ui/core": {
|
||||||
|
"version": "4.11.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.11.2.tgz",
|
||||||
|
"integrity": "sha512-/D1+AQQeYX/WhT/FUk78UCRj8ch/RCglsQLYujYTIqPSJlwZHKcvHidNeVhODXeApojeXjkl0tWdk5C9ofwOkQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.4.4",
|
||||||
|
"@material-ui/styles": "^4.11.2",
|
||||||
|
"@material-ui/system": "^4.11.2",
|
||||||
|
"@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.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.2.tgz",
|
||||||
|
"integrity": "sha512-xbItf8zkfD3FuGoD9f2vlcyPf9jTEtj9YTJoNNV+NMWaSAHXgrW6geqRoo/IwBuMjqpwqsZhct13e2nUyU9Ljw==",
|
||||||
|
"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.0.3",
|
||||||
|
"jss-plugin-camel-case": "^10.0.3",
|
||||||
|
"jss-plugin-default-unit": "^10.0.3",
|
||||||
|
"jss-plugin-global": "^10.0.3",
|
||||||
|
"jss-plugin-nested": "^10.0.3",
|
||||||
|
"jss-plugin-props-sort": "^10.0.3",
|
||||||
|
"jss-plugin-rule-value-function": "^10.0.3",
|
||||||
|
"jss-plugin-vendor-prefixer": "^10.0.3",
|
||||||
|
"prop-types": "^15.7.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@material-ui/system": {
|
||||||
|
"version": "4.11.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.11.2.tgz",
|
||||||
|
"integrity": "sha512-BELFJEel5E+5DMiZb6XXT3peWRn6UixRvBtKwSxqntmD0+zwbbfCij6jtGwwdJhN1qX/aXrKu10zX31GBaeR7A==",
|
||||||
|
"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": "14.14.21",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.21.tgz",
|
||||||
|
"integrity": "sha512-cHYfKsnwllYhjOzuC5q1VpguABBeecUp24yFluHpn/BQaVxB1CuQ1FSRZCzrPxrkIfWISXV2LbeoBthLWg0+0A==",
|
||||||
|
"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.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.0.tgz",
|
||||||
|
"integrity": "sha512-aj/L7RIMsRlWML3YB6KZiXB3fV2t41+5RBGYF8z+tAKU43Px8C3cYUZsDvf1/+Bm4FK21QWBrDutu8ZJ/70qOw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/prop-types": "*",
|
||||||
|
"csstype": "^3.0.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"csstype": {
|
||||||
|
"version": "3.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.6.tgz",
|
||||||
|
"integrity": "sha512-+ZAmfyWMT7TiIlzdqJgjMb7S4f1beorDbWbsocyK4RaiqA5RTX3K14bnBWmmA9QEM0gRdsjyyrEmcyga8Zsxmw==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"version": "17.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.0.tgz",
|
||||||
|
"integrity": "sha512-lUqY7OlkF/RbNtD5nIq7ot8NquXrdFrjSOR6+w9a9RFQevGi1oZO1dcJbXMeONAPKtZ2UrZOEJ5UOCVsxbLk/g==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/react": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/react-select": {
|
||||||
|
"version": "3.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-select/-/react-select-3.1.2.tgz",
|
||||||
|
"integrity": "sha512-ygvR/2FL87R2OLObEWFootYzkvm67LRA+URYEAcBuvKk7IXmdsnIwSGm60cVXGaqkJQHozb2Cy1t94tCYb6rJA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"@types/react-transition-group": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/react-transition-group": {
|
||||||
|
"version": "4.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.0.tgz",
|
||||||
|
"integrity": "sha512-/QfLHGpu+2fQOqQaXh8MG9q03bFENooTb/it4jr5kKaZlDQfWvjqWZg48AwzPVMBHlRuTRAY7hRHCEOXz5kV6w==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/react": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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.14",
|
||||||
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.14.tgz",
|
||||||
|
"integrity": "sha512-2mSc+VEpGPblzAxyeR+vZhJKgYg0Og0nnRi7pmRXFYYxSfnOnW8A5wwQb4n4cE2nIOzqKOAzLCaEX6aBmNEv8A==",
|
||||||
|
"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.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.0.tgz",
|
||||||
|
"integrity": "sha512-Ru5o9+V8CpunKnz5LGgWXkmrH/20cGKwcHwS4m73zIvs54CN9epEmT/HLqFJW3kXpakAFkEdzgy1hzlJe3E4OQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.8.7",
|
||||||
|
"csstype": "^3.0.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"csstype": {
|
||||||
|
"version": "3.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.6.tgz",
|
||||||
|
"integrity": "sha512-+ZAmfyWMT7TiIlzdqJgjMb7S4f1beorDbWbsocyK4RaiqA5RTX3K14bnBWmmA9QEM0gRdsjyyrEmcyga8Zsxmw==",
|
||||||
|
"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.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==",
|
||||||
|
"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.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jss/-/jss-10.5.0.tgz",
|
||||||
|
"integrity": "sha512-B6151NvG+thUg3murLNHRPLxTLwQ13ep4SH5brj4d8qKtogOx/jupnpfkPGSHPqvcwKJaCLctpj2lEk+5yGwMw==",
|
||||||
|
"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.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.6.tgz",
|
||||||
|
"integrity": "sha512-+ZAmfyWMT7TiIlzdqJgjMb7S4f1beorDbWbsocyK4RaiqA5RTX3K14bnBWmmA9QEM0gRdsjyyrEmcyga8Zsxmw==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"jss-plugin-camel-case": {
|
||||||
|
"version": "10.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.5.0.tgz",
|
||||||
|
"integrity": "sha512-GSjPL0adGAkuoqeYiXTgO7PlIrmjv5v8lA6TTBdfxbNYpxADOdGKJgIEkffhlyuIZHlPuuiFYTwUreLUmSn7rg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.3.1",
|
||||||
|
"hyphenate-style-name": "^1.0.3",
|
||||||
|
"jss": "10.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"jss-plugin-default-unit": {
|
||||||
|
"version": "10.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.5.0.tgz",
|
||||||
|
"integrity": "sha512-rsbTtZGCMrbcb9beiDd+TwL991NGmsAgVYH0hATrYJtue9e+LH/Gn4yFD1ENwE+3JzF3A+rPnM2JuD9L/SIIWw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.3.1",
|
||||||
|
"jss": "10.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"jss-plugin-global": {
|
||||||
|
"version": "10.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.5.0.tgz",
|
||||||
|
"integrity": "sha512-FZd9+JE/3D7HMefEG54fEC0XiQ9rhGtDHAT/ols24y8sKQ1D5KIw6OyXEmIdKFmACgxZV2ARQ5pAUypxkk2IFQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.3.1",
|
||||||
|
"jss": "10.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"jss-plugin-nested": {
|
||||||
|
"version": "10.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.5.0.tgz",
|
||||||
|
"integrity": "sha512-ejPlCLNlEGgx8jmMiDk/zarsCZk+DV0YqXfddpgzbO9Toamo0HweCFuwJ3ZO40UFOfqKwfpKMVH/3HUXgxkTMg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.3.1",
|
||||||
|
"jss": "10.5.0",
|
||||||
|
"tiny-warning": "^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"jss-plugin-props-sort": {
|
||||||
|
"version": "10.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.5.0.tgz",
|
||||||
|
"integrity": "sha512-kTLRvrOetFKz5vM88FAhLNeJIxfjhCepnvq65G7xsAQ/Wgy7HwO1BS/2wE5mx8iLaAWC6Rj5h16mhMk9sKdZxg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.3.1",
|
||||||
|
"jss": "10.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"jss-plugin-rule-value-function": {
|
||||||
|
"version": "10.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.5.0.tgz",
|
||||||
|
"integrity": "sha512-jXINGr8BSsB13JVuK274oEtk0LoooYSJqTBCGeBu2cG/VJ3+4FPs1gwLgsq24xTgKshtZ+WEQMVL34OprLidRA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.3.1",
|
||||||
|
"jss": "10.5.0",
|
||||||
|
"tiny-warning": "^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"jss-plugin-vendor-prefixer": {
|
||||||
|
"version": "10.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.5.0.tgz",
|
||||||
|
"integrity": "sha512-rux3gmfwDdOKCLDx0IQjTwTm03IfBa+Rm/hs747cOw5Q7O3RaTUIMPKjtVfc31Xr/XI9Abz2XEupk1/oMQ7zRA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.3.1",
|
||||||
|
"css-vendor": "^2.0.8",
|
||||||
|
"jss": "10.5.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.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.1.tgz",
|
||||||
|
"integrity": "sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA==",
|
||||||
|
"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.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
|
||||||
|
"integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==",
|
||||||
|
"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": {
|
"@sinonjs/commons": {
|
||||||
"version": "1.8.1",
|
"version": "1.8.1",
|
||||||
@ -2796,7 +3433,8 @@
|
|||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz",
|
||||||
"integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=",
|
"integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"har-schema": {
|
"har-schema": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
@ -3226,6 +3864,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
|
||||||
"integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
|
"integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"is-docker": "^2.0.0"
|
"is-docker": "^2.0.0"
|
||||||
}
|
}
|
||||||
@ -4382,6 +5021,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-8.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-8.0.1.tgz",
|
||||||
"integrity": "sha512-BvEXF+UmsnAfYfoapKM9nGxnP+Wn7P91YfXmrKnfcYCx6VBeoN5Ez5Ogck6I8Bi5k4RlpqRYaw75pAwzX9OphA==",
|
"integrity": "sha512-BvEXF+UmsnAfYfoapKM9nGxnP+Wn7P91YfXmrKnfcYCx6VBeoN5Ez5Ogck6I8Bi5k4RlpqRYaw75pAwzX9OphA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"growly": "^1.3.0",
|
"growly": "^1.3.0",
|
||||||
"is-wsl": "^2.2.0",
|
"is-wsl": "^2.2.0",
|
||||||
@ -4396,6 +5036,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"yallist": "^4.0.0"
|
"yallist": "^4.0.0"
|
||||||
}
|
}
|
||||||
@ -4405,6 +5046,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
|
||||||
"integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==",
|
"integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"lru-cache": "^6.0.0"
|
"lru-cache": "^6.0.0"
|
||||||
}
|
}
|
||||||
@ -4414,6 +5056,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"isexe": "^2.0.0"
|
"isexe": "^2.0.0"
|
||||||
}
|
}
|
||||||
@ -4422,7 +5065,8 @@
|
|||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -5438,7 +6082,8 @@
|
|||||||
"version": "0.1.1",
|
"version": "0.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz",
|
||||||
"integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==",
|
"integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"signal-exit": {
|
"signal-exit": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
@ -6315,7 +6960,8 @@
|
|||||||
"version": "8.3.1",
|
"version": "8.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz",
|
||||||
"integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==",
|
"integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"v8-to-istanbul": {
|
"v8-to-istanbul": {
|
||||||
"version": "7.0.0",
|
"version": "7.0.0",
|
||||||
|
|||||||
@ -9,13 +9,9 @@ export class PodLogsMenu extends React.Component<PodLogsMenuProps> {
|
|||||||
Navigation.hideDetails();
|
Navigation.hideDetails();
|
||||||
const pod = this.props.object;
|
const pod = this.props.object;
|
||||||
|
|
||||||
Component.createPodLogsTab({
|
Component.logTabStore.createPodTab({
|
||||||
pod,
|
selectedPod: pod,
|
||||||
containers: pod.getContainers(),
|
|
||||||
initContainers: pod.getInitContainers(),
|
|
||||||
selectedContainer: container,
|
selectedContainer: container,
|
||||||
showTimestamps: false,
|
|
||||||
previous: false,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,10 +6,10 @@
|
|||||||
*/
|
*/
|
||||||
import { Application } from "spectron";
|
import { Application } from "spectron";
|
||||||
import * as utils from "../helpers/utils";
|
import * as utils from "../helpers/utils";
|
||||||
import { spawnSync, exec } from "child_process";
|
import { spawnSync } from "child_process";
|
||||||
import * as util from "util";
|
import { listHelmRepositories } from "../helpers/utils";
|
||||||
|
import { fail } from "assert";
|
||||||
|
|
||||||
export const promiseExec = util.promisify(exec);
|
|
||||||
|
|
||||||
jest.setTimeout(60000);
|
jest.setTimeout(60000);
|
||||||
|
|
||||||
@ -96,8 +96,11 @@ describe("Lens integration tests", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("ensures helm repos", async () => {
|
it("ensures helm repos", async () => {
|
||||||
const { stdout: reposJson } = await promiseExec("helm repo list -o json");
|
const repos = await listHelmRepositories();
|
||||||
const repos = JSON.parse(reposJson);
|
|
||||||
|
if (!repos[0]) {
|
||||||
|
fail("Lens failed to add Bitnami repository");
|
||||||
|
}
|
||||||
|
|
||||||
await app.client.waitUntilTextExists("div.repos #message-bitnami", repos[0].name); // wait for the helm-cli to fetch the repo(s)
|
await app.client.waitUntilTextExists("div.repos #message-bitnami", repos[0].name); // wait for the helm-cli to fetch the repo(s)
|
||||||
await app.client.click("#HelmRepoSelect"); // click the repo select to activate the drop-down
|
await app.client.click("#HelmRepoSelect"); // click the repo select to activate the drop-down
|
||||||
@ -505,19 +508,35 @@ describe("Lens integration tests", () => {
|
|||||||
await app.client.click(".sidebar-nav [data-test-id='workloads'] span.link-text");
|
await app.client.click(".sidebar-nav [data-test-id='workloads'] span.link-text");
|
||||||
await app.client.waitUntilTextExists('a[href^="/pods"]', "Pods");
|
await app.client.waitUntilTextExists('a[href^="/pods"]', "Pods");
|
||||||
await app.client.click('a[href^="/pods"]');
|
await app.client.click('a[href^="/pods"]');
|
||||||
|
await app.client.click(".NamespaceSelect");
|
||||||
|
await app.client.keys("kube-system");
|
||||||
|
await app.client.keys("Enter");// "\uE007"
|
||||||
await app.client.waitUntilTextExists("div.TableCell", "kube-apiserver");
|
await app.client.waitUntilTextExists("div.TableCell", "kube-apiserver");
|
||||||
|
let podMenuItemEnabled = false;
|
||||||
|
|
||||||
|
// Wait until extensions are enabled on renderer
|
||||||
|
while (!podMenuItemEnabled) {
|
||||||
|
const logs = await app.client.getRenderProcessLogs();
|
||||||
|
|
||||||
|
podMenuItemEnabled = !!logs.find(entry => entry.message.includes("[EXTENSION]: enabled lens-pod-menu@"));
|
||||||
|
|
||||||
|
if (!podMenuItemEnabled) {
|
||||||
|
await new Promise(r => setTimeout(r, 1000));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await new Promise(r => setTimeout(r, 500)); // Give some extra time to prepare extensions
|
||||||
// Open logs tab in dock
|
// Open logs tab in dock
|
||||||
await app.client.click(".list .TableRow:first-child");
|
await app.client.click(".list .TableRow:first-child");
|
||||||
await app.client.waitForVisible(".Drawer");
|
await app.client.waitForVisible(".Drawer");
|
||||||
await app.client.click(".drawer-title .Menu li:nth-child(2)");
|
await app.client.click(".drawer-title .Menu li:nth-child(2)");
|
||||||
// Check if controls are available
|
// Check if controls are available
|
||||||
await app.client.waitForVisible(".Logs .VirtualList");
|
await app.client.waitForVisible(".LogList .VirtualList");
|
||||||
await app.client.waitForVisible(".LogResourceSelector");
|
await app.client.waitForVisible(".LogResourceSelector");
|
||||||
await app.client.waitForVisible(".LogResourceSelector .SearchInput");
|
//await app.client.waitForVisible(".LogSearch .SearchInput");
|
||||||
await app.client.waitForVisible(".LogResourceSelector .SearchInput input");
|
await app.client.waitForVisible(".LogSearch .SearchInput input");
|
||||||
// Search for semicolon
|
// Search for semicolon
|
||||||
await app.client.keys(":");
|
await app.client.keys(":");
|
||||||
await app.client.waitForVisible(".Logs .list span.active");
|
await app.client.waitForVisible(".LogList .list span.active");
|
||||||
// Click through controls
|
// Click through controls
|
||||||
await app.client.click(".LogControls .show-timestamps");
|
await app.client.click(".LogControls .show-timestamps");
|
||||||
await app.client.click(".LogControls .show-previous");
|
await app.client.click(".LogControls .show-previous");
|
||||||
@ -556,7 +575,10 @@ describe("Lens integration tests", () => {
|
|||||||
await app.client.click(".sidebar-nav [data-test-id='workloads'] span.link-text");
|
await app.client.click(".sidebar-nav [data-test-id='workloads'] span.link-text");
|
||||||
await app.client.waitUntilTextExists('a[href^="/pods"]', "Pods");
|
await app.client.waitUntilTextExists('a[href^="/pods"]', "Pods");
|
||||||
await app.client.click('a[href^="/pods"]');
|
await app.client.click('a[href^="/pods"]');
|
||||||
await app.client.waitUntilTextExists("div.TableCell", "kube-apiserver");
|
|
||||||
|
await app.client.click(".NamespaceSelect");
|
||||||
|
await app.client.keys(TEST_NAMESPACE);
|
||||||
|
await app.client.keys("Enter");// "\uE007"
|
||||||
await app.client.click(".Icon.new-dock-tab");
|
await app.client.click(".Icon.new-dock-tab");
|
||||||
await app.client.waitUntilTextExists("li.MenuItem.create-resource-tab", "Create resource");
|
await app.client.waitUntilTextExists("li.MenuItem.create-resource-tab", "Create resource");
|
||||||
await app.client.click("li.MenuItem.create-resource-tab");
|
await app.client.click("li.MenuItem.create-resource-tab");
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
import { Application } from "spectron";
|
import { Application } from "spectron";
|
||||||
|
import * as util from "util";
|
||||||
|
import { exec } from "child_process";
|
||||||
|
|
||||||
const AppPaths: Partial<Record<NodeJS.Platform, string>> = {
|
const AppPaths: Partial<Record<NodeJS.Platform, string>> = {
|
||||||
"win32": "./dist/win-unpacked/Lens.exe",
|
"win32": "./dist/win-unpacked/Lens.exe",
|
||||||
@ -26,7 +28,12 @@ export function setup(): Application {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type HelmRepository = {
|
||||||
|
name: string;
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
type AsyncPidGetter = () => Promise<number>;
|
type AsyncPidGetter = () => Promise<number>;
|
||||||
|
export const promiseExec = util.promisify(exec);
|
||||||
|
|
||||||
export async function tearDown(app: Application) {
|
export async function tearDown(app: Application) {
|
||||||
const pid = await (app.mainProcess.pid as any as AsyncPidGetter)();
|
const pid = await (app.mainProcess.pid as any as AsyncPidGetter)();
|
||||||
@ -39,3 +46,19 @@ export async function tearDown(app: Application) {
|
|||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function listHelmRepositories(retries = 0): Promise<HelmRepository[]>{
|
||||||
|
if (retries < 5) {
|
||||||
|
try {
|
||||||
|
const { stdout: reposJson } = await promiseExec("helm repo list -o json");
|
||||||
|
|
||||||
|
return JSON.parse(reposJson);
|
||||||
|
} catch {
|
||||||
|
await new Promise(r => setTimeout(r, 2000)); // if no repositories, wait for Lens adding bitnami repository
|
||||||
|
|
||||||
|
return await listHelmRepositories((retries + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
"name": "kontena-lens",
|
"name": "kontena-lens",
|
||||||
"productName": "Lens",
|
"productName": "Lens",
|
||||||
"description": "Lens - The Kubernetes IDE",
|
"description": "Lens - The Kubernetes IDE",
|
||||||
"version": "4.1.0-alpha.0",
|
"version": "4.1.0-alpha.1",
|
||||||
"main": "static/build/main.js",
|
"main": "static/build/main.js",
|
||||||
"copyright": "© 2020, Mirantis, Inc.",
|
"copyright": "© 2020, Mirantis, Inc.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -42,7 +42,7 @@
|
|||||||
"typedocs-extensions-api": "yarn run typedoc --ignoreCompilerErrors --readme docs/extensions/typedoc-readme.md.tpl --name @k8slens/extensions --out docs/extensions/api --mode library --excludePrivate --hideBreadcrumbs --includes src/ src/extensions/extension-api.ts"
|
"typedocs-extensions-api": "yarn run typedoc --ignoreCompilerErrors --readme docs/extensions/typedoc-readme.md.tpl --name @k8slens/extensions --out docs/extensions/api --mode library --excludePrivate --hideBreadcrumbs --includes src/ src/extensions/extension-api.ts"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"bundledKubectlVersion": "1.17.15",
|
"bundledKubectlVersion": "1.18.15",
|
||||||
"bundledHelmVersion": "3.4.2"
|
"bundledHelmVersion": "3.4.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -328,6 +328,7 @@
|
|||||||
"react-refresh": "^0.9.0",
|
"react-refresh": "^0.9.0",
|
||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
"react-select": "^3.1.0",
|
"react-select": "^3.1.0",
|
||||||
|
"react-select-event": "^5.1.0",
|
||||||
"react-window": "^1.8.5",
|
"react-window": "^1.8.5",
|
||||||
"sass-loader": "^8.0.2",
|
"sass-loader": "^8.0.2",
|
||||||
"sharp": "^0.26.1",
|
"sharp": "^0.26.1",
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { action, computed, observable } from "mobx";
|
import { action, computed, observable,reaction } from "mobx";
|
||||||
|
import { dockStore } from "../renderer/components/dock/dock.store";
|
||||||
import { autobind } from "../renderer/utils";
|
import { autobind } from "../renderer/utils";
|
||||||
|
|
||||||
export class SearchStore {
|
export class SearchStore {
|
||||||
@ -6,6 +7,12 @@ export class SearchStore {
|
|||||||
@observable occurrences: number[] = []; // Array with line numbers, eg [0, 0, 10, 21, 21, 40...]
|
@observable occurrences: number[] = []; // Array with line numbers, eg [0, 0, 10, 21, 21, 40...]
|
||||||
@observable activeOverlayIndex = -1; // Index withing the occurences array. Showing where is activeOverlay currently located
|
@observable activeOverlayIndex = -1; // Index withing the occurences array. Showing where is activeOverlay currently located
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
reaction(() => dockStore.selectedTabId, () => {
|
||||||
|
searchStore.reset();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets default activeOverlayIndex
|
* Sets default activeOverlayIndex
|
||||||
* @param text An array of any textual data (logs, for example)
|
* @param text An array of any textual data (logs, for example)
|
||||||
|
|||||||
@ -38,4 +38,4 @@ export * from "../../renderer/components/+events/kube-event-details";
|
|||||||
// specific exports
|
// specific exports
|
||||||
export * from "../../renderer/components/status-brick";
|
export * from "../../renderer/components/status-brick";
|
||||||
export { terminalStore, createTerminalTab } from "../../renderer/components/dock/terminal.store";
|
export { terminalStore, createTerminalTab } from "../../renderer/components/dock/terminal.store";
|
||||||
export { createPodLogsTab } from "../../renderer/components/dock/log.store";
|
export { logTabStore } from "../../renderer/components/dock/log-tab.store";
|
||||||
|
|||||||
@ -23,10 +23,10 @@ const kubectlMap: Map<string, string> = new Map([
|
|||||||
["1.14", "1.14.10"],
|
["1.14", "1.14.10"],
|
||||||
["1.15", "1.15.11"],
|
["1.15", "1.15.11"],
|
||||||
["1.16", "1.16.15"],
|
["1.16", "1.16.15"],
|
||||||
["1.17", bundledVersion],
|
["1.17", "1.17.17"],
|
||||||
["1.18", "1.18.14"],
|
["1.18", bundledVersion],
|
||||||
["1.19", "1.19.5"],
|
["1.19", "1.19.7"],
|
||||||
["1.20", "1.20.0"]
|
["1.20", "1.20.2"]
|
||||||
]);
|
]);
|
||||||
const packageMirrors: Map<string, string> = new Map([
|
const packageMirrors: Map<string, string> = new Map([
|
||||||
["default", "https://storage.googleapis.com/kubernetes-release/release"],
|
["default", "https://storage.googleapis.com/kubernetes-release/release"],
|
||||||
|
|||||||
@ -21,7 +21,7 @@ export interface KubeJsonApiData extends JsonApiData {
|
|||||||
resourceVersion: string;
|
resourceVersion: string;
|
||||||
continue?: string;
|
continue?: string;
|
||||||
finalizers?: string[];
|
finalizers?: string[];
|
||||||
selfLink: string;
|
selfLink?: string;
|
||||||
labels?: {
|
labels?: {
|
||||||
[label: string]: string;
|
[label: string]: string;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -11,8 +11,11 @@ import { navigation } from "../../navigation";
|
|||||||
import { ItemListLayout } from "../item-object-list/item-list-layout";
|
import { ItemListLayout } from "../item-object-list/item-list-layout";
|
||||||
import { SearchInputUrl } from "../input";
|
import { SearchInputUrl } from "../input";
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
|
description = "description",
|
||||||
|
version = "version",
|
||||||
|
appVersion = "app-version",
|
||||||
repo = "repo",
|
repo = "repo",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,13 +56,15 @@ export class HelmCharts extends Component<Props> {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ItemListLayout
|
<ItemListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="helm_charts"
|
||||||
className="HelmCharts"
|
className="HelmCharts"
|
||||||
store={helmChartStore}
|
store={helmChartStore}
|
||||||
isClusterScoped={true}
|
isClusterScoped={true}
|
||||||
isSelectable={false}
|
isSelectable={false}
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.name]: (chart: HelmChart) => chart.getName(),
|
[columnId.name]: (chart: HelmChart) => chart.getName(),
|
||||||
[sortBy.repo]: (chart: HelmChart) => chart.getRepository(),
|
[columnId.repo]: (chart: HelmChart) => chart.getRepository(),
|
||||||
}}
|
}}
|
||||||
searchFilters={[
|
searchFilters={[
|
||||||
(chart: HelmChart) => chart.getName(),
|
(chart: HelmChart) => chart.getName(),
|
||||||
@ -74,13 +79,12 @@ export class HelmCharts extends Component<Props> {
|
|||||||
<SearchInputUrl placeholder={`Search Helm Charts`} />
|
<SearchInputUrl placeholder={`Search Helm Charts`} />
|
||||||
)}
|
)}
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ className: "icon" },
|
{ className: "icon", showWithColumn: columnId.name },
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||||
{ title: "Description", className: "description" },
|
{ title: "Description", className: "description", id: columnId.description },
|
||||||
{ title: "Version", className: "version" },
|
{ title: "Version", className: "version", id: columnId.version },
|
||||||
{ title: "App Version", className: "app-version" },
|
{ title: "App Version", className: "app-version", id: columnId.appVersion },
|
||||||
{ title: "Repository", className: "repository", sortBy: sortBy.repo },
|
{ title: "Repository", className: "repository", sortBy: columnId.repo, id: columnId.repo },
|
||||||
|
|
||||||
]}
|
]}
|
||||||
renderTableContents={(chart: HelmChart) => [
|
renderTableContents={(chart: HelmChart) => [
|
||||||
<figure key="image">
|
<figure key="image">
|
||||||
@ -93,7 +97,8 @@ export class HelmCharts extends Component<Props> {
|
|||||||
chart.getDescription(),
|
chart.getDescription(),
|
||||||
chart.getVersion(),
|
chart.getVersion(),
|
||||||
chart.getAppVersion(),
|
chart.getAppVersion(),
|
||||||
{ title: chart.getRepository(), className: chart.getRepository().toLowerCase() }
|
{ title: chart.getRepository(), className: chart.getRepository().toLowerCase() },
|
||||||
|
{ className: "menu" }
|
||||||
]}
|
]}
|
||||||
detailsItem={this.selectedChart}
|
detailsItem={this.selectedChart}
|
||||||
onDetails={this.showDetails}
|
onDetails={this.showDetails}
|
||||||
|
|||||||
@ -14,11 +14,13 @@ import { ItemListLayout } from "../item-object-list/item-list-layout";
|
|||||||
import { HelmReleaseMenu } from "./release-menu";
|
import { HelmReleaseMenu } from "./release-menu";
|
||||||
import { secretsStore } from "../+config-secrets/secrets.store";
|
import { secretsStore } from "../+config-secrets/secrets.store";
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
namespace = "namespace",
|
namespace = "namespace",
|
||||||
revision = "revision",
|
revision = "revision",
|
||||||
chart = "chart",
|
chart = "chart",
|
||||||
|
version = "version",
|
||||||
|
appVersion = "app-version",
|
||||||
status = "status",
|
status = "status",
|
||||||
updated = "update"
|
updated = "update"
|
||||||
}
|
}
|
||||||
@ -81,16 +83,18 @@ export class HelmReleases extends Component<Props> {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ItemListLayout
|
<ItemListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="helm_releases"
|
||||||
className="HelmReleases"
|
className="HelmReleases"
|
||||||
store={releaseStore}
|
store={releaseStore}
|
||||||
dependentStores={[secretsStore]}
|
dependentStores={[secretsStore]}
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.name]: (release: HelmRelease) => release.getName(),
|
[columnId.name]: (release: HelmRelease) => release.getName(),
|
||||||
[sortBy.namespace]: (release: HelmRelease) => release.getNs(),
|
[columnId.namespace]: (release: HelmRelease) => release.getNs(),
|
||||||
[sortBy.revision]: (release: HelmRelease) => release.getRevision(),
|
[columnId.revision]: (release: HelmRelease) => release.getRevision(),
|
||||||
[sortBy.chart]: (release: HelmRelease) => release.getChart(),
|
[columnId.chart]: (release: HelmRelease) => release.getChart(),
|
||||||
[sortBy.status]: (release: HelmRelease) => release.getStatus(),
|
[columnId.status]: (release: HelmRelease) => release.getStatus(),
|
||||||
[sortBy.updated]: (release: HelmRelease) => release.getUpdated(false, false),
|
[columnId.updated]: (release: HelmRelease) => release.getUpdated(false, false),
|
||||||
}}
|
}}
|
||||||
searchFilters={[
|
searchFilters={[
|
||||||
(release: HelmRelease) => release.getName(),
|
(release: HelmRelease) => release.getName(),
|
||||||
@ -101,14 +105,14 @@ export class HelmReleases extends Component<Props> {
|
|||||||
]}
|
]}
|
||||||
renderHeaderTitle="Releases"
|
renderHeaderTitle="Releases"
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||||
{ title: "Namespace", className: "namespace", sortBy: sortBy.namespace },
|
{ title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace },
|
||||||
{ title: "Chart", className: "chart", sortBy: sortBy.chart },
|
{ title: "Chart", className: "chart", sortBy: columnId.chart, id: columnId.chart },
|
||||||
{ title: "Revision", className: "revision", sortBy: sortBy.revision },
|
{ title: "Revision", className: "revision", sortBy: columnId.revision, id: columnId.revision },
|
||||||
{ title: "Version", className: "version" },
|
{ title: "Version", className: "version", id: columnId.version },
|
||||||
{ title: "App Version", className: "app-version" },
|
{ title: "App Version", className: "app-version", id: columnId.appVersion },
|
||||||
{ title: "Status", className: "status", sortBy: sortBy.status },
|
{ title: "Status", className: "status", sortBy: columnId.status, id: columnId.status },
|
||||||
{ title: "Updated", className: "updated", sortBy: sortBy.updated },
|
{ title: "Updated", className: "updated", sortBy: columnId.updated, id: columnId.updated },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(release: HelmRelease) => {
|
renderTableContents={(release: HelmRelease) => {
|
||||||
const version = release.getVersion();
|
const version = release.getVersion();
|
||||||
|
|||||||
@ -11,13 +11,15 @@ import { Badge } from "../badge";
|
|||||||
import { cssNames } from "../../utils";
|
import { cssNames } from "../../utils";
|
||||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
namespace = "namespace",
|
namespace = "namespace",
|
||||||
|
metrics = "metrics",
|
||||||
minPods = "min-pods",
|
minPods = "min-pods",
|
||||||
maxPods = "max-pods",
|
maxPods = "max-pods",
|
||||||
replicas = "replicas",
|
replicas = "replicas",
|
||||||
age = "age",
|
age = "age",
|
||||||
|
status = "status"
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props extends RouteComponentProps<IHpaRouteParams> {
|
interface Props extends RouteComponentProps<IHpaRouteParams> {
|
||||||
@ -37,28 +39,30 @@ export class HorizontalPodAutoscalers extends React.Component<Props> {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<KubeObjectListLayout
|
<KubeObjectListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="configuration_hpa"
|
||||||
className="HorizontalPodAutoscalers" store={hpaStore}
|
className="HorizontalPodAutoscalers" store={hpaStore}
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.name]: (item: HorizontalPodAutoscaler) => item.getName(),
|
[columnId.name]: (item: HorizontalPodAutoscaler) => item.getName(),
|
||||||
[sortBy.namespace]: (item: HorizontalPodAutoscaler) => item.getNs(),
|
[columnId.namespace]: (item: HorizontalPodAutoscaler) => item.getNs(),
|
||||||
[sortBy.minPods]: (item: HorizontalPodAutoscaler) => item.getMinPods(),
|
[columnId.minPods]: (item: HorizontalPodAutoscaler) => item.getMinPods(),
|
||||||
[sortBy.maxPods]: (item: HorizontalPodAutoscaler) => item.getMaxPods(),
|
[columnId.maxPods]: (item: HorizontalPodAutoscaler) => item.getMaxPods(),
|
||||||
[sortBy.replicas]: (item: HorizontalPodAutoscaler) => item.getReplicas()
|
[columnId.replicas]: (item: HorizontalPodAutoscaler) => item.getReplicas()
|
||||||
}}
|
}}
|
||||||
searchFilters={[
|
searchFilters={[
|
||||||
(item: HorizontalPodAutoscaler) => item.getSearchFields()
|
(item: HorizontalPodAutoscaler) => item.getSearchFields()
|
||||||
]}
|
]}
|
||||||
renderHeaderTitle="Horizontal Pod Autoscalers"
|
renderHeaderTitle="Horizontal Pod Autoscalers"
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: columnId.name },
|
||||||
{ className: "warning" },
|
{ className: "warning", showWithColumn: columnId.name },
|
||||||
{ title: "Namespace", className: "namespace", sortBy: sortBy.namespace },
|
{ title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace },
|
||||||
{ title: "Metrics", className: "metrics" },
|
{ title: "Metrics", className: "metrics", id: columnId.metrics },
|
||||||
{ title: "Min Pods", className: "min-pods", sortBy: sortBy.minPods },
|
{ title: "Min Pods", className: "min-pods", sortBy: columnId.minPods, id: columnId.minPods },
|
||||||
{ title: "Max Pods", className: "max-pods", sortBy: sortBy.maxPods },
|
{ title: "Max Pods", className: "max-pods", sortBy: columnId.maxPods, id: columnId.maxPods },
|
||||||
{ title: "Replicas", className: "replicas", sortBy: sortBy.replicas },
|
{ title: "Replicas", className: "replicas", sortBy: columnId.replicas, id: columnId.replicas },
|
||||||
{ title: "Age", className: "age", sortBy: sortBy.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
{ title: "Status", className: "status" },
|
{ title: "Status", className: "status", id: columnId.status },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(hpa: HorizontalPodAutoscaler) => [
|
renderTableContents={(hpa: HorizontalPodAutoscaler) => [
|
||||||
hpa.getName(),
|
hpa.getName(),
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import React from "react";
|
|||||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||||
import { LimitRange } from "../../api/endpoints/limit-range.api";
|
import { LimitRange } from "../../api/endpoints/limit-range.api";
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
namespace = "namespace",
|
namespace = "namespace",
|
||||||
age = "age",
|
age = "age",
|
||||||
@ -23,12 +23,14 @@ export class LimitRanges extends React.Component<Props> {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<KubeObjectListLayout
|
<KubeObjectListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="configuration_limitranges"
|
||||||
className="LimitRanges"
|
className="LimitRanges"
|
||||||
store={limitRangeStore}
|
store={limitRangeStore}
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.name]: (item: LimitRange) => item.getName(),
|
[columnId.name]: (item: LimitRange) => item.getName(),
|
||||||
[sortBy.namespace]: (item: LimitRange) => item.getNs(),
|
[columnId.namespace]: (item: LimitRange) => item.getNs(),
|
||||||
[sortBy.age]: (item: LimitRange) => item.metadata.creationTimestamp,
|
[columnId.age]: (item: LimitRange) => item.metadata.creationTimestamp,
|
||||||
}}
|
}}
|
||||||
searchFilters={[
|
searchFilters={[
|
||||||
(item: LimitRange) => item.getName(),
|
(item: LimitRange) => item.getName(),
|
||||||
@ -36,10 +38,10 @@ export class LimitRanges extends React.Component<Props> {
|
|||||||
]}
|
]}
|
||||||
renderHeaderTitle={"Limit Ranges"}
|
renderHeaderTitle={"Limit Ranges"}
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||||
{ className: "warning" },
|
{ className: "warning", showWithColumn: columnId.name },
|
||||||
{ title: "Namespace", className: "namespace", sortBy: sortBy.namespace },
|
{ title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace },
|
||||||
{ title: "Age", className: "age", sortBy: sortBy.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(limitRange: LimitRange) => [
|
renderTableContents={(limitRange: LimitRange) => [
|
||||||
limitRange.getName(),
|
limitRange.getName(),
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import { KubeObjectListLayout } from "../kube-object";
|
|||||||
import { IConfigMapsRouteParams } from "./config-maps.route";
|
import { IConfigMapsRouteParams } from "./config-maps.route";
|
||||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
namespace = "namespace",
|
namespace = "namespace",
|
||||||
keys = "keys",
|
keys = "keys",
|
||||||
@ -24,12 +24,14 @@ export class ConfigMaps extends React.Component<Props> {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<KubeObjectListLayout
|
<KubeObjectListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="configuration_configmaps"
|
||||||
className="ConfigMaps" store={configMapsStore}
|
className="ConfigMaps" store={configMapsStore}
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.name]: (item: ConfigMap) => item.getName(),
|
[columnId.name]: (item: ConfigMap) => item.getName(),
|
||||||
[sortBy.namespace]: (item: ConfigMap) => item.getNs(),
|
[columnId.namespace]: (item: ConfigMap) => item.getNs(),
|
||||||
[sortBy.keys]: (item: ConfigMap) => item.getKeys(),
|
[columnId.keys]: (item: ConfigMap) => item.getKeys(),
|
||||||
[sortBy.age]: (item: ConfigMap) => item.metadata.creationTimestamp,
|
[columnId.age]: (item: ConfigMap) => item.metadata.creationTimestamp,
|
||||||
}}
|
}}
|
||||||
searchFilters={[
|
searchFilters={[
|
||||||
(item: ConfigMap) => item.getSearchFields(),
|
(item: ConfigMap) => item.getSearchFields(),
|
||||||
@ -37,11 +39,11 @@ export class ConfigMaps extends React.Component<Props> {
|
|||||||
]}
|
]}
|
||||||
renderHeaderTitle="Config Maps"
|
renderHeaderTitle="Config Maps"
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||||
{ className: "warning" },
|
{ className: "warning", showWithColumn: columnId.name },
|
||||||
{ title: "Namespace", className: "namespace", sortBy: sortBy.namespace },
|
{ title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace },
|
||||||
{ title: "Keys", className: "keys", sortBy: sortBy.keys },
|
{ title: "Keys", className: "keys", sortBy: columnId.keys, id: columnId.keys },
|
||||||
{ title: "Age", className: "age", sortBy: sortBy.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(configMap: ConfigMap) => [
|
renderTableContents={(configMap: ConfigMap) => [
|
||||||
configMap.getName(),
|
configMap.getName(),
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import { PodDisruptionBudget } from "../../api/endpoints/poddisruptionbudget.api
|
|||||||
import { KubeObjectDetailsProps, KubeObjectListLayout } from "../kube-object";
|
import { KubeObjectDetailsProps, KubeObjectListLayout } from "../kube-object";
|
||||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
namespace = "namespace",
|
namespace = "namespace",
|
||||||
minAvailable = "min-available",
|
minAvailable = "min-available",
|
||||||
@ -25,30 +25,32 @@ export class PodDisruptionBudgets extends React.Component<Props> {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<KubeObjectListLayout
|
<KubeObjectListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="configuration_distribution_budgets"
|
||||||
className="PodDisruptionBudgets"
|
className="PodDisruptionBudgets"
|
||||||
store={podDisruptionBudgetsStore}
|
store={podDisruptionBudgetsStore}
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.name]: (pdb: PodDisruptionBudget) => pdb.getName(),
|
[columnId.name]: (pdb: PodDisruptionBudget) => pdb.getName(),
|
||||||
[sortBy.namespace]: (pdb: PodDisruptionBudget) => pdb.getNs(),
|
[columnId.namespace]: (pdb: PodDisruptionBudget) => pdb.getNs(),
|
||||||
[sortBy.minAvailable]: (pdb: PodDisruptionBudget) => pdb.getMinAvailable(),
|
[columnId.minAvailable]: (pdb: PodDisruptionBudget) => pdb.getMinAvailable(),
|
||||||
[sortBy.maxUnavailable]: (pdb: PodDisruptionBudget) => pdb.getMaxUnavailable(),
|
[columnId.maxUnavailable]: (pdb: PodDisruptionBudget) => pdb.getMaxUnavailable(),
|
||||||
[sortBy.currentHealthy]: (pdb: PodDisruptionBudget) => pdb.getCurrentHealthy(),
|
[columnId.currentHealthy]: (pdb: PodDisruptionBudget) => pdb.getCurrentHealthy(),
|
||||||
[sortBy.desiredHealthy]: (pdb: PodDisruptionBudget) => pdb.getDesiredHealthy(),
|
[columnId.desiredHealthy]: (pdb: PodDisruptionBudget) => pdb.getDesiredHealthy(),
|
||||||
[sortBy.age]: (pdb: PodDisruptionBudget) => pdb.getAge(),
|
[columnId.age]: (pdb: PodDisruptionBudget) => pdb.getAge(),
|
||||||
}}
|
}}
|
||||||
searchFilters={[
|
searchFilters={[
|
||||||
(pdb: PodDisruptionBudget) => pdb.getSearchFields(),
|
(pdb: PodDisruptionBudget) => pdb.getSearchFields(),
|
||||||
]}
|
]}
|
||||||
renderHeaderTitle="Pod Disruption Budgets"
|
renderHeaderTitle="Pod Disruption Budgets"
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||||
{ className: "warning" },
|
{ className: "warning", showWithColumn: columnId.name },
|
||||||
{ title: "Namespace", className: "namespace", sortBy: sortBy.namespace },
|
{ title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace },
|
||||||
{ title: "Min Available", className: "min-available", sortBy: sortBy.minAvailable },
|
{ title: "Min Available", className: "min-available", sortBy: columnId.minAvailable, id: columnId.minAvailable },
|
||||||
{ title: "Max Unavailable", className: "max-unavailable", sortBy: sortBy.maxUnavailable },
|
{ title: "Max Unavailable", className: "max-unavailable", sortBy: columnId.maxUnavailable, id: columnId.maxUnavailable },
|
||||||
{ title: "Current Healthy", className: "current-healthy", sortBy: sortBy.currentHealthy },
|
{ title: "Current Healthy", className: "current-healthy", sortBy: columnId.currentHealthy, id: columnId.currentHealthy },
|
||||||
{ title: "Desired Healthy", className: "desired-healthy", sortBy: sortBy.desiredHealthy },
|
{ title: "Desired Healthy", className: "desired-healthy", sortBy: columnId.desiredHealthy, id: columnId.desiredHealthy },
|
||||||
{ title: "Age", className: "age", sortBy: sortBy.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(pdb: PodDisruptionBudget) => {
|
renderTableContents={(pdb: PodDisruptionBudget) => {
|
||||||
return [
|
return [
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import { resourceQuotaStore } from "./resource-quotas.store";
|
|||||||
import { IResourceQuotaRouteParams } from "./resource-quotas.route";
|
import { IResourceQuotaRouteParams } from "./resource-quotas.route";
|
||||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
namespace = "namespace",
|
namespace = "namespace",
|
||||||
age = "age"
|
age = "age"
|
||||||
@ -25,11 +25,13 @@ export class ResourceQuotas extends React.Component<Props> {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<KubeObjectListLayout
|
<KubeObjectListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="configuration_quotas"
|
||||||
className="ResourceQuotas" store={resourceQuotaStore}
|
className="ResourceQuotas" store={resourceQuotaStore}
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.name]: (item: ResourceQuota) => item.getName(),
|
[columnId.name]: (item: ResourceQuota) => item.getName(),
|
||||||
[sortBy.namespace]: (item: ResourceQuota) => item.getNs(),
|
[columnId.namespace]: (item: ResourceQuota) => item.getNs(),
|
||||||
[sortBy.age]: (item: ResourceQuota) => item.metadata.creationTimestamp,
|
[columnId.age]: (item: ResourceQuota) => item.metadata.creationTimestamp,
|
||||||
}}
|
}}
|
||||||
searchFilters={[
|
searchFilters={[
|
||||||
(item: ResourceQuota) => item.getSearchFields(),
|
(item: ResourceQuota) => item.getSearchFields(),
|
||||||
@ -37,10 +39,10 @@ export class ResourceQuotas extends React.Component<Props> {
|
|||||||
]}
|
]}
|
||||||
renderHeaderTitle="Resource Quotas"
|
renderHeaderTitle="Resource Quotas"
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||||
{ className: "warning" },
|
{ className: "warning", showWithColumn: columnId.name },
|
||||||
{ title: "Namespace", className: "namespace", sortBy: sortBy.namespace },
|
{ title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace },
|
||||||
{ title: "Age", className: "age", sortBy: sortBy.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(resourceQuota: ResourceQuota) => [
|
renderTableContents={(resourceQuota: ResourceQuota) => [
|
||||||
resourceQuota.getName(),
|
resourceQuota.getName(),
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import { Badge } from "../badge";
|
|||||||
import { secretsStore } from "./secrets.store";
|
import { secretsStore } from "./secrets.store";
|
||||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
namespace = "namespace",
|
namespace = "namespace",
|
||||||
labels = "labels",
|
labels = "labels",
|
||||||
@ -29,14 +29,16 @@ export class Secrets extends React.Component<Props> {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<KubeObjectListLayout
|
<KubeObjectListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="configuration_secrets"
|
||||||
className="Secrets" store={secretsStore}
|
className="Secrets" store={secretsStore}
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.name]: (item: Secret) => item.getName(),
|
[columnId.name]: (item: Secret) => item.getName(),
|
||||||
[sortBy.namespace]: (item: Secret) => item.getNs(),
|
[columnId.namespace]: (item: Secret) => item.getNs(),
|
||||||
[sortBy.labels]: (item: Secret) => item.getLabels(),
|
[columnId.labels]: (item: Secret) => item.getLabels(),
|
||||||
[sortBy.keys]: (item: Secret) => item.getKeys(),
|
[columnId.keys]: (item: Secret) => item.getKeys(),
|
||||||
[sortBy.type]: (item: Secret) => item.type,
|
[columnId.type]: (item: Secret) => item.type,
|
||||||
[sortBy.age]: (item: Secret) => item.metadata.creationTimestamp,
|
[columnId.age]: (item: Secret) => item.metadata.creationTimestamp,
|
||||||
}}
|
}}
|
||||||
searchFilters={[
|
searchFilters={[
|
||||||
(item: Secret) => item.getSearchFields(),
|
(item: Secret) => item.getSearchFields(),
|
||||||
@ -44,13 +46,13 @@ export class Secrets extends React.Component<Props> {
|
|||||||
]}
|
]}
|
||||||
renderHeaderTitle="Secrets"
|
renderHeaderTitle="Secrets"
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||||
{ className: "warning" },
|
{ className: "warning", showWithColumn: columnId.name },
|
||||||
{ title: "Namespace", className: "namespace", sortBy: sortBy.namespace },
|
{ title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace },
|
||||||
{ title: "Labels", className: "labels", sortBy: sortBy.labels },
|
{ title: "Labels", className: "labels", sortBy: columnId.labels, id: columnId.labels },
|
||||||
{ title: "Keys", className: "keys", sortBy: sortBy.keys },
|
{ title: "Keys", className: "keys", sortBy: columnId.keys, id: columnId.keys },
|
||||||
{ title: "Type", className: "type", sortBy: sortBy.type },
|
{ title: "Type", className: "type", sortBy: columnId.type, id: columnId.type },
|
||||||
{ title: "Age", className: "age", sortBy: sortBy.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(secret: Secret) => [
|
renderTableContents={(secret: Secret) => [
|
||||||
secret.getName(),
|
secret.getName(),
|
||||||
|
|||||||
@ -19,7 +19,7 @@ export const crdGroupsUrlParam = createPageParam<string[]>({
|
|||||||
defaultValue: [],
|
defaultValue: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
kind = "kind",
|
kind = "kind",
|
||||||
group = "group",
|
group = "group",
|
||||||
version = "version",
|
version = "version",
|
||||||
@ -47,14 +47,16 @@ export class CrdList extends React.Component {
|
|||||||
render() {
|
render() {
|
||||||
const selectedGroups = this.groups;
|
const selectedGroups = this.groups;
|
||||||
const sortingCallbacks = {
|
const sortingCallbacks = {
|
||||||
[sortBy.kind]: (crd: CustomResourceDefinition) => crd.getResourceKind(),
|
[columnId.kind]: (crd: CustomResourceDefinition) => crd.getResourceKind(),
|
||||||
[sortBy.group]: (crd: CustomResourceDefinition) => crd.getGroup(),
|
[columnId.group]: (crd: CustomResourceDefinition) => crd.getGroup(),
|
||||||
[sortBy.version]: (crd: CustomResourceDefinition) => crd.getVersion(),
|
[columnId.version]: (crd: CustomResourceDefinition) => crd.getVersion(),
|
||||||
[sortBy.scope]: (crd: CustomResourceDefinition) => crd.getScope(),
|
[columnId.scope]: (crd: CustomResourceDefinition) => crd.getScope(),
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<KubeObjectListLayout
|
<KubeObjectListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="crd"
|
||||||
className="CrdList"
|
className="CrdList"
|
||||||
isClusterScoped={true}
|
isClusterScoped={true}
|
||||||
store={crdStore}
|
store={crdStore}
|
||||||
@ -97,11 +99,11 @@ export class CrdList extends React.Component {
|
|||||||
};
|
};
|
||||||
}}
|
}}
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Resource", className: "kind", sortBy: sortBy.kind },
|
{ title: "Resource", className: "kind", sortBy: columnId.kind, id: columnId.kind },
|
||||||
{ title: "Group", className: "group", sortBy: sortBy.group },
|
{ title: "Group", className: "group", sortBy: columnId.group, id: columnId.group },
|
||||||
{ title: "Version", className: "version", sortBy: sortBy.group },
|
{ title: "Version", className: "version", sortBy: columnId.version, id: columnId.version },
|
||||||
{ title: "Scope", className: "scope", sortBy: sortBy.scope },
|
{ title: "Scope", className: "scope", sortBy: columnId.scope, id: columnId.scope },
|
||||||
{ title: "Age", className: "age", sortBy: sortBy.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(crd: CustomResourceDefinition) => [
|
renderTableContents={(crd: CustomResourceDefinition) => [
|
||||||
<Link key="link" to={crd.getResourceUrl()} onClick={stopPropagation}>
|
<Link key="link" to={crd.getResourceUrl()} onClick={stopPropagation}>
|
||||||
|
|||||||
@ -16,7 +16,7 @@ import { parseJsonPath } from "../../utils/jsonPath";
|
|||||||
interface Props extends RouteComponentProps<ICRDRouteParams> {
|
interface Props extends RouteComponentProps<ICRDRouteParams> {
|
||||||
}
|
}
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
namespace = "namespace",
|
namespace = "namespace",
|
||||||
age = "age",
|
age = "age",
|
||||||
@ -55,9 +55,9 @@ export class CrdResources extends React.Component<Props> {
|
|||||||
const isNamespaced = crd.isNamespaced();
|
const isNamespaced = crd.isNamespaced();
|
||||||
const extraColumns = crd.getPrinterColumns(false); // Cols with priority bigger than 0 are shown in details
|
const extraColumns = crd.getPrinterColumns(false); // Cols with priority bigger than 0 are shown in details
|
||||||
const sortingCallbacks: { [sortBy: string]: TableSortCallback } = {
|
const sortingCallbacks: { [sortBy: string]: TableSortCallback } = {
|
||||||
[sortBy.name]: (item: KubeObject) => item.getName(),
|
[columnId.name]: (item: KubeObject) => item.getName(),
|
||||||
[sortBy.namespace]: (item: KubeObject) => item.getNs(),
|
[columnId.namespace]: (item: KubeObject) => item.getNs(),
|
||||||
[sortBy.age]: (item: KubeObject) => item.metadata.creationTimestamp,
|
[columnId.age]: (item: KubeObject) => item.metadata.creationTimestamp,
|
||||||
};
|
};
|
||||||
|
|
||||||
extraColumns.forEach(column => {
|
extraColumns.forEach(column => {
|
||||||
@ -66,6 +66,8 @@ export class CrdResources extends React.Component<Props> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<KubeObjectListLayout
|
<KubeObjectListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="crd_resources"
|
||||||
className="CrdResources"
|
className="CrdResources"
|
||||||
isClusterScoped={!isNamespaced}
|
isClusterScoped={!isNamespaced}
|
||||||
store={store}
|
store={store}
|
||||||
@ -75,18 +77,19 @@ export class CrdResources extends React.Component<Props> {
|
|||||||
]}
|
]}
|
||||||
renderHeaderTitle={crd.getResourceTitle()}
|
renderHeaderTitle={crd.getResourceTitle()}
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||||
isNamespaced && { title: "Namespace", className: "namespace", sortBy: sortBy.namespace },
|
isNamespaced && { title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace },
|
||||||
...extraColumns.map(column => {
|
...extraColumns.map(column => {
|
||||||
const { name } = column;
|
const { name } = column;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title: name,
|
title: name,
|
||||||
className: name.toLowerCase(),
|
className: name.toLowerCase(),
|
||||||
sortBy: name
|
sortBy: name,
|
||||||
|
id: name
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
{ title: "Age", className: "age", sortBy: sortBy.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(crdInstance: KubeObject) => [
|
renderTableContents={(crdInstance: KubeObject) => [
|
||||||
crdInstance.getName(),
|
crdInstance.getName(),
|
||||||
|
|||||||
@ -12,11 +12,13 @@ import { cssNames, IClassName, stopPropagation } from "../../utils";
|
|||||||
import { Icon } from "../icon";
|
import { Icon } from "../icon";
|
||||||
import { lookupApiLink } from "../../api/kube-api";
|
import { lookupApiLink } from "../../api/kube-api";
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
|
message = "message",
|
||||||
namespace = "namespace",
|
namespace = "namespace",
|
||||||
object = "object",
|
object = "object",
|
||||||
type = "type",
|
type = "type",
|
||||||
count = "count",
|
count = "count",
|
||||||
|
source = "source",
|
||||||
age = "age",
|
age = "age",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,15 +41,17 @@ export class Events extends React.Component<Props> {
|
|||||||
const events = (
|
const events = (
|
||||||
<KubeObjectListLayout
|
<KubeObjectListLayout
|
||||||
{...layoutProps}
|
{...layoutProps}
|
||||||
|
isConfigurable
|
||||||
|
tableId="events"
|
||||||
className={cssNames("Events", className, { compact })}
|
className={cssNames("Events", className, { compact })}
|
||||||
store={eventStore}
|
store={eventStore}
|
||||||
isSelectable={false}
|
isSelectable={false}
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.namespace]: (event: KubeEvent) => event.getNs(),
|
[columnId.namespace]: (event: KubeEvent) => event.getNs(),
|
||||||
[sortBy.type]: (event: KubeEvent) => event.involvedObject.kind,
|
[columnId.type]: (event: KubeEvent) => event.involvedObject.kind,
|
||||||
[sortBy.object]: (event: KubeEvent) => event.involvedObject.name,
|
[columnId.object]: (event: KubeEvent) => event.involvedObject.name,
|
||||||
[sortBy.count]: (event: KubeEvent) => event.count,
|
[columnId.count]: (event: KubeEvent) => event.count,
|
||||||
[sortBy.age]: (event: KubeEvent) => event.metadata.creationTimestamp,
|
[columnId.age]: (event: KubeEvent) => event.metadata.creationTimestamp,
|
||||||
}}
|
}}
|
||||||
searchFilters={[
|
searchFilters={[
|
||||||
(event: KubeEvent) => event.getSearchFields(),
|
(event: KubeEvent) => event.getSearchFields(),
|
||||||
@ -72,13 +76,13 @@ export class Events extends React.Component<Props> {
|
|||||||
})
|
})
|
||||||
)}
|
)}
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Message", className: "message" },
|
{ title: "Message", className: "message", id: columnId.message },
|
||||||
{ title: "Namespace", className: "namespace", sortBy: sortBy.namespace },
|
{ title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace },
|
||||||
{ title: "Type", className: "type", sortBy: sortBy.type },
|
{ title: "Type", className: "type", sortBy: columnId.type, id: columnId.type },
|
||||||
{ title: "Involved Object", className: "object", sortBy: sortBy.object },
|
{ title: "Involved Object", className: "object", sortBy: columnId.object, id: columnId.object },
|
||||||
{ title: "Source", className: "source" },
|
{ title: "Source", className: "source", id: columnId.source },
|
||||||
{ title: "Count", className: "count", sortBy: sortBy.count },
|
{ title: "Count", className: "count", sortBy: columnId.count, id: columnId.count },
|
||||||
{ title: "Age", className: "age", sortBy: sortBy.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(event: KubeEvent) => {
|
renderTableContents={(event: KubeEvent) => {
|
||||||
const { involvedObject, type, message } = event;
|
const { involvedObject, type, message } = event;
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import { INamespacesRouteParams } from "./namespaces.route";
|
|||||||
import { namespaceStore } from "./namespace.store";
|
import { namespaceStore } from "./namespace.store";
|
||||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
labels = "labels",
|
labels = "labels",
|
||||||
age = "age",
|
age = "age",
|
||||||
@ -27,12 +27,14 @@ export class Namespaces extends React.Component<Props> {
|
|||||||
<TabLayout>
|
<TabLayout>
|
||||||
<KubeObjectListLayout
|
<KubeObjectListLayout
|
||||||
isClusterScoped
|
isClusterScoped
|
||||||
|
isConfigurable
|
||||||
|
tableId="namespaces"
|
||||||
className="Namespaces" store={namespaceStore}
|
className="Namespaces" store={namespaceStore}
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.name]: (ns: Namespace) => ns.getName(),
|
[columnId.name]: (ns: Namespace) => ns.getName(),
|
||||||
[sortBy.labels]: (ns: Namespace) => ns.getLabels(),
|
[columnId.labels]: (ns: Namespace) => ns.getLabels(),
|
||||||
[sortBy.age]: (ns: Namespace) => ns.metadata.creationTimestamp,
|
[columnId.age]: (ns: Namespace) => ns.metadata.creationTimestamp,
|
||||||
[sortBy.status]: (ns: Namespace) => ns.getStatus(),
|
[columnId.status]: (ns: Namespace) => ns.getStatus(),
|
||||||
}}
|
}}
|
||||||
searchFilters={[
|
searchFilters={[
|
||||||
(item: Namespace) => item.getSearchFields(),
|
(item: Namespace) => item.getSearchFields(),
|
||||||
@ -40,11 +42,11 @@ export class Namespaces extends React.Component<Props> {
|
|||||||
]}
|
]}
|
||||||
renderHeaderTitle="Namespaces"
|
renderHeaderTitle="Namespaces"
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||||
{ className: "warning" },
|
{ className: "warning", showWithColumn: columnId.name },
|
||||||
{ title: "Labels", className: "labels", sortBy: sortBy.labels },
|
{ title: "Labels", className: "labels", sortBy: columnId.labels, id: columnId.labels },
|
||||||
{ title: "Age", className: "age", sortBy: sortBy.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
{ title: "Status", className: "status", sortBy: sortBy.status },
|
{ title: "Status", className: "status", sortBy: columnId.status, id: columnId.status },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(item: Namespace) => [
|
renderTableContents={(item: Namespace) => [
|
||||||
item.getName(),
|
item.getName(),
|
||||||
|
|||||||
@ -9,9 +9,10 @@ import { endpointStore } from "./endpoints.store";
|
|||||||
import { KubeObjectListLayout } from "../kube-object";
|
import { KubeObjectListLayout } from "../kube-object";
|
||||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
namespace = "namespace",
|
namespace = "namespace",
|
||||||
|
endpoints = "endpoints",
|
||||||
age = "age",
|
age = "age",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,22 +24,24 @@ export class Endpoints extends React.Component<Props> {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<KubeObjectListLayout
|
<KubeObjectListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="network_endpoints"
|
||||||
className="Endpoints" store={endpointStore}
|
className="Endpoints" store={endpointStore}
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.name]: (endpoint: Endpoint) => endpoint.getName(),
|
[columnId.name]: (endpoint: Endpoint) => endpoint.getName(),
|
||||||
[sortBy.namespace]: (endpoint: Endpoint) => endpoint.getNs(),
|
[columnId.namespace]: (endpoint: Endpoint) => endpoint.getNs(),
|
||||||
[sortBy.age]: (endpoint: Endpoint) => endpoint.metadata.creationTimestamp,
|
[columnId.age]: (endpoint: Endpoint) => endpoint.metadata.creationTimestamp,
|
||||||
}}
|
}}
|
||||||
searchFilters={[
|
searchFilters={[
|
||||||
(endpoint: Endpoint) => endpoint.getSearchFields()
|
(endpoint: Endpoint) => endpoint.getSearchFields()
|
||||||
]}
|
]}
|
||||||
renderHeaderTitle="Endpoints"
|
renderHeaderTitle="Endpoints"
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||||
{ className: "warning" },
|
{ className: "warning", showWithColumn: columnId.name },
|
||||||
{ title: "Namespace", className: "namespace", sortBy: sortBy.namespace },
|
{ title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace },
|
||||||
{ title: "Endpoints", className: "endpoints" },
|
{ title: "Endpoints", className: "endpoints", id: columnId.endpoints },
|
||||||
{ title: "Age", className: "age", sortBy: sortBy.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(endpoint: Endpoint) => [
|
renderTableContents={(endpoint: Endpoint) => [
|
||||||
endpoint.getName(),
|
endpoint.getName(),
|
||||||
|
|||||||
@ -9,9 +9,11 @@ import { ingressStore } from "./ingress.store";
|
|||||||
import { KubeObjectListLayout } from "../kube-object";
|
import { KubeObjectListLayout } from "../kube-object";
|
||||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
namespace = "namespace",
|
namespace = "namespace",
|
||||||
|
loadBalancers ="load-balancers",
|
||||||
|
rules = "rules",
|
||||||
age = "age",
|
age = "age",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,11 +25,13 @@ export class Ingresses extends React.Component<Props> {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<KubeObjectListLayout
|
<KubeObjectListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="network_ingresses"
|
||||||
className="Ingresses" store={ingressStore}
|
className="Ingresses" store={ingressStore}
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.name]: (ingress: Ingress) => ingress.getName(),
|
[columnId.name]: (ingress: Ingress) => ingress.getName(),
|
||||||
[sortBy.namespace]: (ingress: Ingress) => ingress.getNs(),
|
[columnId.namespace]: (ingress: Ingress) => ingress.getNs(),
|
||||||
[sortBy.age]: (ingress: Ingress) => ingress.metadata.creationTimestamp,
|
[columnId.age]: (ingress: Ingress) => ingress.metadata.creationTimestamp,
|
||||||
}}
|
}}
|
||||||
searchFilters={[
|
searchFilters={[
|
||||||
(ingress: Ingress) => ingress.getSearchFields(),
|
(ingress: Ingress) => ingress.getSearchFields(),
|
||||||
@ -35,12 +39,12 @@ export class Ingresses extends React.Component<Props> {
|
|||||||
]}
|
]}
|
||||||
renderHeaderTitle="Ingresses"
|
renderHeaderTitle="Ingresses"
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||||
{ className: "warning" },
|
{ className: "warning", showWithColumn: columnId.name },
|
||||||
{ title: "Namespace", className: "namespace", sortBy: sortBy.namespace },
|
{ title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace },
|
||||||
{ title: "LoadBalancers", className: "loadbalancers" },
|
{ title: "LoadBalancers", className: "loadbalancers", id: columnId.loadBalancers },
|
||||||
{ title: "Rules", className: "rules" },
|
{ title: "Rules", className: "rules", id: columnId.rules },
|
||||||
{ title: "Age", className: "age", sortBy: sortBy.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(ingress: Ingress) => [
|
renderTableContents={(ingress: Ingress) => [
|
||||||
ingress.getName(),
|
ingress.getName(),
|
||||||
|
|||||||
@ -9,9 +9,10 @@ import { INetworkPoliciesRouteParams } from "./network-policies.route";
|
|||||||
import { networkPolicyStore } from "./network-policy.store";
|
import { networkPolicyStore } from "./network-policy.store";
|
||||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
namespace = "namespace",
|
namespace = "namespace",
|
||||||
|
types = "types",
|
||||||
age = "age",
|
age = "age",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,22 +24,24 @@ export class NetworkPolicies extends React.Component<Props> {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<KubeObjectListLayout
|
<KubeObjectListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="network_policies"
|
||||||
className="NetworkPolicies" store={networkPolicyStore}
|
className="NetworkPolicies" store={networkPolicyStore}
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.name]: (item: NetworkPolicy) => item.getName(),
|
[columnId.name]: (item: NetworkPolicy) => item.getName(),
|
||||||
[sortBy.namespace]: (item: NetworkPolicy) => item.getNs(),
|
[columnId.namespace]: (item: NetworkPolicy) => item.getNs(),
|
||||||
[sortBy.age]: (item: NetworkPolicy) => item.metadata.creationTimestamp,
|
[columnId.age]: (item: NetworkPolicy) => item.metadata.creationTimestamp,
|
||||||
}}
|
}}
|
||||||
searchFilters={[
|
searchFilters={[
|
||||||
(item: NetworkPolicy) => item.getSearchFields(),
|
(item: NetworkPolicy) => item.getSearchFields(),
|
||||||
]}
|
]}
|
||||||
renderHeaderTitle="Network Policies"
|
renderHeaderTitle="Network Policies"
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||||
{ className: "warning" },
|
{ className: "warning", showWithColumn: columnId.name },
|
||||||
{ title: "Namespace", className: "namespace", sortBy: sortBy.namespace },
|
{ title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace },
|
||||||
{ title: "Policy Types", className: "type" },
|
{ title: "Policy Types", className: "type", id: columnId.types },
|
||||||
{ title: "Age", className: "age", sortBy: sortBy.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(item: NetworkPolicy) => [
|
renderTableContents={(item: NetworkPolicy) => [
|
||||||
item.getName(),
|
item.getName(),
|
||||||
|
|||||||
@ -10,12 +10,13 @@ import { Badge } from "../badge";
|
|||||||
import { serviceStore } from "./services.store";
|
import { serviceStore } from "./services.store";
|
||||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
namespace = "namespace",
|
namespace = "namespace",
|
||||||
selector = "selector",
|
selector = "selector",
|
||||||
ports = "port",
|
ports = "port",
|
||||||
clusterIp = "cluster-ip",
|
clusterIp = "cluster-ip",
|
||||||
|
externalIp = "external-ip",
|
||||||
age = "age",
|
age = "age",
|
||||||
type = "type",
|
type = "type",
|
||||||
status = "status",
|
status = "status",
|
||||||
@ -29,16 +30,18 @@ export class Services extends React.Component<Props> {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<KubeObjectListLayout
|
<KubeObjectListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="network_services"
|
||||||
className="Services" store={serviceStore}
|
className="Services" store={serviceStore}
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.name]: (service: Service) => service.getName(),
|
[columnId.name]: (service: Service) => service.getName(),
|
||||||
[sortBy.namespace]: (service: Service) => service.getNs(),
|
[columnId.namespace]: (service: Service) => service.getNs(),
|
||||||
[sortBy.selector]: (service: Service) => service.getSelector(),
|
[columnId.selector]: (service: Service) => service.getSelector(),
|
||||||
[sortBy.ports]: (service: Service) => (service.spec.ports || []).map(({ port }) => port)[0],
|
[columnId.ports]: (service: Service) => (service.spec.ports || []).map(({ port }) => port)[0],
|
||||||
[sortBy.clusterIp]: (service: Service) => service.getClusterIp(),
|
[columnId.clusterIp]: (service: Service) => service.getClusterIp(),
|
||||||
[sortBy.type]: (service: Service) => service.getType(),
|
[columnId.type]: (service: Service) => service.getType(),
|
||||||
[sortBy.age]: (service: Service) => service.metadata.creationTimestamp,
|
[columnId.age]: (service: Service) => service.metadata.creationTimestamp,
|
||||||
[sortBy.status]: (service: Service) => service.getStatus(),
|
[columnId.status]: (service: Service) => service.getStatus(),
|
||||||
}}
|
}}
|
||||||
searchFilters={[
|
searchFilters={[
|
||||||
(service: Service) => service.getSearchFields(),
|
(service: Service) => service.getSearchFields(),
|
||||||
@ -47,16 +50,16 @@ export class Services extends React.Component<Props> {
|
|||||||
]}
|
]}
|
||||||
renderHeaderTitle="Services"
|
renderHeaderTitle="Services"
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||||
{ className: "warning" },
|
{ className: "warning", showWithColumn: columnId.name },
|
||||||
{ title: "Namespace", className: "namespace", sortBy: sortBy.namespace },
|
{ title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace },
|
||||||
{ title: "Type", className: "type", sortBy: sortBy.type },
|
{ title: "Type", className: "type", sortBy: columnId.type, id: columnId.type },
|
||||||
{ title: "Cluster IP", className: "clusterIp", sortBy: sortBy.clusterIp, },
|
{ title: "Cluster IP", className: "clusterIp", sortBy: columnId.clusterIp, id: columnId.clusterIp },
|
||||||
{ title: "Ports", className: "ports", sortBy: sortBy.ports },
|
{ title: "Ports", className: "ports", sortBy: columnId.ports, id: columnId.ports },
|
||||||
{ title: "External IP", className: "externalIp" },
|
{ title: "External IP", className: "externalIp", id: columnId.externalIp },
|
||||||
{ title: "Selector", className: "selector", sortBy: sortBy.selector },
|
{ title: "Selector", className: "selector", sortBy: columnId.selector, id: columnId.selector },
|
||||||
{ title: "Age", className: "age", sortBy: sortBy.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
{ title: "Status", className: "status", sortBy: sortBy.status },
|
{ title: "Status", className: "status", sortBy: columnId.status, id: columnId.status },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(service: Service) => [
|
renderTableContents={(service: Service) => [
|
||||||
service.getName(),
|
service.getName(),
|
||||||
|
|||||||
@ -17,7 +17,7 @@ import upperFirst from "lodash/upperFirst";
|
|||||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||||
import { Badge } from "../badge/badge";
|
import { Badge } from "../badge/badge";
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
cpu = "cpu",
|
cpu = "cpu",
|
||||||
memory = "memory",
|
memory = "memory",
|
||||||
@ -135,21 +135,23 @@ export class Nodes extends React.Component<Props> {
|
|||||||
return (
|
return (
|
||||||
<TabLayout>
|
<TabLayout>
|
||||||
<KubeObjectListLayout
|
<KubeObjectListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="nodes"
|
||||||
className="Nodes"
|
className="Nodes"
|
||||||
store={nodesStore} isClusterScoped
|
store={nodesStore} isClusterScoped
|
||||||
isReady={nodesStore.isLoaded}
|
isReady={nodesStore.isLoaded}
|
||||||
dependentStores={[podsStore]}
|
dependentStores={[podsStore]}
|
||||||
isSelectable={false}
|
isSelectable={false}
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.name]: (node: Node) => node.getName(),
|
[columnId.name]: (node: Node) => node.getName(),
|
||||||
[sortBy.cpu]: (node: Node) => nodesStore.getLastMetricValues(node, ["cpuUsage"]),
|
[columnId.cpu]: (node: Node) => nodesStore.getLastMetricValues(node, ["cpuUsage"]),
|
||||||
[sortBy.memory]: (node: Node) => nodesStore.getLastMetricValues(node, ["memoryUsage"]),
|
[columnId.memory]: (node: Node) => nodesStore.getLastMetricValues(node, ["memoryUsage"]),
|
||||||
[sortBy.disk]: (node: Node) => nodesStore.getLastMetricValues(node, ["fsUsage"]),
|
[columnId.disk]: (node: Node) => nodesStore.getLastMetricValues(node, ["fsUsage"]),
|
||||||
[sortBy.conditions]: (node: Node) => node.getNodeConditionText(),
|
[columnId.conditions]: (node: Node) => node.getNodeConditionText(),
|
||||||
[sortBy.taints]: (node: Node) => node.getTaints().length,
|
[columnId.taints]: (node: Node) => node.getTaints().length,
|
||||||
[sortBy.roles]: (node: Node) => node.getRoleLabels(),
|
[columnId.roles]: (node: Node) => node.getRoleLabels(),
|
||||||
[sortBy.age]: (node: Node) => node.metadata.creationTimestamp,
|
[columnId.age]: (node: Node) => node.metadata.creationTimestamp,
|
||||||
[sortBy.version]: (node: Node) => node.getKubeletVersion(),
|
[columnId.version]: (node: Node) => node.getKubeletVersion(),
|
||||||
}}
|
}}
|
||||||
searchFilters={[
|
searchFilters={[
|
||||||
(node: Node) => node.getSearchFields(),
|
(node: Node) => node.getSearchFields(),
|
||||||
@ -159,16 +161,16 @@ export class Nodes extends React.Component<Props> {
|
|||||||
]}
|
]}
|
||||||
renderHeaderTitle="Nodes"
|
renderHeaderTitle="Nodes"
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||||
{ className: "warning" },
|
{ className: "warning", showWithColumn: columnId.name },
|
||||||
{ title: "CPU", className: "cpu", sortBy: sortBy.cpu },
|
{ title: "CPU", className: "cpu", sortBy: columnId.cpu, id: columnId.cpu },
|
||||||
{ title: "Memory", className: "memory", sortBy: sortBy.memory },
|
{ title: "Memory", className: "memory", sortBy: columnId.memory, id: columnId.memory },
|
||||||
{ title: "Disk", className: "disk", sortBy: sortBy.disk },
|
{ title: "Disk", className: "disk", sortBy: columnId.disk, id: columnId.disk },
|
||||||
{ title: "Taints", className: "taints", sortBy: sortBy.taints },
|
{ title: "Taints", className: "taints", sortBy: columnId.taints, id: columnId.taints },
|
||||||
{ title: "Roles", className: "roles", sortBy: sortBy.roles },
|
{ title: "Roles", className: "roles", sortBy: columnId.roles, id: columnId.roles },
|
||||||
{ title: "Version", className: "version", sortBy: sortBy.version },
|
{ title: "Version", className: "version", sortBy: columnId.version, id: columnId.version },
|
||||||
{ title: "Age", className: "age", sortBy: sortBy.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
{ title: "Conditions", className: "conditions", sortBy: sortBy.conditions },
|
{ title: "Conditions", className: "conditions", sortBy: columnId.conditions, id: columnId.conditions },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(node: Node) => {
|
renderTableContents={(node: Node) => {
|
||||||
const tooltipId = `node-taints-${node.getId()}`;
|
const tooltipId = `node-taints-${node.getId()}`;
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import { podSecurityPoliciesStore } from "./pod-security-policies.store";
|
|||||||
import { PodSecurityPolicy } from "../../api/endpoints";
|
import { PodSecurityPolicy } from "../../api/endpoints";
|
||||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
volumes = "volumes",
|
volumes = "volumes",
|
||||||
privileged = "privileged",
|
privileged = "privileged",
|
||||||
@ -19,14 +19,16 @@ export class PodSecurityPolicies extends React.Component {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<KubeObjectListLayout
|
<KubeObjectListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="access_roles"
|
||||||
className="PodSecurityPolicies"
|
className="PodSecurityPolicies"
|
||||||
isClusterScoped={true}
|
isClusterScoped={true}
|
||||||
store={podSecurityPoliciesStore}
|
store={podSecurityPoliciesStore}
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.name]: (item: PodSecurityPolicy) => item.getName(),
|
[columnId.name]: (item: PodSecurityPolicy) => item.getName(),
|
||||||
[sortBy.volumes]: (item: PodSecurityPolicy) => item.getVolumes(),
|
[columnId.volumes]: (item: PodSecurityPolicy) => item.getVolumes(),
|
||||||
[sortBy.privileged]: (item: PodSecurityPolicy) => +item.isPrivileged(),
|
[columnId.privileged]: (item: PodSecurityPolicy) => +item.isPrivileged(),
|
||||||
[sortBy.age]: (item: PodSecurityPolicy) => item.metadata.creationTimestamp,
|
[columnId.age]: (item: PodSecurityPolicy) => item.metadata.creationTimestamp,
|
||||||
}}
|
}}
|
||||||
searchFilters={[
|
searchFilters={[
|
||||||
(item: PodSecurityPolicy) => item.getSearchFields(),
|
(item: PodSecurityPolicy) => item.getSearchFields(),
|
||||||
@ -35,11 +37,11 @@ export class PodSecurityPolicies extends React.Component {
|
|||||||
]}
|
]}
|
||||||
renderHeaderTitle="Pod Security Policies"
|
renderHeaderTitle="Pod Security Policies"
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||||
{ className: "warning" },
|
{ className: "warning", showWithColumn: columnId.name },
|
||||||
{ title: "Privileged", className: "privileged", sortBy: sortBy.privileged },
|
{ title: "Privileged", className: "privileged", sortBy: columnId.privileged, id: columnId.privileged },
|
||||||
{ title: "Volumes", className: "volumes", sortBy: sortBy.volumes },
|
{ title: "Volumes", className: "volumes", sortBy: columnId.volumes, id: columnId.volumes },
|
||||||
{ title: "Age", className: "age", sortBy: sortBy.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(item: PodSecurityPolicy) => {
|
renderTableContents={(item: PodSecurityPolicy) => {
|
||||||
return [
|
return [
|
||||||
|
|||||||
@ -9,10 +9,11 @@ import { IStorageClassesRouteParams } from "./storage-classes.route";
|
|||||||
import { storageClassStore } from "./storage-class.store";
|
import { storageClassStore } from "./storage-class.store";
|
||||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
age = "age",
|
age = "age",
|
||||||
provisioner = "provision",
|
provisioner = "provision",
|
||||||
|
default = "default",
|
||||||
reclaimPolicy = "reclaim",
|
reclaimPolicy = "reclaim",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,13 +25,15 @@ export class StorageClasses extends React.Component<Props> {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<KubeObjectListLayout
|
<KubeObjectListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="storage_classes"
|
||||||
className="StorageClasses"
|
className="StorageClasses"
|
||||||
store={storageClassStore} isClusterScoped
|
store={storageClassStore} isClusterScoped
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.name]: (item: StorageClass) => item.getName(),
|
[columnId.name]: (item: StorageClass) => item.getName(),
|
||||||
[sortBy.age]: (item: StorageClass) => item.metadata.creationTimestamp,
|
[columnId.age]: (item: StorageClass) => item.metadata.creationTimestamp,
|
||||||
[sortBy.provisioner]: (item: StorageClass) => item.provisioner,
|
[columnId.provisioner]: (item: StorageClass) => item.provisioner,
|
||||||
[sortBy.reclaimPolicy]: (item: StorageClass) => item.reclaimPolicy,
|
[columnId.reclaimPolicy]: (item: StorageClass) => item.reclaimPolicy,
|
||||||
}}
|
}}
|
||||||
searchFilters={[
|
searchFilters={[
|
||||||
(item: StorageClass) => item.getSearchFields(),
|
(item: StorageClass) => item.getSearchFields(),
|
||||||
@ -38,12 +41,12 @@ export class StorageClasses extends React.Component<Props> {
|
|||||||
]}
|
]}
|
||||||
renderHeaderTitle="Storage Classes"
|
renderHeaderTitle="Storage Classes"
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||||
{ className: "warning" },
|
{ className: "warning", showWithColumn: columnId.name },
|
||||||
{ title: "Provisioner", className: "provisioner", sortBy: sortBy.provisioner },
|
{ title: "Provisioner", className: "provisioner", sortBy: columnId.provisioner, id: columnId.provisioner },
|
||||||
{ title: "Reclaim Policy", className: "reclaim-policy", sortBy: sortBy.reclaimPolicy },
|
{ title: "Reclaim Policy", className: "reclaim-policy", sortBy: columnId.reclaimPolicy, id: columnId.reclaimPolicy },
|
||||||
{ title: "Default", className: "is-default" },
|
{ title: "Default", className: "is-default", id: columnId.default },
|
||||||
{ title: "Age", className: "age", sortBy: sortBy.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(storageClass: StorageClass) => [
|
renderTableContents={(storageClass: StorageClass) => [
|
||||||
storageClass.getName(),
|
storageClass.getName(),
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import { stopPropagation } from "../../utils";
|
|||||||
import { storageClassApi } from "../../api/endpoints";
|
import { storageClassApi } from "../../api/endpoints";
|
||||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
namespace = "namespace",
|
namespace = "namespace",
|
||||||
pods = "pods",
|
pods = "pods",
|
||||||
@ -31,17 +31,19 @@ export class PersistentVolumeClaims extends React.Component<Props> {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<KubeObjectListLayout
|
<KubeObjectListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="storage_volume_claims"
|
||||||
className="PersistentVolumeClaims"
|
className="PersistentVolumeClaims"
|
||||||
store={volumeClaimStore}
|
store={volumeClaimStore}
|
||||||
dependentStores={[podsStore]}
|
dependentStores={[podsStore]}
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.name]: (pvc: PersistentVolumeClaim) => pvc.getName(),
|
[columnId.name]: (pvc: PersistentVolumeClaim) => pvc.getName(),
|
||||||
[sortBy.namespace]: (pvc: PersistentVolumeClaim) => pvc.getNs(),
|
[columnId.namespace]: (pvc: PersistentVolumeClaim) => pvc.getNs(),
|
||||||
[sortBy.pods]: (pvc: PersistentVolumeClaim) => pvc.getPods(podsStore.items).map(pod => pod.getName()),
|
[columnId.pods]: (pvc: PersistentVolumeClaim) => pvc.getPods(podsStore.items).map(pod => pod.getName()),
|
||||||
[sortBy.status]: (pvc: PersistentVolumeClaim) => pvc.getStatus(),
|
[columnId.status]: (pvc: PersistentVolumeClaim) => pvc.getStatus(),
|
||||||
[sortBy.size]: (pvc: PersistentVolumeClaim) => unitsToBytes(pvc.getStorage()),
|
[columnId.size]: (pvc: PersistentVolumeClaim) => unitsToBytes(pvc.getStorage()),
|
||||||
[sortBy.storageClass]: (pvc: PersistentVolumeClaim) => pvc.spec.storageClassName,
|
[columnId.storageClass]: (pvc: PersistentVolumeClaim) => pvc.spec.storageClassName,
|
||||||
[sortBy.age]: (pvc: PersistentVolumeClaim) => pvc.metadata.creationTimestamp,
|
[columnId.age]: (pvc: PersistentVolumeClaim) => pvc.metadata.creationTimestamp,
|
||||||
}}
|
}}
|
||||||
searchFilters={[
|
searchFilters={[
|
||||||
(item: PersistentVolumeClaim) => item.getSearchFields(),
|
(item: PersistentVolumeClaim) => item.getSearchFields(),
|
||||||
@ -49,14 +51,14 @@ export class PersistentVolumeClaims extends React.Component<Props> {
|
|||||||
]}
|
]}
|
||||||
renderHeaderTitle="Persistent Volume Claims"
|
renderHeaderTitle="Persistent Volume Claims"
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||||
{ className: "warning" },
|
{ className: "warning", showWithColumn: columnId.name },
|
||||||
{ title: "Namespace", className: "namespace", sortBy: sortBy.namespace },
|
{ title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace },
|
||||||
{ title: "Storage class", className: "storageClass", sortBy: sortBy.storageClass },
|
{ title: "Storage class", className: "storageClass", sortBy: columnId.storageClass, id: columnId.storageClass },
|
||||||
{ title: "Size", className: "size", sortBy: sortBy.size },
|
{ title: "Size", className: "size", sortBy: columnId.size, id: columnId.size },
|
||||||
{ title: "Pods", className: "pods", sortBy: sortBy.pods },
|
{ title: "Pods", className: "pods", sortBy: columnId.pods, id: columnId.pods },
|
||||||
{ title: "Age", className: "age", sortBy: sortBy.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
{ title: "Status", className: "status", sortBy: sortBy.status },
|
{ title: "Status", className: "status", sortBy: columnId.status, id: columnId.status },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(pvc: PersistentVolumeClaim) => {
|
renderTableContents={(pvc: PersistentVolumeClaim) => {
|
||||||
const pods = pvc.getPods(podsStore.items);
|
const pods = pvc.getPods(podsStore.items);
|
||||||
|
|||||||
@ -11,10 +11,11 @@ import { volumesStore } from "./volumes.store";
|
|||||||
import { pvcApi, storageClassApi } from "../../api/endpoints";
|
import { pvcApi, storageClassApi } from "../../api/endpoints";
|
||||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
storageClass = "storage-class",
|
storageClass = "storage-class",
|
||||||
capacity = "capacity",
|
capacity = "capacity",
|
||||||
|
claim = "claim",
|
||||||
status = "status",
|
status = "status",
|
||||||
age = "age",
|
age = "age",
|
||||||
}
|
}
|
||||||
@ -27,14 +28,16 @@ export class PersistentVolumes extends React.Component<Props> {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<KubeObjectListLayout
|
<KubeObjectListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="storage_volumes"
|
||||||
className="PersistentVolumes"
|
className="PersistentVolumes"
|
||||||
store={volumesStore} isClusterScoped
|
store={volumesStore} isClusterScoped
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.name]: (item: PersistentVolume) => item.getName(),
|
[columnId.name]: (item: PersistentVolume) => item.getName(),
|
||||||
[sortBy.storageClass]: (item: PersistentVolume) => item.spec.storageClassName,
|
[columnId.storageClass]: (item: PersistentVolume) => item.spec.storageClassName,
|
||||||
[sortBy.capacity]: (item: PersistentVolume) => item.getCapacity(true),
|
[columnId.capacity]: (item: PersistentVolume) => item.getCapacity(true),
|
||||||
[sortBy.status]: (item: PersistentVolume) => item.getStatus(),
|
[columnId.status]: (item: PersistentVolume) => item.getStatus(),
|
||||||
[sortBy.age]: (item: PersistentVolume) => item.metadata.creationTimestamp,
|
[columnId.age]: (item: PersistentVolume) => item.metadata.creationTimestamp,
|
||||||
}}
|
}}
|
||||||
searchFilters={[
|
searchFilters={[
|
||||||
(item: PersistentVolume) => item.getSearchFields(),
|
(item: PersistentVolume) => item.getSearchFields(),
|
||||||
@ -42,13 +45,13 @@ export class PersistentVolumes extends React.Component<Props> {
|
|||||||
]}
|
]}
|
||||||
renderHeaderTitle="Persistent Volumes"
|
renderHeaderTitle="Persistent Volumes"
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||||
{ className: "warning" },
|
{ className: "warning", showWithColumn: columnId.name },
|
||||||
{ title: "Storage Class", className: "storageClass", sortBy: sortBy.storageClass },
|
{ title: "Storage Class", className: "storageClass", sortBy: columnId.storageClass, id: columnId.storageClass },
|
||||||
{ title: "Capacity", className: "capacity", sortBy: sortBy.capacity },
|
{ title: "Capacity", className: "capacity", sortBy: columnId.capacity, id: columnId.capacity },
|
||||||
{ title: "Claim", className: "claim" },
|
{ title: "Claim", className: "claim", id: columnId.claim },
|
||||||
{ title: "Age", className: "age", sortBy: sortBy.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
{ title: "Status", className: "status", sortBy: sortBy.status },
|
{ title: "Status", className: "status", sortBy: columnId.status, id: columnId.status },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(volume: PersistentVolume) => {
|
renderTableContents={(volume: PersistentVolume) => {
|
||||||
const { claimRef, storageClassName } = volume.spec;
|
const { claimRef, storageClassName } = volume.spec;
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import { KubeObjectListLayout } from "../kube-object";
|
|||||||
import { AddRoleBindingDialog } from "./add-role-binding-dialog";
|
import { AddRoleBindingDialog } from "./add-role-binding-dialog";
|
||||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
namespace = "namespace",
|
namespace = "namespace",
|
||||||
bindings = "bindings",
|
bindings = "bindings",
|
||||||
@ -25,13 +25,15 @@ export class RoleBindings extends React.Component<Props> {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<KubeObjectListLayout
|
<KubeObjectListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="access_role_bindings"
|
||||||
className="RoleBindings"
|
className="RoleBindings"
|
||||||
store={roleBindingsStore}
|
store={roleBindingsStore}
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.name]: (binding: RoleBinding) => binding.getName(),
|
[columnId.name]: (binding: RoleBinding) => binding.getName(),
|
||||||
[sortBy.namespace]: (binding: RoleBinding) => binding.getNs(),
|
[columnId.namespace]: (binding: RoleBinding) => binding.getNs(),
|
||||||
[sortBy.bindings]: (binding: RoleBinding) => binding.getSubjectNames(),
|
[columnId.bindings]: (binding: RoleBinding) => binding.getSubjectNames(),
|
||||||
[sortBy.age]: (binding: RoleBinding) => binding.metadata.creationTimestamp,
|
[columnId.age]: (binding: RoleBinding) => binding.metadata.creationTimestamp,
|
||||||
}}
|
}}
|
||||||
searchFilters={[
|
searchFilters={[
|
||||||
(binding: RoleBinding) => binding.getSearchFields(),
|
(binding: RoleBinding) => binding.getSearchFields(),
|
||||||
@ -39,11 +41,11 @@ export class RoleBindings extends React.Component<Props> {
|
|||||||
]}
|
]}
|
||||||
renderHeaderTitle="Role Bindings"
|
renderHeaderTitle="Role Bindings"
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||||
{ className: "warning" },
|
{ className: "warning", showWithColumn: columnId.name },
|
||||||
{ title: "Bindings", className: "bindings", sortBy: sortBy.bindings },
|
{ title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace },
|
||||||
{ title: "Namespace", className: "namespace", sortBy: sortBy.namespace },
|
{ title: "Bindings", className: "bindings", sortBy: columnId.bindings, id: columnId.bindings },
|
||||||
{ title: "Age", className: "age", sortBy: sortBy.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(binding: RoleBinding) => [
|
renderTableContents={(binding: RoleBinding) => [
|
||||||
binding.getName(),
|
binding.getName(),
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import { KubeObjectListLayout } from "../kube-object";
|
|||||||
import { AddRoleDialog } from "./add-role-dialog";
|
import { AddRoleDialog } from "./add-role-dialog";
|
||||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
namespace = "namespace",
|
namespace = "namespace",
|
||||||
age = "age",
|
age = "age",
|
||||||
@ -25,22 +25,24 @@ export class Roles extends React.Component<Props> {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<KubeObjectListLayout
|
<KubeObjectListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="access_roles"
|
||||||
className="Roles"
|
className="Roles"
|
||||||
store={rolesStore}
|
store={rolesStore}
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.name]: (role: Role) => role.getName(),
|
[columnId.name]: (role: Role) => role.getName(),
|
||||||
[sortBy.namespace]: (role: Role) => role.getNs(),
|
[columnId.namespace]: (role: Role) => role.getNs(),
|
||||||
[sortBy.age]: (role: Role) => role.metadata.creationTimestamp,
|
[columnId.age]: (role: Role) => role.metadata.creationTimestamp,
|
||||||
}}
|
}}
|
||||||
searchFilters={[
|
searchFilters={[
|
||||||
(role: Role) => role.getSearchFields(),
|
(role: Role) => role.getSearchFields(),
|
||||||
]}
|
]}
|
||||||
renderHeaderTitle="Roles"
|
renderHeaderTitle="Roles"
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||||
{ className: "warning" },
|
{ className: "warning", showWithColumn: columnId.name },
|
||||||
{ title: "Namespace", className: "namespace", sortBy: sortBy.namespace },
|
{ title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace },
|
||||||
{ title: "Age", className: "age", sortBy: sortBy.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(role: Role) => [
|
renderTableContents={(role: Role) => [
|
||||||
role.getName(),
|
role.getName(),
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import { CreateServiceAccountDialog } from "./create-service-account-dialog";
|
|||||||
import { kubeObjectMenuRegistry } from "../../../extensions/registries/kube-object-menu-registry";
|
import { kubeObjectMenuRegistry } from "../../../extensions/registries/kube-object-menu-registry";
|
||||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
namespace = "namespace",
|
namespace = "namespace",
|
||||||
age = "age",
|
age = "age",
|
||||||
@ -30,21 +30,23 @@ export class ServiceAccounts extends React.Component<Props> {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<KubeObjectListLayout
|
<KubeObjectListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="access_service_accounts"
|
||||||
className="ServiceAccounts" store={serviceAccountsStore}
|
className="ServiceAccounts" store={serviceAccountsStore}
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.name]: (account: ServiceAccount) => account.getName(),
|
[columnId.name]: (account: ServiceAccount) => account.getName(),
|
||||||
[sortBy.namespace]: (account: ServiceAccount) => account.getNs(),
|
[columnId.namespace]: (account: ServiceAccount) => account.getNs(),
|
||||||
[sortBy.age]: (account: ServiceAccount) => account.metadata.creationTimestamp,
|
[columnId.age]: (account: ServiceAccount) => account.metadata.creationTimestamp,
|
||||||
}}
|
}}
|
||||||
searchFilters={[
|
searchFilters={[
|
||||||
(account: ServiceAccount) => account.getSearchFields(),
|
(account: ServiceAccount) => account.getSearchFields(),
|
||||||
]}
|
]}
|
||||||
renderHeaderTitle="Service Accounts"
|
renderHeaderTitle="Service Accounts"
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||||
{ className: "warning" },
|
{ className: "warning", showWithColumn: columnId.name },
|
||||||
{ title: "Namespace", className: "namespace", sortBy: sortBy.namespace },
|
{ title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace },
|
||||||
{ title: "Age", className: "age", sortBy: sortBy.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(account: ServiceAccount) => [
|
renderTableContents={(account: ServiceAccount) => [
|
||||||
account.getName(),
|
account.getName(),
|
||||||
|
|||||||
@ -18,12 +18,13 @@ import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
|||||||
import { ConfirmDialog } from "../confirm-dialog/confirm-dialog";
|
import { ConfirmDialog } from "../confirm-dialog/confirm-dialog";
|
||||||
import { Notifications } from "../notifications/notifications";
|
import { Notifications } from "../notifications/notifications";
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
namespace = "namespace",
|
namespace = "namespace",
|
||||||
|
schedule = "schedule",
|
||||||
suspend = "suspend",
|
suspend = "suspend",
|
||||||
active = "active",
|
active = "active",
|
||||||
lastSchedule = "schedule",
|
lastSchedule = "last-schedule",
|
||||||
age = "age",
|
age = "age",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,15 +36,17 @@ export class CronJobs extends React.Component<Props> {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<KubeObjectListLayout
|
<KubeObjectListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="workload_cronjobs"
|
||||||
className="CronJobs" store={cronJobStore}
|
className="CronJobs" store={cronJobStore}
|
||||||
dependentStores={[jobStore, eventStore]}
|
dependentStores={[jobStore, eventStore]}
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.name]: (cronJob: CronJob) => cronJob.getName(),
|
[columnId.name]: (cronJob: CronJob) => cronJob.getName(),
|
||||||
[sortBy.namespace]: (cronJob: CronJob) => cronJob.getNs(),
|
[columnId.namespace]: (cronJob: CronJob) => cronJob.getNs(),
|
||||||
[sortBy.suspend]: (cronJob: CronJob) => cronJob.getSuspendFlag(),
|
[columnId.suspend]: (cronJob: CronJob) => cronJob.getSuspendFlag(),
|
||||||
[sortBy.active]: (cronJob: CronJob) => cronJobStore.getActiveJobsNum(cronJob),
|
[columnId.active]: (cronJob: CronJob) => cronJobStore.getActiveJobsNum(cronJob),
|
||||||
[sortBy.lastSchedule]: (cronJob: CronJob) => cronJob.getLastScheduleTime(),
|
[columnId.lastSchedule]: (cronJob: CronJob) => cronJob.getLastScheduleTime(),
|
||||||
[sortBy.age]: (cronJob: CronJob) => cronJob.metadata.creationTimestamp,
|
[columnId.age]: (cronJob: CronJob) => cronJob.metadata.creationTimestamp,
|
||||||
}}
|
}}
|
||||||
searchFilters={[
|
searchFilters={[
|
||||||
(cronJob: CronJob) => cronJob.getSearchFields(),
|
(cronJob: CronJob) => cronJob.getSearchFields(),
|
||||||
@ -51,14 +54,14 @@ export class CronJobs extends React.Component<Props> {
|
|||||||
]}
|
]}
|
||||||
renderHeaderTitle="Cron Jobs"
|
renderHeaderTitle="Cron Jobs"
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||||
{ className: "warning" },
|
{ className: "warning", showWithColumn: columnId.name },
|
||||||
{ title: "Namespace", className: "namespace", sortBy: sortBy.namespace },
|
{ title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace },
|
||||||
{ title: "Schedule", className: "schedule" },
|
{ title: "Schedule", className: "schedule", id: columnId.schedule },
|
||||||
{ title: "Suspend", className: "suspend", sortBy: sortBy.suspend },
|
{ title: "Suspend", className: "suspend", sortBy: columnId.suspend, id: columnId.suspend },
|
||||||
{ title: "Active", className: "active", sortBy: sortBy.active },
|
{ title: "Active", className: "active", sortBy: columnId.active, id: columnId.active },
|
||||||
{ title: "Last schedule", className: "last-schedule", sortBy: sortBy.lastSchedule },
|
{ title: "Last schedule", className: "last-schedule", sortBy: columnId.lastSchedule, id: columnId.lastSchedule },
|
||||||
{ title: "Age", className: "age", sortBy: sortBy.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(cronJob: CronJob) => [
|
renderTableContents={(cronJob: CronJob) => [
|
||||||
cronJob.getName(),
|
cronJob.getName(),
|
||||||
|
|||||||
@ -18,7 +18,7 @@ export class DaemonSetStore extends KubeObjectStore<DaemonSet> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getChildPods(daemonSet: DaemonSet): Pod[] {
|
getChildPods(daemonSet: DaemonSet): Pod[] {
|
||||||
return podsStore.getPodsByOwner(daemonSet);
|
return podsStore.getPodsByOwnerId(daemonSet.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
getStatuses(daemonSets?: DaemonSet[]) {
|
getStatuses(daemonSets?: DaemonSet[]) {
|
||||||
|
|||||||
@ -13,10 +13,11 @@ import { IDaemonSetsRouteParams } from "../+workloads";
|
|||||||
import { Badge } from "../badge";
|
import { Badge } from "../badge";
|
||||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
namespace = "namespace",
|
namespace = "namespace",
|
||||||
pods = "pods",
|
pods = "pods",
|
||||||
|
labels = "labels",
|
||||||
age = "age",
|
age = "age",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,13 +39,15 @@ export class DaemonSets extends React.Component<Props> {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<KubeObjectListLayout
|
<KubeObjectListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="workload_daemonsets"
|
||||||
className="DaemonSets" store={daemonSetStore}
|
className="DaemonSets" store={daemonSetStore}
|
||||||
dependentStores={[podsStore, nodesStore, eventStore]}
|
dependentStores={[podsStore, nodesStore, eventStore]}
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.name]: (daemonSet: DaemonSet) => daemonSet.getName(),
|
[columnId.name]: (daemonSet: DaemonSet) => daemonSet.getName(),
|
||||||
[sortBy.namespace]: (daemonSet: DaemonSet) => daemonSet.getNs(),
|
[columnId.namespace]: (daemonSet: DaemonSet) => daemonSet.getNs(),
|
||||||
[sortBy.pods]: (daemonSet: DaemonSet) => this.getPodsLength(daemonSet),
|
[columnId.pods]: (daemonSet: DaemonSet) => this.getPodsLength(daemonSet),
|
||||||
[sortBy.age]: (daemonSet: DaemonSet) => daemonSet.metadata.creationTimestamp,
|
[columnId.age]: (daemonSet: DaemonSet) => daemonSet.metadata.creationTimestamp,
|
||||||
}}
|
}}
|
||||||
searchFilters={[
|
searchFilters={[
|
||||||
(daemonSet: DaemonSet) => daemonSet.getSearchFields(),
|
(daemonSet: DaemonSet) => daemonSet.getSearchFields(),
|
||||||
@ -52,12 +55,12 @@ export class DaemonSets extends React.Component<Props> {
|
|||||||
]}
|
]}
|
||||||
renderHeaderTitle="Daemon Sets"
|
renderHeaderTitle="Daemon Sets"
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||||
{ title: "Namespace", className: "namespace", sortBy: sortBy.namespace },
|
{ title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace },
|
||||||
{ title: "Pods", className: "pods", sortBy: sortBy.pods },
|
{ title: "Pods", className: "pods", sortBy: columnId.pods, id: columnId.pods },
|
||||||
{ className: "warning" },
|
{ className: "warning", showWithColumn: columnId.pods },
|
||||||
{ title: "Node Selector", className: "labels" },
|
{ title: "Node Selector", className: "labels", id: columnId.labels },
|
||||||
{ title: "Age", className: "age", sortBy: sortBy.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(daemonSet: DaemonSet) => [
|
renderTableContents={(daemonSet: DaemonSet) => [
|
||||||
daemonSet.getName(),
|
daemonSet.getName(),
|
||||||
|
|||||||
@ -23,9 +23,10 @@ import { kubeObjectMenuRegistry } from "../../../extensions/registries/kube-obje
|
|||||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||||
import { Notifications } from "../notifications";
|
import { Notifications } from "../notifications";
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
namespace = "namespace",
|
namespace = "namespace",
|
||||||
|
pods = "pods",
|
||||||
replicas = "replicas",
|
replicas = "replicas",
|
||||||
age = "age",
|
age = "age",
|
||||||
condition = "condition",
|
condition = "condition",
|
||||||
@ -55,14 +56,16 @@ export class Deployments extends React.Component<Props> {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<KubeObjectListLayout
|
<KubeObjectListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="workload_deployments"
|
||||||
className="Deployments" store={deploymentStore}
|
className="Deployments" store={deploymentStore}
|
||||||
dependentStores={[replicaSetStore, podsStore, nodesStore, eventStore]}
|
dependentStores={[replicaSetStore, podsStore, nodesStore, eventStore]}
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.name]: (deployment: Deployment) => deployment.getName(),
|
[columnId.name]: (deployment: Deployment) => deployment.getName(),
|
||||||
[sortBy.namespace]: (deployment: Deployment) => deployment.getNs(),
|
[columnId.namespace]: (deployment: Deployment) => deployment.getNs(),
|
||||||
[sortBy.replicas]: (deployment: Deployment) => deployment.getReplicas(),
|
[columnId.replicas]: (deployment: Deployment) => deployment.getReplicas(),
|
||||||
[sortBy.age]: (deployment: Deployment) => deployment.metadata.creationTimestamp,
|
[columnId.age]: (deployment: Deployment) => deployment.metadata.creationTimestamp,
|
||||||
[sortBy.condition]: (deployment: Deployment) => deployment.getConditionsText(),
|
[columnId.condition]: (deployment: Deployment) => deployment.getConditionsText(),
|
||||||
}}
|
}}
|
||||||
searchFilters={[
|
searchFilters={[
|
||||||
(deployment: Deployment) => deployment.getSearchFields(),
|
(deployment: Deployment) => deployment.getSearchFields(),
|
||||||
@ -70,13 +73,13 @@ export class Deployments extends React.Component<Props> {
|
|||||||
]}
|
]}
|
||||||
renderHeaderTitle="Deployments"
|
renderHeaderTitle="Deployments"
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||||
{ className: "warning" },
|
{ className: "warning", showWithColumn: columnId.name },
|
||||||
{ title: "Namespace", className: "namespace", sortBy: sortBy.namespace },
|
{ title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace },
|
||||||
{ title: "Pods", className: "pods" },
|
{ title: "Pods", className: "pods", id: columnId.pods },
|
||||||
{ title: "Replicas", className: "replicas", sortBy: sortBy.replicas },
|
{ title: "Replicas", className: "replicas", sortBy: columnId.replicas, id: columnId.replicas },
|
||||||
{ title: "Age", className: "age", sortBy: sortBy.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
{ title: "Conditions", className: "conditions", sortBy: sortBy.condition },
|
{ title: "Conditions", className: "conditions", sortBy: columnId.condition, id: columnId.condition },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(deployment: Deployment) => [
|
renderTableContents={(deployment: Deployment) => [
|
||||||
deployment.getName(),
|
deployment.getName(),
|
||||||
|
|||||||
@ -10,7 +10,7 @@ export class JobStore extends KubeObjectStore<Job> {
|
|||||||
api = jobApi;
|
api = jobApi;
|
||||||
|
|
||||||
getChildPods(job: Job): Pod[] {
|
getChildPods(job: Job): Pod[] {
|
||||||
return podsStore.getPodsByOwner(job);
|
return podsStore.getPodsByOwnerId(job.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
getJobsByOwner(cronJob: CronJob) {
|
getJobsByOwner(cronJob: CronJob) {
|
||||||
|
|||||||
@ -12,9 +12,10 @@ import { IJobsRouteParams } from "../+workloads";
|
|||||||
import kebabCase from "lodash/kebabCase";
|
import kebabCase from "lodash/kebabCase";
|
||||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
namespace = "namespace",
|
namespace = "namespace",
|
||||||
|
completions = "completions",
|
||||||
conditions = "conditions",
|
conditions = "conditions",
|
||||||
age = "age",
|
age = "age",
|
||||||
}
|
}
|
||||||
@ -27,25 +28,27 @@ export class Jobs extends React.Component<Props> {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<KubeObjectListLayout
|
<KubeObjectListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="workload_jobs"
|
||||||
className="Jobs" store={jobStore}
|
className="Jobs" store={jobStore}
|
||||||
dependentStores={[podsStore, eventStore]}
|
dependentStores={[podsStore, eventStore]}
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.name]: (job: Job) => job.getName(),
|
[columnId.name]: (job: Job) => job.getName(),
|
||||||
[sortBy.namespace]: (job: Job) => job.getNs(),
|
[columnId.namespace]: (job: Job) => job.getNs(),
|
||||||
[sortBy.conditions]: (job: Job) => job.getCondition() != null ? job.getCondition().type : "",
|
[columnId.conditions]: (job: Job) => job.getCondition() != null ? job.getCondition().type : "",
|
||||||
[sortBy.age]: (job: Job) => job.metadata.creationTimestamp,
|
[columnId.age]: (job: Job) => job.metadata.creationTimestamp,
|
||||||
}}
|
}}
|
||||||
searchFilters={[
|
searchFilters={[
|
||||||
(job: Job) => job.getSearchFields(),
|
(job: Job) => job.getSearchFields(),
|
||||||
]}
|
]}
|
||||||
renderHeaderTitle="Jobs"
|
renderHeaderTitle="Jobs"
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||||
{ title: "Namespace", className: "namespace", sortBy: sortBy.namespace },
|
{ title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace },
|
||||||
{ title: "Completions", className: "completions" },
|
{ title: "Completions", className: "completions", id: columnId.completions },
|
||||||
{ className: "warning" },
|
{ className: "warning", showWithColumn: columnId.completions },
|
||||||
{ title: "Age", className: "age", sortBy: sortBy.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
{ title: "Conditions", className: "conditions", sortBy: sortBy.conditions },
|
{ title: "Conditions", className: "conditions", sortBy: columnId.conditions, id: columnId.conditions },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(job: Job) => {
|
renderTableContents={(job: Job) => {
|
||||||
const condition = job.getCondition();
|
const condition = job.getCondition();
|
||||||
|
|||||||
@ -3,8 +3,8 @@ import { action, observable } from "mobx";
|
|||||||
import { KubeObjectStore } from "../../kube-object.store";
|
import { KubeObjectStore } from "../../kube-object.store";
|
||||||
import { autobind, cpuUnitsToNumber, unitsToBytes } from "../../utils";
|
import { autobind, cpuUnitsToNumber, unitsToBytes } from "../../utils";
|
||||||
import { IPodMetrics, Pod, PodMetrics, podMetricsApi, podsApi } from "../../api/endpoints";
|
import { IPodMetrics, Pod, PodMetrics, podMetricsApi, podsApi } from "../../api/endpoints";
|
||||||
import { WorkloadKubeObject } from "../../api/workload-kube-object";
|
|
||||||
import { apiManager } from "../../api/api-manager";
|
import { apiManager } from "../../api/api-manager";
|
||||||
|
import { WorkloadKubeObject } from "../../api/workload-kube-object";
|
||||||
|
|
||||||
@autobind()
|
@autobind()
|
||||||
export class PodsStore extends KubeObjectStore<Pod> {
|
export class PodsStore extends KubeObjectStore<Pod> {
|
||||||
@ -44,6 +44,12 @@ export class PodsStore extends KubeObjectStore<Pod> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getPodsByOwnerId(workloadId: string): Pod[] {
|
||||||
|
return this.items.filter(pod => {
|
||||||
|
return pod.getOwnerRefs().find(owner => owner.uid === workloadId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
getPodsByNode(node: string) {
|
getPodsByNode(node: string) {
|
||||||
if (!this.isLoaded) return [];
|
if (!this.isLoaded) return [];
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,7 @@ export class ReplicaSetStore extends KubeObjectStore<ReplicaSet> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getChildPods(replicaSet: ReplicaSet) {
|
getChildPods(replicaSet: ReplicaSet) {
|
||||||
return podsStore.getPodsByOwner(replicaSet);
|
return podsStore.getPodsByOwnerId(replicaSet.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
getStatuses(replicaSets: ReplicaSet[]) {
|
getStatuses(replicaSets: ReplicaSet[]) {
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import { Icon } from "../icon/icon";
|
|||||||
import { kubeObjectMenuRegistry } from "../../../extensions/registries/kube-object-menu-registry";
|
import { kubeObjectMenuRegistry } from "../../../extensions/registries/kube-object-menu-registry";
|
||||||
import { ReplicaSetScaleDialog } from "./replicaset-scale-dialog";
|
import { ReplicaSetScaleDialog } from "./replicaset-scale-dialog";
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
namespace = "namespace",
|
namespace = "namespace",
|
||||||
desired = "desired",
|
desired = "desired",
|
||||||
@ -31,27 +31,29 @@ export class ReplicaSets extends React.Component<Props> {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<KubeObjectListLayout
|
<KubeObjectListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="workload_replicasets"
|
||||||
className="ReplicaSets" store={replicaSetStore}
|
className="ReplicaSets" store={replicaSetStore}
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.name]: (replicaSet: ReplicaSet) => replicaSet.getName(),
|
[columnId.name]: (replicaSet: ReplicaSet) => replicaSet.getName(),
|
||||||
[sortBy.namespace]: (replicaSet: ReplicaSet) => replicaSet.getNs(),
|
[columnId.namespace]: (replicaSet: ReplicaSet) => replicaSet.getNs(),
|
||||||
[sortBy.desired]: (replicaSet: ReplicaSet) => replicaSet.getDesired(),
|
[columnId.desired]: (replicaSet: ReplicaSet) => replicaSet.getDesired(),
|
||||||
[sortBy.current]: (replicaSet: ReplicaSet) => replicaSet.getCurrent(),
|
[columnId.current]: (replicaSet: ReplicaSet) => replicaSet.getCurrent(),
|
||||||
[sortBy.ready]: (replicaSet: ReplicaSet) => replicaSet.getReady(),
|
[columnId.ready]: (replicaSet: ReplicaSet) => replicaSet.getReady(),
|
||||||
[sortBy.age]: (replicaSet: ReplicaSet) => replicaSet.metadata.creationTimestamp,
|
[columnId.age]: (replicaSet: ReplicaSet) => replicaSet.metadata.creationTimestamp,
|
||||||
}}
|
}}
|
||||||
searchFilters={[
|
searchFilters={[
|
||||||
(replicaSet: ReplicaSet) => replicaSet.getSearchFields(),
|
(replicaSet: ReplicaSet) => replicaSet.getSearchFields(),
|
||||||
]}
|
]}
|
||||||
renderHeaderTitle="Replica Sets"
|
renderHeaderTitle="Replica Sets"
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||||
{ className: "warning" },
|
{ className: "warning", showWithColumn: columnId.name },
|
||||||
{ title: "Namespace", className: "namespace", sortBy: sortBy.namespace },
|
{ title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace },
|
||||||
{ title: "Desired", className: "desired", sortBy: sortBy.desired },
|
{ title: "Desired", className: "desired", sortBy: columnId.desired, id: columnId.desired },
|
||||||
{ title: "Current", className: "current", sortBy: sortBy.current },
|
{ title: "Current", className: "current", sortBy: columnId.current, id: columnId.current },
|
||||||
{ title: "Ready", className: "ready", sortBy: sortBy.ready },
|
{ title: "Ready", className: "ready", sortBy: columnId.ready, id: columnId.ready },
|
||||||
{ title: "Age", className: "age", sortBy: sortBy.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(replicaSet: ReplicaSet) => [
|
renderTableContents={(replicaSet: ReplicaSet) => [
|
||||||
replicaSet.getName(),
|
replicaSet.getName(),
|
||||||
|
|||||||
@ -17,7 +17,7 @@ export class StatefulSetStore extends KubeObjectStore<StatefulSet> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getChildPods(statefulSet: StatefulSet) {
|
getChildPods(statefulSet: StatefulSet) {
|
||||||
return podsStore.getPodsByOwner(statefulSet);
|
return podsStore.getPodsByOwnerId(statefulSet.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
getStatuses(statefulSets: StatefulSet[]) {
|
getStatuses(statefulSets: StatefulSet[]) {
|
||||||
|
|||||||
@ -17,9 +17,10 @@ import { MenuItem } from "../menu/menu";
|
|||||||
import { Icon } from "../icon/icon";
|
import { Icon } from "../icon/icon";
|
||||||
import { kubeObjectMenuRegistry } from "../../../extensions/registries/kube-object-menu-registry";
|
import { kubeObjectMenuRegistry } from "../../../extensions/registries/kube-object-menu-registry";
|
||||||
|
|
||||||
enum sortBy {
|
enum columnId {
|
||||||
name = "name",
|
name = "name",
|
||||||
namespace = "namespace",
|
namespace = "namespace",
|
||||||
|
pods = "pods",
|
||||||
age = "age",
|
age = "age",
|
||||||
replicas = "replicas",
|
replicas = "replicas",
|
||||||
}
|
}
|
||||||
@ -38,25 +39,27 @@ export class StatefulSets extends React.Component<Props> {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<KubeObjectListLayout
|
<KubeObjectListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="workload_statefulsets"
|
||||||
className="StatefulSets" store={statefulSetStore}
|
className="StatefulSets" store={statefulSetStore}
|
||||||
dependentStores={[podsStore, nodesStore, eventStore]}
|
dependentStores={[podsStore, nodesStore, eventStore]}
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.name]: (statefulSet: StatefulSet) => statefulSet.getName(),
|
[columnId.name]: (statefulSet: StatefulSet) => statefulSet.getName(),
|
||||||
[sortBy.namespace]: (statefulSet: StatefulSet) => statefulSet.getNs(),
|
[columnId.namespace]: (statefulSet: StatefulSet) => statefulSet.getNs(),
|
||||||
[sortBy.age]: (statefulSet: StatefulSet) => statefulSet.metadata.creationTimestamp,
|
[columnId.age]: (statefulSet: StatefulSet) => statefulSet.metadata.creationTimestamp,
|
||||||
[sortBy.replicas]: (statefulSet: StatefulSet) => statefulSet.getReplicas(),
|
[columnId.replicas]: (statefulSet: StatefulSet) => statefulSet.getReplicas(),
|
||||||
}}
|
}}
|
||||||
searchFilters={[
|
searchFilters={[
|
||||||
(statefulSet: StatefulSet) => statefulSet.getSearchFields(),
|
(statefulSet: StatefulSet) => statefulSet.getSearchFields(),
|
||||||
]}
|
]}
|
||||||
renderHeaderTitle="Stateful Sets"
|
renderHeaderTitle="Stateful Sets"
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||||
{ title: "Namespace", className: "namespace", sortBy: sortBy.namespace },
|
{ title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace },
|
||||||
{ title: "Pods", className: "pods" },
|
{ title: "Pods", className: "pods", id: columnId.pods },
|
||||||
{ title: "Replicas", className: "replicas", sortBy: sortBy.replicas },
|
{ title: "Replicas", className: "replicas", sortBy: columnId.replicas, id: columnId.replicas },
|
||||||
{ className: "warning" },
|
{ className: "warning", showWithColumn: columnId.replicas },
|
||||||
{ title: "Age", className: "age", sortBy: sortBy.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(statefulSet: StatefulSet) => [
|
renderTableContents={(statefulSet: StatefulSet) => [
|
||||||
statefulSet.getName(),
|
statefulSet.getName(),
|
||||||
|
|||||||
@ -42,7 +42,7 @@ import { ClusterPageMenuRegistration, clusterPageMenuRegistry } from "../../exte
|
|||||||
import { TabLayout, TabLayoutRoute } from "./layout/tab-layout";
|
import { TabLayout, TabLayoutRoute } from "./layout/tab-layout";
|
||||||
import { StatefulSetScaleDialog } from "./+workloads-statefulsets/statefulset-scale-dialog";
|
import { StatefulSetScaleDialog } from "./+workloads-statefulsets/statefulset-scale-dialog";
|
||||||
import { eventStore } from "./+events/event.store";
|
import { eventStore } from "./+events/event.store";
|
||||||
import { computed, reaction } from "mobx";
|
import { reaction, computed, observable } from "mobx";
|
||||||
import { nodesStore } from "./+nodes/nodes.store";
|
import { nodesStore } from "./+nodes/nodes.store";
|
||||||
import { podsStore } from "./+workloads-pods/pods.store";
|
import { podsStore } from "./+workloads-pods/pods.store";
|
||||||
import { sum } from "lodash";
|
import { sum } from "lodash";
|
||||||
@ -75,6 +75,8 @@ export class App extends React.Component {
|
|||||||
whatInput.ask(); // Start to monitor user input device
|
whatInput.ask(); // Start to monitor user input device
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@observable extensionRoutes: Map<ClusterPageMenuRegistration, React.ReactNode> = new Map();
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
const cluster = getHostedCluster();
|
const cluster = getHostedCluster();
|
||||||
const promises: Promise<void>[] = [];
|
const promises: Promise<void>[] = [];
|
||||||
@ -101,6 +103,12 @@ export class App extends React.Component {
|
|||||||
reaction(() => this.warningsCount, (count) => {
|
reaction(() => this.warningsCount, (count) => {
|
||||||
broadcastMessage(`cluster-warning-event-count:${cluster.id}`, count);
|
broadcastMessage(`cluster-warning-event-count:${cluster.id}`, count);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
reaction(() => clusterPageMenuRegistry.getRootItems(), (rootItems) => {
|
||||||
|
this.generateExtensionTabLayoutRoutes(rootItems);
|
||||||
|
}, {
|
||||||
|
fireImmediately: true
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
@ -143,22 +151,38 @@ export class App extends React.Component {
|
|||||||
return routes;
|
return routes;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderExtensionTabLayoutRoutes() {
|
generateExtensionTabLayoutRoutes(rootItems: ClusterPageMenuRegistration[]) {
|
||||||
return clusterPageMenuRegistry.getRootItems().map((menu, index) => {
|
rootItems.forEach((menu, index) => {
|
||||||
const tabRoutes = this.getTabLayoutRoutes(menu);
|
let route = this.extensionRoutes.get(menu);
|
||||||
|
|
||||||
if (tabRoutes.length > 0) {
|
if (!route) {
|
||||||
const pageComponent = () => <TabLayout tabs={tabRoutes}/>;
|
const tabRoutes = this.getTabLayoutRoutes(menu);
|
||||||
|
|
||||||
return <Route key={`extension-tab-layout-route-${index}`} component={pageComponent} path={tabRoutes.map((tab) => tab.routePath)}/>;
|
if (tabRoutes.length > 0) {
|
||||||
} else {
|
const pageComponent = () => <TabLayout tabs={tabRoutes} />;
|
||||||
const page = clusterPageRegistry.getByPageTarget(menu.target);
|
|
||||||
|
|
||||||
if (page) {
|
route = <Route key={`extension-tab-layout-route-${index}`} component={pageComponent} path={tabRoutes.map((tab) => tab.routePath)} />;
|
||||||
return <Route key={`extension-tab-layout-route-${index}`} path={page.url} component={page.components.Page}/>;
|
this.extensionRoutes.set(menu, route);
|
||||||
|
} else {
|
||||||
|
const page = clusterPageRegistry.getByPageTarget(menu.target);
|
||||||
|
|
||||||
|
if (page) {
|
||||||
|
route = <Route key={`extension-tab-layout-route-${index}`} path={page.url} component={page.components.Page}/>;
|
||||||
|
this.extensionRoutes.set(menu, route);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
for (const menu of this.extensionRoutes.keys()) {
|
||||||
|
if (!rootItems.includes(menu)) {
|
||||||
|
this.extensionRoutes.delete(menu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderExtensionTabLayoutRoutes() {
|
||||||
|
return Array.from(this.extensionRoutes.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
renderExtensionRoutes() {
|
renderExtensionRoutes() {
|
||||||
|
|||||||
@ -4,8 +4,6 @@ import "@testing-library/jest-dom/extend-expect";
|
|||||||
|
|
||||||
import { DockTabs } from "../dock-tabs";
|
import { DockTabs } from "../dock-tabs";
|
||||||
import { dockStore, IDockTab, TabKind } from "../dock.store";
|
import { dockStore, IDockTab, TabKind } from "../dock.store";
|
||||||
import { createResourceTab } from "../create-resource.store";
|
|
||||||
import { createTerminalTab } from "../terminal.store";
|
|
||||||
import { observable } from "mobx";
|
import { observable } from "mobx";
|
||||||
|
|
||||||
const onChangeTab = jest.fn();
|
const onChangeTab = jest.fn();
|
||||||
@ -25,11 +23,19 @@ const getTabKinds = () => dockStore.tabs.map(tab => tab.kind);
|
|||||||
|
|
||||||
describe("<DockTabs />", () => {
|
describe("<DockTabs />", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
createTerminalTab();
|
const terminalTab: IDockTab = { id: "terminal1", kind: TabKind.TERMINAL, title: "Terminal" };
|
||||||
createResourceTab();
|
const createResourceTab: IDockTab = { id: "create", kind: TabKind.CREATE_RESOURCE, title: "Create resource" };
|
||||||
createTerminalTab();
|
const editResourceTab: IDockTab = { id: "edit", kind: TabKind.EDIT_RESOURCE, title: "Edit resource" };
|
||||||
createResourceTab();
|
const installChartTab: IDockTab = { id: "install", kind: TabKind.INSTALL_CHART, title: "Install chart" };
|
||||||
createTerminalTab();
|
const logsTab: IDockTab = { id: "logs", kind: TabKind.POD_LOGS, title: "Logs" };
|
||||||
|
|
||||||
|
dockStore.tabs.push(
|
||||||
|
terminalTab,
|
||||||
|
createResourceTab,
|
||||||
|
editResourceTab,
|
||||||
|
installChartTab,
|
||||||
|
logsTab
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -72,9 +78,9 @@ describe("<DockTabs />", () => {
|
|||||||
expect(getTabKinds()).toEqual([
|
expect(getTabKinds()).toEqual([
|
||||||
TabKind.TERMINAL,
|
TabKind.TERMINAL,
|
||||||
TabKind.CREATE_RESOURCE,
|
TabKind.CREATE_RESOURCE,
|
||||||
TabKind.TERMINAL,
|
TabKind.EDIT_RESOURCE,
|
||||||
TabKind.CREATE_RESOURCE,
|
TabKind.INSTALL_CHART,
|
||||||
TabKind.TERMINAL
|
TabKind.POD_LOGS
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -90,7 +96,7 @@ describe("<DockTabs />", () => {
|
|||||||
const tabs = container.querySelectorAll(".Tab");
|
const tabs = container.querySelectorAll(".Tab");
|
||||||
|
|
||||||
expect(tabs.length).toBe(1);
|
expect(tabs.length).toBe(1);
|
||||||
expect(getTabKinds()).toEqual([TabKind.TERMINAL]);
|
expect(getTabKinds()).toEqual([TabKind.EDIT_RESOURCE]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("closes all tabs", () => {
|
it("closes all tabs", () => {
|
||||||
@ -123,7 +129,7 @@ describe("<DockTabs />", () => {
|
|||||||
TabKind.TERMINAL,
|
TabKind.TERMINAL,
|
||||||
TabKind.TERMINAL,
|
TabKind.TERMINAL,
|
||||||
TabKind.CREATE_RESOURCE,
|
TabKind.CREATE_RESOURCE,
|
||||||
TabKind.TERMINAL
|
TabKind.EDIT_RESOURCE
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,103 @@
|
|||||||
|
/**
|
||||||
|
* @jest-environment jsdom
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import "@testing-library/jest-dom/extend-expect";
|
||||||
|
import { render } from "@testing-library/react";
|
||||||
|
import selectEvent from "react-select-event";
|
||||||
|
|
||||||
|
import { Pod } from "../../../api/endpoints";
|
||||||
|
import { LogResourceSelector } from "../log-resource-selector";
|
||||||
|
import { LogTabData } from "../log-tab.store";
|
||||||
|
import { dockerPod, deploymentPod1 } from "./pod.mock";
|
||||||
|
|
||||||
|
const getComponent = (tabData: LogTabData) => {
|
||||||
|
return (
|
||||||
|
<LogResourceSelector
|
||||||
|
tabId="tabId"
|
||||||
|
tabData={tabData}
|
||||||
|
save={jest.fn()}
|
||||||
|
reload={jest.fn()}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getOnePodTabData = (): LogTabData => {
|
||||||
|
const selectedPod = new Pod(dockerPod);
|
||||||
|
|
||||||
|
return {
|
||||||
|
pods: [] as Pod[],
|
||||||
|
selectedPod,
|
||||||
|
selectedContainer: selectedPod.getContainers()[0],
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const getFewPodsTabData = (): LogTabData => {
|
||||||
|
const selectedPod = new Pod(deploymentPod1);
|
||||||
|
const anotherPod = new Pod(dockerPod);
|
||||||
|
|
||||||
|
return {
|
||||||
|
pods: [anotherPod],
|
||||||
|
selectedPod,
|
||||||
|
selectedContainer: selectedPod.getContainers()[0],
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
describe("<LogResourceSelector />", () => {
|
||||||
|
it("renders w/o errors", () => {
|
||||||
|
const tabData = getOnePodTabData();
|
||||||
|
const { container } = render(getComponent(tabData));
|
||||||
|
|
||||||
|
expect(container).toBeInstanceOf(HTMLElement);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders proper namespace", () => {
|
||||||
|
const tabData = getOnePodTabData();
|
||||||
|
const { getByTestId } = render(getComponent(tabData));
|
||||||
|
const ns = getByTestId("namespace-badge");
|
||||||
|
|
||||||
|
expect(ns).toHaveTextContent("default");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders proper selected items within dropdowns", () => {
|
||||||
|
const tabData = getOnePodTabData();
|
||||||
|
const { getByText } = render(getComponent(tabData));
|
||||||
|
|
||||||
|
expect(getByText("dockerExporter")).toBeInTheDocument();
|
||||||
|
expect(getByText("docker-exporter")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders sibling pods in dropdown", () => {
|
||||||
|
const tabData = getFewPodsTabData();
|
||||||
|
const { container, getByText } = render(getComponent(tabData));
|
||||||
|
const podSelector: HTMLElement = container.querySelector(".pod-selector");
|
||||||
|
|
||||||
|
selectEvent.openMenu(podSelector);
|
||||||
|
|
||||||
|
expect(getByText("dockerExporter")).toBeInTheDocument();
|
||||||
|
expect(getByText("deploymentPod1")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders sibling containers in dropdown", () => {
|
||||||
|
const tabData = getFewPodsTabData();
|
||||||
|
const { getByText, container } = render(getComponent(tabData));
|
||||||
|
const containerSelector: HTMLElement = container.querySelector(".container-selector");
|
||||||
|
|
||||||
|
selectEvent.openMenu(containerSelector);
|
||||||
|
|
||||||
|
expect(getByText("node-exporter-1")).toBeInTheDocument();
|
||||||
|
expect(getByText("init-node-exporter")).toBeInTheDocument();
|
||||||
|
expect(getByText("init-node-exporter-1")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders pod owner as dropdown title", () => {
|
||||||
|
const tabData = getFewPodsTabData();
|
||||||
|
const { getByText, container } = render(getComponent(tabData));
|
||||||
|
const podSelector: HTMLElement = container.querySelector(".pod-selector");
|
||||||
|
|
||||||
|
selectEvent.openMenu(podSelector);
|
||||||
|
|
||||||
|
expect(getByText("super-deployment")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
113
src/renderer/components/dock/__test__/log-tab.store.test.ts
Normal file
113
src/renderer/components/dock/__test__/log-tab.store.test.ts
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
/**
|
||||||
|
* @jest-environment jsdom
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { podsStore } from "../../+workloads-pods/pods.store";
|
||||||
|
import { Pod } from "../../../api/endpoints";
|
||||||
|
import { dockStore } from "../dock.store";
|
||||||
|
import { logTabStore } from "../log-tab.store";
|
||||||
|
import { deploymentPod1, deploymentPod2, deploymentPod3, dockerPod } from "./pod.mock";
|
||||||
|
|
||||||
|
|
||||||
|
podsStore.items.push(new Pod(dockerPod));
|
||||||
|
podsStore.items.push(new Pod(deploymentPod1));
|
||||||
|
podsStore.items.push(new Pod(deploymentPod2));
|
||||||
|
|
||||||
|
describe("log tab store", () => {
|
||||||
|
afterEach(() => {
|
||||||
|
logTabStore.reset();
|
||||||
|
dockStore.reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("creates log tab without sibling pods", () => {
|
||||||
|
const selectedPod = new Pod(dockerPod);
|
||||||
|
const selectedContainer = selectedPod.getAllContainers()[0];
|
||||||
|
|
||||||
|
logTabStore.createPodTab({
|
||||||
|
selectedPod,
|
||||||
|
selectedContainer
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(logTabStore.getData(dockStore.selectedTabId)).toEqual({
|
||||||
|
pods: [selectedPod],
|
||||||
|
selectedPod,
|
||||||
|
selectedContainer,
|
||||||
|
showTimestamps: false,
|
||||||
|
previous: false
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("creates log tab with sibling pods", () => {
|
||||||
|
const selectedPod = new Pod(deploymentPod1);
|
||||||
|
const siblingPod = new Pod(deploymentPod2);
|
||||||
|
const selectedContainer = selectedPod.getInitContainers()[0];
|
||||||
|
|
||||||
|
logTabStore.createPodTab({
|
||||||
|
selectedPod,
|
||||||
|
selectedContainer
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(logTabStore.getData(dockStore.selectedTabId)).toEqual({
|
||||||
|
pods: [selectedPod, siblingPod],
|
||||||
|
selectedPod,
|
||||||
|
selectedContainer,
|
||||||
|
showTimestamps: false,
|
||||||
|
previous: false
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("removes item from pods list if pod deleted from store", () => {
|
||||||
|
const selectedPod = new Pod(deploymentPod1);
|
||||||
|
const selectedContainer = selectedPod.getInitContainers()[0];
|
||||||
|
|
||||||
|
logTabStore.createPodTab({
|
||||||
|
selectedPod,
|
||||||
|
selectedContainer
|
||||||
|
});
|
||||||
|
|
||||||
|
podsStore.items.pop();
|
||||||
|
|
||||||
|
expect(logTabStore.getData(dockStore.selectedTabId)).toEqual({
|
||||||
|
pods: [selectedPod],
|
||||||
|
selectedPod,
|
||||||
|
selectedContainer,
|
||||||
|
showTimestamps: false,
|
||||||
|
previous: false
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("adds item into pods list if new sibling pod added to store", () => {
|
||||||
|
const selectedPod = new Pod(deploymentPod1);
|
||||||
|
const selectedContainer = selectedPod.getInitContainers()[0];
|
||||||
|
|
||||||
|
logTabStore.createPodTab({
|
||||||
|
selectedPod,
|
||||||
|
selectedContainer
|
||||||
|
});
|
||||||
|
|
||||||
|
podsStore.items.push(new Pod(deploymentPod3));
|
||||||
|
|
||||||
|
expect(logTabStore.getData(dockStore.selectedTabId)).toEqual({
|
||||||
|
pods: [selectedPod, deploymentPod3],
|
||||||
|
selectedPod,
|
||||||
|
selectedContainer,
|
||||||
|
showTimestamps: false,
|
||||||
|
previous: false
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("closes tab if no pods left in store", () => {
|
||||||
|
const selectedPod = new Pod(deploymentPod1);
|
||||||
|
const selectedContainer = selectedPod.getInitContainers()[0];
|
||||||
|
|
||||||
|
logTabStore.createPodTab({
|
||||||
|
selectedPod,
|
||||||
|
selectedContainer
|
||||||
|
});
|
||||||
|
|
||||||
|
podsStore.items.clear();
|
||||||
|
|
||||||
|
expect(logTabStore.getData(dockStore.selectedTabId)).toBeUndefined();
|
||||||
|
expect(dockStore.getTabById(dockStore.selectedTabId)).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
203
src/renderer/components/dock/__test__/pod.mock.ts
Normal file
203
src/renderer/components/dock/__test__/pod.mock.ts
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
export const dockerPod = {
|
||||||
|
apiVersion: "v1",
|
||||||
|
kind: "dummy",
|
||||||
|
metadata: {
|
||||||
|
uid: "dockerExporter",
|
||||||
|
name: "dockerExporter",
|
||||||
|
creationTimestamp: "dummy",
|
||||||
|
resourceVersion: "dummy",
|
||||||
|
namespace: "default"
|
||||||
|
},
|
||||||
|
spec: {
|
||||||
|
initContainers: [] as any,
|
||||||
|
containers: [
|
||||||
|
{
|
||||||
|
name: "docker-exporter",
|
||||||
|
image: "docker.io/prom/node-exporter:v1.0.0-rc.0",
|
||||||
|
imagePullPolicy: "pull"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
serviceAccountName: "dummy",
|
||||||
|
serviceAccount: "dummy",
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
phase: "Running",
|
||||||
|
conditions: [{
|
||||||
|
type: "Running",
|
||||||
|
status: "Running",
|
||||||
|
lastProbeTime: 1,
|
||||||
|
lastTransitionTime: "Some time",
|
||||||
|
}],
|
||||||
|
hostIP: "dummy",
|
||||||
|
podIP: "dummy",
|
||||||
|
startTime: "dummy",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deploymentPod1 = {
|
||||||
|
apiVersion: "v1",
|
||||||
|
kind: "dummy",
|
||||||
|
metadata: {
|
||||||
|
uid: "deploymentPod1",
|
||||||
|
name: "deploymentPod1",
|
||||||
|
creationTimestamp: "dummy",
|
||||||
|
resourceVersion: "dummy",
|
||||||
|
namespace: "default",
|
||||||
|
ownerReferences: [{
|
||||||
|
apiVersion: "v1",
|
||||||
|
kind: "Deployment",
|
||||||
|
name: "super-deployment",
|
||||||
|
uid: "uuid",
|
||||||
|
controller: true,
|
||||||
|
blockOwnerDeletion: true,
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
spec: {
|
||||||
|
initContainers: [
|
||||||
|
{
|
||||||
|
name: "init-node-exporter",
|
||||||
|
image: "docker.io/prom/node-exporter:v1.0.0-rc.0",
|
||||||
|
imagePullPolicy: "pull"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "init-node-exporter-1",
|
||||||
|
image: "docker.io/prom/node-exporter:v1.0.0-rc.0",
|
||||||
|
imagePullPolicy: "pull"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
containers: [
|
||||||
|
{
|
||||||
|
name: "node-exporter",
|
||||||
|
image: "docker.io/prom/node-exporter:v1.0.0-rc.0",
|
||||||
|
imagePullPolicy: "pull"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "node-exporter-1",
|
||||||
|
image: "docker.io/prom/node-exporter:v1.0.0-rc.0",
|
||||||
|
imagePullPolicy: "pull"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
serviceAccountName: "dummy",
|
||||||
|
serviceAccount: "dummy",
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
phase: "Running",
|
||||||
|
conditions: [{
|
||||||
|
type: "Running",
|
||||||
|
status: "Running",
|
||||||
|
lastProbeTime: 1,
|
||||||
|
lastTransitionTime: "Some time",
|
||||||
|
}],
|
||||||
|
hostIP: "dummy",
|
||||||
|
podIP: "dummy",
|
||||||
|
startTime: "dummy",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deploymentPod2 = {
|
||||||
|
apiVersion: "v1",
|
||||||
|
kind: "dummy",
|
||||||
|
metadata: {
|
||||||
|
uid: "deploymentPod2",
|
||||||
|
name: "deploymentPod2",
|
||||||
|
creationTimestamp: "dummy",
|
||||||
|
resourceVersion: "dummy",
|
||||||
|
namespace: "default",
|
||||||
|
ownerReferences: [{
|
||||||
|
apiVersion: "v1",
|
||||||
|
kind: "Deployment",
|
||||||
|
name: "super-deployment",
|
||||||
|
uid: "uuid",
|
||||||
|
controller: true,
|
||||||
|
blockOwnerDeletion: true,
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
spec: {
|
||||||
|
initContainers: [
|
||||||
|
{
|
||||||
|
name: "init-node-exporter",
|
||||||
|
image: "docker.io/prom/node-exporter:v1.0.0-rc.0",
|
||||||
|
imagePullPolicy: "pull"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "init-node-exporter-1",
|
||||||
|
image: "docker.io/prom/node-exporter:v1.0.0-rc.0",
|
||||||
|
imagePullPolicy: "pull"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
containers: [
|
||||||
|
{
|
||||||
|
name: "node-exporter",
|
||||||
|
image: "docker.io/prom/node-exporter:v1.0.0-rc.0",
|
||||||
|
imagePullPolicy: "pull"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "node-exporter-1",
|
||||||
|
image: "docker.io/prom/node-exporter:v1.0.0-rc.0",
|
||||||
|
imagePullPolicy: "pull"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
serviceAccountName: "dummy",
|
||||||
|
serviceAccount: "dummy",
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
phase: "Running",
|
||||||
|
conditions: [{
|
||||||
|
type: "Running",
|
||||||
|
status: "Running",
|
||||||
|
lastProbeTime: 1,
|
||||||
|
lastTransitionTime: "Some time",
|
||||||
|
}],
|
||||||
|
hostIP: "dummy",
|
||||||
|
podIP: "dummy",
|
||||||
|
startTime: "dummy",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deploymentPod3 = {
|
||||||
|
apiVersion: "v1",
|
||||||
|
kind: "dummy",
|
||||||
|
metadata: {
|
||||||
|
uid: "deploymentPod3",
|
||||||
|
name: "deploymentPod3",
|
||||||
|
creationTimestamp: "dummy",
|
||||||
|
resourceVersion: "dummy",
|
||||||
|
namespace: "default",
|
||||||
|
ownerReferences: [{
|
||||||
|
apiVersion: "v1",
|
||||||
|
kind: "Deployment",
|
||||||
|
name: "super-deployment",
|
||||||
|
uid: "uuid",
|
||||||
|
controller: true,
|
||||||
|
blockOwnerDeletion: true,
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
spec: {
|
||||||
|
containers: [
|
||||||
|
{
|
||||||
|
name: "node-exporter",
|
||||||
|
image: "docker.io/prom/node-exporter:v1.0.0-rc.0",
|
||||||
|
imagePullPolicy: "pull"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "node-exporter-1",
|
||||||
|
image: "docker.io/prom/node-exporter:v1.0.0-rc.0",
|
||||||
|
imagePullPolicy: "pull"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
serviceAccountName: "dummy",
|
||||||
|
serviceAccount: "dummy",
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
phase: "Running",
|
||||||
|
conditions: [{
|
||||||
|
type: "Running",
|
||||||
|
status: "Running",
|
||||||
|
lastProbeTime: 1,
|
||||||
|
lastTransitionTime: "Some time",
|
||||||
|
}],
|
||||||
|
hostIP: "dummy",
|
||||||
|
podIP: "dummy",
|
||||||
|
startTime: "dummy",
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -7,7 +7,7 @@ import { DockTab } from "./dock-tab";
|
|||||||
import { IDockTab } from "./dock.store";
|
import { IDockTab } from "./dock.store";
|
||||||
import { isEditResourceTab } from "./edit-resource.store";
|
import { isEditResourceTab } from "./edit-resource.store";
|
||||||
import { isInstallChartTab } from "./install-chart.store";
|
import { isInstallChartTab } from "./install-chart.store";
|
||||||
import { isLogsTab } from "./log.store";
|
import { isLogsTab } from "./log-tab.store";
|
||||||
import { TerminalTab } from "./terminal-tab";
|
import { TerminalTab } from "./terminal-tab";
|
||||||
import { isTerminalTab } from "./terminal.store";
|
import { isTerminalTab } from "./terminal.store";
|
||||||
import { isUpgradeChartTab } from "./upgrade-chart.store";
|
import { isUpgradeChartTab } from "./upgrade-chart.store";
|
||||||
|
|||||||
@ -208,6 +208,12 @@ export class DockStore {
|
|||||||
this.closeTabs(tabs);
|
this.closeTabs(tabs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renameTab(tabId: TabId, title: string) {
|
||||||
|
const tab = this.getTabById(tabId);
|
||||||
|
|
||||||
|
tab.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
selectTab(tabId: TabId) {
|
selectTab(tabId: TabId) {
|
||||||
this.selectedTabId = this.getTabById(tabId)?.id ?? null;
|
this.selectedTabId = this.getTabById(tabId)?.id ?? null;
|
||||||
|
|||||||
@ -17,7 +17,7 @@ import { isEditResourceTab } from "./edit-resource.store";
|
|||||||
import { InstallChart } from "./install-chart";
|
import { InstallChart } from "./install-chart";
|
||||||
import { isInstallChartTab } from "./install-chart.store";
|
import { isInstallChartTab } from "./install-chart.store";
|
||||||
import { Logs } from "./logs";
|
import { Logs } from "./logs";
|
||||||
import { isLogsTab } from "./log.store";
|
import { isLogsTab } from "./log-tab.store";
|
||||||
import { TerminalWindow } from "./terminal-window";
|
import { TerminalWindow } from "./terminal-window";
|
||||||
import { createTerminalTab, isTerminalTab } from "./terminal.store";
|
import { createTerminalTab, isTerminalTab } from "./terminal.store";
|
||||||
import { UpgradeChart } from "./upgrade-chart";
|
import { UpgradeChart } from "./upgrade-chart";
|
||||||
|
|||||||
@ -5,22 +5,23 @@ import { observer } from "mobx-react";
|
|||||||
|
|
||||||
import { Pod } from "../../api/endpoints";
|
import { Pod } from "../../api/endpoints";
|
||||||
import { cssNames, saveFileDialog } from "../../utils";
|
import { cssNames, saveFileDialog } from "../../utils";
|
||||||
import { IPodLogsData, podLogsStore } from "./log.store";
|
import { logStore } from "./log.store";
|
||||||
import { Checkbox } from "../checkbox";
|
import { Checkbox } from "../checkbox";
|
||||||
import { Icon } from "../icon";
|
import { Icon } from "../icon";
|
||||||
|
import { LogTabData } from "./log-tab.store";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
tabData: IPodLogsData
|
tabData: LogTabData
|
||||||
logs: string[]
|
logs: string[]
|
||||||
save: (data: Partial<IPodLogsData>) => void
|
save: (data: Partial<LogTabData>) => void
|
||||||
reload: () => void
|
reload: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LogControls = observer((props: Props) => {
|
export const LogControls = observer((props: Props) => {
|
||||||
const { tabData, save, reload, logs } = props;
|
const { tabData, save, reload, logs } = props;
|
||||||
const { showTimestamps, previous } = tabData;
|
const { showTimestamps, previous } = tabData;
|
||||||
const since = logs.length ? podLogsStore.getTimestamps(logs[0]) : null;
|
const since = logs.length ? logStore.getTimestamps(logs[0]) : null;
|
||||||
const pod = new Pod(tabData.pod);
|
const pod = new Pod(tabData.selectedPod);
|
||||||
|
|
||||||
const toggleTimestamps = () => {
|
const toggleTimestamps = () => {
|
||||||
save({ showTimestamps: !showTimestamps });
|
save({ showTimestamps: !showTimestamps });
|
||||||
@ -33,7 +34,7 @@ export const LogControls = observer((props: Props) => {
|
|||||||
|
|
||||||
const downloadLogs = () => {
|
const downloadLogs = () => {
|
||||||
const fileName = pod.getName();
|
const fileName = pod.getName();
|
||||||
const logsToDownload = showTimestamps ? logs : podLogsStore.logsWithoutTimestamps;
|
const logsToDownload = showTimestamps ? logs : logStore.logsWithoutTimestamps;
|
||||||
|
|
||||||
saveFileDialog(`${fileName}.log`, logsToDownload.join("\n"), "text/plain");
|
saveFileDialog(`${fileName}.log`, logsToDownload.join("\n"), "text/plain");
|
||||||
};
|
};
|
||||||
|
|||||||
@ -14,7 +14,8 @@ import { Button } from "../button";
|
|||||||
import { Icon } from "../icon";
|
import { Icon } from "../icon";
|
||||||
import { Spinner } from "../spinner";
|
import { Spinner } from "../spinner";
|
||||||
import { VirtualList } from "../virtual-list";
|
import { VirtualList } from "../virtual-list";
|
||||||
import { podLogsStore } from "./log.store";
|
import { logStore } from "./log.store";
|
||||||
|
import { logTabStore } from "./log-tab.store";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
logs: string[]
|
logs: string[]
|
||||||
@ -77,10 +78,10 @@ export class LogList extends React.Component<Props> {
|
|||||||
*/
|
*/
|
||||||
@computed
|
@computed
|
||||||
get logs() {
|
get logs() {
|
||||||
const showTimestamps = podLogsStore.getData(this.props.id).showTimestamps;
|
const showTimestamps = logTabStore.getData(this.props.id).showTimestamps;
|
||||||
|
|
||||||
if (!showTimestamps) {
|
if (!showTimestamps) {
|
||||||
return podLogsStore.logsWithoutTimestamps;
|
return logStore.logsWithoutTimestamps;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.props.logs;
|
return this.props.logs;
|
||||||
|
|||||||
@ -1,27 +1,30 @@
|
|||||||
import "./log-resource-selector.scss";
|
import "./log-resource-selector.scss";
|
||||||
|
|
||||||
import React from "react";
|
import React, { useEffect } from "react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
|
|
||||||
import { IPodContainer, Pod } from "../../api/endpoints";
|
import { Pod } from "../../api/endpoints";
|
||||||
import { Badge } from "../badge";
|
import { Badge } from "../badge";
|
||||||
import { Select, SelectOption } from "../select";
|
import { Select, SelectOption } from "../select";
|
||||||
import { IPodLogsData } from "./log.store";
|
import { LogTabData, logTabStore } from "./log-tab.store";
|
||||||
|
import { podsStore } from "../+workloads-pods/pods.store";
|
||||||
|
import { TabId } from "./dock.store";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
tabData: IPodLogsData
|
tabId: TabId
|
||||||
save: (data: Partial<IPodLogsData>) => void
|
tabData: LogTabData
|
||||||
|
save: (data: Partial<LogTabData>) => void
|
||||||
reload: () => void
|
reload: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LogResourceSelector = observer((props: Props) => {
|
export const LogResourceSelector = observer((props: Props) => {
|
||||||
const { tabData, save, reload } = props;
|
const { tabData, save, reload, tabId } = props;
|
||||||
const { selectedContainer, containers, initContainers } = tabData;
|
const { selectedPod, selectedContainer, pods } = tabData;
|
||||||
const pod = new Pod(tabData.pod);
|
const pod = new Pod(selectedPod);
|
||||||
|
const containers = pod.getContainers();
|
||||||
|
const initContainers = pod.getInitContainers();
|
||||||
|
|
||||||
const onContainerChange = (option: SelectOption) => {
|
const onContainerChange = (option: SelectOption) => {
|
||||||
const { containers, initContainers } = tabData;
|
|
||||||
|
|
||||||
save({
|
save({
|
||||||
selectedContainer: containers
|
selectedContainer: containers
|
||||||
.concat(initContainers)
|
.concat(initContainers)
|
||||||
@ -30,11 +33,18 @@ export const LogResourceSelector = observer((props: Props) => {
|
|||||||
reload();
|
reload();
|
||||||
};
|
};
|
||||||
|
|
||||||
const getSelectOptions = (containers: IPodContainer[]) => {
|
const onPodChange = (option: SelectOption) => {
|
||||||
return containers.map(container => {
|
const selectedPod = podsStore.getByName(option.value, pod.getNs());
|
||||||
|
|
||||||
|
save({ selectedPod });
|
||||||
|
logTabStore.renameTab(tabId);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getSelectOptions = (items: string[]) => {
|
||||||
|
return items.map(item => {
|
||||||
return {
|
return {
|
||||||
value: container.name,
|
value: item,
|
||||||
label: container.name
|
label: item
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -42,24 +52,43 @@ export const LogResourceSelector = observer((props: Props) => {
|
|||||||
const containerSelectOptions = [
|
const containerSelectOptions = [
|
||||||
{
|
{
|
||||||
label: `Containers`,
|
label: `Containers`,
|
||||||
options: getSelectOptions(containers)
|
options: getSelectOptions(containers.map(container => container.name))
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: `Init Containers`,
|
label: `Init Containers`,
|
||||||
options: getSelectOptions(initContainers),
|
options: getSelectOptions(initContainers.map(container => container.name)),
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const podSelectOptions = [
|
||||||
|
{
|
||||||
|
label: pod.getOwnerRefs()[0]?.name,
|
||||||
|
options: getSelectOptions(pods.map(pod => pod.metadata.name))
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
reload();
|
||||||
|
}, [selectedPod]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="LogResourceSelector flex gaps align-center">
|
<div className="LogResourceSelector flex gaps align-center">
|
||||||
<span>Namespace</span> <Badge label={pod.getNs()}/>
|
<span>Namespace</span> <Badge data-testid="namespace-badge" label={pod.getNs()}/>
|
||||||
<span>Pod</span> <Badge label={pod.getName()}/>
|
<span>Pod</span>
|
||||||
|
<Select
|
||||||
|
options={podSelectOptions}
|
||||||
|
value={{ label: pod.getName(), value: pod.getName() }}
|
||||||
|
onChange={onPodChange}
|
||||||
|
autoConvertOptions={false}
|
||||||
|
className="pod-selector"
|
||||||
|
/>
|
||||||
<span>Container</span>
|
<span>Container</span>
|
||||||
<Select
|
<Select
|
||||||
options={containerSelectOptions}
|
options={containerSelectOptions}
|
||||||
value={{ label: selectedContainer.name, value: selectedContainer.name }}
|
value={{ label: selectedContainer.name, value: selectedContainer.name }}
|
||||||
onChange={onContainerChange}
|
onChange={onContainerChange}
|
||||||
autoConvertOptions={false}
|
autoConvertOptions={false}
|
||||||
|
className="container-selector"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
123
src/renderer/components/dock/log-tab.store.ts
Normal file
123
src/renderer/components/dock/log-tab.store.ts
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
import uniqueId from "lodash/uniqueId";
|
||||||
|
import { reaction } from "mobx";
|
||||||
|
import { podsStore } from "../+workloads-pods/pods.store";
|
||||||
|
|
||||||
|
import { IPodContainer, Pod } from "../../api/endpoints";
|
||||||
|
import { WorkloadKubeObject } from "../../api/workload-kube-object";
|
||||||
|
import { DockTabStore } from "./dock-tab.store";
|
||||||
|
import { dockStore, IDockTab, TabKind } from "./dock.store";
|
||||||
|
|
||||||
|
export interface LogTabData {
|
||||||
|
pods: Pod[];
|
||||||
|
selectedPod: Pod;
|
||||||
|
selectedContainer: IPodContainer
|
||||||
|
showTimestamps?: boolean
|
||||||
|
previous?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PodLogsTabData {
|
||||||
|
selectedPod: Pod
|
||||||
|
selectedContainer: IPodContainer
|
||||||
|
}
|
||||||
|
|
||||||
|
interface WorkloadLogsTabData {
|
||||||
|
workload: WorkloadKubeObject
|
||||||
|
}
|
||||||
|
|
||||||
|
export class LogTabStore extends DockTabStore<LogTabData> {
|
||||||
|
constructor() {
|
||||||
|
super({
|
||||||
|
storageName: "pod_logs"
|
||||||
|
});
|
||||||
|
|
||||||
|
reaction(() => podsStore.items.length, () => {
|
||||||
|
this.updateTabsData();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
createPodTab({ selectedPod, selectedContainer }: PodLogsTabData): void {
|
||||||
|
const podOwner = selectedPod.getOwnerRefs()[0];
|
||||||
|
const pods = podsStore.getPodsByOwnerId(podOwner?.uid);
|
||||||
|
const title = `Pod ${selectedPod.getName()}`;
|
||||||
|
|
||||||
|
this.createLogsTab(title, {
|
||||||
|
pods: pods.length ? pods : [selectedPod],
|
||||||
|
selectedPod,
|
||||||
|
selectedContainer
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
createWorkloadTab({ workload }: WorkloadLogsTabData): void {
|
||||||
|
const pods = podsStore.getPodsByOwnerId(workload.getId());
|
||||||
|
|
||||||
|
if (!pods.length) return;
|
||||||
|
|
||||||
|
const selectedPod = pods[0];
|
||||||
|
const selectedContainer = selectedPod.getAllContainers()[0];
|
||||||
|
const title = `${workload.kind} ${selectedPod.getName()}`;
|
||||||
|
|
||||||
|
this.createLogsTab(title, {
|
||||||
|
pods,
|
||||||
|
selectedPod,
|
||||||
|
selectedContainer
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
renameTab(tabId: string) {
|
||||||
|
const { selectedPod } = this.getData(tabId);
|
||||||
|
|
||||||
|
dockStore.renameTab(tabId, `Pod ${selectedPod.metadata.name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
private createDockTab(tabParams: Partial<IDockTab>) {
|
||||||
|
dockStore.createTab({
|
||||||
|
kind: TabKind.POD_LOGS,
|
||||||
|
...tabParams
|
||||||
|
}, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private createLogsTab(title: string, data: LogTabData) {
|
||||||
|
const id = uniqueId("log-tab-");
|
||||||
|
|
||||||
|
this.createDockTab({ id, title });
|
||||||
|
this.setData(id, {
|
||||||
|
...data,
|
||||||
|
showTimestamps: false,
|
||||||
|
previous: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateTabsData() {
|
||||||
|
this.data.forEach((tabData, tabId) => {
|
||||||
|
const pod = new Pod(tabData.selectedPod);
|
||||||
|
const pods = podsStore.getPodsByOwnerId(pod.getOwnerRefs()[0]?.uid);
|
||||||
|
const isSelectedPodInList = pods.find(item => item.getId() == pod.getId());
|
||||||
|
const selectedPod = isSelectedPodInList ? pod : pods[0];
|
||||||
|
const selectedContainer = isSelectedPodInList ? tabData.selectedContainer : pod.getAllContainers()[0];
|
||||||
|
|
||||||
|
if (pods.length) {
|
||||||
|
this.setData(tabId, {
|
||||||
|
...tabData,
|
||||||
|
selectedPod,
|
||||||
|
selectedContainer,
|
||||||
|
pods
|
||||||
|
});
|
||||||
|
|
||||||
|
this.renameTab(tabId);
|
||||||
|
} else {
|
||||||
|
this.closeTab(tabId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private closeTab(tabId: string) {
|
||||||
|
this.clearData(tabId);
|
||||||
|
dockStore.closeTab(tabId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const logTabStore = new LogTabStore();
|
||||||
|
|
||||||
|
export function isLogsTab(tab: IDockTab) {
|
||||||
|
return tab && tab.kind === TabKind.POD_LOGS;
|
||||||
|
}
|
||||||
@ -1,27 +1,16 @@
|
|||||||
import { autorun, computed, observable, reaction } from "mobx";
|
import { autorun, computed, observable } from "mobx";
|
||||||
import { Pod, IPodContainer, podsApi, IPodLogsQuery } from "../../api/endpoints";
|
|
||||||
|
import { IPodLogsQuery, Pod, podsApi } from "../../api/endpoints";
|
||||||
import { autobind, interval } from "../../utils";
|
import { autobind, interval } from "../../utils";
|
||||||
import { DockTabStore } from "./dock-tab.store";
|
import { dockStore, TabId } from "./dock.store";
|
||||||
import { dockStore, IDockTab, TabKind } from "./dock.store";
|
import { isLogsTab, logTabStore } from "./log-tab.store";
|
||||||
import { searchStore } from "../../../common/search-store";
|
|
||||||
|
|
||||||
export interface IPodLogsData {
|
|
||||||
pod: Pod;
|
|
||||||
selectedContainer: IPodContainer
|
|
||||||
containers: IPodContainer[]
|
|
||||||
initContainers: IPodContainer[]
|
|
||||||
showTimestamps: boolean
|
|
||||||
previous: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
type TabId = string;
|
|
||||||
type PodLogLine = string;
|
type PodLogLine = string;
|
||||||
|
|
||||||
// Number for log lines to load
|
const logLinesToLoad = 500;
|
||||||
export const logRange = 500;
|
|
||||||
|
|
||||||
@autobind()
|
@autobind()
|
||||||
export class LogStore extends DockTabStore<IPodLogsData> {
|
export class LogStore {
|
||||||
private refresher = interval(10, () => {
|
private refresher = interval(10, () => {
|
||||||
const id = dockStore.selectedTabId;
|
const id = dockStore.selectedTabId;
|
||||||
|
|
||||||
@ -30,12 +19,8 @@ export class LogStore extends DockTabStore<IPodLogsData> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
@observable podLogs = observable.map<TabId, PodLogLine[]>();
|
@observable podLogs = observable.map<TabId, PodLogLine[]>();
|
||||||
@observable newLogSince = observable.map<TabId, string>(); // Timestamp after which all logs are considered to be new
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super({
|
|
||||||
storageName: "pod_logs"
|
|
||||||
});
|
|
||||||
autorun(() => {
|
autorun(() => {
|
||||||
const { selectedTab, isOpen } = dockStore;
|
const { selectedTab, isOpen } = dockStore;
|
||||||
|
|
||||||
@ -45,15 +30,6 @@ export class LogStore extends DockTabStore<IPodLogsData> {
|
|||||||
this.refresher.stop();
|
this.refresher.stop();
|
||||||
}
|
}
|
||||||
}, { delay: 500 });
|
}, { delay: 500 });
|
||||||
|
|
||||||
reaction(() => this.podLogs.get(dockStore.selectedTabId), () => {
|
|
||||||
this.setNewLogSince(dockStore.selectedTabId);
|
|
||||||
});
|
|
||||||
|
|
||||||
reaction(() => dockStore.selectedTabId, () => {
|
|
||||||
// Clear search query on tab change
|
|
||||||
searchStore.reset();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -66,7 +42,7 @@ export class LogStore extends DockTabStore<IPodLogsData> {
|
|||||||
load = async (tabId: TabId) => {
|
load = async (tabId: TabId) => {
|
||||||
try {
|
try {
|
||||||
const logs = await this.loadLogs(tabId, {
|
const logs = await this.loadLogs(tabId, {
|
||||||
tailLines: this.lines + logRange
|
tailLines: this.lines + logLinesToLoad
|
||||||
});
|
});
|
||||||
|
|
||||||
this.refresher.start();
|
this.refresher.start();
|
||||||
@ -107,9 +83,9 @@ export class LogStore extends DockTabStore<IPodLogsData> {
|
|||||||
* @returns {Promise} A fetch request promise
|
* @returns {Promise} A fetch request promise
|
||||||
*/
|
*/
|
||||||
loadLogs = async (tabId: TabId, params: Partial<IPodLogsQuery>) => {
|
loadLogs = async (tabId: TabId, params: Partial<IPodLogsQuery>) => {
|
||||||
const data = this.getData(tabId);
|
const data = logTabStore.getData(tabId);
|
||||||
const { selectedContainer, previous } = data;
|
const { selectedContainer, previous } = data;
|
||||||
const pod = new Pod(data.pod);
|
const pod = new Pod(data.selectedPod);
|
||||||
const namespace = pod.getNs();
|
const namespace = pod.getNs();
|
||||||
const name = pod.getName();
|
const name = pod.getName();
|
||||||
|
|
||||||
@ -127,17 +103,6 @@ export class LogStore extends DockTabStore<IPodLogsData> {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets newLogSince separator timestamp to split old logs from new ones
|
|
||||||
* @param tabId
|
|
||||||
*/
|
|
||||||
setNewLogSince(tabId: TabId) {
|
|
||||||
if (!this.podLogs.has(tabId) || !this.podLogs.get(tabId).length || this.newLogSince.has(tabId)) return;
|
|
||||||
const timestamp = this.getLastSinceTime(tabId);
|
|
||||||
|
|
||||||
this.newLogSince.set(tabId, timestamp.split(".")[0]); // Removing milliseconds from string
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts logs into a string array
|
* Converts logs into a string array
|
||||||
* @returns {number} Length of log lines
|
* @returns {number} Length of log lines
|
||||||
@ -196,37 +161,6 @@ export class LogStore extends DockTabStore<IPodLogsData> {
|
|||||||
clearLogs(tabId: TabId) {
|
clearLogs(tabId: TabId) {
|
||||||
this.podLogs.delete(tabId);
|
this.podLogs.delete(tabId);
|
||||||
}
|
}
|
||||||
|
|
||||||
clearData(tabId: TabId) {
|
|
||||||
this.data.delete(tabId);
|
|
||||||
this.clearLogs(tabId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const podLogsStore = new LogStore();
|
export const logStore = new LogStore();
|
||||||
|
|
||||||
export function createPodLogsTab(data: IPodLogsData, tabParams: Partial<IDockTab> = {}) {
|
|
||||||
const podId = data.pod.getId();
|
|
||||||
let tab = dockStore.getTabById(podId);
|
|
||||||
|
|
||||||
if (tab) {
|
|
||||||
dockStore.open();
|
|
||||||
dockStore.selectTab(tab.id);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// If no existent tab found
|
|
||||||
tab = dockStore.createTab({
|
|
||||||
id: podId,
|
|
||||||
kind: TabKind.POD_LOGS,
|
|
||||||
title: data.pod.getName(),
|
|
||||||
...tabParams
|
|
||||||
}, false);
|
|
||||||
podLogsStore.setData(tab.id, data);
|
|
||||||
|
|
||||||
return tab;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isLogsTab(tab: IDockTab) {
|
|
||||||
return tab && tab.kind === TabKind.POD_LOGS;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -8,9 +8,10 @@ import { IDockTab } from "./dock.store";
|
|||||||
import { InfoPanel } from "./info-panel";
|
import { InfoPanel } from "./info-panel";
|
||||||
import { LogResourceSelector } from "./log-resource-selector";
|
import { LogResourceSelector } from "./log-resource-selector";
|
||||||
import { LogList } from "./log-list";
|
import { LogList } from "./log-list";
|
||||||
import { IPodLogsData, podLogsStore } from "./log.store";
|
import { logStore } from "./log.store";
|
||||||
import { LogSearch } from "./log-search";
|
import { LogSearch } from "./log-search";
|
||||||
import { LogControls } from "./log-controls";
|
import { LogControls } from "./log-controls";
|
||||||
|
import { LogTabData, logTabStore } from "./log-tab.store";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
className?: string
|
className?: string
|
||||||
@ -30,7 +31,7 @@ export class Logs extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get tabData() {
|
get tabData() {
|
||||||
return podLogsStore.getData(this.tabId);
|
return logTabStore.getData(this.tabId);
|
||||||
}
|
}
|
||||||
|
|
||||||
get tabId() {
|
get tabId() {
|
||||||
@ -38,18 +39,18 @@ export class Logs extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@autobind()
|
@autobind()
|
||||||
save(data: Partial<IPodLogsData>) {
|
save(data: Partial<LogTabData>) {
|
||||||
podLogsStore.setData(this.tabId, { ...this.tabData, ...data });
|
logTabStore.setData(this.tabId, { ...this.tabData, ...data });
|
||||||
}
|
}
|
||||||
|
|
||||||
load = async () => {
|
load = async () => {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
await podLogsStore.load(this.tabId);
|
await logStore.load(this.tabId);
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
reload = async () => {
|
reload = async () => {
|
||||||
podLogsStore.clearLogs(this.tabId);
|
logStore.clearLogs(this.tabId);
|
||||||
await this.load();
|
await this.load();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -82,11 +83,12 @@ export class Logs extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderResourceSelector() {
|
renderResourceSelector() {
|
||||||
const logs = podLogsStore.logs;
|
const logs = logStore.logs;
|
||||||
const searchLogs = this.tabData.showTimestamps ? logs : podLogsStore.logsWithoutTimestamps;
|
const searchLogs = this.tabData.showTimestamps ? logs : logStore.logsWithoutTimestamps;
|
||||||
const controls = (
|
const controls = (
|
||||||
<div className="flex gaps">
|
<div className="flex gaps">
|
||||||
<LogResourceSelector
|
<LogResourceSelector
|
||||||
|
tabId={this.tabId}
|
||||||
tabData={this.tabData}
|
tabData={this.tabData}
|
||||||
save={this.save}
|
save={this.save}
|
||||||
reload={this.reload}
|
reload={this.reload}
|
||||||
@ -112,7 +114,7 @@ export class Logs extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const logs = podLogsStore.logs;
|
const logs = logStore.logs;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="PodLogs flex column">
|
<div className="PodLogs flex column">
|
||||||
|
|||||||
@ -440,11 +440,9 @@ export class ItemListLayout extends React.Component<ItemListLayoutProps> {
|
|||||||
return <TableCell key={cellProps.id ?? index} {...cellProps} />;
|
return <TableCell key={cellProps.id ?? index} {...cellProps} />;
|
||||||
}
|
}
|
||||||
})}
|
})}
|
||||||
{isConfigurable && (
|
<TableCell className="menu">
|
||||||
<TableCell className="menu">
|
{isConfigurable && this.renderColumnVisibilityMenu()}
|
||||||
{this.renderColumnVisibilityMenu()}
|
</TableCell>
|
||||||
</TableCell>
|
|
||||||
)}
|
|
||||||
</TableHead>
|
</TableHead>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,6 +47,10 @@ export abstract class KubeObjectStore<T extends KubeObject = any> extends ItemSt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getById(id: string) {
|
||||||
|
return this.items.find(item => item.getId() === id);
|
||||||
|
}
|
||||||
|
|
||||||
getByName(name: string, namespace?: string): T {
|
getByName(name: string, namespace?: string): T {
|
||||||
return this.items.find(item => {
|
return this.items.find(item => {
|
||||||
return item.getName() === name && (
|
return item.getName() === name && (
|
||||||
|
|||||||
@ -2,7 +2,80 @@
|
|||||||
|
|
||||||
Here you can find description of changes we've built into each release. While we try our best to make each upgrade automatic and as smooth as possible, there may be some cases where you might need to do something to ensure the application works smoothly. So please read through the release highlights!
|
Here you can find description of changes we've built into each release. While we try our best to make each upgrade automatic and as smooth as possible, there may be some cases where you might need to do something to ensure the application works smoothly. So please read through the release highlights!
|
||||||
|
|
||||||
## 4.0.2 (current version)
|
## 4.1.0-alpha.1 (current version)
|
||||||
|
|
||||||
|
- Change: list views default to a namespace (insted of listing resources from all namespaces)
|
||||||
|
- Generic logs view with Pod selector
|
||||||
|
- Possibility to add custom Helm repository through Lens
|
||||||
|
- Possibility to change visibility of Pod list columns
|
||||||
|
- Suspend / resume buttons for CronJobs
|
||||||
|
- Dock tabs context menu
|
||||||
|
- Display node column in Pod list
|
||||||
|
- Unify age column output with kubectl
|
||||||
|
- Use dark colors in Dock regardless of active theme
|
||||||
|
- Improve Pod tolerations layout
|
||||||
|
- Lens metrics: scrape only lens-metrics namespace
|
||||||
|
- Lens metrics: Prometheus v2.19.3
|
||||||
|
- Export PodDetailsList component to extension API
|
||||||
|
- Export Wizard components to extension API
|
||||||
|
- Export NamespaceSelect component to extension API
|
||||||
|
|
||||||
|
## 4.0.8
|
||||||
|
|
||||||
|
- Fix: extension cluster sub-menu/page periodic re-render
|
||||||
|
- Fix: app hang on boot if started from command line & oh-my-zsh prompts for auto-update
|
||||||
|
|
||||||
|
## 4.0.7
|
||||||
|
|
||||||
|
- Fix: typo in Prometheus Ingress metrics
|
||||||
|
- Fix: catch xterm.js fit error
|
||||||
|
- Fix: Windows tray icon click
|
||||||
|
- Fix: error on Kubernetes >= 1.20 on object edit
|
||||||
|
- Fix: multiline log wrapping
|
||||||
|
- Fix: prevent clusters from initializing multiple times
|
||||||
|
- Fix: show default workspace on first boot
|
||||||
|
|
||||||
|
## 4.0.6
|
||||||
|
|
||||||
|
- Don't open Lens at OS login by default
|
||||||
|
- Disable GPU acceleration by setting an env variable
|
||||||
|
- Catch HTTP Errors in case pod metrics resources do not exist or access is forbidden
|
||||||
|
- Check is persistent volume claims resource to allowed for user
|
||||||
|
- Share react-router and react-router-dom libraries to extensions
|
||||||
|
- Fix: long list cropping in sidebar
|
||||||
|
- Fix: k0s distribution detection
|
||||||
|
- Fix: Preserve line breaks when copying logs
|
||||||
|
- Fix: error on api watch on complex api versions
|
||||||
|
|
||||||
|
## 4.0.5
|
||||||
|
|
||||||
|
- Fix: add missing Kubernetes distro detectors
|
||||||
|
- Fix: improve how Workloads Overview is loaded
|
||||||
|
- Fix: race conditions on extension loader
|
||||||
|
- Fix: pod logs scrolling issues
|
||||||
|
- Fix: render node list before metrics are available
|
||||||
|
- Fix: kube-state-metrics v1.9.7
|
||||||
|
- Fix: CRD sidebar expand/collapse
|
||||||
|
- Fix: disable oh-my-zsh auto-update prompt when resolving shell environment
|
||||||
|
- Add kubectl 1.20 support to Lens Smart Terminal
|
||||||
|
- Optimise performance during cluster connect
|
||||||
|
|
||||||
|
## 4.0.4
|
||||||
|
|
||||||
|
- Fix errors on Kubernetes v1.20
|
||||||
|
- Update bundled kubectl to v1.17.15
|
||||||
|
- Fix: MacOS error on shutdown
|
||||||
|
- Fix: Kubernetes distribution detection
|
||||||
|
- Fix: error while displaying CRDs with column which type is an object
|
||||||
|
|
||||||
|
## 4.0.3
|
||||||
|
|
||||||
|
- Fix: install in-tree extensions before others
|
||||||
|
- Fix: bundle all dependencies in in-tree extensions
|
||||||
|
- Fix: display error dialog if extensions couldn't be loaded
|
||||||
|
- Fix: ensure only one app instance
|
||||||
|
|
||||||
|
## 4.0.2
|
||||||
|
|
||||||
We are aware some users are encountering issues and regressions from previous version. Many of these issues are something we have not seen as part of our automated or manual testing process. To make it worse, some of them are really difficult to reproduce. We want to ensure we are putting all our energy and effort trying to resolve these issues. We hope you are patient. Expect to see new patch releases still in the coming days! Fixes in this version:
|
We are aware some users are encountering issues and regressions from previous version. Many of these issues are something we have not seen as part of our automated or manual testing process. To make it worse, some of them are really difficult to reproduce. We want to ensure we are putting all our energy and effort trying to resolve these issues. We hope you are patient. Expect to see new patch releases still in the coming days! Fixes in this version:
|
||||||
|
|
||||||
|
|||||||
51
yarn.lock
51
yarn.lock
@ -267,6 +267,13 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
regenerator-runtime "^0.13.4"
|
regenerator-runtime "^0.13.4"
|
||||||
|
|
||||||
|
"@babel/runtime@^7.12.5":
|
||||||
|
version "7.12.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e"
|
||||||
|
integrity sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==
|
||||||
|
dependencies:
|
||||||
|
regenerator-runtime "^0.13.4"
|
||||||
|
|
||||||
"@babel/template@^7.10.1", "@babel/template@^7.3.3":
|
"@babel/template@^7.10.1", "@babel/template@^7.3.3":
|
||||||
version "7.10.1"
|
version "7.10.1"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.1.tgz#e167154a94cb5f14b28dc58f5356d2162f539811"
|
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.1.tgz#e167154a94cb5f14b28dc58f5356d2162f539811"
|
||||||
@ -775,6 +782,17 @@
|
|||||||
"@types/yargs" "^15.0.0"
|
"@types/yargs" "^15.0.0"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
|
|
||||||
|
"@jest/types@^26.6.2":
|
||||||
|
version "26.6.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e"
|
||||||
|
integrity sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/istanbul-lib-coverage" "^2.0.0"
|
||||||
|
"@types/istanbul-reports" "^3.0.0"
|
||||||
|
"@types/node" "*"
|
||||||
|
"@types/yargs" "^15.0.0"
|
||||||
|
chalk "^4.0.0"
|
||||||
|
|
||||||
"@kubernetes/client-node@^0.12.0":
|
"@kubernetes/client-node@^0.12.0":
|
||||||
version "0.12.0"
|
version "0.12.0"
|
||||||
resolved "https://registry.yarnpkg.com/@kubernetes/client-node/-/client-node-0.12.0.tgz#79120311bced206ac8fa36435fb4cc2c1828fff2"
|
resolved "https://registry.yarnpkg.com/@kubernetes/client-node/-/client-node-0.12.0.tgz#79120311bced206ac8fa36435fb4cc2c1828fff2"
|
||||||
@ -955,6 +973,20 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
defer-to-connect "^1.0.1"
|
defer-to-connect "^1.0.1"
|
||||||
|
|
||||||
|
"@testing-library/dom@>=7":
|
||||||
|
version "7.29.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.29.4.tgz#1647c2b478789621ead7a50614ad81ab5ae5b86c"
|
||||||
|
integrity sha512-CtrJRiSYEfbtNGtEsd78mk1n1v2TUbeABlNIcOCJdDfkN5/JTOwQEbbQpoSRxGqzcWPgStMvJ4mNolSuBRv1NA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/code-frame" "^7.10.4"
|
||||||
|
"@babel/runtime" "^7.12.5"
|
||||||
|
"@types/aria-query" "^4.2.0"
|
||||||
|
aria-query "^4.2.2"
|
||||||
|
chalk "^4.1.0"
|
||||||
|
dom-accessibility-api "^0.5.4"
|
||||||
|
lz-string "^1.4.4"
|
||||||
|
pretty-format "^26.6.2"
|
||||||
|
|
||||||
"@testing-library/dom@^7.26.0":
|
"@testing-library/dom@^7.26.0":
|
||||||
version "7.26.3"
|
version "7.26.3"
|
||||||
resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.26.3.tgz#5554ee985f712d621bd676104b879f85d9a7a0ef"
|
resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.26.3.tgz#5554ee985f712d621bd676104b879f85d9a7a0ef"
|
||||||
@ -4552,7 +4584,7 @@ doctrine@^3.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
esutils "^2.0.2"
|
esutils "^2.0.2"
|
||||||
|
|
||||||
dom-accessibility-api@^0.5.1:
|
dom-accessibility-api@^0.5.1, dom-accessibility-api@^0.5.4:
|
||||||
version "0.5.4"
|
version "0.5.4"
|
||||||
resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.4.tgz#b06d059cdd4a4ad9a79275f9d414a5c126241166"
|
resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.4.tgz#b06d059cdd4a4ad9a79275f9d414a5c126241166"
|
||||||
integrity sha512-TvrjBckDy2c6v6RLxPv5QXOnU+SmF9nBII5621Ve5fu6Z/BDrENurBEvlC1f44lKEUVqOpK4w9E5Idc5/EgkLQ==
|
integrity sha512-TvrjBckDy2c6v6RLxPv5QXOnU+SmF9nBII5621Ve5fu6Z/BDrENurBEvlC1f44lKEUVqOpK4w9E5Idc5/EgkLQ==
|
||||||
@ -10822,6 +10854,16 @@ pretty-format@^26.0.1:
|
|||||||
ansi-styles "^4.0.0"
|
ansi-styles "^4.0.0"
|
||||||
react-is "^16.12.0"
|
react-is "^16.12.0"
|
||||||
|
|
||||||
|
pretty-format@^26.6.2:
|
||||||
|
version "26.6.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93"
|
||||||
|
integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==
|
||||||
|
dependencies:
|
||||||
|
"@jest/types" "^26.6.2"
|
||||||
|
ansi-regex "^5.0.0"
|
||||||
|
ansi-styles "^4.0.0"
|
||||||
|
react-is "^17.0.1"
|
||||||
|
|
||||||
process-nextick-args@~2.0.0:
|
process-nextick-args@~2.0.0:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
||||||
@ -11198,6 +11240,13 @@ react-router@5.2.0, react-router@^5.2.0:
|
|||||||
tiny-invariant "^1.0.2"
|
tiny-invariant "^1.0.2"
|
||||||
tiny-warning "^1.0.0"
|
tiny-warning "^1.0.0"
|
||||||
|
|
||||||
|
react-select-event@^5.1.0:
|
||||||
|
version "5.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-select-event/-/react-select-event-5.1.0.tgz#d45ef68f2a9c872903e8c9725f3ae6e7576f7be0"
|
||||||
|
integrity sha512-D5DzJlYCdZsGbDVFMQFynrG0OLalJM3ZzDT7KQADNVWE604JCeQF9bIuvPZqVD7IzhnPsFzOUCsilzDA6w6WRQ==
|
||||||
|
dependencies:
|
||||||
|
"@testing-library/dom" ">=7"
|
||||||
|
|
||||||
react-select@^3.1.0:
|
react-select@^3.1.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-select/-/react-select-3.1.0.tgz#ab098720b2e9fe275047c993f0d0caf5ded17c27"
|
resolved "https://registry.yarnpkg.com/react-select/-/react-select-3.1.0.tgz#ab098720b2e9fe275047c993f0d0caf5ded17c27"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user