From 63fb853aac77c72a94add78a7ae2badae5f19d30 Mon Sep 17 00:00:00 2001 From: Eric Herbrandson Date: Sat, 23 Mar 2019 20:44:13 -0500 Subject: [PATCH] Adding sorting to all collections. Some styling work --- client/package-lock.json | 199 ++++++++++++++++++++ client/package.json | 1 + client/src/art/loadingSvg.js | 11 +- client/src/components/cpuChart.js | 17 +- client/src/components/eventsPanel.js | 41 ++-- client/src/components/listViewHelpers.js | 52 +++-- client/src/components/loading.js | 2 +- client/src/components/loading.scss | 8 +- client/src/components/namespaceFilter.js | 29 +-- client/src/components/podsPanel.js | 65 ++++--- client/src/components/ramChart.js | 17 +- client/src/components/replicaSetsPanel.js | 35 ++-- client/src/components/replicaSetsPanel.scss | 6 + client/src/components/sorter.js | 60 ++++-- client/src/components/sorter.scss | 5 +- client/src/scss/elements/select.scss | 48 +++-- client/src/services/api.js | 6 +- client/src/services/apiProxy.js | 171 ++++++++++------- client/src/utils/filterHelper.js | 6 +- client/src/utils/metricsHelpers.js | 64 +------ client/src/utils/unitHelpers.js | 17 ++ client/src/views/account.js | 14 ++ client/src/views/clusterRole.js | 22 +-- client/src/views/clusterRoleBinding.js | 55 +++--- client/src/views/configMaps.js | 36 ++-- client/src/views/cronJob.js | 25 ++- client/src/views/daemonSet.js | 14 +- client/src/views/dashboard.js | 18 +- client/src/views/deployment.js | 42 ++++- client/src/views/exec.js | 26 +-- client/src/views/ingress.js | 16 +- client/src/views/ingresses.js | 51 +++-- client/src/views/job.js | 25 ++- client/src/views/logs.js | 24 ++- client/src/views/namespaces.js | 42 +++-- client/src/views/node.js | 14 +- client/src/views/nodes.js | 101 ++++++---- client/src/views/notFound.js | 7 +- client/src/views/persistentVolumeClaims.js | 73 ++++--- client/src/views/persistentVolumes.js | 53 +++--- client/src/views/pods.js | 10 +- client/src/views/replicaSet.js | 14 +- client/src/views/replicaSets.js | 10 +- client/src/views/role.js | 22 +-- client/src/views/roleBinding.js | 47 ++--- client/src/views/roleBindings.js | 41 ++-- client/src/views/roles.js | 41 ++-- client/src/views/secrets.js | 38 ++-- client/src/views/service.js | 23 +-- client/src/views/serviceAccounts.js | 34 ++-- client/src/views/services.js | 34 ++-- client/src/views/statefulSet.js | 25 ++- client/src/views/storageClasses.js | 40 ++-- client/src/views/workloads.js | 49 +++-- 54 files changed, 1250 insertions(+), 696 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index ce811e2..f3995de 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -896,6 +896,62 @@ "resolved": "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz", "integrity": "sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw==" }, + "@emotion/babel-utils": { + "version": "0.6.10", + "resolved": "https://registry.npmjs.org/@emotion/babel-utils/-/babel-utils-0.6.10.tgz", + "integrity": "sha512-/fnkM/LTEp3jKe++T0KyTszVGWNKPNOUJfjNKLO17BzQ6QPxgbg3whayom1Qr2oLFH3V92tDymU+dT5q676uow==", + "requires": { + "@emotion/hash": "^0.6.6", + "@emotion/memoize": "^0.6.6", + "@emotion/serialize": "^0.9.1", + "convert-source-map": "^1.5.1", + "find-root": "^1.1.0", + "source-map": "^0.7.2" + }, + "dependencies": { + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==" + } + } + }, + "@emotion/hash": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.6.6.tgz", + "integrity": "sha512-ojhgxzUHZ7am3D2jHkMzPpsBAiB005GF5YU4ea+8DNPybMk01JJUM9V9YRlF/GE95tcOm8DxQvWA2jq19bGalQ==" + }, + "@emotion/memoize": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.6.6.tgz", + "integrity": "sha512-h4t4jFjtm1YV7UirAFuSuFGyLa+NNxjdkq6DpFLANNQY5rHueFZHVY+8Cu1HYVP6DrheB0kv4m5xPjo7eKT7yQ==" + }, + "@emotion/serialize": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-0.9.1.tgz", + "integrity": "sha512-zTuAFtyPvCctHBEL8KZ5lJuwBanGSutFEncqLn/m9T1a6a93smBStK+bZzcNPgj4QS8Rkw9VTwJGhRIUVO8zsQ==", + "requires": { + "@emotion/hash": "^0.6.6", + "@emotion/memoize": "^0.6.6", + "@emotion/unitless": "^0.6.7", + "@emotion/utils": "^0.8.2" + } + }, + "@emotion/stylis": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.7.1.tgz", + "integrity": "sha512-/SLmSIkN13M//53TtNxgxo57mcJk/UJIDFRKwOiLIBEyBHEcipgR6hNMQ/59Sl4VjCJ0Z/3zeAZyvnSLPG/1HQ==" + }, + "@emotion/unitless": { + "version": "0.6.7", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.6.7.tgz", + "integrity": "sha512-Arj1hncvEVqQ2p7Ega08uHLr1JuRYBuO5cIvcA+WWEQ5+VmkOE3ZXzl04NbQxeQpWX78G7u6MqxKuNX3wvYZxg==" + }, + "@emotion/utils": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-0.8.2.tgz", + "integrity": "sha512-rLu3wcBWH4P5q1CGoSSH/i9hrXs7SlbRLkoq9IGuoPYNGQvDJ3pt/wmOM+XgYjIDRMVIdkUWt0RsfzF50JfnCw==" + }, "@mrmlnc/readdir-enhanced": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", @@ -2039,6 +2095,32 @@ "object.assign": "^4.1.0" } }, + "babel-plugin-emotion": { + "version": "9.2.11", + "resolved": "https://registry.npmjs.org/babel-plugin-emotion/-/babel-plugin-emotion-9.2.11.tgz", + "integrity": "sha512-dgCImifnOPPSeXod2znAmgc64NhaaOjGEHROR/M+lmStb3841yK1sgaDYAYMnlvWNz8GnpwIPN0VmNpbWYZ+VQ==", + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@emotion/babel-utils": "^0.6.4", + "@emotion/hash": "^0.6.2", + "@emotion/memoize": "^0.6.1", + "@emotion/stylis": "^0.7.0", + "babel-plugin-macros": "^2.0.0", + "babel-plugin-syntax-jsx": "^6.18.0", + "convert-source-map": "^1.5.0", + "find-root": "^1.1.0", + "mkdirp": "^0.5.1", + "source-map": "^0.5.7", + "touch": "^2.0.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, "babel-plugin-istanbul": { "version": "4.1.6", "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz", @@ -2079,6 +2161,11 @@ "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.1.tgz", "integrity": "sha512-vzZlo+yEB5YHqI6CRRTDojeT43J3Wf3C/MVkZW5UlbSeIIVUYRKtxaFT2L/VTv9mbIyatCW39+9g/SZolvwRUQ==" }, + "babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=" + }, "babel-plugin-syntax-object-rest-spread": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", @@ -3509,6 +3596,11 @@ } } }, + "classnames": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", + "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" + }, "clean-css": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", @@ -3857,6 +3949,20 @@ "elliptic": "^6.0.0" } }, + "create-emotion": { + "version": "9.2.12", + "resolved": "https://registry.npmjs.org/create-emotion/-/create-emotion-9.2.12.tgz", + "integrity": "sha512-P57uOF9NL2y98Xrbl2OuiDQUZ30GVmASsv5fbsjF4Hlraip2kyAvMm+2PoYUvFFw03Fhgtxk3RqZSm2/qHL9hA==", + "requires": { + "@emotion/hash": "^0.6.2", + "@emotion/memoize": "^0.6.1", + "@emotion/stylis": "^0.7.0", + "@emotion/unitless": "^0.6.2", + "csstype": "^2.5.2", + "stylis": "^3.5.0", + "stylis-rule-sheet": "^0.0.10" + } + }, "create-hash": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", @@ -4543,6 +4649,11 @@ "cssom": "0.3.x" } }, + "csstype": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.3.tgz", + "integrity": "sha512-rINUZXOkcBmoHWEyu7JdHu5JMzkGRoMX4ov9830WNgxf5UYxcBUO0QTKAqeJ5EZfSdlrcJYkC8WwfVW7JYi4yg==" + }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -4911,6 +5022,14 @@ "utila": "~0.4" } }, + "dom-helpers": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz", + "integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==", + "requires": { + "@babel/runtime": "^7.1.2" + } + }, "dom-serializer": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", @@ -5032,6 +5151,15 @@ "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" }, + "emotion": { + "version": "9.2.12", + "resolved": "https://registry.npmjs.org/emotion/-/emotion-9.2.12.tgz", + "integrity": "sha512-hcx7jppaI8VoXxIWEhxpDW7I+B4kq9RNzQLmsrF6LY8BGKqe2N+gFAQr0EfuFucFlPs2A9HM4+xNj4NeqEWIOQ==", + "requires": { + "babel-plugin-emotion": "^9.2.11", + "create-emotion": "^9.2.12" + } + }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -6240,6 +6368,11 @@ "pkg-dir": "^3.0.0" } }, + "find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", @@ -10302,6 +10435,11 @@ "mimic-fn": "^1.0.0" } }, + "memoize-one": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.0.0.tgz", + "integrity": "sha512-7g0+ejkOaI9w5x6LvQwmj68kUj6rxROywPSCqmclG/HBacmFnZqhVscQ8kovkn9FBCNJmOz6SY42+jnvZzDWdw==" + }, "memory-fs": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", @@ -15886,6 +16024,14 @@ "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-5.1.4.tgz", "integrity": "sha512-fp+U98OMZcnduQ+NSEiQa4s/XMsbp+5KlydmkbESOw4P69iWZ68ZMFM5a2BuE0FgqPBKApJyRuYHR95jM8lAmg==" }, + "react-input-autosize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/react-input-autosize/-/react-input-autosize-2.2.1.tgz", + "integrity": "sha512-3+K4CD13iE4lQQ2WlF8PuV5htfmTRLH6MDnfndHM6LuBRszuXnuyIfE7nhSKt8AzRBZ50bu0sAhkNMeS5pxQQA==", + "requires": { + "prop-types": "^15.5.8" + } + }, "react-is": { "version": "16.8.4", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.4.tgz", @@ -16074,6 +16220,20 @@ } } }, + "react-select": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/react-select/-/react-select-2.4.2.tgz", + "integrity": "sha512-5xFOQ6JJktkY5NTaHrc6x9mKwIjhNIiBkGic1j71uyY+ulFpRFra6f4WKLd9fuCylk4WjLpO5zDhdF4CAcwFzA==", + "requires": { + "classnames": "^2.2.5", + "emotion": "^9.1.2", + "memoize-one": "^5.0.0", + "prop-types": "^15.6.0", + "raf": "^3.4.0", + "react-input-autosize": "^2.2.1", + "react-transition-group": "^2.2.1" + } + }, "react-switch": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/react-switch/-/react-switch-4.1.0.tgz", @@ -16082,6 +16242,17 @@ "prop-types": "^15.6.2" } }, + "react-transition-group": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.7.0.tgz", + "integrity": "sha512-CzF22K0x6arjQO4AxkasMaiYcFG/QH0MhPNs45FmNsfWsQmsO9jv52sIZJAalnlryD5RgrrbLtV5CMJSokrrMA==", + "requires": { + "dom-helpers": "^3.3.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2", + "react-lifecycles-compat": "^3.0.4" + } + }, "read-pkg": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", @@ -17968,6 +18139,16 @@ } } }, + "stylis": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz", + "integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==" + }, + "stylis-rule-sheet": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz", + "integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw==" + }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -18278,6 +18459,24 @@ "hoek": "4.x.x" } }, + "touch": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/touch/-/touch-2.0.2.tgz", + "integrity": "sha512-qjNtvsFXTRq7IuMLweVgFxmEuQ6gLbRs2jQxL80TtZ31dEKWYIxRXquij6w6VimyDek5hD3PytljHmEtAs2u0A==", + "requires": { + "nopt": "~1.0.10" + }, + "dependencies": { + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "requires": { + "abbrev": "1" + } + } + } + }, "tough-cookie": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", diff --git a/client/package.json b/client/package.json index 1f0bd40..b062076 100644 --- a/client/package.json +++ b/client/package.json @@ -13,6 +13,7 @@ "react-dom": "^16.8.2", "react-modal": "^3.8.1", "react-scripts": "2.1.5", + "react-select": "^2.4.2", "react-switch": "^4.1.0", "swagger-parser": "^6.0.5", "uuid": "^3.3.2", diff --git a/client/src/art/loadingSvg.js b/client/src/art/loadingSvg.js index 7292129..5b699b2 100644 --- a/client/src/art/loadingSvg.js +++ b/client/src/art/loadingSvg.js @@ -1,13 +1,10 @@ import React from 'react'; const LoadingSvg = props => ( - - - - - - - + + + + ); diff --git a/client/src/components/cpuChart.js b/client/src/components/cpuChart.js index 9009e53..8de249a 100644 --- a/client/src/components/cpuChart.js +++ b/client/src/components/cpuChart.js @@ -1,6 +1,7 @@ +import _ from 'lodash'; import React from 'react'; import Chart from './chart'; -import {getPodCpuTotals} from '../utils/metricsHelpers'; +import {parseCpu, TO_ONE_CPU} from '../utils/unitHelpers'; export default function CpuTotalsChart({items, metrics}) { const totals = getPodCpuTotals(items, metrics); @@ -17,3 +18,17 @@ export default function CpuTotalsChart({items, metrics}) { ); } + +function getPodCpuTotals(items, metrics) { + if (!items || !metrics) return null; + + const metricsContainers = Object.values(metrics).flatMap(x => x.containers); + const podContainers = items + .flatMap(x => x.spec.containers) + .filter(x => x.resources && x.resources.requests); + + const used = _.sumBy(metricsContainers, x => parseCpu(x.usage.cpu)) / TO_ONE_CPU; + const available = _.sumBy(podContainers, x => parseCpu(x.resources.requests.cpu)) / TO_ONE_CPU; + + return {used, available}; +} diff --git a/client/src/components/eventsPanel.js b/client/src/components/eventsPanel.js index f4bcd9e..7b79b86 100644 --- a/client/src/components/eventsPanel.js +++ b/client/src/components/eventsPanel.js @@ -1,27 +1,42 @@ import React from 'react'; import moment from 'moment'; -import {NoResults, hasResults} from './listViewHelpers'; +import {TableBody} from './listViewHelpers'; import log from '../utils/log'; import ResourceSvg from '../art/resourceSvg'; +import Sorter, {sortByDate} from './sorter'; -export default function EventsPanel({items, filter, shortList}) { +export default function EventsPanel({items, filter, shortList, sort}) { return (
- - + + {!shortList && ( - + )} - - + + - - {hasResults(items) ? items.map(x => ( + ( - )) : ( - )} - + />
Time + Type + + Time + Name + Name + ReasonMessage + Reason + + Message +
{x.reason} {x.message}
); } +function sortByName({involvedObject}) { + return `${involvedObject.namespace}:${involvedObject.name}`; +} + function getTypeClass(type) { switch (type) { case 'Normal': diff --git a/client/src/components/listViewHelpers.js b/client/src/components/listViewHelpers.js index f06b297..f0d8753 100644 --- a/client/src/components/listViewHelpers.js +++ b/client/src/components/listViewHelpers.js @@ -1,25 +1,49 @@ +import _ from 'lodash'; import React from 'react'; import moment from 'moment'; import Loading from './loading'; -import Sorter from './sorter'; +import Sorter, {sortByDate} from './sorter'; import ResourceSvg from '../art/resourceSvg'; -export function MetadataHeaders({includeNamespace, sortBy, sortDirection, onSort}) { +export function objectMap(items = {}) { + return Object.entries(items).map(([key, value]) => ( +
+ {key}{value.length <= 50 ? value : `${value.substr(0, 50)}...`} +
+ )); +} + +export function TableBody({items, filter, colSpan, sort, row}) { + if (items && sort) { + const {field, direction} = sort; + items = _.orderBy(items, [field], [direction]); // eslint-disable-line no-param-reassign + } + + return ( + + {items && items.length > 0 ? items.map(row) : ( + + )} + + ); +} + +export function MetadataHeaders({includeNamespace, sort}) { return ( <> - + Type - + Name {includeNamespace && ( - + Namespace )} - + Age ); @@ -36,7 +60,7 @@ export function MetadataColumns({item, href, includeNamespace, isError}) {
{item.kind}
- {item.metadata.name} + {href ? ({item.metadata.name}) : item.metadata.name} {includeNamespace && ( @@ -52,11 +76,7 @@ export function MetadataColumns({item, href, includeNamespace, isError}) { ); } -export function hasResults(items) { - return !!items && items.length > 0; -} - -export function NoResults({items, filter, colSpan}) { +function NoResults({items, filter, colSpan}) { if (!items) { return ( @@ -81,11 +101,3 @@ export function NoResults({items, filter, colSpan}) { ); } } - -export function objectMap(items = {}) { - return Object.entries(items).map(([key, value]) => ( -
- {key}{value.length <= 50 ? value : `${value.substr(0, 50)}...`} -
- )); -} diff --git a/client/src/components/loading.js b/client/src/components/loading.js index 3b65652..ad397f2 100644 --- a/client/src/components/loading.js +++ b/client/src/components/loading.js @@ -4,7 +4,7 @@ import './loading.scss'; const Loading = ({text}) => (
- + {text != null ? text : 'Loading...'}
); diff --git a/client/src/components/loading.scss b/client/src/components/loading.scss index 1f3bce9..d81bbf9 100644 --- a/client/src/components/loading.scss +++ b/client/src/components/loading.scss @@ -6,7 +6,7 @@ justify-content: center; } -.loading_text { - font-size: $font-size-medium; - margin-left: 3px; -} +svg.loading_svg { + width: 30px; + height: 30px; +} \ No newline at end of file diff --git a/client/src/components/namespaceFilter.js b/client/src/components/namespaceFilter.js index 9531656..2791299 100644 --- a/client/src/components/namespaceFilter.js +++ b/client/src/components/namespaceFilter.js @@ -1,4 +1,5 @@ import React from 'react'; +import Select from 'react-select'; import Base from './base'; import api from '../services/api'; @@ -22,21 +23,23 @@ export default class NamespaceFilter extends Base { } render() { - const {namespace, namespaces = []} = this.state; + const {namespace = '', namespaces = []} = this.state; + + const options = namespaces.map(x => ({value: x.metadata.name, label: x.metadata.name})); + options.unshift({value: '', label: 'All Namespaces'}); + + const value = options.find(x => x.value === namespace); return ( - +
+ this.setContainer(x.target.value)} - > - {containers && containers.map(x => ( - - ))} - +
+ this.setContainer(x.target.value)} - > - {containers && containers.map(x => ( - - ))} - +
+