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

Merge branch 'master' into fix/store.loadAll

# Conflicts:
#	src/renderer/api/kube-watch-api.ts
#	src/renderer/components/app.tsx
#	src/renderer/components/item-object-list/item-list-layout.tsx
This commit is contained in:
Roman 2021-02-01 17:57:36 +02:00
commit cd1c8fbd16
41 changed files with 604 additions and 397 deletions

View File

@ -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

View File

@ -2796,7 +2796,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 +3227,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"
} }
@ -4367,6 +4369,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",
@ -4381,6 +4384,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"
} }
@ -4390,6 +4394,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"
} }
@ -4399,6 +4404,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"
} }
@ -4407,7 +4413,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
} }
} }
}, },
@ -5398,7 +5405,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",
@ -6275,7 +6283,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",

View File

@ -2868,7 +2868,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",
@ -3298,6 +3299,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"
} }
@ -4460,6 +4462,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",
@ -4474,6 +4477,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"
} }
@ -4483,6 +4487,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"
} }
@ -4492,6 +4497,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"
} }
@ -4500,7 +4506,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
} }
} }
}, },
@ -5516,7 +5523,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",
@ -6406,7 +6414,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",

View File

@ -2816,7 +2816,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",
@ -3246,6 +3247,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"
} }
@ -4394,6 +4396,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",
@ -4408,6 +4411,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"
} }
@ -5434,7 +5438,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",
@ -6311,7 +6316,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",

View File

@ -2796,7 +2796,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 +3227,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 +4384,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 +4399,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 +4409,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 +4419,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 +4428,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 +5445,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 +6323,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",

View File

@ -2901,7 +2901,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",
@ -3337,6 +3338,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"
} }
@ -4533,6 +4535,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",
@ -4547,6 +4550,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"
} }
@ -4556,6 +4560,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"
} }
@ -4564,13 +4569,15 @@
"version": "8.3.2", "version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"dev": true "dev": true,
"optional": true
}, },
"which": { "which": {
"version": "2.0.2", "version": "2.0.2",
"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"
} }
@ -4579,7 +4586,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
} }
} }
}, },
@ -5595,7 +5603,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",

View File

@ -4,7 +4,7 @@ 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",
"linux": "./dist/linux-unpacked/kontena-lens", "linux": "./dist/linux-unpacked/lens",
"darwin": "./dist/mac/Lens.app/Contents/MacOS/Lens", "darwin": "./dist/mac/Lens.app/Contents/MacOS/Lens",
}; };

View File

@ -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": {
@ -103,7 +103,11 @@
], ],
"linux": { "linux": {
"category": "Network", "category": "Network",
"executableName": "lens",
"artifactName": "${productName}-${version}.${arch}.${ext}",
"target": [ "target": [
"deb",
"rpm",
"snap", "snap",
"AppImage" "AppImage"
], ],

View File

@ -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"],

View File

@ -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}

View File

@ -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();

View File

@ -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(),

View File

@ -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(),

View File

@ -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(),

View File

@ -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 [

View File

@ -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(),

View File

@ -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(),

View File

@ -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}>

View File

@ -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(),

View File

@ -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;

View File

@ -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(),

View File

@ -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(),

View File

@ -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(),

View File

@ -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(),

View File

@ -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(),

View File

@ -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()}`;

View File

@ -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 [

View File

@ -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(),

View File

@ -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);

View File

@ -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;

View File

@ -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(),

View File

@ -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(),

View File

@ -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(),

View File

@ -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(),

View File

@ -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(),

View File

@ -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(),

View File

@ -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();

View File

@ -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(),

View File

@ -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(),

View File

@ -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
]); ]);
}); });

View File

@ -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: