From d0581cd0c904a8f2548345a37d03a6197102e38b Mon Sep 17 00:00:00 2001
From: Breezewish
Date: Sat, 9 May 2020 17:39:52 +0800
Subject: [PATCH 01/14] Prevent animation bug when PD ip is invalid
---
ui/dashboardApp/layout/main/Sider/index.js | 93 +++++++++-------------
1 file changed, 38 insertions(+), 55 deletions(-)
diff --git a/ui/dashboardApp/layout/main/Sider/index.js b/ui/dashboardApp/layout/main/Sider/index.js
index 02dc3f36a6..a6cd0909d5 100644
--- a/ui/dashboardApp/layout/main/Sider/index.js
+++ b/ui/dashboardApp/layout/main/Sider/index.js
@@ -4,44 +4,26 @@ import { Layout, Menu } from 'antd'
import { Link } from 'react-router-dom'
import { useEventListener } from '@umijs/hooks'
import { useTranslation } from 'react-i18next'
-import { useTrail, useSpring, animated } from 'react-spring'
+import { useSpring, animated } from 'react-spring'
import client from '@lib/client'
import Banner from './Banner'
import styles from './index.module.less'
-const AnimatedMenuItem = animated(Menu.Item)
-const AnimatedSubMenu = animated(Menu.SubMenu)
-
-function TrailMenu({ items, delay, ...props }) {
- const trail = useTrail(items.length, {
- opacity: 1,
- transform: 'translate3d(0, 0, 0)',
- from: { opacity: 0, transform: 'translate3d(0, 60px, 0)' },
- delay,
- config: { mass: 1, tension: 5000, friction: 200 },
- })
- return (
-
- )
-}
-
-function useAnimatedAppMenuItem(registry, appId, title) {
+function useAppMenuItem(registry, appId, title) {
const { t } = useTranslation()
- return (animationProps) => {
- const app = registry.apps[appId]
- if (!app) {
- return null
- }
- return (
-
-
- {app.icon ? : null}
- {title ? title : t(`${appId}.nav_title`, appId)}
-
-
- )
+ const app = registry.apps[appId]
+ if (!app) {
+ return null
}
+ return (
+
+
+ {app.icon ? : null}
+ {title ? title : t(`${appId}.nav_title`, appId)}
+
+
+ )
}
function useActiveAppId(registry) {
@@ -69,7 +51,7 @@ function useCurrentLogin() {
return login
}
-export default function Sider({
+function Sider({
registry,
fullWidth,
defaultCollapsed,
@@ -82,11 +64,9 @@ export default function Sider({
const activeAppId = useActiveAppId(registry)
const currentLogin = useCurrentLogin()
- const debugSubMenuItems = [
- useAnimatedAppMenuItem(registry, 'instance_profiling'),
- ]
- const debugSubMenu = (animationProps) => (
-
@@ -94,26 +74,25 @@ export default function Sider({
{t('nav.sider.debug')}
}
- {...animationProps}
>
- {debugSubMenuItems.map((r) => r())}
-
+ {debugSubMenuItems}
+
)
const menuItems = [
- useAnimatedAppMenuItem(registry, 'overview'),
- useAnimatedAppMenuItem(registry, 'cluster_info'),
- useAnimatedAppMenuItem(registry, 'keyviz'),
- useAnimatedAppMenuItem(registry, 'statement'),
- useAnimatedAppMenuItem(registry, 'slow_query'),
- useAnimatedAppMenuItem(registry, 'diagnose'),
- useAnimatedAppMenuItem(registry, 'search_logs'),
+ useAppMenuItem(registry, 'overview'),
+ useAppMenuItem(registry, 'cluster_info'),
+ useAppMenuItem(registry, 'keyviz'),
+ useAppMenuItem(registry, 'statement'),
+ useAppMenuItem(registry, 'slow_query'),
+ useAppMenuItem(registry, 'diagnose'),
+ useAppMenuItem(registry, 'search_logs'),
debugSubMenu,
]
const extraMenuItems = [
- useAnimatedAppMenuItem(registry, 'dashboard_settings'),
- useAnimatedAppMenuItem(
+ useAppMenuItem(registry, 'dashboard_settings'),
+ useAppMenuItem(
registry,
'user_profile',
currentLogin ? currentLogin.username : '...'
@@ -142,20 +121,24 @@ export default function Sider({
fullWidth={fullWidth}
collapsedWidth={collapsedWidth}
/>
-
-
+ {menuItems}
+
+
+ >
+ {extraMenuItems}
+
)
}
+
+export default Sider
From 89a3313441cdb0f9b6b0e8ce3b4fad2df415deac Mon Sep 17 00:00:00 2001
From: Breezewish
Date: Sat, 9 May 2020 19:59:02 +0800
Subject: [PATCH 02/14] Small improvements
---
etc/manualTestEnv/.gitignore | 1 +
etc/manualTestEnv/basic/README.md | 19 +++++++++++++++++++
etc/manualTestEnv/basic/Vagrantfile | 15 +++++++++++++++
.../AnimatedSkeleton/index.module.less | 5 +++++
ui/lib/components/AnimatedSkeleton/index.tsx | 7 +------
5 files changed, 41 insertions(+), 6 deletions(-)
create mode 100644 etc/manualTestEnv/.gitignore
create mode 100644 etc/manualTestEnv/basic/README.md
create mode 100644 etc/manualTestEnv/basic/Vagrantfile
diff --git a/etc/manualTestEnv/.gitignore b/etc/manualTestEnv/.gitignore
new file mode 100644
index 0000000000..a977916f65
--- /dev/null
+++ b/etc/manualTestEnv/.gitignore
@@ -0,0 +1 @@
+.vagrant/
diff --git a/etc/manualTestEnv/basic/README.md b/etc/manualTestEnv/basic/README.md
new file mode 100644
index 0000000000..ce300a4ad7
--- /dev/null
+++ b/etc/manualTestEnv/basic/README.md
@@ -0,0 +1,19 @@
+# basic
+
+An environment with TiDB, PD, TiKV, TiFlash.
+
+## Usage
+
+Start the box and cluster:
+
+```ssh
+vagrant up
+vagrant ssh
+tiup playground nightly --monitor --host 10.0.1.2
+```
+
+Connect the cluster in the box:
+
+```ssh
+bin/tidb-dashboard --pd http://10.0.1.2:2379
+```
diff --git a/etc/manualTestEnv/basic/Vagrantfile b/etc/manualTestEnv/basic/Vagrantfile
new file mode 100644
index 0000000000..1dfffd2ee7
--- /dev/null
+++ b/etc/manualTestEnv/basic/Vagrantfile
@@ -0,0 +1,15 @@
+Vagrant.configure("2") do |config|
+ config.vm.box = "hashicorp/bionic64"
+ config.vm.network "private_network", ip: "10.0.1.2"
+ config.vm.provision "shell", privileged: false, inline: <<-SHELL
+ sudo apt install -y zsh
+ sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
+ sudo chsh -s /usr/bin/zsh vagrant
+ curl --proto '=https' --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh
+ source /home/vagrant/.zshrc
+ SHELL
+ config.vm.provider "virtualbox" do |v|
+ v.memory = 4096
+ v.cpus = 2
+ end
+end
diff --git a/ui/lib/components/AnimatedSkeleton/index.module.less b/ui/lib/components/AnimatedSkeleton/index.module.less
index 8db2e714ae..dc5bf0e153 100644
--- a/ui/lib/components/AnimatedSkeleton/index.module.less
+++ b/ui/lib/components/AnimatedSkeleton/index.module.less
@@ -8,4 +8,9 @@
width: 100%;
height: 100%;
}
+
+ .skeleton,
+ .content {
+ will-change: opacity;
+ }
}
diff --git a/ui/lib/components/AnimatedSkeleton/index.tsx b/ui/lib/components/AnimatedSkeleton/index.tsx
index 6c6f7b7510..572f059403 100644
--- a/ui/lib/components/AnimatedSkeleton/index.tsx
+++ b/ui/lib/components/AnimatedSkeleton/index.tsx
@@ -67,12 +67,7 @@ function AnimatedSkeleton({
}}
>
-
+
Date: Sun, 10 May 2020 12:04:26 +0800
Subject: [PATCH 03/14] Add instructions for env presets
---
etc/manualTestEnv/.gitignore | 2 +
etc/manualTestEnv/basic/README.md | 20 +++---
etc/manualTestEnv/basicMultiHost/README.md | 35 +++++++++++
etc/manualTestEnv/basicMultiHost/Vagrantfile | 23 +++++++
.../basicMultiHost/topology.yaml | 29 +++++++++
etc/manualTestEnv/multiReplica/README.md | 35 +++++++++++
etc/manualTestEnv/multiReplica/Vagrantfile | 19 ++++++
etc/manualTestEnv/multiReplica/topology.yaml | 61 +++++++++++++++++++
8 files changed, 214 insertions(+), 10 deletions(-)
create mode 100644 etc/manualTestEnv/basicMultiHost/README.md
create mode 100644 etc/manualTestEnv/basicMultiHost/Vagrantfile
create mode 100644 etc/manualTestEnv/basicMultiHost/topology.yaml
create mode 100644 etc/manualTestEnv/multiReplica/README.md
create mode 100644 etc/manualTestEnv/multiReplica/Vagrantfile
create mode 100644 etc/manualTestEnv/multiReplica/topology.yaml
diff --git a/etc/manualTestEnv/.gitignore b/etc/manualTestEnv/.gitignore
index a977916f65..dd2a4be7ca 100644
--- a/etc/manualTestEnv/.gitignore
+++ b/etc/manualTestEnv/.gitignore
@@ -1 +1,3 @@
.vagrant/
+shared_key
+shared_key.pub
diff --git a/etc/manualTestEnv/basic/README.md b/etc/manualTestEnv/basic/README.md
index ce300a4ad7..0e8040f179 100644
--- a/etc/manualTestEnv/basic/README.md
+++ b/etc/manualTestEnv/basic/README.md
@@ -4,16 +4,16 @@ An environment with TiDB, PD, TiKV, TiFlash.
## Usage
-Start the box and cluster:
+1. Start the box and cluster:
-```ssh
-vagrant up
-vagrant ssh
-tiup playground nightly --monitor --host 10.0.1.2
-```
+ ```bash
+ vagrant up
+ vagrant ssh
+ tiup playground nightly --monitor --host 10.0.1.2
+ ```
-Connect the cluster in the box:
+2. Outside the box, start TiDB Dashboard server:
-```ssh
-bin/tidb-dashboard --pd http://10.0.1.2:2379
-```
+ ```bash
+ bin/tidb-dashboard --pd http://10.0.1.2:2379
+ ```
diff --git a/etc/manualTestEnv/basicMultiHost/README.md b/etc/manualTestEnv/basicMultiHost/README.md
new file mode 100644
index 0000000000..0af0747a52
--- /dev/null
+++ b/etc/manualTestEnv/basicMultiHost/README.md
@@ -0,0 +1,35 @@
+# basicMultiHost
+
+An environment with TiDB, PD, TiKV, TiFlash, each in different host.
+
+## Usage
+
+1. Generate shared SSH key (only need to do it once):
+
+ ```bash
+ ssh-keygen -t rsa -b 2048 -f ./shared_key -q -N ""
+ ```
+
+1. Start the box:
+
+ ```bash
+ vagrant up
+ ```
+
+1. Use [TiUP](https://tiup.io/) to deploy the cluster to the box (only need to do it once):
+
+ ```bash
+ tiup cluster deploy multiHost nightly topology.yaml -i shared_key -y --user vagrant
+ ```
+
+1. Start the cluster in the box:
+
+ ```bash
+ tiup cluster start multiHost
+ ```
+
+1. Start TiDB Dashboard server:
+
+ ```bash
+ bin/tidb-dashboard --pd http://10.0.1.11:2379
+ ```
diff --git a/etc/manualTestEnv/basicMultiHost/Vagrantfile b/etc/manualTestEnv/basicMultiHost/Vagrantfile
new file mode 100644
index 0000000000..87bb599f69
--- /dev/null
+++ b/etc/manualTestEnv/basicMultiHost/Vagrantfile
@@ -0,0 +1,23 @@
+Vagrant.configure("2") do |config|
+ ssh_pub_key = File.readlines("#{File.dirname(__FILE__)}/shared_key.pub").first.strip
+
+ config.vm.box = "hashicorp/bionic64"
+ config.vm.provision "shell", privileged: false, inline: <<-SHELL
+ sudo apt install -y zsh
+ sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
+ sudo chsh -s /usr/bin/zsh vagrant
+
+ echo #{ssh_pub_key} >> /home/vagrant/.ssh/authorized_keys
+ SHELL
+
+ config.vm.provider "virtualbox" do |v|
+ v.memory = 1024
+ v.cpus = 1
+ end
+
+ (1..4).each do |i|
+ config.vm.define "node #{i}" do |node|
+ node.vm.network "private_network", ip: "10.0.1.#{i+10}"
+ end
+ end
+end
diff --git a/etc/manualTestEnv/basicMultiHost/topology.yaml b/etc/manualTestEnv/basicMultiHost/topology.yaml
new file mode 100644
index 0000000000..15fe4aa74a
--- /dev/null
+++ b/etc/manualTestEnv/basicMultiHost/topology.yaml
@@ -0,0 +1,29 @@
+global:
+ user: tidb
+ deploy_dir: "tidb-deploy"
+ data_dir: "tidb-data"
+
+server_configs:
+ pd:
+ replication.enable-placement-rules: true
+
+pd_servers:
+ - host: 10.0.1.11
+
+tikv_servers:
+ - host: 10.0.1.12
+
+tidb_servers:
+ - host: 10.0.1.13
+
+tiflash_servers:
+ - host: 10.0.1.14
+
+grafana_servers:
+ - host: 10.0.1.11
+
+monitoring_servers:
+ - host: 10.0.1.11
+
+alertmanager_servers:
+ - host: 10.0.1.11
diff --git a/etc/manualTestEnv/multiReplica/README.md b/etc/manualTestEnv/multiReplica/README.md
new file mode 100644
index 0000000000..2c139afff3
--- /dev/null
+++ b/etc/manualTestEnv/multiReplica/README.md
@@ -0,0 +1,35 @@
+# multiReplica
+
+An environment with multiple TiKV nodes in different labels.
+
+## Usage
+
+1. Generate shared SSH key (only need to do it once):
+
+ ```bash
+ ssh-keygen -t rsa -b 2048 -f ./shared_key -q -N ""
+ ```
+
+1. Start the box:
+
+ ```bash
+ vagrant up
+ ```
+
+1. Use [TiUP](https://tiup.io/) to deploy the cluster to the box (only need to do it once):
+
+ ```bash
+ tiup cluster deploy multiReplica nightly topology.yaml -i shared_key -y --user vagrant
+ ```
+
+1. Start the cluster in the box:
+
+ ```bash
+ tiup cluster start multiReplica
+ ```
+
+1. Start TiDB Dashboard server:
+
+ ```bash
+ bin/tidb-dashboard --pd http://10.0.1.20:2379
+ ```
diff --git a/etc/manualTestEnv/multiReplica/Vagrantfile b/etc/manualTestEnv/multiReplica/Vagrantfile
new file mode 100644
index 0000000000..5a0e123cff
--- /dev/null
+++ b/etc/manualTestEnv/multiReplica/Vagrantfile
@@ -0,0 +1,19 @@
+Vagrant.configure("2") do |config|
+ ssh_pub_key = File.readlines("#{File.dirname(__FILE__)}/shared_key.pub").first.strip
+
+ config.vm.box = "hashicorp/bionic64"
+ config.vm.provision "shell", privileged: false, inline: <<-SHELL
+ sudo apt install -y zsh
+ sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
+ sudo chsh -s /usr/bin/zsh vagrant
+
+ echo #{ssh_pub_key} >> /home/vagrant/.ssh/authorized_keys
+ SHELL
+
+ config.vm.provider "virtualbox" do |v|
+ v.memory = 4096
+ v.cpus = 2
+ end
+
+ config.vm.network "private_network", ip: "10.0.1.20"
+end
diff --git a/etc/manualTestEnv/multiReplica/topology.yaml b/etc/manualTestEnv/multiReplica/topology.yaml
new file mode 100644
index 0000000000..78a03385a1
--- /dev/null
+++ b/etc/manualTestEnv/multiReplica/topology.yaml
@@ -0,0 +1,61 @@
+global:
+ user: tidb
+ deploy_dir: "tidb-deploy"
+ data_dir: "tidb-data"
+
+server_configs:
+ tikv:
+ server.grpc-concurrency: 1
+ raftstore.apply-pool-size: 1
+ raftstore.store-pool-size: 1
+ readpool.unified.max-thread-count: 1
+ readpool.storage.use-unified-pool: false
+ readpool.coprocessor.use-unified-pool: true
+ storage.block-cache.capacity: 256MB
+ raftstore.capacity: 10GB
+ pd:
+ replication.location-labels: ["zone", "rack", "host"]
+
+pd_servers:
+ - host: 10.0.1.20
+
+tikv_servers:
+ - host: 10.0.1.20
+ port: 20160
+ status_port: 20180
+ config:
+ server.labels: { host: "tikv1", rack: "rack1" }
+ - host: 10.0.1.20
+ port: 20161
+ status_port: 20181
+ config:
+ server.labels: { host: "tikv1", rack: "rack1" }
+ - host: 10.0.1.20
+ port: 20162
+ status_port: 20182
+ config:
+ server.labels: { host: "tikv2", rack: "rack1" }
+ - host: 10.0.1.20
+ port: 20163
+ status_port: 20183
+ config:
+ server.labels: { host: "tikv2", rack: "rack1" }
+ - host: 10.0.1.20
+ port: 20164
+ status_port: 20184
+ config:
+ server.labels: { host: "tikv3", rack: "rack2" }
+ - host: 10.0.1.20
+ port: 20165
+ status_port: 20185
+ config:
+ server.labels: { host: "tikv3", rack: "rack2" }
+
+tidb_servers:
+ - host: 10.0.1.20
+
+grafana_servers:
+ - host: 10.0.1.20
+
+monitoring_servers:
+ - host: 10.0.1.20
From fa50922bd8eade6e5faa25530d41d23745ac0a1b Mon Sep 17 00:00:00 2001
From: Breezewish
Date: Mon, 11 May 2020 11:59:51 +0800
Subject: [PATCH 04/14] Remove some unnecessary quotes
Signed-off-by: Breezewish
---
.../basicMultiHost/topology.yaml | 4 ++--
etc/manualTestEnv/multiReplica/topology.yaml | 21 +++++++++++--------
2 files changed, 14 insertions(+), 11 deletions(-)
diff --git a/etc/manualTestEnv/basicMultiHost/topology.yaml b/etc/manualTestEnv/basicMultiHost/topology.yaml
index 15fe4aa74a..f2039e4ca3 100644
--- a/etc/manualTestEnv/basicMultiHost/topology.yaml
+++ b/etc/manualTestEnv/basicMultiHost/topology.yaml
@@ -1,7 +1,7 @@
global:
user: tidb
- deploy_dir: "tidb-deploy"
- data_dir: "tidb-data"
+ deploy_dir: tidb-deploy
+ data_dir: tidb-data
server_configs:
pd:
diff --git a/etc/manualTestEnv/multiReplica/topology.yaml b/etc/manualTestEnv/multiReplica/topology.yaml
index 78a03385a1..cad40a20ea 100644
--- a/etc/manualTestEnv/multiReplica/topology.yaml
+++ b/etc/manualTestEnv/multiReplica/topology.yaml
@@ -1,7 +1,7 @@
global:
user: tidb
- deploy_dir: "tidb-deploy"
- data_dir: "tidb-data"
+ deploy_dir: tidb-deploy
+ data_dir: tidb-data
server_configs:
tikv:
@@ -14,7 +14,10 @@ server_configs:
storage.block-cache.capacity: 256MB
raftstore.capacity: 10GB
pd:
- replication.location-labels: ["zone", "rack", "host"]
+ replication.location-labels:
+ - zone
+ - rack
+ - host
pd_servers:
- host: 10.0.1.20
@@ -24,32 +27,32 @@ tikv_servers:
port: 20160
status_port: 20180
config:
- server.labels: { host: "tikv1", rack: "rack1" }
+ server.labels: { host: tikv1, rack: rack1 }
- host: 10.0.1.20
port: 20161
status_port: 20181
config:
- server.labels: { host: "tikv1", rack: "rack1" }
+ server.labels: { host: tikv1, rack: rack1 }
- host: 10.0.1.20
port: 20162
status_port: 20182
config:
- server.labels: { host: "tikv2", rack: "rack1" }
+ server.labels: { host: tikv2, rack: rack1 }
- host: 10.0.1.20
port: 20163
status_port: 20183
config:
- server.labels: { host: "tikv2", rack: "rack1" }
+ server.labels: { host: tikv2, rack: rack1 }
- host: 10.0.1.20
port: 20164
status_port: 20184
config:
- server.labels: { host: "tikv3", rack: "rack2" }
+ server.labels: { host: tikv3, rack: rack2 }
- host: 10.0.1.20
port: 20165
status_port: 20185
config:
- server.labels: { host: "tikv3", rack: "rack2" }
+ server.labels: { host: tikv3, rack: rack2 }
tidb_servers:
- host: 10.0.1.20
From eb0f902716e794c3a4ab37798d169ec7bdd79a35 Mon Sep 17 00:00:00 2001
From: Breezewish
Date: Thu, 14 May 2020 11:25:37 +0800
Subject: [PATCH 05/14] wip
Signed-off-by: Breezewish
---
pkg/apiserver/clusterinfo/fetch.go | 97 ----
pkg/apiserver/clusterinfo/service.go | 241 +++++---
pkg/apiserver/clusterinfo/topology.go | 32 ++
pkg/apiserver/metrics/metrics.go | 31 +-
pkg/utils/clusterinfo/fetcher.go | 518 ------------------
.../clusterinfo.go => topology/models.go} | 36 +-
pkg/utils/topology/monitor.go | 51 ++
pkg/utils/topology/pd.go | 146 +++++
pkg/utils/topology/store.go | 155 ++++++
pkg/utils/topology/tidb.go | 139 +++++
pkg/utils/topology/topology.go | 87 +++
ui/dashboardApp/index.js | 6 +-
ui/dashboardApp/layout/main/Sider/index.js | 1 +
.../apps/ClusterInfo/components/HostTable.tsx | 2 +-
.../ClusterInfo/components/InstanceTable.tsx | 273 ++++-----
ui/lib/apps/ClusterInfo/translations/en.yaml | 7 -
.../apps/ClusterInfo/translations/zh-CN.yaml | 7 -
ui/lib/apps/DebugPlayground/index.meta.ts | 8 +
ui/lib/apps/DebugPlayground/index.tsx | 58 ++
ui/lib/apps/InstanceProfiling/pages/List.tsx | 83 +--
.../KeyViz/components/KeyVizSettingForm.tsx | 15 +-
.../components/MonitorAlertBar.module.less | 8 -
.../Overview/components/MonitorAlertBar.tsx | 119 ++--
ui/lib/apps/Overview/components/Nodes.tsx | 150 ++---
ui/lib/apps/Overview/index.tsx | 18 +-
ui/lib/apps/Overview/translations/en.yaml | 9 +-
ui/lib/apps/Overview/translations/zh-CN.yaml | 11 +-
.../SearchLogs/components/SearchHeader.tsx | 8 +-
ui/lib/apps/SearchLogs/components/utils.ts | 119 ++--
.../components/BaseSelect/index.module.less | 89 +++
ui/lib/components/BaseSelect/index.tsx | 183 +++++++
ui/lib/components/CardTableV2/GroupHeader.tsx | 114 ++++
ui/lib/components/CardTableV2/index.tsx | 53 +-
.../InstanceSelect/DropOverlay.module.less | 6 +
.../components/InstanceSelect/DropOverlay.tsx | 56 ++
.../InstanceSelect/SelectDisplay.tsx | 68 +++
ui/lib/components/InstanceSelect/index.tsx | 165 ++++++
.../components/InstanceStatusBadge/index.tsx | 83 +++
ui/lib/components/index.ts | 6 +
ui/lib/utils/form.ts | 11 -
ui/lib/utils/instanceTable.ts | 92 ++++
ui/lib/utils/useClientRequest.ts | 10 +-
42 files changed, 2157 insertions(+), 1214 deletions(-)
delete mode 100644 pkg/apiserver/clusterinfo/fetch.go
create mode 100644 pkg/apiserver/clusterinfo/topology.go
delete mode 100644 pkg/utils/clusterinfo/fetcher.go
rename pkg/utils/{clusterinfo/clusterinfo.go => topology/models.go} (67%)
create mode 100644 pkg/utils/topology/monitor.go
create mode 100644 pkg/utils/topology/pd.go
create mode 100644 pkg/utils/topology/store.go
create mode 100644 pkg/utils/topology/tidb.go
create mode 100644 pkg/utils/topology/topology.go
create mode 100644 ui/lib/apps/DebugPlayground/index.meta.ts
create mode 100644 ui/lib/apps/DebugPlayground/index.tsx
delete mode 100644 ui/lib/apps/Overview/components/MonitorAlertBar.module.less
create mode 100644 ui/lib/components/BaseSelect/index.module.less
create mode 100644 ui/lib/components/BaseSelect/index.tsx
create mode 100644 ui/lib/components/CardTableV2/GroupHeader.tsx
create mode 100644 ui/lib/components/InstanceSelect/DropOverlay.module.less
create mode 100644 ui/lib/components/InstanceSelect/DropOverlay.tsx
create mode 100644 ui/lib/components/InstanceSelect/SelectDisplay.tsx
create mode 100644 ui/lib/components/InstanceSelect/index.tsx
create mode 100644 ui/lib/components/InstanceStatusBadge/index.tsx
delete mode 100644 ui/lib/utils/form.ts
create mode 100644 ui/lib/utils/instanceTable.ts
diff --git a/pkg/apiserver/clusterinfo/fetch.go b/pkg/apiserver/clusterinfo/fetch.go
deleted file mode 100644
index 182660fc52..0000000000
--- a/pkg/apiserver/clusterinfo/fetch.go
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 2020 PingCAP, Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package clusterinfo
-
-import (
- "context"
-
- "github.com/pingcap-incubator/tidb-dashboard/pkg/utils/clusterinfo"
-)
-
-type ClusterInfo struct {
- TiDB struct {
- Nodes []clusterinfo.TiDBInfo `json:"nodes"`
- Err *string `json:"err"`
- } `json:"tidb"`
-
- TiKV struct {
- Nodes []clusterinfo.TiKVInfo `json:"nodes"`
- Err *string `json:"err"`
- } `json:"tikv"`
-
- PD struct {
- Nodes []clusterinfo.PDInfo `json:"nodes"`
- Err *string `json:"err"`
- } `json:"pd"`
-
- TiFlash struct {
- Nodes []clusterinfo.TiFlashInfo `json:"nodes"`
- Err *string `json:"err"`
- } `json:"tiflash"`
-
- Grafana *clusterinfo.GrafanaInfo `json:"grafana"`
- AlertManager *clusterinfo.AlertManagerInfo `json:"alert_manager"`
-}
-
-// fetches etcd, and parses the ns below:
-// * /topology/grafana
-// * /topology/alertmanager
-// * /topology/tidb
-func fillTopologyUnderEtcd(ctx context.Context, service *Service, fillTargetInfo *ClusterInfo) {
- tidb, grafana, alertManager, err := clusterinfo.GetTopologyUnderEtcd(ctx, service.etcdClient)
- if err != nil {
- // Note: GetTopology return error only when fetch etcd failed.
- // So it's ok to fill all of them err
- errString := err.Error()
- fillTargetInfo.TiDB.Err = &errString
- return
- }
- if grafana != nil {
- fillTargetInfo.Grafana = grafana
- }
- if alertManager != nil {
- fillTargetInfo.AlertManager = alertManager
- }
- //if len(tidb) == 0 {
- // tidb, err = clusterinfo.GetTiDBTopologyFromOld(ctx, service.etcdClient)
- // if err != nil {
- // errString := err.Error()
- // fillTargetInfo.TiDB.Err = &errString
- // return
- // }
- //}
- fillTargetInfo.TiDB.Nodes = tidb
-}
-
-func fillPDTopology(ctx context.Context, service *Service, fillTargetInfo *ClusterInfo) {
- pdPeers, err := clusterinfo.GetPDTopology(service.config.PDEndPoint, service.httpClient)
- if err != nil {
- errString := err.Error()
- fillTargetInfo.PD.Err = &errString
- return
- }
- fillTargetInfo.PD.Nodes = pdPeers
-}
-
-func fillStoreTopology(ctx context.Context, service *Service, fillTargetInfo *ClusterInfo) {
- kv, tiflashes, err := clusterinfo.GetStoreTopology(service.config.PDEndPoint, service.httpClient)
- if err != nil {
- errString := err.Error()
- fillTargetInfo.TiKV.Err = &errString
- fillTargetInfo.TiFlash.Err = &errString
- return
- }
- fillTargetInfo.TiKV.Nodes = kv
- fillTargetInfo.TiFlash.Nodes = tiflashes
-}
diff --git a/pkg/apiserver/clusterinfo/service.go b/pkg/apiserver/clusterinfo/service.go
index e306dae32d..463f1ad64e 100644
--- a/pkg/apiserver/clusterinfo/service.go
+++ b/pkg/apiserver/clusterinfo/service.go
@@ -20,6 +20,7 @@ import (
"context"
"fmt"
"net/http"
+ "sort"
"sync"
"time"
@@ -30,7 +31,7 @@ import (
"github.com/pingcap-incubator/tidb-dashboard/pkg/apiserver/utils"
"github.com/pingcap-incubator/tidb-dashboard/pkg/config"
"github.com/pingcap-incubator/tidb-dashboard/pkg/tidb"
- "github.com/pingcap-incubator/tidb-dashboard/pkg/utils/clusterinfo"
+ "github.com/pingcap-incubator/tidb-dashboard/pkg/utils/topology"
)
type Service struct {
@@ -52,14 +53,18 @@ func NewService(config *config.Config, etcdClient *clientv3.Client, httpClient *
func Register(r *gin.RouterGroup, auth *user.AuthService, s *Service) {
endpoint := r.Group("/topology")
endpoint.Use(auth.MWAuthRequired())
- endpoint.GET("/all", s.topologyHandler)
- endpoint.DELETE("/tidb/:address", s.deleteTiDBTopologyHandler)
- endpoint.GET("/alertmanager/:address/count", s.topologyGetAlertCount)
+ endpoint.GET("/tidb", s.getTiDBTopology)
+ endpoint.DELETE("/tidb/:address", s.deleteTiDBTopology)
+ endpoint.GET("/store", s.getStoreTopology)
+ endpoint.GET("/pd", s.getPDTopology)
+ endpoint.GET("/alertmanager", s.getAlertManagerTopology)
+ endpoint.GET("/alertmanager/:address/count", s.getAlertManagerCounts)
+ endpoint.GET("/grafana", s.getGrafanaTopology)
endpoint = r.Group("/host")
endpoint.Use(auth.MWAuthRequired())
endpoint.Use(utils.MWConnectTiDB(s.tidbForwarder))
- endpoint.GET("/all", s.hostHandler)
+ endpoint.GET("/all", s.getHostsInfo)
}
// @Summary Delete etcd's tidb key.
@@ -70,7 +75,7 @@ func Register(r *gin.RouterGroup, auth *user.AuthService, s *Service) {
// @Failure 401 {object} utils.APIError "Unauthorized failure"
// @Security JwtAuth
// @Router /topology/tidb/{address} [delete]
-func (s *Service) deleteTiDBTopologyHandler(c *gin.Context) {
+func (s *Service) deleteTiDBTopology(c *gin.Context) {
address := c.Param("address")
errorChannel := make(chan error, 2)
ttlKey := fmt.Sprintf("/topology/tidb/%v/ttl", address)
@@ -103,50 +108,111 @@ func (s *Service) deleteTiDBTopologyHandler(c *gin.Context) {
c.JSON(http.StatusOK, nil)
}
-// @Summary Get all Dashboard topology and liveness.
-// @Description Get information about the dashboard topology.
+// @ID getTiDBTopology
+// @Summary Get TiDB instances
+// @Description Get TiDB instances topology
// @Produce json
-// @Success 200 {object} clusterinfo.ClusterInfo
-// @Router /topology/all [get]
+// @Success 200 {array} topology.TiDBInfo
+// @Router /topology/tidb [get]
// @Security JwtAuth
// @Failure 401 {object} utils.APIError "Unauthorized failure"
-func (s *Service) topologyHandler(c *gin.Context) {
- var returnObject ClusterInfo
+func (s *Service) getTiDBTopology(c *gin.Context) {
+ instances, err := topology.FetchTiDBTopology(s.etcdClient)
+ if err != nil {
+ _ = c.Error(err)
+ return
+ }
+ c.JSON(http.StatusOK, instances)
+}
- ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
- defer cancel()
+type StoreTopologyResponse struct {
+ TiKV []topology.StoreInfo `json:"tikv"`
+ TiFlash []topology.StoreInfo `json:"tiflash"`
+}
- fetchers := []func(ctx context.Context, service *Service, info *ClusterInfo){
- fillTopologyUnderEtcd,
- fillStoreTopology,
- fillPDTopology,
+// @ID getStoreTopology
+// @Summary Get TiKV / TiFlash instances
+// @Description Get TiKV / TiFlash instances topology
+// @Produce json
+// @Success 200 {object} StoreTopologyResponse
+// @Router /topology/store [get]
+// @Security JwtAuth
+// @Failure 401 {object} utils.APIError "Unauthorized failure"
+func (s *Service) getStoreTopology(c *gin.Context) {
+ tikvInstances, tiFlashInstances, err := topology.FetchStoreTopology(s.config.PDEndPoint, s.httpClient)
+ if err != nil {
+ _ = c.Error(err)
+ return
}
+ c.JSON(http.StatusOK, StoreTopologyResponse{
+ TiKV: tikvInstances,
+ TiFlash: tiFlashInstances,
+ })
+}
- var wg sync.WaitGroup
- for _, fetcher := range fetchers {
- wg.Add(1)
- currentFetcher := fetcher
- go func() {
- defer wg.Done()
- currentFetcher(ctx, s, &returnObject)
- }()
+// @ID getPDTopology
+// @Summary Get PD instances
+// @Description Get PD instances topology
+// @Produce json
+// @Success 200 {array} topology.PDInfo
+// @Router /topology/pd [get]
+// @Security JwtAuth
+// @Failure 401 {object} utils.APIError "Unauthorized failure"
+func (s *Service) getPDTopology(c *gin.Context) {
+ instances, err := topology.FetchPDTopology(s.config.PDEndPoint, s.httpClient)
+ if err != nil {
+ _ = c.Error(err)
+ return
}
- wg.Wait()
+ c.JSON(http.StatusOK, instances)
+}
- c.JSON(http.StatusOK, returnObject)
+// @ID getAlertManagerTopology
+// @Summary Get AlertManager instance
+// @Description Get AlertManager instance topology
+// @Produce json
+// @Success 200 {object} topology.AlertManagerInfo
+// @Router /topology/alertmanager [get]
+// @Security JwtAuth
+// @Failure 401 {object} utils.APIError "Unauthorized failure"
+func (s *Service) getAlertManagerTopology(c *gin.Context) {
+ instance, err := topology.FetchAlertManagerTopology(s.etcdClient)
+ if err != nil {
+ _ = c.Error(err)
+ return
+ }
+ c.JSON(http.StatusOK, instance)
+}
+
+// @ID getGrafanaTopology
+// @Summary Get Grafana instance
+// @Description Get Grafana instance topology
+// @Produce json
+// @Success 200 {object} topology.GrafanaInfo
+// @Router /topology/grafana [get]
+// @Security JwtAuth
+// @Failure 401 {object} utils.APIError "Unauthorized failure"
+func (s *Service) getGrafanaTopology(c *gin.Context) {
+ instance, err := topology.FetchGrafanaTopology(s.etcdClient)
+ if err != nil {
+ _ = c.Error(err)
+ return
+ }
+ c.JSON(http.StatusOK, instance)
}
-// @Summary Get the count of alert
-// @Description Get alert number of the alert manager.
+// @ID getAlertManagerCounts
+// @Summary Get alert count
+// @Description Get alert count from alert manager
// @Produce json
// @Success 200 {object} int
// @Param address path string true "ip:port"
// @Router /topology/alertmanager/{address}/count [get]
// @Security JwtAuth
// @Failure 401 {object} utils.APIError "Unauthorized failure"
-func (s *Service) topologyGetAlertCount(c *gin.Context) {
+func (s *Service) getAlertManagerCounts(c *gin.Context) {
address := c.Param("address")
- cnt, err := clusterinfo.GetAlertCountByAddress(address, s.httpClient)
+ cnt, err := fetchAlertManagerCounts(address, s.httpClient)
if err != nil {
_ = c.Error(err)
return
@@ -154,6 +220,7 @@ func (s *Service) topologyGetAlertCount(c *gin.Context) {
c.JSON(http.StatusOK, cnt)
}
+// @ID getHostsInfo
// @Summary Get all host information in the cluster
// @Description Get information about host in the cluster
// @Produce json
@@ -161,80 +228,72 @@ func (s *Service) topologyGetAlertCount(c *gin.Context) {
// @Router /host/all [get]
// @Security JwtAuth
// @Failure 401 {object} utils.APIError "Unauthorized failure"
-func (s *Service) hostHandler(c *gin.Context) {
+func (s *Service) getHostsInfo(c *gin.Context) {
db := utils.GetTiDBConnection(c)
- ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
- defer cancel()
-
- var wg sync.WaitGroup
- var clusterInfo ClusterInfo
- fetchers := []func(ctx context.Context, service *Service, info *ClusterInfo){
- fillTopologyUnderEtcd,
- fillStoreTopology,
- fillPDTopology,
- }
- for _, fetcher := range fetchers {
- wg.Add(1)
- currentFetcher := fetcher
- go func() {
- defer wg.Done()
- currentFetcher(ctx, s, &clusterInfo)
- }()
+ allHostsMap, err := s.fetchAllInstanceHostsMap()
+ if err != nil {
+ _ = c.Error(err)
+ return
}
-
- var infos []HostInfo
- var err error
- wg.Add(1)
- go func() {
- defer wg.Done()
- infos, err = GetAllHostInfo(db)
- }()
- wg.Wait()
-
+ hostsInfo, err := GetAllHostInfo(db)
if err != nil {
_ = c.Error(err)
return
}
- allHosts := loadUnavailableHosts(clusterInfo)
+ hostsInfoMap := make(map[string]HostInfo)
+ for _, hi := range hostsInfo {
+ hostsInfoMap[hi.IP] = hi
+ }
-OuterLoop:
- for _, host := range allHosts {
- for _, info := range infos {
- if host == info.IP {
- continue OuterLoop
- }
+ hiList := make([]HostInfo, 0, len(hostsInfo))
+ for hostIP, _ := range allHostsMap {
+ if hi, ok := hostsInfoMap[hostIP]; ok {
+ hiList = append(hiList, hi)
+ } else {
+ hiList = append(hiList, HostInfo{
+ IP: hostIP,
+ Unavailable: true,
+ })
}
- infos = append(infos, HostInfo{
- IP: host,
- Unavailable: true,
- })
}
- c.JSON(http.StatusOK, infos)
+ sort.Slice(hiList, func(i, j int) bool {
+ return hiList[i].IP > hiList[j].IP
+ })
+
+ c.JSON(http.StatusOK, hiList)
}
-func loadUnavailableHosts(info ClusterInfo) []string {
- var allNodes []string
- for _, node := range info.TiDB.Nodes {
- if node.Status != clusterinfo.ComponentStatusUp {
- allNodes = append(allNodes, node.IP)
- }
+func (s *Service) fetchAllInstanceHostsMap() (map[string]struct{}, error) {
+ allHosts := make(map[string]struct{})
+ pdInfo, err := topology.FetchPDTopology(s.config.PDEndPoint, s.httpClient)
+ if err != nil {
+ return nil, err
}
- for _, node := range info.TiKV.Nodes {
- switch node.Status {
- case clusterinfo.ComponentStatusUp,
- clusterinfo.ComponentStatusOffline,
- clusterinfo.ComponentStatusTombstone:
- default:
- allNodes = append(allNodes, node.IP)
- }
+ for _, i := range pdInfo {
+ allHosts[i.IP] = struct{}{}
}
- for _, node := range info.PD.Nodes {
- if node.Status != clusterinfo.ComponentStatusUp {
- allNodes = append(allNodes, node.IP)
- }
+
+ tikvInfo, tiFlashInfo, err := topology.FetchStoreTopology(s.config.PDEndPoint, s.httpClient)
+ if err != nil {
+ return nil, err
+ }
+ for _, i := range tikvInfo {
+ allHosts[i.IP] = struct{}{}
+ }
+ for _, i := range tiFlashInfo {
+ allHosts[i.IP] = struct{}{}
+ }
+
+ tidbInfo, err := topology.FetchTiDBTopology(s.etcdClient)
+ if err != nil {
+ return nil, err
}
- return allNodes
+ for _, i := range tidbInfo {
+ allHosts[i.IP] = struct{}{}
+ }
+
+ return allHosts, nil
}
diff --git a/pkg/apiserver/clusterinfo/topology.go b/pkg/apiserver/clusterinfo/topology.go
new file mode 100644
index 0000000000..aa8ba69f39
--- /dev/null
+++ b/pkg/apiserver/clusterinfo/topology.go
@@ -0,0 +1,32 @@
+package clusterinfo
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+)
+
+func fetchAlertManagerCounts(alertManagerAddr string, httpClient *http.Client) (int, error) {
+ apiAddress := fmt.Sprintf("http://%s/api/v2/alerts", alertManagerAddr)
+ resp, err := httpClient.Get(apiAddress)
+ if err != nil {
+ return 0, err
+ }
+
+ defer resp.Body.Close()
+ data, err := ioutil.ReadAll(resp.Body)
+
+ if err != nil {
+ return 0, err
+ }
+
+ var alerts []struct{}
+
+ err = json.Unmarshal(data, &alerts)
+ if err != nil {
+ return 0, err
+ }
+
+ return len(alerts), nil
+}
diff --git a/pkg/apiserver/metrics/metrics.go b/pkg/apiserver/metrics/metrics.go
index 50096e0a6e..dd4d1b781c 100644
--- a/pkg/apiserver/metrics/metrics.go
+++ b/pkg/apiserver/metrics/metrics.go
@@ -1,8 +1,6 @@
package metrics
import (
- "context"
- "encoding/json"
"fmt"
"io/ioutil"
"net/http"
@@ -15,15 +13,13 @@ import (
"go.etcd.io/etcd/clientv3"
"github.com/pingcap-incubator/tidb-dashboard/pkg/apiserver/user"
- "github.com/pingcap-incubator/tidb-dashboard/pkg/utils/clusterinfo"
+ "github.com/pingcap-incubator/tidb-dashboard/pkg/utils/topology"
)
var (
- ErrNS = errorx.NewNamespace("error.api.metrics")
- ErrEtcdAccessFailed = ErrNS.NewType("etcd_access_failed")
- ErrPrometheusNotFound = ErrNS.NewType("prometheus_not_found")
- ErrPrometheusRegistryInvalid = ErrNS.NewType("prometheus_registry_invalid")
- ErrPrometheusQueryFailed = ErrNS.NewType("prometheus_query_failed")
+ ErrNS = errorx.NewNamespace("error.api.metrics")
+ ErrPrometheusNotFound = ErrNS.NewType("prometheus_not_found")
+ ErrPrometheusQueryFailed = ErrNS.NewType("prometheus_query_failed")
)
type Service struct {
@@ -69,22 +65,15 @@ func (s *Service) queryHandler(c *gin.Context) {
return
}
- ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
- defer cancel()
- resp, err := s.etcdClient.Get(ctx, "/topology/prometheus", clientv3.WithPrefix())
+ pi, err := topology.FetchPrometheusTopology(s.etcdClient)
if err != nil {
- _ = c.Error(ErrEtcdAccessFailed.NewWithNoMessage())
+ _ = c.Error(err)
return
}
- if resp.Count == 0 {
+ if pi == nil {
_ = c.Error(ErrPrometheusNotFound.NewWithNoMessage())
return
}
- info := clusterinfo.PrometheusInfo{}
- if err = json.Unmarshal(resp.Kvs[0].Value, &info); err != nil {
- _ = c.Error(ErrPrometheusRegistryInvalid.NewWithNoMessage())
- return
- }
params := url.Values{}
params.Add("query", req.Query)
@@ -95,15 +84,15 @@ func (s *Service) queryHandler(c *gin.Context) {
client := http.Client{
Timeout: 10 * time.Second,
}
- promResp, err := client.Get(fmt.Sprintf("http://%s:%d/api/v1/query_range?%s", info.IP, info.Port, params.Encode()))
+ promResp, err := client.Get(fmt.Sprintf("http://%s:%d/api/v1/query_range?%s", pi.IP, pi.Port, params.Encode()))
if err != nil {
- _ = c.Error(ErrPrometheusQueryFailed.Wrap(err, "failed to query Prometheus"))
+ _ = c.Error(ErrPrometheusQueryFailed.Wrap(err, "failed to send requests to Prometheus"))
return
}
defer promResp.Body.Close()
body, err := ioutil.ReadAll(promResp.Body)
if err != nil {
- _ = c.Error(ErrPrometheusQueryFailed.Wrap(err, "failed to query Prometheus"))
+ _ = c.Error(ErrPrometheusQueryFailed.Wrap(err, "failed to read Prometheus query result"))
return
}
c.Data(promResp.StatusCode, promResp.Header.Get("content-type"), body)
diff --git a/pkg/utils/clusterinfo/fetcher.go b/pkg/utils/clusterinfo/fetcher.go
deleted file mode 100644
index dfa1d4dd22..0000000000
--- a/pkg/utils/clusterinfo/fetcher.go
+++ /dev/null
@@ -1,518 +0,0 @@
-// Copyright 2020 PingCAP, Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package clusterinfo
-
-import (
- "context"
- "encoding/json"
- "fmt"
- "io/ioutil"
- "net/http"
- "net/url"
- "strconv"
- "strings"
- "time"
-
- "github.com/pingcap/log"
- "go.etcd.io/etcd/clientv3"
- "go.uber.org/zap"
-)
-
-// GetTopology return error only when fetch etcd failed.
-func GetTopologyUnderEtcd(ctx context.Context, etcdClient *clientv3.Client) (tidbNodes []TiDBInfo, grafanaNode *GrafanaInfo, alertManagerNode *AlertManagerInfo, e error) {
- resp, err := etcdClient.Get(ctx, "/topology", clientv3.WithPrefix())
- if err != nil {
- return nil, nil, nil, err
- }
- tidbTTLMap := map[string][]byte{}
- tidbEntryMap := map[string]*TiDBInfo{}
- for _, kv := range resp.Kvs {
- keyParts := strings.Split(string(kv.Key), "/")[1:]
- if len(keyParts) < 2 {
- continue
- }
- // There can be four kinds of keys:
- // * /topology/grafana: stores grafana topology info.
- // * /topology/alertmanager: stores alertmanager topology info.
- // * /topology/tidb/ip:port/info: stores tidb topology info.
- // * /topology/tidb/ip:port/ttl : stores tidb last update ttl time.
- switch keyParts[1] {
- case "grafana":
- r := GrafanaInfo{}
- if err = json.Unmarshal(kv.Value, &r); err != nil {
- continue
- }
- grafanaNode = &r
- case "alertmanager":
- r := AlertManagerInfo{}
- if err = json.Unmarshal(kv.Value, &r); err != nil {
- continue
- }
- alertManagerNode = &r
- case "tidb":
- // the key should be like /topology/tidb/ip:port/info or /ttl
- if len(keyParts) != 4 {
- continue
- }
- address, fieldType := keyParts[2], keyParts[3]
- fillDBMap(address, fieldType, kv.Value, tidbEntryMap, tidbTTLMap)
- }
- }
-
- tidbNodes = genDBList(tidbEntryMap, tidbTTLMap)
-
- return tidbNodes, grafanaNode, alertManagerNode, nil
-}
-
-// address should be like "ip:port"
-// fieldType should be "ttl" or "info"
-// value is field value.
-func fillDBMap(address, fieldType string, value []byte, infoMap map[string]*TiDBInfo, ttlMap map[string][]byte) {
- if fieldType == "ttl" {
- ttlMap[address] = value
- } else if fieldType == "info" {
- ds := struct {
- Version string `json:"version"`
- GitHash string `json:"git_hash"`
- StatusPort uint `json:"status_port"`
- DeployPath string `json:"deploy_path"`
- StartTimestamp int64 `json:"start_timestamp"`
- }{}
-
- //var currentInfo TiDB
- err := json.Unmarshal(value, &ds)
- if err != nil {
- return
- }
- host, port, err := parseHostAndPortFromAddress(address)
- if err != nil {
- return
- }
-
- infoMap[address] = &TiDBInfo{
- GitHash: ds.GitHash,
- Version: ds.Version,
- IP: host,
- Port: port,
- DeployPath: ds.DeployPath,
- Status: ComponentStatusUnreachable,
- StatusPort: ds.StatusPort,
- StartTimestamp: ds.StartTimestamp,
- }
- }
-}
-
-func genDBList(infoMap map[string]*TiDBInfo, ttlMap map[string][]byte) []TiDBInfo {
- nodes := make([]TiDBInfo, 0)
-
- // Note: it means this TiDB has non-ttl key, but ttl-key not exists.
- for address, info := range infoMap {
- if ttlFreshUnixNanoSec, ok := ttlMap[address]; ok {
- unixNano, err := strconv.ParseInt(string(ttlFreshUnixNanoSec), 10, 64)
- if err != nil {
- info.Status = ComponentStatusUnreachable
- } else {
- ttlFreshTime := time.Unix(0, unixNano)
- if time.Since(ttlFreshTime) > time.Second*45 {
- info.Status = ComponentStatusUnreachable
- } else {
- info.Status = ComponentStatusUp
- }
- }
- } else {
- info.Status = ComponentStatusUnreachable
- }
- nodes = append(nodes, *info)
- }
-
- return nodes
-}
-
-type store struct {
- Address string `json:"address"`
- ID int `json:"id"`
- Labels []struct {
- Key string `json:"key"`
- Value string `json:"value"`
- }
- StateName string `json:"state_name"`
- Version string `json:"version"`
- StatusAddress string `json:"status_address"`
- GitHash string `json:"git_hash"`
- DeployPath string `json:"deploy_path"`
- StartTimestamp int64 `json:"start_timestamp"`
-}
-
-func getAllStoreNodes(endpoint string, httpClient *http.Client) ([]store, error) {
- resp, err := httpClient.Get(endpoint + "/pd/api/v1/stores")
- if err != nil {
- return nil, err
- }
- if resp.StatusCode != 200 {
- return nil, fmt.Errorf("fetch stores got wrong status code")
- }
- defer resp.Body.Close()
- storeResp := struct {
- Count int `json:"count"`
- Stores []struct {
- Store store
- } `json:"stores"`
- }{}
- data, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- return nil, err
- }
- err = json.Unmarshal(data, &storeResp)
- if err != nil {
- return nil, err
- }
- ret := make([]store, storeResp.Count)
- for i, s := range storeResp.Stores {
- ret[i] = s.Store
- }
- return ret, nil
-}
-
-type tikvStore struct {
- store
-}
-
-func getAllTiKVNodes(stores []store) []tikvStore {
- tikvs := make([]tikvStore, len(stores))
- for i := range stores {
- isTiFlash := false
- for _, label := range stores[i].Labels {
- if label.Key == "engine" && label.Value == "tiflash" {
- isTiFlash = true
- }
- }
- if !isTiFlash {
- tikvs = append(tikvs, tikvStore{stores[i]})
- }
- }
- return tikvs
-}
-
-func getTiKVTopology(stores []tikvStore) ([]TiKVInfo, error) {
- nodes := make([]TiKVInfo, 0)
- for _, v := range stores {
- // parse ip and port
- host, port, err := parseHostAndPortFromAddress(v.Address)
- if err != nil {
- continue
- }
- _, statusPort, err := parseHostAndPortFromAddress(v.StatusAddress)
- if err != nil {
- continue
- }
- // In current TiKV, it's version may not start with 'v',
- // so we may need to add a prefix 'v' for it.
- version := strings.Trim(v.Version, "\n ")
- if !strings.HasPrefix(version, "v") {
- version = "v" + version
- }
- node := TiKVInfo{
- Version: version,
- IP: host,
- Port: port,
- GitHash: v.GitHash,
- DeployPath: v.DeployPath,
- Status: storeStateToStatus(v.StateName),
- StatusPort: statusPort,
- Labels: map[string]string{},
- StartTimestamp: v.StartTimestamp,
- }
- for _, v := range v.Labels {
- node.Labels[v.Key] = node.Labels[v.Value]
- }
- nodes = append(nodes, node)
- }
-
- return nodes, nil
-}
-
-type tiflashStore struct {
- store
-}
-
-func getAllTiFlashNodes(stores []store) []tiflashStore {
- tiflashes := make([]tiflashStore, len(stores))
- for i := range stores {
- for _, label := range stores[i].Labels {
- if label.Key == "engine" && label.Value == "tiflash" {
- tiflashes = append(tiflashes, tiflashStore{stores[i]})
- }
- }
- }
-
- return tiflashes
-}
-
-func getTiFlashTopology(stores []tiflashStore) ([]TiFlashInfo, error) {
- nodes := make([]TiFlashInfo, 0)
- for _, v := range stores {
- // parse ip and port
- host, port, err := parseHostAndPortFromAddress(v.Address)
- if err != nil {
- continue
- }
- _, statusPort, err := parseHostAndPortFromAddress(v.StatusAddress)
- if err != nil {
- continue
- }
- version := strings.Trim(v.Version, "\n ")
- node := TiFlashInfo{
- Version: version,
- IP: host,
- Port: port,
- DeployPath: v.DeployPath, // TiFlash hasn't BinaryPath for now, so it would be empty
- Status: storeStateToStatus(v.StateName),
- StatusPort: statusPort,
- Labels: map[string]string{},
- StartTimestamp: v.StartTimestamp,
- }
- for _, v := range v.Labels {
- node.Labels[v.Key] = node.Labels[v.Value]
- }
- nodes = append(nodes, node)
- }
-
- return nodes, nil
-}
-
-func GetStoreTopology(endpoint string, httpClient *http.Client) ([]TiKVInfo, []TiFlashInfo, error) {
- stores, err := getAllStoreNodes(endpoint, httpClient)
- if err != nil {
- return nil, nil, err
- }
-
- tikvStores := getAllTiKVNodes(stores)
- tikvInfos, err := getTiKVTopology(tikvStores)
- if err != nil {
- return nil, nil, err
- }
-
- tiflashStores := getAllTiFlashNodes(stores)
- tiflashInfos, err := getTiFlashTopology(tiflashStores)
- if err != nil {
- return nil, nil, err
- }
-
- return tikvInfos, tiflashInfos, nil
-}
-
-func GetPDTopology(pdEndPoint string, httpClient *http.Client) ([]PDInfo, error) {
- nodes := make([]PDInfo, 0)
- healthMapChan := make(chan map[string]struct{})
- go func() {
- var err error
- healthMap, err := getPDNodesHealth(pdEndPoint, httpClient)
- if err != nil {
- healthMap = map[string]struct{}{}
- }
- healthMapChan <- healthMap
- }()
-
- resp, err := httpClient.Get(pdEndPoint + "/pd/api/v1/members")
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
- if resp.StatusCode != 200 {
- return nil, fmt.Errorf("fetch PD members got wrong status code")
- }
- data, err := ioutil.ReadAll(resp.Body)
-
- if err != nil {
- return nil, err
- }
-
- ds := struct {
- Count int `json:"count"`
- Members []struct {
- GitHash string `json:"git_hash"`
- ClientUrls []string `json:"client_urls"`
- DeployPath string `json:"deploy_path"`
- BinaryVersion string `json:"binary_version"`
- MemberID json.Number `json:"member_id"`
- } `json:"members"`
- }{}
-
- err = json.Unmarshal(data, &ds)
- if err != nil {
- return nil, err
- }
-
- healthMap := <-healthMapChan
- close(healthMapChan)
- for _, ds := range ds.Members {
- u := ds.ClientUrls[0]
- ts, err := getPDStartTimestamp(u, httpClient)
- if err != nil {
- log.Warn("failed to get PD node status", zap.Error(err))
- continue
- }
- host, port, err := parseHostAndPortFromAddressURL(u)
- if err != nil {
- continue
- }
- var storeStatus ComponentStatus
- if _, ok := healthMap[ds.MemberID.String()]; ok {
- storeStatus = ComponentStatusUp
- } else {
- storeStatus = ComponentStatusUnreachable
- }
-
- nodes = append(nodes, PDInfo{
- GitHash: ds.GitHash,
- Version: ds.BinaryVersion,
- IP: host,
- Port: port,
- DeployPath: ds.DeployPath,
- Status: storeStatus,
- StartTimestamp: ts,
- })
- }
- return nodes, nil
-}
-
-func getPDStartTimestamp(pdEndPoint string, httpClient *http.Client) (int64, error) {
- resp, err := httpClient.Get(pdEndPoint + "/pd/api/v1/status")
- if err != nil {
- return 0, err
- }
- defer resp.Body.Close()
- if resp.StatusCode != 200 {
- return 0, fmt.Errorf("fetch PD %s status got wrong status code", pdEndPoint)
- }
- data, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- return 0, err
- }
-
- ds := struct {
- StartTimestamp int64 `json:"start_timestamp"`
- }{}
- err = json.Unmarshal(data, &ds)
- if err != nil {
- return 0, err
- }
-
- return ds.StartTimestamp, nil
-}
-
-// address should be like "ip:port" as "127.0.0.1:2379".
-// return error if string is not like "ip:port".
-func parseHostAndPortFromAddress(address string) (string, uint, error) {
- addresses := strings.Split(address, ":")
- if len(addresses) != 2 {
- return "", 0, fmt.Errorf("invalid address %s", address)
- }
- port, err := strconv.Atoi(addresses[1])
- if err != nil {
- return "", 0, err
- }
- return addresses[0], uint(port), nil
-}
-
-// address should be like "protocol://ip:port" as "http://127.0.0.1:2379".
-func parseHostAndPortFromAddressURL(urlString string) (string, uint, error) {
- u, err := url.Parse(urlString)
- if err != nil {
- return "", 0, err
- }
- port, err := strconv.Atoi(u.Port())
- if err != nil {
- return "", 0, err
- }
- return u.Hostname(), uint(port), nil
-}
-
-func storeStateToStatus(state string) ComponentStatus {
- state = strings.Trim(strings.ToLower(state), "\n ")
- switch state {
- case "up":
- return ComponentStatusUp
- case "tombstone":
- return ComponentStatusTombstone
- case "offline":
- return ComponentStatusOffline
- case "down":
- return ComponentStatusDown
- case "disconnected":
- return ComponentStatusUnreachable
- default:
- return ComponentStatusUnreachable
- }
-}
-
-func getPDNodesHealth(pdEndPoint string, httpClient *http.Client) (map[string]struct{}, error) {
- // health member set
- memberHealth := map[string]struct{}{}
- resp, err := httpClient.Get(pdEndPoint + "/pd/api/v1/health")
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
- data, err := ioutil.ReadAll(resp.Body)
-
- if err != nil {
- return nil, err
- }
-
- var healths []struct {
- MemberID json.Number `json:"member_id"`
- }
-
- err = json.Unmarshal(data, &healths)
- if err != nil {
- return nil, err
- }
-
- for _, v := range healths {
- memberHealth[v.MemberID.String()] = struct{}{}
- }
- return memberHealth, nil
-}
-
-// GetAlertCountByAddress receives alert manager's address like "ip:port", and it returns the
-// alert number of the alert manager.
-func GetAlertCountByAddress(address string, httpClient *http.Client) (int, error) {
- ip, port, err := parseHostAndPortFromAddress(address)
- if err != nil {
- return 0, err
- }
-
- apiAddress := fmt.Sprintf("http://%s:%d/api/v2/alerts", ip, port)
- resp, err := httpClient.Get(apiAddress)
- if err != nil {
- return 0, err
- }
-
- defer resp.Body.Close()
- data, err := ioutil.ReadAll(resp.Body)
-
- if err != nil {
- return 0, err
- }
-
- var alerts []struct{}
-
- err = json.Unmarshal(data, &alerts)
- if err != nil {
- return 0, err
- }
-
- return len(alerts), nil
-}
diff --git a/pkg/utils/clusterinfo/clusterinfo.go b/pkg/utils/topology/models.go
similarity index 67%
rename from pkg/utils/clusterinfo/clusterinfo.go
rename to pkg/utils/topology/models.go
index 8dfea81240..8a9104c88c 100644
--- a/pkg/utils/clusterinfo/clusterinfo.go
+++ b/pkg/utils/topology/models.go
@@ -11,19 +11,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package clusterinfo
+package topology
type ComponentStatus uint
const (
- // ComponentStatusUnreachable means unreachable or disconnected
ComponentStatusUnreachable ComponentStatus = 0
ComponentStatusUp ComponentStatus = 1
ComponentStatusTombstone ComponentStatus = 2
ComponentStatusOffline ComponentStatus = 3
-
- // PD's Store may have state name down.
- ComponentStatusDown ComponentStatus = 4
+ ComponentStatusDown ComponentStatus = 4
)
type PDInfo struct {
@@ -33,7 +30,7 @@ type PDInfo struct {
Port uint `json:"port"`
DeployPath string `json:"deploy_path"`
Status ComponentStatus `json:"status"`
- StartTimestamp int64 `json:"start_timestamp"`
+ StartTimestamp int64 `json:"start_timestamp"` // Ts = 0 means unknown
}
type TiDBInfo struct {
@@ -47,7 +44,8 @@ type TiDBInfo struct {
StartTimestamp int64 `json:"start_timestamp"`
}
-type TiKVInfo struct {
+// Store may be a TiKV store or TiFlash store
+type StoreInfo struct {
GitHash string `json:"git_hash"`
Version string `json:"version"`
IP string `json:"ip"`
@@ -59,31 +57,19 @@ type TiKVInfo struct {
StartTimestamp int64 `json:"start_timestamp"`
}
-type TiFlashInfo struct {
- Version string `json:"version"`
- IP string `json:"ip"`
- Port uint `json:"port"`
- DeployPath string `json:"deploy_path"`
- Status ComponentStatus `json:"status"`
- StatusPort uint `json:"status_port"`
- Labels map[string]string `json:"labels"`
- StartTimestamp int64 `json:"start_timestamp"`
+type StandardComponentInfo struct {
+ IP string `json:"ip"`
+ Port uint `json:"port"`
}
type AlertManagerInfo struct {
- IP string `json:"ip"`
- Port uint `json:"port"`
- DeployPath string `json:"deploy_path"`
+ StandardComponentInfo
}
type GrafanaInfo struct {
- IP string `json:"ip"`
- Port uint `json:"port"`
- DeployPath string `json:"deploy_path"`
+ StandardComponentInfo
}
type PrometheusInfo struct {
- IP string `json:"ip"`
- Port uint `json:"port"`
- BinaryPath string `json:"binary_path"`
+ StandardComponentInfo
}
diff --git a/pkg/utils/topology/monitor.go b/pkg/utils/topology/monitor.go
new file mode 100644
index 0000000000..79f82619e9
--- /dev/null
+++ b/pkg/utils/topology/monitor.go
@@ -0,0 +1,51 @@
+// Copyright 2020 PingCAP, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package topology
+
+import (
+ "go.etcd.io/etcd/clientv3"
+)
+
+func FetchAlertManagerTopology(etcdClient *clientv3.Client) (*AlertManagerInfo, error) {
+ i, err := fetchStandardComponentTopology("alertmanager", etcdClient)
+ if err != nil {
+ return nil, err
+ }
+ if i == nil {
+ return nil, nil
+ }
+ return &AlertManagerInfo{StandardComponentInfo: *i}, nil
+}
+
+func FetchGrafanaTopology(etcdClient *clientv3.Client) (*GrafanaInfo, error) {
+ i, err := fetchStandardComponentTopology("grafana", etcdClient)
+ if err != nil {
+ return nil, err
+ }
+ if i == nil {
+ return nil, nil
+ }
+ return &GrafanaInfo{StandardComponentInfo: *i}, nil
+}
+
+func FetchPrometheusTopology(etcdClient *clientv3.Client) (*PrometheusInfo, error) {
+ i, err := fetchStandardComponentTopology("prometheus", etcdClient)
+ if err != nil {
+ return nil, err
+ }
+ if i == nil {
+ return nil, nil
+ }
+ return &PrometheusInfo{StandardComponentInfo: *i}, nil
+}
diff --git a/pkg/utils/topology/pd.go b/pkg/utils/topology/pd.go
new file mode 100644
index 0000000000..964b45f82d
--- /dev/null
+++ b/pkg/utils/topology/pd.go
@@ -0,0 +1,146 @@
+// Copyright 2020 PingCAP, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package topology
+
+import (
+ "encoding/json"
+ "io/ioutil"
+ "net/http"
+ "sort"
+
+ "github.com/pingcap/log"
+ "go.uber.org/zap"
+)
+
+func FetchPDTopology(pdEndPoint string, httpClient *http.Client) ([]PDInfo, error) {
+ nodes := make([]PDInfo, 0)
+ healthMap, err := fetchPDHealth(pdEndPoint, httpClient)
+ if err != nil {
+ return nil, err
+ }
+
+ resp, err := httpClient.Get(pdEndPoint + "/pd/api/v1/members")
+ if err != nil {
+ return nil, ErrPDAccessFailed.Wrap(err, "PD members API HTTP get failed")
+ }
+ defer resp.Body.Close()
+ data, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return nil, ErrPDAccessFailed.Wrap(err, "PD members API read failed")
+ }
+
+ ds := struct {
+ Count int `json:"count"`
+ Members []struct {
+ GitHash string `json:"git_hash"`
+ ClientUrls []string `json:"client_urls"`
+ DeployPath string `json:"deploy_path"`
+ BinaryVersion string `json:"binary_version"`
+ MemberID json.Number `json:"member_id"`
+ } `json:"members"`
+ }{}
+
+ err = json.Unmarshal(data, &ds)
+ if err != nil {
+ return nil, ErrInvalidTopologyData.Wrap(err, "PD members API unmarshal failed")
+ }
+
+ for _, ds := range ds.Members {
+ u := ds.ClientUrls[0]
+ host, port, err := parseHostAndPortFromAddressURL(u)
+ if err != nil {
+ continue
+ }
+
+ ts, err := fetchPDStartTimestamp(u, httpClient)
+ if err != nil {
+ log.Warn("Failed to fetch PD start timestamp", zap.String("targetPdNode", u), zap.Error(err))
+ ts = 0
+ }
+
+ var storeStatus ComponentStatus
+ if _, ok := healthMap[ds.MemberID.String()]; ok {
+ storeStatus = ComponentStatusUp
+ } else {
+ storeStatus = ComponentStatusUnreachable
+ }
+
+ nodes = append(nodes, PDInfo{
+ GitHash: ds.GitHash,
+ Version: ds.BinaryVersion,
+ IP: host,
+ Port: port,
+ DeployPath: ds.DeployPath,
+ Status: storeStatus,
+ StartTimestamp: ts,
+ })
+ }
+
+ sort.Slice(nodes, func(i, j int) bool {
+ return nodes[i].IP > nodes[j].IP && nodes[i].Port > nodes[j].Port
+ })
+
+ return nodes, nil
+}
+
+func fetchPDStartTimestamp(pdEndPoint string, httpClient *http.Client) (int64, error) {
+ resp, err := httpClient.Get(pdEndPoint + "/pd/api/v1/status")
+ if err != nil {
+ return 0, ErrPDAccessFailed.Wrap(err, "PD status API HTTP get failed")
+ }
+ defer resp.Body.Close()
+ data, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return 0, ErrPDAccessFailed.Wrap(err, "PD status API read failed")
+ }
+
+ ds := struct {
+ StartTimestamp int64 `json:"start_timestamp"`
+ }{}
+ err = json.Unmarshal(data, &ds)
+ if err != nil {
+ return 0, ErrInvalidTopologyData.Wrap(err, "PD status API unmarshal failed")
+ }
+
+ return ds.StartTimestamp, nil
+}
+
+func fetchPDHealth(pdEndPoint string, httpClient *http.Client) (map[string]struct{}, error) {
+ // health member set
+ memberHealth := map[string]struct{}{}
+ resp, err := httpClient.Get(pdEndPoint + "/pd/api/v1/health")
+ if err != nil {
+ return nil, ErrPDAccessFailed.Wrap(err, "PD health API HTTP get failed")
+ }
+ defer resp.Body.Close()
+ data, err := ioutil.ReadAll(resp.Body)
+
+ if err != nil {
+ return nil, ErrPDAccessFailed.Wrap(err, "PD health API read failed")
+ }
+
+ var healths []struct {
+ MemberID json.Number `json:"member_id"`
+ }
+
+ err = json.Unmarshal(data, &healths)
+ if err != nil {
+ return nil, ErrInvalidTopologyData.Wrap(err, "PD health API unmarshal failed")
+ }
+
+ for _, v := range healths {
+ memberHealth[v.MemberID.String()] = struct{}{}
+ }
+ return memberHealth, nil
+}
diff --git a/pkg/utils/topology/store.go b/pkg/utils/topology/store.go
new file mode 100644
index 0000000000..fd0e99a91d
--- /dev/null
+++ b/pkg/utils/topology/store.go
@@ -0,0 +1,155 @@
+// Copyright 2020 PingCAP, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package topology
+
+import (
+ "encoding/json"
+ "io/ioutil"
+ "net/http"
+ "sort"
+ "strings"
+
+ "github.com/pingcap/log"
+ "go.uber.org/zap"
+)
+
+// FetchStoreTopology returns TiKV info and TiFlash info.
+func FetchStoreTopology(pdEndpoint string, httpClient *http.Client) ([]StoreInfo, []StoreInfo, error) {
+ stores, err := fetchStores(pdEndpoint, httpClient)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ tiKVStores := make([]store, 0, len(stores))
+ tiFlashStores := make([]store, 0, len(stores))
+ for _, store := range stores {
+ isTiFlash := false
+ for _, label := range store.Labels {
+ if label.Key == "engine" && label.Value == "tiflash" {
+ isTiFlash = true
+ }
+ }
+ if isTiFlash {
+ tiFlashStores = append(tiFlashStores, store)
+ } else {
+ tiKVStores = append(tiKVStores, store)
+ }
+ }
+
+ return buildStoreTopology(tiKVStores), buildStoreTopology(tiFlashStores), nil
+}
+
+func buildStoreTopology(stores []store) []StoreInfo {
+ nodes := make([]StoreInfo, 0, len(stores))
+ for _, v := range stores {
+ host, port, err := parseHostAndPortFromAddress(v.Address)
+ if err != nil {
+ log.Warn("Failed to parse store address", zap.Any("store", v))
+ continue
+ }
+ _, statusPort, err := parseHostAndPortFromAddress(v.StatusAddress)
+ if err != nil {
+ log.Warn("Failed to parse store status address", zap.Any("store", v))
+ continue
+ }
+ // In current TiKV, it's version may not start with 'v',
+ // so we may need to add a prefix 'v' for it.
+ version := strings.Trim(v.Version, "\n ")
+ if !strings.HasPrefix(version, "v") {
+ version = "v" + version
+ }
+ node := StoreInfo{
+ Version: version,
+ IP: host,
+ Port: port,
+ GitHash: v.GitHash,
+ DeployPath: v.DeployPath,
+ Status: parseStoreState(v.StateName),
+ StatusPort: statusPort,
+ Labels: map[string]string{},
+ StartTimestamp: v.StartTimestamp,
+ }
+ for _, v := range v.Labels {
+ node.Labels[v.Key] = node.Labels[v.Value]
+ }
+ nodes = append(nodes, node)
+ }
+
+ return nodes
+}
+
+type store struct {
+ Address string `json:"address"`
+ ID int `json:"id"`
+ Labels []struct {
+ Key string `json:"key"`
+ Value string `json:"value"`
+ }
+ StateName string `json:"state_name"`
+ Version string `json:"version"`
+ StatusAddress string `json:"status_address"`
+ GitHash string `json:"git_hash"`
+ DeployPath string `json:"deploy_path"`
+ StartTimestamp int64 `json:"start_timestamp"`
+}
+
+func fetchStores(endpoint string, httpClient *http.Client) ([]store, error) {
+ resp, err := httpClient.Get(endpoint + "/pd/api/v1/stores")
+ if err != nil {
+ return nil, ErrPDAccessFailed.Wrap(err, "PD stores API HTTP get failed")
+ }
+ defer resp.Body.Close()
+ storeResp := struct {
+ Count int `json:"count"`
+ Stores []struct {
+ Store store
+ } `json:"stores"`
+ }{}
+ data, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return nil, ErrPDAccessFailed.Wrap(err, "PD stores API read failed")
+ }
+ err = json.Unmarshal(data, &storeResp)
+ if err != nil {
+ return nil, ErrInvalidTopologyData.Wrap(err, "PD stores API unmarshal failed")
+ }
+ ret := make([]store, 0, storeResp.Count)
+ for _, s := range storeResp.Stores {
+ ret = append(ret, s.Store)
+ }
+
+ sort.Slice(ret, func(i, j int) bool {
+ return ret[i].Address > ret[j].Address
+ })
+
+ return ret, nil
+}
+
+func parseStoreState(state string) ComponentStatus {
+ state = strings.Trim(strings.ToLower(state), "\n ")
+ switch state {
+ case "up":
+ return ComponentStatusUp
+ case "tombstone":
+ return ComponentStatusTombstone
+ case "offline":
+ return ComponentStatusOffline
+ case "down":
+ return ComponentStatusDown
+ case "disconnected":
+ return ComponentStatusUnreachable
+ default:
+ return ComponentStatusUnreachable
+ }
+}
diff --git a/pkg/utils/topology/tidb.go b/pkg/utils/topology/tidb.go
new file mode 100644
index 0000000000..f144246098
--- /dev/null
+++ b/pkg/utils/topology/tidb.go
@@ -0,0 +1,139 @@
+// Copyright 2020 PingCAP, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package topology
+
+import (
+ "context"
+ "encoding/json"
+ "sort"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/pingcap/log"
+ "go.etcd.io/etcd/clientv3"
+ "go.uber.org/zap"
+)
+
+const tidbTopologyKeyPrefix = "/topology/tidb/"
+
+func FetchTiDBTopology(etcdClient *clientv3.Client) ([]TiDBInfo, error) {
+ ctx, cancel := context.WithTimeout(context.Background(), defaultFetchTimeout)
+ defer cancel()
+
+ resp, err := etcdClient.Get(ctx, tidbTopologyKeyPrefix, clientv3.WithPrefix())
+ if err != nil {
+ return nil, ErrPDAccessFailed.Wrap(err, "PD etcd get key %s failed", tidbTopologyKeyPrefix)
+ }
+
+ nodesAlive := map[string]bool{}
+ nodesInfo := map[string]*TiDBInfo{}
+
+ for _, kv := range resp.Kvs {
+ key := string(kv.Key)
+ if !strings.HasPrefix(key, tidbTopologyKeyPrefix) {
+ continue
+ }
+ // remainingKey looks like `ip:port/info` or `ip:port/ttl`.
+ remainingKey := key[len(tidbTopologyKeyPrefix):]
+ keyParts := strings.Split(remainingKey, "/")
+ if len(keyParts) != 2 {
+ log.Warn("Ignored invalid TiDB topology key", zap.String("key", key))
+ continue
+ }
+
+ switch keyParts[1] {
+ case "info":
+ node, err := parseTiDBInfo(keyParts[0], kv.Value)
+ if err == nil {
+ nodesInfo[keyParts[0]] = node
+ } else {
+ log.Warn("Ignored invalid TiDB topology info entry",
+ zap.String("key", key),
+ zap.String("value", string(kv.Value)),
+ zap.Error(err))
+ }
+ case "ttl":
+ alive, err := parseTiDBAliveness(kv.Value)
+ if err == nil {
+ nodesAlive[keyParts[0]] = alive
+ } else {
+ log.Warn("Ignored invalid TiDB topology TTL entry",
+ zap.String("key", key),
+ zap.String("value", string(kv.Value)),
+ zap.Error(err))
+ }
+ }
+ }
+
+ nodes := make([]TiDBInfo, 0)
+
+ for addr, info := range nodesInfo {
+ if alive, ok := nodesAlive[addr]; ok {
+ if alive {
+ info.Status = ComponentStatusUp
+ }
+ }
+ nodes = append(nodes, *info)
+ }
+
+ sort.Slice(nodes, func(i, j int) bool {
+ return nodes[i].IP > nodes[j].IP && nodes[i].Port > nodes[j].Port
+ })
+
+ return nodes, nil
+}
+
+func parseTiDBInfo(address string, value []byte) (*TiDBInfo, error) {
+ ds := struct {
+ Version string `json:"version"`
+ GitHash string `json:"git_hash"`
+ StatusPort uint `json:"status_port"`
+ DeployPath string `json:"deploy_path"`
+ StartTimestamp int64 `json:"start_timestamp"`
+ }{}
+
+ err := json.Unmarshal(value, &ds)
+ if err != nil {
+ return nil, ErrInvalidTopologyData.Wrap(err, "TiDB info unmarshal failed")
+ }
+ host, port, err := parseHostAndPortFromAddress(address)
+ if err != nil {
+ return nil, ErrInvalidTopologyData.Wrap(err, "TiDB info address parse failed")
+ }
+
+ return &TiDBInfo{
+ GitHash: ds.GitHash,
+ Version: ds.Version,
+ IP: host,
+ Port: port,
+ DeployPath: ds.DeployPath,
+ Status: ComponentStatusUnreachable,
+ StatusPort: ds.StatusPort,
+ StartTimestamp: ds.StartTimestamp,
+ }, nil
+}
+
+func parseTiDBAliveness(value []byte) (bool, error) {
+ unixTimestampNano, err := strconv.ParseUint(string(value), 10, 64)
+ if err != nil {
+ return false, ErrInvalidTopologyData.Wrap(err, "TiDB TTL info parse failed")
+ }
+ t := time.Unix(0, int64(unixTimestampNano))
+ if time.Since(t) > time.Second*45 {
+ return false, nil
+ } else {
+ return true, nil
+ }
+}
diff --git a/pkg/utils/topology/topology.go b/pkg/utils/topology/topology.go
new file mode 100644
index 0000000000..a020860328
--- /dev/null
+++ b/pkg/utils/topology/topology.go
@@ -0,0 +1,87 @@
+// Copyright 2020 PingCAP, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package topology
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/url"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/joomcode/errorx"
+ "github.com/pingcap/log"
+ "go.etcd.io/etcd/clientv3"
+ "go.uber.org/zap"
+)
+
+var (
+ ErrNS = errorx.NewNamespace("error.topology")
+ ErrPDAccessFailed = ErrNS.NewType("pd_access_failed")
+ ErrInvalidTopologyData = ErrNS.NewType("invalid_topology_data")
+)
+
+const defaultFetchTimeout = 2 * time.Second
+
+// address should be like "ip:port" as "127.0.0.1:2379".
+// return error if string is not like "ip:port".
+func parseHostAndPortFromAddress(address string) (string, uint, error) {
+ addresses := strings.Split(address, ":")
+ if len(addresses) != 2 {
+ return "", 0, fmt.Errorf("invalid address %s", address)
+ }
+ port, err := strconv.Atoi(addresses[1])
+ if err != nil {
+ return "", 0, err
+ }
+ return addresses[0], uint(port), nil
+}
+
+// address should be like "protocol://ip:port" as "http://127.0.0.1:2379".
+func parseHostAndPortFromAddressURL(urlString string) (string, uint, error) {
+ u, err := url.Parse(urlString)
+ if err != nil {
+ return "", 0, err
+ }
+ port, err := strconv.Atoi(u.Port())
+ if err != nil {
+ return "", 0, err
+ }
+ return u.Hostname(), uint(port), nil
+}
+
+func fetchStandardComponentTopology(componentName string, etcdClient *clientv3.Client) (*StandardComponentInfo, error) {
+ ctx, cancel := context.WithTimeout(context.Background(), defaultFetchTimeout)
+ defer cancel()
+
+ key := "/topology/" + componentName
+ resp, err := etcdClient.Get(ctx, key, clientv3.WithPrefix())
+ if err != nil {
+ return nil, ErrPDAccessFailed.New("PD etcd get key %s failed", key)
+ }
+ if resp.Count == 0 {
+ return nil, nil
+ }
+ info := StandardComponentInfo{}
+ kv := resp.Kvs[0]
+ if err = json.Unmarshal(kv.Value, &info); err != nil {
+ log.Warn("Failed to unmarshal topology value",
+ zap.String("key", string(kv.Key)),
+ zap.String("value", string(kv.Value)))
+ return nil, nil
+ }
+ return &info, nil
+}
diff --git a/ui/dashboardApp/index.js b/ui/dashboardApp/index.js
index f97471f348..05f8d8e515 100644
--- a/ui/dashboardApp/index.js
+++ b/ui/dashboardApp/index.js
@@ -11,6 +11,7 @@ import * as client from '@dashboard/client'
import LayoutMain from '@dashboard/layout/main'
import LayoutSignIn from '@dashboard/layout/signin'
+import AppDebugPlayground from '@lib/apps/DebugPlayground/index.meta'
import AppDashboardSettings from '@lib/apps/DashboardSettings/index.meta'
import AppUserProfile from '@lib/apps/UserProfile/index.meta'
import AppOverview from '@lib/apps/Overview/index.meta'
@@ -18,7 +19,7 @@ import AppKeyViz from '@lib/apps/KeyViz/index.meta'
import AppStatement from '@lib/apps/Statement/index.meta'
import AppDiagnose from '@lib/apps/Diagnose/index.meta'
import AppSearchLogs from '@lib/apps/SearchLogs/index.meta'
-import AppInstanceProfiling from '@lib/apps/InstanceProfiling/index.meta'
+// import AppInstanceProfiling from '@lib/apps/InstanceProfiling/index.meta'
import AppClusterInfo from '@lib/apps/ClusterInfo/index.meta'
import AppSlowQuery from '@lib/apps/SlowQuery/index.meta'
@@ -50,6 +51,7 @@ async function main() {
)
registry
+ .register(AppDebugPlayground)
.register(AppDashboardSettings)
.register(AppUserProfile)
.register(AppOverview)
@@ -58,7 +60,7 @@ async function main() {
.register(AppClusterInfo)
.register(AppDiagnose)
.register(AppSearchLogs)
- .register(AppInstanceProfiling)
+ // .register(AppInstanceProfiling)
.register(AppSlowQuery)
if (routing.isLocationMatch('/')) {
diff --git a/ui/dashboardApp/layout/main/Sider/index.js b/ui/dashboardApp/layout/main/Sider/index.js
index a6cd0909d5..ab3ee416a7 100644
--- a/ui/dashboardApp/layout/main/Sider/index.js
+++ b/ui/dashboardApp/layout/main/Sider/index.js
@@ -80,6 +80,7 @@ function Sider({
)
const menuItems = [
+ useAppMenuItem(registry, 'debug_playground'),
useAppMenuItem(registry, 'overview'),
useAppMenuItem(registry, 'cluster_info'),
useAppMenuItem(registry, 'keyviz'),
diff --git a/ui/lib/apps/ClusterInfo/components/HostTable.tsx b/ui/lib/apps/ClusterInfo/components/HostTable.tsx
index 0347e100f5..0e73da8cc9 100644
--- a/ui/lib/apps/ClusterInfo/components/HostTable.tsx
+++ b/ui/lib/apps/ClusterInfo/components/HostTable.tsx
@@ -23,7 +23,7 @@ export default function HostTable() {
const { t } = useTranslation()
const { data: tableData, isLoading } = useClientRequest((cancelToken) =>
- client.getInstance().hostAllGet({ cancelToken })
+ client.getInstance().getHostsInfo({ cancelToken })
)
const columns = [
diff --git a/ui/lib/apps/ClusterInfo/components/InstanceTable.tsx b/ui/lib/apps/ClusterInfo/components/InstanceTable.tsx
index 54bda880aa..0d8e53cd65 100644
--- a/ui/lib/apps/ClusterInfo/components/InstanceTable.tsx
+++ b/ui/lib/apps/ClusterInfo/components/InstanceTable.tsx
@@ -1,152 +1,96 @@
-import { Badge, Divider, Popconfirm, Tooltip } from 'antd'
+import { Divider, Popconfirm, Tooltip, Alert } from 'antd'
import { ColumnActionsMode } from 'office-ui-fabric-react/lib/DetailsList'
-import React, { ReactNode } from 'react'
+import React, { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { DeleteOutlined } from '@ant-design/icons'
-
-import {
- STATUS_DOWN,
- STATUS_OFFLINE,
- STATUS_TOMBSTONE,
- STATUS_UP,
-} from '@lib/apps/ClusterInfo/status/status'
-import client from '@lib/client'
-import { CardTableV2 } from '@lib/components'
+import { CardTableV2, InstanceStatusBadge } from '@lib/components'
import DateTime from '@lib/components/DateTime'
import { useClientRequest } from '@lib/utils/useClientRequest'
+import { usePersistFn } from '@umijs/hooks'
+import {
+ buildInstanceTable,
+ IInstanceTableItem,
+ InstanceStatus,
+} from '@lib/utils/instanceTable'
+import client from '@lib/client'
-function useStatusColumnRender(handleHideTiDB) {
+function StatusColumn({
+ node,
+ onHideTiDB,
+}: {
+ node: IInstanceTableItem
+ onHideTiDB: (node) => void
+}) {
const { t } = useTranslation()
- return (node) => {
- if (node.status == null) {
- // Tree node
- return
- }
- let statusNode: ReactNode = null
- switch (node.status) {
- case STATUS_DOWN:
- statusNode = (
-
- )
- break
- case STATUS_UP:
- statusNode = (
-
- )
- break
- case STATUS_TOMBSTONE:
- statusNode = (
-
- )
- break
- case STATUS_OFFLINE:
- statusNode = (
-
- )
- break
- default:
- statusNode = (
-
- )
- break
- }
- return (
-
- {statusNode}
- {node.nodeKind === 'tidb' && node.status !== STATUS_UP && (
- <>
-
- {
+ onHideTiDB && onHideTiDB(node)
+ })
+
+ return (
+
+
+ {node.instanceKind === 'tidb' && node.status !== InstanceStatus.Up && (
+ <>
+
+
+ handleHideTiDB(node)}
>
-
-
-
-
-
-
- >
- )}
-
- )
- }
-}
-
-function useHideTiDBHandler(updateData) {
- return async (node) => {
- await client
- .getInstance()
- .topologyTidbAddressDelete(`${node.ip}:${node.port}`)
- updateData()
- }
-}
-
-function buildData(data) {
- if (data === undefined) {
- return {}
- }
- const tableData: any[] = [] // FIXME
- const groupData: any[] = [] // FIXME
- let startIndex = 0
- const kinds = ['tidb', 'tikv', 'pd', 'tiflash']
- kinds.forEach((nodeKind) => {
- const nodes = data[nodeKind]
- if (nodes.err) {
- return
- }
- const count = nodes.nodes.length
- groupData.push({
- key: nodeKind,
- name: nodeKind,
- startIndex: startIndex,
- count: count,
- level: 0,
- })
- startIndex += count
- const children = nodes.nodes.map((node) => {
- return {
- key: `${node.ip}:${node.port}`,
- ...node,
- nodeKind,
- }
- })
- tableData.push(...children)
- })
- return { tableData, groupData }
+
+
+
+
+
+ >
+ )}
+
+ )
}
export default function ListPage() {
const { t } = useTranslation()
-
- const { data, isLoading, sendRequest } = useClientRequest((cancelToken) =>
- client.getInstance().topologyAllGet({ cancelToken })
+ const {
+ data: dataTiDB,
+ isLoading: loadingTiDB,
+ error: errTiDB,
+ sendRequest,
+ } = useClientRequest((cancelToken) =>
+ client.getInstance().getTiDBTopology({ cancelToken })
+ )
+ const {
+ data: dataStores,
+ isLoading: loadingStores,
+ error: errStores,
+ } = useClientRequest((cancelToken) =>
+ client.getInstance().getStoreTopology({ cancelToken })
+ )
+ const {
+ data: dataPD,
+ isLoading: loadingPD,
+ error: errPD,
+ } = useClientRequest((cancelToken) =>
+ client.getInstance().getPDTopology({ cancelToken })
)
- const { tableData, groupData } = buildData(data)
- const handleHideTiDB = useHideTiDBHandler(sendRequest)
- const renderStatusColumn = useStatusColumnRender(handleHideTiDB)
+ const [tableData, groupData] = useMemo(
+ () =>
+ buildInstanceTable({
+ dataPD,
+ dataTiDB,
+ dataTiKV: dataStores?.tikv,
+ dataTiFlash: dataStores?.tiflash,
+ includeTiFlash: true,
+ }),
+ [dataTiDB, dataStores, dataPD]
+ )
const columns = [
{
@@ -171,13 +115,23 @@ export default function ListPage() {
maxWidth: 100,
isResizable: true,
columnActionsMode: ColumnActionsMode.disabled,
- onRender: renderStatusColumn,
+ onRender: (node) => (
+ {
+ await client
+ .getInstance()
+ .topologyTidbAddressDelete(`${node.ip}:${node.port}`)
+ sendRequest()
+ }}
+ />
+ ),
},
{
name: t('cluster_info.list.instance_table.columns.up_time'),
key: 'start_timestamp',
minWidth: 100,
- maxWidth: 150,
+ maxWidth: 200,
isResizable: true,
columnActionsMode: ColumnActionsMode.disabled,
onRender: ({ start_timestamp: ts }) => {
@@ -190,24 +144,24 @@ export default function ListPage() {
name: t('cluster_info.list.instance_table.columns.version'),
fieldName: 'version',
key: 'version',
- minWidth: 150,
- maxWidth: 300,
+ minWidth: 100,
+ maxWidth: 150,
isResizable: true,
columnActionsMode: ColumnActionsMode.disabled,
},
{
- name: t('cluster_info.list.instance_table.columns.deploy_path'),
- fieldName: 'deploy_path',
- key: 'deploy_path',
- minWidth: 150,
- maxWidth: 300,
+ name: t('cluster_info.list.instance_table.columns.git_hash'),
+ fieldName: 'git_hash',
+ key: 'git_hash',
+ minWidth: 100,
+ maxWidth: 200,
isResizable: true,
columnActionsMode: ColumnActionsMode.disabled,
},
{
- name: t('cluster_info.list.instance_table.columns.git_hash'),
- fieldName: 'git_hash',
- key: 'git_hash',
+ name: t('cluster_info.list.instance_table.columns.deploy_path'),
+ fieldName: 'deploy_path',
+ key: 'deploy_path',
minWidth: 150,
maxWidth: 300,
isResizable: true,
@@ -216,12 +170,27 @@ export default function ListPage() {
]
return (
-
+ <>
+ {errTiDB && (
+
+ )}
+ {errStores && (
+
+ )}
+ {errPD && (
+
+ )}
+
+ >
)
}
diff --git a/ui/lib/apps/ClusterInfo/translations/en.yaml b/ui/lib/apps/ClusterInfo/translations/en.yaml
index d7f68b01ef..9052b8462d 100644
--- a/ui/lib/apps/ClusterInfo/translations/en.yaml
+++ b/ui/lib/apps/ClusterInfo/translations/en.yaml
@@ -14,13 +14,6 @@ cluster_info:
hide_db:
tooltip: Hide
confirm: Do you want to hide this TiDB node?
- status:
- up: Up
- down: Down
- tombstone: Tombstone
- offline: Offline
- unknown: Unknown
- unreachable: Unreachable
host_table:
title: Hosts
columns:
diff --git a/ui/lib/apps/ClusterInfo/translations/zh-CN.yaml b/ui/lib/apps/ClusterInfo/translations/zh-CN.yaml
index 5bc14bab7a..32e7bfb2c6 100644
--- a/ui/lib/apps/ClusterInfo/translations/zh-CN.yaml
+++ b/ui/lib/apps/ClusterInfo/translations/zh-CN.yaml
@@ -14,13 +14,6 @@ cluster_info:
hide_db:
tooltip: 隐藏
confirm: 您确认要隐藏该 TiDB 节点吗?
- status:
- up: 在线
- down: 离线
- tombstone: 已缩容下线
- offline: 下线中
- unknown: 未知
- unreachable: 无法访问
host_table:
title: 主机
columns:
diff --git a/ui/lib/apps/DebugPlayground/index.meta.ts b/ui/lib/apps/DebugPlayground/index.meta.ts
new file mode 100644
index 0000000000..ece87f1f28
--- /dev/null
+++ b/ui/lib/apps/DebugPlayground/index.meta.ts
@@ -0,0 +1,8 @@
+import { BugOutlined } from '@ant-design/icons'
+
+export default {
+ id: 'debug_playground',
+ routerPrefix: '/debug_playground',
+ icon: BugOutlined,
+ reactRoot: () => import(/* webpackChunkName: "debug_playground" */ '.'),
+}
diff --git a/ui/lib/apps/DebugPlayground/index.tsx b/ui/lib/apps/DebugPlayground/index.tsx
new file mode 100644
index 0000000000..ab02b3c038
--- /dev/null
+++ b/ui/lib/apps/DebugPlayground/index.tsx
@@ -0,0 +1,58 @@
+import React, { useState } from 'react'
+import { Root, BaseSelect, InstanceSelect } from '@lib/components'
+import { Select, Button } from 'antd'
+
+const App = () => {
+ const [instanceSelectValue, setInstanceSelectValue] = useState([])
+ return (
+
+ Debug Playground
+ Base Select
+ Content
}
+ valueRender={() => Short}
+ />
+ Content
}
+ valueRender={() => Very Lonnnnnnnnng Value}
+ />
+ Content
}
+ valueRender={() => Disabled}
+ />
+
+ Antd Select
+
+
+ Instance Select
+
+ Instance select value = {JSON.stringify(instanceSelectValue)}
+ Misc
+ {
+ e.preventDefault()
+ }}
+ >
+ Prevent Default Area
+
+
+ )
+}
+
+export default App
diff --git a/ui/lib/apps/InstanceProfiling/pages/List.tsx b/ui/lib/apps/InstanceProfiling/pages/List.tsx
index fac509b6da..d1f485db46 100644
--- a/ui/lib/apps/InstanceProfiling/pages/List.tsx
+++ b/ui/lib/apps/InstanceProfiling/pages/List.tsx
@@ -50,47 +50,48 @@ function filterTreeNode(inputValue, treeNode) {
}
function useTargetsMap() {
- const { data } = useClientRequest((cancelToken) =>
- client.getInstance().topologyAllGet({ cancelToken })
- )
- return useMemo(() => {
- const map = {}
- if (!data) {
- return map
- }
- // FIXME, declare type
- data.tidb?.nodes?.forEach((node) => {
- const display = `${node.ip}:${node.port}`
- const target = {
- kind: 'tidb',
- display_name: display,
- ip: node.ip,
- port: node.status_port,
- }
- map[display] = target
- })
- data.tikv?.nodes?.forEach((node) => {
- const display = `${node.ip}:${node.port}`
- const target = {
- kind: 'tikv',
- display_name: display,
- ip: node.ip,
- port: node.status_port,
- }
- map[display] = target
- })
- data.pd?.nodes?.forEach((node) => {
- const display = `${node.ip}:${node.port}`
- const target = {
- kind: 'pd',
- display_name: display,
- ip: node.ip,
- port: node.port,
- }
- map[display] = target
- })
- return map
- }, [data])
+ return {}
+ // const { data } = useClientRequest((cancelToken) =>
+ // client.getInstance().topologyAllGet({ cancelToken })
+ // )
+ // return useMemo(() => {
+ // const map = {}
+ // if (!data) {
+ // return map
+ // }
+ // // FIXME, declare type
+ // data.tidb?.nodes?.forEach((node) => {
+ // const display = `${node.ip}:${node.port}`
+ // const target = {
+ // kind: 'tidb',
+ // display_name: display,
+ // ip: node.ip,
+ // port: node.status_port,
+ // }
+ // map[display] = target
+ // })
+ // data.tikv?.nodes?.forEach((node) => {
+ // const display = `${node.ip}:${node.port}`
+ // const target = {
+ // kind: 'tikv',
+ // display_name: display,
+ // ip: node.ip,
+ // port: node.status_port,
+ // }
+ // map[display] = target
+ // })
+ // data.pd?.nodes?.forEach((node) => {
+ // const display = `${node.ip}:${node.port}`
+ // const target = {
+ // kind: 'pd',
+ // display_name: display,
+ // ip: node.ip,
+ // port: node.port,
+ // }
+ // map[display] = target
+ // })
+ // return map
+ // }, [data])
}
const profilingDurationsSec = [10, 30, 60, 120]
diff --git a/ui/lib/apps/KeyViz/components/KeyVizSettingForm.tsx b/ui/lib/apps/KeyViz/components/KeyVizSettingForm.tsx
index 5add68218a..4cfc5963c2 100644
--- a/ui/lib/apps/KeyViz/components/KeyVizSettingForm.tsx
+++ b/ui/lib/apps/KeyViz/components/KeyVizSettingForm.tsx
@@ -12,7 +12,6 @@ import {
import { ExclamationCircleOutlined } from '@ant-design/icons'
import { useTranslation } from 'react-i18next'
import client, { ConfigKeyVisualConfig } from '@lib/client'
-import { setHidden } from '@lib/utils/form'
const policyConfigurable = process.env.NODE_ENV === 'development'
@@ -167,17 +166,23 @@ function KeyVizSettingForm({ onClose, onConfigUpdated }: Props) {
{policyOptions}
+ client.getInstance().getAlertManagerTopology({ cancelToken })
+ )
+ const {
+ data: grafanaData,
+ isLoading: grafanaIsLoading,
+ } = useClientRequest((cancelToken) =>
+ client.getInstance().getGrafanaTopology({ cancelToken })
+ )
+
useEffect(() => {
- const fetchNum = async () => {
- if (!cluster || !cluster.alert_manager) {
- return
- }
+ if (!amData) {
+ return
+ }
+ async function fetch() {
let resp = await client
.getInstance()
- .topologyAlertmanagerAddressCountGet(
- `${cluster.alert_manager.ip}:${cluster.alert_manager.port}`
- )
+ .getAlertManagerCounts(`${amData!.ip}:${amData!.port}`)
setAlertCounter(resp.data)
}
- fetchNum()
- }, [cluster])
+ fetch()
+ }, [amData])
return (
-
-
- {!cluster || !cluster.grafana ? (
- t('overview.monitor_alert.view_monitor_warn')
- ) : (
-
- {t('overview.monitor_alert.view_monitor')}
-
+
+
+ {!grafanaData && (
+
+
+
+ {t('overview.monitor_alert.view_monitor_warn')}
+
+
+ )}
+ {grafanaData && (
+
+
+ {t('overview.monitor_alert.view_monitor')}
+
+
)}
-
-
- {!cluster || !cluster.alert_manager ? (
- t('overview.monitor_alert.view_alerts_warn')
- ) : (
-
- {alertCounter === 0
- ? t('overview.monitor_alert.view_zero_alerts')
- : t('overview.monitor_alert.view_alerts', {
- alertCount: alertCounter,
- })}
-
+
+
+ {!amData && (
+
+
+
+ {t('overview.monitor_alert.view_alerts_warn')}
+
+
+ )}
+ {amData && (
+
+
+ 0 ? 'danger' : undefined}>
+ {alertCounter === 0
+ ? t('overview.monitor_alert.view_zero_alerts')
+ : t('overview.monitor_alert.view_alerts', {
+ alertCount: alertCounter,
+ })}
+
+
+
)}
-
-
-
-
- {t('overview.monitor_alert.run_diagnose')}
-
-
-
+
+
+
+
+ {t('overview.monitor_alert.run_diagnose')}
+
+
+
+
+
)
}
diff --git a/ui/lib/apps/Overview/components/Nodes.tsx b/ui/lib/apps/Overview/components/Nodes.tsx
index b8e1721e13..639ac12d72 100644
--- a/ui/lib/apps/Overview/components/Nodes.tsx
+++ b/ui/lib/apps/Overview/components/Nodes.tsx
@@ -1,93 +1,113 @@
import { Link } from 'react-router-dom'
import React, { useMemo } from 'react'
-import { Card, AnimatedSkeleton } from '@lib/components'
+import { Card, AnimatedSkeleton, Descriptions } from '@lib/components'
import { useTranslation } from 'react-i18next'
import { useClientRequest } from '@lib/utils/useClientRequest'
import client from '@lib/client'
-import { Alert, Typography } from 'antd'
+import { Typography, Row, Col, Space } from 'antd'
import {
STATUS_UP,
STATUS_TOMBSTONE,
STATUS_OFFLINE,
} from '@lib/apps/ClusterInfo/status/status'
-import { RightOutlined } from '@ant-design/icons'
+import { RightOutlined, WarningOutlined } from '@ant-design/icons'
+import { Stack } from 'office-ui-fabric-react/lib/Stack'
-export default function Nodes() {
- const { t } = useTranslation()
- const { data, isLoading, error } = useClientRequest((cancelToken) =>
- client.getInstance().topologyAllGet({ cancelToken })
- )
-
- const statusMap = useMemo(() => {
- if (!data) {
- return []
+function ComponentItem(props: {
+ name: string
+ resp: { data?: { status?: number }[]; isLoading: boolean; error?: any }
+}) {
+ const { name, resp } = props
+ const [upNums, allNums] = useMemo(() => {
+ if (!resp.data) {
+ return [0, 0]
}
- const r: any[] = []
- const components = ['tidb', 'tikv', 'tiflash', 'pd']
- components.forEach((componentName) => {
- if (!data[componentName]) {
- return
- }
- if (data[componentName].err) {
- r.push({ name: componentName, error: true })
- return
+ let up = 0
+ let all = 0
+ for (const instance of resp.data) {
+ all++
+ if (
+ instance.status === STATUS_UP ||
+ instance.status === STATUS_TOMBSTONE ||
+ instance.status === STATUS_OFFLINE
+ ) {
+ up++
}
+ }
+ return [up, all]
+ }, [resp])
- let normals = 0,
- abnormals = 0
- data[componentName].nodes.forEach((n) => {
- if (
- n.status === STATUS_UP ||
- n.status === STATUS_TOMBSTONE ||
- n.status === STATUS_OFFLINE
- ) {
- normals++
- } else {
- abnormals++
- }
- })
+ return (
+
+ {!resp.error && (
+
+
+
+ {upNums}
+ / {allNums}
+
+
+
+ )}
+ {resp.error && (
+
+
+ Error
+
+
+ )}
+
+ )
+}
- if (normals > 0 || abnormals > 0) {
- r.push({ name: componentName, normals, abnormals })
- }
- })
- return r
- }, [data])
+export default function Nodes() {
+ const { t } = useTranslation()
+ const tidbResp = useClientRequest((cancelToken) =>
+ client.getInstance().getTiDBTopology({ cancelToken })
+ )
+ const storeResp = useClientRequest((cancelToken) =>
+ client.getInstance().getStoreTopology({ cancelToken })
+ )
+ const tiKVResp = {
+ ...storeResp,
+ data: storeResp.data?.tikv,
+ }
+ const tiFlashResp = {
+ ...storeResp,
+ data: storeResp.data?.tiflash,
+ }
+ const pdResp = useClientRequest((cancelToken) =>
+ client.getInstance().getPDTopology({ cancelToken })
+ )
return (
- {t('overview.nodes.title')}
+ {t('overview.status.title')}
}
noMarginLeft
>
-
- {error && }
- {data &&
- statusMap.map((s) => {
- return (
-
- {t(`overview.nodes.component.${s.name}`)}:
- {s.error && (
- Error
- )}
- {!s.error && (
-
- {s.normals} Up /{' '}
- 0 ? 'danger' : undefined}
- >
- {s.abnormals} Down
-
-
- )}
-
- )
- })}
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
)
}
diff --git a/ui/lib/apps/Overview/index.tsx b/ui/lib/apps/Overview/index.tsx
index 7a485c7254..1010d06147 100644
--- a/ui/lib/apps/Overview/index.tsx
+++ b/ui/lib/apps/Overview/index.tsx
@@ -1,11 +1,10 @@
import { Col, Row } from 'antd'
-import React, { useEffect, useState } from 'react'
+import React from 'react'
import { useTranslation } from 'react-i18next'
import { HashRouter as Router, Link } from 'react-router-dom'
import { RightOutlined } from '@ant-design/icons'
import { StatementsTable, useStatement } from '@lib/apps/Statement'
-import client, { ClusterinfoClusterInfo } from '@lib/client'
import { DateTime, MetricChart, Root } from '@lib/components'
import SlowQueriesTable from '../SlowQuery/components/SlowQueriesTable'
@@ -18,7 +17,6 @@ import Nodes from './components/Nodes'
export default function App() {
const { t } = useTranslation()
- const [cluster, setCluster] = useState(null)
const {
orderOptions: stmtOrderOptions,
changeOrder: changeStmtOrder,
@@ -37,18 +35,6 @@ export default function App() {
queryTimeRange,
} = useSlowQuery({ ...DEF_SLOW_QUERY_OPTIONS, limit: 10 }, false)
- useEffect(() => {
- const fetchLoad = async () => {
- try {
- let res = await client.getInstance().topologyAllGet()
- setCluster(res.data)
- } catch (error) {
- setCluster(null)
- }
- }
- fetchLoad()
- }, [])
-
return (
@@ -149,7 +135,7 @@ export default function App() {
-
+
diff --git a/ui/lib/apps/Overview/translations/en.yaml b/ui/lib/apps/Overview/translations/en.yaml
index b6c7734533..0b15c4f5c1 100644
--- a/ui/lib/apps/Overview/translations/en.yaml
+++ b/ui/lib/apps/Overview/translations/en.yaml
@@ -4,6 +4,8 @@ overview:
title: Top SQL Statements
recent_slow_query:
title: Recent Slow Queries
+ status:
+ title: Alive Instances
monitor_alert:
title: Monitor
view_monitor: View Metrics
@@ -15,10 +17,3 @@ overview:
metrics:
total_requests: QPS
latency: Latency
- nodes:
- title: Nodes
- component:
- tidb: TiDB
- tikv: TiKV
- pd: PD
- tiflash: TiFlash
diff --git a/ui/lib/apps/Overview/translations/zh-CN.yaml b/ui/lib/apps/Overview/translations/zh-CN.yaml
index 622ae01ae6..9abf5b6198 100644
--- a/ui/lib/apps/Overview/translations/zh-CN.yaml
+++ b/ui/lib/apps/Overview/translations/zh-CN.yaml
@@ -5,9 +5,7 @@ overview:
recent_slow_query:
title: 最近的慢查询
status:
- up: 正常
- abnormal: 异常
- nodes: '{{nodeType}} 节点'
+ title: 在线实例
monitor_alert:
title: 监控告警
view_monitor: 查看监控
@@ -19,10 +17,3 @@ overview:
metrics:
total_requests: QPS
latency: 延迟
- nodes:
- title: 节点
- component:
- tidb: TiDB
- tikv: TiKV
- pd: PD
- tiflash: TiFlash
diff --git a/ui/lib/apps/SearchLogs/components/SearchHeader.tsx b/ui/lib/apps/SearchLogs/components/SearchHeader.tsx
index 5edf9dc1f7..cb5a69fedf 100644
--- a/ui/lib/apps/SearchLogs/components/SearchHeader.tsx
+++ b/ui/lib/apps/SearchLogs/components/SearchHeader.tsx
@@ -14,7 +14,7 @@ import {
namingMap,
NodeKind,
NodeKindList,
- parseClusterInfo,
+ // parseClusterInfo,
parseSearchingParams,
} from './utils'
import {
@@ -77,8 +77,10 @@ export default function SearchHeader({ taskGroupID }: Props) {
useMount(() => {
async function fetchData() {
- const res = await client.getInstance().topologyAllGet()
- const targets = parseClusterInfo(res.data)
+ const res = {} as any
+ // const res = await client.getInstance().topologyAllGet()
+ // const targets = parseClusterInfo(res.data)
+ const targets = [] as any
setAllTargets(targets)
setComponents(targets.map((item) => item.display_name!))
if (!taskGroupID) {
diff --git a/ui/lib/apps/SearchLogs/components/utils.ts b/ui/lib/apps/SearchLogs/components/utils.ts
index 47cc2819d9..a05b5832d4 100644
--- a/ui/lib/apps/SearchLogs/components/utils.ts
+++ b/ui/lib/apps/SearchLogs/components/utils.ts
@@ -1,5 +1,4 @@
import {
- ClusterinfoClusterInfo,
LogsearchTaskGroupResponse,
LogsearchTaskModel,
ModelRequestTargetNode,
@@ -40,65 +39,65 @@ export const namingMap = {
export const AllLogLevel = [1, 2, 3, 4, 5, 6]
-export function parseClusterInfo(
- info: ClusterinfoClusterInfo
-): ModelRequestTargetNode[] {
- const targets: ModelRequestTargetNode[] = []
- info?.tidb?.nodes?.forEach((item) => {
- if (
- item.ip === undefined ||
- item.port === undefined ||
- item.status_port === undefined
- ) {
- return
- }
- // TiDB has a different behavior: it use "status_port" for grpc, "port" for display.
- targets.push({
- kind: NodeKind.TiDB,
- ip: item.ip,
- port: item.status_port,
- display_name: `${item.ip}:${item.port}`,
- })
- })
- info?.tikv?.nodes?.forEach((item) => {
- if (
- item.ip === undefined ||
- item.port === undefined ||
- item.status_port === undefined
- ) {
- return
- }
- targets.push({
- kind: NodeKind.TiKV,
- ip: item.ip,
- port: item.port,
- display_name: `${item.ip}:${item.port}`,
- })
- })
- info?.pd?.nodes?.forEach((item) => {
- if (item.ip === undefined || item.port === undefined) {
- return
- }
- targets.push({
- kind: NodeKind.PD,
- ip: item.ip,
- port: item.port,
- display_name: `${item.ip}:${item.port}`,
- })
- })
- info?.tiflash?.nodes?.forEach((item) => {
- if (!(item.ip && item.port)) {
- return
- }
- targets.push({
- kind: NodeKind.TiFlash,
- ip: item.ip,
- port: item.port,
- display_name: `${item.ip}:${item.port}`,
- })
- })
- return targets
-}
+// export function parseClusterInfo(
+// info: ClusterinfoClusterInfo
+// ): ModelRequestTargetNode[] {
+// const targets: ModelRequestTargetNode[] = []
+// info?.tidb?.nodes?.forEach((item) => {
+// if (
+// item.ip === undefined ||
+// item.port === undefined ||
+// item.status_port === undefined
+// ) {
+// return
+// }
+// // TiDB has a different behavior: it use "status_port" for grpc, "port" for display.
+// targets.push({
+// kind: NodeKind.TiDB,
+// ip: item.ip,
+// port: item.status_port,
+// display_name: `${item.ip}:${item.port}`,
+// })
+// })
+// info?.tikv?.nodes?.forEach((item) => {
+// if (
+// item.ip === undefined ||
+// item.port === undefined ||
+// item.status_port === undefined
+// ) {
+// return
+// }
+// targets.push({
+// kind: NodeKind.TiKV,
+// ip: item.ip,
+// port: item.port,
+// display_name: `${item.ip}:${item.port}`,
+// })
+// })
+// info?.pd?.nodes?.forEach((item) => {
+// if (item.ip === undefined || item.port === undefined) {
+// return
+// }
+// targets.push({
+// kind: NodeKind.PD,
+// ip: item.ip,
+// port: item.port,
+// display_name: `${item.ip}:${item.port}`,
+// })
+// })
+// info?.tiflash?.nodes?.forEach((item) => {
+// if (!(item.ip && item.port)) {
+// return
+// }
+// targets.push({
+// kind: NodeKind.TiFlash,
+// ip: item.ip,
+// port: item.port,
+// display_name: `${item.ip}:${item.port}`,
+// })
+// })
+// return targets
+// }
interface Params {
timeRange: TimeRange
diff --git a/ui/lib/components/BaseSelect/index.module.less b/ui/lib/components/BaseSelect/index.module.less
new file mode 100644
index 0000000000..8952c4ab24
--- /dev/null
+++ b/ui/lib/components/BaseSelect/index.module.less
@@ -0,0 +1,89 @@
+@import '~antd/es/style/themes/default.less';
+@import '~antd/es/style/mixins/index';
+@import '~antd/es/input/style/mixin';
+@import '~antd/es/select/style/index';
+
+.baseSelect {
+ .reset-component;
+ position: relative;
+ display: inline-block;
+}
+
+.baseSelectInner {
+ position: relative;
+ background-color: @select-background;
+ border: @border-width-base @border-style-base @select-border-color;
+ border-radius: @border-radius-base;
+ transition: all 0.3s @ease-in-out;
+ display: flex;
+ width: 100%;
+ height: @input-height-base;
+ padding: 0 @input-padding-horizontal-base;
+ cursor: pointer;
+ color: @text-color;
+
+ &.focused {
+ .active();
+ }
+
+ &.disabled {
+ color: @disabled-color;
+ background: @input-disabled-bg;
+ cursor: not-allowed;
+
+ .baseSelectInput {
+ cursor: not-allowed;
+ }
+ }
+
+ &:not(.disabled):hover {
+ .hover();
+ }
+}
+
+.baseSelectInput {
+ opacity: 0;
+ position: absolute;
+ top: 0;
+ left: 0;
+ background: transparent;
+ border: none;
+ outline: none;
+ cursor: pointer;
+ width: 100%;
+ height: @select-height-without-border;
+}
+
+.baseSelectValueDisplay {
+ position: relative;
+ display: block;
+ padding-right: @selection-item-padding;
+ font-weight: normal;
+ font-size: @select-dropdown-font-size;
+ line-height: @select-height-without-border;
+ transition: all 0.3s;
+ pointer-events: none;
+ width: 100%;
+}
+
+.baseSelectArrow {
+ position: absolute;
+ top: 53%; // The same as Ant-design's select
+ right: @input-padding-horizontal-base;
+ width: @font-size-sm;
+ height: @font-size-sm;
+ margin-top: -@font-size-sm / 2;
+ color: @disabled-color;
+ font-size: @font-size-sm;
+ line-height: 1;
+ text-align: center;
+ pointer-events: none;
+}
+
+.baseSelectOverlay {
+ background-color: @select-dropdown-bg;
+ border-radius: @border-radius-base;
+ outline: none;
+ box-shadow: @box-shadow-base;
+ box-sizing: border-box;
+}
diff --git a/ui/lib/components/BaseSelect/index.tsx b/ui/lib/components/BaseSelect/index.tsx
new file mode 100644
index 0000000000..a3ce881009
--- /dev/null
+++ b/ui/lib/components/BaseSelect/index.tsx
@@ -0,0 +1,183 @@
+import React, { useState, useCallback, useRef } from 'react'
+import cx from 'classnames'
+import { Dropdown } from 'antd'
+import { useEventListener } from '@umijs/hooks'
+import { DownOutlined } from '@ant-design/icons'
+import KeyCode from 'rc-util/lib/KeyCode'
+import { TextWrap } from '..'
+
+import styles from './index.module.less'
+
+export interface IBaseSelectDropdownRenderProps {
+ value?: T
+ triggerOnChange?: (value: T) => void
+}
+
+export interface IBaseSelectProps
+ extends Omit, 'onChange'> {
+ dropdownRender: (
+ renderProps: IBaseSelectDropdownRenderProps
+ ) => React.ReactElement
+ value?: T
+ valueRender: (value?: T) => React.ReactNode
+ onChange?: (value: T) => void
+ disabled?: boolean
+ tabIndex?: number
+ autoFocus?: boolean
+}
+
+function BaseSelect({
+ dropdownRender,
+ value,
+ valueRender,
+ onChange,
+ disabled,
+ tabIndex,
+ autoFocus,
+ className,
+ onFocus,
+ onBlur,
+ onKeyDown,
+ onMouseDown,
+ ...restProps
+}: IBaseSelectProps) {
+ const [dropdownVisible, setDropdownVisible] = useState(false)
+ const toggleDropdownVisible = useCallback(() => {
+ if (disabled) {
+ return
+ }
+ setDropdownVisible((v) => !v)
+ }, [disabled])
+
+ const [isFocused, setFocused] = useState(false)
+
+ const handleContainerFocus = useCallback(
+ (ev: React.FocusEvent) => {
+ setFocused(true)
+ onFocus && onFocus(ev)
+ },
+ [onFocus]
+ )
+
+ const handleContainerBlur = useCallback(
+ (ev: React.FocusEvent) => {
+ setDropdownVisible(false)
+ setFocused(false)
+ onBlur && onBlur(ev)
+ },
+ [onBlur]
+ )
+
+ const handleContainerKeyDown = useCallback(
+ (ev: React.KeyboardEvent) => {
+ if (ev.which === KeyCode.ENTER) {
+ toggleDropdownVisible()
+ } else if (ev.which === KeyCode.ESC) {
+ setDropdownVisible(false)
+ }
+ onKeyDown && onKeyDown(ev)
+ },
+ [toggleDropdownVisible, onKeyDown]
+ )
+
+ const handleContainerMouseDown = useCallback(
+ (ev: React.MouseEvent) => {
+ toggleDropdownVisible()
+ onMouseDown && onMouseDown(ev)
+ },
+ [toggleDropdownVisible, onMouseDown]
+ )
+
+ const handleOverlayMouseDown = useCallback(
+ (ev: React.MouseEvent) => {
+ // Prevent dropdown container blur event
+ ev.preventDefault()
+ },
+ []
+ )
+
+ const dropdownOverlayRef = useRef(null)
+ const containerRef = useRef(null)
+
+ const overlay = (
+
+ {dropdownRender({
+ value,
+ triggerOnChange: onChange,
+ })}
+
+ )
+
+ useEventListener('mousedown', (ev: MouseEvent) => {
+ // Close the dropdown if click outside
+ if (!dropdownVisible) {
+ return
+ }
+ const hitElements = [dropdownOverlayRef.current, containerRef.current]
+ if (
+ hitElements.every(
+ (e) =>
+ !e ||
+ !ev.target ||
+ (!e.contains(ev.target as HTMLElement) && e !== ev.target)
+ )
+ ) {
+ setDropdownVisible(false)
+ }
+ })
+
+ // Close dropdown when disabled change
+ React.useEffect(() => {
+ setDropdownVisible((v) => {
+ if (v && !disabled) {
+ return false
+ }
+ // Otherwise, unchanged
+ return v
+ })
+ }, [disabled])
+
+ return (
+
+
+
+
+
+ {valueRender(value)}
+
+
+
+
+
+
+
+ )
+}
+
+BaseSelect.whyDidYouRender = true
+
+export default React.memo(BaseSelect)
diff --git a/ui/lib/components/CardTableV2/GroupHeader.tsx b/ui/lib/components/CardTableV2/GroupHeader.tsx
new file mode 100644
index 0000000000..5a2ac87aa9
--- /dev/null
+++ b/ui/lib/components/CardTableV2/GroupHeader.tsx
@@ -0,0 +1,114 @@
+// FIXME: This is mostly a clone from https://github.com/microsoft/fluentui/blob/master/packages/office-ui-fabric-react/src/components/GroupedList/GroupHeader.base.tsx, but replaced with Ant'd Checkbox
+// Drop it after https://github.com/microsoft/fluentui/issues/13144 is resolved
+
+import React from 'react'
+import {
+ classNamesFunction,
+ styled,
+} from 'office-ui-fabric-react/lib/Utilities'
+import {
+ IGroupHeaderStyleProps,
+ IGroupHeaderStyles,
+ IGroupHeaderProps,
+ GroupSpacer,
+} from 'office-ui-fabric-react/lib/GroupedList'
+import {
+ FocusZone,
+ FocusZoneDirection,
+} from 'office-ui-fabric-react/lib/FocusZone'
+import { getStyles } from 'office-ui-fabric-react/lib/components/GroupedList/GroupHeader.styles'
+
+import { Icon } from 'office-ui-fabric-react/lib/Icon'
+import { Checkbox } from 'antd'
+import { usePersistFn } from '@umijs/hooks'
+
+const getClassNames = classNamesFunction<
+ IGroupHeaderStyleProps,
+ IGroupHeaderStyles
+>()
+
+function BaseAntCheckboxGroupHeader(props: IGroupHeaderProps) {
+ const _classNames = getClassNames(props.styles, {
+ theme: props.theme!,
+ className: props.className,
+ selected: props.selected,
+ isCollapsed: props.group?.isCollapsed,
+ compact: props.compact,
+ })
+
+ const _onHeaderClick = usePersistFn(() => {
+ if (props.onToggleSelectGroup) {
+ props.onToggleSelectGroup(props.group!)
+ }
+ })
+
+ const _onToggleSelectGroupClick = usePersistFn(
+ (ev: React.MouseEvent) => {
+ if (props.onToggleSelectGroup) {
+ props.onToggleSelectGroup(props.group!)
+ }
+ ev.preventDefault()
+ ev.stopPropagation()
+ }
+ )
+
+ const _onToggleCollapse = usePersistFn(
+ (ev: React.MouseEvent) => {
+ if (props.onToggleCollapse) {
+ props.onToggleCollapse(props.group!)
+ }
+ ev.stopPropagation()
+ ev.preventDefault()
+ }
+ )
+
+ return (
+
+
+
+
+
+
+
+ {props.group?.name}
+
+
+
+ )
+}
+
+export const AntCheckboxGroupHeader: React.FunctionComponent = styled<
+ IGroupHeaderProps,
+ IGroupHeaderStyleProps,
+ IGroupHeaderStyles
+>(BaseAntCheckboxGroupHeader, getStyles, undefined, {
+ scope: 'GroupHeader',
+})
diff --git a/ui/lib/components/CardTableV2/index.tsx b/ui/lib/components/CardTableV2/index.tsx
index 13bb57500f..02107b128d 100644
--- a/ui/lib/components/CardTableV2/index.tsx
+++ b/ui/lib/components/CardTableV2/index.tsx
@@ -6,20 +6,52 @@ import {
IColumn,
IDetailsListProps,
SelectionMode,
+ // IDetailsGroupDividerProps,
} from 'office-ui-fabric-react/lib/DetailsList'
import { Sticky, StickyPositionType } from 'office-ui-fabric-react/lib/Sticky'
import React, { useCallback, useEffect, useMemo } from 'react'
import { usePersistFn } from '@umijs/hooks'
-
import AnimatedSkeleton from '../AnimatedSkeleton'
import Card from '../Card'
+
import styles from './index.module.less'
+export { AntCheckboxGroupHeader } from './GroupHeader'
+// import { GroupSpacer } from 'office-ui-fabric-react/lib/GroupedList'
+// import { Icon } from 'office-ui-fabric-react/lib/Icon'
+
DetailsList.whyDidYouRender = {
customName: 'DetailsList',
} as any
-const MemoDetailsList = React.memo(DetailsList)
+function renderStickyHeader(props, defaultRender) {
+ if (!props) {
+ return null
+ }
+ return (
+
+ {defaultRender!(props)}
+
+ )
+}
+
+function renderCheckbox(props) {
+ return
+}
+
+export function ImprovedDetailsList(props: IDetailsListProps) {
+ return (
+
+ )
+}
+
+ImprovedDetailsList.whyDidYouRender = true
+
+export const MemoDetailsList = React.memo(ImprovedDetailsList)
function copyAndSort(
items: T[],
@@ -62,17 +94,6 @@ export interface ICardTableV2Props extends IDetailsListProps {
onGetColumns?: (columns: IColumn[]) => void
}
-function renderStickyHeader(props, defaultRender) {
- if (!props) {
- return null
- }
- return (
-
- {defaultRender!(props)}
-
- )
-}
-
function useRenderClickableRow(onRowClicked) {
return useCallback(
(props, defaultRender) => {
@@ -163,10 +184,6 @@ function CardTableV2(props: ICardTableV2Props) {
// eslint-disable-next-line
}, [columns])
- const onRenderCheckbox = useCallback((props) => {
- return
- }, [])
-
return (
,
+}
+
+export default function DropOverlay({
+ selection,
+ columns,
+ items,
+ groups,
+}: {
+ selection: Selection
+ columns: IColumn[]
+ items: IInstanceTableItem[]
+ groups: IGroup[]
+}) {
+ const [containerState, containerRef] = useSize()
+ return (
+
+ )
+}
diff --git a/ui/lib/components/InstanceSelect/SelectDisplay.tsx b/ui/lib/components/InstanceSelect/SelectDisplay.tsx
new file mode 100644
index 0000000000..0337e966e2
--- /dev/null
+++ b/ui/lib/components/InstanceSelect/SelectDisplay.tsx
@@ -0,0 +1,68 @@
+import React, { useMemo } from 'react'
+import { IInstanceTableItem, InstanceKind } from '@lib/utils/instanceTable'
+import { Typography } from 'antd'
+
+interface InstanceStat {
+ all: number
+ selected: number
+}
+
+function newInstanceStat(): InstanceStat {
+ return {
+ all: 0,
+ selected: 0,
+ }
+}
+
+export default function SelectDisplay({
+ items,
+ selectedKeys,
+}: {
+ items: IInstanceTableItem[]
+ selectedKeys: string[]
+}) {
+ const text = useMemo(() => {
+ const selectedKeysMap = {}
+ selectedKeys.forEach((key) => (selectedKeysMap[key] = true))
+ const instanceStats: { [key in InstanceKind]: InstanceStat } = {
+ pd: newInstanceStat(),
+ tidb: newInstanceStat(),
+ tikv: newInstanceStat(),
+ tiflash: newInstanceStat(),
+ }
+ items.forEach((item) => {
+ instanceStats[item.instanceKind].all++
+ if (selectedKeysMap[item.key]) {
+ instanceStats[item.instanceKind].selected++
+ }
+ })
+
+ let hasUnselected = false
+ const p: string[] = []
+ for (const ik in instanceStats) {
+ const stats = instanceStats[ik] as InstanceStat
+ if (stats.selected !== stats.all) {
+ hasUnselected = true
+ }
+ if (stats.selected > 0) {
+ if (stats.all === stats.selected) {
+ p.push('All ' + ik)
+ } else {
+ p.push(`${stats.selected} ${ik}`)
+ }
+ }
+ }
+
+ if (!hasUnselected) {
+ return 'All Instances'
+ }
+ return p.join(', ')
+ }, [items, selectedKeys])
+
+ if (items.length === 0 || selectedKeys.length === 0) {
+ // Not yet loaded
+ return Select Instance
+ } else {
+ return {text}
+ }
+}
diff --git a/ui/lib/components/InstanceSelect/index.tsx b/ui/lib/components/InstanceSelect/index.tsx
new file mode 100644
index 0000000000..9106b6c8ff
--- /dev/null
+++ b/ui/lib/components/InstanceSelect/index.tsx
@@ -0,0 +1,165 @@
+import React, { useCallback, useRef, useMemo, useEffect, useState } from 'react'
+import { Tooltip, Typography } from 'antd'
+import { Selection } from 'office-ui-fabric-react/lib/Selection'
+import { BaseSelect, InstanceStatusBadge, TextWrap } from '../'
+import { useClientRequest } from '@lib/utils/useClientRequest'
+import client from '@lib/client'
+import { usePersistFn } from '@umijs/hooks'
+import { IColumn } from 'office-ui-fabric-react/lib/DetailsList'
+import {
+ buildInstanceTable,
+ IInstanceTableItem,
+} from '@lib/utils/instanceTable'
+
+import DropOverlay from './DropOverlay'
+import SelectDisplay from './SelectDisplay'
+
+export interface IInstanceSelectProps {
+ enableTiFlash?: boolean
+ defaultSelectAll?: boolean
+ onChange?: (values: string[]) => void
+ value?: string[]
+}
+
+export interface IInstanceSelectRefProps {
+ mapValueToNode: (value: string) => void
+}
+
+function InstanceSelect(
+ props: IInstanceSelectProps,
+ ref: React.Ref
+) {
+ const {
+ data: dataTiDB,
+ isLoading: loadingTiDB,
+ } = useClientRequest((cancelToken) =>
+ client.getInstance().getTiDBTopology({ cancelToken })
+ )
+ const {
+ data: dataStores,
+ isLoading: loadingStores,
+ } = useClientRequest((cancelToken) =>
+ client.getInstance().getStoreTopology({ cancelToken })
+ )
+ const {
+ data: dataPD,
+ isLoading: loadingPD,
+ } = useClientRequest((cancelToken) =>
+ client.getInstance().getPDTopology({ cancelToken })
+ )
+
+ const columns = useMemo(() => {
+ const c: IColumn[] = [
+ {
+ name: 'Instance',
+ key: 'key',
+ minWidth: 160,
+ maxWidth: 160,
+ onRender: (node: IInstanceTableItem) => {
+ return (
+
+
+ {node.key}
+
+
+ )
+ },
+ },
+ {
+ name: 'Status',
+ key: 'status',
+ minWidth: 100,
+ maxWidth: 100,
+ onRender: (node: IInstanceTableItem) => {
+ return (
+
+
+
+ )
+ },
+ },
+ ]
+ return c
+ }, [])
+
+ const [tableItems, tableGroups] = useMemo(() => {
+ if (loadingTiDB || loadingStores || loadingPD) {
+ return [[], []]
+ }
+ return buildInstanceTable({
+ dataPD,
+ dataTiDB,
+ dataTiKV: dataStores?.tikv,
+ dataTiFlash: dataStores?.tiflash,
+ includeTiFlash: props.enableTiFlash,
+ })
+ }, [
+ props.enableTiFlash,
+ props.defaultSelectAll,
+ dataTiDB,
+ dataStores,
+ dataPD,
+ loadingTiDB,
+ loadingStores,
+ loadingPD,
+ ])
+
+ const [selectedKeys, setSelectedKeys] = useState(props.value ?? [])
+
+ const selection = useRef(
+ new Selection({
+ onSelectionChanged: () => {
+ const s = selection.current.getSelection() as IInstanceTableItem[]
+ setSelectedKeys(s.map((v) => v.key))
+ },
+ })
+ )
+
+ const dataHasLoaded = useRef(false)
+
+ useEffect(() => {
+ // Select all if `defaultSelectAll` is set.
+ if (dataHasLoaded.current) {
+ return
+ }
+ if (tableItems.length === 0) {
+ return
+ }
+ if (props.defaultSelectAll) {
+ selection.current.setItems(tableItems)
+ selection.current.setAllSelected(true)
+ }
+ dataHasLoaded.current = true
+ }, [tableItems])
+
+ const mapValueToNode = usePersistFn(() => {})
+
+ React.useImperativeHandle(ref, () => ({
+ mapValueToNode,
+ }))
+
+ const renderValue = useCallback(() => {
+ return
+ }, [tableItems, selectedKeys])
+
+ const renderDropdown = useCallback(() => {
+ return (
+
+ )
+ }, [columns, tableItems, tableGroups])
+
+ return (
+
+ )
+}
+
+export default React.forwardRef(InstanceSelect)
diff --git a/ui/lib/components/InstanceStatusBadge/index.tsx b/ui/lib/components/InstanceStatusBadge/index.tsx
new file mode 100644
index 0000000000..3d3a835572
--- /dev/null
+++ b/ui/lib/components/InstanceStatusBadge/index.tsx
@@ -0,0 +1,83 @@
+import React from 'react'
+import { useTranslation } from 'react-i18next'
+import { InstanceStatus } from '@lib/utils/instanceTable'
+import { Badge } from 'antd'
+import { addTranslationResource } from '@lib/utils/i18n'
+
+const translations = {
+ en: {
+ status: {
+ up: 'Up',
+ down: 'Down',
+ tombstone: 'Tombstone',
+ offline: 'Offline',
+ unknown: 'Unknown',
+ unreachable: 'Unreachable',
+ },
+ },
+ 'zh-CN': {
+ status: {
+ up: '在线',
+ down: '离线',
+ tombstone: '已缩容下线',
+ offline: '下线中',
+ unknown: '未知',
+ unreachable: '无法访问',
+ },
+ },
+}
+
+for (const key in translations) {
+ addTranslationResource(key, {
+ component: {
+ instanceStatusBadge: translations[key],
+ },
+ })
+}
+
+export interface IInstanceStatusBadgeProps {
+ status?: number
+}
+
+function InstanceStatusBadge({ status }: IInstanceStatusBadgeProps) {
+ const { t } = useTranslation()
+ switch (status) {
+ case InstanceStatus.Down:
+ return (
+
+ )
+ case InstanceStatus.Up:
+ return (
+
+ )
+ case InstanceStatus.Tombstone:
+ return (
+
+ )
+ case InstanceStatus.Offline:
+ return (
+
+ )
+ default:
+ return (
+
+ )
+ }
+}
+
+export default React.memo(InstanceStatusBadge)
diff --git a/ui/lib/components/index.ts b/ui/lib/components/index.ts
index 33823aef9f..80637c04d1 100644
--- a/ui/lib/components/index.ts
+++ b/ui/lib/components/index.ts
@@ -38,5 +38,11 @@ export * from './TimeRangeSelector'
export { default as TimeRangeSelector } from './TimeRangeSelector'
export * from './AnimatedSkeleton'
export { default as AnimatedSkeleton } from './AnimatedSkeleton'
+export * from './InstanceStatusBadge'
+export { default as InstanceStatusBadge } from './InstanceStatusBadge'
+export * from './BaseSelect'
+export { default as BaseSelect } from './BaseSelect'
+export * from './InstanceSelect'
+export { default as InstanceSelect } from './InstanceSelect'
export { default as LanguageDropdown } from './LanguageDropdown'
diff --git a/ui/lib/utils/form.ts b/ui/lib/utils/form.ts
deleted file mode 100644
index 059704099c..0000000000
--- a/ui/lib/utils/form.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-const hiddenProps = {
- style: {
- display: 'none',
- },
-}
-
-const showProps = {}
-
-export function setHidden(hidden: boolean) {
- return hidden ? hiddenProps : showProps
-}
diff --git a/ui/lib/utils/instanceTable.ts b/ui/lib/utils/instanceTable.ts
new file mode 100644
index 0000000000..3d40bccaa6
--- /dev/null
+++ b/ui/lib/utils/instanceTable.ts
@@ -0,0 +1,92 @@
+import {
+ TopologyPDInfo,
+ TopologyTiDBInfo,
+ TopologyStoreInfo,
+} from '@lib/client'
+import { IGroup } from 'office-ui-fabric-react/lib/DetailsList'
+
+export type InstanceKind = 'pd' | 'tidb' | 'tikv' | 'tiflash'
+
+export const InstanceStatus = {
+ Unreachable: 0,
+ Up: 1,
+ Tombstone: 2,
+ Offline: 3,
+ Down: 4,
+}
+
+export const InstanceKindName: { [key in InstanceKind]: string } = {
+ pd: 'PD',
+ tidb: 'TiDB',
+ tikv: 'TiKV',
+ tiflash: 'TiFlash',
+}
+
+export interface IInstanceTableItem
+ extends TopologyPDInfo,
+ TopologyTiDBInfo,
+ TopologyStoreInfo {
+ key: string
+ instanceKind: InstanceKind
+}
+
+export interface IBuildInstanceTableProps {
+ dataPD?: TopologyPDInfo[]
+ dataTiDB?: TopologyTiDBInfo[]
+ dataTiKV?: TopologyStoreInfo[]
+ dataTiFlash?: TopologyStoreInfo[]
+ includeTiFlash?: boolean
+ filterHost?: string
+}
+
+export function buildInstanceTable({
+ dataPD,
+ dataTiDB,
+ dataTiKV,
+ dataTiFlash,
+ includeTiFlash,
+ filterHost,
+}: IBuildInstanceTableProps): [IInstanceTableItem[], IGroup[]] {
+ const tableData: IInstanceTableItem[] = []
+ const groupData: IGroup[] = []
+ let startIndex = 0
+ const kinds: [
+ InstanceKind,
+ TopologyPDInfo[] | TopologyTiDBInfo[] | TopologyStoreInfo[] | undefined
+ ][] = [
+ ['pd', dataPD],
+ ['tidb', dataTiDB],
+ ['tikv', dataTiKV],
+ ]
+ if (includeTiFlash) {
+ kinds.push(['tiflash', dataTiFlash])
+ }
+ for (const item of kinds) {
+ const [ik, instances] = item
+ if (!instances || instances.length === 0) {
+ continue
+ }
+ groupData.push({
+ key: ik,
+ name: InstanceKindName[ik],
+ startIndex: startIndex,
+ count: instances.length,
+ level: 0,
+ })
+ startIndex += instances.length
+ instances.forEach((instance) => {
+ const key = `${instance.ip}:${instance.port}`
+ if (filterHost != null && filterHost.length > 0) {
+ if (key.indexOf(filterHost) === -1) {
+ return
+ }
+ }
+ tableData.push({
+ key: key,
+ instanceKind: ik,
+ ...instance,
+ })
+ })
+ }
+ return [tableData, groupData]
+}
diff --git a/ui/lib/utils/useClientRequest.ts b/ui/lib/utils/useClientRequest.ts
index b625167d6d..26bc6aca7e 100644
--- a/ui/lib/utils/useClientRequest.ts
+++ b/ui/lib/utils/useClientRequest.ts
@@ -1,4 +1,4 @@
-import { useMount, useUnmount } from '@umijs/hooks'
+import { useMount, useUnmount, usePersistFn } from '@umijs/hooks'
import { useState, useRef, useEffect } from 'react'
import { CancelToken, AxiosPromise, CancelTokenSource } from 'axios'
import axios from 'axios'
@@ -34,7 +34,7 @@ export function useClientRequest(
const cancelTokenSource = useRef(null)
const mounted = useRef(false)
- const sendRequest = async () => {
+ const sendRequest = usePersistFn(async () => {
if (!mounted.current) {
return
}
@@ -72,7 +72,7 @@ export function useClientRequest(
cancelTokenSource.current = null
afterRequest && afterRequest()
- }
+ })
useMount(() => {
mounted.current = true
@@ -138,7 +138,7 @@ export function useBatchClientRequest(
}
}
- const sendRequest = async () => {
+ const sendRequest = usePersistFn(async () => {
if (!mounted.current) {
return
}
@@ -167,7 +167,7 @@ export function useBatchClientRequest(
cancelTokenSource.current = null
afterRequest && afterRequest()
- }
+ })
useMount(() => {
mounted.current = true
From cc1ce633d51473462e13ed463d036f918f7b3f71 Mon Sep 17 00:00:00 2001
From: Breezewish
Date: Fri, 15 May 2020 10:42:48 +0800
Subject: [PATCH 06/14] Adjust vagrant files
Signed-off-by: Breezewish
---
etc/manualTestEnv/.gitignore | 3 +-
.../Vagrantfile.partial.pubKey.ruby} | 11 ++----
etc/manualTestEnv/_shared/vagrant_key | 27 +++++++++++++
etc/manualTestEnv/_shared/vagrant_key.pub | 1 +
etc/manualTestEnv/basic/README.md | 19 ---------
etc/manualTestEnv/basicMultiHost/Vagrantfile | 23 -----------
.../{basicMultiHost => multiHost}/README.md | 19 ++++-----
etc/manualTestEnv/multiHost/Vagrantfile | 14 +++++++
.../topology.yaml | 9 +++++
etc/manualTestEnv/multiReplica/README.md | 17 ++++----
etc/manualTestEnv/multiReplica/Vagrantfile | 15 ++-----
etc/manualTestEnv/singleHost/README.md | 36 +++++++++++++++++
etc/manualTestEnv/singleHost/Vagrantfile | 10 +++++
etc/manualTestEnv/singleHost/topology.yaml | 37 ++++++++++++++++++
.../singleHostMultiDisk/.gitignore | 1 +
.../singleHostMultiDisk/README.md | 36 +++++++++++++++++
.../singleHostMultiDisk/Vagrantfile | 10 +++++
.../singleHostMultiDisk/topology.yaml | 39 +++++++++++++++++++
.../apps/ClusterInfo/components/HostTable.tsx | 9 ++++-
19 files changed, 254 insertions(+), 82 deletions(-)
rename etc/manualTestEnv/{basic/Vagrantfile => _shared/Vagrantfile.partial.pubKey.ruby} (55%)
create mode 100644 etc/manualTestEnv/_shared/vagrant_key
create mode 100644 etc/manualTestEnv/_shared/vagrant_key.pub
delete mode 100644 etc/manualTestEnv/basic/README.md
delete mode 100644 etc/manualTestEnv/basicMultiHost/Vagrantfile
rename etc/manualTestEnv/{basicMultiHost => multiHost}/README.md (54%)
create mode 100644 etc/manualTestEnv/multiHost/Vagrantfile
rename etc/manualTestEnv/{basicMultiHost => multiHost}/topology.yaml (56%)
create mode 100644 etc/manualTestEnv/singleHost/README.md
create mode 100644 etc/manualTestEnv/singleHost/Vagrantfile
create mode 100644 etc/manualTestEnv/singleHost/topology.yaml
create mode 100644 etc/manualTestEnv/singleHostMultiDisk/.gitignore
create mode 100644 etc/manualTestEnv/singleHostMultiDisk/README.md
create mode 100644 etc/manualTestEnv/singleHostMultiDisk/Vagrantfile
create mode 100644 etc/manualTestEnv/singleHostMultiDisk/topology.yaml
diff --git a/etc/manualTestEnv/.gitignore b/etc/manualTestEnv/.gitignore
index dd2a4be7ca..2f8e58cd1e 100644
--- a/etc/manualTestEnv/.gitignore
+++ b/etc/manualTestEnv/.gitignore
@@ -1,3 +1,2 @@
.vagrant/
-shared_key
-shared_key.pub
+tiup-cluster-*.log
diff --git a/etc/manualTestEnv/basic/Vagrantfile b/etc/manualTestEnv/_shared/Vagrantfile.partial.pubKey.ruby
similarity index 55%
rename from etc/manualTestEnv/basic/Vagrantfile
rename to etc/manualTestEnv/_shared/Vagrantfile.partial.pubKey.ruby
index 1dfffd2ee7..3af2b17570 100644
--- a/etc/manualTestEnv/basic/Vagrantfile
+++ b/etc/manualTestEnv/_shared/Vagrantfile.partial.pubKey.ruby
@@ -1,15 +1,12 @@
Vagrant.configure("2") do |config|
+ ssh_pub_key = File.readlines("#{File.dirname(__FILE__)}/vagrant_key.pub").first.strip
+
config.vm.box = "hashicorp/bionic64"
- config.vm.network "private_network", ip: "10.0.1.2"
config.vm.provision "shell", privileged: false, inline: <<-SHELL
sudo apt install -y zsh
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
sudo chsh -s /usr/bin/zsh vagrant
- curl --proto '=https' --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh
- source /home/vagrant/.zshrc
+
+ echo #{ssh_pub_key} >> /home/vagrant/.ssh/authorized_keys
SHELL
- config.vm.provider "virtualbox" do |v|
- v.memory = 4096
- v.cpus = 2
- end
end
diff --git a/etc/manualTestEnv/_shared/vagrant_key b/etc/manualTestEnv/_shared/vagrant_key
new file mode 100644
index 0000000000..7b55495744
--- /dev/null
+++ b/etc/manualTestEnv/_shared/vagrant_key
@@ -0,0 +1,27 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
+NhAAAAAwEAAQAAAQEAxboZzYumqNoVOQ/hKKhIZHxNhf5tmnkLZry8i6Xur4FPLDiRxos/
+xVVDx0ynTPOyQVVaXtNxZnAmbR4HuNBzRvNoklwSXazt5YgWeiKCHtPpKFt3PJeE2cn6FJ
+p6F6qFChG0NSPbZxJWWxv4noX0U3PLKgHNIehYK2Fu0E6plhSZazzJEVWapwo9d7aGnAsz
+bBCd5TNZ5ogrXn+3bSFcdCbAfWOwYg54a+PzTQlzgt6JmhlEjpFfPhhpBW92pQXxmQ2c17
+iPCbA8G++FiaEwA5teex8k1+HzmHf7YjyhPr+I67EzEiIueJg2+0PYbM1p06S8kVTNDXsf
+0eJx4Dr8qQAAA9iFPcpVhT3KVQAAAAdzc2gtcnNhAAABAQDFuhnNi6ao2hU5D+EoqEhkfE
+2F/m2aeQtmvLyLpe6vgU8sOJHGiz/FVUPHTKdM87JBVVpe03FmcCZtHge40HNG82iSXBJd
+rO3liBZ6IoIe0+koW3c8l4TZyfoUmnoXqoUKEbQ1I9tnElZbG/iehfRTc8sqAc0h6FgrYW
+7QTqmWFJlrPMkRVZqnCj13toacCzNsEJ3lM1nmiCtef7dtIVx0JsB9Y7BiDnhr4/NNCXOC
+3omaGUSOkV8+GGkFb3alBfGZDZzXuI8JsDwb74WJoTADm157HyTX4fOYd/tiPKE+v4jrsT
+MSIi54mDb7Q9hszWnTpLyRVM0Nex/R4nHgOvypAAAAAwEAAQAAAQBtk0+/YDgQ9SKzx8AQ
+xwmvXk+cBT76T0BpRAj9HwziiDe3GvZ2YC8MDc+NAEbq11ae7E0zpdv/WAGDkRPYcPShij
+0Wdx3aef4wqLVEJCGWMfvRWLcAhjuiclM73cvxl5c42EzU8jUhrsDapuql9zhKky4w7mSe
++OL7z3gYyq8isvcQMe+1eXJqiv27AJJfAir+rLJZO/gDW36hOowhnZxYRlVYPgZ8GwetxD
+VdCrgwUgR/2HYmbXYdVxI0PwswGc6rEqs5XXOYRzwvPTvRKdD3J5MxmsvJljT7FMr4kCLT
+X1+aWysk1cgAUIdzzwQL8DLE/N9PFFYdZyNBkZMgedl9AAAAgCtP3F8XYFR18gQLPGLDyQ
+FFg8+JHN9b/yIg2pymC6SI8qEp+GnuEK9IKhqh/Uw14KEKcs/9sgbZo0K9uTBTDG5F6Qmp
+hADVbWXJ/97Xeya6kH2Sa56UKLCQ/uQWBKwLQ0auU/qwxATIZowh31XUXjzVBg6wgUjT7Q
++3Fk1zGYxnAAAAgQD5USIRUNwkI+htv+f1g8QdmrFAGymcGEkXAixKvBTon9cWQb2iyiK+
+2IO8EwFwRdL5kw2foILCnlp/4FevfxHU7wTcoFEp3PItUlcxYqO8vY2VCZ913oNLKBIt9p
+uFfG2BZM5szMRNMh0svelu61FePsfN5Z8J0ltPrS8UKB95ywAAAIEAywbyNbjz1AxEjWIX
+2Vbk4/MjQyjui8Wi7H0F+LDWyMfPJHzhnbr79Z/lIZmDAo++3EYU9J9s0C+wJ6vXGK+gvC
+7e5qGfT/0J0DwBfLbpeTdDELCa/LmfLWVPzZ9Q+9Fq0AjmW9YXFZ/+qT9xfY1v9XfztFRS
+xR1iXJ42q6ff5NsAAAAeYnJlZXpld2lzaEBCcmVlemV3aXNoTUJQLmxvY2FsAQIDBAU=
+-----END OPENSSH PRIVATE KEY-----
diff --git a/etc/manualTestEnv/_shared/vagrant_key.pub b/etc/manualTestEnv/_shared/vagrant_key.pub
new file mode 100644
index 0000000000..e9962c03b1
--- /dev/null
+++ b/etc/manualTestEnv/_shared/vagrant_key.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDFuhnNi6ao2hU5D+EoqEhkfE2F/m2aeQtmvLyLpe6vgU8sOJHGiz/FVUPHTKdM87JBVVpe03FmcCZtHge40HNG82iSXBJdrO3liBZ6IoIe0+koW3c8l4TZyfoUmnoXqoUKEbQ1I9tnElZbG/iehfRTc8sqAc0h6FgrYW7QTqmWFJlrPMkRVZqnCj13toacCzNsEJ3lM1nmiCtef7dtIVx0JsB9Y7BiDnhr4/NNCXOC3omaGUSOkV8+GGkFb3alBfGZDZzXuI8JsDwb74WJoTADm157HyTX4fOYd/tiPKE+v4jrsTMSIi54mDb7Q9hszWnTpLyRVM0Nex/R4nHgOvyp
diff --git a/etc/manualTestEnv/basic/README.md b/etc/manualTestEnv/basic/README.md
deleted file mode 100644
index 0e8040f179..0000000000
--- a/etc/manualTestEnv/basic/README.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# basic
-
-An environment with TiDB, PD, TiKV, TiFlash.
-
-## Usage
-
-1. Start the box and cluster:
-
- ```bash
- vagrant up
- vagrant ssh
- tiup playground nightly --monitor --host 10.0.1.2
- ```
-
-2. Outside the box, start TiDB Dashboard server:
-
- ```bash
- bin/tidb-dashboard --pd http://10.0.1.2:2379
- ```
diff --git a/etc/manualTestEnv/basicMultiHost/Vagrantfile b/etc/manualTestEnv/basicMultiHost/Vagrantfile
deleted file mode 100644
index 87bb599f69..0000000000
--- a/etc/manualTestEnv/basicMultiHost/Vagrantfile
+++ /dev/null
@@ -1,23 +0,0 @@
-Vagrant.configure("2") do |config|
- ssh_pub_key = File.readlines("#{File.dirname(__FILE__)}/shared_key.pub").first.strip
-
- config.vm.box = "hashicorp/bionic64"
- config.vm.provision "shell", privileged: false, inline: <<-SHELL
- sudo apt install -y zsh
- sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
- sudo chsh -s /usr/bin/zsh vagrant
-
- echo #{ssh_pub_key} >> /home/vagrant/.ssh/authorized_keys
- SHELL
-
- config.vm.provider "virtualbox" do |v|
- v.memory = 1024
- v.cpus = 1
- end
-
- (1..4).each do |i|
- config.vm.define "node #{i}" do |node|
- node.vm.network "private_network", ip: "10.0.1.#{i+10}"
- end
- end
-end
diff --git a/etc/manualTestEnv/basicMultiHost/README.md b/etc/manualTestEnv/multiHost/README.md
similarity index 54%
rename from etc/manualTestEnv/basicMultiHost/README.md
rename to etc/manualTestEnv/multiHost/README.md
index 0af0747a52..d7ba3c2985 100644
--- a/etc/manualTestEnv/basicMultiHost/README.md
+++ b/etc/manualTestEnv/multiHost/README.md
@@ -1,15 +1,9 @@
-# basicMultiHost
+# multiHost
-An environment with TiDB, PD, TiKV, TiFlash, each in different host.
+TiDB, PD, TiKV, TiFlash each in different hosts.
## Usage
-1. Generate shared SSH key (only need to do it once):
-
- ```bash
- ssh-keygen -t rsa -b 2048 -f ./shared_key -q -N ""
- ```
-
1. Start the box:
```bash
@@ -19,7 +13,7 @@ An environment with TiDB, PD, TiKV, TiFlash, each in different host.
1. Use [TiUP](https://tiup.io/) to deploy the cluster to the box (only need to do it once):
```bash
- tiup cluster deploy multiHost nightly topology.yaml -i shared_key -y --user vagrant
+ tiup cluster deploy multiHost nightly topology.yaml -i ../_shared/vagrant_key -y --user vagrant
```
1. Start the cluster in the box:
@@ -33,3 +27,10 @@ An environment with TiDB, PD, TiKV, TiFlash, each in different host.
```bash
bin/tidb-dashboard --pd http://10.0.1.11:2379
```
+
+## Cleanup
+
+```bash
+tiup cluster destroy multiHost -y
+vagrant destroy --force
+```
diff --git a/etc/manualTestEnv/multiHost/Vagrantfile b/etc/manualTestEnv/multiHost/Vagrantfile
new file mode 100644
index 0000000000..9f4890fdd1
--- /dev/null
+++ b/etc/manualTestEnv/multiHost/Vagrantfile
@@ -0,0 +1,14 @@
+load "#{File.dirname(__FILE__)}/../_shared/Vagrantfile.partial.pubKey.ruby"
+
+Vagrant.configure("2") do |config|
+ config.vm.provider "virtualbox" do |v|
+ v.memory = 1024
+ v.cpus = 1
+ end
+
+ (1..4).each do |i|
+ config.vm.define "node#{i}" do |node|
+ node.vm.network "private_network", ip: "10.0.1.#{i+10}"
+ end
+ end
+end
diff --git a/etc/manualTestEnv/basicMultiHost/topology.yaml b/etc/manualTestEnv/multiHost/topology.yaml
similarity index 56%
rename from etc/manualTestEnv/basicMultiHost/topology.yaml
rename to etc/manualTestEnv/multiHost/topology.yaml
index f2039e4ca3..0129db2ca5 100644
--- a/etc/manualTestEnv/basicMultiHost/topology.yaml
+++ b/etc/manualTestEnv/multiHost/topology.yaml
@@ -4,6 +4,15 @@ global:
data_dir: tidb-data
server_configs:
+ tikv:
+ server.grpc-concurrency: 1
+ raftstore.apply-pool-size: 1
+ raftstore.store-pool-size: 1
+ readpool.unified.max-thread-count: 1
+ readpool.storage.use-unified-pool: false
+ readpool.coprocessor.use-unified-pool: true
+ storage.block-cache.capacity: 256MB
+ raftstore.capacity: 10GB
pd:
replication.enable-placement-rules: true
diff --git a/etc/manualTestEnv/multiReplica/README.md b/etc/manualTestEnv/multiReplica/README.md
index 2c139afff3..6e1717809d 100644
--- a/etc/manualTestEnv/multiReplica/README.md
+++ b/etc/manualTestEnv/multiReplica/README.md
@@ -1,15 +1,9 @@
# multiReplica
-An environment with multiple TiKV nodes in different labels.
+Multiple TiKV nodes in different labels.
## Usage
-1. Generate shared SSH key (only need to do it once):
-
- ```bash
- ssh-keygen -t rsa -b 2048 -f ./shared_key -q -N ""
- ```
-
1. Start the box:
```bash
@@ -19,7 +13,7 @@ An environment with multiple TiKV nodes in different labels.
1. Use [TiUP](https://tiup.io/) to deploy the cluster to the box (only need to do it once):
```bash
- tiup cluster deploy multiReplica nightly topology.yaml -i shared_key -y --user vagrant
+ tiup cluster deploy multiReplica nightly topology.yaml -i ../_shared/vagrant_key -y --user vagrant
```
1. Start the cluster in the box:
@@ -33,3 +27,10 @@ An environment with multiple TiKV nodes in different labels.
```bash
bin/tidb-dashboard --pd http://10.0.1.20:2379
```
+
+## Cleanup
+
+```bash
+tiup cluster destroy multiReplica -y
+vagrant destroy --force
+```
diff --git a/etc/manualTestEnv/multiReplica/Vagrantfile b/etc/manualTestEnv/multiReplica/Vagrantfile
index 5a0e123cff..82098283c1 100644
--- a/etc/manualTestEnv/multiReplica/Vagrantfile
+++ b/etc/manualTestEnv/multiReplica/Vagrantfile
@@ -1,17 +1,8 @@
-Vagrant.configure("2") do |config|
- ssh_pub_key = File.readlines("#{File.dirname(__FILE__)}/shared_key.pub").first.strip
-
- config.vm.box = "hashicorp/bionic64"
- config.vm.provision "shell", privileged: false, inline: <<-SHELL
- sudo apt install -y zsh
- sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
- sudo chsh -s /usr/bin/zsh vagrant
-
- echo #{ssh_pub_key} >> /home/vagrant/.ssh/authorized_keys
- SHELL
+load "#{File.dirname(__FILE__)}/../_shared/Vagrantfile.partial.pubKey.ruby"
+Vagrant.configure("2") do |config|
config.vm.provider "virtualbox" do |v|
- v.memory = 4096
+ v.memory = 4 * 1024
v.cpus = 2
end
diff --git a/etc/manualTestEnv/singleHost/README.md b/etc/manualTestEnv/singleHost/README.md
new file mode 100644
index 0000000000..e7a52a5c14
--- /dev/null
+++ b/etc/manualTestEnv/singleHost/README.md
@@ -0,0 +1,36 @@
+# singleHost
+
+TiDB, PD, TiKV, TiFlash in the same host.
+
+## Usage
+
+1. Start the box:
+
+ ```bash
+ vagrant up
+ ```
+
+1. Use [TiUP](https://tiup.io/) to deploy the cluster to the box (only need to do it once):
+
+ ```bash
+ tiup cluster deploy singleHost nightly topology.yaml -i ../_shared/vagrant_key -y --user vagrant
+ ```
+
+1. Start the cluster in the box:
+
+ ```bash
+ tiup cluster start singleHost
+ ```
+
+1. Start TiDB Dashboard server:
+
+ ```bash
+ bin/tidb-dashboard --pd http://10.0.1.2:2379
+ ```
+
+## Cleanup
+
+```bash
+tiup cluster destroy singleHost -y
+vagrant destroy --force
+```
diff --git a/etc/manualTestEnv/singleHost/Vagrantfile b/etc/manualTestEnv/singleHost/Vagrantfile
new file mode 100644
index 0000000000..77d49ffdea
--- /dev/null
+++ b/etc/manualTestEnv/singleHost/Vagrantfile
@@ -0,0 +1,10 @@
+load "#{File.dirname(__FILE__)}/../_shared/Vagrantfile.partial.pubKey.ruby"
+
+Vagrant.configure("2") do |config|
+ config.vm.provider "virtualbox" do |v|
+ v.memory = 3 * 1024
+ v.cpus = 2
+ end
+
+ config.vm.network "private_network", ip: "10.0.1.2"
+end
diff --git a/etc/manualTestEnv/singleHost/topology.yaml b/etc/manualTestEnv/singleHost/topology.yaml
new file mode 100644
index 0000000000..bf79c98bff
--- /dev/null
+++ b/etc/manualTestEnv/singleHost/topology.yaml
@@ -0,0 +1,37 @@
+global:
+ user: tidb
+ deploy_dir: tidb-deploy
+ data_dir: tidb-data
+
+server_configs:
+ tikv:
+ server.grpc-concurrency: 1
+ raftstore.apply-pool-size: 1
+ raftstore.store-pool-size: 1
+ readpool.unified.max-thread-count: 1
+ readpool.storage.use-unified-pool: false
+ readpool.coprocessor.use-unified-pool: true
+ storage.block-cache.capacity: 256MB
+ pd:
+ replication.enable-placement-rules: true
+
+pd_servers:
+ - host: 10.0.1.2
+
+tikv_servers:
+ - host: 10.0.1.2
+
+tidb_servers:
+ - host: 10.0.1.2
+
+tiflash_servers:
+ - host: 10.0.1.2
+
+grafana_servers:
+ - host: 10.0.1.2
+
+monitoring_servers:
+ - host: 10.0.1.2
+
+alertmanager_servers:
+ - host: 10.0.1.2
diff --git a/etc/manualTestEnv/singleHostMultiDisk/.gitignore b/etc/manualTestEnv/singleHostMultiDisk/.gitignore
new file mode 100644
index 0000000000..8fce603003
--- /dev/null
+++ b/etc/manualTestEnv/singleHostMultiDisk/.gitignore
@@ -0,0 +1 @@
+data/
diff --git a/etc/manualTestEnv/singleHostMultiDisk/README.md b/etc/manualTestEnv/singleHostMultiDisk/README.md
new file mode 100644
index 0000000000..f32e4a59f6
--- /dev/null
+++ b/etc/manualTestEnv/singleHostMultiDisk/README.md
@@ -0,0 +1,36 @@
+# singleHostMultiDisk
+
+All instances in a single host, but on different disks.
+
+## Usage
+
+1. Start the box:
+
+ ```bash
+ vagrant up
+ ```
+
+1. Use [TiUP](https://tiup.io/) to deploy the cluster to the box (only need to do it once):
+
+ ```bash
+ tiup cluster deploy singleHostMultiDisk nightly topology.yaml -i ../_shared/vagrant_key -y --user vagrant
+ ```
+
+1. Start the cluster in the box:
+
+ ```bash
+ tiup cluster start singleHostMultiDisk
+ ```
+
+1. Start TiDB Dashboard server:
+
+ ```bash
+ bin/tidb-dashboard --pd http://10.0.1.3:2379
+ ```
+
+## Cleanup
+
+```bash
+tiup cluster destroy singleHostMultiDisk -y
+vagrant destroy --force
+```
diff --git a/etc/manualTestEnv/singleHostMultiDisk/Vagrantfile b/etc/manualTestEnv/singleHostMultiDisk/Vagrantfile
new file mode 100644
index 0000000000..971db113cc
--- /dev/null
+++ b/etc/manualTestEnv/singleHostMultiDisk/Vagrantfile
@@ -0,0 +1,10 @@
+load "#{File.dirname(__FILE__)}/../_shared/Vagrantfile.partial.pubKey.ruby"
+
+Vagrant.configure("2") do |config|
+ config.vm.provider "virtualbox" do |v|
+ v.memory = 3 * 1024
+ v.cpus = 2
+ end
+
+ config.vm.network "private_network", ip: "10.0.1.3"
+end
diff --git a/etc/manualTestEnv/singleHostMultiDisk/topology.yaml b/etc/manualTestEnv/singleHostMultiDisk/topology.yaml
new file mode 100644
index 0000000000..516de7cb5c
--- /dev/null
+++ b/etc/manualTestEnv/singleHostMultiDisk/topology.yaml
@@ -0,0 +1,39 @@
+global:
+ user: vagrant
+ deploy_dir: tidb-deploy
+ data_dir: tidb-data
+
+server_configs:
+ tikv:
+ server.grpc-concurrency: 1
+ raftstore.apply-pool-size: 1
+ raftstore.store-pool-size: 1
+ readpool.unified.max-thread-count: 1
+ readpool.storage.use-unified-pool: false
+ readpool.coprocessor.use-unified-pool: true
+ storage.block-cache.capacity: 256MB
+ pd:
+ replication.enable-placement-rules: true
+
+pd_servers:
+ - host: 10.0.1.3
+
+tikv_servers:
+ - host: 10.0.1.3
+
+tidb_servers:
+ - host: 10.0.1.3
+ deploy_dir: /vagrant/data/tidb
+ log_dir: /vagrant/data/tidb/log
+
+tiflash_servers:
+ - host: 10.0.1.3
+
+grafana_servers:
+ - host: 10.0.1.3
+
+monitoring_servers:
+ - host: 10.0.1.3
+
+alertmanager_servers:
+ - host: 10.0.1.3
diff --git a/ui/lib/apps/ClusterInfo/components/HostTable.tsx b/ui/lib/apps/ClusterInfo/components/HostTable.tsx
index 0e73da8cc9..4f7d9cf595 100644
--- a/ui/lib/apps/ClusterInfo/components/HostTable.tsx
+++ b/ui/lib/apps/ClusterInfo/components/HostTable.tsx
@@ -138,7 +138,7 @@ export default function HostTable() {
pd: 0,
tiflash: 0,
}
- return filterUniquePartitions(partitions).map((partition) => {
+ return filterUniquePartitions(partitions).map((partition, i) => {
const currentMountPoint = partition.partition.path
partitions.forEach((item) => {
if (item.partition.path !== currentMountPoint) {
@@ -159,9 +159,14 @@ export default function HostTable() {
if (serverTotal.tiflash > 0) {
serverInfos.push(`${serverTotal.tiflash} TiFlash`)
}
- return `${serverInfos.join(
+ const content = `${serverInfos.join(
','
)}: ${partition.partition.fstype.toUpperCase()} ${currentMountPoint}`
+ return (
+
+ {content}
+
+ )
})
},
},
From 2f138d87a263788e6d98fbc89227e53e42961a75 Mon Sep 17 00:00:00 2001
From: Breezewish
Date: Sun, 17 May 2020 19:15:42 +0800
Subject: [PATCH 07/14] Add placeholder
Signed-off-by: Breezewish
---
.../components/BaseSelect/index.module.less | 4 +++
ui/lib/components/BaseSelect/index.tsx | 20 ++++++++++--
.../{SelectDisplay.tsx => ValueDisplay.tsx} | 20 +++++-------
ui/lib/components/InstanceSelect/index.tsx | 32 ++++++++++++++++---
4 files changed, 57 insertions(+), 19 deletions(-)
rename ui/lib/components/InstanceSelect/{SelectDisplay.tsx => ValueDisplay.tsx} (82%)
diff --git a/ui/lib/components/BaseSelect/index.module.less b/ui/lib/components/BaseSelect/index.module.less
index 8952c4ab24..5433f4e63c 100644
--- a/ui/lib/components/BaseSelect/index.module.less
+++ b/ui/lib/components/BaseSelect/index.module.less
@@ -64,6 +64,10 @@
transition: all 0.3s;
pointer-events: none;
width: 100%;
+
+ &.isPlaceholder {
+ opacity: 0.4;
+ }
}
.baseSelectArrow {
diff --git a/ui/lib/components/BaseSelect/index.tsx b/ui/lib/components/BaseSelect/index.tsx
index a3ce881009..be0b9cde1e 100644
--- a/ui/lib/components/BaseSelect/index.tsx
+++ b/ui/lib/components/BaseSelect/index.tsx
@@ -14,13 +14,17 @@ export interface IBaseSelectDropdownRenderProps {
}
export interface IBaseSelectProps
- extends Omit, 'onChange'> {
+ extends Omit<
+ React.HTMLAttributes,
+ 'onChange' | 'placeholder'
+ > {
dropdownRender: (
renderProps: IBaseSelectDropdownRenderProps
) => React.ReactElement
value?: T
valueRender: (value?: T) => React.ReactNode
onChange?: (value: T) => void
+ placeholder?: React.ReactNode
disabled?: boolean
tabIndex?: number
autoFocus?: boolean
@@ -31,6 +35,7 @@ function BaseSelect({
value,
valueRender,
onChange,
+ placeholder,
disabled,
tabIndex,
autoFocus,
@@ -141,6 +146,9 @@ function BaseSelect({
})
}, [disabled])
+ const renderedValue = valueRender(value)
+ const displayAsPlaceholder = renderedValue == null
+
return (
({
autoFocus={autoFocus}
readOnly
/>
-
-
{valueRender(value)}
+
+
+ {displayAsPlaceholder ? placeholder : renderedValue}
+
diff --git a/ui/lib/components/InstanceSelect/SelectDisplay.tsx b/ui/lib/components/InstanceSelect/ValueDisplay.tsx
similarity index 82%
rename from ui/lib/components/InstanceSelect/SelectDisplay.tsx
rename to ui/lib/components/InstanceSelect/ValueDisplay.tsx
index 0337e966e2..6bef518195 100644
--- a/ui/lib/components/InstanceSelect/SelectDisplay.tsx
+++ b/ui/lib/components/InstanceSelect/ValueDisplay.tsx
@@ -1,6 +1,5 @@
import React, { useMemo } from 'react'
import { IInstanceTableItem, InstanceKind } from '@lib/utils/instanceTable'
-import { Typography } from 'antd'
interface InstanceStat {
all: number
@@ -14,13 +13,15 @@ function newInstanceStat(): InstanceStat {
}
}
-export default function SelectDisplay({
- items,
- selectedKeys,
-}: {
+export interface IValueDisplayProps {
items: IInstanceTableItem[]
selectedKeys: string[]
-}) {
+}
+
+export default function ValueDisplay({
+ items,
+ selectedKeys,
+}: IValueDisplayProps) {
const text = useMemo(() => {
const selectedKeysMap = {}
selectedKeys.forEach((key) => (selectedKeysMap[key] = true))
@@ -59,10 +60,5 @@ export default function SelectDisplay({
return p.join(', ')
}, [items, selectedKeys])
- if (items.length === 0 || selectedKeys.length === 0) {
- // Not yet loaded
- return
Select Instance
- } else {
- return
{text}
- }
+ return <>{text}>
}
diff --git a/ui/lib/components/InstanceSelect/index.tsx b/ui/lib/components/InstanceSelect/index.tsx
index 9106b6c8ff..a51942ec0a 100644
--- a/ui/lib/components/InstanceSelect/index.tsx
+++ b/ui/lib/components/InstanceSelect/index.tsx
@@ -1,5 +1,5 @@
import React, { useCallback, useRef, useMemo, useEffect, useState } from 'react'
-import { Tooltip, Typography } from 'antd'
+import { Tooltip } from 'antd'
import { Selection } from 'office-ui-fabric-react/lib/Selection'
import { BaseSelect, InstanceStatusBadge, TextWrap } from '../'
import { useClientRequest } from '@lib/utils/useClientRequest'
@@ -12,7 +12,8 @@ import {
} from '@lib/utils/instanceTable'
import DropOverlay from './DropOverlay'
-import SelectDisplay from './SelectDisplay'
+import ValueDisplay from './ValueDisplay'
+import { useShallowCompareEffect } from 'react-use'
export interface IInstanceSelectProps {
enableTiFlash?: boolean
@@ -106,15 +107,34 @@ function InstanceSelect(
const [selectedKeys, setSelectedKeys] = useState(props.value ?? [])
+ const onChange = usePersistFn((v: string[]) => {
+ console.log('onChange', v)
+ props.onChange?.(v)
+ })
+
const selection = useRef(
new Selection({
onSelectionChanged: () => {
+ console.log('onSelectionChanged')
const s = selection.current.getSelection() as IInstanceTableItem[]
- setSelectedKeys(s.map((v) => v.key))
+ const keys = s.map((v) => v.key)
+ setSelectedKeys(keys)
+ onChange([...keys])
},
})
)
+ useShallowCompareEffect(() => {
+ console.log('props.value changed')
+ // Update selection when value is changed
+ selection.current.setAllSelected(false)
+ if (props.value) {
+ for (const key of props.value) {
+ selection.current.setKeySelected(key, true, false)
+ }
+ }
+ }, [props.value])
+
const dataHasLoaded = useRef(false)
useEffect(() => {
@@ -139,7 +159,10 @@ function InstanceSelect(
}))
const renderValue = useCallback(() => {
- return
+ if (tableItems.length === 0 || selectedKeys.length === 0) {
+ return null
+ }
+ return
}, [tableItems, selectedKeys])
const renderDropdown = useCallback(() => {
@@ -158,6 +181,7 @@ function InstanceSelect(
dropdownRender={renderDropdown}
valueRender={renderValue}
disabled={loadingTiDB || loadingStores || loadingPD}
+ placeholder="Select Instances"
/>
)
}
From 88be557b0b703dc2f60cf1aedd57073d67a02250 Mon Sep 17 00:00:00 2001
From: Breezewish
Date: Mon, 25 May 2020 02:22:20 +0800
Subject: [PATCH 08/14] Use InstanceSelect
---
ui/dashboardApp/index.js | 4 +-
ui/lib/apps/DebugPlayground/index.tsx | 43 ++-
.../apps/InstanceProfiling/pages/Detail.tsx | 5 +-
ui/lib/apps/InstanceProfiling/pages/List.tsx | 354 ++++++++----------
.../InstanceProfiling/translations/en.yaml | 3 +-
.../InstanceProfiling/translations/zh-CN.yaml | 3 +-
.../SearchLogs/components/SearchHeader.tsx | 278 +++++++-------
.../SearchLogs/components/SearchHistory.tsx | 101 +++--
.../SearchLogs/components/SearchResult.tsx | 70 ++--
.../SearchLogs/components/Styles.module.css | 4 -
ui/lib/apps/SearchLogs/components/utils.ts | 138 ++-----
ui/lib/apps/SearchLogs/translations/en.yaml | 4 +-
.../apps/SearchLogs/translations/zh-CN.yaml | 4 +-
ui/lib/apps/SlowQuery/utils/useSlowQuery.ts | 6 +-
.../pages/List/TimeRangeSelector.tsx | 2 +-
ui/lib/apps/Statement/utils/useStatement.ts | 4 +-
.../components/BaseSelect/index.module.less | 9 +
ui/lib/components/BaseSelect/index.tsx | 68 ++--
ui/lib/components/CardTable/index.module.less | 22 --
ui/lib/components/CardTable/index.tsx | 50 ---
ui/lib/components/CardTableV2/GroupHeader.tsx | 1 -
.../components/InstanceSelect/DropOverlay.tsx | 4 +-
.../InstanceSelect/ValueDisplay.tsx | 27 +-
ui/lib/components/InstanceSelect/index.tsx | 191 +++++++---
ui/lib/components/TimeRangeSelector/index.tsx | 117 +++---
ui/lib/components/index.ts | 2 -
26 files changed, 720 insertions(+), 794 deletions(-)
delete mode 100644 ui/lib/components/CardTable/index.module.less
delete mode 100644 ui/lib/components/CardTable/index.tsx
diff --git a/ui/dashboardApp/index.js b/ui/dashboardApp/index.js
index 05f8d8e515..c3a26d08e8 100644
--- a/ui/dashboardApp/index.js
+++ b/ui/dashboardApp/index.js
@@ -19,7 +19,7 @@ import AppKeyViz from '@lib/apps/KeyViz/index.meta'
import AppStatement from '@lib/apps/Statement/index.meta'
import AppDiagnose from '@lib/apps/Diagnose/index.meta'
import AppSearchLogs from '@lib/apps/SearchLogs/index.meta'
-// import AppInstanceProfiling from '@lib/apps/InstanceProfiling/index.meta'
+import AppInstanceProfiling from '@lib/apps/InstanceProfiling/index.meta'
import AppClusterInfo from '@lib/apps/ClusterInfo/index.meta'
import AppSlowQuery from '@lib/apps/SlowQuery/index.meta'
@@ -60,7 +60,7 @@ async function main() {
.register(AppClusterInfo)
.register(AppDiagnose)
.register(AppSearchLogs)
- // .register(AppInstanceProfiling)
+ .register(AppInstanceProfiling)
.register(AppSlowQuery)
if (routing.isLocationMatch('/')) {
diff --git a/ui/lib/apps/DebugPlayground/index.tsx b/ui/lib/apps/DebugPlayground/index.tsx
index ab02b3c038..4677c98fc1 100644
--- a/ui/lib/apps/DebugPlayground/index.tsx
+++ b/ui/lib/apps/DebugPlayground/index.tsx
@@ -1,9 +1,38 @@
-import React, { useState } from 'react'
-import { Root, BaseSelect, InstanceSelect } from '@lib/components'
+import React, { useState, useRef } from 'react'
+import {
+ Root,
+ BaseSelect,
+ InstanceSelect,
+ IInstanceSelectRefProps,
+ Pre,
+} from '@lib/components'
import { Select, Button } from 'antd'
-const App = () => {
+const InstanceSelectRegion = () => {
const [instanceSelectValue, setInstanceSelectValue] = useState([])
+ const s = useRef(null)
+
+ return (
+ <>
+ Instance Select
+
+ Instance select value = {JSON.stringify(instanceSelectValue)}
+
+ Instance select value instances ={' '}
+ {JSON.stringify(
+ s.current && s.current.getInstanceByKeys(instanceSelectValue)
+ )}
+
+ >
+ )
+}
+
+const App = () => {
return (
Debug Playground
@@ -35,13 +64,7 @@ const App = () => {
- Instance Select
-
- Instance select value = {JSON.stringify(instanceSelectValue)}
+
Misc
record.target.kind,
+ onRender: (record) => {
+ return InstanceKindName[record.target.kind]
+ },
},
{
name: t('instance_profiling.detail.table.columns.status'),
diff --git a/ui/lib/apps/InstanceProfiling/pages/List.tsx b/ui/lib/apps/InstanceProfiling/pages/List.tsx
index d1f485db46..758b749eb0 100644
--- a/ui/lib/apps/InstanceProfiling/pages/List.tsx
+++ b/ui/lib/apps/InstanceProfiling/pages/List.tsx
@@ -1,139 +1,92 @@
-import { Badge, Button, Form, message, Select, TreeSelect } from 'antd'
+import { Badge, Button, Form, message, Select, Modal } from 'antd'
import { ColumnActionsMode } from 'office-ui-fabric-react/lib/DetailsList'
import { ScrollablePane } from 'office-ui-fabric-react/lib/ScrollablePane'
-import React, { useMemo, useState } from 'react'
+import React, { useMemo, useState, useCallback, useRef } from 'react'
import { useTranslation } from 'react-i18next'
import { useNavigate } from 'react-router-dom'
import { usePersistFn } from '@umijs/hooks'
-
-import client from '@lib/client'
-import { Card, CardTableV2 } from '@lib/components'
+import client, {
+ ProfilingStartRequest,
+ ModelRequestTargetNode,
+} from '@lib/client'
+import {
+ Card,
+ CardTableV2,
+ InstanceSelect,
+ IInstanceSelectRefProps,
+} from '@lib/components'
import DateTime from '@lib/components/DateTime'
import openLink from '@lib/utils/openLink'
import { useClientRequest } from '@lib/utils/useClientRequest'
-// FIXME: The following logic should be extracted into a common component.
-function getTreeData(topologyMap) {
- const treeDataByKind = {
- tidb: [],
- tikv: [],
- pd: [],
- }
- Object.values(topologyMap).forEach((target: any) => {
- if (!(target.kind in treeDataByKind)) {
- return
- }
- treeDataByKind[target.kind].push({
- title: target.display_name,
- value: target.display_name,
- key: target.display_name,
- })
- })
- const kindTitleMap = {
- tidb: 'TiDB',
- tikv: 'TiKV',
- pd: 'PD',
- }
- return Object.keys(treeDataByKind)
- .filter((kind) => treeDataByKind[kind].length > 0)
- .map((kind) => ({
- title: kindTitleMap[kind],
- value: kind,
- key: kind,
- children: treeDataByKind[kind],
- }))
-}
-
-function filterTreeNode(inputValue, treeNode) {
- const name = treeNode.key
- return name.includes(inputValue)
-}
-
-function useTargetsMap() {
- return {}
- // const { data } = useClientRequest((cancelToken) =>
- // client.getInstance().topologyAllGet({ cancelToken })
- // )
- // return useMemo(() => {
- // const map = {}
- // if (!data) {
- // return map
- // }
- // // FIXME, declare type
- // data.tidb?.nodes?.forEach((node) => {
- // const display = `${node.ip}:${node.port}`
- // const target = {
- // kind: 'tidb',
- // display_name: display,
- // ip: node.ip,
- // port: node.status_port,
- // }
- // map[display] = target
- // })
- // data.tikv?.nodes?.forEach((node) => {
- // const display = `${node.ip}:${node.port}`
- // const target = {
- // kind: 'tikv',
- // display_name: display,
- // ip: node.ip,
- // port: node.status_port,
- // }
- // map[display] = target
- // })
- // data.pd?.nodes?.forEach((node) => {
- // const display = `${node.ip}:${node.port}`
- // const target = {
- // kind: 'pd',
- // display_name: display,
- // ip: node.ip,
- // port: node.port,
- // }
- // map[display] = target
- // })
- // return map
- // }, [data])
-}
-
const profilingDurationsSec = [10, 30, 60, 120]
const defaultProfilingDuration = 30
export default function Page() {
- const targetsMap = useTargetsMap()
-
- // FIXME: Use Antd form
- const [selectedTargets, setSelectedTargets] = useState([])
- const [duration, setDuration] = useState(defaultProfilingDuration)
-
- const [submitting, setSubmitting] = useState(false)
const {
data: historyTable,
isLoading: listLoading,
} = useClientRequest((cancelToken) =>
client.getInstance().getProfilingGroups({ cancelToken })
)
-
const { t } = useTranslation()
const navigate = useNavigate()
+ const instanceSelect = useRef
(null)
+ const [submitting, setSubmitting] = useState(false)
- async function handleStart() {
- if (selectedTargets.length === 0) {
- // TODO: Show notification
- return
- }
- setSubmitting(true)
- const req = {
- targets: selectedTargets.map((k) => targetsMap[k]),
- duration_secs: duration,
- }
- try {
- const res = await client.getInstance().startProfiling(req)
- navigate(`/instance_profiling/${res.data.id}`)
- } catch (e) {
- // FIXME
- message.error(e.message)
- }
- setSubmitting(false)
- }
+ const handleFinish = useCallback(
+ async (fieldsValue) => {
+ if (!fieldsValue.instances || fieldsValue.instances.length === 0) {
+ Modal.error({
+ content: 'Some required fields are not filled',
+ })
+ return
+ }
+ if (!instanceSelect.current) {
+ Modal.error({
+ content: 'Internal error: Instance select is not ready',
+ })
+ return
+ }
+ setSubmitting(true)
+ const targets: ModelRequestTargetNode[] = instanceSelect
+ .current!.getInstanceByKeys(fieldsValue.instances)
+ .map((instance) => {
+ let port
+ switch (instance.instanceKind) {
+ case 'pd':
+ port = instance.port
+ break
+ case 'tidb':
+ case 'tikv':
+ port = instance.status_port
+ break
+ }
+ return {
+ kind: instance.instanceKind,
+ display_name: instance.key,
+ ip: instance.ip,
+ port,
+ }
+ })
+ .filter((i) => i.port != null)
+ const req: ProfilingStartRequest = {
+ targets,
+ duration_secs: fieldsValue.duration,
+ }
+ try {
+ const res = await client.getInstance().startProfiling(req)
+ navigate(`/instance_profiling/${res.data.id}`)
+ } catch (e) {
+ // FIXME
+ Modal.error({
+ content: e.message,
+ })
+ }
+ setSubmitting(false)
+ },
+ [navigate]
+ )
const handleRowClick = usePersistFn(
(rec, _idx, ev: React.MouseEvent) => {
@@ -141,106 +94,103 @@ export default function Page() {
}
)
- const historyTableColumns = [
- {
- name: t('instance_profiling.list.table.columns.targets'),
- key: 'targets',
- minWidth: 150,
- maxWidth: 250,
- isResizable: true,
- columnActionsMode: ColumnActionsMode.disabled,
- onRender: (rec) => {
- // TODO: Extract to utility function
- const r: string[] = []
- if (rec.target_stats.num_tidb_nodes) {
- r.push(`${rec.target_stats.num_tidb_nodes} TiDB`)
- }
- if (rec.target_stats.num_tikv_nodes) {
- r.push(`${rec.target_stats.num_tikv_nodes} TiKV`)
- }
- if (rec.target_stats.num_pd_nodes) {
- r.push(`${rec.target_stats.num_pd_nodes} PD`)
- }
- return {r.join(', ')}
+ const historyTableColumns = useMemo(
+ () => [
+ {
+ name: t('instance_profiling.list.table.columns.targets'),
+ key: 'targets',
+ minWidth: 150,
+ maxWidth: 250,
+ isResizable: true,
+ columnActionsMode: ColumnActionsMode.disabled,
+ onRender: (rec) => {
+ // TODO: Extract to utility function
+ const r: string[] = []
+ if (rec.target_stats.num_tidb_nodes) {
+ r.push(`${rec.target_stats.num_tidb_nodes} TiDB`)
+ }
+ if (rec.target_stats.num_tikv_nodes) {
+ r.push(`${rec.target_stats.num_tikv_nodes} TiKV`)
+ }
+ if (rec.target_stats.num_pd_nodes) {
+ r.push(`${rec.target_stats.num_pd_nodes} PD`)
+ }
+ return {r.join(', ')}
+ },
},
- },
- {
- name: t('instance_profiling.list.table.columns.status'),
- key: 'status',
- minWidth: 100,
- maxWidth: 150,
- isResizable: true,
- columnActionsMode: ColumnActionsMode.disabled,
- onRender: (rec) => {
- if (rec.state === 1) {
- return (
-
- )
- } else if (rec.state === 2) {
- return (
-
- )
- }
+ {
+ name: t('instance_profiling.list.table.columns.status'),
+ key: 'status',
+ minWidth: 100,
+ maxWidth: 150,
+ isResizable: true,
+ columnActionsMode: ColumnActionsMode.disabled,
+ onRender: (rec) => {
+ if (rec.state === 1) {
+ return (
+
+ )
+ } else if (rec.state === 2) {
+ return (
+
+ )
+ }
+ },
},
- },
- {
- name: t('instance_profiling.list.table.columns.start_at'),
- key: 'started_at',
- minWidth: 160,
- maxWidth: 220,
- isResizable: true,
- columnActionsMode: ColumnActionsMode.disabled,
- onRender: (rec) => {
- return
+ {
+ name: t('instance_profiling.list.table.columns.start_at'),
+ key: 'started_at',
+ minWidth: 160,
+ maxWidth: 220,
+ isResizable: true,
+ columnActionsMode: ColumnActionsMode.disabled,
+ onRender: (rec) => {
+ return
+ },
},
- },
- {
- name: t('instance_profiling.list.table.columns.duration'),
- key: 'duration',
- minWidth: 100,
- maxWidth: 150,
- fieldName: 'profile_duration_secs',
- isResizable: true,
- columnActionsMode: ColumnActionsMode.disabled,
- },
- ]
+ {
+ name: t('instance_profiling.list.table.columns.duration'),
+ key: 'duration',
+ minWidth: 100,
+ maxWidth: 150,
+ fieldName: 'profile_duration_secs',
+ isResizable: true,
+ columnActionsMode: ColumnActionsMode.disabled,
+ },
+ ],
+ [t]
+ )
return (
-
-
+
-
-
diff --git a/ui/lib/apps/InstanceProfiling/translations/en.yaml b/ui/lib/apps/InstanceProfiling/translations/en.yaml
index 4e186900d9..5cc654138c 100644
--- a/ui/lib/apps/InstanceProfiling/translations/en.yaml
+++ b/ui/lib/apps/InstanceProfiling/translations/en.yaml
@@ -3,9 +3,8 @@ instance_profiling:
list:
control_form:
title: Start Profiling Instances
- nodes:
+ instances:
label: Select instances
- placeholder: Please select the instance to profile
duration:
label: Duration
submit: Start Profiling
diff --git a/ui/lib/apps/InstanceProfiling/translations/zh-CN.yaml b/ui/lib/apps/InstanceProfiling/translations/zh-CN.yaml
index 2fb7d98695..591c430286 100644
--- a/ui/lib/apps/InstanceProfiling/translations/zh-CN.yaml
+++ b/ui/lib/apps/InstanceProfiling/translations/zh-CN.yaml
@@ -3,9 +3,8 @@ instance_profiling:
list:
control_form:
title: 开始性能分析
- nodes:
+ instances:
label: 选择实例
- placeholder: 请选择需要进行性能分析的目标实例
duration:
label: 分析时长
submit: 开始分析
diff --git a/ui/lib/apps/SearchLogs/components/SearchHeader.tsx b/ui/lib/apps/SearchLogs/components/SearchHeader.tsx
index cb5a69fedf..28a08541a2 100644
--- a/ui/lib/apps/SearchLogs/components/SearchHeader.tsx
+++ b/ui/lib/apps/SearchLogs/components/SearchHeader.tsx
@@ -3,211 +3,185 @@ import {
LogsearchCreateTaskGroupRequest,
ModelRequestTargetNode,
} from '@lib/client'
-import { Button, Form, Input, Select, TreeSelect } from 'antd'
-import { LegacyDataNode } from 'rc-tree-select/lib/interface'
-import React, { ChangeEvent, useState } from 'react'
+import { Button, Form, Input, Select, Modal } from 'antd'
+import React, { useState, useCallback, useRef } from 'react'
import { useTranslation } from 'react-i18next'
import { useNavigate } from 'react-router-dom'
import { useMount } from '@umijs/hooks'
-import styles from './Styles.module.css'
-import {
- namingMap,
- NodeKind,
- NodeKindList,
- // parseClusterInfo,
- parseSearchingParams,
-} from './utils'
import {
TimeRangeSelector,
TimeRange,
- DEF_TIME_RANGE,
calcTimeRange,
+ InstanceSelect,
+ IInstanceSelectRefProps,
} from '@lib/components'
-const { SHOW_CHILD } = TreeSelect
-const { Option } = Select
-
-function buildTreeData(targets: ModelRequestTargetNode[]) {
- const servers = {
- [NodeKind.TiDB]: [],
- [NodeKind.TiKV]: [],
- [NodeKind.PD]: [],
- [NodeKind.TiFlash]: [],
- }
-
- targets.forEach((item) => {
- if (item === undefined || item.kind === undefined) {
- return
- }
- servers[item.kind].push(item)
- })
-
- return NodeKindList.filter((kind) => servers[kind].length > 0).map(
- (kind) => ({
- title: namingMap[kind],
- value: kind,
- key: kind,
- children: servers[kind].map((item: ModelRequestTargetNode) => {
- const addr = item.display_name!
- return {
- title: addr,
- value: addr,
- key: addr,
- }
- }),
- })
- )
-}
+import { ValidLogLevels, LogLevelText } from './utils'
interface Props {
taskGroupID?: number
}
-const LOG_LEVELS = ['debug', 'info', 'warn', 'trace', 'critical', 'error']
+interface IFormProps {
+ timeRange?: TimeRange
+ logLevel?: number
+ instances?: string[]
+ keywords?: string
+}
export default function SearchHeader({ taskGroupID }: Props) {
const { t } = useTranslation()
const navigate = useNavigate()
-
- const [timeRange, setTimeRange] = useState(DEF_TIME_RANGE)
- const [logLevel, setLogLevel] = useState(2)
- const [selectedComponents, setComponents] = useState([])
- const [searchValue, setSearchValue] = useState('')
- const [allTargets, setAllTargets] = useState([])
+ const [form] = Form.useForm()
+ const [isSubmitting, setSubmitting] = useState(false)
+ const instanceSelect = useRef(null)
useMount(() => {
async function fetchData() {
- const res = {} as any
- // const res = await client.getInstance().topologyAllGet()
- // const targets = parseClusterInfo(res.data)
- const targets = [] as any
- setAllTargets(targets)
- setComponents(targets.map((item) => item.display_name!))
if (!taskGroupID) {
return
}
- const res2 = await client
+ const res = await client
.getInstance()
- .logsTaskgroupsIdGet(taskGroupID + '')
- const {
- timeRange,
- logLevel,
- components,
- searchValue,
- } = parseSearchingParams(res2.data)
- setTimeRange(timeRange)
- setLogLevel(logLevel === 0 ? 2 : logLevel)
- setComponents(components.map((item) => item.display_name ?? ''))
- setSearchValue(searchValue)
+ .logsTaskgroupsIdGet(String(taskGroupID))
+ const { task_group, tasks } = res.data
+ const { start_time, end_time, min_level, patterns } =
+ task_group?.search_request ?? {}
+ const fieldsValue: IFormProps = {
+ timeRange: {
+ type: 'absolute',
+ value: [start_time! / 1000, end_time! / 1000],
+ },
+ logLevel: min_level || 2,
+ instances: (tasks ?? [])
+ .filter((t) => t.target && t.target!.display_name)
+ .map((t) => t.target!.display_name!),
+ keywords: (patterns ?? []).join(' '),
+ }
+ form.setFieldsValue(fieldsValue)
}
fetchData()
})
- async function createTaskGroup() {
- // TODO: check select at least one component
- const targets: ModelRequestTargetNode[] = allTargets.filter((item) =>
- selectedComponents.some((addr) => addr === item.display_name ?? '')
- )
+ const handleSearch = useCallback(async (fieldsValue: IFormProps) => {
+ if (
+ !fieldsValue.instances ||
+ fieldsValue.instances.length === 0 ||
+ !fieldsValue.logLevel ||
+ !fieldsValue.timeRange
+ ) {
+ Modal.error({
+ content: 'Some required fields are not filled',
+ })
+ return
+ }
+ if (!instanceSelect.current) {
+ Modal.error({
+ content: 'Internal error: Instance select is not ready',
+ })
+ return
+ }
+ setSubmitting(true)
+
+ const targets: ModelRequestTargetNode[] = instanceSelect
+ .current!.getInstanceByKeys(fieldsValue.instances)
+ .map((instance) => {
+ let port
+ switch (instance.instanceKind) {
+ case 'pd':
+ case 'tikv':
+ case 'tiflash':
+ port = instance.port
+ break
+ case 'tidb':
+ port = instance.status_port
+ break
+ }
+ return {
+ kind: instance.instanceKind,
+ display_name: instance.key,
+ ip: instance.ip,
+ port,
+ }
+ })
+ .filter((i) => i.port != null)
+
+ const [startTime, endTime] = calcTimeRange(fieldsValue.timeRange)
- const [startTime, endTime] = calcTimeRange(timeRange)
- const params: LogsearchCreateTaskGroupRequest = {
- targets: targets,
+ const req: LogsearchCreateTaskGroupRequest = {
+ targets,
request: {
start_time: startTime * 1000, // unix millionsecond
end_time: endTime * 1000, // unix millionsecond
- min_level: logLevel,
- patterns: searchValue.split(/\s+/), // 'foo boo' => ['foo', 'boo']
+ min_level: fieldsValue.logLevel,
+ patterns: (fieldsValue.keywords ?? '').split(/\s+/), // 'foo boo' => ['foo', 'boo']
},
}
- const result = await client.getInstance().logsTaskgroupPut(params)
- const id = result.data.task_group?.id
- if (!id) {
- // promp error here
- return
- }
- navigate('/search_logs/detail/' + id)
- }
- function handleTimeRangeChange(value: TimeRange) {
- setTimeRange(value)
- }
-
- function handleLogLevelChange(value: number) {
- setLogLevel(value)
- }
-
- function handleComponentChange(values: string[]) {
- setComponents(values)
- }
-
- function handleSearchPatternChange(e: ChangeEvent) {
- setSearchValue(e.target.value)
- }
-
- function handleSearch() {
- createTaskGroup()
- }
-
- function filterTreeNode(
- inputValue: string,
- legacyDataNode?: LegacyDataNode
- ): boolean {
- const name = legacyDataNode?.key as string
- return name.includes(inputValue)
- }
+ try {
+ const result = await client.getInstance().logsTaskgroupPut(req)
+ const id = result.data.task_group?.id
+ if (!id) {
+ throw new Error('Invalid server response')
+ }
+ navigate(`/search_logs/detail/${id}`)
+ } catch (e) {
+ // FIXME
+ Modal.error({
+ content: e.message,
+ })
+ }
+ setSubmitting(false)
+ }, [])
return (
-
+
+
-
-
- {LOG_LEVELS.map((val, idx) => (
-
+
+
+ {ValidLogLevels.map((val) => (
+
+ {LogLevelText[val]}
+
))}
-
-
-
0 ? '' : 'error'}
+ rules={[{ required: true }]}
>
-
+
+
+
-
+
{t('search_logs.common.search')}
diff --git a/ui/lib/apps/SearchLogs/components/SearchHistory.tsx b/ui/lib/apps/SearchLogs/components/SearchHistory.tsx
index 8be84f8f05..43bff70a70 100644
--- a/ui/lib/apps/SearchLogs/components/SearchHistory.tsx
+++ b/ui/lib/apps/SearchLogs/components/SearchHistory.tsx
@@ -1,20 +1,19 @@
import client from '@lib/client'
import { LogsearchTaskGroupModel } from '@lib/client'
-import { Head, CardTableV2 } from '@lib/components'
+import { Head, CardTableV2, DateTime } from '@lib/components'
import { ArrowLeftOutlined } from '@ant-design/icons'
import { Badge, Button } from 'antd'
-import { RangeValue } from 'rc-picker/lib/interface'
-import moment, { Moment } from 'moment'
import React, { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Link } from 'react-router-dom'
-import { DATE_TIME_FORMAT, LogLevelMap } from './utils'
+import { LogLevelText } from './utils'
import {
Selection,
SelectionMode,
} from 'office-ui-fabric-react/lib/DetailsList'
function componentRender({ target_stats: stats }) {
+ // FIXME: Extract common util
const r: Array = []
if (stats?.num_tidb_nodes) {
r.push(`${stats.num_tidb_nodes} TiDB`)
@@ -28,21 +27,26 @@ function componentRender({ target_stats: stats }) {
return {r.join(', ')}
}
-function formatTime(time: Moment | null | undefined): string {
- if (!time) {
- return ''
- }
- return time.format(DATE_TIME_FORMAT)
+function timeRender({ search_request }: LogsearchTaskGroupModel) {
+ return (
+
+ {search_request?.start_time && (
+
+ )}
+ {' ~ '}
+ {search_request?.end_time && (
+
+ )}
+
+ )
}
-function timeRender({ search_request: request }) {
- const startTime = request.start_time ? moment(request.start_time) : null
- const endTime = request.end_time ? moment(request.end_time) : null
- const timeRange = [startTime, endTime] as RangeValue
- if (!timeRange?.[0] || !timeRange?.[1]) {
- return ''
- }
- return `${formatTime(timeRange[0])} ~ ${formatTime(timeRange[1])}`
+function levelRender({ search_request: request }: LogsearchTaskGroupModel) {
+ return LogLevelText[request?.min_level!]
+}
+
+function patternRender({ search_request: request }: LogsearchTaskGroupModel) {
+ return (request?.patterns ?? []).join(' ')
}
export default function SearchHistory() {
@@ -60,20 +64,7 @@ export default function SearchHistory() {
getData()
}, [])
- function levelRender({ search_request: request }) {
- return LogLevelMap[request.min_level!]
- }
-
- function patternRender({ search_request: request }) {
- return request.patterns && request.patterns.length > 0
- ? request.patterns.join(' ')
- : ''
- }
-
- function stateRender({ state }) {
- if (state === undefined || state < 1) {
- return
- }
+ function stateRender({ state }: LogsearchTaskGroupModel) {
switch (state) {
case 1:
return (
@@ -102,9 +93,9 @@ export default function SearchHistory() {
async function handleDeleteSelected() {
for (const taskGroupID of selectedRowKeys) {
await client.getInstance().logsTaskgroupsIdDelete(taskGroupID)
- const res = await client.getInstance().logsTaskgroupsGet()
- setTaskGroups(res.data)
}
+ const res = await client.getInstance().logsTaskgroupsGet()
+ setTaskGroups(res.data)
}
async function handleDeleteAll() {
@@ -113,7 +104,7 @@ export default function SearchHistory() {
if (key === undefined) {
continue
}
- await client.getInstance().logsTaskgroupsIdDelete(key + '')
+ await client.getInstance().logsTaskgroupsIdDelete(String(key))
}
const res = await client.getInstance().logsTaskgroupsGet()
setTaskGroups(res.data)
@@ -131,42 +122,42 @@ export default function SearchHistory() {
name: t('search_logs.common.time_range'),
key: 'time',
minWidth: 200,
- maxWidth: 400,
+ maxWidth: 300,
onRender: timeRender,
},
{
name: t('search_logs.preview.level'),
key: 'level',
- minWidth: 100,
- maxWidth: 200,
+ minWidth: 70,
+ maxWidth: 120,
onRender: levelRender,
},
{
- name: t('search_logs.preview.component'),
+ name: t('search_logs.history.instances'),
key: 'target_stats',
- minWidth: 150,
- maxWidth: 230,
+ minWidth: 100,
+ maxWidth: 250,
onRender: componentRender,
},
{
name: t('search_logs.common.keywords'),
key: 'keywords',
- minWidth: 150,
- maxWidth: 230,
+ minWidth: 100,
+ maxWidth: 200,
onRender: patternRender,
},
{
- name: t('search_logs.history.state'),
+ name: t('search_logs.history.status'),
key: 'state',
- minWidth: 150,
- maxWidth: 230,
+ minWidth: 100,
+ maxWidth: 150,
onRender: stateRender,
},
{
name: t('search_logs.history.action'),
key: 'action',
- minWidth: 150,
- maxWidth: 230,
+ minWidth: 100,
+ maxWidth: 200,
onRender: actionRender,
},
]
@@ -196,15 +187,13 @@ export default function SearchHistory() {
>
}
/>
-
-
-
+
)
}
diff --git a/ui/lib/apps/SearchLogs/components/SearchResult.tsx b/ui/lib/apps/SearchLogs/components/SearchResult.tsx
index 77d309de6b..228c02fba7 100644
--- a/ui/lib/apps/SearchLogs/components/SearchResult.tsx
+++ b/ui/lib/apps/SearchLogs/components/SearchResult.tsx
@@ -3,9 +3,9 @@ import { ModelRequestTargetNode, LogsearchTaskModel } from '@lib/client'
import { CardTableV2 } from '@lib/components'
import { Alert } from 'antd'
import moment from 'moment'
-import React, { useEffect, useState } from 'react'
+import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
-import { DATE_TIME_FORMAT, LogLevelMap, namingMap } from './utils'
+import { LogLevelText, namingMap } from './utils'
import Log from './Log'
type LogPreview = {
@@ -57,8 +57,8 @@ export default function SearchResult({ taskGroupID, tasks }: Props) {
(value, index): LogPreview => {
return {
key: index,
- time: moment(value.time).format(DATE_TIME_FORMAT),
- level: LogLevelMap[value.level ?? 0],
+ time: moment(value.time).format('YYYY-MM-DD HH:mm:ss'),
+ level: LogLevelText[value.level ?? 0],
component: getComponent(value.task_id),
log: value.message,
}
@@ -73,35 +73,39 @@ export default function SearchResult({ taskGroupID, tasks }: Props) {
getLogPreview()
}, [taskGroupID, tasks])
- const columns = [
- {
- name: t('search_logs.preview.time'),
- key: 'time',
- fieldName: 'time',
- minWidth: 160,
- maxWidth: 300,
- },
- {
- name: t('search_logs.preview.level'),
- key: 'level',
- fieldName: 'level',
- minWidth: 60,
- maxWidth: 120,
- },
- {
- name: t('search_logs.preview.component'),
- key: 'component',
- minWidth: 120,
- maxWidth: 200,
- onRender: componentRender,
- },
- {
- name: t('search_logs.preview.log'),
- key: 'log',
- minWidth: 500,
- onRender: ({ log }) => ,
- },
- ]
+ const columns = useMemo(
+ () => [
+ {
+ name: t('search_logs.preview.time'),
+ key: 'time',
+ fieldName: 'time',
+ minWidth: 160,
+ maxWidth: 300,
+ },
+ {
+ name: t('search_logs.preview.level'),
+ key: 'level',
+ fieldName: 'level',
+ minWidth: 60,
+ maxWidth: 120,
+ },
+ {
+ name: t('search_logs.preview.component'),
+ key: 'component',
+ minWidth: 120,
+ maxWidth: 200,
+ onRender: componentRender,
+ },
+ {
+ name: t('search_logs.preview.log'),
+ key: 'log',
+ minWidth: 500,
+ onRender: ({ log }) => ,
+ },
+ ],
+ [t]
+ )
+
return (
<>
{!loading && (
diff --git a/ui/lib/apps/SearchLogs/components/Styles.module.css b/ui/lib/apps/SearchLogs/components/Styles.module.css
index 932db1a4c7..ccb887fc10 100644
--- a/ui/lib/apps/SearchLogs/components/Styles.module.css
+++ b/ui/lib/apps/SearchLogs/components/Styles.module.css
@@ -6,7 +6,3 @@
margin-right: 12px;
margin-bottom: 12px;
}
-
-.components > :global(div) {
- width: 100%;
-}
diff --git a/ui/lib/apps/SearchLogs/components/utils.ts b/ui/lib/apps/SearchLogs/components/utils.ts
index a05b5832d4..40a07d1a7c 100644
--- a/ui/lib/apps/SearchLogs/components/utils.ts
+++ b/ui/lib/apps/SearchLogs/components/utils.ts
@@ -1,22 +1,34 @@
-import {
- LogsearchTaskGroupResponse,
- LogsearchTaskModel,
- ModelRequestTargetNode,
-} from '@lib/client'
-import { TimeRange } from '@lib/components'
-
export const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss'
-export const LogLevelMap = {
- 0: 'UNKNOWN',
- 1: 'DEBUG',
- 2: 'INFO',
- 3: 'WARN',
- 4: 'TRACE',
- 5: 'CRITICAL',
- 6: 'ERROR',
+export enum LogLevel {
+ Unknown = 0,
+ Debug,
+ Info,
+ Warn,
+ Trace,
+ Critical,
+ Error,
+}
+
+export const LogLevelText = {
+ [LogLevel.Unknown]: 'UNKNOWN',
+ [LogLevel.Debug]: 'DEBUG',
+ [LogLevel.Info]: 'INFO',
+ [LogLevel.Warn]: 'WARN',
+ [LogLevel.Trace]: 'TRACE',
+ [LogLevel.Critical]: 'CRITICAL',
+ [LogLevel.Error]: 'ERROR',
}
+export const ValidLogLevels = [
+ LogLevel.Debug,
+ LogLevel.Info,
+ LogLevel.Warn,
+ // LogLevel.Trace,
+ LogLevel.Critical,
+ LogLevel.Error,
+]
+
export enum TaskState {
Running = 1,
Finished,
@@ -37,102 +49,6 @@ export const namingMap = {
[NodeKind.TiFlash]: 'TiFlash',
}
-export const AllLogLevel = [1, 2, 3, 4, 5, 6]
-
-// export function parseClusterInfo(
-// info: ClusterinfoClusterInfo
-// ): ModelRequestTargetNode[] {
-// const targets: ModelRequestTargetNode[] = []
-// info?.tidb?.nodes?.forEach((item) => {
-// if (
-// item.ip === undefined ||
-// item.port === undefined ||
-// item.status_port === undefined
-// ) {
-// return
-// }
-// // TiDB has a different behavior: it use "status_port" for grpc, "port" for display.
-// targets.push({
-// kind: NodeKind.TiDB,
-// ip: item.ip,
-// port: item.status_port,
-// display_name: `${item.ip}:${item.port}`,
-// })
-// })
-// info?.tikv?.nodes?.forEach((item) => {
-// if (
-// item.ip === undefined ||
-// item.port === undefined ||
-// item.status_port === undefined
-// ) {
-// return
-// }
-// targets.push({
-// kind: NodeKind.TiKV,
-// ip: item.ip,
-// port: item.port,
-// display_name: `${item.ip}:${item.port}`,
-// })
-// })
-// info?.pd?.nodes?.forEach((item) => {
-// if (item.ip === undefined || item.port === undefined) {
-// return
-// }
-// targets.push({
-// kind: NodeKind.PD,
-// ip: item.ip,
-// port: item.port,
-// display_name: `${item.ip}:${item.port}`,
-// })
-// })
-// info?.tiflash?.nodes?.forEach((item) => {
-// if (!(item.ip && item.port)) {
-// return
-// }
-// targets.push({
-// kind: NodeKind.TiFlash,
-// ip: item.ip,
-// port: item.port,
-// display_name: `${item.ip}:${item.port}`,
-// })
-// })
-// return targets
-// }
-
-interface Params {
- timeRange: TimeRange
- logLevel: number
- components: ModelRequestTargetNode[]
- searchValue: string
-}
-
-export function parseSearchingParams(resp: LogsearchTaskGroupResponse): Params {
- const { task_group, tasks } = resp
- const { start_time, end_time, min_level, patterns } =
- task_group?.search_request || {}
- let timeRange: TimeRange = {
- type: 'absolute',
- value: [start_time! / 1000, end_time! / 1000],
- }
- return {
- timeRange: timeRange,
- logLevel: min_level ?? 2,
- searchValue: patterns && patterns.length > 0 ? patterns.join(' ') : '',
- components: tasks && tasks.length > 0 ? getComponents(tasks) : [],
- }
-}
-
-function getComponents(tasks: LogsearchTaskModel[]): ModelRequestTargetNode[] {
- const targets: ModelRequestTargetNode[] = []
- tasks.forEach((task) => {
- if (task.target === undefined) {
- return
- }
- targets.push(task.target)
- })
- return targets
-}
-
export const NodeKindList = [
NodeKind.TiDB,
NodeKind.TiKV,
diff --git a/ui/lib/apps/SearchLogs/translations/en.yaml b/ui/lib/apps/SearchLogs/translations/en.yaml
index 8bfe3f1115..6251d0bdca 100644
--- a/ui/lib/apps/SearchLogs/translations/en.yaml
+++ b/ui/lib/apps/SearchLogs/translations/en.yaml
@@ -15,7 +15,6 @@ search_logs:
end_time: End Time
log_level: Log Level
components: instances
- components_placeholder: Select at least one instance
keywords: Keywords
keywords_placeholder: Keywords, Optional, separated by spaces
search: Search
@@ -36,11 +35,12 @@ search_logs:
component: Component
log: Log
history:
+ instances: Instances
running: Running
finished: Finished
delete_selected: Delete selected
delete_all: Delete All
- state: State
+ status: Status
action: Action
detail: Detail
delete: Delete
diff --git a/ui/lib/apps/SearchLogs/translations/zh-CN.yaml b/ui/lib/apps/SearchLogs/translations/zh-CN.yaml
index 4ecd58efa1..c44f2deed4 100644
--- a/ui/lib/apps/SearchLogs/translations/zh-CN.yaml
+++ b/ui/lib/apps/SearchLogs/translations/zh-CN.yaml
@@ -15,7 +15,6 @@ search_logs:
end_time: 结束时间
log_level: 日志等级
components: 选择实例
- components_placeholder: 至少选择一个实例
keywords: 关键字
keywords_placeholder: 搜索关键字,可选,以空格分割
search: 搜索
@@ -36,11 +35,12 @@ search_logs:
component: 组件
log: 日志
history:
+ instances: 实例
running: 正在搜索
finished: 已完成
delete_selected: 删除选中的任务
delete_all: 删除全部任务
- state: 状态
+ status: 状态
action: 操作
detail: 查看详情
delete: 删除
diff --git a/ui/lib/apps/SlowQuery/utils/useSlowQuery.ts b/ui/lib/apps/SlowQuery/utils/useSlowQuery.ts
index d80f75f4f5..39ba03fbdf 100644
--- a/ui/lib/apps/SlowQuery/utils/useSlowQuery.ts
+++ b/ui/lib/apps/SlowQuery/utils/useSlowQuery.ts
@@ -2,7 +2,7 @@ import { useEffect, useMemo, useState } from 'react'
import { useSessionStorageState } from '@umijs/hooks'
import client, { SlowqueryBase } from '@lib/client'
-import { calcTimeRange, DEF_TIME_RANGE, TimeRange } from '@lib/components'
+import { calcTimeRange, TimeRange } from '@lib/components'
import useOrderState, { IOrderOptions } from '@lib/utils/useOrderState'
const QUERY_OPTIONS = 'slow_query.query_options'
@@ -13,7 +13,7 @@ const DEF_ORDER_OPTIONS: IOrderOptions = {
}
export interface ISlowQueryOptions {
- timeRange: TimeRange
+ timeRange?: TimeRange
schemas: string[]
searchText: string
limit: number
@@ -23,7 +23,7 @@ export interface ISlowQueryOptions {
}
export const DEF_SLOW_QUERY_OPTIONS: ISlowQueryOptions = {
- timeRange: DEF_TIME_RANGE,
+ timeRange: undefined,
schemas: [],
searchText: '',
limit: 100,
diff --git a/ui/lib/apps/Statement/pages/List/TimeRangeSelector.tsx b/ui/lib/apps/Statement/pages/List/TimeRangeSelector.tsx
index 0e18f49917..259144db70 100644
--- a/ui/lib/apps/Statement/pages/List/TimeRangeSelector.tsx
+++ b/ui/lib/apps/Statement/pages/List/TimeRangeSelector.tsx
@@ -34,7 +34,7 @@ interface RangeTime {
export type TimeRange = RecentSecTime | RangeTime
-export const DEF_TIME_RANGE: TimeRange = {
+export const DEFAULT_TIME_RANGE: TimeRange = {
type: 'recent',
value: 30 * 60,
}
diff --git a/ui/lib/apps/Statement/utils/useStatement.ts b/ui/lib/apps/Statement/utils/useStatement.ts
index c56b4a95b8..2c09ebb81c 100644
--- a/ui/lib/apps/Statement/utils/useStatement.ts
+++ b/ui/lib/apps/Statement/utils/useStatement.ts
@@ -6,7 +6,7 @@ import useOrderState, { IOrderOptions } from '@lib/utils/useOrderState'
import {
calcValidStatementTimeRange,
- DEF_TIME_RANGE,
+ DEFAULT_TIME_RANGE,
TimeRange,
} from '../pages/List/TimeRangeSelector'
@@ -24,7 +24,7 @@ export interface IStatementQueryOptions {
}
export const DEF_STMT_QUERY_OPTIONS: IStatementQueryOptions = {
- timeRange: DEF_TIME_RANGE,
+ timeRange: DEFAULT_TIME_RANGE,
schemas: [],
stmtTypes: [],
}
diff --git a/ui/lib/components/BaseSelect/index.module.less b/ui/lib/components/BaseSelect/index.module.less
index 5433f4e63c..b0572755bc 100644
--- a/ui/lib/components/BaseSelect/index.module.less
+++ b/ui/lib/components/BaseSelect/index.module.less
@@ -41,6 +41,15 @@
}
}
+:global(.ant-form-item-has-error) {
+ .baseSelectInner {
+ border-color: @error-color !important;
+ &.focused {
+ .active(@error-color);
+ }
+ }
+}
+
.baseSelectInput {
opacity: 0;
position: absolute;
diff --git a/ui/lib/components/BaseSelect/index.tsx b/ui/lib/components/BaseSelect/index.tsx
index be0b9cde1e..183c9593e7 100644
--- a/ui/lib/components/BaseSelect/index.tsx
+++ b/ui/lib/components/BaseSelect/index.tsx
@@ -1,45 +1,50 @@
-import React, { useState, useCallback, useRef } from 'react'
+import React, { useState, useCallback, useRef, useMemo } from 'react'
import cx from 'classnames'
-import { Dropdown } from 'antd'
import { useEventListener } from '@umijs/hooks'
import { DownOutlined } from '@ant-design/icons'
+import Trigger from 'rc-trigger'
import KeyCode from 'rc-util/lib/KeyCode'
import { TextWrap } from '..'
import styles from './index.module.less'
-export interface IBaseSelectDropdownRenderProps {
- value?: T
- triggerOnChange?: (value: T) => void
-}
-
export interface IBaseSelectProps
extends Omit<
React.HTMLAttributes,
'onChange' | 'placeholder'
> {
- dropdownRender: (
- renderProps: IBaseSelectDropdownRenderProps
- ) => React.ReactElement
+ dropdownRender: () => React.ReactElement
value?: T
valueRender: (value?: T) => React.ReactNode
- onChange?: (value: T) => void
placeholder?: React.ReactNode
+ overlayClassName?: string
disabled?: boolean
tabIndex?: number
autoFocus?: boolean
}
+const builtinPlacements = {
+ bottomLeft: {
+ ignoreShake: true,
+ points: ['tl', 'bl'],
+ offset: [0, 4],
+ overflow: {
+ adjustX: 0,
+ adjustY: 0,
+ },
+ },
+}
+
function BaseSelect({
dropdownRender,
value,
valueRender,
- onChange,
placeholder,
disabled,
tabIndex,
autoFocus,
className,
+ overlayClassName,
onFocus,
onBlur,
onKeyDown,
@@ -104,18 +109,17 @@ function BaseSelect({
const dropdownOverlayRef = useRef(null)
const containerRef = useRef(null)
- const overlay = (
-
- {dropdownRender({
- value,
- triggerOnChange: onChange,
- })}
-
- )
+ const overlay = useMemo(() => {
+ return (
+
+ {dropdownRender()}
+
+ )
+ }, [dropdownRender, overlayClassName, handleOverlayMouseDown])
useEventListener('mousedown', (ev: MouseEvent) => {
// Close the dropdown if click outside
@@ -141,7 +145,6 @@ function BaseSelect({
if (v && !disabled) {
return false
}
- // Otherwise, unchanged
return v
})
}, [disabled])
@@ -150,7 +153,16 @@ function BaseSelect({
const displayAsPlaceholder = renderedValue == null
return (
-
+
({
-
+
)
}
-BaseSelect.whyDidYouRender = true
-
export default React.memo(BaseSelect)
diff --git a/ui/lib/components/CardTable/index.module.less b/ui/lib/components/CardTable/index.module.less
deleted file mode 100644
index 811e990e7b..0000000000
--- a/ui/lib/components/CardTable/index.module.less
+++ /dev/null
@@ -1,22 +0,0 @@
-@import '~antd/es/style/themes/default.less';
-
-.cardTable {
- :global {
- .ant-table-content tr:first-child > th:first-child {
- padding-left: @padding-page !important;
- }
-
- .ant-table-row td:first-child {
- padding-left: @padding-page !important;
- }
-
- .ant-table-pagination {
- margin-right: @padding-page !important;
- }
- }
-}
-
-.cardTableContent {
- margin-left: -@padding-page;
- margin-right: -@padding-page;
-}
diff --git a/ui/lib/components/CardTable/index.tsx b/ui/lib/components/CardTable/index.tsx
deleted file mode 100644
index 02e0220366..0000000000
--- a/ui/lib/components/CardTable/index.tsx
+++ /dev/null
@@ -1,50 +0,0 @@
-import React, { ReactNode } from 'react'
-import { Table, Skeleton } from 'antd'
-import { TableProps } from 'antd/es/table'
-import cx from 'classnames'
-import Card from '../Card'
-import styles from './index.module.less'
-
-export interface ICardTableProps
- extends TableProps {
- title?: any
- className?: string
- style?: object
- loading?: boolean
- loadingSkeletonRows?: number
- cardExtra?: ReactNode
- children?: ReactNode
-}
-
-function CardTable({
- title,
- className,
- style,
- loading,
- loadingSkeletonRows,
- cardExtra,
- ...rest
-}: ICardTableProps) {
- return (
-
- {loading ? (
-
- ) : (
-
- )}
-
- )
-}
-
-export default CardTable
diff --git a/ui/lib/components/CardTableV2/GroupHeader.tsx b/ui/lib/components/CardTableV2/GroupHeader.tsx
index 5a2ac87aa9..a4f086c12c 100644
--- a/ui/lib/components/CardTableV2/GroupHeader.tsx
+++ b/ui/lib/components/CardTableV2/GroupHeader.tsx
@@ -75,7 +75,6 @@ function BaseAntCheckboxGroupHeader(props: IGroupHeaderProps) {
diff --git a/ui/lib/components/InstanceSelect/DropOverlay.tsx b/ui/lib/components/InstanceSelect/DropOverlay.tsx
index 4b2a352838..0870ccd035 100644
--- a/ui/lib/components/InstanceSelect/DropOverlay.tsx
+++ b/ui/lib/components/InstanceSelect/DropOverlay.tsx
@@ -17,7 +17,7 @@ const groupProps = {
onRenderHeader: (props) => ,
}
-export default function DropOverlay({
+function DropOverlay({
selection,
columns,
items,
@@ -54,3 +54,5 @@ export default function DropOverlay({
)
}
+
+export default React.memo(DropOverlay)
diff --git a/ui/lib/components/InstanceSelect/ValueDisplay.tsx b/ui/lib/components/InstanceSelect/ValueDisplay.tsx
index 6bef518195..50639166ad 100644
--- a/ui/lib/components/InstanceSelect/ValueDisplay.tsx
+++ b/ui/lib/components/InstanceSelect/ValueDisplay.tsx
@@ -1,5 +1,10 @@
import React, { useMemo } from 'react'
-import { IInstanceTableItem, InstanceKind } from '@lib/utils/instanceTable'
+import {
+ IInstanceTableItem,
+ InstanceKind,
+ InstanceKindName,
+} from '@lib/utils/instanceTable'
+import { useTranslation } from 'react-i18next'
interface InstanceStat {
all: number
@@ -22,6 +27,8 @@ export default function ValueDisplay({
items,
selectedKeys,
}: IValueDisplayProps) {
+ const { t } = useTranslation()
+
const text = useMemo(() => {
const selectedKeysMap = {}
selectedKeys.forEach((key) => (selectedKeysMap[key] = true))
@@ -47,18 +54,28 @@ export default function ValueDisplay({
}
if (stats.selected > 0) {
if (stats.all === stats.selected) {
- p.push('All ' + ik)
+ p.push(
+ t('component.instanceSelect.selected.partial.all', {
+ component: InstanceKindName[ik],
+ })
+ )
} else {
- p.push(`${stats.selected} ${ik}`)
+ p.push(
+ t('component.instanceSelect.selected.partial.n', {
+ n: stats.selected,
+ component: InstanceKindName[ik],
+ })
+ )
}
}
}
if (!hasUnselected) {
- return 'All Instances'
+ return t('component.instanceSelect.selected.all')
}
+
return p.join(', ')
- }, [items, selectedKeys])
+ }, [t, items, selectedKeys])
return <>{text}>
}
diff --git a/ui/lib/components/InstanceSelect/index.tsx b/ui/lib/components/InstanceSelect/index.tsx
index a51942ec0a..0981bf557c 100644
--- a/ui/lib/components/InstanceSelect/index.tsx
+++ b/ui/lib/components/InstanceSelect/index.tsx
@@ -1,9 +1,17 @@
-import React, { useCallback, useRef, useMemo, useEffect, useState } from 'react'
+import React, { useCallback, useRef, useMemo, useEffect } from 'react'
+import { useTranslation } from 'react-i18next'
+import { useShallowCompareEffect } from 'react-use'
import { Tooltip } from 'antd'
import { Selection } from 'office-ui-fabric-react/lib/Selection'
-import { BaseSelect, InstanceStatusBadge, TextWrap } from '../'
+import {
+ IBaseSelectProps,
+ BaseSelect,
+ InstanceStatusBadge,
+ TextWrap,
+} from '../'
import { useClientRequest } from '@lib/utils/useClientRequest'
import client from '@lib/client'
+import { addTranslationResource } from '@lib/utils/i18n'
import { usePersistFn } from '@umijs/hooks'
import { IColumn } from 'office-ui-fabric-react/lib/DetailsList'
import {
@@ -13,23 +21,70 @@ import {
import DropOverlay from './DropOverlay'
import ValueDisplay from './ValueDisplay'
-import { useShallowCompareEffect } from 'react-use'
-export interface IInstanceSelectProps {
+export interface IInstanceSelectProps
+ extends Omit, 'dropdownRender' | 'valueRender'> {
+ onChange?: (value: string[]) => void
enableTiFlash?: boolean
defaultSelectAll?: boolean
- onChange?: (values: string[]) => void
- value?: string[]
}
export interface IInstanceSelectRefProps {
- mapValueToNode: (value: string) => void
+ getInstanceByKeys: (keys: string[]) => IInstanceTableItem[]
+ getInstanceByKey: (key: string) => IInstanceTableItem
+}
+
+const translations = {
+ en: {
+ placeholder: 'Select Instances',
+ selected: {
+ all: 'All Instances',
+ partial: {
+ n: '{{n}} {{component}}',
+ all: 'All {{component}}',
+ },
+ },
+ columns: {
+ key: 'Instance',
+ status: 'Status',
+ },
+ },
+ 'zh-CN': {
+ placeholder: '选择实例',
+ selected: {
+ all: '所有实例',
+ partial: {
+ n: '{{n}} {{component}}',
+ all: '所有 {{component}}',
+ },
+ },
+ columns: {
+ key: '实例',
+ status: '状态',
+ },
+ },
+}
+
+for (const key in translations) {
+ addTranslationResource(key, {
+ component: {
+ instanceSelect: translations[key],
+ },
+ })
}
function InstanceSelect(
- props: IInstanceSelectProps,
+ {
+ enableTiFlash,
+ defaultSelectAll,
+ onChange,
+ value,
+ ...restProps
+ }: IInstanceSelectProps,
ref: React.Ref
) {
+ const { t } = useTranslation()
+
const {
data: dataTiDB,
isLoading: loadingTiDB,
@@ -49,10 +104,10 @@ function InstanceSelect(
client.getInstance().getPDTopology({ cancelToken })
)
- const columns = useMemo(() => {
- const c: IColumn[] = [
+ const columns: IColumn[] = useMemo(
+ () => [
{
- name: 'Instance',
+ name: t('component.instanceSelect.columns.key'),
key: 'key',
minWidth: 160,
maxWidth: 160,
@@ -67,7 +122,7 @@ function InstanceSelect(
},
},
{
- name: 'Status',
+ name: t('component.instanceSelect.columns.status'),
key: 'status',
minWidth: 100,
maxWidth: 100,
@@ -79,9 +134,9 @@ function InstanceSelect(
)
},
},
- ]
- return c
- }, [])
+ ],
+ [t]
+ )
const [tableItems, tableGroups] = useMemo(() => {
if (loadingTiDB || loadingStores || loadingPD) {
@@ -92,11 +147,10 @@ function InstanceSelect(
dataTiDB,
dataTiKV: dataStores?.tikv,
dataTiFlash: dataStores?.tiflash,
- includeTiFlash: props.enableTiFlash,
+ includeTiFlash: enableTiFlash,
})
}, [
- props.enableTiFlash,
- props.defaultSelectAll,
+ enableTiFlash,
dataTiDB,
dataStores,
dataPD,
@@ -105,83 +159,122 @@ function InstanceSelect(
loadingPD,
])
- const [selectedKeys, setSelectedKeys] = useState(props.value ?? [])
-
- const onChange = usePersistFn((v: string[]) => {
- console.log('onChange', v)
- props.onChange?.(v)
+ const onChangePersist = usePersistFn((v: string[]) => {
+ onChange?.(v)
})
const selection = useRef(
new Selection({
onSelectionChanged: () => {
- console.log('onSelectionChanged')
const s = selection.current.getSelection() as IInstanceTableItem[]
const keys = s.map((v) => v.key)
- setSelectedKeys(keys)
- onChange([...keys])
+ onChangePersist([...keys])
},
})
)
useShallowCompareEffect(() => {
- console.log('props.value changed')
+ const sel = selection.current
+ if (value != null) {
+ const s = sel.getSelection() as IInstanceTableItem[]
+ if (
+ s.length === value.length &&
+ s.every((item, index) => value?.[index] === item.key)
+ ) {
+ return
+ }
+ }
// Update selection when value is changed
- selection.current.setAllSelected(false)
- if (props.value) {
- for (const key of props.value) {
- selection.current.setKeySelected(key, true, false)
+ sel.setChangeEvents(false)
+ sel.setAllSelected(false)
+ if (value && value.length > 0) {
+ for (const key of value) {
+ sel.setKeySelected(key, true, false)
}
}
- }, [props.value])
+ sel.setChangeEvents(true)
+ }, [value])
const dataHasLoaded = useRef(false)
useEffect(() => {
- // Select all if `defaultSelectAll` is set.
+ // When data is loaded for the first time, we need to:
+ // - Select all if `defaultSelectAll` is set and value is not given.
+ // - Update selection according to value
if (dataHasLoaded.current) {
return
}
if (tableItems.length === 0) {
return
}
- if (props.defaultSelectAll) {
- selection.current.setItems(tableItems)
- selection.current.setAllSelected(true)
+ const sel = selection.current
+ sel.setChangeEvents(false)
+ sel.setItems(tableItems)
+ if (value && value.length > 0) {
+ sel.setAllSelected(false)
+ for (const key of value) {
+ sel.setKeySelected(key, true, false)
+ }
+ } else if (defaultSelectAll) {
+ sel.setAllSelected(true)
}
+ sel.setChangeEvents(true)
dataHasLoaded.current = true
+ // [defaultSelectAll, value] is not needed
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [tableItems])
- const mapValueToNode = usePersistFn(() => {})
+ const getInstanceByKeys = usePersistFn((keys: string[]) => {
+ const keyToItemMap = {}
+ for (const item of tableItems) {
+ keyToItemMap[item.key] = item
+ }
+ return keys.map((key) => keyToItemMap[key])
+ })
+
+ const getInstanceByKey = usePersistFn((key: string) => {
+ return getInstanceByKeys([key])[0]
+ })
React.useImperativeHandle(ref, () => ({
- mapValueToNode,
+ getInstanceByKey,
+ getInstanceByKeys,
}))
- const renderValue = useCallback(() => {
- if (tableItems.length === 0 || selectedKeys.length === 0) {
- return null
- }
- return
- }, [tableItems, selectedKeys])
+ const renderValue = useCallback(
+ (selectedKeys) => {
+ if (
+ tableItems.length === 0 ||
+ !selectedKeys ||
+ selectedKeys.length === 0
+ ) {
+ return null
+ }
+ return
+ },
+ [tableItems]
+ )
- const renderDropdown = useCallback(() => {
- return (
+ const renderDropdown = useCallback(
+ () => (
- )
- }, [columns, tableItems, tableGroups])
+ ),
+ [columns, tableItems, tableGroups]
+ )
return (
)
}
diff --git a/ui/lib/components/TimeRangeSelector/index.tsx b/ui/lib/components/TimeRangeSelector/index.tsx
index 47d5260812..cd26baf08e 100644
--- a/ui/lib/components/TimeRangeSelector/index.tsx
+++ b/ui/lib/components/TimeRangeSelector/index.tsx
@@ -1,4 +1,4 @@
-import React, { useState, useMemo } from 'react'
+import React, { useState, useMemo, useCallback, useEffect } from 'react'
import { Dropdown, Button, DatePicker } from 'antd'
import { ClockCircleOutlined, DownOutlined } from '@ant-design/icons'
import { getValueFormat } from '@baurine/grafana-value-formats'
@@ -12,14 +12,28 @@ import styles from './index.module.less'
const { RangePicker } = DatePicker
const RECENT_SECONDS = [
+ 15 * 60,
30 * 60,
60 * 60,
- 3 * 60 * 60,
+
+ 2 * 60 * 60,
6 * 60 * 60,
12 * 60 * 60,
+
24 * 60 * 60,
+ 2 * 24 * 60 * 60,
+ 3 * 24 * 60 * 60,
+
+ 7 * 24 * 60 * 60,
+ 14 * 24 * 60 * 60,
+ 28 * 24 * 60 * 60,
]
+const DEFAULT_TIME_RANGE: TimeRange = {
+ type: 'recent',
+ value: 30 * 60,
+}
+
interface RecentSecTime {
type: 'recent'
value: number // unit: seconds
@@ -32,62 +46,63 @@ interface RangeTime {
export type TimeRange = RecentSecTime | RangeTime
-export const DEF_TIME_RANGE: TimeRange = {
- type: 'recent',
- value: 30 * 60,
-}
-
-export function calcTimeRange(timeRange: TimeRange): [number, number] {
- if (timeRange.type === 'absolute') {
- return timeRange.value
+export function calcTimeRange(timeRange?: TimeRange): [number, number] {
+ let t2 = timeRange ?? DEFAULT_TIME_RANGE
+ if (t2.type === 'absolute') {
+ return t2.value
} else {
const now = dayjs().unix()
- return [now - timeRange.value, now]
+ return [now - t2.value, now]
}
}
export interface ITimeRangeSelectorProps {
- value: TimeRange
- onChange: (val: TimeRange) => void
+ value?: TimeRange
+ onChange?: (val: TimeRange) => void
}
-function TimeRangeSelector({
- value: curTimeRange,
- onChange,
-}: ITimeRangeSelectorProps) {
+function TimeRangeSelector({ value, onChange }: ITimeRangeSelectorProps) {
const { t } = useTranslation()
const [dropdownVisible, setDropdownVisible] = useState(false)
+ useEffect(() => {
+ if (!value) {
+ onChange?.(DEFAULT_TIME_RANGE)
+ }
+ }, [value])
+
const rangePickerValue = useMemo(() => {
- return curTimeRange.type === 'absolute'
- ? ([
- moment(curTimeRange.value[0] * 1000),
- moment(curTimeRange.value[1] * 1000),
- ] as [Moment, Moment])
- : null
- }, [curTimeRange])
-
- function handleRecentChange(seconds: number) {
- onChange({
- type: 'recent',
- value: seconds,
- })
- setDropdownVisible(false)
- }
+ if (value?.type !== 'absolute') {
+ return null
+ }
+ return value.value.map((sec) => moment(sec * 1000)) as [Moment, Moment]
+ }, [value])
+
+ const handleRecentChange = useCallback(
+ (seconds: number) => {
+ onChange?.({
+ type: 'recent',
+ value: seconds,
+ })
+ setDropdownVisible(false)
+ },
+ [onChange]
+ )
- function handleRangePickerChange(values) {
- if (values === null) {
- if (curTimeRange.type === 'absolute') {
- handleRecentChange(30 * 60)
+ const handleRangePickerChange = useCallback(
+ (values) => {
+ if (values === null) {
+ onChange?.(DEFAULT_TIME_RANGE)
+ } else {
+ onChange?.({
+ type: 'absolute',
+ value: values.map((v) => v.unix()),
+ })
}
- } else {
- onChange({
- type: 'absolute',
- value: [values[0].unix(), values[1].unix()],
- })
setDropdownVisible(false)
- }
- }
+ },
+ [onChange]
+ )
const dropdownContent = (
@@ -104,8 +119,7 @@ function TimeRangeSelector({
key={seconds}
className={cx(styles.time_range_item, {
[styles.time_range_item_active]:
- curTimeRange.type === 'recent' &&
- curTimeRange.value === seconds,
+ value && value.type === 'recent' && value.value === seconds,
})}
onClick={() => handleRecentChange(seconds)}
>
@@ -141,17 +155,20 @@ function TimeRangeSelector({
onVisibleChange={setDropdownVisible}
>
}>
- {curTimeRange.type === 'recent' ? (
+ {value && value.type === 'recent' && (
{t('statement.pages.overview.toolbar.time_range_selector.recent')}{' '}
- {getValueFormat('s')(curTimeRange.value, 0)}
+ {getValueFormat('s')(value.value, 0)}
- ) : (
+ )}
+ {value && value.type === 'absolute' && (
- {dayjs.unix(curTimeRange.value[0]).format('MM-DD HH:mm:ss')} ~{' '}
- {dayjs.unix(curTimeRange.value[1]).format('MM-DD HH:mm:ss')}
+ {value.value
+ .map((v) => dayjs.unix(v).format('MM-DD HH:mm:ss'))
+ .join(' ~ ')}
)}
+ {!value && 'Select Time'}
diff --git a/ui/lib/components/index.ts b/ui/lib/components/index.ts
index 80637c04d1..f5b36488c5 100644
--- a/ui/lib/components/index.ts
+++ b/ui/lib/components/index.ts
@@ -6,8 +6,6 @@ export * from './Card'
export { default as Card } from './Card'
export * from './CardTabs'
export { default as CardTabs } from './CardTabs'
-export * from './CardTable'
-export { default as CardTable } from './CardTable'
export * from './CardTableV2'
export { default as CardTableV2 } from './CardTableV2'
export * from './Bar'
From 989e47008a098bbfe2ded3e9edb6a54f75c538d6 Mon Sep 17 00:00:00 2001
From: Breezewish
Date: Mon, 25 May 2020 23:21:27 +0800
Subject: [PATCH 09/14] Fix
---
ui/lib/antd.global.less | 2 ++
ui/lib/components/TimeRangeSelector/index.tsx | 2 ++
2 files changed, 4 insertions(+)
diff --git a/ui/lib/antd.global.less b/ui/lib/antd.global.less
index 292c0dfb39..5b81af33f7 100644
--- a/ui/lib/antd.global.less
+++ b/ui/lib/antd.global.less
@@ -1,3 +1,5 @@
+// Slightly modified from https://github.com/ant-design/ant-design/blob/master/components/style/core/base.less
+
/* stylelint-disable at-rule-no-unknown */
// Reboot
diff --git a/ui/lib/components/TimeRangeSelector/index.tsx b/ui/lib/components/TimeRangeSelector/index.tsx
index cd26baf08e..35f3a68aa1 100644
--- a/ui/lib/components/TimeRangeSelector/index.tsx
+++ b/ui/lib/components/TimeRangeSelector/index.tsx
@@ -69,6 +69,8 @@ function TimeRangeSelector({ value, onChange }: ITimeRangeSelectorProps) {
if (!value) {
onChange?.(DEFAULT_TIME_RANGE)
}
+ // ignore [onChange]
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [value])
const rangePickerValue = useMemo(() => {
From 612f9693211bb6a69c2cbe7ad7843e86959fd657 Mon Sep 17 00:00:00 2001
From: Breezewish
Date: Tue, 2 Jun 2020 17:44:44 +0800
Subject: [PATCH 10/14] Update
---
go.mod | 2 +-
ui/lib/utils/formatSql.ts | 2 +-
ui/package.json | 2 +-
ui/yarn.lock | 1170 +++++++++++++++----------------------
4 files changed, 483 insertions(+), 693 deletions(-)
diff --git a/go.mod b/go.mod
index 8faa533434..fb2ef09b51 100644
--- a/go.mod
+++ b/go.mod
@@ -30,7 +30,7 @@ require (
github.com/spf13/pflag v1.0.1
github.com/stretchr/testify v1.4.0
github.com/swaggo/http-swagger v0.0.0-20200103000832-0e9263c4b516
- github.com/swaggo/swag v1.6.5
+ github.com/swaggo/swag v1.6.7-0.20200529100950-7c765ddd0476
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738
go.uber.org/atomic v1.5.0
go.uber.org/fx v1.10.0
diff --git a/ui/lib/utils/formatSql.ts b/ui/lib/utils/formatSql.ts
index d0335d9b2b..62bdb9a8e2 100644
--- a/ui/lib/utils/formatSql.ts
+++ b/ui/lib/utils/formatSql.ts
@@ -1,4 +1,4 @@
-import sqlFormatter from 'sql-formatter-plus'
+import sqlFormatter from 'sql-formatter-plus-plus'
export default function formatSql(sql?: string): string {
return sqlFormatter.format(sql || '', { uppercase: true })
diff --git a/ui/package.json b/ui/package.json
index f348dc3d37..703986826e 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -36,7 +36,7 @@
"react-use": "^14.2.0",
"single-spa": "^5.3.4",
"single-spa-react": "^2.14.0",
- "sql-formatter-plus": "^1.3.6",
+ "sql-formatter-plus-plus": "^1.4.0",
"string-template": "^1.0.0"
},
"scripts": {
diff --git a/ui/yarn.lock b/ui/yarn.lock
index d0eab62154..cd859c3f86 100644
--- a/ui/yarn.lock
+++ b/ui/yarn.lock
@@ -53,21 +53,12 @@
dependencies:
"@babel/highlight" "^7.8.3"
-"@babel/compat-data@^7.8.6":
- version "7.8.6"
- resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.8.6.tgz#7eeaa0dfa17e50c7d9c0832515eee09b56f04e35"
- integrity sha512-CurCIKPTkS25Mb8mz267vU95vy+TyUpnctEX2lV33xWNmHAfjruztgiPBbXZRh3xZZy1CYvGx6XfxyTVS+sk7Q==
+"@babel/compat-data@^7.9.0", "@babel/compat-data@^7.9.6":
+ version "7.9.6"
+ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.9.6.tgz#3f604c40e420131affe6f2c8052e9a275ae2049b"
+ integrity sha512-5QPTrNen2bm7RBc7dsOmcA5hbrS4O2Vhmk5XOL4zWW/zD/hV0iinpefDlkm+tBBy8kDtFaaeEvmAqt+nURAV2g==
dependencies:
- browserslist "^4.8.5"
- invariant "^2.2.4"
- semver "^5.5.0"
-
-"@babel/compat-data@^7.9.0":
- version "7.9.0"
- resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.9.0.tgz#04815556fc90b0c174abd2c0c1bb966faa036a6c"
- integrity sha512-zeFQrr+284Ekvd9e7KAX954LkapWiOmQtsfHirhxqfdlX6MEC32iRE+pqUGlYIBchdevaCwvzxWGSy/YBNI85g==
- dependencies:
- browserslist "^4.9.1"
+ browserslist "^4.11.1"
invariant "^2.2.4"
semver "^5.5.0"
@@ -94,42 +85,33 @@
source-map "^0.5.0"
"@babel/core@^7.1.0", "@babel/core@^7.4.5":
- version "7.8.7"
- resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.7.tgz#b69017d221ccdeb203145ae9da269d72cf102f3b"
- integrity sha512-rBlqF3Yko9cynC5CCFy6+K/w2N+Sq/ff2BPy+Krp7rHlABIr5epbA7OxVeKoMHB39LZOp1UY5SuLjy6uWi35yA==
+ version "7.9.6"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.6.tgz#d9aa1f580abf3b2286ef40b6904d390904c63376"
+ integrity sha512-nD3deLvbsApbHAHttzIssYqgb883yU/d9roe4RZymBCDaZryMJDbptVpEpeQuRh4BJ+SYI8le9YGxKvFEvl1Wg==
dependencies:
"@babel/code-frame" "^7.8.3"
- "@babel/generator" "^7.8.7"
- "@babel/helpers" "^7.8.4"
- "@babel/parser" "^7.8.7"
+ "@babel/generator" "^7.9.6"
+ "@babel/helper-module-transforms" "^7.9.0"
+ "@babel/helpers" "^7.9.6"
+ "@babel/parser" "^7.9.6"
"@babel/template" "^7.8.6"
- "@babel/traverse" "^7.8.6"
- "@babel/types" "^7.8.7"
+ "@babel/traverse" "^7.9.6"
+ "@babel/types" "^7.9.6"
convert-source-map "^1.7.0"
debug "^4.1.0"
gensync "^1.0.0-beta.1"
- json5 "^2.1.0"
+ json5 "^2.1.2"
lodash "^4.17.13"
resolve "^1.3.2"
semver "^5.4.1"
source-map "^0.5.0"
-"@babel/generator@^7.4.0", "@babel/generator@^7.8.6", "@babel/generator@^7.8.7":
- version "7.8.8"
- resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.8.tgz#cdcd58caab730834cee9eeadb729e833b625da3e"
- integrity sha512-HKyUVu69cZoclptr8t8U5b6sx6zoWjh8jiUhnuj3MpZuKT2dJ8zPTuiy31luq32swhI0SpwItCIlU8XW7BZeJg==
+"@babel/generator@^7.4.0", "@babel/generator@^7.9.0", "@babel/generator@^7.9.6":
+ version "7.9.6"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.6.tgz#5408c82ac5de98cda0d77d8124e99fa1f2170a43"
+ integrity sha512-+htwWKJbH2bL72HRluF8zumBxzuX0ZZUFl3JLNyoUjM/Ho8wnVpPXM6aUz8cfKDqQ/h7zHqKt4xzJteUosckqQ==
dependencies:
- "@babel/types" "^7.8.7"
- jsesc "^2.5.1"
- lodash "^4.17.13"
- source-map "^0.5.0"
-
-"@babel/generator@^7.9.0", "@babel/generator@^7.9.5":
- version "7.9.5"
- resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.5.tgz#27f0917741acc41e6eaaced6d68f96c3fa9afaf9"
- integrity sha512-GbNIxVB3ZJe3tLeDm1HSn2AhuD/mVcyLDpgtLXa5tplmWrJdF/elxB56XNqCuD6szyNkDi6wuoKXln3QeBmCHQ==
- dependencies:
- "@babel/types" "^7.9.5"
+ "@babel/types" "^7.9.6"
jsesc "^2.5.1"
lodash "^4.17.13"
source-map "^0.5.0"
@@ -158,14 +140,6 @@
"@babel/helper-module-imports" "^7.8.3"
"@babel/types" "^7.9.5"
-"@babel/helper-builder-react-jsx@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.8.3.tgz#dee98d7d79cc1f003d80b76fe01c7f8945665ff6"
- integrity sha512-JT8mfnpTkKNCboTqZsQTdGo3l3Ik3l7QIt9hh0O9DYiwVel37VoJpILKM4YFbP2euF32nkQSb+F9cUk9b7DDXQ==
- dependencies:
- "@babel/types" "^7.8.3"
- esutils "^2.0.0"
-
"@babel/helper-builder-react-jsx@^7.9.0":
version "7.9.0"
resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.9.0.tgz#16bf391990b57732700a3278d4d9a81231ea8d32"
@@ -174,36 +148,27 @@
"@babel/helper-annotate-as-pure" "^7.8.3"
"@babel/types" "^7.9.0"
-"@babel/helper-call-delegate@^7.8.7":
- version "7.8.7"
- resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.8.7.tgz#28a279c2e6c622a6233da548127f980751324cab"
- integrity sha512-doAA5LAKhsFCR0LAFIf+r2RSMmC+m8f/oQ+URnUET/rWeEzC0yTRmAGyWkD4sSu3xwbS7MYQ2u+xlt1V5R56KQ==
+"@babel/helper-compilation-targets@^7.8.7", "@babel/helper-compilation-targets@^7.9.6":
+ version "7.9.6"
+ resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.9.6.tgz#1e05b7ccc9d38d2f8b40b458b380a04dcfadd38a"
+ integrity sha512-x2Nvu0igO0ejXzx09B/1fGBxY9NXQlBW2kZsSxCJft+KHN8t9XWzIvFxtPHnBOAXpVsdxZKZFbRUC8TsNKajMw==
dependencies:
- "@babel/helper-hoist-variables" "^7.8.3"
- "@babel/traverse" "^7.8.3"
- "@babel/types" "^7.8.7"
-
-"@babel/helper-compilation-targets@^7.8.7":
- version "7.8.7"
- resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.7.tgz#dac1eea159c0e4bd46e309b5a1b04a66b53c1dde"
- integrity sha512-4mWm8DCK2LugIS+p1yArqvG1Pf162upsIsjE7cNBjez+NjliQpVhj20obE520nao0o14DaTnFJv+Fw5a0JpoUw==
- dependencies:
- "@babel/compat-data" "^7.8.6"
- browserslist "^4.9.1"
+ "@babel/compat-data" "^7.9.6"
+ browserslist "^4.11.1"
invariant "^2.2.4"
levenary "^1.1.1"
semver "^5.5.0"
-"@babel/helper-create-class-features-plugin@^7.8.3":
- version "7.8.6"
- resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.8.6.tgz#243a5b46e2f8f0f674dc1387631eb6b28b851de0"
- integrity sha512-klTBDdsr+VFFqaDHm5rR69OpEQtO2Qv8ECxHS1mNhJJvaHArR6a1xTf5K/eZW7eZpJbhCx3NW1Yt/sKsLXLblg==
+"@babel/helper-create-class-features-plugin@^7.8.3", "@babel/helper-create-class-features-plugin@^7.9.6":
+ version "7.9.6"
+ resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.9.6.tgz#965c8b0a9f051801fd9d3b372ca0ccf200a90897"
+ integrity sha512-6N9IeuyHvMBRyjNYOMJHrhwtu4WJMrYf8hVbEHD3pbbbmNOk1kmXSQs7bA4dYDUaIx4ZEzdnvo6NwC3WHd/Qow==
dependencies:
- "@babel/helper-function-name" "^7.8.3"
+ "@babel/helper-function-name" "^7.9.5"
"@babel/helper-member-expression-to-functions" "^7.8.3"
"@babel/helper-optimise-call-expression" "^7.8.3"
"@babel/helper-plugin-utils" "^7.8.3"
- "@babel/helper-replace-supers" "^7.8.6"
+ "@babel/helper-replace-supers" "^7.9.6"
"@babel/helper-split-export-declaration" "^7.8.3"
"@babel/helper-create-regexp-features-plugin@^7.8.3", "@babel/helper-create-regexp-features-plugin@^7.8.8":
@@ -232,16 +197,7 @@
"@babel/traverse" "^7.8.3"
"@babel/types" "^7.8.3"
-"@babel/helper-function-name@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz#eeeb665a01b1f11068e9fb86ad56a1cb1a824cca"
- integrity sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==
- dependencies:
- "@babel/helper-get-function-arity" "^7.8.3"
- "@babel/template" "^7.8.3"
- "@babel/types" "^7.8.3"
-
-"@babel/helper-function-name@^7.9.5":
+"@babel/helper-function-name@^7.8.3", "@babel/helper-function-name@^7.9.5":
version "7.9.5"
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz#2b53820d35275120e1874a82e5aabe1376920a5c"
integrity sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==
@@ -278,19 +234,6 @@
dependencies:
"@babel/types" "^7.8.3"
-"@babel/helper-module-transforms@^7.8.3":
- version "7.8.6"
- resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.8.6.tgz#6a13b5eecadc35692047073a64e42977b97654a4"
- integrity sha512-RDnGJSR5EFBJjG3deY0NiL0K9TO8SXxS9n/MPsbPK/s9LbQymuLNtlzvDiNS7IpecuL45cMeLVkA+HfmlrnkRg==
- dependencies:
- "@babel/helper-module-imports" "^7.8.3"
- "@babel/helper-replace-supers" "^7.8.6"
- "@babel/helper-simple-access" "^7.8.3"
- "@babel/helper-split-export-declaration" "^7.8.3"
- "@babel/template" "^7.8.6"
- "@babel/types" "^7.8.6"
- lodash "^4.17.13"
-
"@babel/helper-module-transforms@^7.9.0":
version "7.9.0"
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz#43b34dfe15961918707d247327431388e9fe96e5"
@@ -334,15 +277,15 @@
"@babel/traverse" "^7.8.3"
"@babel/types" "^7.8.3"
-"@babel/helper-replace-supers@^7.8.3", "@babel/helper-replace-supers@^7.8.6":
- version "7.8.6"
- resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz#5ada744fd5ad73203bf1d67459a27dcba67effc8"
- integrity sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA==
+"@babel/helper-replace-supers@^7.8.3", "@babel/helper-replace-supers@^7.8.6", "@babel/helper-replace-supers@^7.9.6":
+ version "7.9.6"
+ resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.9.6.tgz#03149d7e6a5586ab6764996cd31d6981a17e1444"
+ integrity sha512-qX+chbxkbArLyCImk3bWV+jB5gTNU/rsze+JlcF6Nf8tVTigPJSI1o1oBow/9Resa1yehUO9lIipsmu9oG4RzA==
dependencies:
"@babel/helper-member-expression-to-functions" "^7.8.3"
"@babel/helper-optimise-call-expression" "^7.8.3"
- "@babel/traverse" "^7.8.6"
- "@babel/types" "^7.8.6"
+ "@babel/traverse" "^7.9.6"
+ "@babel/types" "^7.9.6"
"@babel/helper-simple-access@^7.8.3":
version "7.8.3"
@@ -359,7 +302,7 @@
dependencies:
"@babel/types" "^7.8.3"
-"@babel/helper-validator-identifier@^7.9.5":
+"@babel/helper-validator-identifier@^7.9.0", "@babel/helper-validator-identifier@^7.9.5":
version "7.9.5"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz#90977a8e6fbf6b431a7dc31752eee233bf052d80"
integrity sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==
@@ -374,42 +317,28 @@
"@babel/traverse" "^7.8.3"
"@babel/types" "^7.8.3"
-"@babel/helpers@^7.8.4":
- version "7.8.4"
- resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.8.4.tgz#754eb3ee727c165e0a240d6c207de7c455f36f73"
- integrity sha512-VPbe7wcQ4chu4TDQjimHv/5tj73qz88o12EPkO2ValS2QiQS/1F2SsjyIGNnAD0vF/nZS6Cf9i+vW6HIlnaR8w==
+"@babel/helpers@^7.9.0", "@babel/helpers@^7.9.6":
+ version "7.9.6"
+ resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.9.6.tgz#092c774743471d0bb6c7de3ad465ab3d3486d580"
+ integrity sha512-tI4bUbldloLcHWoRUMAj4g1bF313M/o6fBKhIsb3QnGVPwRm9JsNf/gqMkQ7zjqReABiffPV6RWj7hEglID5Iw==
dependencies:
"@babel/template" "^7.8.3"
- "@babel/traverse" "^7.8.4"
- "@babel/types" "^7.8.3"
-
-"@babel/helpers@^7.9.0":
- version "7.9.2"
- resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.9.2.tgz#b42a81a811f1e7313b88cba8adc66b3d9ae6c09f"
- integrity sha512-JwLvzlXVPjO8eU9c/wF9/zOIN7X6h8DYf7mG4CiFRZRvZNKEF5dQ3H3V+ASkHoIB3mWhatgl5ONhyqHRI6MppA==
- dependencies:
- "@babel/template" "^7.8.3"
- "@babel/traverse" "^7.9.0"
- "@babel/types" "^7.9.0"
+ "@babel/traverse" "^7.9.6"
+ "@babel/types" "^7.9.6"
"@babel/highlight@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.8.3.tgz#28f173d04223eaaa59bc1d439a3836e6d1265797"
- integrity sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==
+ version "7.9.0"
+ resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.9.0.tgz#4e9b45ccb82b79607271b2979ad82c7b68163079"
+ integrity sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==
dependencies:
+ "@babel/helper-validator-identifier" "^7.9.0"
chalk "^2.0.0"
- esutils "^2.0.2"
js-tokens "^4.0.0"
-"@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.8.6", "@babel/parser@^7.8.7":
- version "7.8.8"
- resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.8.tgz#4c3b7ce36db37e0629be1f0d50a571d2f86f6cd4"
- integrity sha512-mO5GWzBPsPf6865iIbzNE0AvkKF3NE+2S3eRUpE+FE07BOAkXh6G+GW/Pj01hhXjve1WScbaIO4UlY1JKeqCcA==
-
-"@babel/parser@^7.7.0", "@babel/parser@^7.9.0":
- version "7.9.4"
- resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.4.tgz#68a35e6b0319bbc014465be43828300113f2f2e8"
- integrity sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA==
+"@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.7.0", "@babel/parser@^7.8.6", "@babel/parser@^7.9.0", "@babel/parser@^7.9.6":
+ version "7.9.6"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.6.tgz#3b1bbb30dabe600cd72db58720998376ff653bc7"
+ integrity sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q==
"@babel/plugin-proposal-async-generator-functions@^7.8.3":
version "7.8.3"
@@ -469,18 +398,10 @@
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-syntax-numeric-separator" "^7.8.3"
-"@babel/plugin-proposal-object-rest-spread@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.8.3.tgz#eb5ae366118ddca67bed583b53d7554cad9951bb"
- integrity sha512-8qvuPwU/xxUCt78HocNlv0mXXo0wdh9VT1R04WU8HGOfaOob26pF+9P5/lYjN/q7DHOX1bvX60hnhOvuQUJdbA==
- dependencies:
- "@babel/helper-plugin-utils" "^7.8.3"
- "@babel/plugin-syntax-object-rest-spread" "^7.8.0"
-
-"@babel/plugin-proposal-object-rest-spread@^7.9.0":
- version "7.9.5"
- resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.5.tgz#3fd65911306d8746014ec0d0cf78f0e39a149116"
- integrity sha512-VP2oXvAf7KCYTthbUHwBlewbl1Iq059f6seJGsxMizaCdgHIeczOr7FBqELhSqfkIl04Fi8okzWzl63UKbQmmg==
+"@babel/plugin-proposal-object-rest-spread@^7.9.0", "@babel/plugin-proposal-object-rest-spread@^7.9.6":
+ version "7.9.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.6.tgz#7a093586fcb18b08266eb1a7177da671ac575b63"
+ integrity sha512-Ga6/fhGqA9Hj+y6whNpPv8psyaK5xzrQwSPsGPloVkvmH+PqW1ixdnfJ9uIO06OjQNYol3PMnfmJ8vfZtkzF+A==
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-syntax-object-rest-spread" "^7.8.0"
@@ -502,14 +423,6 @@
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-syntax-optional-chaining" "^7.8.0"
-"@babel/plugin-proposal-optional-chaining@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.8.3.tgz#ae10b3214cb25f7adb1f3bc87ba42ca10b7e2543"
- integrity sha512-QIoIR9abkVn+seDE3OjA08jWcs3eZ9+wJCKSRgo3WdEU2csFYgdScb+8qHB3+WXsGJD55u+5hWCISI7ejXS+kg==
- dependencies:
- "@babel/helper-plugin-utils" "^7.8.3"
- "@babel/plugin-syntax-optional-chaining" "^7.8.0"
-
"@babel/plugin-proposal-unicode-property-regex@^7.4.4", "@babel/plugin-proposal-unicode-property-regex@^7.8.3":
version "7.8.8"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.8.tgz#ee3a95e90cdc04fe8cd92ec3279fa017d68a0d1d"
@@ -640,21 +553,7 @@
"@babel/helper-plugin-utils" "^7.8.3"
lodash "^4.17.13"
-"@babel/plugin-transform-classes@^7.8.6":
- version "7.8.6"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.8.6.tgz#77534447a477cbe5995ae4aee3e39fbc8090c46d"
- integrity sha512-k9r8qRay/R6v5aWZkrEclEhKO6mc1CCQr2dLsVHBmOQiMpN6I2bpjX3vgnldUWeEI1GHVNByULVxZ4BdP4Hmdg==
- dependencies:
- "@babel/helper-annotate-as-pure" "^7.8.3"
- "@babel/helper-define-map" "^7.8.3"
- "@babel/helper-function-name" "^7.8.3"
- "@babel/helper-optimise-call-expression" "^7.8.3"
- "@babel/helper-plugin-utils" "^7.8.3"
- "@babel/helper-replace-supers" "^7.8.6"
- "@babel/helper-split-export-declaration" "^7.8.3"
- globals "^11.1.0"
-
-"@babel/plugin-transform-classes@^7.9.0":
+"@babel/plugin-transform-classes@^7.9.0", "@babel/plugin-transform-classes@^7.9.5":
version "7.9.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.9.5.tgz#800597ddb8aefc2c293ed27459c1fcc935a26c2c"
integrity sha512-x2kZoIuLC//O5iA7PEvecB105o7TLzZo8ofBVhP79N+DO3jaX+KYfww9TQcfBEZD0nikNyYcGB1IKtRq36rdmg==
@@ -675,10 +574,10 @@
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
-"@babel/plugin-transform-destructuring@^7.8.3":
- version "7.8.8"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.8.8.tgz#fadb2bc8e90ccaf5658de6f8d4d22ff6272a2f4b"
- integrity sha512-eRJu4Vs2rmttFCdhPUM3bV0Yo/xPSdPw6ML9KHs/bjB4bLA5HXlbvYXPOD5yASodGod+krjYx21xm1QmL8dCJQ==
+"@babel/plugin-transform-destructuring@^7.8.3", "@babel/plugin-transform-destructuring@^7.9.5":
+ version "7.9.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.9.5.tgz#72c97cf5f38604aea3abf3b935b0e17b1db76a50"
+ integrity sha512-j3OEsGel8nHL/iusv/mRd5fYZ3DrOxWC82x0ogmdN/vHfAP4MYw+AFKYanzWlktNwikKvlzUV//afBW5FTp17Q==
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
@@ -713,13 +612,6 @@
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-syntax-flow" "^7.8.3"
-"@babel/plugin-transform-for-of@^7.8.6":
- version "7.8.6"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.8.6.tgz#a051bd1b402c61af97a27ff51b468321c7c2a085"
- integrity sha512-M0pw4/1/KI5WAxPsdcUL/w2LJ7o89YHN3yLkzNjg7Yl15GlVGgzHyCU+FMeAxevHGsLVmUqbirlUIKTafPmzdw==
- dependencies:
- "@babel/helper-plugin-utils" "^7.8.3"
-
"@babel/plugin-transform-for-of@^7.9.0":
version "7.9.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.9.0.tgz#0f260e27d3e29cd1bb3128da5e76c761aa6c108e"
@@ -749,71 +641,34 @@
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
-"@babel/plugin-transform-modules-amd@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.8.3.tgz#65606d44616b50225e76f5578f33c568a0b876a5"
- integrity sha512-MadJiU3rLKclzT5kBH4yxdry96odTUwuqrZM+GllFI/VhxfPz+k9MshJM+MwhfkCdxxclSbSBbUGciBngR+kEQ==
- dependencies:
- "@babel/helper-module-transforms" "^7.8.3"
- "@babel/helper-plugin-utils" "^7.8.3"
- babel-plugin-dynamic-import-node "^2.3.0"
-
-"@babel/plugin-transform-modules-amd@^7.9.0":
- version "7.9.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.9.0.tgz#19755ee721912cf5bb04c07d50280af3484efef4"
- integrity sha512-vZgDDF003B14O8zJy0XXLnPH4sg+9X5hFBBGN1V+B2rgrB+J2xIypSN6Rk9imB2hSTHQi5OHLrFWsZab1GMk+Q==
+"@babel/plugin-transform-modules-amd@^7.9.0", "@babel/plugin-transform-modules-amd@^7.9.6":
+ version "7.9.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.9.6.tgz#8539ec42c153d12ea3836e0e3ac30d5aae7b258e"
+ integrity sha512-zoT0kgC3EixAyIAU+9vfaUVKTv9IxBDSabgHoUCBP6FqEJ+iNiN7ip7NBKcYqbfUDfuC2mFCbM7vbu4qJgOnDw==
dependencies:
"@babel/helper-module-transforms" "^7.9.0"
"@babel/helper-plugin-utils" "^7.8.3"
- babel-plugin-dynamic-import-node "^2.3.0"
+ babel-plugin-dynamic-import-node "^2.3.3"
-"@babel/plugin-transform-modules-commonjs@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.8.3.tgz#df251706ec331bd058a34bdd72613915f82928a5"
- integrity sha512-JpdMEfA15HZ/1gNuB9XEDlZM1h/gF/YOH7zaZzQu2xCFRfwc01NXBMHHSTT6hRjlXJJs5x/bfODM3LiCk94Sxg==
- dependencies:
- "@babel/helper-module-transforms" "^7.8.3"
- "@babel/helper-plugin-utils" "^7.8.3"
- "@babel/helper-simple-access" "^7.8.3"
- babel-plugin-dynamic-import-node "^2.3.0"
-
-"@babel/plugin-transform-modules-commonjs@^7.9.0":
- version "7.9.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.0.tgz#e3e72f4cbc9b4a260e30be0ea59bdf5a39748940"
- integrity sha512-qzlCrLnKqio4SlgJ6FMMLBe4bySNis8DFn1VkGmOcxG9gqEyPIOzeQrA//u0HAKrWpJlpZbZMPB1n/OPa4+n8g==
+"@babel/plugin-transform-modules-commonjs@^7.9.0", "@babel/plugin-transform-modules-commonjs@^7.9.6":
+ version "7.9.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.6.tgz#64b7474a4279ee588cacd1906695ca721687c277"
+ integrity sha512-7H25fSlLcn+iYimmsNe3uK1at79IE6SKW9q0/QeEHTMC9MdOZ+4bA+T1VFB5fgOqBWoqlifXRzYD0JPdmIrgSQ==
dependencies:
"@babel/helper-module-transforms" "^7.9.0"
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/helper-simple-access" "^7.8.3"
- babel-plugin-dynamic-import-node "^2.3.0"
+ babel-plugin-dynamic-import-node "^2.3.3"
-"@babel/plugin-transform-modules-systemjs@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.8.3.tgz#d8bbf222c1dbe3661f440f2f00c16e9bb7d0d420"
- integrity sha512-8cESMCJjmArMYqa9AO5YuMEkE4ds28tMpZcGZB/jl3n0ZzlsxOAi3mC+SKypTfT8gjMupCnd3YiXCkMjj2jfOg==
- dependencies:
- "@babel/helper-hoist-variables" "^7.8.3"
- "@babel/helper-module-transforms" "^7.8.3"
- "@babel/helper-plugin-utils" "^7.8.3"
- babel-plugin-dynamic-import-node "^2.3.0"
-
-"@babel/plugin-transform-modules-systemjs@^7.9.0":
- version "7.9.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.9.0.tgz#e9fd46a296fc91e009b64e07ddaa86d6f0edeb90"
- integrity sha512-FsiAv/nao/ud2ZWy4wFacoLOm5uxl0ExSQ7ErvP7jpoihLR6Cq90ilOFyX9UXct3rbtKsAiZ9kFt5XGfPe/5SQ==
+"@babel/plugin-transform-modules-systemjs@^7.9.0", "@babel/plugin-transform-modules-systemjs@^7.9.6":
+ version "7.9.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.9.6.tgz#207f1461c78a231d5337a92140e52422510d81a4"
+ integrity sha512-NW5XQuW3N2tTHim8e1b7qGy7s0kZ2OH3m5octc49K1SdAKGxYxeIx7hiIz05kS1R2R+hOWcsr1eYwcGhrdHsrg==
dependencies:
"@babel/helper-hoist-variables" "^7.8.3"
"@babel/helper-module-transforms" "^7.9.0"
"@babel/helper-plugin-utils" "^7.8.3"
- babel-plugin-dynamic-import-node "^2.3.0"
-
-"@babel/plugin-transform-modules-umd@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.8.3.tgz#592d578ce06c52f5b98b02f913d653ffe972661a"
- integrity sha512-evhTyWhbwbI3/U6dZAnx/ePoV7H6OUG+OjiJFHmhr9FPn0VShjwC2kdxqIuQ/+1P50TMrneGzMeyMTFOjKSnAw==
- dependencies:
- "@babel/helper-module-transforms" "^7.8.3"
- "@babel/helper-plugin-utils" "^7.8.3"
+ babel-plugin-dynamic-import-node "^2.3.3"
"@babel/plugin-transform-modules-umd@^7.9.0":
version "7.9.0"
@@ -845,16 +700,7 @@
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/helper-replace-supers" "^7.8.3"
-"@babel/plugin-transform-parameters@^7.8.7":
- version "7.8.8"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.8.8.tgz#0381de466c85d5404565243660c4496459525daf"
- integrity sha512-hC4Ld/Ulpf1psQciWWwdnUspQoQco2bMzSrwU6TmzRlvoYQe4rQFy9vnCZDTlVeCQj0JPfL+1RX0V8hCJvkgBA==
- dependencies:
- "@babel/helper-call-delegate" "^7.8.7"
- "@babel/helper-get-function-arity" "^7.8.3"
- "@babel/helper-plugin-utils" "^7.8.3"
-
-"@babel/plugin-transform-parameters@^7.9.5":
+"@babel/plugin-transform-parameters@^7.8.7", "@babel/plugin-transform-parameters@^7.9.5":
version "7.9.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.9.5.tgz#173b265746f5e15b2afe527eeda65b73623a0795"
integrity sha512-0+1FhHnMfj6lIIhVvS4KGQJeuhe1GI//h5uptK4PvLt+BGBxsoUJbd3/IW002yk//6sZPlFgsG1hY6OHLcy6kA==
@@ -870,11 +716,10 @@
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-transform-react-constant-elements@^7.0.0":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.8.3.tgz#784c25294bddaad2323eb4ff0c9f4a3f6c87d6bc"
- integrity sha512-glrzN2U+egwRfkNFtL34xIBYTxbbUF2qJTP8HD3qETBBqzAWSeNB821X0GjU06+dNpq/UyCIjI72FmGE5NNkQQ==
+ version "7.9.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.9.0.tgz#a75abc936a3819edec42d3386d9f1c93f28d9d9e"
+ integrity sha512-wXMXsToAUOxJuBBEHajqKLFWcCkOSLshTI2ChCFFj1zDd7od4IOxiwLCOObNUvOpkxLpjIuaIdBMmNt6ocCPAw==
dependencies:
- "@babel/helper-annotate-as-pure" "^7.8.3"
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-transform-react-display-name@7.8.3", "@babel/plugin-transform-react-display-name@^7.8.3":
@@ -893,14 +738,6 @@
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-syntax-jsx" "^7.8.3"
-"@babel/plugin-transform-react-jsx-self@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.8.3.tgz#c4f178b2aa588ecfa8d077ea80d4194ee77ed702"
- integrity sha512-01OT7s5oa0XTLf2I8XGsL8+KqV9lx3EZV+jxn/L2LQ97CGKila2YMroTkCEIE0HV/FF7CMSRsIAybopdN9NTdg==
- dependencies:
- "@babel/helper-plugin-utils" "^7.8.3"
- "@babel/plugin-syntax-jsx" "^7.8.3"
-
"@babel/plugin-transform-react-jsx-self@^7.9.0":
version "7.9.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.9.0.tgz#f4f26a325820205239bb915bad8e06fcadabb49b"
@@ -909,14 +746,6 @@
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-syntax-jsx" "^7.8.3"
-"@babel/plugin-transform-react-jsx-source@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.8.3.tgz#951e75a8af47f9f120db731be095d2b2c34920e0"
- integrity sha512-PLMgdMGuVDtRS/SzjNEQYUT8f4z1xb2BAT54vM1X5efkVuYBf5WyGUMbpmARcfq3NaglIwz08UVQK4HHHbC6ag==
- dependencies:
- "@babel/helper-plugin-utils" "^7.8.3"
- "@babel/plugin-syntax-jsx" "^7.8.3"
-
"@babel/plugin-transform-react-jsx-source@^7.9.0":
version "7.9.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.9.0.tgz#89ef93025240dd5d17d3122294a093e5e0183de0"
@@ -925,16 +754,7 @@
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-syntax-jsx" "^7.8.3"
-"@babel/plugin-transform-react-jsx@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.8.3.tgz#4220349c0390fdefa505365f68c103562ab2fc4a"
- integrity sha512-r0h+mUiyL595ikykci+fbwm9YzmuOrUBi0b+FDIKmi3fPQyFokWVEMJnRWHJPPQEjyFJyna9WZC6Viv6UHSv1g==
- dependencies:
- "@babel/helper-builder-react-jsx" "^7.8.3"
- "@babel/helper-plugin-utils" "^7.8.3"
- "@babel/plugin-syntax-jsx" "^7.8.3"
-
-"@babel/plugin-transform-react-jsx@^7.9.1":
+"@babel/plugin-transform-react-jsx@^7.9.1", "@babel/plugin-transform-react-jsx@^7.9.4":
version "7.9.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.9.4.tgz#86f576c8540bd06d0e95e0b61ea76d55f6cbd03f"
integrity sha512-Mjqf3pZBNLt854CK0C/kRuXAnE6H/bo7xYojP+WGtX8glDGSibcwnsWwhwoSuRg0+EBnxPC1ouVnuetUIlPSAw==
@@ -1006,11 +826,11 @@
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-transform-typescript@^7.9.0":
- version "7.9.4"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.9.4.tgz#4bb4dde4f10bbf2d787fce9707fb09b483e33359"
- integrity sha512-yeWeUkKx2auDbSxRe8MusAG+n4m9BFY/v+lPjmQDgOFX5qnySkUY5oXzkp6FwPdsYqnKay6lorXYdC0n3bZO7w==
+ version "7.9.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.9.6.tgz#2248971416a506fc78278fc0c0ea3179224af1e9"
+ integrity sha512-8OvsRdvpt3Iesf2qsAn+YdlwAJD7zJ+vhFZmDCa4b8dTp7MmHtKk5FF2mCsGxjZwuwsy/yIIay/nLmxST1ctVQ==
dependencies:
- "@babel/helper-create-class-features-plugin" "^7.8.3"
+ "@babel/helper-create-class-features-plugin" "^7.9.6"
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-syntax-typescript" "^7.8.3"
@@ -1022,7 +842,7 @@
"@babel/helper-create-regexp-features-plugin" "^7.8.3"
"@babel/helper-plugin-utils" "^7.8.3"
-"@babel/polyfill@^7.6.0":
+"@babel/polyfill@^7.7.0":
version "7.8.7"
resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.8.7.tgz#151ec24c7135481336168c3bd8b8bf0cf91c032f"
integrity sha512-LeSfP9bNZH2UOZgcGcZ0PIHUt1ZuHub1L3CVmEyqLxCeDLm4C5Gi8jRH8ZX2PNpDhQCo0z6y/+DIs2JlliXW8w==
@@ -1097,26 +917,28 @@
semver "^5.5.0"
"@babel/preset-env@^7.4.5":
- version "7.8.7"
- resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.8.7.tgz#1fc7d89c7f75d2d70c2b6768de6c2e049b3cb9db"
- integrity sha512-BYftCVOdAYJk5ASsznKAUl53EMhfBbr8CJ1X+AJLfGPscQkwJFiaV/Wn9DPH/7fzm2v6iRYJKYHSqyynTGw0nw==
+ version "7.9.6"
+ resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.9.6.tgz#df063b276c6455ec6fcfc6e53aacc38da9b0aea6"
+ integrity sha512-0gQJ9RTzO0heXOhzftog+a/WyOuqMrAIugVYxMYf83gh1CQaQDjMtsOpqOwXyDL/5JcWsrCm8l4ju8QC97O7EQ==
dependencies:
- "@babel/compat-data" "^7.8.6"
- "@babel/helper-compilation-targets" "^7.8.7"
+ "@babel/compat-data" "^7.9.6"
+ "@babel/helper-compilation-targets" "^7.9.6"
"@babel/helper-module-imports" "^7.8.3"
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-proposal-async-generator-functions" "^7.8.3"
"@babel/plugin-proposal-dynamic-import" "^7.8.3"
"@babel/plugin-proposal-json-strings" "^7.8.3"
"@babel/plugin-proposal-nullish-coalescing-operator" "^7.8.3"
- "@babel/plugin-proposal-object-rest-spread" "^7.8.3"
+ "@babel/plugin-proposal-numeric-separator" "^7.8.3"
+ "@babel/plugin-proposal-object-rest-spread" "^7.9.6"
"@babel/plugin-proposal-optional-catch-binding" "^7.8.3"
- "@babel/plugin-proposal-optional-chaining" "^7.8.3"
+ "@babel/plugin-proposal-optional-chaining" "^7.9.0"
"@babel/plugin-proposal-unicode-property-regex" "^7.8.3"
"@babel/plugin-syntax-async-generators" "^7.8.0"
"@babel/plugin-syntax-dynamic-import" "^7.8.0"
"@babel/plugin-syntax-json-strings" "^7.8.0"
"@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0"
+ "@babel/plugin-syntax-numeric-separator" "^7.8.0"
"@babel/plugin-syntax-object-rest-spread" "^7.8.0"
"@babel/plugin-syntax-optional-catch-binding" "^7.8.0"
"@babel/plugin-syntax-optional-chaining" "^7.8.0"
@@ -1125,24 +947,24 @@
"@babel/plugin-transform-async-to-generator" "^7.8.3"
"@babel/plugin-transform-block-scoped-functions" "^7.8.3"
"@babel/plugin-transform-block-scoping" "^7.8.3"
- "@babel/plugin-transform-classes" "^7.8.6"
+ "@babel/plugin-transform-classes" "^7.9.5"
"@babel/plugin-transform-computed-properties" "^7.8.3"
- "@babel/plugin-transform-destructuring" "^7.8.3"
+ "@babel/plugin-transform-destructuring" "^7.9.5"
"@babel/plugin-transform-dotall-regex" "^7.8.3"
"@babel/plugin-transform-duplicate-keys" "^7.8.3"
"@babel/plugin-transform-exponentiation-operator" "^7.8.3"
- "@babel/plugin-transform-for-of" "^7.8.6"
+ "@babel/plugin-transform-for-of" "^7.9.0"
"@babel/plugin-transform-function-name" "^7.8.3"
"@babel/plugin-transform-literals" "^7.8.3"
"@babel/plugin-transform-member-expression-literals" "^7.8.3"
- "@babel/plugin-transform-modules-amd" "^7.8.3"
- "@babel/plugin-transform-modules-commonjs" "^7.8.3"
- "@babel/plugin-transform-modules-systemjs" "^7.8.3"
- "@babel/plugin-transform-modules-umd" "^7.8.3"
+ "@babel/plugin-transform-modules-amd" "^7.9.6"
+ "@babel/plugin-transform-modules-commonjs" "^7.9.6"
+ "@babel/plugin-transform-modules-systemjs" "^7.9.6"
+ "@babel/plugin-transform-modules-umd" "^7.9.0"
"@babel/plugin-transform-named-capturing-groups-regex" "^7.8.3"
"@babel/plugin-transform-new-target" "^7.8.3"
"@babel/plugin-transform-object-super" "^7.8.3"
- "@babel/plugin-transform-parameters" "^7.8.7"
+ "@babel/plugin-transform-parameters" "^7.9.5"
"@babel/plugin-transform-property-literals" "^7.8.3"
"@babel/plugin-transform-regenerator" "^7.8.7"
"@babel/plugin-transform-reserved-words" "^7.8.3"
@@ -1152,8 +974,9 @@
"@babel/plugin-transform-template-literals" "^7.8.3"
"@babel/plugin-transform-typeof-symbol" "^7.8.4"
"@babel/plugin-transform-unicode-regex" "^7.8.3"
- "@babel/types" "^7.8.7"
- browserslist "^4.8.5"
+ "@babel/preset-modules" "^0.1.3"
+ "@babel/types" "^7.9.6"
+ browserslist "^4.11.1"
core-js-compat "^3.6.2"
invariant "^2.2.2"
levenary "^1.1.1"
@@ -1183,15 +1006,16 @@
"@babel/plugin-transform-react-jsx-source" "^7.9.0"
"@babel/preset-react@^7.0.0":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.8.3.tgz#23dc63f1b5b0751283e04252e78cf1d6589273d2"
- integrity sha512-9hx0CwZg92jGb7iHYQVgi0tOEHP/kM60CtWJQnmbATSPIQQ2xYzfoCI3EdqAhFBeeJwYMdWQuDUHMsuDbH9hyQ==
+ version "7.9.4"
+ resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.9.4.tgz#c6c97693ac65b6b9c0b4f25b948a8f665463014d"
+ integrity sha512-AxylVB3FXeOTQXNXyiuAQJSvss62FEotbX2Pzx3K/7c+MKJMdSg6Ose6QYllkdCFA8EInCJVw7M/o5QbLuA4ZQ==
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-transform-react-display-name" "^7.8.3"
- "@babel/plugin-transform-react-jsx" "^7.8.3"
- "@babel/plugin-transform-react-jsx-self" "^7.8.3"
- "@babel/plugin-transform-react-jsx-source" "^7.8.3"
+ "@babel/plugin-transform-react-jsx" "^7.9.4"
+ "@babel/plugin-transform-react-jsx-development" "^7.9.0"
+ "@babel/plugin-transform-react-jsx-self" "^7.9.0"
+ "@babel/plugin-transform-react-jsx-source" "^7.9.0"
"@babel/preset-typescript@7.9.0":
version "7.9.0"
@@ -1202,9 +1026,9 @@
"@babel/plugin-transform-typescript" "^7.9.0"
"@babel/runtime-corejs3@^7.8.3":
- version "7.9.2"
- resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.9.2.tgz#26fe4aa77e9f1ecef9b776559bbb8e84d34284b7"
- integrity sha512-HHxmgxbIzOfFlZ+tdeRKtaxWOMUoCG5Mu3wKeUmOxjYrwb3AAHgnmtCUbPPK11/raIWLIBK250t8E2BPO0p7jA==
+ version "7.9.6"
+ resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.9.6.tgz#67aded13fffbbc2cb93247388cf84d77a4be9a71"
+ integrity sha512-6toWAfaALQjt3KMZQc6fABqZwUDDuWzz+cAfPhqyEnzxvdWOAkjwPNxgF8xlmo7OWLsSjaKjsskpKHRLaMArOA==
dependencies:
core-js-pure "^3.0.0"
regenerator-runtime "^0.13.4"
@@ -1216,10 +1040,10 @@
dependencies:
regenerator-runtime "^0.13.4"
-"@babel/runtime@^7.0.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7":
- version "7.8.7"
- resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.8.7.tgz#8fefce9802db54881ba59f90bb28719b4996324d"
- integrity sha512-+AATMUFppJDw6aiR5NVPHqIQBlV/Pj8wY/EZH+lmvRdUo9xBaz/rF3alAwFJQavvKfeOlPE7oaaDHVbcySbCsg==
+"@babel/runtime@^7.0.0", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
+ version "7.9.6"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.6.tgz#a9102eb5cadedf3f31d08a9ecf294af7827ea29f"
+ integrity sha512-64AF1xY3OAkFHqOb9s4jpgk1Mm5vDZ4L3acHvAml+53nO1XbXLuDodsVpO4OIUsmemlUHMxNdYMNJmsvOwLrvQ==
dependencies:
regenerator-runtime "^0.13.4"
@@ -1230,6 +1054,13 @@
dependencies:
regenerator-runtime "^0.13.4"
+"@babel/runtime@^7.3.1", "@babel/runtime@^7.5.5":
+ version "7.8.7"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.8.7.tgz#8fefce9802db54881ba59f90bb28719b4996324d"
+ integrity sha512-+AATMUFppJDw6aiR5NVPHqIQBlV/Pj8wY/EZH+lmvRdUo9xBaz/rF3alAwFJQavvKfeOlPE7oaaDHVbcySbCsg==
+ dependencies:
+ regenerator-runtime "^0.13.4"
+
"@babel/template@^7.4.0", "@babel/template@^7.8.3", "@babel/template@^7.8.6":
version "7.8.6"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b"
@@ -1239,49 +1070,25 @@
"@babel/parser" "^7.8.6"
"@babel/types" "^7.8.6"
-"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.4", "@babel/traverse@^7.8.6":
- version "7.8.6"
- resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.6.tgz#acfe0c64e1cd991b3e32eae813a6eb564954b5ff"
- integrity sha512-2B8l0db/DPi8iinITKuo7cbPznLCEk0kCxDoB9/N6gGNg/gxOXiR/IcymAFPiBwk5w6TtQ27w4wpElgp9btR9A==
- dependencies:
- "@babel/code-frame" "^7.8.3"
- "@babel/generator" "^7.8.6"
- "@babel/helper-function-name" "^7.8.3"
- "@babel/helper-split-export-declaration" "^7.8.3"
- "@babel/parser" "^7.8.6"
- "@babel/types" "^7.8.6"
- debug "^4.1.0"
- globals "^11.1.0"
- lodash "^4.17.13"
-
-"@babel/traverse@^7.7.0", "@babel/traverse@^7.9.0":
- version "7.9.5"
- resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.5.tgz#6e7c56b44e2ac7011a948c21e283ddd9d9db97a2"
- integrity sha512-c4gH3jsvSuGUezlP6rzSJ6jf8fYjLj3hsMZRx/nX0h+fmHN0w+ekubRrHPqnMec0meycA2nwCsJ7dC8IPem2FQ==
+"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.7.0", "@babel/traverse@^7.8.3", "@babel/traverse@^7.9.0", "@babel/traverse@^7.9.6":
+ version "7.9.6"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.6.tgz#5540d7577697bf619cc57b92aa0f1c231a94f442"
+ integrity sha512-b3rAHSjbxy6VEAvlxM8OV/0X4XrG72zoxme6q1MOoe2vd0bEc+TwayhuC1+Dfgqh1QEG+pj7atQqvUprHIccsg==
dependencies:
"@babel/code-frame" "^7.8.3"
- "@babel/generator" "^7.9.5"
+ "@babel/generator" "^7.9.6"
"@babel/helper-function-name" "^7.9.5"
"@babel/helper-split-export-declaration" "^7.8.3"
- "@babel/parser" "^7.9.0"
- "@babel/types" "^7.9.5"
+ "@babel/parser" "^7.9.6"
+ "@babel/types" "^7.9.6"
debug "^4.1.0"
globals "^11.1.0"
lodash "^4.17.13"
-"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.8.7":
- version "7.8.7"
- resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.7.tgz#1fc9729e1acbb2337d5b6977a63979b4819f5d1d"
- integrity sha512-k2TreEHxFA4CjGkL+GYjRyx35W0Mr7DP5+9q6WMkyKXB+904bYmG40syjMFV0oLlhhFCwWl0vA0DyzTDkwAiJw==
- dependencies:
- esutils "^2.0.2"
- lodash "^4.17.13"
- to-fast-properties "^2.0.0"
-
-"@babel/types@^7.7.0", "@babel/types@^7.9.0", "@babel/types@^7.9.5":
- version "7.9.5"
- resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.5.tgz#89231f82915a8a566a703b3b20133f73da6b9444"
- integrity sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==
+"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0", "@babel/types@^7.9.5", "@babel/types@^7.9.6":
+ version "7.9.6"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.6.tgz#2c5502b427251e9de1bd2dff95add646d95cc9f7"
+ integrity sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==
dependencies:
"@babel/helper-validator-identifier" "^7.9.5"
lodash "^4.17.13"
@@ -1671,9 +1478,9 @@
loader-utils "^1.2.3"
"@types/babel__core@^7.1.0":
- version "7.1.6"
- resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.6.tgz#16ff42a5ae203c9af1c6e190ed1f30f83207b610"
- integrity sha512-tTnhWszAqvXnhW7m5jQU9PomXSiKXk2sFxpahXvI20SZKu9ylPi8WtIxueZ6ehDWikPT0jeFujMj3X4ZHuf3Tg==
+ version "7.1.7"
+ resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.7.tgz#1dacad8840364a57c98d0dd4855c6dd3752c6b89"
+ integrity sha512-RL62NqSFPCDK2FM1pSDH0scHpJvsXtZNiYlMB73DgPBaG1E38ZYVL+ei5EkWRbr+KC4YNiAUNBnRj+bgwpgjMw==
dependencies:
"@babel/parser" "^7.1.0"
"@babel/types" "^7.0.0"
@@ -1697,9 +1504,9 @@
"@babel/types" "^7.0.0"
"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6":
- version "7.0.9"
- resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.9.tgz#be82fab304b141c3eee81a4ce3b034d0eba1590a"
- integrity sha512-jEFQ8L1tuvPjOI8lnpaf73oCJe+aoxL6ygqSy6c8LcW98zaC+4mzWuQIRCEvKeCOu+lbqdXcg4Uqmm1S8AP1tw==
+ version "7.0.11"
+ resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.11.tgz#1ae3010e8bf8851d324878b42acec71986486d18"
+ integrity sha512-ddHK5icION5U6q11+tV2f9Mo6CZVuT8GJKld2q9LqHSZbvLbH34Kcu2yFGckZut453+eQU6btIA3RihmnRgI+Q==
dependencies:
"@babel/types" "^7.3.0"
@@ -2001,9 +1808,9 @@
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
"@types/node@*":
- version "13.9.1"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-13.9.1.tgz#96f606f8cd67fb018847d9b61e93997dabdefc72"
- integrity sha512-E6M6N0blf/jiZx8Q3nb0vNaswQeEyn0XlupO+xN6DtJ6r6IT4nXrTry7zhIfYvFCl3/8Cu6WIysmUBKiqV0bqQ==
+ version "14.0.1"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.1.tgz#5d93e0a099cd0acd5ef3d5bde3c086e1f49ff68c"
+ integrity sha512-FAYBGwC+W6F9+huFIDtn43cpy7+SzG+atzRiTfdp3inUKL2hXnd4rG8hylJLIh4+hqrQy1P17kvJByE/z825hA==
"@types/node@^13.11.1":
version "13.11.1"
@@ -2064,53 +1871,53 @@
integrity sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==
"@types/yargs@^13.0.0":
- version "13.0.8"
- resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.8.tgz#a38c22def2f1c2068f8971acb3ea734eb3c64a99"
- integrity sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA==
+ version "13.0.9"
+ resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.9.tgz#44028e974343c7afcf3960f1a2b1099c39a7b5e1"
+ integrity sha512-xrvhZ4DZewMDhoH1utLtOAwYQy60eYFoXeje30TzM3VOvQlBwQaEpKFq5m34k1wOw2AKIi2pwtiAjdmhvlBUzg==
dependencies:
"@types/yargs-parser" "*"
"@typescript-eslint/eslint-plugin@^2.10.0":
- version "2.28.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.28.0.tgz#4431bc6d3af41903e5255770703d4e55a0ccbdec"
- integrity sha512-w0Ugcq2iatloEabQP56BRWJowliXUP5Wv6f9fKzjJmDW81hOTBxRoJ4LoEOxRpz9gcY51Libytd2ba3yLmSOfg==
+ version "2.33.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.33.0.tgz#d6c8319d5011b4783bb3d2dadf105d8bdd499bd5"
+ integrity sha512-QV6P32Btu1sCI/kTqjTNI/8OpCYyvlGjW5vD8MpTIg+HGE5S88HtT1G+880M4bXlvXj/NjsJJG0aGcVh0DdbeQ==
dependencies:
- "@typescript-eslint/experimental-utils" "2.28.0"
+ "@typescript-eslint/experimental-utils" "2.33.0"
functional-red-black-tree "^1.0.1"
regexpp "^3.0.0"
tsutils "^3.17.1"
-"@typescript-eslint/experimental-utils@2.28.0":
- version "2.28.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.28.0.tgz#1fd0961cd8ef6522687b4c562647da6e71f8833d"
- integrity sha512-4SL9OWjvFbHumM/Zh/ZeEjUFxrYKtdCi7At4GyKTbQlrj1HcphIDXlje4Uu4cY+qzszR5NdVin4CCm6AXCjd6w==
+"@typescript-eslint/experimental-utils@2.33.0":
+ version "2.33.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.33.0.tgz#000f1e5f344fbea1323dc91cc174805d75f99a03"
+ integrity sha512-qzPM2AuxtMrRq78LwyZa8Qn6gcY8obkIrBs1ehqmQADwkYzTE1Pb4y2W+U3rE/iFkSWcWHG2LS6MJfj6SmHApg==
dependencies:
"@types/json-schema" "^7.0.3"
- "@typescript-eslint/typescript-estree" "2.28.0"
+ "@typescript-eslint/typescript-estree" "2.33.0"
eslint-scope "^5.0.0"
eslint-utils "^2.0.0"
"@typescript-eslint/parser@^2.10.0":
- version "2.28.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.28.0.tgz#bb761286efd2b0714761cab9d0ee5847cf080385"
- integrity sha512-RqPybRDquui9d+K86lL7iPqH6Dfp9461oyqvlXMNtap+PyqYbkY5dB7LawQjDzot99fqzvS0ZLZdfe+1Bt3Jgw==
+ version "2.33.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.33.0.tgz#395c0ef229ebef883608f8632a34f0acf02b9bdd"
+ integrity sha512-AUtmwUUhJoH6yrtxZMHbRUEMsC2G6z5NSxg9KsROOGqNXasM71I8P2NihtumlWTUCRld70vqIZ6Pm4E5PAziEA==
dependencies:
"@types/eslint-visitor-keys" "^1.0.0"
- "@typescript-eslint/experimental-utils" "2.28.0"
- "@typescript-eslint/typescript-estree" "2.28.0"
+ "@typescript-eslint/experimental-utils" "2.33.0"
+ "@typescript-eslint/typescript-estree" "2.33.0"
eslint-visitor-keys "^1.1.0"
-"@typescript-eslint/typescript-estree@2.28.0":
- version "2.28.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.28.0.tgz#d34949099ff81092c36dc275b6a1ea580729ba00"
- integrity sha512-HDr8MP9wfwkiuqzRVkuM3BeDrOC4cKbO5a6BymZBHUt5y/2pL0BXD6I/C/ceq2IZoHWhcASk+5/zo+dwgu9V8Q==
+"@typescript-eslint/typescript-estree@2.33.0":
+ version "2.33.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.33.0.tgz#33504c050ccafd38f397a645d4e9534d2eccbb5c"
+ integrity sha512-d8rY6/yUxb0+mEwTShCQF2zYQdLlqihukNfG9IUlLYz5y1CH6G/9XYbrxQLq3Z14RNvkCC6oe+OcFlyUpwUbkg==
dependencies:
debug "^4.1.1"
eslint-visitor-keys "^1.1.0"
glob "^7.1.6"
is-glob "^4.0.1"
lodash "^4.17.15"
- semver "^6.3.0"
+ semver "^7.3.2"
tsutils "^3.17.1"
"@uifabric/foundation@^7.5.23":
@@ -2413,9 +2220,9 @@ acorn@^6.0.1, acorn@^6.0.4, acorn@^6.2.1:
integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==
acorn@^7.1.1:
- version "7.1.1"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.1.tgz#e35668de0b402f359de515c5482a1ab9f89a69bf"
- integrity sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.2.0.tgz#17ea7e40d7c8640ff54a694c889c26f31704effe"
+ integrity sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ==
add-dom-event-listener@^1.1.0:
version "1.1.0"
@@ -2459,9 +2266,9 @@ ajv-keywords@^3.1.0, ajv-keywords@^3.4.1:
integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==
ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.0, ajv@^6.5.5:
- version "6.12.0"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.0.tgz#06d60b96d87b8454a5adaba86e7854da629db4b7"
- integrity sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==
+ version "6.12.2"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.2.tgz#c629c5eced17baf314437918d2da88c99d5958cd"
+ integrity sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==
dependencies:
fast-deep-equal "^3.1.1"
fast-json-stable-stringify "^2.0.0"
@@ -2905,17 +2712,17 @@ atob@^2.1.2:
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
autoprefixer@^9.6.1:
- version "9.7.4"
- resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.7.4.tgz#f8bf3e06707d047f0641d87aee8cfb174b2a5378"
- integrity sha512-g0Ya30YrMBAEZk60lp+qfX5YQllG+S5W3GYCFvyHTvhOki0AEQJLPEcIuGRsqVwLi8FvXPVtwTGhfr38hVpm0g==
+ version "9.7.6"
+ resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.7.6.tgz#63ac5bbc0ce7934e6997207d5bb00d68fa8293a4"
+ integrity sha512-F7cYpbN7uVVhACZTeeIeealwdGM6wMtfWARVLTy5xmKtgVdBNJvbDRoCK3YO1orcs7gv/KwYlb3iXwu9Ug9BkQ==
dependencies:
- browserslist "^4.8.3"
- caniuse-lite "^1.0.30001020"
+ browserslist "^4.11.1"
+ caniuse-lite "^1.0.30001039"
chalk "^2.4.2"
normalize-range "^0.1.2"
num2fraction "^1.2.2"
- postcss "^7.0.26"
- postcss-value-parser "^4.0.2"
+ postcss "^7.0.27"
+ postcss-value-parser "^4.0.3"
aws-sign2@~0.7.0:
version "0.7.0"
@@ -2998,6 +2805,13 @@ babel-plugin-dynamic-import-node@^2.3.0:
dependencies:
object.assign "^4.1.0"
+babel-plugin-dynamic-import-node@^2.3.3:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3"
+ integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==
+ dependencies:
+ object.assign "^4.1.0"
+
babel-plugin-import@^1.13.0:
version "1.13.0"
resolved "https://registry.yarnpkg.com/babel-plugin-import/-/babel-plugin-import-1.13.0.tgz#c532fd533df9db53b47d4d4db3676090fc5c07a5"
@@ -3189,11 +3003,16 @@ bluebird@^3.5.5:
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
-bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0:
+bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.4.0:
version "4.11.8"
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f"
integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==
+bn.js@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.1.tgz#48efc4031a9c4041b9c99c6941d903463ab62eb5"
+ integrity sha512-IUTD/REb78Z2eodka1QZyyEk66pciRcP6Sroka0aI3tG/iwIdYLrBD62RsubR7vqdt3WyX8p4jxeatzmRSphtA==
+
body-parser@1.19.0:
version "1.19.0"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
@@ -3311,7 +3130,7 @@ browserify-des@^1.0.0:
inherits "^2.0.1"
safe-buffer "^5.1.2"
-browserify-rsa@^4.0.0:
+browserify-rsa@^4.0.0, browserify-rsa@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524"
integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=
@@ -3320,17 +3139,18 @@ browserify-rsa@^4.0.0:
randombytes "^2.0.1"
browserify-sign@^4.0.0:
- version "4.0.4"
- resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298"
- integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=
- dependencies:
- bn.js "^4.1.1"
- browserify-rsa "^4.0.0"
- create-hash "^1.1.0"
- create-hmac "^1.1.2"
- elliptic "^6.0.0"
- inherits "^2.0.1"
- parse-asn1 "^5.0.0"
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.1.0.tgz#4fe971b379a5aeb4925e06779f9fa1f41d249d70"
+ integrity sha512-VYxo7cDCeYUoBZ0ZCy4UyEUCP3smyBd4DRQM5nrFS1jJjPJjX7rP3oLRpPoWfkhQfyJ0I9ZbHbKafrFD/SGlrg==
+ dependencies:
+ bn.js "^5.1.1"
+ browserify-rsa "^4.0.1"
+ create-hash "^1.2.0"
+ create-hmac "^1.1.7"
+ elliptic "^6.5.2"
+ inherits "^2.0.4"
+ parse-asn1 "^5.1.5"
+ readable-stream "^3.6.0"
browserify-zlib@^0.2.0:
version "0.2.0"
@@ -3349,22 +3169,13 @@ browserslist@4.10.0:
node-releases "^1.1.52"
pkg-up "^3.1.0"
-browserslist@^4.0.0, browserslist@^4.6.4, browserslist@^4.8.3, browserslist@^4.8.5, browserslist@^4.9.1:
- version "4.9.1"
- resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.9.1.tgz#01ffb9ca31a1aef7678128fc6a2253316aa7287c"
- integrity sha512-Q0DnKq20End3raFulq6Vfp1ecB9fh8yUNV55s8sekaDDeqBaCtWlRHCUdaWyUeSSBJM7IbM6HcsyaeYqgeDhnw==
+browserslist@^4.0.0, browserslist@^4.11.1, browserslist@^4.6.2, browserslist@^4.6.4, browserslist@^4.8.5, browserslist@^4.9.1:
+ version "4.12.0"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.12.0.tgz#06c6d5715a1ede6c51fc39ff67fd647f740b656d"
+ integrity sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg==
dependencies:
- caniuse-lite "^1.0.30001030"
- electron-to-chromium "^1.3.363"
- node-releases "^1.1.50"
-
-browserslist@^4.6.2:
- version "4.11.1"
- resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.11.1.tgz#92f855ee88d6e050e7e7311d987992014f1a1f1b"
- integrity sha512-DCTr3kDrKEYNw6Jb9HFxVLQNaue8z+0ZfRBRjmCunKDEXEBajKDj2Y+Uelg+Pi29OnvaSGwjOsnRyNEkXzHg5g==
- dependencies:
- caniuse-lite "^1.0.30001038"
- electron-to-chromium "^1.3.390"
+ caniuse-lite "^1.0.30001043"
+ electron-to-chromium "^1.3.413"
node-releases "^1.1.53"
pkg-up "^2.0.0"
@@ -3433,9 +3244,9 @@ bytes@3.1.0:
integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
cacache@^12.0.2:
- version "12.0.3"
- resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.3.tgz#be99abba4e1bf5df461cd5a2c1071fc432573390"
- integrity sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==
+ version "12.0.4"
+ resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c"
+ integrity sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==
dependencies:
bluebird "^3.5.5"
chownr "^1.1.1"
@@ -3564,15 +3375,10 @@ caniuse-api@^3.0.0:
lodash.memoize "^4.1.2"
lodash.uniq "^4.5.0"
-caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001020, caniuse-lite@^1.0.30001030:
- version "1.0.30001035"
- resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001035.tgz#2bb53b8aa4716b2ed08e088d4dc816a5fe089a1e"
- integrity sha512-C1ZxgkuA4/bUEdMbU5WrGY4+UhMFFiXrgNAfxiMIqWgFTWfv/xsZCS2xEHT2LMq7xAZfuAnu6mcqyDl0ZR6wLQ==
-
-caniuse-lite@^1.0.30001035, caniuse-lite@^1.0.30001038:
- version "1.0.30001042"
- resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001042.tgz#c91ec21ec2d270bd76dbc2ce261260c292b8c93c"
- integrity sha512-igMQ4dlqnf4tWv0xjaaE02op9AJ2oQzXKjWf4EuAHFN694Uo9/EfPVIPJcmn2WkU9RqozCxx5e2KPcVClHDbDw==
+caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001035, caniuse-lite@^1.0.30001039, caniuse-lite@^1.0.30001043:
+ version "1.0.30001058"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001058.tgz#9f8a318389e28f060272274ac93a661d17f8bf0d"
+ integrity sha512-UiRZmBYd1HdVVdFKy7PuLVx9e2NS7SMyx7QpWvFjiklYrLJKpLd19cRnRNqlw4zYa7vVejS3c8JUVobX241zHQ==
capture-exit@^2.0.0:
version "2.0.0"
@@ -3652,7 +3458,7 @@ check-types@^8.0.3:
resolved "https://registry.yarnpkg.com/check-types/-/check-types-8.0.3.tgz#3356cca19c889544f2d7a95ed49ce508a0ecf552"
integrity sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ==
-chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.1.8:
+chokidar@^2.0.0, chokidar@^2.1.8:
version "2.1.8"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917"
integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==
@@ -3672,9 +3478,9 @@ chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.1.8:
fsevents "^1.2.7"
chokidar@^3.3.0:
- version "3.3.1"
- resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.1.tgz#c84e5b3d18d9a4d77558fef466b1bf16bbeb3450"
- integrity sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==
+ version "3.4.0"
+ resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.0.tgz#b30611423ce376357c765b9b8f904b9fba3c0be8"
+ integrity sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==
dependencies:
anymatch "~3.1.1"
braces "~3.0.2"
@@ -3682,7 +3488,7 @@ chokidar@^3.3.0:
is-binary-path "~2.1.0"
is-glob "~4.0.1"
normalize-path "~3.0.0"
- readdirp "~3.3.0"
+ readdirp "~3.4.0"
optionalDependencies:
fsevents "~2.1.2"
@@ -3751,9 +3557,9 @@ cli-cursor@^3.1.0:
restore-cursor "^3.1.0"
cli-width@^2.0.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639"
- integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48"
+ integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==
clipboard@^2.0.0:
version "2.0.6"
@@ -4119,11 +3925,11 @@ copy-to-clipboard@^3, copy-to-clipboard@^3.2.0:
toggle-selection "^1.0.6"
core-js-compat@^3.6.2:
- version "3.6.4"
- resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.4.tgz#938476569ebb6cda80d339bcf199fae4f16fff17"
- integrity sha512-zAa3IZPvsJ0slViBQ2z+vgyyTuhd3MFn1rBQjZSKVEgB0UMYhUkCj9jJUVPgGTGqWvsBVmfnruXgTcNyTlEiSA==
+ version "3.6.5"
+ resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.5.tgz#2a51d9a4e25dfd6e690251aa81f99e3c05481f1c"
+ integrity sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng==
dependencies:
- browserslist "^4.8.3"
+ browserslist "^4.8.5"
semver "7.0.0"
core-js-pure@^3.0.0:
@@ -4142,9 +3948,9 @@ core-js@^2.4.0, core-js@^2.6.5:
integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==
core-js@^3.5.0:
- version "3.6.4"
- resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.4.tgz#440a83536b458114b9cb2ac1580ba377dc470647"
- integrity sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw==
+ version "3.6.5"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a"
+ integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==
core-util-is@1.0.2, core-util-is@~1.0.0:
version "1.0.2"
@@ -4180,7 +3986,7 @@ create-ecdh@^4.0.0:
bn.js "^4.1.0"
elliptic "^6.0.0"
-create-hash@^1.1.0, create-hash@^1.1.2:
+create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196"
integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==
@@ -4191,7 +3997,7 @@ create-hash@^1.1.0, create-hash@^1.1.2:
ripemd160 "^2.0.1"
sha.js "^2.4.0"
-create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4:
+create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7:
version "1.1.7"
resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff"
integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==
@@ -4356,7 +4162,7 @@ css-tree@1.0.0-alpha.37:
mdn-data "2.0.4"
source-map "^0.6.1"
-css-tree@^1.0.0-alpha.28:
+css-tree@1.0.0-alpha.39, css-tree@^1.0.0-alpha.28:
version "1.0.0-alpha.39"
resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.39.tgz#2bff3ffe1bb3f776cf7eefd91ee5cba77a149eeb"
integrity sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA==
@@ -4468,11 +4274,11 @@ cssnano@^4.1.10:
postcss "^7.0.0"
csso@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/csso/-/csso-4.0.2.tgz#e5f81ab3a56b8eefb7f0092ce7279329f454de3d"
- integrity sha512-kS7/oeNVXkHWxby5tHVxlhjizRCSv8QdU7hB2FpdAibDU8FjTAolhNjKNTiLzXtUrKT6HwClE81yXwEk1309wg==
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/csso/-/csso-4.0.3.tgz#0d9985dc852c7cc2b2cacfbbe1079014d1a8e903"
+ integrity sha512-NL3spysxUkcrOgnpsT4Xdl2aiEiBG6bXswAABQVHcMrfjjBisFOKwLDOmf4wf32aPdcJws1zds2B0Rg+jqMyHQ==
dependencies:
- css-tree "1.0.0-alpha.37"
+ css-tree "1.0.0-alpha.39"
cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0", cssom@^0.3.4:
version "0.3.8"
@@ -5189,17 +4995,12 @@ ejs@^2.6.1:
resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba"
integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==
-electron-to-chromium@^1.3.363:
- version "1.3.378"
- resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.378.tgz#18c572cbb54bf5b2769855597cdc7511c02b481f"
- integrity sha512-nBp/AfhaVIOnfwgL1CZxt80IcqWcyYXiX6v5gflAksxy+SzBVz7A7UWR1Nos92c9ofXW74V9PoapzRb0jJfYXw==
-
-electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.390:
- version "1.3.409"
- resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.409.tgz#c9a4380ff0ad3e26cd1b4b4cef800d17c46aec7e"
- integrity sha512-CB2HUXiMsaVYY5VvcpELhDShiTRhI2FfN7CuacEZ5mDmMFuSG/ZVm8HoSya0+S61RvUd3TjIjFSKywqHZpRPzQ==
+electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.413:
+ version "1.3.437"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.437.tgz#110f1cd407e5d09b43d5585e5f237b71063412cf"
+ integrity sha512-PBQn2q68ErqMyBUABh9Gh8R6DunGky8aB5y3N5lPM7OVpldwyUbAK5AX9WcwE/5F6ceqvQ+iQLYkJYRysAs6Bg==
-elliptic@^6.0.0:
+elliptic@^6.0.0, elliptic@^6.5.2:
version "6.5.2"
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.2.tgz#05c5678d7173c049d8ca433552224a495d0e3762"
integrity sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==
@@ -5266,9 +5067,9 @@ entities@^1.1.1:
integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==
entities@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4"
- integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.2.tgz#ac74db0bba8d33808bbf36809c3a5c3683531436"
+ integrity sha512-dmD3AvJQBUjKpcNkoqr+x+IF0SdRtPz9Vk0uTy4yWqga9ibB6s4v++QFWNohjiUGoMlF552ZvNyXDxz5iW0qmw==
errno@^0.1.1, errno@^0.1.3, errno@~0.1.7:
version "0.1.7"
@@ -5291,10 +5092,10 @@ error-stack-parser@^2.0.6:
dependencies:
stackframe "^1.1.1"
-es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2:
- version "1.17.4"
- resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.4.tgz#e3aedf19706b20e7c2594c35fc0d57605a79e184"
- integrity sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==
+es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.5:
+ version "1.17.5"
+ resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.5.tgz#d8c9d1d66c8981fb9200e2251d799eee92774ae9"
+ integrity sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==
dependencies:
es-to-primitive "^1.2.1"
function-bind "^1.1.1"
@@ -5575,11 +5376,11 @@ esprima@^4.0.0, esprima@^4.0.1:
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
esquery@^1.0.1:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.1.0.tgz#c5c0b66f383e7656404f86b31334d72524eddb48"
- integrity sha512-MxYW9xKmROWF672KqjO75sszsA8Mxhw06YFeS5VHlB98KDHbOSurm3ArsjO60Eaf3QmGMCP1yn+0JQkNLo/97Q==
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57"
+ integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==
dependencies:
- estraverse "^4.0.0"
+ estraverse "^5.1.0"
esrecurse@^4.1.0:
version "4.2.1"
@@ -5588,12 +5389,17 @@ esrecurse@^4.1.0:
dependencies:
estraverse "^4.1.0"
-estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0:
+estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
-esutils@^2.0.0, esutils@^2.0.2:
+estraverse@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.1.0.tgz#374309d39fd935ae500e7b92e8a6b4c720e59642"
+ integrity sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw==
+
+esutils@^2.0.2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
@@ -5604,9 +5410,9 @@ etag@~1.8.1:
integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
eventemitter3@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.0.tgz#d65176163887ee59f386d64c82610b696a4a74eb"
- integrity sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==
+ version "4.0.4"
+ resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384"
+ integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==
events@^3.0.0:
version "3.1.0"
@@ -5898,9 +5704,9 @@ fbjs@^0.8.9:
ua-parser-js "^0.7.18"
figgy-pudding@^3.5.1:
- version "3.5.1"
- resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790"
- integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==
+ version "3.5.2"
+ resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e"
+ integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==
figures@^3.0.0:
version "3.2.0"
@@ -6079,9 +5885,9 @@ flat-cache@^2.0.1:
write "1.0.3"
flatted@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08"
- integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138"
+ integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==
flatten@^1.0.2:
version "1.0.3"
@@ -6104,9 +5910,9 @@ follow-redirects@1.5.10:
debug "=3.1.0"
follow-redirects@^1.0.0:
- version "1.10.0"
- resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.10.0.tgz#01f5263aee921c6a54fb91667f08f4155ce169eb"
- integrity sha512-4eyLK6s6lH32nOvLLwlIOnr9zrL8Sm+OvW4pVTJNoXeGzYIkHVf+pADQi+OJ0E67hiuSLezPVPyBcIZO50TmmQ==
+ version "1.11.0"
+ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.11.0.tgz#afa14f08ba12a52963140fe43212658897bc0ecb"
+ integrity sha512-KZm0V+ll8PfBrKwMzdo5D13b1bur9Iq9Zd/RMmAoQQcl2PxxFml8cxXPaaPYVbV0RjNjq1CU7zIzAOqtUPudmA==
dependencies:
debug "^3.0.0"
@@ -6273,19 +6079,24 @@ fs.realpath@^1.0.0:
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
-fsevents@2.1.2, fsevents@~2.1.2:
+fsevents@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805"
integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==
fsevents@^1.2.7:
- version "1.2.11"
- resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.11.tgz#67bf57f4758f02ede88fb2a1712fef4d15358be3"
- integrity sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==
+ version "1.2.13"
+ resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38"
+ integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==
dependencies:
bindings "^1.5.0"
nan "^2.12.1"
+fsevents@~2.1.2:
+ version "2.1.3"
+ resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e"
+ integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==
+
function-bind@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
@@ -6355,14 +6166,7 @@ glob-parent@^3.1.0:
is-glob "^3.1.0"
path-dirname "^1.0.0"
-glob-parent@^5.0.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2"
- integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==
- dependencies:
- is-glob "^4.0.1"
-
-glob-parent@~5.1.0:
+glob-parent@^5.0.0, glob-parent@~5.1.0:
version "5.1.1"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229"
integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==
@@ -6500,11 +6304,16 @@ good-listener@^1.2.2:
dependencies:
delegate "^3.1.2"
-graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2:
+graceful-fs@^4.0.0:
version "4.2.3"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423"
integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==
+graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2:
+ version "4.2.4"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
+ integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
+
growly@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
@@ -6577,9 +6386,9 @@ hammerjs@^2.0.8:
integrity sha1-BO93hiz/K7edMPdpIJWTAiK/YPE=
handle-thing@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.0.tgz#0e039695ff50c93fc288557d696f3c1dc6776754"
- integrity sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e"
+ integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==
har-schema@^2.0.0:
version "2.0.0"
@@ -6665,12 +6474,13 @@ has@^1.0.0, has@^1.0.3:
function-bind "^1.1.1"
hash-base@^3.0.0:
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918"
- integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33"
+ integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==
dependencies:
- inherits "^2.0.1"
- safe-buffer "^5.0.1"
+ inherits "^2.0.4"
+ readable-stream "^3.6.0"
+ safe-buffer "^5.2.0"
hash.js@^1.0.0, hash.js@^1.0.3:
version "1.1.7"
@@ -6796,14 +6606,14 @@ html-entities@^1.2.1:
integrity sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA==
html-escaper@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.0.tgz#71e87f931de3fe09e56661ab9a29aadec707b491"
- integrity sha512-a4u9BeERWGu/S8JiWEAQcdrg9v4QArtP9keViQjGMdff20fBdd8waotXaNmODqBe6uZ3Nafi7K/ho4gCQHV3Ig==
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453"
+ integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==
html-minifier-terser@^5.0.1:
- version "5.0.5"
- resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-5.0.5.tgz#8f12f639789f04faa9f5cf2ff9b9f65607f21f8b"
- integrity sha512-cBSFFghQh/uHcfSiL42KxxIRMF7A144+3E44xdlctIjxEmkEfCvouxNyFH2wysXk1fCGBPwtcr3hDWlGTfkDew==
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#922e96f1f3bb60832c2634b79884096389b1f054"
+ integrity sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg==
dependencies:
camel-case "^4.1.1"
clean-css "^4.2.3"
@@ -7107,7 +6917,7 @@ inflight@^1.0.4:
once "^1.3.0"
wrappy "1"
-inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3:
+inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
@@ -7513,11 +7323,6 @@ is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4:
dependencies:
isobject "^3.0.1"
-is-promise@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
- integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=
-
is-regex@^1.0.4, is-regex@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae"
@@ -7619,9 +7424,11 @@ is-wsl@^1.1.0:
integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=
is-wsl@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.1.1.tgz#4a1c152d429df3d441669498e2486d3596ebaf1d"
- integrity sha512-umZHcSrwlDHo2TGMXv0DZ8dIUGunZ2Iv68YZnrmCiBPkZ4aaOhtv7pXJKeki9k3qJ3RJr0cDyitcl5wEH3AYog==
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271"
+ integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==
+ dependencies:
+ is-docker "^2.0.0"
isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
version "1.0.0"
@@ -8075,9 +7882,9 @@ jest-worker@^24.6.0, jest-worker@^24.9.0:
supports-color "^6.1.0"
jest-worker@^25.1.0:
- version "25.2.6"
- resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-25.2.6.tgz#d1292625326794ce187c38f51109faced3846c58"
- integrity sha512-FJn9XDUSxcOR4cwDzRfL1z56rUofNTFs539FGASpd50RHdb6EVkhxQqktodW2mI49l+W3H+tFJDotCHUQF6dmA==
+ version "25.5.0"
+ resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-25.5.0.tgz#2611d071b79cea0f43ee57a3d118593ac1547db1"
+ integrity sha512-/dsSmUkIy5EBGfv/IjjqmFxrNAUpBERfGs1oHROyD7yxjG/w+t0GOJDX8O1k32ySmd7+a5IhnJU2qQFcJ4n1vw==
dependencies:
merge-stream "^2.0.0"
supports-color "^7.0.0"
@@ -8248,13 +8055,6 @@ json5@^1.0.1:
dependencies:
minimist "^1.2.0"
-json5@^2.1.0:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.2.tgz#43ef1f0af9835dd624751a6b7fa48874fb2d608e"
- integrity sha512-MoUOQ4WdiN3yxhm7NEVJSJrieAo5hNSLQ5sj05OTRHPL9HOBy8u4Bu88jsC1jvqAdN+E1bJmsUcZH+1HQxliqQ==
- dependencies:
- minimist "^1.2.5"
-
json5@^2.1.2:
version "2.1.3"
resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43"
@@ -8501,12 +8301,12 @@ load-json-file@^4.0.0:
strip-bom "^3.0.0"
loader-fs-cache@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/loader-fs-cache/-/loader-fs-cache-1.0.2.tgz#54cedf6b727e1779fd8f01205f05f6e88706f086"
- integrity sha512-70IzT/0/L+M20jUlEqZhZyArTU6VKLRTYRDAYN26g4jfzpJqjipLL3/hgYpySqI9PwsVRHHFja0LfEmsx9X2Cw==
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/loader-fs-cache/-/loader-fs-cache-1.0.3.tgz#f08657646d607078be2f0a032f8bd69dd6f277d9"
+ integrity sha512-ldcgZpjNJj71n+2Mf6yetz+c9bM4xpKtNds4LbqXzU/PTdeAX0g3ytnU1AJMEcTk2Lex4Smpe3Q/eCTsvUBxbA==
dependencies:
find-cache-dir "^0.1.1"
- mkdirp "0.5.1"
+ mkdirp "^0.5.1"
loader-runner@^2.4.0:
version "2.4.0"
@@ -8684,9 +8484,9 @@ make-dir@^2.0.0, make-dir@^2.1.0:
semver "^5.6.0"
make-dir@^3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.0.2.tgz#04a1acbf22221e1d6ef43559f43e05a90dbb4392"
- integrity sha512-rYKABKutXa6vXTXhoV18cBE7PaewPXHe/Bdq4v+ZLMhxbWApkFFplT0LcbMW+6BbjnQXzZ/sAvSE/JdguApG5w==
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
+ integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==
dependencies:
semver "^6.0.0"
@@ -8873,17 +8673,17 @@ miller-rabin@^4.0.0:
bn.js "^4.0.0"
brorand "^1.0.1"
-mime-db@1.43.0, "mime-db@>= 1.43.0 < 2":
- version "1.43.0"
- resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58"
- integrity sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==
+mime-db@1.44.0, "mime-db@>= 1.43.0 < 2":
+ version "1.44.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92"
+ integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==
mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24:
- version "2.1.26"
- resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.26.tgz#9c921fc09b7e149a65dfdc0da4d20997200b0a06"
- integrity sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==
+ version "2.1.27"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f"
+ integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==
dependencies:
- mime-db "1.43.0"
+ mime-db "1.44.0"
mime@1.6.0, mime@^1.4.1:
version "1.6.0"
@@ -8891,9 +8691,9 @@ mime@1.6.0, mime@^1.4.1:
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
mime@^2.4.4:
- version "2.4.4"
- resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5"
- integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==
+ version "2.4.5"
+ resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.5.tgz#d8de2ecb92982dedbb6541c9b6841d7f218ea009"
+ integrity sha512-3hQhEUF027BuxZjQA3s7rIv/7VCQPa27hN9u9g87sEkWaKwQPuXOkVKtOeiyUrnWqTDiOs8Ed2rwg733mB0R5w==
mimic-fn@^2.0.0, mimic-fn@^2.1.0:
version "2.1.0"
@@ -8937,11 +8737,6 @@ minimatch@3.0.4, minimatch@^3.0.4:
dependencies:
brace-expansion "^1.1.7"
-minimist@0.0.8:
- version "0.0.8"
- resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
- integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
-
minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
@@ -8962,16 +8757,16 @@ minipass-flush@^1.0.5:
minipass "^3.0.0"
minipass-pipeline@^1.2.2:
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.2.tgz#3dcb6bb4a546e32969c7ad710f2c79a86abba93a"
- integrity sha512-3JS5A2DKhD2g0Gg8x3yamO0pj7YeKGwVlDS90pF++kxptwx/F+B//roxf9SqYil5tQo65bijy+dAuAFZmYOouA==
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.3.tgz#55f7839307d74859d6e8ada9c3ebe72cec216a34"
+ integrity sha512-cFOknTvng5vqnwOpDsZTWhNll6Jf8o2x+/diplafmxpuIymAjzoOolZG0VvQf3V2HgqzJNhnuKHYp2BqDgz8IQ==
dependencies:
minipass "^3.0.0"
minipass@^3.0.0, minipass@^3.1.1:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.1.tgz#7607ce778472a185ad6d89082aa2070f79cedcd5"
- integrity sha512-UFqVihv6PQgwj8/yTGvl9kPz7xIAY+R5z6XYjRInD3Gk3qx6QGSD6zEcpeG4Dy/lQnv1J6zv8ejV90hyYIKf3w==
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.3.tgz#7d42ff1f39635482e15f9cdb53184deebd5815fd"
+ integrity sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==
dependencies:
yallist "^4.0.0"
@@ -9007,21 +8802,14 @@ mixin-object@^2.0.1:
for-in "^0.1.3"
is-extendable "^0.1.1"
-mkdirp@0.5.1:
- version "0.5.1"
- resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
- integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
- dependencies:
- minimist "0.0.8"
-
-mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1:
+mkdirp@^0.5.0:
version "0.5.3"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.3.tgz#5a514b7179259287952881e94410ec5465659f8c"
integrity sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==
dependencies:
minimist "^1.2.5"
-mkdirp@^0.5.3:
+mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@~0.5.1:
version "0.5.5"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
@@ -9109,9 +8897,9 @@ mute-stream@0.0.8:
integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
nan@^2.12.1:
- version "2.14.0"
- resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
- integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==
+ version "2.14.1"
+ resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01"
+ integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==
nano-css@^5.2.1:
version "5.3.0"
@@ -9250,17 +9038,10 @@ node-notifier@^5.4.2:
shellwords "^0.1.1"
which "^1.3.0"
-node-releases@^1.1.50:
- version "1.1.52"
- resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.52.tgz#bcffee3e0a758e92e44ecfaecd0a47554b0bcba9"
- integrity sha512-snSiT1UypkgGt2wxPqS6ImEUICbNCMb31yaxWrOLXjhlt2z2/IBpaOxzONExqSm4y5oLnAqjjRWu+wsDzK5yNQ==
- dependencies:
- semver "^6.3.0"
-
node-releases@^1.1.52, node-releases@^1.1.53:
- version "1.1.53"
- resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.53.tgz#2d821bfa499ed7c5dffc5e2f28c88e78a08ee3f4"
- integrity sha512-wp8zyQVwef2hpZ/dJH7SfSrIPD6YoJz6BDQDpGEkcA0s3LpAQoxBIYmfIq6QAhC1DhwsyCgTaTTcONwX8qzCuQ==
+ version "1.1.55"
+ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.55.tgz#8af23b7c561d8e2e6e36a46637bab84633b07cee"
+ integrity sha512-H3R3YR/8TjT5WPin/wOoHOUPHgvj8leuU/Keta/rwelEQN9pA/S2Dx8/se4pZ2LBxSd0nAGzsNzhqwa77v7F1w==
normalize-package-data@^2.3.2:
version "2.5.0"
@@ -9377,9 +9158,12 @@ object-inspect@^1.7.0:
integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==
object-is@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.2.tgz#6b80eb84fe451498f65007982f035a5b445edec4"
- integrity sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ==
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.2.tgz#c5d2e87ff9e119f78b7a088441519e2eec1573b6"
+ integrity sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ==
+ dependencies:
+ define-properties "^1.1.3"
+ es-abstract "^1.17.5"
object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1:
version "1.1.1"
@@ -9653,14 +9437,7 @@ p-limit@^1.1.0:
dependencies:
p-try "^1.0.0"
-p-limit@^2.0.0, p-limit@^2.2.0:
- version "2.2.2"
- resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.2.tgz#61279b67721f5287aa1c13a9a7fbbc48c9291b1e"
- integrity sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==
- dependencies:
- p-try "^2.0.0"
-
-p-limit@^2.2.2:
+p-limit@^2.0.0, p-limit@^2.2.0, p-limit@^2.2.2:
version "2.3.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
@@ -9751,7 +9528,7 @@ parent-module@^1.0.0:
dependencies:
callsites "^3.0.0"
-parse-asn1@^5.0.0:
+parse-asn1@^5.0.0, parse-asn1@^5.1.5:
version "5.1.5"
resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e"
integrity sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==
@@ -9960,7 +9737,7 @@ performance-now@^2.1.0:
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
-picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.0.7:
+picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1:
version "2.2.2"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad"
integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==
@@ -10083,9 +9860,9 @@ popmotion@9.0.0-beta-8:
tslib "^1.10.0"
portfinder@^1.0.25:
- version "1.0.25"
- resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.25.tgz#254fd337ffba869f4b9d37edc298059cb4d35eca"
- integrity sha512-6ElJnHBbxVA1XSLgBp7G1FiCkQdlqGzuF7DswL5tcea+E8UpuvPU7beVAjjRwCioTS9ZluNbu+ZyRvgTsmqEBg==
+ version "1.0.26"
+ resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.26.tgz#475658d56ca30bed72ac7f1378ed350bd1b64e70"
+ integrity sha512-Xi7mKxJHHMI3rIUrnm/jjUgwhbYMkp/XKEcZX3aG4BrumLpq3nmoQMX+ClYnDZnZ/New7IatC1no5RX0zo1vXQ==
dependencies:
async "^2.6.2"
debug "^3.1.1"
@@ -10725,10 +10502,10 @@ postcss-value-parser@^3.0.0, postcss-value-parser@^3.3.0:
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281"
integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==
-postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2:
- version "4.0.3"
- resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.3.tgz#651ff4593aa9eda8d5d0d66593a2417aeaeb325d"
- integrity sha512-N7h4pG+Nnu5BEIzyeaaIYWs0LI5XC40OrRh5L60z0QjFsqGWcHcbkBvpe1WYpcIS9yQ8sOi/vIPt1ejQCrMVrg==
+postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2, postcss-value-parser@^4.0.3:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb"
+ integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==
postcss-values-parser@^2.0.0, postcss-values-parser@^2.0.1:
version "2.0.1"
@@ -10748,10 +10525,10 @@ postcss@7.0.21:
source-map "^0.6.1"
supports-color "^6.1.0"
-postcss@^7, postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.23, postcss@^7.0.26, postcss@^7.0.27, postcss@^7.0.5, postcss@^7.0.6:
- version "7.0.27"
- resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.27.tgz#cc67cdc6b0daa375105b7c424a85567345fc54d9"
- integrity sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==
+postcss@^7, postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.23, postcss@^7.0.27, postcss@^7.0.5, postcss@^7.0.6:
+ version "7.0.30"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.30.tgz#cc9378beffe46a02cbc4506a0477d05fcea9a8e2"
+ integrity sha512-nu/0m+NtIzoubO+xdAlwZl/u5S5vi/y6BCsoL8D+8IxsD3XvBS8X4YEADNIVXKVuQvduiucnRv+vPIqj56EGMQ==
dependencies:
chalk "^2.4.2"
source-map "^0.6.1"
@@ -10871,9 +10648,9 @@ promise@^8.0.3:
asap "~2.0.6"
prompts@^2.0.1:
- version "2.3.1"
- resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.3.1.tgz#b63a9ce2809f106fa9ae1277c275b167af46ea05"
- integrity sha512-qIP2lQyCwYbdzcqHIUi2HAxiWixhoM9OdLCWf8txXsapC/X9YdsCoeyRIXE/GP+Q0J37Q7+XN/MFqbUa7IzXNA==
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.3.2.tgz#480572d89ecf39566d2bd3fe2c9fccb7c4c0b068"
+ integrity sha512-Q06uKs2CkNYVID0VqwfAl9mipo99zkBv/n2JtWY89Yxa3ZabWSrs0e2KTudKVa3peLUvYXMefDqIleLPVUBZMA==
dependencies:
kleur "^3.0.3"
sisteransi "^1.0.4"
@@ -10908,9 +10685,9 @@ prr@~1.0.1:
integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY=
psl@^1.1.28:
- version "1.7.0"
- resolved "https://registry.yarnpkg.com/psl/-/psl-1.7.0.tgz#f1c4c47a8ef97167dea5d6bbf4816d736e884a3c"
- integrity sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
+ integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==
public-encrypt@^4.0.0:
version "4.0.3"
@@ -11507,12 +11284,12 @@ react-i18next@^11.3.5:
"@babel/runtime" "^7.3.1"
html-parse-stringify2 "2.0.1"
-react-is@^16.12.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4:
+react-is@^16.12.0, react-is@^16.7.0:
version "16.13.0"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.0.tgz#0f37c3613c34fe6b37cd7f763a0d6293ab15c527"
integrity sha512-GFMtL0vHkiBv9HluwNZTggSn/sCyEt9n02aM0dSAjGGyqyNlAyftYm4phPxdvCigG15JreC5biwxCgTAJZ7yAA==
-react-is@^16.8.6:
+react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
@@ -11734,7 +11511,7 @@ read-pkg@^3.0.0:
string_decoder "~1.1.1"
util-deprecate "~1.0.1"
-"readable-stream@2 || 3", readable-stream@^3.0.6, readable-stream@^3.1.1:
+"readable-stream@2 || 3", readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
@@ -11752,12 +11529,12 @@ readdirp@^2.2.1:
micromatch "^3.1.10"
readable-stream "^2.0.2"
-readdirp@~3.3.0:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.3.0.tgz#984458d13a1e42e2e9f5841b129e162f369aff17"
- integrity sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==
+readdirp@~3.4.0:
+ version "3.4.0"
+ resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.4.0.tgz#9fdccdf9e9155805449221ac645e8303ab5b9ada"
+ integrity sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==
dependencies:
- picomatch "^2.0.7"
+ picomatch "^2.2.1"
realpath-native@^1.1.0:
version "1.1.0"
@@ -11812,9 +11589,9 @@ regenerator-runtime@^0.13.3, regenerator-runtime@^0.13.4:
integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==
regenerator-transform@^0.14.2:
- version "0.14.3"
- resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.3.tgz#54aebff2ef58c0ae61e695ad1b9a9d65995fff78"
- integrity sha512-zXHNKJspmONxBViAb3ZUmFoFPnTBs3zFhCEZJiwp/gkNzxVbTqNJVjYKx6Qk1tQ1P4XLf4TbH9+KBB7wGoAaUw==
+ version "0.14.4"
+ resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.4.tgz#5266857896518d1616a78a0479337a30ea974cc7"
+ integrity sha512-EaJaKPBI9GvKpvUz2mz4fhx7WPgvwRLY9v3hlNHWmAuJHI13T4nwKnNvm5RWJzEdnI5g5UwtOww+S8IdoUC2bw==
dependencies:
"@babel/runtime" "^7.8.4"
private "^0.1.8"
@@ -11846,9 +11623,9 @@ regexpp@^2.0.1:
integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==
regexpp@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.0.0.tgz#dd63982ee3300e67b41c1956f850aa680d9d330e"
- integrity sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g==
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2"
+ integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==
regexpu-core@^4.7.0:
version "4.7.0"
@@ -12089,17 +11866,17 @@ resolve@1.15.0:
dependencies:
path-parse "^1.0.6"
-resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.3.2, resolve@^1.4.0, resolve@^1.8.1:
+resolve@^1.1.6, resolve@^1.1.7, resolve@^1.4.0:
version "1.15.1"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8"
integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==
dependencies:
path-parse "^1.0.6"
-resolve@^1.15.1:
- version "1.16.0"
- resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.16.0.tgz#063dc704fa3413e13ac1d0d1756a7cbfe95dd1a7"
- integrity sha512-LarL/PIKJvc09k1jaeT4kQb/8/7P+qV4qSnN2K80AES+OHdfZELAKVOBjxsvtToT/uLOfFbvYvKfZmV8cee7nA==
+resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.15.1, resolve@^1.3.2, resolve@^1.8.1:
+ version "1.17.0"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444"
+ integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==
dependencies:
path-parse "^1.0.6"
@@ -12187,11 +11964,9 @@ rtl-css-js@^1.9.0:
"@babel/runtime" "^7.1.2"
run-async@^2.2.0, run-async@^2.4.0:
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.0.tgz#e59054a5b86876cfae07f431d18cbaddc594f1e8"
- integrity sha512-xJTbh/d7Lm7SBhc1tNvTpeCHaEzoyxPrqNlvSdMfBTYwaY++UJFyXUOxAtsRUXjlqOfj8luNaR9vjCh4KeV+pg==
- dependencies:
- is-promise "^2.1.0"
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
+ integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==
run-queue@^1.0.0, run-queue@^1.0.3:
version "1.0.3"
@@ -12206,9 +11981,9 @@ rw@1:
integrity sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q=
rxjs@^6.5.3:
- version "6.5.4"
- resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c"
- integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==
+ version "6.5.5"
+ resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.5.tgz#c5c884e3094c8cfee31bf27eb87e54ccfc87f9ec"
+ integrity sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==
dependencies:
tslib "^1.9.0"
@@ -12217,10 +11992,10 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
-safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0:
- version "5.2.0"
- resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519"
- integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==
+safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
+ integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
safe-regex@^1.1.0:
version "1.1.0"
@@ -12295,9 +12070,9 @@ schema-utils@^1.0.0:
ajv-keywords "^3.1.0"
schema-utils@^2.5.0, schema-utils@^2.6.0, schema-utils@^2.6.1, schema-utils@^2.6.4, schema-utils@^2.6.5:
- version "2.6.5"
- resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.5.tgz#c758f0a7e624263073d396e29cd40aa101152d8a"
- integrity sha512-5KXuwKziQrTVHh8j/Uxz+QUbxkaLW9X/86NBlx/gnKgtsZA2GIVMUn17qWhRFwF8jdYb3Dig5hRO/W5mZqy6SQ==
+ version "2.6.6"
+ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.6.tgz#299fe6bd4a3365dc23d99fd446caff8f1d6c330c"
+ integrity sha512-wHutF/WPSbIi9x6ctjGGk2Hvl0VOz5l3EKEuKbjPlB30mKZUzb9A5k9yEXRX3pwyqVLPvpfZZEllaFq/M718hA==
dependencies:
ajv "^6.12.0"
ajv-keywords "^3.4.1"
@@ -12368,6 +12143,11 @@ semver@7.0.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
+semver@^7.3.2:
+ version "7.3.2"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938"
+ integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==
+
send@0.17.1:
version "0.17.1"
resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8"
@@ -12523,9 +12303,9 @@ side-channel@^1.0.2:
object-inspect "^1.7.0"
signal-exit@^3.0.0, signal-exit@^3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
- integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
+ integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
simple-swizzle@^0.2.2:
version "0.2.2"
@@ -12545,9 +12325,9 @@ single-spa@^5.3.4:
integrity sha512-J0I+OfKn04QdaOp3lC8UL2xmD/BA/V0OisbCFbrR5LDIdsbcP9QG6ZFRNqIQQP8C9XXUtlGnA3ZWPLQBKGcOrw==
sisteransi@^1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.4.tgz#386713f1ef688c7c0304dc4c0632898941cad2e3"
- integrity sha512-/ekMoM4NJ59ivGSfKapeG+FWtrmWvA1p6FBZwXrqojw90vJu8lBmrTxCMuBCydKtkaUe2zt4PlxeTKpjwMbyig==
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"
+ integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==
size-sensor@^0.2.0:
version "0.2.6"
@@ -12652,9 +12432,9 @@ source-map-resolve@^0.5.0, source-map-resolve@^0.5.2:
urix "^0.1.0"
source-map-support@^0.5.6, source-map-support@~0.5.12:
- version "0.5.16"
- resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042"
- integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==
+ version "0.5.19"
+ resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"
+ integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==
dependencies:
buffer-from "^1.0.0"
source-map "^0.6.0"
@@ -12703,14 +12483,14 @@ spdx-correct@^3.0.0:
spdx-license-ids "^3.0.0"
spdx-exceptions@^2.1.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977"
- integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d"
+ integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==
spdx-expression-parse@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0"
- integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679"
+ integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==
dependencies:
spdx-exceptions "^2.1.0"
spdx-license-ids "^3.0.0"
@@ -12755,13 +12535,14 @@ sprintf-js@~1.0.2:
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
-sql-formatter-plus@^1.3.6:
- version "1.3.6"
- resolved "https://registry.yarnpkg.com/sql-formatter-plus/-/sql-formatter-plus-1.3.6.tgz#56e671181ff34c0dc403bac6f950486626f9d406"
- integrity sha512-3pelcpLve9GgsXshWL/59zyDkhICkXDURKjXyUN+PJqVGAt+ZmNPB2JY+hgnaQG5X9TQI7Q+WiyLEprHQAWuaQ==
+sql-formatter-plus-plus@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/sql-formatter-plus-plus/-/sql-formatter-plus-plus-1.4.0.tgz#e7b329ed572a4b804fd7f8ceb9960811af0b8656"
+ integrity sha512-AEXMcq+jwTTS/Ol1cD83eSRMdJje6yb5vWOFtl0drF9sGl7yVjc7tmJnDWaLStAOcalv/9BIk/91KKcw++ZjOA==
dependencies:
- "@babel/polyfill" "^7.6.0"
+ "@babel/polyfill" "^7.7.0"
lodash "^4.17.15"
+ regexpu-core "^4.7.0"
sshpk@^1.7.0:
version "1.16.1"
@@ -12982,21 +12763,39 @@ string.prototype.matchall@^4.0.2:
regexp.prototype.flags "^1.3.0"
side-channel "^1.0.2"
+string.prototype.trimend@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913"
+ integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==
+ dependencies:
+ define-properties "^1.1.3"
+ es-abstract "^1.17.5"
+
string.prototype.trimleft@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz#9bdb8ac6abd6d602b17a4ed321870d2f8dcefc74"
- integrity sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz#4408aa2e5d6ddd0c9a80739b087fbc067c03b3cc"
+ integrity sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==
dependencies:
define-properties "^1.1.3"
- function-bind "^1.1.1"
+ es-abstract "^1.17.5"
+ string.prototype.trimstart "^1.0.0"
string.prototype.trimright@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz#440314b15996c866ce8a0341894d45186200c5d9"
- integrity sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz#c76f1cef30f21bbad8afeb8db1511496cfb0f2a3"
+ integrity sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==
dependencies:
define-properties "^1.1.3"
- function-bind "^1.1.1"
+ es-abstract "^1.17.5"
+ string.prototype.trimend "^1.0.0"
+
+string.prototype.trimstart@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54"
+ integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==
+ dependencies:
+ define-properties "^1.1.3"
+ es-abstract "^1.17.5"
string_decoder@^1.0.0, string_decoder@^1.1.1:
version "1.3.0"
@@ -13080,9 +12879,9 @@ strip-final-newline@^2.0.0:
integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
strip-json-comments@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7"
- integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.0.tgz#7638d31422129ecf4457440009fba03f9f9ac180"
+ integrity sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==
style-loader@0.23.1:
version "0.23.1"
@@ -13259,19 +13058,10 @@ terser-webpack-plugin@^1.4.3:
webpack-sources "^1.4.0"
worker-farm "^1.7.0"
-terser@^4.1.2:
- version "4.6.7"
- resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.7.tgz#478d7f9394ec1907f0e488c5f6a6a9a2bad55e72"
- integrity sha512-fmr7M1f7DBly5cX2+rFDvmGBAaaZyPrHYK4mMdHEDAdNTqXSZgSOfqsfGq2HqPGT/1V0foZZuCZFx8CHKgAk3g==
- dependencies:
- commander "^2.20.0"
- source-map "~0.6.1"
- source-map-support "~0.5.12"
-
-terser@^4.4.3, terser@^4.6.3:
- version "4.6.11"
- resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.11.tgz#12ff99fdd62a26de2a82f508515407eb6ccd8a9f"
- integrity sha512-76Ynm7OXUG5xhOpblhytE7X58oeNSmC8xnNhjWVo8CksHit0U0kO4hfNbPrrYwowLWFgM2n9L176VNx2QaHmtA==
+terser@^4.1.2, terser@^4.4.3, terser@^4.6.3:
+ version "4.6.13"
+ resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.13.tgz#e879a7364a5e0db52ba4891ecde007422c56a916"
+ integrity sha512-wMvqukYgVpQlymbnNbabVZbtM6PN63AzqexpwJL8tbh/mRT9LE5o+ruVduAGL7D6Fpjl+Q+06U5I9Ul82odAhw==
dependencies:
commander "^2.20.0"
source-map "~0.6.1"
@@ -13492,9 +13282,9 @@ ts-pnp@^1.1.6:
integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==
tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0:
- version "1.11.1"
- resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35"
- integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==
+ version "1.13.0"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043"
+ integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==
tsutils@^3.17.1:
version "3.17.1"
@@ -14001,11 +13791,11 @@ warning@^4.0.1, warning@^4.0.3, warning@~4.0.3:
loose-envify "^1.0.0"
watchpack@^1.6.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00"
- integrity sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==
+ version "1.6.1"
+ resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.1.tgz#280da0a8718592174010c078c7585a74cd8cd0e2"
+ integrity sha512-+IF9hfUFOrYOOaKyfaI7h7dquUIOgyEMoQMLA7OP5FxegKA2+XdXThAZ9TU2kucfhDH7rfMHs1oPYziVGWRnZA==
dependencies:
- chokidar "^2.0.2"
+ chokidar "^2.1.8"
graceful-fs "^4.1.2"
neo-async "^2.5.0"
@@ -14543,11 +14333,11 @@ yaml-loader@^0.5.0:
js-yaml "^3.5.2"
yaml@^1.7.2:
- version "1.8.2"
- resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.8.2.tgz#a29c03f578faafd57dcb27055f9a5d569cb0c3d9"
- integrity sha512-omakb0d7FjMo3R1D2EbTKVIk6dAVLRxFXdLZMEUToeAvuqgG/YuHMuQOZ5fgk+vQ8cx+cnGKwyg+8g8PNT0xQg==
+ version "1.9.2"
+ resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.9.2.tgz#f0cfa865f003ab707663e4f04b3956957ea564ed"
+ integrity sha512-HPT7cGGI0DuRcsO51qC1j9O16Dh1mZ2bnXwsi0jrSpsLz0WxOLSLXfkABVl6bZO629py3CU+OMJtpNHDLB97kg==
dependencies:
- "@babel/runtime" "^7.8.7"
+ "@babel/runtime" "^7.9.2"
yargs-parser@^11.1.1:
version "11.1.1"
From 7b132878a9e6963b5b4df351d47c8a426fabcfb3 Mon Sep 17 00:00:00 2001
From: Breezewish
Date: Tue, 2 Jun 2020 19:41:13 +0800
Subject: [PATCH 11/14] Fix warnings
---
ui/lib/apps/InstanceProfiling/pages/List.tsx | 2 +-
.../SearchLogs/components/SearchHeader.tsx | 133 +++++++++---------
2 files changed, 69 insertions(+), 66 deletions(-)
diff --git a/ui/lib/apps/InstanceProfiling/pages/List.tsx b/ui/lib/apps/InstanceProfiling/pages/List.tsx
index 758b749eb0..8fc23a24a9 100644
--- a/ui/lib/apps/InstanceProfiling/pages/List.tsx
+++ b/ui/lib/apps/InstanceProfiling/pages/List.tsx
@@ -1,4 +1,4 @@
-import { Badge, Button, Form, message, Select, Modal } from 'antd'
+import { Badge, Button, Form, Select, Modal } from 'antd'
import { ColumnActionsMode } from 'office-ui-fabric-react/lib/DetailsList'
import { ScrollablePane } from 'office-ui-fabric-react/lib/ScrollablePane'
import React, { useMemo, useState, useCallback, useRef } from 'react'
diff --git a/ui/lib/apps/SearchLogs/components/SearchHeader.tsx b/ui/lib/apps/SearchLogs/components/SearchHeader.tsx
index 28a08541a2..cf653d2438 100644
--- a/ui/lib/apps/SearchLogs/components/SearchHeader.tsx
+++ b/ui/lib/apps/SearchLogs/components/SearchHeader.tsx
@@ -63,76 +63,79 @@ export default function SearchHeader({ taskGroupID }: Props) {
fetchData()
})
- const handleSearch = useCallback(async (fieldsValue: IFormProps) => {
- if (
- !fieldsValue.instances ||
- fieldsValue.instances.length === 0 ||
- !fieldsValue.logLevel ||
- !fieldsValue.timeRange
- ) {
- Modal.error({
- content: 'Some required fields are not filled',
- })
- return
- }
- if (!instanceSelect.current) {
- Modal.error({
- content: 'Internal error: Instance select is not ready',
- })
- return
- }
- setSubmitting(true)
+ const handleSearch = useCallback(
+ async (fieldsValue: IFormProps) => {
+ if (
+ !fieldsValue.instances ||
+ fieldsValue.instances.length === 0 ||
+ !fieldsValue.logLevel ||
+ !fieldsValue.timeRange
+ ) {
+ Modal.error({
+ content: 'Some required fields are not filled',
+ })
+ return
+ }
+ if (!instanceSelect.current) {
+ Modal.error({
+ content: 'Internal error: Instance select is not ready',
+ })
+ return
+ }
+ setSubmitting(true)
- const targets: ModelRequestTargetNode[] = instanceSelect
- .current!.getInstanceByKeys(fieldsValue.instances)
- .map((instance) => {
- let port
- switch (instance.instanceKind) {
- case 'pd':
- case 'tikv':
- case 'tiflash':
- port = instance.port
- break
- case 'tidb':
- port = instance.status_port
- break
- }
- return {
- kind: instance.instanceKind,
- display_name: instance.key,
- ip: instance.ip,
- port,
- }
- })
- .filter((i) => i.port != null)
+ const targets: ModelRequestTargetNode[] = instanceSelect
+ .current!.getInstanceByKeys(fieldsValue.instances)
+ .map((instance) => {
+ let port
+ switch (instance.instanceKind) {
+ case 'pd':
+ case 'tikv':
+ case 'tiflash':
+ port = instance.port
+ break
+ case 'tidb':
+ port = instance.status_port
+ break
+ }
+ return {
+ kind: instance.instanceKind,
+ display_name: instance.key,
+ ip: instance.ip,
+ port,
+ }
+ })
+ .filter((i) => i.port != null)
- const [startTime, endTime] = calcTimeRange(fieldsValue.timeRange)
+ const [startTime, endTime] = calcTimeRange(fieldsValue.timeRange)
- const req: LogsearchCreateTaskGroupRequest = {
- targets,
- request: {
- start_time: startTime * 1000, // unix millionsecond
- end_time: endTime * 1000, // unix millionsecond
- min_level: fieldsValue.logLevel,
- patterns: (fieldsValue.keywords ?? '').split(/\s+/), // 'foo boo' => ['foo', 'boo']
- },
- }
+ const req: LogsearchCreateTaskGroupRequest = {
+ targets,
+ request: {
+ start_time: startTime * 1000, // unix millionsecond
+ end_time: endTime * 1000, // unix millionsecond
+ min_level: fieldsValue.logLevel,
+ patterns: (fieldsValue.keywords ?? '').split(/\s+/), // 'foo boo' => ['foo', 'boo']
+ },
+ }
- try {
- const result = await client.getInstance().logsTaskgroupPut(req)
- const id = result.data.task_group?.id
- if (!id) {
- throw new Error('Invalid server response')
+ try {
+ const result = await client.getInstance().logsTaskgroupPut(req)
+ const id = result.data.task_group?.id
+ if (!id) {
+ throw new Error('Invalid server response')
+ }
+ navigate(`/search_logs/detail/${id}`)
+ } catch (e) {
+ // FIXME
+ Modal.error({
+ content: e.message,
+ })
}
- navigate(`/search_logs/detail/${id}`)
- } catch (e) {
- // FIXME
- Modal.error({
- content: e.message,
- })
- }
- setSubmitting(false)
- }, [])
+ setSubmitting(false)
+ },
+ [navigate]
+ )
return (