From aaa6ebb2312d601a74ef491ece989eda3503d9b4 Mon Sep 17 00:00:00 2001 From: Jack Westbrook Date: Tue, 26 Jan 2021 15:35:30 +0100 Subject: [PATCH 01/41] DashboardSettings: fixes vertical scrolling (#30640) * fix(dashboardsettings): allow view to scroll vertically * refactor(dashboardsettings): use theme bg colour instead of palette colour --- .../DashboardSettings/DashboardSettings.tsx | 80 +++++++++++-------- .../sass/components/_dashboard_settings.scss | 6 -- 2 files changed, 48 insertions(+), 38 deletions(-) diff --git a/public/app/features/dashboard/components/DashboardSettings/DashboardSettings.tsx b/public/app/features/dashboard/components/DashboardSettings/DashboardSettings.tsx index 6e165184d46..76c0b15aacf 100644 --- a/public/app/features/dashboard/components/DashboardSettings/DashboardSettings.tsx +++ b/public/app/features/dashboard/components/DashboardSettings/DashboardSettings.tsx @@ -1,7 +1,8 @@ import React, { PureComponent } from 'react'; -import { cx } from 'emotion'; +import { css, cx } from 'emotion'; import { selectors } from '@grafana/e2e-selectors'; -import { Button, CustomScrollbar, Icon, IconName } from '@grafana/ui'; +import { Button, CustomScrollbar, Icon, IconName, stylesFactory } from '@grafana/ui'; +import config from 'app/core/config'; import { contextSrv } from 'app/core/services/context_srv'; import { BackButton } from 'app/core/components/BackButton/BackButton'; import { dashboardWatcher } from 'app/features/live/dashboard/dashboardWatcher'; @@ -15,12 +16,20 @@ import { AnnotationsSettings } from './AnnotationsSettings'; import { LinksSettings } from './LinksSettings'; import { VersionsSettings } from './VersionsSettings'; import { JsonEditorSettings } from './JsonEditorSettings'; +import { GrafanaTheme } from '@grafana/data'; export interface Props { dashboard: DashboardModel; updateLocation: typeof updateLocation; editview: string; } +export interface SettingsPage { + id: string; + title: string; + icon: IconName; + render: () => React.ReactNode; +} + export class DashboardSettings extends PureComponent { onClose = () => { this.props.updateLocation({ @@ -142,6 +151,7 @@ export class DashboardSettings extends PureComponent { const currentPage = pages.find((page) => page.id === editview) ?? pages[0]; const canSaveAs = contextSrv.hasEditPermissionInFolders; const canSave = dashboard.meta.canSave; + const styles = getStyles(config.theme); return (
@@ -154,40 +164,46 @@ export class DashboardSettings extends PureComponent { {dashboard.title} / Settings
-
- -
- + +
+
+
{currentPage.render()}
- +
-
+
); } } -export interface SettingsPage { - id: string; - title: string; - icon: IconName; - render: () => React.ReactNode; -} +const getStyles = stylesFactory((theme: GrafanaTheme) => ({ + scrollInner: css` + min-width: 100%; + min-height: 100%; + `, + settingsWrapper: css` + background: ${theme.colors.bg1}; + display: flex; + min-height: 100%; + width: 100%; + `, +})); diff --git a/public/sass/components/_dashboard_settings.scss b/public/sass/components/_dashboard_settings.scss index 3b4fa5c64e3..6d46a7c469f 100644 --- a/public/sass/components/_dashboard_settings.scss +++ b/public/sass/components/_dashboard_settings.scss @@ -20,12 +20,6 @@ background: $panel-bg; } -.dashboard-settings__scroll { - flex-grow: 1; - min-width: 0; - height: 100%; -} - .dashboard-settings__content { flex-grow: 1; min-width: 0; From d2c88034e9d5fbffbe3fe73c70dd5023e9f95509 Mon Sep 17 00:00:00 2001 From: Jack Westbrook Date: Tue, 26 Jan 2021 15:48:13 +0100 Subject: [PATCH 02/41] chore(grafana-ui): bump storybook to 6.1.15 (#30642) --- packages/grafana-ui/package.json | 14 +- yarn.lock | 1697 ++++++++++++++++-------------- 2 files changed, 914 insertions(+), 797 deletions(-) diff --git a/packages/grafana-ui/package.json b/packages/grafana-ui/package.json index 77b21d5148b..8da2e491115 100644 --- a/packages/grafana-ui/package.json +++ b/packages/grafana-ui/package.json @@ -78,12 +78,12 @@ "@rollup/plugin-commonjs": "16.0.0", "@rollup/plugin-image": "2.0.5", "@rollup/plugin-node-resolve": "10.0.0", - "@storybook/addon-controls": "6.1.9", - "@storybook/addon-essentials": "6.1.9", - "@storybook/addon-knobs": "6.1.9", - "@storybook/addon-storysource": "6.1.9", - "@storybook/react": "6.1.9", - "@storybook/theming": "6.1.9", + "@storybook/addon-controls": "6.1.15", + "@storybook/addon-essentials": "6.1.15", + "@storybook/addon-knobs": "6.1.15", + "@storybook/addon-storysource": "6.1.15", + "@storybook/react": "6.1.15", + "@storybook/theming": "6.1.15", "@types/classnames": "2.2.7", "@types/common-tags": "^1.8.0", "@types/d3": "5.7.2", @@ -110,7 +110,7 @@ "rollup-plugin-terser": "7.0.2", "rollup-plugin-typescript2": "0.29.0", "rollup-plugin-visualizer": "4.2.0", - "storybook-dark-mode": "1.0.3", + "storybook-dark-mode": "1.0.4", "ts-loader": "8.0.11", "typescript": "4.1.2", "webpack-filter-warnings-plugin": "1.2.1" diff --git a/yarn.lock b/yarn.lock index 4f28b7f9f23..7d9e2af4c12 100644 --- a/yarn.lock +++ b/yarn.lock @@ -108,10 +108,17 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/compat-data@^7.12.1", "@babel/compat-data@^7.12.5": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.12.5.tgz#f56db0c4bb1bbbf221b4e81345aab4141e7cb0e9" - integrity sha512-DTsS7cxrsH3by8nqQSpFSyjSfSYl57D6Cf4q8dW3LK83tBKBDCkfcay1nYkXq1nIHXnpX8WMMb/O25HOy3h1zg== +"@babel/code-frame@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" + integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== + dependencies: + "@babel/highlight" "^7.10.4" + +"@babel/compat-data@^7.12.5", "@babel/compat-data@^7.12.7": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.12.7.tgz#9329b4782a7d6bbd7eef57e11addf91ee3ef1e41" + integrity sha512-YaxPMGs/XIWtYqrdEOZOCPsVWfEoriXopnsz3/i7apYPXQ3698UFhS6dVT1KN5qOsWmVgw/FOrmQgpRaZayGsw== "@babel/compat-data@^7.8.4": version "7.8.5" @@ -131,19 +138,19 @@ invariant "^2.2.4" semver "^5.5.0" -"@babel/core@7.11.6": - version "7.11.6" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.6.tgz#3a9455dc7387ff1bac45770650bc13ba04a15651" - integrity sha512-Wpcv03AGnmkgm6uS6k8iwhIwTrcP0m17TL1n1sy7qD0qelDu4XNeW0dN0mHfa+Gei211yDaLoEe/VlbXQzM4Bg== +"@babel/core@7.12.9": + version "7.12.9" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.9.tgz#fd450c4ec10cdbb980e2928b7aa7a28484593fc8" + integrity sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ== dependencies: "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.11.6" - "@babel/helper-module-transforms" "^7.11.0" - "@babel/helpers" "^7.10.4" - "@babel/parser" "^7.11.5" - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.11.5" - "@babel/types" "^7.11.5" + "@babel/generator" "^7.12.5" + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helpers" "^7.12.5" + "@babel/parser" "^7.12.7" + "@babel/template" "^7.12.7" + "@babel/traverse" "^7.12.9" + "@babel/types" "^7.12.7" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.1" @@ -237,24 +244,23 @@ source-map "^0.5.0" "@babel/core@^7.12.1", "@babel/core@^7.12.3": - version "7.12.3" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.3.tgz#1b436884e1e3bff6fb1328dc02b208759de92ad8" - integrity sha512-0qXcZYKZp3/6N2jKYVxZv0aNCsxTSVCiK72DTiTYZAu7sjg73W0/aynWjMbiGd87EQL4WyA8reiJVh92AVla9g== + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.10.tgz#b79a2e1b9f70ed3d84bbfb6d8c4ef825f606bccd" + integrity sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w== dependencies: "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.12.1" + "@babel/generator" "^7.12.10" "@babel/helper-module-transforms" "^7.12.1" - "@babel/helpers" "^7.12.1" - "@babel/parser" "^7.12.3" - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.12.1" - "@babel/types" "^7.12.1" + "@babel/helpers" "^7.12.5" + "@babel/parser" "^7.12.10" + "@babel/template" "^7.12.7" + "@babel/traverse" "^7.12.10" + "@babel/types" "^7.12.10" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.1" json5 "^2.1.2" lodash "^4.17.19" - resolve "^1.3.2" semver "^5.4.1" source-map "^0.5.0" @@ -279,12 +285,12 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.11.6", "@babel/generator@^7.12.1", "@babel/generator@^7.12.5": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.5.tgz#a2c50de5c8b6d708ab95be5e6053936c1884a4de" - integrity sha512-m16TQQJ8hPt7E+OS/XVQg/7U184MLXtvuGbCdA7na61vha+ImkyyNM/9DDA0unYCVZn3ZOhng+qz48/KBOT96A== +"@babel/generator@^7.12.1", "@babel/generator@^7.12.10", "@babel/generator@^7.12.11", "@babel/generator@^7.12.5": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.11.tgz#98a7df7b8c358c9a37ab07a24056853016aba3af" + integrity sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA== dependencies: - "@babel/types" "^7.12.5" + "@babel/types" "^7.12.11" jsesc "^2.5.1" source-map "^0.5.0" @@ -338,12 +344,12 @@ lodash "^4.17.13" source-map "^0.5.0" -"@babel/helper-annotate-as-pure@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz#5bf0d495a3f757ac3bda48b5bf3b3ba309c72ba3" - integrity sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA== +"@babel/helper-annotate-as-pure@^7.10.4", "@babel/helper-annotate-as-pure@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.10.tgz#54ab9b000e60a93644ce17b3f37d313aaf1d115d" + integrity sha512-XplmVbC1n+KY6jL8/fgLVXXUauDIB+lD5+GsQEh6F6GBF1dq1qy4DP4yXWzDKcoqXB3X58t61e85Fitoww4JVQ== dependencies: - "@babel/types" "^7.10.4" + "@babel/types" "^7.12.10" "@babel/helper-annotate-as-pure@^7.7.4": version "7.7.4" @@ -383,23 +389,6 @@ "@babel/helper-explode-assignable-expression" "^7.8.3" "@babel/types" "^7.8.3" -"@babel/helper-builder-react-jsx-experimental@^7.12.1": - version "7.12.4" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.12.4.tgz#55fc1ead5242caa0ca2875dcb8eed6d311e50f48" - integrity sha512-AjEa0jrQqNk7eDQOo0pTfUOwQBMF+xVqrausQwT9/rTKy0g04ggFNaJpaE09IQMn9yExluigWMJcj0WC7bq+Og== - dependencies: - "@babel/helper-annotate-as-pure" "^7.10.4" - "@babel/helper-module-imports" "^7.12.1" - "@babel/types" "^7.12.1" - -"@babel/helper-builder-react-jsx@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.10.4.tgz#8095cddbff858e6fa9c326daee54a2f2732c1d5d" - integrity sha512-5nPcIZ7+KKDxT1427oBivl9V9YTal7qk0diccnh7RrcgrT/pGFOjgGw1dgryyx1GvHEpXVfoDF6Ak3rTiWh8Rg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.10.4" - "@babel/types" "^7.10.4" - "@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" @@ -426,7 +415,7 @@ "@babel/traverse" "^7.8.3" "@babel/types" "^7.8.3" -"@babel/helper-compilation-targets@^7.12.1": +"@babel/helper-compilation-targets@^7.12.5": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz#cb470c76198db6a24e9dbc8987275631e5d29831" integrity sha512-+qH6NrscMolUlzOYngSBMIOQpKUGPPsc61Bu5W10mg84LxZ7cmvnBHzARKbDoFxVvqqAbj6Tg6N7bSrWSPXMyw== @@ -482,12 +471,11 @@ "@babel/helper-split-export-declaration" "^7.8.3" "@babel/helper-create-regexp-features-plugin@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.1.tgz#18b1302d4677f9dc4740fe8c9ed96680e29d37e8" - integrity sha512-rsZ4LGvFTZnzdNZR5HZdmJVuXK8834R5QkF3WvcnBhrlVtF0HSIUC6zbreL9MgjTywhKokn8RIYRiq99+DLAxA== + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.7.tgz#2084172e95443fa0a09214ba1bb328f9aea1278f" + integrity sha512-idnutvQPdpbduutvi3JVfEgcVIHooQnhvhx0Nk9isOINOIGYkZea1Pk2JlJRiUnMefrlvr0vkByATBY/mB4vjQ== dependencies: "@babel/helper-annotate-as-pure" "^7.10.4" - "@babel/helper-regex" "^7.10.4" regexpu-core "^4.7.1" "@babel/helper-create-regexp-features-plugin@^7.7.4": @@ -574,14 +562,14 @@ "@babel/template" "^7.1.0" "@babel/types" "^7.0.0" -"@babel/helper-function-name@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a" - integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ== +"@babel/helper-function-name@^7.10.4", "@babel/helper-function-name@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz#1fd7738aee5dcf53c3ecff24f1da9c511ec47b42" + integrity sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA== dependencies: - "@babel/helper-get-function-arity" "^7.10.4" - "@babel/template" "^7.10.4" - "@babel/types" "^7.10.4" + "@babel/helper-get-function-arity" "^7.12.10" + "@babel/template" "^7.12.7" + "@babel/types" "^7.12.11" "@babel/helper-function-name@^7.7.4": version "7.7.4" @@ -608,12 +596,12 @@ dependencies: "@babel/types" "^7.0.0" -"@babel/helper-get-function-arity@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2" - integrity sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A== +"@babel/helper-get-function-arity@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz#b158817a3165b5faa2047825dfa61970ddcc16cf" + integrity sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag== dependencies: - "@babel/types" "^7.10.4" + "@babel/types" "^7.12.10" "@babel/helper-get-function-arity@^7.7.4": version "7.7.4" @@ -657,12 +645,12 @@ dependencies: "@babel/types" "^7.5.5" -"@babel/helper-member-expression-to-functions@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.1.tgz#fba0f2fcff3fba00e6ecb664bb5e6e26e2d6165c" - integrity sha512-k0CIe3tXUKTRSoEx1LQEPFU9vRQfqHtl+kf8eNnDqb4AUJEy5pz6aIiog+YWtVm2jpggjS1laH68bPsR+KWWPQ== +"@babel/helper-member-expression-to-functions@^7.12.1", "@babel/helper-member-expression-to-functions@^7.12.7": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz#aa77bd0396ec8114e5e30787efa78599d874a855" + integrity sha512-DCsuPyeWxeHgh1Dus7APn7iza42i/qXqiFPWyBDdOFtvS581JQePsc1F/nD+fHrcswhLlRc2UpYS1NwERxZhHw== dependencies: - "@babel/types" "^7.12.1" + "@babel/types" "^7.12.7" "@babel/helper-member-expression-to-functions@^7.7.4": version "7.7.4" @@ -685,7 +673,7 @@ dependencies: "@babel/types" "^7.0.0" -"@babel/helper-module-imports@^7.12.1": +"@babel/helper-module-imports@^7.12.1", "@babel/helper-module-imports@^7.12.5": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz#1bfc0229f794988f76ed0a4d4e90860850b54dfb" integrity sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA== @@ -706,7 +694,7 @@ dependencies: "@babel/types" "^7.8.3" -"@babel/helper-module-transforms@^7.11.0", "@babel/helper-module-transforms@^7.12.1": +"@babel/helper-module-transforms@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz#7954fec71f5b32c48e4b303b437c34453fd7247c" integrity sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w== @@ -765,12 +753,12 @@ dependencies: "@babel/types" "^7.0.0" -"@babel/helper-optimise-call-expression@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz#50dc96413d594f995a77905905b05893cd779673" - integrity sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg== +"@babel/helper-optimise-call-expression@^7.10.4", "@babel/helper-optimise-call-expression@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.10.tgz#94ca4e306ee11a7dd6e9f42823e2ac6b49881e2d" + integrity sha512-4tpbU0SrSTjjt65UMWSrUOPZTsgvPgGG4S8QSTNHacKzpS51IVWGDj0yCwyeZND/i+LSN2g/O63jEXEWm49sYQ== dependencies: - "@babel/types" "^7.10.4" + "@babel/types" "^7.12.10" "@babel/helper-optimise-call-expression@^7.7.4": version "7.7.4" @@ -813,13 +801,6 @@ dependencies: lodash "^4.17.13" -"@babel/helper-regex@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.10.5.tgz#32dfbb79899073c415557053a19bd055aae50ae0" - integrity sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg== - dependencies: - lodash "^4.17.19" - "@babel/helper-regex@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.8.3.tgz#139772607d51b93f23effe72105b319d2a4c6965" @@ -869,14 +850,14 @@ "@babel/types" "^7.5.5" "@babel/helper-replace-supers@^7.12.1": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.5.tgz#f009a17543bbbbce16b06206ae73b63d3fca68d9" - integrity sha512-5YILoed0ZyIpF4gKcpZitEnXEJ9UoDRki1Ey6xz46rxOzfNMAhVIJMoune1hmPVxh40LRv1+oafz7UsWX+vyWA== + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.11.tgz#ea511658fc66c7908f923106dd88e08d1997d60d" + integrity sha512-q+w1cqmhL7R0FNzth/PLLp2N+scXEK/L2AHbXUyydxp828F4FEa5WcVoqui9vFRiHDQErj9Zof8azP32uGVTRA== dependencies: - "@babel/helper-member-expression-to-functions" "^7.12.1" - "@babel/helper-optimise-call-expression" "^7.10.4" - "@babel/traverse" "^7.12.5" - "@babel/types" "^7.12.5" + "@babel/helper-member-expression-to-functions" "^7.12.7" + "@babel/helper-optimise-call-expression" "^7.12.10" + "@babel/traverse" "^7.12.10" + "@babel/types" "^7.12.11" "@babel/helper-replace-supers@^7.7.4": version "7.7.4" @@ -938,12 +919,12 @@ dependencies: "@babel/types" "^7.12.1" -"@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" - integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg== +"@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0", "@babel/helper-split-export-declaration@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz#1b4cc424458643c47d37022223da33d76ea4603a" + integrity sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g== dependencies: - "@babel/types" "^7.11.0" + "@babel/types" "^7.12.11" "@babel/helper-split-export-declaration@^7.4.4": version "7.4.4" @@ -976,15 +957,20 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== +"@babel/helper-validator-identifier@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" + integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== + "@babel/helper-validator-identifier@^7.9.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.0.tgz#ad53562a7fc29b3b9a91bbf7d10397fd146346ed" integrity sha512-6G8bQKjOh+of4PV/ThDm/rRqlU7+IGoJuofpagU5GlEl29Vv0RGqqt86ZGRV8ZuSOY3o+8yXl5y782SMcG7SHw== -"@babel/helper-validator-option@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.1.tgz#175567380c3e77d60ff98a54bb015fe78f2178d9" - integrity sha512-YpJabsXlJVWP0USHjnC/AQDTLlZERbON577YUVO/wLpqyj6HAtVYnWaQaN0iUN+1/tWn3c+uKKXjRut5115Y2A== +"@babel/helper-validator-option@^7.12.1", "@babel/helper-validator-option@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz#d66cb8b7a3e7fe4c6962b32020a131ecf0847f4f" + integrity sha512-TBFCyj939mFSdeX7U7DDj32WtzYY7fDcalgq8v3fBZMNOJQNn7nOYzMaUCiPxPYfCup69mtIpqlKgMZLvQ8Xhw== "@babel/helper-wrap-function@^7.10.4": version "7.12.3" @@ -1016,7 +1002,7 @@ "@babel/traverse" "^7.8.3" "@babel/types" "^7.8.3" -"@babel/helpers@^7.10.4", "@babel/helpers@^7.12.1": +"@babel/helpers@^7.12.5": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.5.tgz#1a1ba4a768d9b58310eda516c449913fe647116e" integrity sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA== @@ -1116,10 +1102,10 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.2.tgz#871807f10442b92ff97e4783b9b54f6a0ca812d0" integrity sha512-PApSXlNMJyB4JiGVhCOlzKIif+TKFTvu0aQAhnTvfP/z3vVSN6ZypH5bfUNwFXXjRQtUEBNFd2PtmCmG2Py3qQ== -"@babel/parser@^7.10.4", "@babel/parser@^7.11.5", "@babel/parser@^7.12.3", "@babel/parser@^7.12.5": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.5.tgz#b4af32ddd473c0bfa643bd7ff0728b8e71b81ea0" - integrity sha512-FVM6RZQ0mn2KCf1VUED7KepYeUWoVShczewOCfm3nzoBybaih51h+sYVVGthW9M6lPByEPTQf+xm27PBdlpwmQ== +"@babel/parser@^7.12.10", "@babel/parser@^7.12.11", "@babel/parser@^7.12.3", "@babel/parser@^7.12.7": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.11.tgz#9ce3595bcd74bc5c466905e86c535b8b25011e79" + integrity sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg== "@babel/parser@^7.7.4": version "7.7.4" @@ -1142,9 +1128,9 @@ integrity sha512-E6SpIDJZ0cZAKoCNk+qSDd0ChfTnpiJN9FfNf3RZ20dzwA2vL2oq5IX1XTVT+4vDmRlta2nGk5HGMMskJAR+4A== "@babel/plugin-proposal-async-generator-functions@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.1.tgz#dc6c1170e27d8aca99ff65f4925bd06b1c90550e" - integrity sha512-d+/o30tJxFxrA1lhzJqiUcEJdI6jKlNregCv5bASeGf2Q4MXmnwH7viDo7nhx1/ohf09oaH8j1GVYG/e3Yqk6A== + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.12.tgz#04b8f24fd4532008ab4e79f788468fd5a8476566" + integrity sha512-nrz9y0a4xmUrRq51bYkWJIO5SBZyG2ys2qinHsN0zHDHVsUaModrkpyWWWXfGqYQmOL3x9sQIcTNN/pBGpo09A== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/helper-remap-async-to-generator" "^7.12.1" @@ -1177,9 +1163,9 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-proposal-decorators@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.12.1.tgz#59271439fed4145456c41067450543aee332d15f" - integrity sha512-knNIuusychgYN8fGJHONL0RbFxLGawhXOJNLBk75TniTsZZeA+wdkDuv6wp4lGwzQEKjZi6/WYtnb3udNPmQmQ== + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.12.12.tgz#067a6d3d6ca86d54cf56bb183239199c20daeafe" + integrity sha512-fhkE9lJYpw2mjHelBpM2zCbaA11aov2GJs7q4cFaXNrWx0H3bW58H9Esy2rdtYOghFBEYUDRIpvlgi+ZD+AvvQ== dependencies: "@babel/helper-create-class-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" @@ -1273,10 +1259,10 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" -"@babel/plugin-proposal-numeric-separator@^7.12.1": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.5.tgz#b1ce757156d40ed79d59d467cb2b154a5c4149ba" - integrity sha512-UiAnkKuOrCyjZ3sYNHlRlfuZJbBHknMQ9VMwVeX97Ofwx7RpD6gS2HfqTCh8KNUQgcOm8IKt103oR4KIjh7Q8g== +"@babel/plugin-proposal-numeric-separator@^7.12.7": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.7.tgz#8bf253de8139099fea193b297d23a9d406ef056b" + integrity sha512-8c+uy0qmnRTeukiGsjLGy6uVs/TFjJchGXUeBqlG4VWYOdJWkhhVPdQ3uHwbmalfJwv2JsV0qffXP4asRfL2SQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-numeric-separator" "^7.10.4" @@ -1289,16 +1275,7 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-numeric-separator" "^7.8.3" -"@babel/plugin-proposal-object-rest-spread@7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz#bd81f95a1f746760ea43b6c2d3d62b11790ad0af" - integrity sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-transform-parameters" "^7.10.4" - -"@babel/plugin-proposal-object-rest-spread@^7.12.1": +"@babel/plugin-proposal-object-rest-spread@7.12.1", "@babel/plugin-proposal-object-rest-spread@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz#def9bd03cea0f9b72283dac0ec22d289c7691069" integrity sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA== @@ -1363,10 +1340,10 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.0" -"@babel/plugin-proposal-optional-chaining@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.1.tgz#cce122203fc8a32794296fc377c6dedaf4363797" - integrity sha512-c2uRpY6WzaVDzynVY9liyykS+kVU+WRZPMPYpkelXH8KBt1oXoI89kPbZKKG/jDT5UK92FTW2fZkZaJhdiBabw== +"@babel/plugin-proposal-optional-chaining@^7.12.1", "@babel/plugin-proposal-optional-chaining@^7.12.7": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.7.tgz#e02f0ea1b5dc59d401ec16fb824679f683d3303c" + integrity sha512-4ovylXZ0PWmwoOvhU2vhnzVNnm88/Sm9nx7V8BPgMvAzn5zDou3/Awy0EjglyubVHasJj+XCEkr/r1X3P5elCA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" @@ -1525,14 +1502,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.10.4.tgz#39abaae3cbf710c4373d8429484e6ba21340166c" - integrity sha512-KCg9mio9jwiARCB7WAcQ7Y1q+qicILjoK8LP/VkPkEKaf5dkaZZK1EcTe91a3JJlZ3qy6L5s9X52boEYi8DM9g== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-jsx@^7.12.1": +"@babel/plugin-syntax-jsx@7.12.1", "@babel/plugin-syntax-jsx@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz#9d9d357cc818aa7ae7935917c1257f67677a0926" integrity sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg== @@ -1720,10 +1690,10 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-block-scoping@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.1.tgz#f0ee727874b42a208a48a586b84c3d222c2bbef1" - integrity sha512-zJyAC9sZdE60r1nVQHblcfCj29Dh2Y0DOvlMkcqSo0ckqjiCwNiUezUKw+RjOCwGfpLRwnAeQ2XlLpsnGkvv9w== +"@babel/plugin-transform-block-scoping@^7.12.1", "@babel/plugin-transform-block-scoping@^7.12.11": + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.12.tgz#d93a567a152c22aea3b1929bb118d1d0a175cdca" + integrity sha512-VOEPQ/ExOVqbukuP7BYJtI5ZxxsmegTwzZ04j1aF0dkSypGo9XpDHuOrABsJu+ie+penpSJheDJ11x1BEZNiyQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -1911,9 +1881,9 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-transform-flow-strip-types@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.12.1.tgz#8430decfa7eb2aea5414ed4a3fa6e1652b7d77c4" - integrity sha512-8hAtkmsQb36yMmEtk2JZ9JnVyDSnDOdlB+0nEGzIDLuK4yR3JcEjfuFPYkdEPSh8Id+rAMeBEn+X0iVEyho6Hg== + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.12.10.tgz#d85e30ecfa68093825773b7b857e5085bbd32c95" + integrity sha512-0ti12wLTLeUIzu9U7kjqIn4MyOL7+Wibc7avsHhj4o1l5C0ATs8p2IMHrVYjm9t9wzhfEO6S3kxax0Rpdo8LTg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-flow" "^7.12.1" @@ -2226,7 +2196,7 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/helper-replace-supers" "^7.8.3" -"@babel/plugin-transform-parameters@^7.10.4", "@babel/plugin-transform-parameters@^7.12.1": +"@babel/plugin-transform-parameters@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.1.tgz#d2e963b038771650c922eff593799c96d853255d" integrity sha512-xq9C5EQhdPK23ZeCdMxl8bbRnAgHFrw5EOC3KJUsSylZqdkCaFEXxGSBuTSObOpiiHHNyb82es8M1QYgfQGfNg== @@ -2294,21 +2264,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-react-jsx-development@^7.12.5": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.5.tgz#677de5b96da310430d6cfb7fee16a1603afa3d56" - integrity sha512-1JJusg3iPgsZDthyWiCr3KQiGs31ikU/mSf2N2dSYEAO0GEImmVUbWf0VoSDGDFTAn5Dj4DUiR6SdIXHY7tELA== +"@babel/plugin-transform-react-jsx-development@^7.12.7": + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.12.tgz#bccca33108fe99d95d7f9e82046bfe762e71f4e7" + integrity sha512-i1AxnKxHeMxUaWVXQOSIco4tvVvvCxMSfeBMnMM06mpaJt3g+MpxYQQrDfojUQldP1xxraPSJYSMEljoWM/dCg== dependencies: - "@babel/helper-builder-react-jsx-experimental" "^7.12.1" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-jsx" "^7.12.1" - -"@babel/plugin-transform-react-jsx-self@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.12.1.tgz#ef43cbca2a14f1bd17807dbe4376ff89d714cf28" - integrity sha512-FbpL0ieNWiiBB5tCldX17EtXgmzeEZjFrix72rQYeq9X6nUK38HCaxexzVQrZWXanxKJPKVVIU37gFjEQYkPkA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-react-jsx" "^7.12.12" "@babel/plugin-transform-react-jsx-self@^7.8.3": version "7.8.3" @@ -2318,13 +2279,6 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-jsx" "^7.8.3" -"@babel/plugin-transform-react-jsx-source@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.12.1.tgz#d07de6863f468da0809edcf79a1aa8ce2a82a26b" - integrity sha512-keQ5kBfjJNRc6zZN1/nVHCd6LLIHq4aUKcVnvE/2l+ZZROSbqoiGFRtT5t3Is89XJxBQaP7NLZX2jgGHdZvvFQ== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@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" @@ -2333,15 +2287,16 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-jsx" "^7.8.3" -"@babel/plugin-transform-react-jsx@^7.12.1", "@babel/plugin-transform-react-jsx@^7.12.5": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.5.tgz#39ede0e30159770561b6963be143e40af3bde00c" - integrity sha512-2xkcPqqrYiOQgSlM/iwto1paPijjsDbUynN13tI6bosDz/jOW3CRzYguIE8wKX32h+msbBM22Dv5fwrFkUOZjQ== +"@babel/plugin-transform-react-jsx@^7.12.1", "@babel/plugin-transform-react-jsx@^7.12.10", "@babel/plugin-transform-react-jsx@^7.12.12": + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.12.tgz#b0da51ffe5f34b9a900e9f1f5fb814f9e512d25e" + integrity sha512-JDWGuzGNWscYcq8oJVCtSE61a5+XAOos+V0HrxnDieUus4UMnBEosDnY1VJqU5iZ4pA04QY7l0+JvHL1hZEfsw== dependencies: - "@babel/helper-builder-react-jsx" "^7.10.4" - "@babel/helper-builder-react-jsx-experimental" "^7.12.1" + "@babel/helper-annotate-as-pure" "^7.12.10" + "@babel/helper-module-imports" "^7.12.5" "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-jsx" "^7.12.1" + "@babel/types" "^7.12.12" "@babel/plugin-transform-react-jsx@^7.8.3": version "7.8.3" @@ -2452,13 +2407,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-sticky-regex@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.1.tgz#5c24cf50de396d30e99afc8d1c700e8bce0f5caf" - integrity sha512-CiUgKQ3AGVk7kveIaPEET1jNDhZZEl1RPMWdTBE1799bdz++SwqDHStmxfCtDfBhQgCl38YRiSnrMuUMZIWSUQ== +"@babel/plugin-transform-sticky-regex@^7.12.7": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.7.tgz#560224613ab23987453948ed21d0b0b193fa7fad" + integrity sha512-VEiqZL5N/QvDbdjfYQBhruN0HYjSPjC4XkeqW4ny/jNtH9gcbgaqBIXYEZCNnESMAGs0/K/R7oFGMhOyu/eIxg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-regex" "^7.10.4" "@babel/plugin-transform-sticky-regex@^7.7.4": version "7.7.4" @@ -2499,10 +2453,10 @@ "@babel/helper-annotate-as-pure" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-typeof-symbol@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.1.tgz#9ca6be343d42512fbc2e68236a82ae64bc7af78a" - integrity sha512-EPGgpGy+O5Kg5pJFNDKuxt9RdmTgj5sgrus2XVeMp/ZIbOESadgILUbm50SNpghOh3/6yrbsH+NB5+WJTmsA7Q== +"@babel/plugin-transform-typeof-symbol@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.10.tgz#de01c4c8f96580bd00f183072b0d0ecdcf0dec4b" + integrity sha512-JQ6H8Rnsogh//ijxspCjc21YPd3VLVoYtAwv3zQmqAt8YGYUtdo5usNhdl4b9/Vir2kPFZl6n1h0PfUz4hJhaA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -2756,15 +2710,15 @@ semver "^5.5.0" "@babel/preset-env@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.12.1.tgz#9c7e5ca82a19efc865384bb4989148d2ee5d7ac2" - integrity sha512-H8kxXmtPaAGT7TyBvSSkoSTUK6RHh61So05SyEbpmr0MCZrsNYn7mGMzzeYoOUCdHzww61k8XBft2TaES+xPLg== + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.12.11.tgz#55d5f7981487365c93dbbc84507b1c7215e857f9" + integrity sha512-j8Tb+KKIXKYlDBQyIOy4BLxzv1NUOwlHfZ74rvW+Z0Gp4/cI2IMDPBWAgWceGcE7aep9oL/0K9mlzlMGxA8yNw== dependencies: - "@babel/compat-data" "^7.12.1" - "@babel/helper-compilation-targets" "^7.12.1" - "@babel/helper-module-imports" "^7.12.1" + "@babel/compat-data" "^7.12.7" + "@babel/helper-compilation-targets" "^7.12.5" + "@babel/helper-module-imports" "^7.12.5" "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-validator-option" "^7.12.1" + "@babel/helper-validator-option" "^7.12.11" "@babel/plugin-proposal-async-generator-functions" "^7.12.1" "@babel/plugin-proposal-class-properties" "^7.12.1" "@babel/plugin-proposal-dynamic-import" "^7.12.1" @@ -2772,10 +2726,10 @@ "@babel/plugin-proposal-json-strings" "^7.12.1" "@babel/plugin-proposal-logical-assignment-operators" "^7.12.1" "@babel/plugin-proposal-nullish-coalescing-operator" "^7.12.1" - "@babel/plugin-proposal-numeric-separator" "^7.12.1" + "@babel/plugin-proposal-numeric-separator" "^7.12.7" "@babel/plugin-proposal-object-rest-spread" "^7.12.1" "@babel/plugin-proposal-optional-catch-binding" "^7.12.1" - "@babel/plugin-proposal-optional-chaining" "^7.12.1" + "@babel/plugin-proposal-optional-chaining" "^7.12.7" "@babel/plugin-proposal-private-methods" "^7.12.1" "@babel/plugin-proposal-unicode-property-regex" "^7.12.1" "@babel/plugin-syntax-async-generators" "^7.8.0" @@ -2793,7 +2747,7 @@ "@babel/plugin-transform-arrow-functions" "^7.12.1" "@babel/plugin-transform-async-to-generator" "^7.12.1" "@babel/plugin-transform-block-scoped-functions" "^7.12.1" - "@babel/plugin-transform-block-scoping" "^7.12.1" + "@babel/plugin-transform-block-scoping" "^7.12.11" "@babel/plugin-transform-classes" "^7.12.1" "@babel/plugin-transform-computed-properties" "^7.12.1" "@babel/plugin-transform-destructuring" "^7.12.1" @@ -2817,14 +2771,14 @@ "@babel/plugin-transform-reserved-words" "^7.12.1" "@babel/plugin-transform-shorthand-properties" "^7.12.1" "@babel/plugin-transform-spread" "^7.12.1" - "@babel/plugin-transform-sticky-regex" "^7.12.1" + "@babel/plugin-transform-sticky-regex" "^7.12.7" "@babel/plugin-transform-template-literals" "^7.12.1" - "@babel/plugin-transform-typeof-symbol" "^7.12.1" + "@babel/plugin-transform-typeof-symbol" "^7.12.10" "@babel/plugin-transform-unicode-escapes" "^7.12.1" "@babel/plugin-transform-unicode-regex" "^7.12.1" "@babel/preset-modules" "^0.1.3" - "@babel/types" "^7.12.1" - core-js-compat "^3.6.2" + "@babel/types" "^7.12.11" + core-js-compat "^3.8.0" semver "^5.5.0" "@babel/preset-flow@^7.12.1": @@ -2858,16 +2812,14 @@ "@babel/plugin-transform-react-jsx-source" "^7.8.3" "@babel/preset-react@^7.12.1": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.12.5.tgz#d45625f65d53612078a43867c5c6750e78772c56" - integrity sha512-jcs++VPrgyFehkMezHtezS2BpnUlR7tQFAyesJn1vGTO9aTFZrgIQrA5YydlTwxbcjMwkFY6i04flCigRRr3GA== + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.12.10.tgz#4fed65f296cbb0f5fb09de6be8cddc85cc909be9" + integrity sha512-vtQNjaHRl4DUpp+t+g4wvTHsLQuye+n0H/wsXIZRn69oz/fvNC7gQ4IK73zGJBaxvHoxElDvnYCthMcT7uzFoQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-react-display-name" "^7.12.1" - "@babel/plugin-transform-react-jsx" "^7.12.5" - "@babel/plugin-transform-react-jsx-development" "^7.12.5" - "@babel/plugin-transform-react-jsx-self" "^7.12.1" - "@babel/plugin-transform-react-jsx-source" "^7.12.1" + "@babel/plugin-transform-react-jsx" "^7.12.10" + "@babel/plugin-transform-react-jsx-development" "^7.12.7" "@babel/plugin-transform-react-pure-annotations" "^7.12.1" "@babel/preset-typescript@7.8.3": @@ -2879,17 +2831,18 @@ "@babel/plugin-transform-typescript" "^7.8.3" "@babel/preset-typescript@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.12.1.tgz#86480b483bb97f75036e8864fe404cc782cc311b" - integrity sha512-hNK/DhmoJPsksdHuI/RVrcEws7GN5eamhi28JkO52MqIxU8Z0QpmiSOQxZHWOHV7I3P4UjHV97ay4TcamMA6Kw== + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.12.7.tgz#fc7df8199d6aae747896f1e6c61fc872056632a3" + integrity sha512-nOoIqIqBmHBSEgBXWR4Dv/XBehtIFcw9PqZw6rFYuKrzsZmOQm3PR5siLBnKZFEsDb03IegG8nSjU/iXXXYRmw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-validator-option" "^7.12.1" "@babel/plugin-transform-typescript" "^7.12.1" "@babel/register@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.12.1.tgz#cdb087bdfc4f7241c03231f22e15d211acf21438" - integrity sha512-XWcmseMIncOjoydKZnWvWi0/5CUCD+ZYKhRwgYlWOrA8fGZ/FjuLRpqtIhLOVD/fvR1b9DQHtZPn68VvhpYf+Q== + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.12.10.tgz#19b87143f17128af4dbe7af54c735663b3999f60" + integrity sha512-EvX/BvMMJRAA3jZgILWgbsrHwBQvllC5T8B29McyME8DvkdOxk4ujESfrMvME8IHSDvWXrmMXxPvA/lx2gqPLQ== dependencies: find-cache-dir "^2.0.0" lodash "^4.17.19" @@ -2956,14 +2909,14 @@ "@babel/parser" "^7.6.0" "@babel/types" "^7.6.0" -"@babel/template@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" - integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA== +"@babel/template@^7.10.4", "@babel/template@^7.12.7": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.7.tgz#c817233696018e39fbb6c491d2fb684e05ed43bc" + integrity sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow== dependencies: "@babel/code-frame" "^7.10.4" - "@babel/parser" "^7.10.4" - "@babel/types" "^7.10.4" + "@babel/parser" "^7.12.7" + "@babel/types" "^7.12.7" "@babel/template@^7.3.3": version "7.10.1" @@ -3016,17 +2969,17 @@ globals "^11.1.0" lodash "^4.17.13" -"@babel/traverse@^7.10.4", "@babel/traverse@^7.11.5", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.5": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.5.tgz#78a0c68c8e8a35e4cacfd31db8bb303d5606f095" - integrity sha512-xa15FbQnias7z9a62LwYAA5SZZPkHIXpd42C6uW68o8uTuua96FHZy1y61Va5P/i83FAAcMpW8+A/QayntzuqA== +"@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.10", "@babel/traverse@^7.12.5", "@babel/traverse@^7.12.9": + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.12.tgz#d0cd87892704edd8da002d674bc811ce64743376" + integrity sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w== dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.12.5" - "@babel/helper-function-name" "^7.10.4" - "@babel/helper-split-export-declaration" "^7.11.0" - "@babel/parser" "^7.12.5" - "@babel/types" "^7.12.5" + "@babel/code-frame" "^7.12.11" + "@babel/generator" "^7.12.11" + "@babel/helper-function-name" "^7.12.11" + "@babel/helper-split-export-declaration" "^7.12.11" + "@babel/parser" "^7.12.11" + "@babel/types" "^7.12.12" debug "^4.1.0" globals "^11.1.0" lodash "^4.17.19" @@ -3109,12 +3062,12 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" -"@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.11.5", "@babel/types@^7.12.1", "@babel/types@^7.12.5": - version "7.12.6" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.6.tgz#ae0e55ef1cce1fbc881cd26f8234eb3e657edc96" - integrity sha512-hwyjw6GvjBLiyy3W0YQf0Z5Zf4NpYejUnKFcfcUhZCSffoBBp30w6wP2Wn6pk31jMYZvcOrB/1b7cGXvEoKogA== +"@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.11", "@babel/types@^7.12.12", "@babel/types@^7.12.5", "@babel/types@^7.12.7": + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.12.tgz#4608a6ec313abbd87afa55004d373ad04a96c299" + integrity sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ== dependencies: - "@babel/helper-validator-identifier" "^7.10.4" + "@babel/helper-validator-identifier" "^7.12.11" lodash "^4.17.19" to-fast-properties "^2.0.0" @@ -4685,32 +4638,32 @@ write-file-atomic "^2.3.0" "@mdx-js/loader@^1.6.19": - version "1.6.21" - resolved "https://registry.yarnpkg.com/@mdx-js/loader/-/loader-1.6.21.tgz#e5b2b5c48d182e495d36104b0c7a5da96964a2dd" - integrity sha512-4xNtT7oal4PrLSpZE+75nj9XMwYwc5BuoHmer1GDmer2Hhg8DCLxskk4lWpXnMv+IUg7MboK0EAtZ2fk0szt3A== + version "1.6.22" + resolved "https://registry.yarnpkg.com/@mdx-js/loader/-/loader-1.6.22.tgz#d9e8fe7f8185ff13c9c8639c048b123e30d322c4" + integrity sha512-9CjGwy595NaxAYp0hF9B/A0lH6C8Rms97e2JS9d3jVUtILn6pT5i5IV965ra3lIWc7Rs1GG1tBdVF7dCowYe6Q== dependencies: - "@mdx-js/mdx" "1.6.21" - "@mdx-js/react" "1.6.21" + "@mdx-js/mdx" "1.6.22" + "@mdx-js/react" "1.6.22" loader-utils "2.0.0" -"@mdx-js/mdx@1.6.21", "@mdx-js/mdx@^1.6.19": - version "1.6.21" - resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-1.6.21.tgz#d3651b4802db7bdc399270c0ffa9e2aa99dd4b00" - integrity sha512-z35VI6qDw9eAzR/obtgHbYVUdb/Pm+oUnlP1lLR94Oe05Xs2H7vlAgpuFBCLH5g/egzAc2wZCyoVydr25CsF+A== +"@mdx-js/mdx@1.6.22", "@mdx-js/mdx@^1.6.19": + version "1.6.22" + resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-1.6.22.tgz#8a723157bf90e78f17dc0f27995398e6c731f1ba" + integrity sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA== dependencies: - "@babel/core" "7.11.6" - "@babel/plugin-syntax-jsx" "7.10.4" + "@babel/core" "7.12.9" + "@babel/plugin-syntax-jsx" "7.12.1" "@babel/plugin-syntax-object-rest-spread" "7.8.3" - "@mdx-js/util" "1.6.21" - babel-plugin-apply-mdx-type-prop "1.6.21" - babel-plugin-extract-import-names "1.6.21" + "@mdx-js/util" "1.6.22" + babel-plugin-apply-mdx-type-prop "1.6.22" + babel-plugin-extract-import-names "1.6.22" camelcase-css "2.0.1" - detab "2.0.3" + detab "2.0.4" hast-util-raw "6.0.1" lodash.uniq "4.5.0" - mdast-util-to-hast "9.1.2" + mdast-util-to-hast "10.0.1" remark-footnotes "2.0.0" - remark-mdx "1.6.21" + remark-mdx "1.6.22" remark-parse "8.0.3" remark-squeeze-paragraphs "4.0.0" style-to-object "0.3.0" @@ -4718,15 +4671,15 @@ unist-builder "2.0.3" unist-util-visit "2.0.3" -"@mdx-js/react@1.6.21", "@mdx-js/react@^1.6.19": - version "1.6.21" - resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-1.6.21.tgz#86d962471a5e160c59a6b32054aa55c0c7ca404e" - integrity sha512-CgSNT9sq2LAlhEbVlPg7DwUQkypz+CWaWGcJbkgmp9WCAy6vW33CQ44UbKPiH3wet9o+UbXeQOqzZd041va83g== +"@mdx-js/react@1.6.22", "@mdx-js/react@^1.6.19": + version "1.6.22" + resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-1.6.22.tgz#ae09b4744fddc74714ee9f9d6f17a66e77c43573" + integrity sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg== -"@mdx-js/util@1.6.21": - version "1.6.21" - resolved "https://registry.yarnpkg.com/@mdx-js/util/-/util-1.6.21.tgz#25f97a0a1b76e78c16ae5d98c6c73e1be8d89e39" - integrity sha512-6sANhqfEHu6gdHZSrzDjN18Y48mIon8f2Os6J+IFmMHN0IhNG/0PUIIsI07kA1sZ9t6vgZNBloVmcDa5WOSe6A== +"@mdx-js/util@1.6.22": + version "1.6.22" + resolved "https://registry.yarnpkg.com/@mdx-js/util/-/util-1.6.22.tgz#219dfd89ae5b97a8801f015323ffa4b62f45718b" + integrity sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA== "@microsoft/api-extractor-model@workspace:*": version "7.10.3" @@ -4781,11 +4734,12 @@ fastq "^1.6.0" "@npmcli/move-file@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.0.1.tgz#de103070dac0f48ce49cf6693c23af59c0f70464" - integrity sha512-Uv6h1sT+0DrblvIrolFtbvM1FgWm+/sy4B3pvLp67Zys+thcukzS5ekn7HsZFGpWP4Q3fYJCljbWQE/XivMRLw== + version "1.1.0" + resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.1.0.tgz#4ef8a53d727b9e43facf35404caf55ebf92cfec8" + integrity sha512-Iv2iq0JuyYjKeFkSR4LPaCdDZwlGK9X2cP/01nJcp3yMJ1FjNd9vpiEYvLUgzBxKPg2SFmaOhizoQsPc0LWeOQ== dependencies: mkdirp "^1.0.4" + rimraf "^2.7.1" "@octokit/auth-token@^2.4.0": version "2.4.4" @@ -4914,11 +4868,16 @@ schema-utils "^2.6.5" source-map "^0.7.3" -"@popperjs/core@2.5.4", "@popperjs/core@^2.4.4", "@popperjs/core@^2.5.4": +"@popperjs/core@2.5.4": version "2.5.4" resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.5.4.tgz#de25b5da9f727985a3757fd59b5d028aba75841a" integrity sha512-ZpKr+WTb8zsajqgDkvCEWgp6d5eJT6Q63Ng2neTbzBO76Lbe91vX/iVIW9dikq+Fs3yEo+ls4cxeXABD2LtcbQ== +"@popperjs/core@^2.5.4": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.6.0.tgz#f022195afdfc942e088ee2101285a1d31c7d727f" + integrity sha512-cPqjjzuFWNK3BSKLm0abspP0sp/IGOli4p5I5fKFAzdS8fvjdOwDCfZqAaIiXd9lPkOWi3SUUfZof3hEb7J/uw== + "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" @@ -5213,17 +5172,17 @@ resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5" integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ== -"@storybook/addon-actions@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-6.1.9.tgz#b6d185b8e4e73691acc428b59e4d331195d64a40" - integrity sha512-vYqwuaBHrjRbbuyf4WBc5uDhrSejVEEiCabuu4g00R3dN7P5Ne/tbSw9EkYbbrRKxlEhdkk83DU1/J/+mCY5jw== +"@storybook/addon-actions@6.1.15": + version "6.1.15" + resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-6.1.15.tgz#07f6770e419da2ca5398a346d150141951a744e8" + integrity sha512-Mw0wlF3a2OHmI/HyHTbLxRWKCrdRIkKcLHTLptMi/9sOHcPRniwB2jTD1hdzwZrQCPbvvAkYBntVYH0XkNkGEA== dependencies: - "@storybook/addons" "6.1.9" - "@storybook/api" "6.1.9" - "@storybook/client-api" "6.1.9" - "@storybook/components" "6.1.9" - "@storybook/core-events" "6.1.9" - "@storybook/theming" "6.1.9" + "@storybook/addons" "6.1.15" + "@storybook/api" "6.1.15" + "@storybook/client-api" "6.1.15" + "@storybook/components" "6.1.15" + "@storybook/core-events" "6.1.15" + "@storybook/theming" "6.1.15" core-js "^3.0.1" fast-deep-equal "^3.1.1" global "^4.3.2" @@ -5236,17 +5195,17 @@ util-deprecate "^1.0.2" uuid "^8.0.0" -"@storybook/addon-backgrounds@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/addon-backgrounds/-/addon-backgrounds-6.1.9.tgz#4e9647001b2f396f56428218480f541e3a8a0e60" - integrity sha512-0/nnbnWZqo4NjyHFxcCHkcU+t8uUdk///9jSXRs4swmOLIFRaftEc/ZJ2rScu1Sc7y0CQdbk1Jjyx5/2cHBQtw== +"@storybook/addon-backgrounds@6.1.15": + version "6.1.15" + resolved "https://registry.yarnpkg.com/@storybook/addon-backgrounds/-/addon-backgrounds-6.1.15.tgz#2b7b68bad10b22af5736979563123f3d3bf86003" + integrity sha512-nb9XMXjjjUZoq8Km9PpgIRRo8eWRdjWiSg4QAD8lHtzEC06b2pWjEepZ/77vVw1lL2acTnbyZKvj8yKfs5fqEA== dependencies: - "@storybook/addons" "6.1.9" - "@storybook/api" "6.1.9" - "@storybook/client-logger" "6.1.9" - "@storybook/components" "6.1.9" - "@storybook/core-events" "6.1.9" - "@storybook/theming" "6.1.9" + "@storybook/addons" "6.1.15" + "@storybook/api" "6.1.15" + "@storybook/client-logger" "6.1.15" + "@storybook/components" "6.1.15" + "@storybook/core-events" "6.1.15" + "@storybook/theming" "6.1.15" core-js "^3.0.1" global "^4.3.2" memoizerific "^1.11.3" @@ -5254,24 +5213,24 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/addon-controls@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/addon-controls/-/addon-controls-6.1.9.tgz#d7663d4c95db49163c372989f04264b11a4fa5cf" - integrity sha512-ctMXTcouqrPlNpQ0w3q6wjg16s1DL9VJtw1WvkySwezOE0ytfeC8M4nsbsKJnuY+dCadHKGn392DC1qVidY7Hg== +"@storybook/addon-controls@6.1.15": + version "6.1.15" + resolved "https://registry.yarnpkg.com/@storybook/addon-controls/-/addon-controls-6.1.15.tgz#037c7a849bd656eb745cb598aa70e9e81112d54f" + integrity sha512-2GLLQZIyRVwawiHemiRXqLcVwGXm0NgJJ1cefQAvh6WFzp2y1eD6M5KUDFKAPvIGuo6vdjdr8BN++R3b1TbmVg== dependencies: - "@storybook/addons" "6.1.9" - "@storybook/api" "6.1.9" - "@storybook/client-api" "6.1.9" - "@storybook/components" "6.1.9" - "@storybook/node-logger" "6.1.9" - "@storybook/theming" "6.1.9" + "@storybook/addons" "6.1.15" + "@storybook/api" "6.1.15" + "@storybook/client-api" "6.1.15" + "@storybook/components" "6.1.15" + "@storybook/node-logger" "6.1.15" + "@storybook/theming" "6.1.15" core-js "^3.0.1" ts-dedent "^2.0.0" -"@storybook/addon-docs@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/addon-docs/-/addon-docs-6.1.9.tgz#41cf82cece4abcf7640a1b7c2be6a7d5908c4678" - integrity sha512-5pwt2WU/yD4cnHU2KOpzU4t7A9FoePhZ15WOajtuV+W/hekNQSOGgNASQZbVOOldl954ireNIjZHtvthpI0tvQ== +"@storybook/addon-docs@6.1.15": + version "6.1.15" + resolved "https://registry.yarnpkg.com/@storybook/addon-docs/-/addon-docs-6.1.15.tgz#b2c08d0e9d058dc01a10ddd39266630551697ee5" + integrity sha512-SYXqdTVxv2M0XzmB9ybgYrbqVTAu4FEj+0JL3EJUIS7usWlhZmZIBgU4DFBOd5Aojaq1SGd0QJksMS3L1ym/Bg== dependencies: "@babel/core" "^7.12.1" "@babel/generator" "^7.12.1" @@ -5282,18 +5241,18 @@ "@mdx-js/loader" "^1.6.19" "@mdx-js/mdx" "^1.6.19" "@mdx-js/react" "^1.6.19" - "@storybook/addons" "6.1.9" - "@storybook/api" "6.1.9" - "@storybook/client-api" "6.1.9" - "@storybook/client-logger" "6.1.9" - "@storybook/components" "6.1.9" - "@storybook/core" "6.1.9" - "@storybook/core-events" "6.1.9" + "@storybook/addons" "6.1.15" + "@storybook/api" "6.1.15" + "@storybook/client-api" "6.1.15" + "@storybook/client-logger" "6.1.15" + "@storybook/components" "6.1.15" + "@storybook/core" "6.1.15" + "@storybook/core-events" "6.1.15" "@storybook/csf" "0.0.1" - "@storybook/node-logger" "6.1.9" - "@storybook/postinstall" "6.1.9" - "@storybook/source-loader" "6.1.9" - "@storybook/theming" "6.1.9" + "@storybook/node-logger" "6.1.15" + "@storybook/postinstall" "6.1.15" + "@storybook/source-loader" "6.1.15" + "@storybook/theming" "6.1.15" acorn "^7.1.0" acorn-jsx "^5.1.0" acorn-walk "^7.0.0" @@ -5314,36 +5273,36 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/addon-essentials@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/addon-essentials/-/addon-essentials-6.1.9.tgz#e689de480ea626a784bc3784b36ceb4c9b366561" - integrity sha512-mw05LsBjWLu79u0lFsd3/kSpU7Dctt0xzcx8hXcaUKsiq7QvqPoKVutFuC8tvgoAVaCmmokLygscbMBOD2hq0w== +"@storybook/addon-essentials@6.1.15": + version "6.1.15" + resolved "https://registry.yarnpkg.com/@storybook/addon-essentials/-/addon-essentials-6.1.15.tgz#dd910cfac9496fe8e46927fa5a809f1b496074f4" + integrity sha512-LiFIIMdjX1GUXkfERBtJKRpcMDKSdj0nuXy5LnROjQn41WreZXdW8u+PXkCduZQgftW9qYTboUn9+yXO2vBbKw== dependencies: - "@storybook/addon-actions" "6.1.9" - "@storybook/addon-backgrounds" "6.1.9" - "@storybook/addon-controls" "6.1.9" - "@storybook/addon-docs" "6.1.9" - "@storybook/addon-toolbars" "6.1.9" - "@storybook/addon-viewport" "6.1.9" - "@storybook/addons" "6.1.9" - "@storybook/api" "6.1.9" - "@storybook/node-logger" "6.1.9" + "@storybook/addon-actions" "6.1.15" + "@storybook/addon-backgrounds" "6.1.15" + "@storybook/addon-controls" "6.1.15" + "@storybook/addon-docs" "6.1.15" + "@storybook/addon-toolbars" "6.1.15" + "@storybook/addon-viewport" "6.1.15" + "@storybook/addons" "6.1.15" + "@storybook/api" "6.1.15" + "@storybook/node-logger" "6.1.15" core-js "^3.0.1" regenerator-runtime "^0.13.7" ts-dedent "^2.0.0" -"@storybook/addon-knobs@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/addon-knobs/-/addon-knobs-6.1.9.tgz#49773931770effc208db094c61eeecbceaf5836b" - integrity sha512-aUKD9FaQGl/WOkGT6utElspYZJ7cBtUARe41JN59qOao7RNviabipQUASrjORcYUUU55sfKsLPEqQaEKB3x2bw== +"@storybook/addon-knobs@6.1.15": + version "6.1.15" + resolved "https://registry.yarnpkg.com/@storybook/addon-knobs/-/addon-knobs-6.1.15.tgz#8f12fd5da15c0a00993dbe837b971a4867339de2" + integrity sha512-eiwav0/9fGrChwAs7yTi13W1mR9g+vYtkQaCKQFF2VIarY9mFH0gKZvLDSs+SH2wyPMp1JOROu8ef39B8Cyj4A== dependencies: - "@storybook/addons" "6.1.9" - "@storybook/api" "6.1.9" - "@storybook/channels" "6.1.9" - "@storybook/client-api" "6.1.9" - "@storybook/components" "6.1.9" - "@storybook/core-events" "6.1.9" - "@storybook/theming" "6.1.9" + "@storybook/addons" "6.1.15" + "@storybook/api" "6.1.15" + "@storybook/channels" "6.1.15" + "@storybook/client-api" "6.1.15" + "@storybook/components" "6.1.15" + "@storybook/core-events" "6.1.15" + "@storybook/theming" "6.1.15" copy-to-clipboard "^3.0.8" core-js "^3.0.1" escape-html "^1.0.3" @@ -5357,18 +5316,18 @@ react-select "^3.0.8" regenerator-runtime "^0.13.7" -"@storybook/addon-storysource@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/addon-storysource/-/addon-storysource-6.1.9.tgz#9f7c50522b4de4bc90508a3882ba473bec82f435" - integrity sha512-xG3UAHRFfdn7dvoOjlvIHUNWgMPRLy87qjjHgmdW0jWyvGEtT7k10IRGgnozXp64ETy8dAnIyt3kmRUwXj/pkg== +"@storybook/addon-storysource@6.1.15": + version "6.1.15" + resolved "https://registry.yarnpkg.com/@storybook/addon-storysource/-/addon-storysource-6.1.15.tgz#83db5b5153cf05a333e4357c8e623189bf5480a8" + integrity sha512-Qs6eEO7l8bJX7rhd1FiGHtt0QENtSMbQZQlsVe/ALVgBdFzcWji2FTVIzSlFHut1iwqmLHF7UEkNKhXpB3Nfzw== dependencies: - "@storybook/addons" "6.1.9" - "@storybook/api" "6.1.9" - "@storybook/client-logger" "6.1.9" - "@storybook/components" "6.1.9" - "@storybook/router" "6.1.9" - "@storybook/source-loader" "6.1.9" - "@storybook/theming" "6.1.9" + "@storybook/addons" "6.1.15" + "@storybook/api" "6.1.15" + "@storybook/client-logger" "6.1.15" + "@storybook/components" "6.1.15" + "@storybook/router" "6.1.15" + "@storybook/source-loader" "6.1.15" + "@storybook/theming" "6.1.15" core-js "^3.0.1" estraverse "^4.2.0" loader-utils "^2.0.0" @@ -5377,63 +5336,63 @@ react-syntax-highlighter "^13.5.0" regenerator-runtime "^0.13.7" -"@storybook/addon-toolbars@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/addon-toolbars/-/addon-toolbars-6.1.9.tgz#99c8b48afc24773faf9490753788ee354e97f5d8" - integrity sha512-rXYkVqSahrb6eG6CwyuI2TNzazUBGTsSQK1ywOmLwFK2xs+ybn1jDkkh5UmzuPN7g6ouT3qJfz1H2PMqfGEY8Q== +"@storybook/addon-toolbars@6.1.15": + version "6.1.15" + resolved "https://registry.yarnpkg.com/@storybook/addon-toolbars/-/addon-toolbars-6.1.15.tgz#0788f53235d59adb6ab095824b6b91c3fcc86786" + integrity sha512-XR+bwcPqa17iwL4B1WcYeOwxMXCE5AuYIc92FlJruyJBGX37TKZEl2Sc4PzQ2Pb3oypWvYDJd+LRGT5C2axaXA== dependencies: - "@storybook/addons" "6.1.9" - "@storybook/api" "6.1.9" - "@storybook/client-api" "6.1.9" - "@storybook/components" "6.1.9" + "@storybook/addons" "6.1.15" + "@storybook/api" "6.1.15" + "@storybook/client-api" "6.1.15" + "@storybook/components" "6.1.15" core-js "^3.0.1" -"@storybook/addon-viewport@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/addon-viewport/-/addon-viewport-6.1.9.tgz#7160b7598a34b8c19ff7571b781329fe8ad5de8d" - integrity sha512-+raES4+fDc0eCnpF4JW5kYwOTFEGiVmjmhFSrsXXuRXNGrCx4s5t9Bpklwm4YswIgmubB0Fpd0kaQS2LjRz94Q== +"@storybook/addon-viewport@6.1.15": + version "6.1.15" + resolved "https://registry.yarnpkg.com/@storybook/addon-viewport/-/addon-viewport-6.1.15.tgz#fc7913713c8341af136a0ee28e67b422952c428f" + integrity sha512-lHCGwFdfC8XTRbmw6XmLPO1DxyjJJga3p1sITULSUt8A9UVh8M6mkO7e3w5z34IfDWOaxSAEnx5DHM33ZoTt5Q== dependencies: - "@storybook/addons" "6.1.9" - "@storybook/api" "6.1.9" - "@storybook/client-logger" "6.1.9" - "@storybook/components" "6.1.9" - "@storybook/core-events" "6.1.9" - "@storybook/theming" "6.1.9" + "@storybook/addons" "6.1.15" + "@storybook/api" "6.1.15" + "@storybook/client-logger" "6.1.15" + "@storybook/components" "6.1.15" + "@storybook/core-events" "6.1.15" + "@storybook/theming" "6.1.15" core-js "^3.0.1" global "^4.3.2" memoizerific "^1.11.3" prop-types "^15.7.2" regenerator-runtime "^0.13.7" -"@storybook/addons@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-6.1.9.tgz#78f3cb27b7d934f091f311f89b6ca312d34f12b8" - integrity sha512-NRxdlGLmmSoVwlirVRgKC8xmW9cFkG+Sp5GEd4XkJDaaIg2vKR3RuFU9GuvIOVMxOhhERqhQ07bnDaAMKbFzGw== +"@storybook/addons@6.1.15": + version "6.1.15" + resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-6.1.15.tgz#09eb8d962f58bd20b4ac2f83b515831c83226352" + integrity sha512-ENyHapLFOG93VaoQXPX8O3IWjLRyVBox9C9P20LMruKX/SfXAXx20qsoAWKKPGssopyOin17aoQX9pj+lFmCZQ== dependencies: - "@storybook/api" "6.1.9" - "@storybook/channels" "6.1.9" - "@storybook/client-logger" "6.1.9" - "@storybook/core-events" "6.1.9" - "@storybook/router" "6.1.9" - "@storybook/theming" "6.1.9" + "@storybook/api" "6.1.15" + "@storybook/channels" "6.1.15" + "@storybook/client-logger" "6.1.15" + "@storybook/core-events" "6.1.15" + "@storybook/router" "6.1.15" + "@storybook/theming" "6.1.15" core-js "^3.0.1" global "^4.3.2" regenerator-runtime "^0.13.7" -"@storybook/api@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/api/-/api-6.1.9.tgz#3f9bf00b2b18fa02965079fe775bd713677b30a3" - integrity sha512-S9SXlSiMeI450NIbOnx3UU9TZNyVD7jcBCjfNzhj0PqzRX/IG5Usj+R88Jm6MSIDjtsVjrWRCou+PrCh2xMnlQ== +"@storybook/api@6.1.15": + version "6.1.15" + resolved "https://registry.yarnpkg.com/@storybook/api/-/api-6.1.15.tgz#285ba42f7a8efcd3bd0e586a5e978487d826fbb4" + integrity sha512-C4D08e2ZbSe62nNKtmh9YBraoWb2j6Chw8VCkuj91kuKHh3YDNc1gjj5Fi+KYZwIcy0EllzW3RFQs+YR1/Vg1g== dependencies: "@reach/router" "^1.3.3" - "@storybook/channels" "6.1.9" - "@storybook/client-logger" "6.1.9" - "@storybook/core-events" "6.1.9" + "@storybook/channels" "6.1.15" + "@storybook/client-logger" "6.1.15" + "@storybook/core-events" "6.1.15" "@storybook/csf" "0.0.1" - "@storybook/router" "6.1.9" + "@storybook/router" "6.1.15" "@storybook/semver" "^7.3.2" - "@storybook/theming" "6.1.9" - "@types/reach__router" "^1.3.5" + "@storybook/theming" "6.1.15" + "@types/reach__router" "^1.3.7" core-js "^3.0.1" fast-deep-equal "^3.1.1" global "^4.3.2" @@ -5445,38 +5404,38 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/channel-postmessage@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-6.1.9.tgz#5d73c67ba94bcf68b14138bba6c5bb0850c72c5e" - integrity sha512-tX7pD9Xrf1WsatpJqtJ6o8MlgxG7jH+oFhNPkGvUbWiolVDQmuDndwM8Hh1kUnOWlyE1AN5hlM7av8MY+9D3NA== +"@storybook/channel-postmessage@6.1.15": + version "6.1.15" + resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-6.1.15.tgz#80ea2346d18496f9710dd7f87fd2a9eca46ef36f" + integrity sha512-Es4B5zpLrW28KSbY8FhGVEDgUnKspJ7wPuJyKExUpZ5L9w52RkTD6lRnVPzLUfoQ4luPsExy5fiuo878/Wc9ag== dependencies: - "@storybook/channels" "6.1.9" - "@storybook/client-logger" "6.1.9" - "@storybook/core-events" "6.1.9" + "@storybook/channels" "6.1.15" + "@storybook/client-logger" "6.1.15" + "@storybook/core-events" "6.1.15" core-js "^3.0.1" global "^4.3.2" qs "^6.6.0" telejson "^5.0.2" -"@storybook/channels@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-6.1.9.tgz#94f07ff3615b11c07d1902be6b6cd298c0eea55c" - integrity sha512-aV+KsZPuoTtFKSMUkSCyVlVmtVHkSH35dSbyMazjlUD9cOLwkXB1s+LZL/GxxSR6a6uR75V0QWxItfNxaJETMQ== +"@storybook/channels@6.1.15": + version "6.1.15" + resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-6.1.15.tgz#22bb06a671a5ae09d2537bcf63aaf90d7f6b9f6b" + integrity sha512-HIKHDeL/0BDk9a7xc2PLiFFoHjUMKUd2djhUGdeKgdKqoWejp4JJ60fI68+2QuSRbkB8k+rAwmuWJzV7EfB5fg== dependencies: core-js "^3.0.1" ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/client-api@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-6.1.9.tgz#d4a8d38bc657f26e4837831b961e085da1954d51" - integrity sha512-b2DFaGAS5G2ly3UJY5NJNXh/LxgLgSJLbqPL4t48MFW5XjH+rmEWXE9P+ujCaPclH1/y7mZRMprDj3ycDbRo3Q== +"@storybook/client-api@6.1.15": + version "6.1.15" + resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-6.1.15.tgz#8f8ead111459b94621571bdb2276f8a0aace17b1" + integrity sha512-iwuDlgNdB6Y4OidlhWPob3tEIax9taymdKEe9by4rLJ3nfXu7viHcvCAjN24oI4NFW3NZsmtqJotgftRYk0r1Q== dependencies: - "@storybook/addons" "6.1.9" - "@storybook/channel-postmessage" "6.1.9" - "@storybook/channels" "6.1.9" - "@storybook/client-logger" "6.1.9" - "@storybook/core-events" "6.1.9" + "@storybook/addons" "6.1.15" + "@storybook/channel-postmessage" "6.1.15" + "@storybook/channels" "6.1.15" + "@storybook/client-logger" "6.1.15" + "@storybook/core-events" "6.1.15" "@storybook/csf" "0.0.1" "@types/qs" "^6.9.0" "@types/webpack-env" "^1.15.3" @@ -5491,23 +5450,23 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/client-logger@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-6.1.9.tgz#1d61a64000d4691780d75e19b78fd44adfdb5d9c" - integrity sha512-i7Q2ky9+Jwv+wmnlOGxmDOEdmaTIB69OQnnZNWGKufOwoIMjn6QO0VifARyA9W++nNSijjJ5th84tLJALaoCTA== +"@storybook/client-logger@6.1.15": + version "6.1.15" + resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-6.1.15.tgz#b558d6ecbee82c038d684717d8c598eaa4a9324d" + integrity sha512-lUpatG8SxzrUapWMsIPWiR+5qRVT5ebn8tGHQeBeRHXbdmEqyq5DOlrotLUemkA5nNTCs1pMFNvKSpCHznG+fg== dependencies: core-js "^3.0.1" global "^4.3.2" -"@storybook/components@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/components/-/components-6.1.9.tgz#f25d18f3a410cc7e9549ddb3c971c40d9108d4d8" - integrity sha512-cYYm3fHo9MW0bbl47lu1ncwulV7V9VEF8FC96uvys07oaCTFWKzQ0z/FD0nCqeK6eEz1+SEqnGwLFmOtqlRXDQ== +"@storybook/components@6.1.15": + version "6.1.15" + resolved "https://registry.yarnpkg.com/@storybook/components/-/components-6.1.15.tgz#b4a2af23ee6b9cba4c255191eae3d3463e29bfb7" + integrity sha512-lPbA/zyBfctdlpDhRTcRFLWlZPJ3PB4+wI0FUvYs69iG3/bNbQPYu8vRmNhCZOsaGt+b+dik4Tfcth8Bu+eQug== dependencies: - "@popperjs/core" "^2.4.4" - "@storybook/client-logger" "6.1.9" + "@popperjs/core" "^2.5.4" + "@storybook/client-logger" "6.1.15" "@storybook/csf" "0.0.1" - "@storybook/theming" "6.1.9" + "@storybook/theming" "6.1.15" "@types/overlayscrollbars" "^1.9.0" "@types/react-color" "^3.0.1" "@types/react-syntax-highlighter" "11.0.4" @@ -5520,22 +5479,22 @@ overlayscrollbars "^1.10.2" polished "^3.4.4" react-color "^2.17.0" - react-popper-tooltip "^3.1.0" + react-popper-tooltip "^3.1.1" react-syntax-highlighter "^13.5.0" react-textarea-autosize "^8.1.1" ts-dedent "^2.0.0" -"@storybook/core-events@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-6.1.9.tgz#0a88281837d1aa657a93a9abf7f5aad65b8d68e7" - integrity sha512-oOpqpjCTJCt0U5lnQ16OZU0iKIDh2/MIg4yrnDw+Pt6zGyX3zSvtB+9W8LQFnMwm+cXaNmiizGwt/W+4OiORjQ== +"@storybook/core-events@6.1.15": + version "6.1.15" + resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-6.1.15.tgz#f66e30cbed8afdb8df2254d2aa47fe139e641c60" + integrity sha512-2sz02hdGZshanoq83jaB+goAcapVEWrxe+RJZn/gu2OymlEioWNjPPtOVGgi5DNIiJFnYvc66adayNwX39+tDA== dependencies: core-js "^3.0.1" -"@storybook/core@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/core/-/core-6.1.9.tgz#e6575e294cb4d2d9b57d5976a145cae8f4a88594" - integrity sha512-guz+R6eDX923Cw7NqgS5PrpTmmjDB+m5X1iF9pwKlpPTfzIiT/wTzJm4PwhFoGONNoXrItObX/6hW6OQbX4aOA== +"@storybook/core@6.1.15": + version "6.1.15" + resolved "https://registry.yarnpkg.com/@storybook/core/-/core-6.1.15.tgz#7ff8c314d3857497bf2e26c69a1fa93ef37301aa" + integrity sha512-mQeKAXcowUwF+pOdWZEFwb5M6sz4yv5cOv1vTci3/1pMmB8QpYlH+P61p4lsRO17Vlak70h18TworPka/4+mhA== dependencies: "@babel/core" "^7.12.3" "@babel/plugin-proposal-class-properties" "^7.12.1" @@ -5559,20 +5518,20 @@ "@babel/preset-react" "^7.12.1" "@babel/preset-typescript" "^7.12.1" "@babel/register" "^7.12.1" - "@storybook/addons" "6.1.9" - "@storybook/api" "6.1.9" - "@storybook/channel-postmessage" "6.1.9" - "@storybook/channels" "6.1.9" - "@storybook/client-api" "6.1.9" - "@storybook/client-logger" "6.1.9" - "@storybook/components" "6.1.9" - "@storybook/core-events" "6.1.9" + "@storybook/addons" "6.1.15" + "@storybook/api" "6.1.15" + "@storybook/channel-postmessage" "6.1.15" + "@storybook/channels" "6.1.15" + "@storybook/client-api" "6.1.15" + "@storybook/client-logger" "6.1.15" + "@storybook/components" "6.1.15" + "@storybook/core-events" "6.1.15" "@storybook/csf" "0.0.1" - "@storybook/node-logger" "6.1.9" - "@storybook/router" "6.1.9" + "@storybook/node-logger" "6.1.15" + "@storybook/router" "6.1.15" "@storybook/semver" "^7.3.2" - "@storybook/theming" "6.1.9" - "@storybook/ui" "6.1.9" + "@storybook/theming" "6.1.15" + "@storybook/ui" "6.1.15" "@types/glob-base" "^0.3.0" "@types/micromatch" "^4.0.1" "@types/node-fetch" "^2.5.4" @@ -5646,10 +5605,10 @@ dependencies: lodash "^4.17.15" -"@storybook/node-logger@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-6.1.9.tgz#c63a61f72209d76eeeffe9d151fec043864b9438" - integrity sha512-2gP9BSBXEOGIcUyzRdIkIJi1UEINUAIyuv9bfKODo4GfujRg7DLz/mpi/FdwmulGg/viXWSXa6ccb6ziIgY9RA== +"@storybook/node-logger@6.1.15": + version "6.1.15" + resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-6.1.15.tgz#fcf786d3a323feb6821e40e26f98a513a60d1a79" + integrity sha512-lrO0ei3W7BRci2iUkWTr/rXgHkzxwZTrlkx0iBzbQQRy7K1AJ9bjzhurCH9B8C9XGLmn60LXT81RWD3iCLZjcw== dependencies: "@types/npmlog" "^4.1.2" chalk "^4.0.0" @@ -5657,24 +5616,24 @@ npmlog "^4.1.2" pretty-hrtime "^1.0.3" -"@storybook/postinstall@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/postinstall/-/postinstall-6.1.9.tgz#1c62cf46b7b8c50e939c8b14de9e7133368aab45" - integrity sha512-9aL0+ALWHKGJAnC8CdRBE7PlX87sKMEWZkDQJL5uT1eikfgfAmS1AgkpIbFD8mcxstcZmFKRwc1BD4mvwzqtQQ== +"@storybook/postinstall@6.1.15": + version "6.1.15" + resolved "https://registry.yarnpkg.com/@storybook/postinstall/-/postinstall-6.1.15.tgz#e371d5152100501b1fc45e452c9b11ee4fdf92b0" + integrity sha512-sfQz9hU/WVanLVzhx7gx3TyNWRxrKgbK7Zam2eE4MxgRcAIEJCgrd3nvllExjoPVStttuUFa3p4K94n2TQM9qA== dependencies: core-js "^3.0.1" -"@storybook/react@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/react/-/react-6.1.9.tgz#063427015b3d0ce582b1b6b7826d40d963d265ce" - integrity sha512-HJWHQE+eCC7sz1vqvgmBMn2sA1uc0ByEj+NeSgyi45jBFI+Ke4a8hxx6k5XA7k9gLznqG8TPGg0z6EdQTJTLkQ== +"@storybook/react@6.1.15": + version "6.1.15" + resolved "https://registry.yarnpkg.com/@storybook/react/-/react-6.1.15.tgz#e17d00b05b8980ad381ba701805309ed46d1fdcd" + integrity sha512-7WoYLOZuAlzgQsL9oy4JCr9NcB4NBCuxslPSncN5l/7ewGXgfVXTAOMOfw+EVNrtUeVJU2fC8gFiHVl0SJpTZw== dependencies: "@babel/preset-flow" "^7.12.1" "@babel/preset-react" "^7.12.1" "@pmmmwh/react-refresh-webpack-plugin" "^0.4.2" - "@storybook/addons" "6.1.9" - "@storybook/core" "6.1.9" - "@storybook/node-logger" "6.1.9" + "@storybook/addons" "6.1.15" + "@storybook/core" "6.1.15" + "@storybook/node-logger" "6.1.15" "@storybook/semver" "^7.3.2" "@types/webpack-env" "^1.15.3" babel-plugin-add-react-displayname "^0.0.5" @@ -5691,13 +5650,13 @@ ts-dedent "^2.0.0" webpack "^4.44.2" -"@storybook/router@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/router/-/router-6.1.9.tgz#c0b24dc3ab53d58541b81c7abea2f11d7fbbebf6" - integrity sha512-kIlmSFBnqI198oMCncFZR7MxoV5/kP6KS0paFcyu1XE1zO2ovV6eQZ8pPpOjSsD/ISu4Y44uE+ZDNsEehjj6GQ== +"@storybook/router@6.1.15": + version "6.1.15" + resolved "https://registry.yarnpkg.com/@storybook/router/-/router-6.1.15.tgz#e0cd7440a2ddc9b265e506b1cb590d3eeab56476" + integrity sha512-HlxDkGpiTSxXCJuqRoZ9Viq6Y/h/7efI8LPhhopr50qWRBTh/PEQzDqWBXG3sj8ISmi9GyUaTSAuqRwdA3lJQQ== dependencies: "@reach/router" "^1.3.3" - "@types/reach__router" "^1.3.5" + "@types/reach__router" "^1.3.7" core-js "^3.0.1" global "^4.3.2" memoizerific "^1.11.3" @@ -5711,13 +5670,13 @@ core-js "^3.6.5" find-up "^4.1.0" -"@storybook/source-loader@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/source-loader/-/source-loader-6.1.9.tgz#10eebf12ecd7baa70e51f368c41b89b4b5084eb1" - integrity sha512-2h3TS1O9qJ0xmOOJrWxY9ODEFK0/RLxEmWcXngWAcH1ZrHAuz6UcEatO2bIgykrorf9xKqqk7/AYyE9KxW668A== +"@storybook/source-loader@6.1.15": + version "6.1.15" + resolved "https://registry.yarnpkg.com/@storybook/source-loader/-/source-loader-6.1.15.tgz#21b985ede0ec626c1a4916fc92a58cffca9d6c63" + integrity sha512-ZFmbuvo4sq0jVeWj7Ur1zDq5SCfTxLYuQcV6mAOqUr89dyP778PX9AO1b1/BmipjsHL3JOHN6uHAn74ksB9ofg== dependencies: - "@storybook/addons" "6.1.9" - "@storybook/client-logger" "6.1.9" + "@storybook/addons" "6.1.15" + "@storybook/client-logger" "6.1.15" "@storybook/csf" "0.0.1" core-js "^3.0.1" estraverse "^4.2.0" @@ -5728,15 +5687,15 @@ regenerator-runtime "^0.13.7" source-map "^0.7.3" -"@storybook/theming@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-6.1.9.tgz#8c584aa623f3d6e33b1e3b3de2ec1f41bdc5d9ab" - integrity sha512-orzMQkyEhAQEi0E9iwmUkzh5yPHoYGBz17t2aydDeT6oGKii6if8Mq2oPVycfVKZ84QO7GFAS9q1nVCRcuD8oA== +"@storybook/theming@6.1.15": + version "6.1.15" + resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-6.1.15.tgz#01083ab89904dd959429b0b3fd1c76bd0ecc59ef" + integrity sha512-88IdYaPzp4NMKf/GKBrPggxD6/d/lkdQ4SNowXxN9g9eONd9M7HtTbjuJGRCbGMJ52xGcbpj2exEnAqKQ2iodA== dependencies: "@emotion/core" "^10.1.1" "@emotion/is-prop-valid" "^0.8.6" "@emotion/styled" "^10.0.23" - "@storybook/client-logger" "6.1.9" + "@storybook/client-logger" "6.1.15" core-js "^3.0.1" deep-object-diff "^1.1.0" emotion-theming "^10.0.19" @@ -5746,21 +5705,21 @@ resolve-from "^5.0.0" ts-dedent "^2.0.0" -"@storybook/ui@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-6.1.9.tgz#1ed3168d9fe5827285c13d8507dd1fd872830542" - integrity sha512-4MK5iTf7kI5DYVeWRiD6lkXdd0S6eiQJu9lvWqMOQJLOH5Bq77g0Ejo+38RTEQpV6we7hCPWWnRXQBjmJ2+19w== +"@storybook/ui@6.1.15": + version "6.1.15" + resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-6.1.15.tgz#a0f6c49fcf81cf172cd2de4c8dba2be1296891f6" + integrity sha512-quyhJWlOxhk95he7s5/TSYM3eEsaz3s4+98kUZE6r3ssME8u6zDvqa/qa6EWs5/nvZ2V3+12efIzCNbiiT3v3g== dependencies: "@emotion/core" "^10.1.1" - "@storybook/addons" "6.1.9" - "@storybook/api" "6.1.9" - "@storybook/channels" "6.1.9" - "@storybook/client-logger" "6.1.9" - "@storybook/components" "6.1.9" - "@storybook/core-events" "6.1.9" - "@storybook/router" "6.1.9" + "@storybook/addons" "6.1.15" + "@storybook/api" "6.1.15" + "@storybook/channels" "6.1.15" + "@storybook/client-logger" "6.1.15" + "@storybook/components" "6.1.15" + "@storybook/core-events" "6.1.15" + "@storybook/router" "6.1.15" "@storybook/semver" "^7.3.2" - "@storybook/theming" "6.1.9" + "@storybook/theming" "6.1.15" "@types/markdown-to-jsx" "^6.11.0" copy-to-clipboard "^3.0.8" core-js "^3.0.1" @@ -6380,11 +6339,6 @@ dependencies: "@types/unist" "*" -"@types/history@*": - version "4.7.8" - resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.8.tgz#49348387983075705fe8f4e02fb67f7daaec4934" - integrity sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA== - "@types/hoist-non-react-statics@3.3.1", "@types/hoist-non-react-statics@^3.3.0", "@types/hoist-non-react-statics@^3.3.1": version "3.3.1" resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" @@ -6515,11 +6469,16 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA== -"@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6": +"@types/json-schema@^7.0.5": version "7.0.6" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== +"@types/json-schema@^7.0.6": + version "7.0.7" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad" + integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA== + "@types/jsurl@^1.2.28": version "1.2.28" resolved "https://registry.yarnpkg.com/@types/jsurl/-/jsurl-1.2.28.tgz#03430a7cc878d1415c5b3cb03547ff238bc7a75c" @@ -6618,9 +6577,9 @@ integrity sha512-13gmo3M2qVvjQrWNseqM3+cR6S2Ss3grbR2NZltgMq94wOwqJYQdgn8qzwDshzgXqMlSUtyPZjysImmktu22ew== "@types/node-fetch@^2.5.4": - version "2.5.7" - resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.7.tgz#20a2afffa882ab04d44ca786449a276f9f6bbf3c" - integrity sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw== + version "2.5.8" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.8.tgz#e199c835d234c7eb0846f6618012e558544ee2fb" + integrity sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw== dependencies: "@types/node" "*" form-data "^3.0.0" @@ -6741,12 +6700,11 @@ resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c" integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA== -"@types/reach__router@^1.3.5": - version "1.3.6" - resolved "https://registry.yarnpkg.com/@types/reach__router/-/reach__router-1.3.6.tgz#413417ce74caab331c70ce6a03a4c825188e4709" - integrity sha512-RHYataCUPQnt+GHoASyRLq6wmZ0n8jWlBW8Lxcwd30NN6vQfbmTeoSDfkgxO0S1lEzArp8OFDsq5KIs7FygjtA== +"@types/reach__router@^1.3.7": + version "1.3.7" + resolved "https://registry.yarnpkg.com/@types/reach__router/-/reach__router-1.3.7.tgz#de8ab374259ae7f7499fc1373b9697a5f3cd6428" + integrity sha512-cyBEb8Ef3SJNH5NYEIDGPoMMmYUxROatuxbICusVRQIqZUB85UCt6R2Ok60tKS/TABJsJYaHyNTW3kqbpxlMjg== dependencies: - "@types/history" "*" "@types/react" "*" "@types/react-beautiful-dnd@12.1.2": @@ -7166,9 +7124,9 @@ "@types/webpack" "*" "@types/webpack-env@^1.15.3": - version "1.15.3" - resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.15.3.tgz#fb602cd4c2f0b7c0fb857e922075fdf677d25d84" - integrity sha512-5oiXqR7kwDGZ6+gmzIO2lTC+QsriNuQXZDWNYRV3l2XRN/zmPgnC21DLSx2D05zvD8vnXW6qUg7JnXZ4I6qLVQ== + version "1.16.0" + resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.16.0.tgz#8c0a9435dfa7b3b1be76562f3070efb3f92637b4" + integrity sha512-Fx+NpfOO0CpeYX2g9bkvX8O5qh9wrU1sOF4g8sft4Mu7z+qfe387YlyY8w8daDyDsKY5vUxM0yxkAYnbkRbZEw== "@types/webpack-sources@*": version "0.1.5" @@ -7216,9 +7174,9 @@ source-map "^0.6.0" "@types/webpack@^4.41.8": - version "4.41.24" - resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.24.tgz#75b664abe3d5bcfe54e64313ca3b43e498550422" - integrity sha512-1A0MXPwZiMOD3DPMuOKUKcpkdPo8Lq33UGggZ7xio6wJ/jV1dAu5cXDrOfGDnldUroPIRLsr/DT43/GqOA4RFQ== + version "4.41.26" + resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.26.tgz#27a30d7d531e16489f9c7607c747be6bc1a459ef" + integrity sha512-7ZyTfxjCRwexh+EJFwRUM+CDB2XvgHl4vfuqf1ZKrgGvcS5BrNvPQqJh3tsZ0P6h6Aa1qClVHaJZszLPzpqHeA== dependencies: "@types/anymatch" "*" "@types/node" "*" @@ -8263,7 +8221,18 @@ array-ify@^1.0.0: resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" integrity sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4= -array-includes@^3.0.3, array-includes@^3.1.1: +array-includes@^3.0.3: + version "3.1.2" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.2.tgz#a8db03e0b88c8c6aeddc49cb132f9bcab4ebf9c8" + integrity sha512-w2GspexNQpx+PutG3QpT437/BenZBj0M/MZGn5mzv/MofYqo0xmRHzn4lFsoDlWJ+THYsGJmFlW68WlDFx7VRw== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + get-intrinsic "^1.0.1" + is-string "^1.0.5" + +array-includes@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.1.tgz#cdd67e6852bdf9c1215460786732255ed2459348" integrity sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ== @@ -8316,13 +8285,13 @@ array.prototype.find@^2.1.1: es-abstract "^1.17.4" array.prototype.flat@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.2.tgz#8f3c71d245ba349b6b64b4078f76f5576f1fd723" - integrity sha512-VXjh7lAL4KXKF2hY4FnEW9eRW6IhdvFW1sN/JwLbmECbCgACCnBHNyP3lFiYuttr0jxRN9Bsc5+G27dMseSWqQ== + version "1.2.4" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz#6ef638b43312bd401b4c6199fdec7e2dc9e9a123" + integrity sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg== dependencies: + call-bind "^1.0.0" define-properties "^1.1.3" - es-abstract "^1.15.0" - function-bind "^1.1.1" + es-abstract "^1.18.0-next.1" array.prototype.flat@^1.2.3: version "1.2.3" @@ -8332,7 +8301,17 @@ array.prototype.flat@^1.2.3: define-properties "^1.1.3" es-abstract "^1.17.0-next.1" -array.prototype.flatmap@^1.2.1, array.prototype.flatmap@^1.2.3: +array.prototype.flatmap@^1.2.1: + version "1.2.4" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.4.tgz#94cfd47cc1556ec0747d97f7c7738c58122004c9" + integrity sha512-r9Z0zYoxqHz60vvQbWEdXIEtCwHF0yxaWfno9qzXeNHvfyl3BZqygmGzb84dsubyaXLH4husF+NFgMSdpZhk2Q== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + function-bind "^1.1.1" + +array.prototype.flatmap@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.3.tgz#1c13f84a178566042dd63de4414440db9222e443" integrity sha512-OOEk+lkePcg+ODXIpvuU9PAryCikCJyo7GlDG1upleEpQRx6mzL9puEBkozQ5iAx20KV0l3DbyQwqciJtqe5Pg== @@ -8341,15 +8320,16 @@ array.prototype.flatmap@^1.2.1, array.prototype.flatmap@^1.2.3: es-abstract "^1.17.0-next.1" function-bind "^1.1.1" -array.prototype.map@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array.prototype.map/-/array.prototype.map-1.0.2.tgz#9a4159f416458a23e9483078de1106b2ef68f8ec" - integrity sha512-Az3OYxgsa1g7xDYp86l0nnN4bcmuEITGe1rbdEBVkrqkzMgDcbdQ2R7r41pNzti+4NMces3H8gMmuioZUilLgw== +array.prototype.map@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array.prototype.map/-/array.prototype.map-1.0.3.tgz#1609623618d3d84134a37d4a220030c2bd18420b" + integrity sha512-nNcb30v0wfDyIe26Yif3PcV1JXQp4zEeEfupG7L4SRjnD6HLbO5b2a7eVSba53bOx4YCHYMBHt+Fp4vYstneRA== dependencies: + call-bind "^1.0.0" define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" + es-abstract "^1.18.0-next.1" es-array-method-boxes-properly "^1.0.0" - is-string "^1.0.4" + is-string "^1.0.5" arrify@^1.0.1: version "1.0.1" @@ -8585,7 +8565,7 @@ babel-loader@8.0.6, babel-loader@^8.0.2: mkdirp "^0.5.1" pify "^4.0.1" -babel-loader@8.1.0, babel-loader@^8.0.6: +babel-loader@8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.1.0.tgz#c611d5112bd5209abe8b9fa84c3e4da25275f1c3" integrity sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw== @@ -8596,6 +8576,16 @@ babel-loader@8.1.0, babel-loader@^8.0.6: pify "^4.0.1" schema-utils "^2.6.5" +babel-loader@^8.0.6: + version "8.2.2" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.2.tgz#9363ce84c10c9a40e6c753748e1441b60c8a0b81" + integrity sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g== + dependencies: + find-cache-dir "^3.3.1" + loader-utils "^1.4.0" + make-dir "^3.1.0" + schema-utils "^2.6.5" + babel-plugin-add-react-displayname@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/babel-plugin-add-react-displayname/-/babel-plugin-add-react-displayname-0.0.5.tgz#339d4cddb7b65fd62d1df9db9fe04de134122bd5" @@ -8610,13 +8600,13 @@ babel-plugin-angularjs-annotate@0.10.0: "@babel/types" "^7.2.0" simple-is "~0.2.0" -babel-plugin-apply-mdx-type-prop@1.6.21: - version "1.6.21" - resolved "https://registry.yarnpkg.com/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.21.tgz#0c8600c965ca4203e3c026ed971ed5b7e810aeba" - integrity sha512-+vQarmm+g+kePH4CMp2iEN/HOx1oEvZeSKCdKCEZlnJOthXzkpaRAbM3ZNCiKqVr9WuoqPNfoXQ0EVppYpIwfg== +babel-plugin-apply-mdx-type-prop@1.6.22: + version "1.6.22" + resolved "https://registry.yarnpkg.com/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.22.tgz#d216e8fd0de91de3f1478ef3231e05446bc8705b" + integrity sha512-VefL+8o+F/DfK24lPZMtJctrCVOfgbqLAGZSkxwhazQv4VxPg3Za/i40fu22KR2m8eEda+IfSOlPLUSIiLcnCQ== dependencies: "@babel/helper-plugin-utils" "7.10.4" - "@mdx-js/util" "1.6.21" + "@mdx-js/util" "1.6.22" babel-plugin-dynamic-import-node@^2.3.0: version "2.3.0" @@ -8680,10 +8670,10 @@ babel-plugin-emotion@^10.0.27: find-root "^1.1.0" source-map "^0.5.7" -babel-plugin-extract-import-names@1.6.21: - version "1.6.21" - resolved "https://registry.yarnpkg.com/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.21.tgz#94efffee4ea79982491573e5f67d9957ab77596a" - integrity sha512-mCjTry00HB/4xHGunxQNMOGZ7JEGJdEScNh7C1WJBto7nePyn9wCdYAZP61pGC6+z3ETH5btY20mqg0plcxZGA== +babel-plugin-extract-import-names@1.6.22: + version "1.6.22" + resolved "https://registry.yarnpkg.com/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz#de5f9a28eb12f3eb2578bf74472204e66d1a13dc" + integrity sha512-yJ9BsJaISua7d8zNT7oRG1ZLBJCIdZ4PZqmH8qa9N5AK01ifk3fnkc98AXhtzE7UkfCsEumvoQWgoYLhOnJ7jQ== dependencies: "@babel/helper-plugin-utils" "7.10.4" @@ -9272,7 +9262,7 @@ browserslist@4.10.0: node-releases "^1.1.52" pkg-up "^3.1.0" -browserslist@^4.0.0: +browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.16.1: version "4.16.1" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.1.tgz#bf757a2da376b3447b800a16f0f1c96358138766" integrity sha512-UXhDrwqsNcpTYJBTZsbGATDxZbiVDsx6UjpmRUmtnP10pr8wAYr5LgFoEFw9ixriQH2mv/NX2SfGzE/o8GndLA== @@ -9283,16 +9273,6 @@ browserslist@^4.0.0: escalade "^3.1.1" node-releases "^1.1.69" -browserslist@^4.12.0, browserslist@^4.14.5: - version "4.14.6" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.6.tgz#97702a9c212e0c6b6afefad913d3a1538e348457" - integrity sha512-zeFYcUo85ENhc/zxHbiIp0LGzzTrE2Pv2JhxvS7kpUb9Q9D38kUX6Bie7pGutJ/5iF5rOxE7CepAuWD56xJ33A== - dependencies: - caniuse-lite "^1.0.30001154" - electron-to-chromium "^1.3.585" - escalade "^3.1.1" - node-releases "^1.1.65" - browserslist@^4.6.0, browserslist@^4.6.4, browserslist@^4.7.0, browserslist@^4.8.3, browserslist@^4.8.5, browserslist@^4.9.1: version "4.13.0" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.13.0.tgz#42556cba011e1b0a2775b611cba6a8eca18e940d" @@ -9508,6 +9488,14 @@ call-bind@^1.0.0: function-bind "^1.1.1" get-intrinsic "^1.0.0" +call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + call-me-maybe@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" @@ -9563,12 +9551,12 @@ camel-case@3.0.x: upper-case "^1.1.1" camel-case@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.1.tgz#1fc41c854f00e2f7d0139dfeba1542d6896fe547" - integrity sha512-7fa2WcG4fYFkclIvEmxBbTvmibwF2/agfEBc6q3lOpVu0A13ltLsA+Hr/8Hp6kp5f+G7hKi6t8lys6XxP+1K6Q== + version "4.1.2" + resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" + integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== dependencies: - pascal-case "^3.1.1" - tslib "^1.10.0" + pascal-case "^3.1.2" + tslib "^2.0.3" camelcase-css@2.0.1: version "2.0.1" @@ -9651,10 +9639,10 @@ caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001020, caniuse-lite@^1.0.300010 resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001104.tgz#4e3d5b3b1dd3c3529f10cb7f519c62ba3e579f5d" integrity sha512-pkpCg7dmI/a7WcqM2yfdOiT4Xx5tzyoHAXWsX5/HxZ3TemwDZs0QXdqbE0UPLPVy/7BeK7693YfzfRYfu1YVpg== -caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001154: - version "1.0.30001156" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001156.tgz#75c20937b6012fe2b02ab58b30d475bf0718de97" - integrity sha512-z7qztybA2eFZTB6Z3yvaQBIoJpQtsewRD74adw2UbRWwsRq3jIPvgrQGawBMbfafekQaD21FWuXNcywtTDGGCw== +caniuse-lite@^1.0.30001109: + version "1.0.30001179" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001179.tgz#b0803883b4471a6c62066fb1752756f8afc699c8" + integrity sha512-blMmO0QQujuUWZKyVrD1msR4WNDAqb/UPO1Sw2WWsQ7deoM5bJiicKnWJ1Y0NS/aGINSnKPIWBMw5luX+NDUCA== capture-exit@^2.0.0: version "2.0.0" @@ -9811,7 +9799,7 @@ chokidar@3.3.0: optionalDependencies: fsevents "~2.1.1" -"chokidar@>=2.0.0 <4.0.0", chokidar@^3.4.1: +"chokidar@>=2.0.0 <4.0.0": version "3.4.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.3.tgz#c1df38231448e45ca4ac588e6c79573ba6a57d5b" integrity sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ== @@ -9845,7 +9833,7 @@ chokidar@^2.0.2, chokidar@^2.0.4, chokidar@^2.1.8: optionalDependencies: fsevents "^1.2.7" -chokidar@^3.2.2: +chokidar@^3.2.2, chokidar@^3.4.1: version "3.5.1" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== @@ -10357,7 +10345,7 @@ compression@^1.7.4: safe-buffer "5.1.2" vary "~1.1.2" -compute-scroll-into-view@^1.0.14: +compute-scroll-into-view@^1.0.16: version "1.0.16" resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.16.tgz#5b7bf4f7127ea2c19b750353d7ce6776a90ee088" integrity sha512-a85LHKY81oQnikatZYA90pufpZ6sQx++BoCxOEMsjpZx+ZnaKGQnCyCehTRr/1p9GBIAHTjcU9k71kSYWloLiQ== @@ -10626,15 +10614,23 @@ core-js-compat@^3.6.2: browserslist "^4.8.3" semver "7.0.0" +core-js-compat@^3.8.0: + version "3.8.3" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.8.3.tgz#9123fb6b9cad30f0651332dc77deba48ef9b0b3f" + integrity sha512-1sCb0wBXnBIL16pfFG1Gkvei6UzvKyTNYpiC41yrdjEv0UoJoq9E/abTMzyYJ6JpTkAj15dLjbqifIzEBDVvog== + dependencies: + browserslist "^4.16.1" + semver "7.0.0" + core-js-pure@^3.0.0: version "3.7.0" resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.7.0.tgz#28a57c861d5698e053f0ff36905f7a3301b4191e" integrity sha512-EZD2ckZysv8MMt4J6HSvS9K2GdtlZtdBncKAmF9lr2n0c9dJUaUN88PSTjvgwCgQPWKTkERXITgS6JJRAnljtg== core-js-pure@^3.0.1: - version "3.6.5" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813" - integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA== + version "3.8.3" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.8.3.tgz#10e9e3b2592ecaede4283e8f3ad7020811587c02" + integrity sha512-V5qQZVAr9K0xu7jXg1M7qTEwuxUgqr7dUOezGaNa7i+Xn9oXAU/d1fzqD9ObuwpVQOaorO5s70ckyi1woP9lVA== core-js@3.6.4: version "3.6.4" @@ -10652,9 +10648,9 @@ core-js@^2.0.0, core-js@^2.4.0: integrity sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA== core-js@^3.0.1, core-js@^3.0.4, core-js@^3.6.5: - 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== + version "3.8.3" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.8.3.tgz#c21906e1f14f3689f93abcc6e26883550dd92dd0" + integrity sha512-KPYXeVZYemC2TkNEkX/01I+7yd+nX3KddKwZ1Ww7SKWdI2wQprSgLmrTddT8nw92AjEklTsPBoSdQBhbI1bQ6Q== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" @@ -10946,7 +10942,7 @@ css-select@^1.1.0, css-select@~1.2.0: domutils "1.5.1" nth-check "~1.0.1" -css-select@^2.0.0: +css-select@^2.0.0, css-select@^2.0.2: version "2.1.0" resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.1.0.tgz#6a34653356635934a81baca68d0255432105dbef" integrity sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ== @@ -11578,7 +11574,7 @@ debug@3.1.0: dependencies: ms "2.0.0" -debug@3.2.6, debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.6: +debug@3.2.6, debug@^3.1.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.6: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== @@ -11597,6 +11593,13 @@ debug@^0.7.2: resolved "https://registry.yarnpkg.com/debug/-/debug-0.7.4.tgz#06e1ea8082c2cb14e39806e22e2f6f757f92af39" integrity sha1-BuHqgILCyxTjmAbiLi9vdX+Srzk= +debug@^3.0.0: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" @@ -11784,10 +11787,10 @@ destroy@~1.0.4: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= -detab@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/detab/-/detab-2.0.3.tgz#33e5dd74d230501bd69985a0d2b9a3382699a130" - integrity sha512-Up8P0clUVwq0FnFjDclzZsy9PadzRn5FFxrr47tQQvMHqyiFYVbpH8oXDzWtF0Q7pYy3l+RPmtBl+BsFF6wH0A== +detab@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/detab/-/detab-2.0.4.tgz#b927892069aff405fbb9a186fe97a44a92a94b43" + integrity sha512-8zdsQA5bIkoRECvCrNKPla84lyoR7DSAyf7p0YgXzBO9PDJx8KntPUay7NS6yp+KdxdVtiE5SpHKtbp2ZQyA9g== dependencies: repeat-string "^1.5.4" @@ -12060,13 +12063,13 @@ domutils@^1.5.1, domutils@^1.7.0: dom-serializer "0" domelementtype "1" -dot-case@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.3.tgz#21d3b52efaaba2ea5fda875bb1aa8124521cf4aa" - integrity sha512-7hwEmg6RiSQfm/GwPL4AAWXKy3YNNZA3oFv2Pdiey0mwkRCPZ9x6SZbkLcn8Ma5PYeVokzoD4Twv2n7LKp5WeA== +dot-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" + integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== dependencies: - no-case "^3.0.3" - tslib "^1.10.0" + no-case "^3.0.4" + tslib "^2.0.3" dot-prop@^4.2.0, dot-prop@^4.2.1: version "4.2.1" @@ -12119,14 +12122,14 @@ dotignore@~0.1.2: minimatch "^3.0.4" downshift@^6.0.6: - version "6.0.6" - resolved "https://registry.yarnpkg.com/downshift/-/downshift-6.0.6.tgz#82aee8e2e260d7ad99df8a0969bd002dd523abe8" - integrity sha512-tmLab3cXCn6PtZYl9V8r/nB2m+7/nCNrwo0B3kTHo/2lRBHr+1en1VNOQt2wIt0ajanAnxquZ00WPCyxe6cNFQ== + version "6.1.0" + resolved "https://registry.yarnpkg.com/downshift/-/downshift-6.1.0.tgz#f008063d9b63935910d9db12ead07979ab51ce66" + integrity sha512-MnEJERij+1pTVAsOPsH3q9MJGNIZuu2sT90uxOCEOZYH6sEzkVGtUcTBVDRQkE8y96zpB7uEbRn24aE9VpHnZg== dependencies: - "@babel/runtime" "^7.11.2" - compute-scroll-into-view "^1.0.14" + "@babel/runtime" "^7.12.5" + compute-scroll-into-view "^1.0.16" prop-types "^15.7.2" - react-is "^16.13.1" + react-is "^17.0.1" duplexer3@^0.1.4: version "0.1.4" @@ -12188,11 +12191,6 @@ electron-to-chromium@^1.3.488: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.502.tgz#6a55e993ef60a01fbdc2152ef5e47ee00c885c98" integrity sha512-TIeXOaHAvfP7FemGUtAJxStmOc1YFGWFNqdey/4Nk41L9b1nMmDVDGNMIWhZJvOfJxix6Cv5FGEnBK+yvw3UTg== -electron-to-chromium@^1.3.585: - version "1.3.588" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.588.tgz#c6515571737bfb42678115a5eaa818384593a9a5" - integrity sha512-0zr+ZfytnLeJZxGgmEpPTcItu5Mm4A5zHPZXLfHcGp0mdsk95rmD7ePNewYtK1yIdLbk8Z1U2oTRRfOtR4gbYg== - electron-to-chromium@^1.3.634: version "1.3.642" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.642.tgz#8b884f50296c2ae2a9997f024d0e3e57facc2b94" @@ -12337,10 +12335,10 @@ enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0: memory-fs "^0.5.0" tapable "^1.0.0" -enhanced-resolve@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz#3b806f3bfafc1ec7de69551ef93cca46c1704126" - integrity sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ== +enhanced-resolve@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec" + integrity sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg== dependencies: graceful-fs "^4.1.2" memory-fs "^0.5.0" @@ -12515,7 +12513,7 @@ es-abstract@1.18.0-next.1, es-abstract@^1.18.0-next.0, es-abstract@^1.18.0-next. string.prototype.trimend "^1.0.1" string.prototype.trimstart "^1.0.1" -es-abstract@^1.12.0, es-abstract@^1.13.0, es-abstract@^1.15.0, es-abstract@^1.5.1: +es-abstract@^1.12.0, es-abstract@^1.13.0, es-abstract@^1.5.1: version "1.16.0" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.0.tgz#d3a26dc9c3283ac9750dca569586e976d9dcc06d" integrity sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg== @@ -12565,17 +12563,38 @@ es-abstract@^1.17.0-next.0, es-abstract@^1.17.2, es-abstract@^1.17.4, es-abstrac string.prototype.trimend "^1.0.1" string.prototype.trimstart "^1.0.1" +es-abstract@^1.18.0-next.2: + version "1.18.0-next.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.2.tgz#088101a55f0541f595e7e057199e27ddc8f3a5c2" + integrity sha512-Ih4ZMFHEtZupnUh6497zEL4y2+w8+1ljnCyaTa+adcoafI1GOvMwFlDjBLfWR7y9VLfrjRJe9ocuHY1PSR9jjw== + dependencies: + call-bind "^1.0.2" + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.2.2" + is-negative-zero "^2.0.1" + is-regex "^1.1.1" + object-inspect "^1.9.0" + object-keys "^1.1.1" + object.assign "^4.1.2" + string.prototype.trimend "^1.0.3" + string.prototype.trimstart "^1.0.3" + es-array-method-boxes-properly@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== es-get-iterator@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.0.tgz#bb98ad9d6d63b31aacdc8f89d5d0ee57bcb5b4c8" - integrity sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ== + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.1.tgz#b93ddd867af16d5118e00881396533c1c6647ad9" + integrity sha512-qorBw8Y7B15DVLaJWy6WdEV/ZkieBcu6QCq/xzWzGOKJqgG1j754vXRfZ3NY7HSShneqU43mPB4OkQBTkvHhFw== dependencies: - es-abstract "^1.17.4" + call-bind "^1.0.0" + get-intrinsic "^1.0.1" has-symbols "^1.0.1" is-arguments "^1.0.4" is-map "^2.0.1" @@ -12611,9 +12630,9 @@ es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@^0.10.51, es5-ext@ next-tick "^1.0.0" es5-shim@^4.5.13: - version "4.5.14" - resolved "https://registry.yarnpkg.com/es5-shim/-/es5-shim-4.5.14.tgz#90009e1019d0ea327447cb523deaff8fe45697ef" - integrity sha512-7SwlpL+2JpymWTt8sNLuC2zdhhc+wrfe5cMPI2j0o6WsPdfAiPwmFy2f0AocPB4RQVBOZ9kNTgi5YF7TdhkvEg== + version "4.5.15" + resolved "https://registry.yarnpkg.com/es5-shim/-/es5-shim-4.5.15.tgz#6a26869b261854a3b045273f5583c52d390217fe" + integrity sha512-FYpuxEjMeDvU4rulKqFdukQyZSTpzhg4ScQHrAosrlVpR6GFyaw14f74yn2+4BugniIS0Frpg7TvwZocU4ZMTw== es6-iterator@^2.0.3, es6-iterator@~2.0.1, es6-iterator@~2.0.3: version "2.0.3" @@ -14056,14 +14075,15 @@ function-bind@^1.1.1, function-bind@~1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== -function.prototype.name@^1.1.0, function.prototype.name@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.2.tgz#5cdf79d7c05db401591dfde83e3b70c5123e9a45" - integrity sha512-C8A+LlHBJjB2AdcRPorc5JvJ5VUoWlXdEHLOJdCI7kjHEtGTpHQUiqMvCIKUwIsGwZX2jZJy761AXsn356bJQg== +function.prototype.name@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.3.tgz#0bb034bb308e7682826f215eb6b2ae64918847fe" + integrity sha512-H51qkbNSp8mtkJt+nyW1gyStBiKZxfRqySNUR99ylq6BPXHKI4SEvIlTKp4odLfjRKJV04DFWMU3G/YRlQOsag== dependencies: + call-bind "^1.0.0" define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" - functions-have-names "^1.2.0" + es-abstract "^1.18.0-next.1" + functions-have-names "^1.2.1" function.prototype.name@^1.1.1: version "1.1.1" @@ -14075,6 +14095,15 @@ function.prototype.name@^1.1.1: functions-have-names "^1.1.1" is-callable "^1.1.4" +function.prototype.name@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.2.tgz#5cdf79d7c05db401591dfde83e3b70c5123e9a45" + integrity sha512-C8A+LlHBJjB2AdcRPorc5JvJ5VUoWlXdEHLOJdCI7kjHEtGTpHQUiqMvCIKUwIsGwZX2jZJy761AXsn356bJQg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + functions-have-names "^1.2.0" + functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" @@ -14090,6 +14119,11 @@ functions-have-names@^1.2.0: resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.1.tgz#a981ac397fa0c9964551402cdc5533d7a4d52f91" integrity sha512-j48B/ZI7VKs3sgeI2cZp7WXWmZXu7Iq5pl5/vptV5N2mq+DGFuS/ulaDjtaoLpYzuD6u8UgrUKHfgo7fDTSiBA== +functions-have-names@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.2.tgz#98d93991c39da9361f8e50b337c4f6e41f120e21" + integrity sha512-bLgc3asbWdwPbx2mNk2S49kmJCuQeu0nfmaOgbs8WIyzzkw3r4htszdIi9Q9EMezDPTYuJx2wvjZ/EwgAthpnA== + fuse.js@^3.6.1: version "3.6.1" resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-3.6.1.tgz#7de85fdd6e1b3377c23ce010892656385fd9b10c" @@ -14169,6 +14203,15 @@ get-intrinsic@^1.0.0: has "^1.0.3" has-symbols "^1.0.1" +get-intrinsic@^1.0.1, get-intrinsic@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.0.tgz#892e62931e6938c8a23ea5aaebcfb67bd97da97e" + integrity sha512-M11rgtQp5GZMZzDL7jLTNxbDfurpzuau5uqRWDPvlHjfvg3TdScAZo96GLvhMjImrmR8uAt0FS2RLoMrfWGKlg== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + get-own-enumerable-property-symbols@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.1.tgz#6f7764f88ea11e0b514bd9bd860a132259992ca4" @@ -14852,10 +14895,10 @@ highlight-words-core@^1.2.0: resolved "https://registry.yarnpkg.com/highlight-words-core/-/highlight-words-core-1.2.2.tgz#1eff6d7d9f0a22f155042a00791237791b1eeaaa" integrity sha512-BXUKIkUuh6cmmxzi5OIbUJxrG8OAk2MqoL1DtO3Wo9D2faJg2ph5ntyuQeLqaHJmzER6H5tllCDA9ZnNe9BVGg== -highlight.js@^10.1.1, highlight.js@~10.4.0: - version "10.4.1" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.4.1.tgz#d48fbcf4a9971c4361b3f95f302747afe19dbad0" - integrity sha512-yR5lWvNz7c85OhVAEAeFhVCc/GV4C30Fjzc/rCP0aCWzc1UUOPUk55dK/qdwTZHBvMZo+eZ2jpk62ndX/xMFlg== +highlight.js@^10.1.1, highlight.js@~10.5.0: + version "10.5.0" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.5.0.tgz#3f09fede6a865757378f2d9ebdcbc15ba268f98f" + integrity sha512-xTmvd9HiIHR6L53TMC7TKolEj65zG1XU+Onr8oi86mYa+nLcIbxTTWkpW7CsEwv/vK7u1zb8alZIMLDqqN6KTw== hmac-drbg@^1.0.0: version "1.0.1" @@ -14960,17 +15003,7 @@ html-encoding-sniffer@^2.0.1: dependencies: whatwg-encoding "^1.0.5" -html-entities@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.3.1.tgz#fb9a1a4b5b14c5daba82d3e34c6ae4fe701a0e44" - integrity sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA== - -html-entities@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f" - integrity sha1-DfKTUfByEWNRXfueVUPl9u7VFi8= - -html-entities@^1.3.1: +html-entities@^1.2.0, html-entities@^1.2.1, html-entities@^1.3.1: version "1.4.0" resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.4.0.tgz#cfbd1b01d2afaf9adca1b10ae7dffab98c71d2dc" integrity sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA== @@ -15048,21 +15081,21 @@ html-webpack-plugin@3.2.0, html-webpack-plugin@^3.2.0: util.promisify "1.0.0" html-webpack-plugin@^4.2.1: - version "4.5.0" - resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.5.0.tgz#625097650886b97ea5dae331c320e3238f6c121c" - integrity sha512-MouoXEYSjTzCrjIxWwg8gxL5fE2X2WZJLmBYXlaJhQUH5K/b5OrqmV7T4dB7iu0xkmJ6JlUuV6fFVtnqbPopZw== + version "4.5.1" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.5.1.tgz#40aaf1b5cb78f2f23a83333999625c20929cda65" + integrity sha512-yzK7RQZwv9xB+pcdHNTjcqbaaDZ+5L0zJHXfi89iWIZmb/FtzxhLk0635rmJihcQbs3ZUF27Xp4oWGx6EK56zg== dependencies: "@types/html-minifier-terser" "^5.0.0" "@types/tapable" "^1.0.5" "@types/webpack" "^4.41.8" html-minifier-terser "^5.0.1" loader-utils "^1.2.3" - lodash "^4.17.15" + lodash "^4.17.20" pretty-error "^2.1.1" tapable "^1.1.3" util.promisify "1.0.0" -htmlparser2@^3.3.0, htmlparser2@^3.9.1: +htmlparser2@^3.10.1, htmlparser2@^3.3.0, htmlparser2@^3.9.1: version "3.10.1" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== @@ -15722,6 +15755,13 @@ is-core-module@^2.0.0: dependencies: has "^1.0.3" +is-core-module@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.2.0.tgz#97037ef3d52224d85163f5597b2b63d9afed981a" + integrity sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ== + dependencies: + has "^1.0.3" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -15899,9 +15939,9 @@ is-interactive@^1.0.0: integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== is-map@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.1.tgz#520dafc4307bb8ebc33b813de5ce7c9400d644a1" - integrity sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw== + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127" + integrity sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg== is-module@^1.0.0: version "1.0.0" @@ -15929,6 +15969,11 @@ is-negative-zero@^2.0.0: resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.0.tgz#9553b121b0fac28869da9ed459e20c7543788461" integrity sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE= +is-negative-zero@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" + integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== + is-npm@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" @@ -15962,9 +16007,9 @@ is-obj@^2.0.0: integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== is-object@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" - integrity sha1-iVJojF7C/9awPsyF52ngKQMINHA= + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.2.tgz#a56552e1c665c9e950b4a025461da87e72f86fcf" + integrity sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA== is-observable@^1.1.0: version "1.1.0" @@ -16107,9 +16152,9 @@ is-root@2.1.0: integrity sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg== is-set@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.1.tgz#d1604afdab1724986d30091575f54945da7e5f43" - integrity sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA== + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.2.tgz#90755fa4c2562dc1c5d4024760d6119b94ca18ec" + integrity sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g== is-ssh@^1.3.0: version "1.3.2" @@ -16128,7 +16173,7 @@ is-stream@^2.0.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== -is-string@^1.0.4, is-string@^1.0.5: +is-string@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ== @@ -16327,7 +16372,7 @@ iterate-iterator@^1.0.1: resolved "https://registry.yarnpkg.com/iterate-iterator/-/iterate-iterator-1.0.1.tgz#1693a768c1ddd79c969051459453f082fe82e9f6" integrity sha512-3Q6tudGN05kbkDQDI4CqjaBf4qf85w6W6GnuZDtUVYwKgtC1q8yxYX7CZed7N+tLzQqS6roujWvszf13T+n9aw== -iterate-value@^1.0.0: +iterate-value@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/iterate-value/-/iterate-value-1.0.2.tgz#935115bd37d006a52046535ebc8d07e9c9337f57" integrity sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ== @@ -17535,7 +17580,12 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" -lodash-es@^4.17.15, lodash-es@^4.2.1: +lodash-es@^4.17.15: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.20.tgz#29f6332eefc60e849f869c264bc71126ad61e8f7" + integrity sha512-JD1COMZsq8maT6mnuz1UMV0jvYD0E0aUsSOdrr1/nAG3dhqQXwRRgeW0cSqH1U43INKcqxaiVIQNOUDld7gRDA== + +lodash-es@^4.2.1: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78" integrity sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ== @@ -17773,12 +17823,12 @@ lower-case@^1.1.1: resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw= -lower-case@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.1.tgz#39eeb36e396115cc05e29422eaea9e692c9408c7" - integrity sha512-LiWgfDLLb1dwbFQZsSglpRj+1ctGnayXz3Uv0/WO8n558JycT5fg6zkNcnW0G68Nn0aEldTFeEfmjCfmqry/rQ== +lower-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" + integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== dependencies: - tslib "^1.10.0" + tslib "^2.0.3" lowercase-keys@^1.0.0: version "1.0.1" @@ -17786,12 +17836,12 @@ lowercase-keys@^1.0.0: integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== lowlight@^1.14.0: - version "1.17.0" - resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.17.0.tgz#a1143b2fba8239df8cd5893f9fe97aaf8465af4a" - integrity sha512-vmtBgYKD+QVNy7tIa7ulz5d//Il9R4MooOVh4nkOf9R9Cb/Dk5TXMSTieg/vDulkBkIWj59/BIlyFQxT9X1oAQ== + version "1.18.0" + resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.18.0.tgz#cfff11cfb125ca66f1c12cb43d27fff68cbeafa9" + integrity sha512-Zlc3GqclU71HRw5fTOy00zz5EOlqAdKMYhOFIO8ay4SQEDQgFuhR8JNwDIzAGMLoqTsWxe0elUNmq5o2USRAzw== dependencies: fault "^1.0.0" - highlight.js "~10.4.0" + highlight.js "~10.5.0" lru-cache@^4.0.1: version "4.1.5" @@ -17859,7 +17909,7 @@ make-dir@^3.0.0: dependencies: semver "^6.0.0" -make-dir@^3.0.2: +make-dir@^3.0.2, make-dir@^3.1.0: 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== @@ -17999,21 +18049,21 @@ mdast-util-definitions@^2.0.0: dependencies: unist-util-visit "^2.0.0" -mdast-util-definitions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-3.0.1.tgz#06af6c49865fc63d6d7d30125569e2f7ae3d0a86" - integrity sha512-BAv2iUm/e6IK/b2/t+Fx69EL/AGcq/IG2S+HxHjDJGfLJtd6i9SZUS76aC9cig+IEucsqxKTR0ot3m933R3iuA== +mdast-util-definitions@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz#c5c1a84db799173b4dcf7643cda999e440c24db2" + integrity sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ== dependencies: unist-util-visit "^2.0.0" -mdast-util-to-hast@9.1.2: - version "9.1.2" - resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-9.1.2.tgz#10fa5ed9d45bf3755891e5801d0f32e2584a9423" - integrity sha512-OpkFLBC2VnNAb2FNKcKWu9FMbJhQKog+FCT8nuKmQNIKXyT1n3SIskE7uWDep6x+cA20QXlK5AETHQtYmQmxtQ== +mdast-util-to-hast@10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-10.0.1.tgz#0cfc82089494c52d46eb0e3edb7a4eb2aea021eb" + integrity sha512-BW3LM9SEMnjf4HXXVApZMt8gLQWVNXc3jryK0nJu/rOXPOnlkUjmdkDlmxMirpbU9ILncGFIwLH/ubnWBbcdgA== dependencies: "@types/mdast" "^3.0.0" "@types/unist" "^2.0.0" - mdast-util-definitions "^3.0.0" + mdast-util-definitions "^4.0.0" mdurl "^1.0.0" unist-builder "^2.0.0" unist-util-generated "^1.0.0" @@ -18217,10 +18267,10 @@ mime-db@1.40.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32" integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA== -mime-db@1.44.0: - 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-db@1.45.0: + version "1.45.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" + integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w== "mime-db@>= 1.40.0 < 2": version "1.42.0" @@ -18235,11 +18285,11 @@ mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: mime-db "1.40.0" mime-types@^2.1.27: - version "2.1.27" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" - integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w== + version "2.1.28" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.28.tgz#1160c4757eab2c5363888e005273ecf79d2a0ecd" + integrity sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ== dependencies: - mime-db "1.44.0" + mime-db "1.45.0" mime@1.6.0, mime@^1.4.1: version "1.6.0" @@ -18785,13 +18835,13 @@ no-case@^2.2.0: dependencies: lower-case "^1.1.1" -no-case@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.3.tgz#c21b434c1ffe48b39087e86cfb4d2582e9df18f8" - integrity sha512-ehY/mVQCf9BL0gKfsJBvFJen+1V//U+0HQMPrWct40ixE4jnv0bfvxDbWtAHL9EcaPEOJHVVYKoQn1TlZUB8Tw== +no-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" + integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== dependencies: - lower-case "^2.0.1" - tslib "^1.10.0" + lower-case "^2.0.2" + tslib "^2.0.3" node-dir@^0.1.10: version "0.1.17" @@ -18931,11 +18981,6 @@ node-releases@^1.1.58: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.59.tgz#4d648330641cec704bff10f8e4fe28e453ab8e8e" integrity sha512-H3JrdUczbdiwxN5FuJPyCHnGHIFqQ0wWxo+9j1kAXAzqNMAHlo+4I/sYYxpyK0irQ73HgdiyzD32oqQDcU2Osw== -node-releases@^1.1.65: - version "1.1.65" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.65.tgz#52d9579176bd60f23eba05c4438583f341944b81" - integrity sha512-YpzJOe2WFIW0V4ZkJQd/DGR/zdVwc/pI4Nl1CZrBO19FdRcSTmsuhdttw9rsTzzJLrNcSloLiBbEYx1C4f6gpA== - node-releases@^1.1.69: version "1.1.70" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.70.tgz#66e0ed0273aa65666d7fe78febe7634875426a08" @@ -19174,6 +19219,11 @@ object-inspect@^1.8.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA== +object-inspect@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a" + integrity sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw== + object-is@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.1.tgz#0aa60ec9989a0b3ed795cf4d06f62cf1ad6539b6" @@ -19214,7 +19264,7 @@ object.assign@4.1.0, object.assign@^4.1.0: has-symbols "^1.0.0" object-keys "^1.0.11" -object.assign@^4.1.1: +object.assign@^4.1.1, object.assign@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== @@ -19254,13 +19304,13 @@ object.entries@^1.1.2: has "^1.0.3" "object.fromentries@^2.0.0 || ^1.0.0": - version "2.0.1" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.1.tgz#050f077855c7af8ae6649f45c80b16ee2d31e704" - integrity sha512-PUQv8Hbg3j2QX0IQYv3iAGCbGcu4yY4KQ92/dhA4sFSixBmSmp13UpDLs6jGK8rBtbmhNNIK99LD2k293jpiGA== + version "2.0.3" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.3.tgz#13cefcffa702dc67750314a3305e8cb3fad1d072" + integrity sha512-IDUSMXs6LOSJBWE++L0lzIbSqHl9KDCfff2x/JSEIDtEUavUnyMYC2ZGay/04Zq4UT8lvd4xNhU4/YHKibAOlw== dependencies: + call-bind "^1.0.0" define-properties "^1.1.3" - es-abstract "^1.15.0" - function-bind "^1.1.1" + es-abstract "^1.18.0-next.1" has "^1.0.3" object.fromentries@^2.0.2: @@ -19502,9 +19552,9 @@ ospath@^1.2.2: integrity sha1-EnZjl3Sj+O8lcvf+QoDg6kVQwHs= overlayscrollbars@^1.10.2: - version "1.13.0" - resolved "https://registry.yarnpkg.com/overlayscrollbars/-/overlayscrollbars-1.13.0.tgz#1edb436328133b94877b558f77966d5497ca36a7" - integrity sha512-p8oHrMeRAKxXDMPI/EBNITj/zTVHKNnAnM59Im+xnoZUlV07FyTg46wom2286jJlXGGfcPFG/ba5NUiCwWNd4w== + version "1.13.1" + resolved "https://registry.yarnpkg.com/overlayscrollbars/-/overlayscrollbars-1.13.1.tgz#0b840a88737f43a946b9d87875a2f9e421d0338a" + integrity sha512-gIQfzgGgu1wy80EB4/6DaJGHMEGmizq27xHIESrzXq0Y/J0Ay1P3DWk6tuVmEPIZH15zaBlxeEJOqdJKmowHCQ== p-all@^2.1.0: version "2.1.0" @@ -19581,11 +19631,11 @@ p-limit@^2.3.0: p-try "^2.0.0" p-limit@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.0.2.tgz#1664e010af3cadc681baafd3e2a437be7b0fb5fe" - integrity sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg== + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== dependencies: - p-try "^2.0.0" + yocto-queue "^0.1.0" p-locate@^2.0.0: version "2.0.0" @@ -19736,12 +19786,12 @@ param-case@2.1.x: no-case "^2.2.0" param-case@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.3.tgz#4be41f8399eff621c56eebb829a5e451d9801238" - integrity sha512-VWBVyimc1+QrzappRs7waeN2YmoZFCGXWASRYX1/rGHtXqEcrGEIDm+jqIwFa2fRXNgQEwrxaYuIrX0WcAguTA== + version "3.0.4" + resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" + integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A== dependencies: - dot-case "^3.0.3" - tslib "^1.10.0" + dot-case "^3.0.4" + tslib "^2.0.3" parent-module@^1.0.0: version "1.0.1" @@ -19856,13 +19906,13 @@ parseurl@~1.3.2, parseurl@~1.3.3: resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== -pascal-case@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.1.tgz#5ac1975133ed619281e88920973d2cd1f279de5f" - integrity sha512-XIeHKqIrsquVTQL2crjq3NfJUxmdLasn3TYOU0VBM+UX2a6ztAWBlJQBePLGY7VHW8+2dRadeIPK5+KImwTxQA== +pascal-case@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb" + integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g== dependencies: - no-case "^3.0.3" - tslib "^1.10.0" + no-case "^3.0.4" + tslib "^2.0.3" pascalcase@^0.1.1: version "0.1.1" @@ -21031,10 +21081,10 @@ prismjs@1.21.0: optionalDependencies: clipboard "^2.0.0" -prismjs@^1.21.0, prismjs@~1.22.0: - version "1.22.0" - resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.22.0.tgz#73c3400afc58a823dd7eed023f8e1ce9fd8977fa" - integrity sha512-lLJ/Wt9yy0AiSYBf212kK3mM5L8ycwlyTlSxHBAneXLR0nzFMlZ5y7riFPF3E33zXOF2IH95xdY5jIyZbM9z/w== +prismjs@^1.21.0, prismjs@~1.23.0: + version "1.23.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.23.0.tgz#d3b3967f7d72440690497652a9d40ff046067f33" + integrity sha512-c29LVsqOaLbBHuIbsTxaKENh1N2EQBOHaWv7gkHN4dgRbxSREqDnDbtFJYdpPauS4YCplMSNCABQ6Eeor69bAA== optionalDependencies: clipboard "^2.0.0" @@ -21077,15 +21127,16 @@ promise-retry@^1.1.1: retry "^0.10.0" promise.allsettled@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/promise.allsettled/-/promise.allsettled-1.0.2.tgz#d66f78fbb600e83e863d893e98b3d4376a9c47c9" - integrity sha512-UpcYW5S1RaNKT6pd+s9jp9K9rlQge1UXKskec0j6Mmuq7UJCvlS2J2/s/yuPN8ehftf9HXMxWlKiPbGGUzpoRg== + version "1.0.4" + resolved "https://registry.yarnpkg.com/promise.allsettled/-/promise.allsettled-1.0.4.tgz#65e71f2a604082ed69c548b68603294090ee6803" + integrity sha512-o73CbvQh/OnPFShxHcHxk0baXR2a1m4ozb85ha0H14VEoi/EJJLa9mnPfEWJx9RjA9MLfhdjZ8I6HhWtBa64Ag== dependencies: - array.prototype.map "^1.0.1" + array.prototype.map "^1.0.3" + call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" - function-bind "^1.1.1" - iterate-value "^1.0.0" + es-abstract "^1.18.0-next.2" + get-intrinsic "^1.0.2" + iterate-value "^1.0.2" promise.prototype.finally@^3.1.0: version "3.1.2" @@ -21151,11 +21202,11 @@ propagating-hammerjs@^1.4.6: hammerjs "^2.0.8" property-information@^5.0.0, property-information@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/property-information/-/property-information-5.3.0.tgz#bc87ac82dc4e72a31bb62040544b1bf9653da039" - integrity sha512-IslotQn1hBCZDY7SaJ3zmCjVea219VTwmOk6Pu3z9haU9m4+T8GwaDubur+6NMHEU+Fjs/6/p66z6QULPkcL1w== + version "5.6.0" + resolved "https://registry.yarnpkg.com/property-information/-/property-information-5.6.0.tgz#61675545fb23002f245c6540ec46077d4da3ed69" + integrity sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA== dependencies: - xtend "^4.0.1" + xtend "^4.0.0" proto-list@~1.2.1: version "1.2.4" @@ -21302,12 +21353,7 @@ qs@6.7.0: resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== -qs@^6.6.0: - version "6.9.4" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.4.tgz#9090b290d1f91728d3c22e54843ca44aea5ab687" - integrity sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ== - -qs@^6.9.4: +qs@^6.6.0, qs@^6.9.4: version "6.9.6" resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.6.tgz#26ed3c8243a431b2924aca84cc90471f35d5a0ee" integrity sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ== @@ -21742,7 +21788,7 @@ react-dev-utils@^10.0.0, react-dev-utils@^10.2.1: strip-ansi "6.0.0" text-table "0.2.0" -react-docgen-typescript-loader@3.7.2, react-docgen-typescript-loader@^3.7.2: +react-docgen-typescript-loader@3.7.2: version "3.7.2" resolved "https://registry.yarnpkg.com/react-docgen-typescript-loader/-/react-docgen-typescript-loader-3.7.2.tgz#45cb2305652c0602767242a8700ad1ebd66bbbbd" integrity sha512-fNzUayyUGzSyoOl7E89VaPKJk9dpvdSgyXg81cUkwy0u+NBvkzQG3FC5WBIlXda0k/iaxS+PWi+OC+tUiGxzPA== @@ -21752,15 +21798,14 @@ react-docgen-typescript-loader@3.7.2, react-docgen-typescript-loader@^3.7.2: react-docgen-typescript "^1.15.0" react-docgen-typescript-plugin@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/react-docgen-typescript-plugin/-/react-docgen-typescript-plugin-0.6.2.tgz#c83305206c61d5c7e004eaf2dc4661367ddc105d" - integrity sha512-Orw0WKdJGAg5eMZGbEMw/rKonoxbi8epU6RJWTW3ukWuTarxckFXTltGvm8XADAWlBHak30KD71XThtJruxfTg== + version "0.6.3" + resolved "https://registry.yarnpkg.com/react-docgen-typescript-plugin/-/react-docgen-typescript-plugin-0.6.3.tgz#664b22601df083597ecb1e60bd21beca60125fdf" + integrity sha512-av1S/fmWBNFGgNa4qtkidFjjOz23eEi6EdCtwSWo9WNhGzUMyMygbD/DosMWoeFlZpk9R3MXPkRE7PDH6j5GMQ== dependencies: debug "^4.1.1" endent "^2.0.1" micromatch "^4.0.2" - react-docgen-typescript "^1.20.1" - react-docgen-typescript-loader "^3.7.2" + react-docgen-typescript "^1.20.5" tslib "^2.0.0" react-docgen-typescript@^1.15.0: @@ -21768,7 +21813,7 @@ react-docgen-typescript@^1.15.0: resolved "https://registry.yarnpkg.com/react-docgen-typescript/-/react-docgen-typescript-1.15.0.tgz#963f14210841f9b51ed18c65152a6cc37f1c3184" integrity sha512-8xObdkRQbrc0505tEdVRO+pdId8pKFyD6jhLYM9FDdceKma+iB+a17Dk7e3lPRBRh8ArQLCedOCOfN/bO338kw== -react-docgen-typescript@^1.20.1: +react-docgen-typescript@^1.20.5: version "1.20.5" resolved "https://registry.yarnpkg.com/react-docgen-typescript/-/react-docgen-typescript-1.20.5.tgz#fb8d78a707243498436c2952bd3f6f488a68d4f3" integrity sha512-AbLGMtn76bn7SYBJSSaKJrZ0lgNRRR3qL60PucM5M4v/AXyC8221cKBXW5Pyt9TfDRfe+LDnPNlg7TibxX0ovA== @@ -21922,6 +21967,13 @@ react-input-autosize@^2.2.2: dependencies: prop-types "^15.5.8" +react-input-autosize@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-3.0.0.tgz#6b5898c790d4478d69420b55441fcc31d5c50a85" + integrity sha512-nL9uS7jEs/zu8sqwFE5MAPx6pPkNAriACQ2rGLlqmKr2sPGtN7TXTyDdQt4lbNXVx7Uzadb40x8qotIuru6Rhg== + dependencies: + prop-types "^15.5.8" + react-inspector@^5.0.1: version "5.1.0" resolved "https://registry.yarnpkg.com/react-inspector/-/react-inspector-5.1.0.tgz#45a325e15f33e595be5356ca2d3ceffb7d6b8c3a" @@ -21972,7 +22024,7 @@ react-monaco-editor@0.36.0: monaco-editor "*" prop-types "^15.7.2" -react-popper-tooltip@^3.1.0: +react-popper-tooltip@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/react-popper-tooltip/-/react-popper-tooltip-3.1.1.tgz#329569eb7b287008f04fcbddb6370452ad3f9eac" integrity sha512-EnERAnnKRptQBJyaee5GJScWNUKQPDD2ywvzZyUjst/wj5U64C8/CnSYLNEmP2hG0IJ3ZhtDxE8oDN+KOyavXQ== @@ -22031,9 +22083,9 @@ react-reverse-portal@^2.0.1: integrity sha512-sj/D9nSHspqV8i8hWkTSZ5Ohnrqk2A5fkDKw4Xe/zV4OfF1UYwmbzrxLdmNRdKkWgQwnXIxaa2E3FC7QYdZAeA== react-select@^3.0.8: - version "3.1.0" - resolved "https://registry.yarnpkg.com/react-select/-/react-select-3.1.0.tgz#ab098720b2e9fe275047c993f0d0caf5ded17c27" - integrity sha512-wBFVblBH1iuCBprtpyGtd1dGMadsG36W5/t2Aj8OE6WbByDg5jIFyT7X5gT+l0qmT5TqWhxX+VsKJvCEl2uL9g== + version "3.2.0" + resolved "https://registry.yarnpkg.com/react-select/-/react-select-3.2.0.tgz#de9284700196f5f9b5277c5d850a9ce85f5c72fe" + integrity sha512-B/q3TnCZXEKItO0fFN/I0tWOX3WJvi/X2wtdffmwSQVRwg5BpValScTO1vdic9AxlUgmeSzib2hAZAwIUQUZGQ== dependencies: "@babel/runtime" "^7.4.4" "@emotion/cache" "^10.0.9" @@ -22041,7 +22093,7 @@ react-select@^3.0.8: "@emotion/css" "^10.0.9" memoize-one "^5.0.0" prop-types "^15.6.0" - react-input-autosize "^2.2.2" + react-input-autosize "^3.0.0" react-transition-group "^4.3.0" react-shallow-renderer@^16.13.1: @@ -22143,9 +22195,9 @@ react-test-renderer@^17.0.0-0: scheduler "^0.20.1" react-textarea-autosize@^8.1.1: - version "8.2.0" - resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.2.0.tgz#fae38653f5ec172a855fd5fffb39e466d56aebdb" - integrity sha512-grajUlVbkx6VdtSxCgzloUIphIZF5bKr21OYMceWPKkniy7H0mRAT/AXPrRtObAe+zUePnNlBwUc4ivVjUGIjw== + version "8.3.0" + resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.3.0.tgz#e6e2fd186d9f61bb80ac6e2dcb4c55504f93c2fa" + integrity sha512-3GLWFAan2pbwBeoeNDoqGmSbrShORtgWfaWX0RJDivsUrpShh01saRM5RU/i4Zmf+whpBVEY5cA90Eq8Ub1N3w== dependencies: "@babel/runtime" "^7.10.2" use-composed-ref "^1.0.0" @@ -22547,13 +22599,13 @@ reflect.ownkeys@^0.2.0: integrity sha1-dJrO7H8/34tj+SegSAnpDFwLNGA= refractor@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/refractor/-/refractor-3.2.0.tgz#bc46f7cfbb6adbf45cd304e8e299b7fa854804e0" - integrity sha512-hSo+EyMIZTLBvNNgIU5lW4yjCzNYMZ4dcEhBq/3nReGfqzd2JfVhdlPDfU9rEsgcAyWx+OimIIUoL4ZU7NtYHQ== + version "3.3.1" + resolved "https://registry.yarnpkg.com/refractor/-/refractor-3.3.1.tgz#ebbc04b427ea81dc25ad333f7f67a0b5f4f0be3a" + integrity sha512-vaN6R56kLMuBszHSWlwTpcZ8KTMG6aUCok4GrxYDT20UIOXxOc5o6oDc8tNTzSlH3m2sI+Eu9Jo2kVdDcUTWYw== dependencies: hastscript "^6.0.0" parse-entities "^2.0.0" - prismjs "~1.22.0" + prismjs "~1.23.0" regenerate-unicode-properties@^8.1.0: version "8.1.0" @@ -22745,16 +22797,16 @@ remark-footnotes@2.0.0: resolved "https://registry.yarnpkg.com/remark-footnotes/-/remark-footnotes-2.0.0.tgz#9001c4c2ffebba55695d2dd80ffb8b82f7e6303f" integrity sha512-3Clt8ZMH75Ayjp9q4CorNeyjwIxHFcTkaektplKGl2A1jNGEUey8cKL0ZC5vJwfcD5GFGsNLImLG/NGzWIzoMQ== -remark-mdx@1.6.21: - version "1.6.21" - resolved "https://registry.yarnpkg.com/remark-mdx/-/remark-mdx-1.6.21.tgz#0c1a7e042e50938ff89ad8dd7e8e219d4b0404ce" - integrity sha512-IGb3l46a6NFi62egT+WXeTT3T8wYTunmPCEGTfDO6oRAfuss9VAb/3InVCKKGXXoiNi0mTuplI0EFusdCLGk3A== +remark-mdx@1.6.22: + version "1.6.22" + resolved "https://registry.yarnpkg.com/remark-mdx/-/remark-mdx-1.6.22.tgz#06a8dab07dcfdd57f3373af7f86bd0e992108bbd" + integrity sha512-phMHBJgeV76uyFkH4rvzCftLfKCr2RZuF+/gmVcaKrpsihyzmhXjA0BEMDaPTXG5y8qZOKPVo83NAOX01LPnOQ== dependencies: - "@babel/core" "7.11.6" + "@babel/core" "7.12.9" "@babel/helper-plugin-utils" "7.10.4" - "@babel/plugin-proposal-object-rest-spread" "7.11.0" - "@babel/plugin-syntax-jsx" "7.10.4" - "@mdx-js/util" "1.6.21" + "@babel/plugin-proposal-object-rest-spread" "7.12.1" + "@babel/plugin-syntax-jsx" "7.12.1" + "@mdx-js/util" "1.6.22" is-alphabetical "1.0.4" remark-parse "8.0.3" unified "9.2.0" @@ -22814,13 +22866,13 @@ renderkid@^2.0.1: utila "^0.4.0" renderkid@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-2.0.4.tgz#d325e532afb28d3f8796ffee306be8ffd6fc864c" - integrity sha512-K2eXrSOJdq+HuKzlcjOlGoOarUu5SDguDEhE7+Ah4zuOWL40j8A/oHvLlLob9PSTNvVnBd+/q0Er1QfpEuem5g== + version "2.0.5" + resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-2.0.5.tgz#483b1ac59c6601ab30a7a596a5965cabccfdd0a5" + integrity sha512-ccqoLg+HLOHq1vdfYNm4TBeaCDIi1FLt3wGojTDSvdewUv65oTmI3cnT2E4hRjl1gzKZIPK+KZrXzlUYKnR+vQ== dependencies: - css-select "^1.1.0" + css-select "^2.0.2" dom-converter "^0.2" - htmlparser2 "^3.3.0" + htmlparser2 "^3.10.1" lodash "^4.17.20" strip-ansi "^3.0.0" @@ -22841,11 +22893,6 @@ repeating@^2.0.0: dependencies: is-finite "^1.0.0" -replace-ext@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" - integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= - replace-in-file-webpack-plugin@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/replace-in-file-webpack-plugin/-/replace-in-file-webpack-plugin-1.0.6.tgz#eee7e139be967e8e48a0552f73037ed567b54dbd" @@ -23057,14 +23104,22 @@ resolve@1.17.0, resolve@^1.17.0, resolve@~1.17.0: dependencies: path-parse "^1.0.6" -resolve@^1.1.6, resolve@^1.10.0, resolve@^1.3.2: +resolve@^1.1.6, resolve@^1.12.0: + version "1.19.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" + integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== + dependencies: + is-core-module "^2.1.0" + path-parse "^1.0.6" + +resolve@^1.10.0, resolve@^1.3.2: version "1.12.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== dependencies: path-parse "^1.0.6" -resolve@^1.12.0, resolve@^1.18.1: +resolve@^1.18.1: version "1.18.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.18.1.tgz#018fcb2c5b207d2a6424aee361c5a266da8f4130" integrity sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA== @@ -23802,6 +23857,15 @@ side-channel@^1.0.2: es-abstract "^1.18.0-next.0" object-inspect "^1.8.0" +side-channel@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.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" @@ -24333,10 +24397,10 @@ storybook-dark-mode@0.4.0: fast-deep-equal "^3.0.0" memoizerific "^1.11.3" -storybook-dark-mode@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/storybook-dark-mode/-/storybook-dark-mode-1.0.3.tgz#8d58a874b6107ff1a7f29ebb0e6726b8036eee08" - integrity sha512-mjHLrv/dwtqKmbOoQ2CMtGKDttWSnUybutujsIPxLcEC77EujjWiRBFv46LtXAZEyZLm8sGFUz0s6HJJfJ3tSw== +storybook-dark-mode@1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/storybook-dark-mode/-/storybook-dark-mode-1.0.4.tgz#848e5ee6c5dd6180d15c533380c8b35579ec4975" + integrity sha512-4ZQh6scu/WlUycAMNbkNyF/9fN2bI/sJvNdPZoBa1b2X1UtsgzUeHRCGWcLsTpoiaPgPE/+eT077PuYHm5sYLQ== dependencies: fast-deep-equal "^3.0.0" memoizerific "^1.11.3" @@ -24446,7 +24510,20 @@ string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" -"string.prototype.matchall@^4.0.0 || ^3.0.1", string.prototype.matchall@^4.0.2: +"string.prototype.matchall@^4.0.0 || ^3.0.1": + version "4.0.3" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.3.tgz#24243399bc31b0a49d19e2b74171a15653ec996a" + integrity sha512-OBxYDA2ifZQ2e13cP82dWFMaCV9CGF8GzmN4fljBVw5O5wep0lu4gacm1OL6MjROoUnB8VbkWRThqkV2YFLNxw== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + has-symbols "^1.0.1" + internal-slot "^1.0.2" + regexp.prototype.flags "^1.3.0" + side-channel "^1.0.3" + +string.prototype.matchall@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.2.tgz#48bb510326fb9fdeb6a33ceaa81a6ea04ef7648e" integrity sha512-N/jp6O5fMf9os0JU3E72Qhf590RSRZU/ungsL/qJUYVTNv7hTG0P/dbPjxINVN9jpscu3nzYwKESU3P3RY5tOg== @@ -24459,20 +24536,22 @@ string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0: side-channel "^1.0.2" string.prototype.padend@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.1.0.tgz#dc08f57a8010dc5c153550318f67e13adbb72ac3" - integrity sha512-3aIv8Ffdp8EZj8iLwREGpQaUZiPyrWrpzMBHvkiSW/bK/EGve9np07Vwy7IJ5waydpGXzQZu/F8Oze2/IWkBaA== + version "3.1.1" + resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.1.1.tgz#824c84265dbac46cade2b957b38b6a5d8d1683c5" + integrity sha512-eCzTASPnoCr5Ht+Vn1YXgm8SB015hHKgEIMu9Nr9bQmLhRBxKRfmzSj/IQsxDFc8JInJDDFA0qXwK+xxI7wDkg== dependencies: + call-bind "^1.0.0" define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" + es-abstract "^1.18.0-next.1" string.prototype.padstart@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string.prototype.padstart/-/string.prototype.padstart-3.1.0.tgz#b47c087540d0710be5a49375751a0a627bd4ff90" - integrity sha512-envqZvUp2JItI+OeQ5UAh1ihbAV5G/2bixTojvlIa090GGqF+NQRxbWb2nv9fTGrZABv6+pE6jXoAZhhS2k4Hw== + version "3.1.1" + resolved "https://registry.yarnpkg.com/string.prototype.padstart/-/string.prototype.padstart-3.1.1.tgz#5a1ce79d21899073f630895cb9c7ce7f5acf51d6" + integrity sha512-kcFjKhQYg40AK9MITCWYr/vIebruAD01sc/fxi8szHJaEG7Rke4XHw6LU9c1VWXh/+J/PxvWLLf/aIAGKhXkAQ== dependencies: + call-bind "^1.0.0" define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" + es-abstract "^1.18.0-next.1" string.prototype.trim@^1.2.1: version "1.2.1" @@ -24500,6 +24579,14 @@ string.prototype.trimend@^1.0.1: define-properties "^1.1.3" es-abstract "^1.18.0-next.1" +string.prototype.trimend@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz#a22bd53cca5c7cf44d7c9d5c732118873d6cd18b" + integrity sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + string.prototype.trimleft@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" @@ -24540,6 +24627,14 @@ string.prototype.trimstart@^1.0.1: define-properties "^1.1.3" es-abstract "^1.18.0-next.1" +string.prototype.trimstart@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz#9b4cb590e123bb36564401d59824298de50fd5aa" + integrity sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -24802,12 +24897,14 @@ symbol-tree@^3.2.2, symbol-tree@^3.2.4: integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== symbol.prototype.description@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/symbol.prototype.description/-/symbol.prototype.description-1.0.2.tgz#f325e1e6ad534b3b29c9c3ca73c136c9ce03c5e2" - integrity sha512-2CW5SU4/Ki1cYOOHcL2cXK4rxSg5hCU1TwZ7X4euKhV9VnfqKslh7T6/UyKkubA8cq2tOmsOv7m3ZUmQslBRuw== + version "1.0.3" + resolved "https://registry.yarnpkg.com/symbol.prototype.description/-/symbol.prototype.description-1.0.3.tgz#5b0eb61595bca6945da95ec7696a25e55aa1eca6" + integrity sha512-NvwWb5AdyTtmFNa1x0ksJakFUV/WJ+z7iRrYGU1xZew77Qd+kMrZKsk3uatCckk6yPNpbHhRcOO+JBU+ohcMBw== dependencies: - es-abstract "^1.17.0-next.1" + call-bind "^1.0.0" + es-abstract "^1.18.0-next.1" has-symbols "^1.0.1" + object.getownpropertydescriptors "^2.1.0" systemjs-plugin-css@0.1.37: version "0.1.37" @@ -24892,9 +24989,9 @@ tar@^4, tar@^4.4.10, tar@^4.4.12, tar@^4.4.8: yallist "^3.0.3" tar@^6.0.2: - version "6.0.5" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.5.tgz#bde815086e10b39f1dcd298e89d596e1535e200f" - integrity sha512-0b4HOimQHj9nXNEAA7zWwMM91Zhhba3pspja6sQbgTpynOJf+bkjBnfybNYzbpLbnwXnbyB4LOREvlyXLkCHSg== + version "6.1.0" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.0.tgz#d1724e9bcc04b977b18d5c573b333a2207229a83" + integrity sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA== dependencies: chownr "^2.0.0" fs-minipass "^2.0.0" @@ -24904,9 +25001,9 @@ tar@^6.0.2: yallist "^4.0.0" telejson@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/telejson/-/telejson-5.0.2.tgz#ed1e64be250cc1c757a53c19e1740b49832b3d51" - integrity sha512-XCrDHGbinczsscs8LXFr9jDhvy37yBk9piB7FJrCfxE8oP66WDkolNMpaBkWYgQqB9dQGBGtTDzGQPedc9KJmw== + version "5.1.0" + resolved "https://registry.yarnpkg.com/telejson/-/telejson-5.1.0.tgz#cc04e4c2a355f9eb6af557e37acd6449feb1d146" + integrity sha512-Yy0N2OV0mosmr1SCZEm3Ezhu/oi5Dbao5RqauZu4+VI5I/XtVBHXajRk0txuqbFYtKdzzWGDZFGSif9ovVLjEA== dependencies: "@types/is-function" "^1.0.0" global "^4.4.0" @@ -24914,7 +25011,7 @@ telejson@^5.0.2: is-regex "^1.1.1" is-symbol "^1.0.3" isobject "^4.0.0" - lodash "^4.17.19" + lodash "^4.17.20" memoizerific "^1.11.3" temp-dir@^1.0.0: @@ -25449,7 +25546,7 @@ tslib@2.0.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.1.tgz#410eb0d113e5b6356490eec749603725b021b43e" integrity sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ== -tslib@2.0.3, tslib@^2.0.0, tslib@^2.0.1: +tslib@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.3.tgz#8e0741ac45fc0c226e58a17bfc3e64b9bc6ca61c" integrity sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ== @@ -25459,6 +25556,11 @@ tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== +tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a" + integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A== + tsutils@^3.17.1: version "3.17.1" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" @@ -25757,9 +25859,9 @@ unist-util-generated@^1.0.0: integrity sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg== unist-util-is@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.0.3.tgz#e8b44db55fc20c43752b3346c116344d45d7c91d" - integrity sha512-bTofCFVx0iQM8Jqb1TBDVRIQW03YkD3p66JOd/aCWuqzlLyUtx1ZAGw/u+Zw+SttKvSVcvTiKYbfrtLoLefykw== + version "4.0.4" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.0.4.tgz#3e9e8de6af2eb0039a59f50c9b3e99698a924f50" + integrity sha512-3dF39j/u423v4BBQrk1AQ2Ve1FxY5W3JKwXxVFzBODQ6WEvccguhgp802qQLKSnxPODE6WuRZtV+ohlUg4meBA== unist-util-map@^1.0.2: version "1.0.5" @@ -25962,9 +26064,9 @@ use-composed-ref@^1.0.0: ts-essentials "^2.0.3" use-isomorphic-layout-effect@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.0.tgz#4db2111e0d53ca694187ea5fd5cb2ba610286fe0" - integrity sha512-kady5Z1O1qx5RitodCCKbpJSVEtECXYcnBnb5Q48Bz5V6gBmTu85ZcGdVwVFs8+DaOurNb/L5VdGHoQRMknghw== + version "1.1.1" + resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.1.tgz#7bb6589170cd2987a152042f9084f9effb75c225" + integrity sha512-L7Evj8FGcwo/wpbv/qvSfrkHFtOpCzvM5yl2KVyDJoylVuSvzphiiasmjgQPttIGBAy2WKiBNR98q8w7PiNgKQ== use-latest@^1.0.0: version "1.2.0" @@ -26152,13 +26254,12 @@ vfile-message@^2.0.0: unist-util-stringify-position "^2.0.0" vfile@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/vfile/-/vfile-4.2.0.tgz#26c78ac92eb70816b01d4565e003b7e65a2a0e01" - integrity sha512-a/alcwCvtuc8OX92rqqo7PflxiCgXRFjdyoGVuYV+qbgCb0GgZJRvIgCD4+U/Kl1yhaRsaTwksF88xbPyGsgpw== + version "4.2.1" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-4.2.1.tgz#03f1dce28fc625c625bc6514350fbdb00fa9e624" + integrity sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA== dependencies: "@types/unist" "^2.0.0" is-buffer "^2.0.0" - replace-ext "1.0.0" unist-util-stringify-position "^2.0.0" vfile-message "^2.0.0" @@ -26230,10 +26331,10 @@ warning@^4.0.1, warning@^4.0.2, warning@^4.0.3: dependencies: loose-envify "^1.0.0" -watchpack-chokidar2@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz#9948a1866cbbd6cb824dea13a7ed691f6c8ddff0" - integrity sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA== +watchpack-chokidar2@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz#38500072ee6ece66f3769936950ea1771be1c957" + integrity sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww== dependencies: chokidar "^2.1.8" @@ -26247,15 +26348,15 @@ watchpack@^1.6.0: neo-async "^2.5.0" watchpack@^1.7.4: - version "1.7.4" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.4.tgz#6e9da53b3c80bb2d6508188f5b200410866cd30b" - integrity sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg== + version "1.7.5" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.5.tgz#1267e6c55e0b9b5be44c2023aed5437a2c26c453" + integrity sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ== dependencies: graceful-fs "^4.1.2" neo-async "^2.5.0" optionalDependencies: chokidar "^3.4.1" - watchpack-chokidar2 "^2.0.0" + watchpack-chokidar2 "^2.0.1" wbuf@^1.1.0, wbuf@^1.7.3: version "1.7.3" @@ -26336,7 +26437,18 @@ webpack-cli@3.3.10: v8-compile-cache "2.0.3" yargs "13.2.4" -webpack-dev-middleware@^3.7.0, webpack-dev-middleware@^3.7.2: +webpack-dev-middleware@^3.7.0: + version "3.7.3" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz#0639372b143262e2b84ab95d3b91a7597061c2c5" + integrity sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ== + dependencies: + memory-fs "^0.4.1" + mime "^2.4.4" + mkdirp "^0.5.1" + range-parser "^1.2.1" + webpack-log "^2.0.0" + +webpack-dev-middleware@^3.7.2: version "3.7.2" resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz#0019c3db716e3fa5cecbf64f2ab88a74bab331f3" integrity sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw== @@ -26471,9 +26583,9 @@ webpack@4.41.5: webpack-sources "^1.4.1" webpack@^4.44.2: - version "4.44.2" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.44.2.tgz#6bfe2b0af055c8b2d1e90ed2cd9363f841266b72" - integrity sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q== + version "4.46.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.46.0.tgz#bf9b4404ea20a073605e0a011d188d77cb6ad542" + integrity sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q== dependencies: "@webassemblyjs/ast" "1.9.0" "@webassemblyjs/helper-module-context" "1.9.0" @@ -26483,7 +26595,7 @@ webpack@^4.44.2: ajv "^6.10.2" ajv-keywords "^3.4.1" chrome-trace-event "^1.0.2" - enhanced-resolve "^4.3.0" + enhanced-resolve "^4.5.0" eslint-scope "^4.0.3" json-parse-better-errors "^1.0.2" loader-runner "^2.4.0" @@ -27070,6 +27182,11 @@ yn@3.1.1: resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + z-schema@~3.18.3: version "3.18.4" resolved "https://registry.yarnpkg.com/z-schema/-/z-schema-3.18.4.tgz#ea8132b279533ee60be2485a02f7e3e42541a9a2" From 3df6f583592f54f1d11342dbb86dc5f68ddcbe59 Mon Sep 17 00:00:00 2001 From: Diana Payton <52059945+oddlittlebird@users.noreply.github.com> Date: Tue, 26 Jan 2021 07:35:53 -0800 Subject: [PATCH 03/41] Docs: Update queries.md (#30616) --- docs/sources/panels/queries.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/sources/panels/queries.md b/docs/sources/panels/queries.md index 46696dc2a7b..8c688535131 100644 --- a/docs/sources/panels/queries.md +++ b/docs/sources/panels/queries.md @@ -21,7 +21,7 @@ Because of the difference between query languages, data sources may have query e **Prometheus (PromQL) query editor** -{{< docs-imagebox img="/img/docs/queries/prometheus-query-editor-7-2.png" class="docs-image--no-shadow" max-width="1000px" >}} +{{< docs-imagebox img="/img/docs/queries/prometheus-query-editor-7-4.png" class="docs-image--no-shadow" max-width="1000px" >}} ## Query syntax @@ -118,8 +118,7 @@ You can: | Icon | Description | |:--:|:---| -| {{< docs-imagebox img="/img/docs/queries/query-editor-help-7-4.png" class="docs-image--no-shadow" max-width="30px" max-height="30px" >}} | Toggle query editor help. If supported by the data source, this will toggle displaying information on how to use its query editor, or provide quick -access to commonly-used queries. | +| {{< docs-imagebox img="/img/docs/queries/query-editor-help-7-4.png" class="docs-image--no-shadow" max-width="30px" max-height="30px" >}} | Toggle query editor help. If supported by the data source, click this icon to display information on how to use the query editor or provide quick access to common queries. | | {{< docs-imagebox img="/img/docs/queries/duplicate-query-icon-7-0.png" class="docs-image--no-shadow" max-width="30px" max-height="30px" >}} | Copy a query. Duplicating queries is useful when working with multiple complex queries that are similar and you want to either experiment with different variants or do minor alterations. | | {{< docs-imagebox img="/img/docs/queries/hide-query-icon-7-0.png" class="docs-image--no-shadow" max-width="30px" max-height="30px" >}} | Hide a query. Grafana does not send hidden queries to the data source. | | {{< docs-imagebox img="/img/docs/queries/remove-query-icon-7-0.png" class="docs-image--no-shadow" max-width="30px" max-height="30px" >}} | Remove a query. Removing a query permanently deletes it, but sometimes you can recover deleted queries by reverting to previously saved versions of the panel. | From c1906db21fe840623c8201cc7a245068b00bf901 Mon Sep 17 00:00:00 2001 From: Diana Payton <52059945+oddlittlebird@users.noreply.github.com> Date: Tue, 26 Jan 2021 07:46:27 -0800 Subject: [PATCH 04/41] Update documentation-style-guide.md (#30611) * Update documentation-style-guide.md * Update contribute/style-guides/documentation-style-guide.md Co-authored-by: Ursula Kallio <73951760+osg-grafana@users.noreply.github.com> Co-authored-by: Ursula Kallio <73951760+osg-grafana@users.noreply.github.com> --- contribute/style-guides/documentation-style-guide.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/contribute/style-guides/documentation-style-guide.md b/contribute/style-guides/documentation-style-guide.md index f95971757f9..115856cef3c 100644 --- a/contribute/style-guides/documentation-style-guide.md +++ b/contribute/style-guides/documentation-style-guide.md @@ -147,6 +147,18 @@ The first letter of the name of an integration is always capitalized, even if th - Etcd Integration - I installed an integration on my local Grafana. +#### Kubernetes objects + +Capitalize Kubernetes objects such as Job, Pod, and StatefulSet when it is clear you are specifically talking about them and not generic jobs, pods, or whatever. + +Introduce the object as "Kubernetes XX" on the first usage, then just the object in subsequent uses. + +**Example:** + +Create the Kubernetes Job and check the logs to retrieve the generated token: + +The Job requires the token be submitted as … + ### Links and references When referencing another document, use "Refer to" rather than alternatives such as "See" or "Check out." From 12a7b342b91e4e8cb23b7cfbe3a62754716ed6aa Mon Sep 17 00:00:00 2001 From: Vardan Torosyan Date: Tue, 26 Jan 2021 17:19:57 +0100 Subject: [PATCH 05/41] Licensing Docs: Adding license restrictions docs (#30216) --- docs/sources/enterprise/activate-license.md | 2 +- docs/sources/enterprise/license-expiration.md | 2 +- .../enterprise/license-restrictions.md | 49 +++++++++++++++++++ 3 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 docs/sources/enterprise/license-restrictions.md diff --git a/docs/sources/enterprise/activate-license.md b/docs/sources/enterprise/activate-license.md index 69861b5d6d7..904cfc67529 100644 --- a/docs/sources/enterprise/activate-license.md +++ b/docs/sources/enterprise/activate-license.md @@ -2,7 +2,7 @@ title = "Activate an Enterprise license" description = "Activate an Enterprise license" keywords = ["grafana", "licensing", "enterprise"] -weight = 7 +weight = 100 +++ # Activate an Enterprise license diff --git a/docs/sources/enterprise/license-expiration.md b/docs/sources/enterprise/license-expiration.md index d2a242ff782..d2d8584dac4 100644 --- a/docs/sources/enterprise/license-expiration.md +++ b/docs/sources/enterprise/license-expiration.md @@ -2,7 +2,7 @@ title = "License Expiration" description = "" keywords = ["grafana", "licensing"] -weight = 8 +weight = 120 +++ # License expiration diff --git a/docs/sources/enterprise/license-restrictions.md b/docs/sources/enterprise/license-restrictions.md new file mode 100644 index 00000000000..aef95cf3b9e --- /dev/null +++ b/docs/sources/enterprise/license-restrictions.md @@ -0,0 +1,49 @@ ++++ +title = "License restrictions" +description = "Grafana Enterprise license restrictions" +keywords = ["grafana", "licensing", "enterprise"] +weight = 110 ++++ + +# License restrictions + +Enterprise licenses are limited by the number of active users, a license expiration date, and the URL of the Grafana instance. + +## User limits + +Grafana licenses allow for a certain number of active users per instance. An active user is any user that has signed in to Grafana within the past 30 days. + +In the context of licensing, each user is classified as either a viewer or an editor: + +- An editor is a user who has permission to edit and save a dashboard. Examples of editors are as follows: + - Grafana server administrators. + - Users who are assigned an organizational role of Editor or Admin. + - Users that have been granted Admin or Edit permissions at the dashboard or folder level. Refer to [Dashboard and folder permissions](https://grafana.com/docs/grafana/latest/permissions/dashboard_folder_permissions/). +- A viewer is a user with the Viewer role, which does not permit the user to save a dashboard. + +Restrictions are applied separately for viewers and editors. + +When the number of maximum active viewers or editors is reached, Grafana displays a warning banner. + +## Expiration date + +The license expiration date is the date when a license is no longer active. As the license expiration date approaches, Grafana Enterprise displays a banner. + +## License URL + +License URL is the root URL of your Grafana instance. The license will not work on an instance of Grafana with a different root URL. + +## Download a dashboard and folder permissions report + +This CSV report helps to identify users, teams, and roles that have been granted Admin or Edit permissions at the dashboard or folder level. + +To download the report: +1. Hover your cursor over the **Server Admin** (shield) icon in the side menu and then click **Licensing**. +2. At the bottom of the page, click **Download report**. + +## Update license restrictions + +To increase the number of licensed users within Grafana, extend a license, or change your licensed URL, contact [Grafana support](https://grafana.com/profile/org#support) or your Grafana Labs account team. They will update your license, which you can activate from within Grafana. + +For instructions on how to activate your license after it is updated, refer to +[Activate an Enterprise license]({{< relref "./activate-license.md" >}}) From f3e96ca212dfadb24e1e6e19d996c90c728a0dce Mon Sep 17 00:00:00 2001 From: Giordano Ricci Date: Tue, 26 Jan 2021 16:27:15 +0000 Subject: [PATCH 06/41] Docs: Update ES screenshots (#30598) * Docs: Update ES screenshots * Update file naming --- docs/sources/datasources/elasticsearch.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/sources/datasources/elasticsearch.md b/docs/sources/datasources/elasticsearch.md index b28af607d65..522e48af70f 100644 --- a/docs/sources/datasources/elasticsearch.md +++ b/docs/sources/datasources/elasticsearch.md @@ -49,7 +49,7 @@ http.cors.allow-origin: "*" ### Index settings -![Elasticsearch data source details](/img/docs/elasticsearch/elasticsearch_ds_details.png) +![Elasticsearch data source details](/img/docs/elasticsearch/elasticsearch-ds-details-7-4.png) Here you can specify a default for the `time field` and specify the name of your Elasticsearch index. You can use a time pattern for the index name or a wildcard. @@ -100,7 +100,7 @@ Each data link configuration consists of: ## Metric Query editor -![Elasticsearch Query Editor](/img/docs/elasticsearch/query_editor.png) +![Elasticsearch Query Editor](/img/docs/elasticsearch/query-editor-7-4.png) The Elasticsearch query editor allows you to select multiple metrics and group by multiple terms or filters. Use the plus and minus icons to the right to add/remove metrics or group by clauses. Some metrics and group by clauses haves options, click the option text to expand the row to view and edit metric or group by options. @@ -119,7 +119,7 @@ You can control the name for time series via the `Alias` input field. Some metric aggregations are called Pipeline aggregations, for example, *Moving Average* and *Derivative*. Elasticsearch pipeline metrics require another metric to be based on. Use the eye icon next to the metric to hide metrics from appearing in the graph. This is useful for metrics you only have in the query for use in a pipeline metric. -![](/img/docs/elasticsearch/pipeline_metrics_editor.png) +![Pipeline aggregation editor](/img/docs/elasticsearch/pipeline-aggregation-editor-7-4.png) ## Templating @@ -169,7 +169,7 @@ There are two syntaxes: Why two ways? The first syntax is easier to read and write but does not allow you to use a variable in the middle of a word. When the *Multi-value* or *Include all value* options are enabled, Grafana converts the labels from plain text to a lucene compatible condition. -![](/img/docs/v43/elastic_templating_query.png) +![Query with template variables](/img/docs/elasticsearch/elastic-templating-query-7-4.png) In the above example, we have a lucene query that filters documents based on the `@hostname` property using a variable named `$hostname`. It is also using a variable in the *Terms* group by field input box. This allows you to use a variable to quickly change how the data is grouped. From 94a29759ab165dcd9ec03e921a9df372dd81f0e4 Mon Sep 17 00:00:00 2001 From: Sofia Papagiannaki Date: Tue, 26 Jan 2021 18:49:58 +0200 Subject: [PATCH 07/41] Docs: Fix expressions enabled description (#30589) --- conf/defaults.ini | 2 +- conf/sample.ini | 2 +- docs/sources/administration/configuration.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/conf/defaults.ini b/conf/defaults.ini index a9bf50562e6..67388c213cf 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -895,5 +895,5 @@ use_browser_locale = false default_timezone = browser [expressions] -# Disable expressions & UI features +# Enable or disable the expressions functionality. enabled = true diff --git a/conf/sample.ini b/conf/sample.ini index 7fc783fee13..aa3d66df1ff 100644 --- a/conf/sample.ini +++ b/conf/sample.ini @@ -885,5 +885,5 @@ ;default_timezone = browser [expressions] -# Disable expressions & UI features +# Enable or disable the expressions functionality. ;enabled = true diff --git a/docs/sources/administration/configuration.md b/docs/sources/administration/configuration.md index 9f6f62d82a6..879501f0126 100644 --- a/docs/sources/administration/configuration.md +++ b/docs/sources/administration/configuration.md @@ -1515,6 +1515,6 @@ Set this to `true` to have date formats automatically derived from your browser Used as the default time zone for user preferences. Can be either `browser` for the browser local time zone or a time zone name from the IANA Time Zone database, such as `UTC` or `Europe/Amsterdam`. ## [expressions] ->Note: This is available in Grafana v7.4 and later versions. +> **Note:** This feature is available in Grafana v7.4 and later versions. ### enabled Set this to `false` to disable expressions and hide them in the Grafana UI. Default is `true`. From 19c639109c471ee3de86ce3b9a73be35963040f0 Mon Sep 17 00:00:00 2001 From: Arve Knudsen Date: Tue, 26 Jan 2021 17:55:55 +0100 Subject: [PATCH 08/41] Docs: Define TLS/SSL terminology (#30533) * Docs: Define TLS/SSL terminology Signed-off-by: Arve Knudsen * Apply suggestions from code review Co-authored-by: Ursula Kallio <73951760+osg-grafana@users.noreply.github.com> * Change title Signed-off-by: Arve Knudsen * Move terminology.md Signed-off-by: Arve Knudsen Co-authored-by: Ursula Kallio <73951760+osg-grafana@users.noreply.github.com> --- contribute/engineering/terminology.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 contribute/engineering/terminology.md diff --git a/contribute/engineering/terminology.md b/contribute/engineering/terminology.md new file mode 100644 index 00000000000..756a3c032dd --- /dev/null +++ b/contribute/engineering/terminology.md @@ -0,0 +1,17 @@ +# Grafana technical terminology + + + +This document defines technical terms used in Grafana. + +## TLS/SSL + +The acronyms [TLS](https://en.wikipedia.org/wiki/Transport_Layer_Security) (Transport Layer Security and +[SSL](https://en.wikipedia.org/wiki/SSL) (Secure Socket Layer) are both used to describe the HTTPS security layer, +and are in practice synonymous. However, TLS is considered the current name for the technology, and SSL is considered +[deprecated](https://tools.ietf.org/html/rfc7568). + +As such, while both terms are in use (also in our codebase) and are indeed interchangeable, TLS is the preferred term. +That said however, we have at Grafana Labs decided to use both acronyms in combination when referring to this type of +technology, i.e. _TLS/SSL_. This is in order to not confuse those who may not be aware of them being synonymous, +and SSL still being so prevalent in common discourse. From 66db73064205c0221e5e1a8f7fab48c61b6da07b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agn=C3=A8s=20Toulet?= <35176601+AgnesToulet@users.noreply.github.com> Date: Tue, 26 Jan 2021 17:57:04 +0100 Subject: [PATCH 09/41] Docs: add hidden_users configuration field (#30435) * Docs: add hidden_users configuration field * Add feature in the what's new * Update configuration.md * apply PR feedback Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * fix what's new link * Update docs/sources/whatsnew/whats-new-in-v7-4.md Co-authored-by: Leonard Gram Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> Co-authored-by: Leonard Gram --- docs/sources/administration/configuration.md | 4 ++++ docs/sources/whatsnew/whats-new-in-v7-4.md | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/docs/sources/administration/configuration.md b/docs/sources/administration/configuration.md index 879501f0126..e02c688d482 100644 --- a/docs/sources/administration/configuration.md +++ b/docs/sources/administration/configuration.md @@ -631,6 +631,10 @@ The duration in time a user invitation remains valid before expiring. This setting should be expressed as a duration. Examples: 6h (hours), 2d (days), 1w (week). Default is `24h` (24 hours). The minimum supported duration is `15m` (15 minutes). +### hidden_users + +This is a comma-separated list of usernames. Users specified here are hidden in the Grafana UI. They are still visible to Grafana administrators and to themselves. +
## [auth] diff --git a/docs/sources/whatsnew/whats-new-in-v7-4.md b/docs/sources/whatsnew/whats-new-in-v7-4.md index 086634211d8..b1b0c7d4553 100644 --- a/docs/sources/whatsnew/whats-new-in-v7-4.md +++ b/docs/sources/whatsnew/whats-new-in-v7-4.md @@ -105,6 +105,11 @@ You can lock down what can be done in the frontend code. Lock down what can be l [content_security_policy]({{< relref "../administration/configuration.md#content_security_policy" >}}) and [content_security_policy_template]({{< relref "../administration/configuration.md#content_security_policy_template" >}}) were added to [Configuration]({{< relref "../administration/configuration.md" >}}) as a result of this change. +### Hide users in UI + +You can now use the `hidden_users` configuration setting to hide specific users in the UI. For example, this feature can be used to hide users that are used for automation purposes. +[Configuration]({{< relref "../administration/configuration.md#hidden_users" >}}) has been updated for this feature. + ### Elasticsearch data source updates Grafana 7.4 includes the following enhancements From a1a8dbcffcfd9937463f0aad1e16df5479beddda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agn=C3=A8s=20Toulet?= <35176601+AgnesToulet@users.noreply.github.com> Date: Tue, 26 Jan 2021 17:57:35 +0100 Subject: [PATCH 10/41] Docs: Auditing updates (#30433) * Docs: reformat auditing table * Docs: update auditing log format section * fix SAML SLO link in auditing doc * Apply suggestions from code review Co-authored-by: Ursula Kallio <73951760+osg-grafana@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Ursula Kallio <73951760+osg-grafana@users.noreply.github.com> * update user field desc Co-authored-by: Ursula Kallio <73951760+osg-grafana@users.noreply.github.com> --- docs/sources/enterprise/auditing.md | 67 ++++++++++++++++------------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/docs/sources/enterprise/auditing.md b/docs/sources/enterprise/auditing.md index 23772f99702..71a3da15434 100644 --- a/docs/sources/enterprise/auditing.md +++ b/docs/sources/enterprise/auditing.md @@ -22,34 +22,43 @@ Audit logs are JSON objects representing user actions like: Audit logs contain the following fields. The fields followed by **\*** are always available, the others depends on the type of action logged. -| Field name | Type | Description | -| ----------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `timestamp`\* | string | The date and time the request was made, in coordinated universal time (UTC) using the [RFC3339](https://tools.ietf.org/html/rfc3339#section-5.6) format. | -| `user`\* | object | Information about the user that made the request. At least one of the `UserID` / `ApiKeyID` fields will not be empty if `isAnonymous=false`. | -| `user.userId` | number | ID of the Grafana user that made the request. | -| `user.orgId`\* | number | Current organization of the user that made the request. | -| `user.orgRole` | string | Current role of the user that made the request. | -| `user.name` | string | Name of the Grafana user that made the request. | -| `user.apiKeyId` | number | ID of the Grafana API key used to make the request. | -| `user.isAnonymous`\* | boolean | `true` if an anonymous user made the request, `false` otherwise. | -| `action`\* | string | The request action (eg. `create`, `update`, `manage-permissions`). | -| `request`\* | object | Information about the HTTP request. | -| `request.params` | object | Request path parameters. | -| `request.query` | object | Request query parameters. | -| `request.body` | string | Request body. | -| `result`\* | object | Information about the HTTP response. | -| `result.statusType`\* | string | `success` if the request action was successful, `failure` otherwise. | -| `result.statusCode` | number | HTTP status of the request. | -| `result.failureMessage` | string | HTTP error message. | -| `result.body` | string | Response body. | -| `resources` | array | Information about the resources that the request action impacted. Can be null for non-resource actions like `login` and `logout`. | -| `resources[x].id`\* | number | ID of the resource. | -| `resources[x].type`\* | string | Type of the resource (logged resources are: `alert`, `alert-notification`, `annotation`, `api-key`, `auth-token`, `dashboard`, `datasource`, `folder`, `org`, `panel`, `playlist`, `report`, `team`, `user`, `version`). | -| `requestUri`\* | string | Request URI. | -| `ipAddress`\* | string | IP address that the request was made from. | -| `userAgent`\* | string | Agent through which the request was made. | -| `grafanaVersion`\* | string | Grafana current version when this log is created. | -| `additionalData` | object | Provide additional information on the request. For now, it's only used in `login` actions to log external user information if an external system was used to log in. | +| Field name | Type | Description | +| ---------- | ---- | ----------- | +| `timestamp`\* | string | The date and time the request was made, in coordinated universal time (UTC) using the [RFC3339](https://tools.ietf.org/html/rfc3339#section-5.6) format. | +| `user`\* | object | Information about the user that made the request. Either one of the `UserID` or `ApiKeyID` fields will contain content if `isAnonymous=false`. | +| `user.userId` | number | ID of the Grafana user that made the request. | +| `user.orgId`\* | number | Current organization of the user that made the request. | +| `user.orgRole` | string | Current role of the user that made the request. | +| `user.name` | string | Name of the Grafana user that made the request. | +| `user.tokenId` | number | ID of the user authentication token. | +| `user.apiKeyId` | number | ID of the Grafana API key used to make the request. | +| `user.isAnonymous`\* | boolean | If an anonymous user made the request, `true`. Otherwise, `false`. | +| `action`\* | string | The request action. For example, `create`, `update`, or `manage-permissions`. | +| `request`\* | object | Information about the HTTP request. | +| `request.params` | object | Request’s path parameters. | +| `request.query` | object | Request’s query parameters. | +| `request.body` | string | Request’s body. | +| `result`\* | object | Information about the HTTP response. | +| `result.statusType` | string | If the request action was successful, `success`. Otherwise, `failure`. | +| `result.statusCode` | number | HTTP status of the request. | +| `result.failureMessage` | string | HTTP error message. | +| `result.body` | string | Response body. | +| `resources` | array | Information about the resources that the request action affected. This field can be null for non-resource actions such as `login` or `logout`. | +| `resources[x].id`\* | number | ID of the resource. | +| `resources[x].type`\* | string | The type of the resource that was logged: `alert`, `alert-notification`, `annotation`, `api-key`, `auth-token`, `dashboard`, `datasource`, `folder`, `org`, `panel`, `playlist`, `report`, `team`, `user`, or `version`. | +| `requestUri`\* | string | Request URI. | +| `ipAddress`\* | string | IP address that the request was made from. | +| `userAgent`\* | string | Agent through which the request was made. | +| `grafanaVersion`\* | string | Current version of Grafana when this log is created. | +| `additionalData` | object | Additional information that can be provided about the request. | + +The `additionalData` field can contain the following information: +| Field name | Action | Description | +| ---------- | ------ | ----------- | +| `loginUsername` | `login` | Login used in the Grafana authentication form. | +| `extUserInfo` | `login` | User information provided by the external system that was used to log in. | +| `authTokenCount` | `login` | Number of active authentication tokens for the user that logged in. | +| `terminationReason` | `logout` | The reason why the user logged out, such as a manual logout or a token expiring. | ### Recorded actions @@ -58,7 +67,7 @@ The audit logs include records about the following categories of actions: **Sessions** - Log in. -- Log out. +- Log out (manual log out, token expired/revoked, [SAML Single Logout]({{< relref "saml.md#single-logout" >}})). - Revoke a user authentication token. - Create or delete an API key. From f0a8d8d5092049debfc1273ed211e37d6ebe536a Mon Sep 17 00:00:00 2001 From: Diana Payton <52059945+oddlittlebird@users.noreply.github.com> Date: Tue, 26 Jan 2021 11:57:17 -0800 Subject: [PATCH 11/41] Docs: Update _index.md (#30655) --- docs/sources/_index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/sources/_index.md b/docs/sources/_index.md index 95a9803c8c8..6d21b1bd0b9 100755 --- a/docs/sources/_index.md +++ b/docs/sources/_index.md @@ -60,8 +60,8 @@ aliases = ["/docs/grafana/v1.1", "/docs/grafana/latest/guides/reference/admin",

Provisioning

Learn how to automate your Grafana configuration.

- }}" class="nav-cards__item nav-cards__item--guide"> -

What's new in v7.3

+
}}" class="nav-cards__item nav-cards__item--guide"> +

What's new in v7.4

Explore the features and enhancements in the latest release.

From b5d7f1e7d894e69674323d18e4bc523dff5b7247 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Wed, 27 Jan 2021 06:47:10 +0100 Subject: [PATCH 12/41] Variables: Fixes display value when using capture groups in regex (#30636) * Variables: Fixes display value for variables with regex * Chore: adds a test for getAllMatches --- .../features/variables/query/reducer.test.ts | 64 ++++++++++++++++++- .../app/features/variables/query/reducer.ts | 3 +- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/public/app/features/variables/query/reducer.test.ts b/public/app/features/variables/query/reducer.test.ts index c1452f0a130..73efcf43cf0 100644 --- a/public/app/features/variables/query/reducer.test.ts +++ b/public/app/features/variables/query/reducer.test.ts @@ -1,12 +1,18 @@ import { reducerTester } from '../../../../test/core/redux/reducerTester'; -import { queryVariableReducer, sortVariableValues, updateVariableOptions, updateVariableTags } from './reducer'; +import { + getAllMatches, + queryVariableReducer, + sortVariableValues, + updateVariableOptions, + updateVariableTags, +} from './reducer'; import { QueryVariableModel, VariableSort } from '../types'; import cloneDeep from 'lodash/cloneDeep'; import { VariablesState } from '../state/variablesReducer'; import { getVariableTestContext } from '../state/helpers'; import { toVariablePayload } from '../state/types'; import { createQueryVariableAdapter } from './adapter'; -import { MetricFindValue } from '@grafana/data'; +import { MetricFindValue, stringToJsRegex } from '@grafana/data'; describe('queryVariableReducer', () => { const adapter = createQueryVariableAdapter(); @@ -218,6 +224,25 @@ describe('queryVariableReducer', () => { }); }); + it('unnamed capture group returns any unnamed match', () => { + const regex = '/.*_(\\w+)\\{/gi'; + const { initialState } = getVariableTestContext(adapter, { includeAll: false, regex }); + const metrics = [createMetric('instance_counter{someother="atext",something="avalue"}'), createMetric('B')]; + const update = { results: metrics, templatedRegex: regex }; + const payload = toVariablePayload({ id: '0', type: 'query' }, update); + + reducerTester() + .givenReducer(queryVariableReducer, cloneDeep(initialState)) + .whenActionIsDispatched(updateVariableOptions(payload)) + .thenStateShouldEqual({ + ...initialState, + '0': ({ + ...initialState[0], + options: [{ text: 'counter', value: 'counter', selected: false }], + } as unknown) as QueryVariableModel, + }); + }); + it('unmatched text capture and unmatched value capture returns empty state', () => { const regex = '/somevalue="(?[^"]+)|somelabel="(?[^"]+)/gi'; const { initialState } = getVariableTestContext(adapter, { includeAll: false, regex }); @@ -282,6 +307,41 @@ describe('sortVariableValues', () => { }); }); +describe('getAllMatches', () => { + it.each` + str | regex | expected + ${'A{somelabel="atext",somevalue="avalue"}'} | ${'/unknown/gi'} | ${{}} + ${'A{somelabel="atext",somevalue="avalue"}'} | ${'/unknown/i'} | ${{}} + ${'A{somelabel="atext",somevalue="avalue"}'} | ${'/some(\\w+)/gi'} | ${{ 0: 'somevalue', 1: 'value', index: 20, input: 'A{somelabel="atext",somevalue="avalue"}' }} + ${'A{somelabel="atext",somevalue="avalue"}'} | ${'/some(\\w+)/i'} | ${{ 0: 'somelabel', 1: 'label', index: 2, input: 'A{somelabel="atext",somevalue="avalue"}' }} + ${'A{somelabel="atext",somevalue="avalue"}'} | ${'/somevalue="(?[^"]+)|somelabel="(?[^"]+)/gi'} | ${{ + 0: 'somevalue="avalue', + 1: 'avalue', + 2: 'atext', + groups: { + text: 'atext', + value: 'avalue', + }, + index: 20, + input: 'A{somelabel="atext",somevalue="avalue"}', +}} + ${'A{somelabel="atext",somevalue="avalue"}'} | ${'/somevalue="(?[^"]+)|somelabel="(?[^"]+)/i'} | ${{ + 0: 'somelabel="atext', + 1: undefined, + 2: 'atext', + groups: { + text: 'atext', + }, + index: 2, + input: 'A{somelabel="atext",somevalue="avalue"}', +}} + `('when called with str:{$str}, regex:{$regex} then it should return correct matches', ({ str, regex, expected }) => { + const result = getAllMatches(str, stringToJsRegex(regex)); + + expect(result).toEqual(expected); + }); +}); + function createMetric(value: string) { return { text: value, diff --git a/public/app/features/variables/query/reducer.ts b/public/app/features/variables/query/reducer.ts index 8c8160ce1b2..4513e7e6d78 100644 --- a/public/app/features/variables/query/reducer.ts +++ b/public/app/features/variables/query/reducer.ts @@ -88,7 +88,7 @@ export const sortVariableValues = (options: any[], sortOrder: VariableSort) => { return options; }; -const getAllMatches = (str: string, regex: RegExp): any => { +export const getAllMatches = (str: string, regex: RegExp): any => { const results = {}; let matches; @@ -139,6 +139,7 @@ const metricNamesToVariableValues = (variableRegEx: string, sort: VariableSort, text = matches.groups.text; value = text; } else if (matches['1']) { + text = matches['1']; value = matches['1']; } } From 6668eaea2d900b9df106ea2bc9ccfdabd50d16e4 Mon Sep 17 00:00:00 2001 From: "Grot (@grafanabot)" <43478413+grafanabot@users.noreply.github.com> Date: Wed, 27 Jan 2021 07:18:06 -0600 Subject: [PATCH 13/41] ReleaseNotes: Updated changelog and release notes for 7.4.0-beta1 (#30666) * ReleaseNotes: Updated changelog and release notes for 7.4.0-beta1 * Apply suggestions from code review Co-authored-by: Ursula Kallio <73951760+osg-grafana@users.noreply.github.com> Co-authored-by: Giordano Ricci Co-authored-by: Ursula Kallio <73951760+osg-grafana@users.noreply.github.com> --- CHANGELOG.md | 7 ++++--- docs/sources/release-notes/release-notes-7-4-0-beta1.md | 8 ++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80a2d7950ef..c3f7563a2d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,12 +5,11 @@ ### Features and enhancements -* ** MSSQL**: Integrated security. [#30369](https://github.com/grafana/grafana/pull/30369), [@daniellee](https://github.com/daniellee) * **API**: Add ID to snapshot API responses. [#29600](https://github.com/grafana/grafana/pull/29600), [@AgnesToulet](https://github.com/AgnesToulet) * **AlertListPanel**: Add options to sort by Time(asc) and Time(desc). [#29764](https://github.com/grafana/grafana/pull/29764), [@dboslee](https://github.com/dboslee) * **AlertListPanel**: Changed alert url to to go the panel view instead of panel edit. [#29060](https://github.com/grafana/grafana/pull/29060), [@zakiharis](https://github.com/zakiharis) * **Alerting**: Add support for Sensu Go notification channel. [#28012](https://github.com/grafana/grafana/pull/28012), [@nixwiz](https://github.com/nixwiz) -* **Alerting**: Evaluate data templating in alert rule name and message. [#29908](https://github.com/grafana/grafana/pull/29908), [@wbrowne](https://github.com/wbrowne) +* **Alerting**: Add support for alert notification query label interpolation. [#29908](https://github.com/grafana/grafana/pull/29908), [@wbrowne](https://github.com/wbrowne) * **Annotations**: Remove annotation_tag entries as part of annotations cleanup. [#29534](https://github.com/grafana/grafana/pull/29534), [@dafydd-t](https://github.com/dafydd-t) * **Azure Monitor**: Add Microsoft.Network/natGateways. [#29479](https://github.com/grafana/grafana/pull/29479), [@JoeyLemur](https://github.com/JoeyLemur) * **Backend plugins**: Support Forward OAuth Identity for backend data source plugins. [#27055](https://github.com/grafana/grafana/pull/27055), [@billoley](https://github.com/billoley) @@ -40,9 +39,11 @@ * **Loki**: Add query type and line limit to query editor in dashboard. [#29356](https://github.com/grafana/grafana/pull/29356), [@ivanahuckova](https://github.com/ivanahuckova) * **Loki**: Add query type selector to query editor in Explore. [#28817](https://github.com/grafana/grafana/pull/28817), [@ivanahuckova](https://github.com/ivanahuckova) * **Loki**: Retry web socket connection when connection is closed abnormally. [#29438](https://github.com/grafana/grafana/pull/29438), [@ivanahuckova](https://github.com/ivanahuckova) +* **MS SQL**: Integrated security. [#30369](https://github.com/grafana/grafana/pull/30369), [@daniellee](https://github.com/daniellee) * **Middleware**: Add CSP support. [#29740](https://github.com/grafana/grafana/pull/29740), [@aknuds1](https://github.com/aknuds1) * **OAuth**: Configurable user name attribute. [#28286](https://github.com/grafana/grafana/pull/28286), [@alexanderzobnin](https://github.com/alexanderzobnin) * **PanelEditor**: Render panel field config categories as separate option group sections. [#30301](https://github.com/grafana/grafana/pull/30301), [@dprokop](https://github.com/dprokop) +* **Postgres**: SSL certification. [#30352](https://github.com/grafana/grafana/pull/30352), [@ying-jeanne](https://github.com/ying-jeanne) * **Prometheus**: Add support for Exemplars. [#28057](https://github.com/grafana/grafana/pull/28057), [@zoltanbedi](https://github.com/zoltanbedi) * **Prometheus**: Improve autocomplete performance and remove disabling of dynamic label lookup. [#30199](https://github.com/grafana/grafana/pull/30199), [@ivanahuckova](https://github.com/ivanahuckova) * **Prometheus**: Update default query type option to "Both" in Explore query editor. [#28935](https://github.com/grafana/grafana/pull/28935), [@ivanahuckova](https://github.com/ivanahuckova) @@ -55,6 +56,7 @@ * **Templating**: Custom variable edit UI, change options input into textarea. [#28322](https://github.com/grafana/grafana/pull/28322), [@darrylsepeda](https://github.com/darrylsepeda) * **TimeSeriesPanel**: The new graph panel now supports y-axis value mapping. [#30272](https://github.com/grafana/grafana/pull/30272), [@torkelo](https://github.com/torkelo) * **Tracing**: Tag spans with user login and datasource name instead of id. [#29183](https://github.com/grafana/grafana/pull/29183), [@bergquist](https://github.com/bergquist) +* **Transformations**: Add "Rename By Regex" transformer. [#29281](https://github.com/grafana/grafana/pull/29281), [@simianhacker](https://github.com/simianhacker) * **Transformations**: Added new transform for excluding and including rows based on their values. [#26884](https://github.com/grafana/grafana/pull/26884), [@Totalus](https://github.com/Totalus) * **Transforms**: Add sort by transformer. [#30370](https://github.com/grafana/grafana/pull/30370), [@ryantxu](https://github.com/ryantxu) * **Variables**: Add deprecation warning for value group tags. [#30160](https://github.com/grafana/grafana/pull/30160), [@torkelo](https://github.com/torkelo) @@ -63,7 +65,6 @@ * **Variables**: Adds variables inspection. [#25214](https://github.com/grafana/grafana/pull/25214), [@hugohaggmark](https://github.com/hugohaggmark) * **Variables**: New Variables are stored immediately. [#29178](https://github.com/grafana/grafana/pull/29178), [@hugohaggmark](https://github.com/hugohaggmark) * **Zipkin**: Remove browser access mode. [#30360](https://github.com/grafana/grafana/pull/30360), [@zoltanbedi](https://github.com/zoltanbedi) -* **postgres SSL certification**. [#30352](https://github.com/grafana/grafana/pull/30352), [@ying-jeanne](https://github.com/ying-jeanne) ### Bug fixes diff --git a/docs/sources/release-notes/release-notes-7-4-0-beta1.md b/docs/sources/release-notes/release-notes-7-4-0-beta1.md index d311dc47e9d..5285954149a 100644 --- a/docs/sources/release-notes/release-notes-7-4-0-beta1.md +++ b/docs/sources/release-notes/release-notes-7-4-0-beta1.md @@ -10,12 +10,11 @@ list = false ### Features and enhancements -* ** MSSQL**: Integrated security. [#30369](https://github.com/grafana/grafana/pull/30369), [@daniellee](https://github.com/daniellee) * **API**: Add ID to snapshot API responses. [#29600](https://github.com/grafana/grafana/pull/29600), [@AgnesToulet](https://github.com/AgnesToulet) * **AlertListPanel**: Add options to sort by Time(asc) and Time(desc). [#29764](https://github.com/grafana/grafana/pull/29764), [@dboslee](https://github.com/dboslee) * **AlertListPanel**: Changed alert url to to go the panel view instead of panel edit. [#29060](https://github.com/grafana/grafana/pull/29060), [@zakiharis](https://github.com/zakiharis) * **Alerting**: Add support for Sensu Go notification channel. [#28012](https://github.com/grafana/grafana/pull/28012), [@nixwiz](https://github.com/nixwiz) -* **Alerting**: Evaluate data templating in alert rule name and message. [#29908](https://github.com/grafana/grafana/pull/29908), [@wbrowne](https://github.com/wbrowne) +* **Alerting**: Add support for alert notification query label interpolation. [#29908](https://github.com/grafana/grafana/pull/29908), [@wbrowne](https://github.com/wbrowne) * **Annotations**: Remove annotation_tag entries as part of annotations cleanup. [#29534](https://github.com/grafana/grafana/pull/29534), [@dafydd-t](https://github.com/dafydd-t) * **Azure Monitor**: Add Microsoft.Network/natGateways. [#29479](https://github.com/grafana/grafana/pull/29479), [@JoeyLemur](https://github.com/JoeyLemur) * **Backend plugins**: Support Forward OAuth Identity for backend data source plugins. [#27055](https://github.com/grafana/grafana/pull/27055), [@billoley](https://github.com/billoley) @@ -45,9 +44,11 @@ list = false * **Loki**: Add query type and line limit to query editor in dashboard. [#29356](https://github.com/grafana/grafana/pull/29356), [@ivanahuckova](https://github.com/ivanahuckova) * **Loki**: Add query type selector to query editor in Explore. [#28817](https://github.com/grafana/grafana/pull/28817), [@ivanahuckova](https://github.com/ivanahuckova) * **Loki**: Retry web socket connection when connection is closed abnormally. [#29438](https://github.com/grafana/grafana/pull/29438), [@ivanahuckova](https://github.com/ivanahuckova) +* **MS SQL**: Integrated security. [#30369](https://github.com/grafana/grafana/pull/30369), [@daniellee](https://github.com/daniellee) * **Middleware**: Add CSP support. [#29740](https://github.com/grafana/grafana/pull/29740), [@aknuds1](https://github.com/aknuds1) * **OAuth**: Configurable user name attribute. [#28286](https://github.com/grafana/grafana/pull/28286), [@alexanderzobnin](https://github.com/alexanderzobnin) * **PanelEditor**: Render panel field config categories as separate option group sections. [#30301](https://github.com/grafana/grafana/pull/30301), [@dprokop](https://github.com/dprokop) +* **Postgres**: SSL certification. [#30352](https://github.com/grafana/grafana/pull/30352), [@ying-jeanne](https://github.com/ying-jeanne) * **Prometheus**: Add support for Exemplars. [#28057](https://github.com/grafana/grafana/pull/28057), [@zoltanbedi](https://github.com/zoltanbedi) * **Prometheus**: Improve autocomplete performance and remove disabling of dynamic label lookup. [#30199](https://github.com/grafana/grafana/pull/30199), [@ivanahuckova](https://github.com/ivanahuckova) * **Prometheus**: Update default query type option to "Both" in Explore query editor. [#28935](https://github.com/grafana/grafana/pull/28935), [@ivanahuckova](https://github.com/ivanahuckova) @@ -60,6 +61,7 @@ list = false * **Templating**: Custom variable edit UI, change options input into textarea. [#28322](https://github.com/grafana/grafana/pull/28322), [@darrylsepeda](https://github.com/darrylsepeda) * **TimeSeriesPanel**: The new graph panel now supports y-axis value mapping. [#30272](https://github.com/grafana/grafana/pull/30272), [@torkelo](https://github.com/torkelo) * **Tracing**: Tag spans with user login and datasource name instead of id. [#29183](https://github.com/grafana/grafana/pull/29183), [@bergquist](https://github.com/bergquist) +* **Transformations**: Add "Rename By Regex" transformer. [#29281](https://github.com/grafana/grafana/pull/29281), [@simianhacker](https://github.com/simianhacker) * **Transformations**: Added new transform for excluding and including rows based on their values. [#26884](https://github.com/grafana/grafana/pull/26884), [@Totalus](https://github.com/Totalus) * **Transforms**: Add sort by transformer. [#30370](https://github.com/grafana/grafana/pull/30370), [@ryantxu](https://github.com/ryantxu) * **Variables**: Add deprecation warning for value group tags. [#30160](https://github.com/grafana/grafana/pull/30160), [@torkelo](https://github.com/torkelo) @@ -68,7 +70,6 @@ list = false * **Variables**: Adds variables inspection. [#25214](https://github.com/grafana/grafana/pull/25214), [@hugohaggmark](https://github.com/hugohaggmark) * **Variables**: New Variables are stored immediately. [#29178](https://github.com/grafana/grafana/pull/29178), [@hugohaggmark](https://github.com/hugohaggmark) * **Zipkin**: Remove browser access mode. [#30360](https://github.com/grafana/grafana/pull/30360), [@zoltanbedi](https://github.com/zoltanbedi) -* **postgres SSL certification**. [#30352](https://github.com/grafana/grafana/pull/30352), [@ying-jeanne](https://github.com/ying-jeanne) ### Bug fixes @@ -144,4 +145,3 @@ This option to group query variable values into groups by tags has been an exper * **Card**: Add new Card component. [#28216](https://github.com/grafana/grafana/pull/28216), [@Clarity-89](https://github.com/Clarity-89) * **FieldConfig**: Implementation slider editor (#27592). [#28007](https://github.com/grafana/grafana/pull/28007), [@isaozlerfm](https://github.com/isaozlerfm) * **MutableDataFrame**: Remove unique field name constraint and values field index and unused/seldom used stuff. [#27573](https://github.com/grafana/grafana/pull/27573), [@torkelo](https://github.com/torkelo) - From bdf00d3a595d75e45ade96b6e832880b55bc2710 Mon Sep 17 00:00:00 2001 From: Will Browne Date: Wed, 27 Jan 2021 14:27:01 +0100 Subject: [PATCH 14/41] Docs: Refer to product docs in whats new for alerting templating feature (#30652) * Docs: Refer to product docs in whats new for alerting templating feature * move link below image * remove whitespace --- docs/sources/whatsnew/whats-new-in-v7-4.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/sources/whatsnew/whats-new-in-v7-4.md b/docs/sources/whatsnew/whats-new-in-v7-4.md index b1b0c7d4553..2972795796d 100644 --- a/docs/sources/whatsnew/whats-new-in-v7-4.md +++ b/docs/sources/whatsnew/whats-new-in-v7-4.md @@ -95,6 +95,8 @@ You can now provide detailed information to alert notification recipients by inj {{< figure src="/img/docs/alerting/alert-notification-template-7-4.png" max-width="700px" caption="Variable support in alert notifications" >}} +For more information, refer to the [alert notification docs]({{< relref "../alerting/notifications.md#notification-templating" >}}). + ### Content security policy support We have added support for [Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP), a layer of security that helps detect and mitigate certain types of attacks, including Cross Site Scripting (XSS) and data injection attacks. From 1c158744e8c6061280964886989d06316b8a622e Mon Sep 17 00:00:00 2001 From: Sofia Papagiannaki Date: Wed, 27 Jan 2021 15:51:00 +0200 Subject: [PATCH 15/41] AlertingNG: pause/unpause definitions via the API (#30627) * AlertingNG: pause/unpause definitions via the API * Apply suggestions from code review Co-authored-by: Will Browne * Enable pausing/unpausing multiple definitions Co-authored-by: Will Browne --- pkg/services/ngalert/api.go | 28 +++++++++++++++++++++ pkg/services/ngalert/database.go | 35 ++++++++++++++++++++++++++- pkg/services/ngalert/database_mig.go | 4 +++ pkg/services/ngalert/models.go | 9 +++++++ pkg/services/ngalert/schedule.go | 4 +++ pkg/services/ngalert/schedule_test.go | 27 +++++++++++++++++++++ 6 files changed, 106 insertions(+), 1 deletion(-) diff --git a/pkg/services/ngalert/api.go b/pkg/services/ngalert/api.go index 49968f1346f..28143cd3679 100644 --- a/pkg/services/ngalert/api.go +++ b/pkg/services/ngalert/api.go @@ -1,6 +1,8 @@ package ngalert import ( + "fmt" + "github.com/go-macaron/binding" "github.com/grafana/grafana-plugin-sdk-go/data" "github.com/grafana/grafana/pkg/api/response" @@ -21,6 +23,8 @@ func (ng *AlertNG) registerAPIEndpoints() { alertDefinitions.Delete("/:alertDefinitionUID", ng.validateOrgAlertDefinition, routing.Wrap(ng.deleteAlertDefinitionEndpoint)) alertDefinitions.Post("/", middleware.ReqSignedIn, binding.Bind(saveAlertDefinitionCommand{}), routing.Wrap(ng.createAlertDefinitionEndpoint)) alertDefinitions.Put("/:alertDefinitionUID", ng.validateOrgAlertDefinition, binding.Bind(updateAlertDefinitionCommand{}), routing.Wrap(ng.updateAlertDefinitionEndpoint)) + alertDefinitions.Post("/pause", ng.validateOrgAlertDefinition, binding.Bind(updateAlertDefinitionPausedCommand{}), routing.Wrap(ng.alertDefinitionPauseEndpoint)) + alertDefinitions.Post("/unpause", ng.validateOrgAlertDefinition, binding.Bind(updateAlertDefinitionPausedCommand{}), routing.Wrap(ng.alertDefinitionUnpauseEndpoint)) }) ng.RouteRegister.Group("/api/ngalert/", func(schedulerRouter routing.RouteRegister) { @@ -180,3 +184,27 @@ func (ng *AlertNG) unpauseScheduler() response.Response { } return response.JSON(200, util.DynMap{"message": "alert definition scheduler unpaused"}) } + +// alertDefinitionPauseEndpoint handles POST /api/alert-definitions/pause. +func (ng *AlertNG) alertDefinitionPauseEndpoint(c *models.ReqContext, cmd updateAlertDefinitionPausedCommand) response.Response { + cmd.OrgID = c.SignedInUser.OrgId + cmd.Paused = true + + err := ng.updateAlertDefinitionPaused(&cmd) + if err != nil { + return response.Error(500, "Failed to pause alert definition", err) + } + return response.JSON(200, util.DynMap{"message": fmt.Sprintf("%d alert definitions paused", cmd.ResultCount)}) +} + +// alertDefinitionUnpauseEndpoint handles POST /api/alert-definitions/unpause. +func (ng *AlertNG) alertDefinitionUnpauseEndpoint(c *models.ReqContext, cmd updateAlertDefinitionPausedCommand) response.Response { + cmd.OrgID = c.SignedInUser.OrgId + cmd.Paused = false + + err := ng.updateAlertDefinitionPaused(&cmd) + if err != nil { + return response.Error(500, "Failed to unpause alert definition", err) + } + return response.JSON(200, util.DynMap{"message": fmt.Sprintf("%d alert definitions unpaused", cmd.ResultCount)}) +} diff --git a/pkg/services/ngalert/database.go b/pkg/services/ngalert/database.go index 4cc55c8b17b..aededd4c552 100644 --- a/pkg/services/ngalert/database.go +++ b/pkg/services/ngalert/database.go @@ -212,7 +212,7 @@ func (ng *AlertNG) getOrgAlertDefinitions(query *listAlertDefinitionsQuery) erro func (ng *AlertNG) getAlertDefinitions(query *listAlertDefinitionsQuery) error { return ng.SQLStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error { alerts := make([]*AlertDefinition, 0) - q := "SELECT uid, org_id, interval_seconds, version FROM alert_definition" + q := "SELECT uid, org_id, interval_seconds, version, paused FROM alert_definition" if err := sess.SQL(q).Find(&alerts); err != nil { return err } @@ -221,6 +221,39 @@ func (ng *AlertNG) getAlertDefinitions(query *listAlertDefinitionsQuery) error { return nil }) } + +func (ng *AlertNG) updateAlertDefinitionPaused(cmd *updateAlertDefinitionPausedCommand) error { + return ng.SQLStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error { + placeHolders := strings.Builder{} + const separator = ", " + separatorVar := separator + params := []interface{}{cmd.Paused, cmd.OrgID} + for i, UID := range cmd.UIDs { + if i == len(cmd.UIDs)-1 { + separatorVar = "" + } + placeHolders.WriteString(fmt.Sprintf("?%s", separatorVar)) + params = append(params, UID) + } + sql := fmt.Sprintf("UPDATE alert_definition SET paused = ? WHERE org_id = ? AND uid IN (%s)", placeHolders.String()) + + // prepend sql statement to params + var i interface{} + params = append(params, i) + copy(params[1:], params[0:]) + params[0] = sql + + res, err := sess.Exec(params...) + if err != nil { + return err + } + if cmd.ResultCount, err = res.RowsAffected(); err != nil { + ng.log.Debug("failed to get rows affected: %w", err) + } + return nil + }) +} + func generateNewAlertDefinitionUID(sess *sqlstore.DBSession, orgID int64) (string, error) { for i := 0; i < 3; i++ { uid := util.GenerateShortUID() diff --git a/pkg/services/ngalert/database_mig.go b/pkg/services/ngalert/database_mig.go index 38478afc3aa..ec130328244 100644 --- a/pkg/services/ngalert/database_mig.go +++ b/pkg/services/ngalert/database_mig.go @@ -46,6 +46,10 @@ func addAlertDefinitionMigrations(mg *migrator.Migrator) { } mg.AddMigration("add unique index in alert_definition on org_id and title columns", migrator.NewAddIndexMigration(alertDefinition, uniqueIndices[0])) mg.AddMigration("add unique index in alert_definition on org_id and uid columns", migrator.NewAddIndexMigration(alertDefinition, uniqueIndices[1])) + + mg.AddMigration("Add column paused in alert_definition", migrator.NewAddColumnMigration(alertDefinition, &migrator.Column{ + Name: "paused", Type: migrator.DB_Bool, Nullable: false, Default: "0", + })) } func addAlertDefinitionVersionMigrations(mg *migrator.Migrator) { diff --git a/pkg/services/ngalert/models.go b/pkg/services/ngalert/models.go index f3f5556a460..416c00b60da 100644 --- a/pkg/services/ngalert/models.go +++ b/pkg/services/ngalert/models.go @@ -21,6 +21,7 @@ type AlertDefinition struct { IntervalSeconds int64 `json:"intervalSeconds"` Version int64 `json:"version"` UID string `xorm:"uid" json:"uid"` + Paused bool `json:"paused"` } type alertDefinitionKey struct { @@ -101,3 +102,11 @@ type listAlertDefinitionsQuery struct { Result []*AlertDefinition } + +type updateAlertDefinitionPausedCommand struct { + OrgID int64 `json:"-"` + UIDs []string `json:"uids"` + Paused bool `json:"-"` + + ResultCount int64 +} diff --git a/pkg/services/ngalert/schedule.go b/pkg/services/ngalert/schedule.go index effb8e4e7d1..3a74d40e2a6 100644 --- a/pkg/services/ngalert/schedule.go +++ b/pkg/services/ngalert/schedule.go @@ -185,6 +185,10 @@ func (ng *AlertNG) alertingTicker(grafanaCtx context.Context) error { } readyToRun := make([]readyToRunItem, 0) for _, item := range alertDefinitions { + if item.Paused { + continue + } + key := item.getKey() itemVersion := item.Version newRoutine := !ng.schedule.registry.exists(key) diff --git a/pkg/services/ngalert/schedule_test.go b/pkg/services/ngalert/schedule_test.go index e86db6000fe..ca44cbe1ef0 100644 --- a/pkg/services/ngalert/schedule_test.go +++ b/pkg/services/ngalert/schedule_test.go @@ -123,6 +123,33 @@ func TestAlertingTicker(t *testing.T) { tick := advanceClock(t, mockedClock) assertEvalRun(t, evalAppliedCh, tick, expectedAlertDefinitionsEvaluated...) }) + + // pause alert definition + err = ng.updateAlertDefinitionPaused(&updateAlertDefinitionPausedCommand{UIDs: []string{alerts[2].UID}, OrgID: alerts[2].OrgID, Paused: true}) + require.NoError(t, err) + t.Logf("alert definition: %v paused", alerts[2].getKey()) + + expectedAlertDefinitionsEvaluated = []alertDefinitionKey{} + t.Run(fmt.Sprintf("on 8th tick alert definitions: %s should be evaluated", concatenate(expectedAlertDefinitionsEvaluated)), func(t *testing.T) { + tick := advanceClock(t, mockedClock) + assertEvalRun(t, evalAppliedCh, tick, expectedAlertDefinitionsEvaluated...) + }) + + expectedAlertDefinitionsStopped = []alertDefinitionKey{alerts[2].getKey()} + t.Run(fmt.Sprintf("on 8th tick alert definitions: %s should be stopped", concatenate(expectedAlertDefinitionsStopped)), func(t *testing.T) { + assertStopRun(t, stopAppliedCh, expectedAlertDefinitionsStopped...) + }) + + // unpause alert definition + err = ng.updateAlertDefinitionPaused(&updateAlertDefinitionPausedCommand{UIDs: []string{alerts[2].UID}, OrgID: alerts[2].OrgID, Paused: false}) + require.NoError(t, err) + t.Logf("alert definition: %v unpaused", alerts[2].getKey()) + + expectedAlertDefinitionsEvaluated = []alertDefinitionKey{alerts[0].getKey(), alerts[2].getKey()} + t.Run(fmt.Sprintf("on 9th tick alert definitions: %s should be evaluated", concatenate(expectedAlertDefinitionsEvaluated)), func(t *testing.T) { + tick := advanceClock(t, mockedClock) + assertEvalRun(t, evalAppliedCh, tick, expectedAlertDefinitionsEvaluated...) + }) } func assertEvalRun(t *testing.T, ch <-chan evalAppliedInfo, tick time.Time, keys ...alertDefinitionKey) { From 701ad79bb5618e08e38529734be7df7cef546f09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 27 Jan 2021 15:02:04 +0100 Subject: [PATCH 16/41] PageToolbar: Extracting navbar styles & layout into a modern emotion based component (#30588) * Explore: Replaces navbar-button and overriden explore button css classes with ToolbarButton and cleans up scss & markup, removes ResponsiveButton * Change live button text when paused * For the dashboard toolbar button I need a transparent button so I refactored the states/variants into a new ToolbarButtonVariatn * PageToolbar wip * Progress * Prgress * Minor progress * Fixed back button and responsive titles * Fixed tv mode * Updated * support tv modes and playlist * more progress * Fixing lots of view states and responsive features * Minor fixes * review fixes * Fixes to e2e tests * Review fixes --- e2e/shared/smokeTestScenario.ts | 2 +- e2e/suite1/specs/dashboard-time-zone.spec.ts | 2 +- e2e/suite1/specs/select-focus.spec.ts | 2 +- ...emplating-dashboard-links-and-variables.ts | 2 +- .../specs/variables/set-options-from-ui.ts | 6 +- .../specs/variables/textbox-variables.ts | 6 +- .../src/selectors/components.ts | 8 +- .../src/selectors/pages.ts | 4 - .../grafana-e2e/src/flows/addDashboard.ts | 4 +- .../grafana-e2e/src/flows/configurePanel.ts | 2 +- .../grafana-e2e/src/flows/deleteDashboard.ts | 2 +- .../grafana-e2e/src/flows/saveDashboard.ts | 2 +- .../src/flows/setDashboardTimeRange.ts | 2 +- .../components/Button/ToolbarButton.story.tsx | 24 ++- .../src/components/Button/ToolbarButton.tsx | 39 ++-- .../src/components/Dropdown/ButtonSelect.tsx | 1 - .../grafana-ui/src/components/Icon/Icon.tsx | 2 +- .../src/components/Icon/assets/PanelAdd.tsx | 6 +- .../grafana-ui/src/components/Menu/Menu.tsx | 3 +- .../PageLayout/PageToolbar.story.tsx | 53 +++++ .../src/components/PageLayout/PageToolbar.tsx | 202 ++++++++++++++++++ .../RefreshPicker/RefreshPicker.tsx | 1 - .../components/TimePicker/TimeRangePicker.tsx | 4 +- packages/grafana-ui/src/components/index.ts | 1 + packages/grafana-ui/src/themes/mixins.ts | 4 + .../dashboard/components/DashNav/DashNav.tsx | 183 ++++++---------- .../components/DashNav/DashNavButton.tsx | 16 +- .../app/features/explore/LiveTailButton.tsx | 109 +++------- .../explore/ReturnToDashboardButton.tsx | 1 - public/sass/_old_responsive.scss | 44 ---- public/sass/components/_navbar.scss | 73 ------- public/sass/components/_panel_editor.scss | 4 - public/sass/components/_sidemenu.scss | 7 +- public/sass/components/_view_states.scss | 53 ++--- 34 files changed, 464 insertions(+), 410 deletions(-) create mode 100644 packages/grafana-ui/src/components/PageLayout/PageToolbar.story.tsx create mode 100644 packages/grafana-ui/src/components/PageLayout/PageToolbar.tsx diff --git a/e2e/shared/smokeTestScenario.ts b/e2e/shared/smokeTestScenario.ts index 00e3ecb9cf2..5b7171c6880 100644 --- a/e2e/shared/smokeTestScenario.ts +++ b/e2e/shared/smokeTestScenario.ts @@ -8,7 +8,7 @@ export const smokeTestScenario = { skipScenario: false, scenario: () => { e2e.flows.openDashboard(); - e2e.pages.Dashboard.Toolbar.toolbarItems('Add panel').click(); + e2e.components.PageToolbar.item('Add panel').click(); e2e.pages.AddDashboard.addNewPanel().click(); e2e.components.DataSource.TestData.QueryTab.scenarioSelectContainer() diff --git a/e2e/suite1/specs/dashboard-time-zone.spec.ts b/e2e/suite1/specs/dashboard-time-zone.spec.ts index 0bb93b1ad08..7b4f99464a9 100644 --- a/e2e/suite1/specs/dashboard-time-zone.spec.ts +++ b/e2e/suite1/specs/dashboard-time-zone.spec.ts @@ -38,7 +38,7 @@ e2e.scenario({ ); } - e2e.pages.Dashboard.Toolbar.toolbarItems('Dashboard settings').click(); + e2e.components.PageToolbar.item('Dashboard settings').click(); e2e.components.TimeZonePicker.container() .should('be.visible') diff --git a/e2e/suite1/specs/select-focus.spec.ts b/e2e/suite1/specs/select-focus.spec.ts index 8c0cae407fb..77d7b6a1c0e 100644 --- a/e2e/suite1/specs/select-focus.spec.ts +++ b/e2e/suite1/specs/select-focus.spec.ts @@ -8,7 +8,7 @@ e2e.scenario({ skipScenario: false, scenario: () => { e2e.flows.openDashboard({ uid: '5SdHCadmz' }); - e2e.pages.Dashboard.Toolbar.toolbarItems('Dashboard settings').click(); + e2e.components.PageToolbar.item('Dashboard settings').click(); e2e.components.FolderPicker.container() .should('be.visible') diff --git a/e2e/suite1/specs/templating-dashboard-links-and-variables.ts b/e2e/suite1/specs/templating-dashboard-links-and-variables.ts index b1fa3b42883..926f63f98ae 100644 --- a/e2e/suite1/specs/templating-dashboard-links-and-variables.ts +++ b/e2e/suite1/specs/templating-dashboard-links-and-variables.ts @@ -50,7 +50,7 @@ e2e.scenario({ e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('p2').should('be.visible').click(); - e2e.pages.Dashboard.Toolbar.navBar().click(); + e2e.components.PageToolbar.container().click(); e2e.components.DashboardLinks.dropDown().should('be.visible').click().wait('@tagsTemplatingSearch'); diff --git a/e2e/suite1/specs/variables/set-options-from-ui.ts b/e2e/suite1/specs/variables/set-options-from-ui.ts index 77275ff9894..3f0e6b0aaef 100644 --- a/e2e/suite1/specs/variables/set-options-from-ui.ts +++ b/e2e/suite1/specs/variables/set-options-from-ui.ts @@ -20,7 +20,7 @@ describe('Variables - Set options from ui', () => { e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('A').should('be.visible').click(); e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('B').should('be.visible').click(); - e2e.pages.Dashboard.Toolbar.navBar().click(); + e2e.components.PageToolbar.container().click(); e2e().wait('@query'); @@ -77,7 +77,7 @@ describe('Variables - Set options from ui', () => { e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('A').should('be.visible').click(); e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('B').should('be.visible').click(); - e2e.pages.Dashboard.Toolbar.navBar().click(); + e2e.components.PageToolbar.container().click(); e2e().wait('@query'); e2e().wait(500); @@ -132,7 +132,7 @@ describe('Variables - Set options from ui', () => { e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('A + B').should('be.visible').click(); e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('A').should('be.visible').click(); - e2e.pages.Dashboard.Toolbar.navBar().click(); + e2e.components.PageToolbar.container().click(); e2e().wait('@query'); e2e().wait(500); diff --git a/e2e/suite1/specs/variables/textbox-variables.ts b/e2e/suite1/specs/variables/textbox-variables.ts index 7e353947783..f9ced2945df 100644 --- a/e2e/suite1/specs/variables/textbox-variables.ts +++ b/e2e/suite1/specs/variables/textbox-variables.ts @@ -185,7 +185,7 @@ function copyExistingDashboard() { } function saveDashboard(saveVariables: boolean) { - e2e.pages.Dashboard.Toolbar.toolbarItems('Save dashboard').should('be.visible').click(); + e2e.components.PageToolbar.item('Save dashboard').should('be.visible').click(); if (saveVariables) { e2e.pages.SaveDashboardModal.saveVariables().should('exist').click({ force: true }); @@ -212,7 +212,7 @@ function validateTextboxAndMarkup(value: string) { } function validateVariable(value: string) { - e2e.pages.Dashboard.Toolbar.toolbarItems('Dashboard settings').should('be.visible').click(); + e2e.components.PageToolbar.item('Dashboard settings').should('be.visible').click(); e2e.pages.Dashboard.Settings.General.sectionItems('Variables').should('be.visible').click(); @@ -245,7 +245,7 @@ function changeTextBoxInput() { } function changeQueryInput() { - e2e.pages.Dashboard.Toolbar.toolbarItems('Dashboard settings').should('be.visible').click(); + e2e.components.PageToolbar.item('Dashboard settings').should('be.visible').click(); e2e.pages.Dashboard.Settings.General.sectionItems('Variables').should('be.visible').click(); diff --git a/packages/grafana-e2e-selectors/src/selectors/components.ts b/packages/grafana-e2e-selectors/src/selectors/components.ts index a25d1164a4f..29e80da67ce 100644 --- a/packages/grafana-e2e-selectors/src/selectors/components.ts +++ b/packages/grafana-e2e-selectors/src/selectors/components.ts @@ -56,8 +56,8 @@ export const Components = { }, OptionsPane: { content: 'Panel editor option pane content', - close: 'Dashboard navigation bar button Close options pane', - open: 'Dashboard navigation bar button Open options pane', + close: 'Page toolbar button Close options pane', + open: 'Page toolbar button Open options pane', select: 'Panel editor option pane select', tab: (title: string) => `Panel editor option pane tab ${title}`, }, @@ -123,6 +123,10 @@ export const Components = { calculationsLabel: 'Transform calculations label', }, }, + PageToolbar: { + container: () => '.page-toolbar', + item: (tooltip: string) => `Page toolbar button ${tooltip}`, + }, QueryEditorToolbarItem: { button: (title: string) => `QueryEditor toolbar item button ${title}`, }, diff --git a/packages/grafana-e2e-selectors/src/selectors/pages.ts b/packages/grafana-e2e-selectors/src/selectors/pages.ts index 88cbb7edc2a..204b56a191b 100644 --- a/packages/grafana-e2e-selectors/src/selectors/pages.ts +++ b/packages/grafana-e2e-selectors/src/selectors/pages.ts @@ -34,10 +34,6 @@ export const Pages = { }, Dashboard: { url: (uid: string) => `/d/${uid}`, - Toolbar: { - toolbarItems: (button: string) => `Dashboard navigation bar button ${button}`, - navBar: () => '.navbar', - }, SubMenu: { submenuItem: 'Dashboard template variables submenu item', submenuItemLabels: (item: string) => `Dashboard template variables submenu Label ${item}`, diff --git a/packages/grafana-e2e/src/flows/addDashboard.ts b/packages/grafana-e2e/src/flows/addDashboard.ts index 7a74218ecab..a94a679db2d 100644 --- a/packages/grafana-e2e/src/flows/addDashboard.ts +++ b/packages/grafana-e2e/src/flows/addDashboard.ts @@ -59,7 +59,7 @@ export const addDashboard = (config?: Partial) => { e2e.pages.AddDashboard.visit(); if (annotations.length > 0 || variables.length > 0) { - e2e.pages.Dashboard.Toolbar.toolbarItems('Dashboard settings').click(); + e2e.components.PageToolbar.item('Dashboard settings').click(); addAnnotations(annotations); fullConfig.variables = addVariables(variables); @@ -69,7 +69,7 @@ export const addDashboard = (config?: Partial) => { setDashboardTimeRange(timeRange); - e2e.pages.Dashboard.Toolbar.toolbarItems('Save dashboard').click(); + e2e.components.PageToolbar.item('Save dashboard').click(); e2e.pages.SaveDashboardAsModal.newName().clear().type(title); e2e.pages.SaveDashboardAsModal.save().click(); e2e.flows.assertSuccessNotification(); diff --git a/packages/grafana-e2e/src/flows/configurePanel.ts b/packages/grafana-e2e/src/flows/configurePanel.ts index fb65ecb157d..0c4673c36ad 100644 --- a/packages/grafana-e2e/src/flows/configurePanel.ts +++ b/packages/grafana-e2e/src/flows/configurePanel.ts @@ -99,7 +99,7 @@ export const configurePanel = (config: PartialAddPanelConfig | PartialEditPanelC e2e.components.Panels.Panel.title(panelTitle).click(); e2e.components.Panels.Panel.headerItems('Edit').click(); } else { - e2e.pages.Dashboard.Toolbar.toolbarItems('Add panel').click(); + e2e.components.PageToolbar.item('Add panel').click(); e2e.pages.AddDashboard.addNewPanel().click(); } } diff --git a/packages/grafana-e2e/src/flows/deleteDashboard.ts b/packages/grafana-e2e/src/flows/deleteDashboard.ts index a5a34f5d030..9bb90a6412e 100644 --- a/packages/grafana-e2e/src/flows/deleteDashboard.ts +++ b/packages/grafana-e2e/src/flows/deleteDashboard.ts @@ -33,7 +33,7 @@ const quickDelete = (uid: string) => { const uiDelete = (uid: string, title: string) => { e2e.pages.Dashboard.visit(uid); - e2e.pages.Dashboard.Toolbar.toolbarItems('Dashboard settings').click(); + e2e.components.PageToolbar.item('Dashboard settings').click(); e2e.pages.Dashboard.Settings.General.deleteDashBoard().click(); e2e.pages.ConfirmModal.delete().click(); e2e.flows.assertSuccessNotification(); diff --git a/packages/grafana-e2e/src/flows/saveDashboard.ts b/packages/grafana-e2e/src/flows/saveDashboard.ts index 94541fbd858..37d5238f431 100644 --- a/packages/grafana-e2e/src/flows/saveDashboard.ts +++ b/packages/grafana-e2e/src/flows/saveDashboard.ts @@ -1,7 +1,7 @@ import { e2e } from '../index'; export const saveDashboard = () => { - e2e.pages.Dashboard.Toolbar.toolbarItems('Save dashboard').click(); + e2e.components.PageToolbar.item('Save dashboard').click(); e2e.pages.SaveDashboardModal.save().click(); diff --git a/packages/grafana-e2e/src/flows/setDashboardTimeRange.ts b/packages/grafana-e2e/src/flows/setDashboardTimeRange.ts index c061fcdc4fd..9b04412fd0c 100644 --- a/packages/grafana-e2e/src/flows/setDashboardTimeRange.ts +++ b/packages/grafana-e2e/src/flows/setDashboardTimeRange.ts @@ -4,4 +4,4 @@ import { setTimeRange, TimeRangeConfig } from './setTimeRange'; export { TimeRangeConfig }; export const setDashboardTimeRange = (config: TimeRangeConfig) => - e2e.pages.Dashboard.Toolbar.navBar().within(() => setTimeRange(config)); + e2e.components.PageToolbar.container().within(() => setTimeRange(config)); diff --git a/packages/grafana-ui/src/components/Button/ToolbarButton.story.tsx b/packages/grafana-ui/src/components/Button/ToolbarButton.story.tsx index 6f1dbfa0a99..d20f90cde72 100644 --- a/packages/grafana-ui/src/components/Button/ToolbarButton.story.tsx +++ b/packages/grafana-ui/src/components/Button/ToolbarButton.story.tsx @@ -1,8 +1,9 @@ import React from 'react'; -import { ToolbarButton, ButtonGroup, useTheme, VerticalGroup, HorizontalGroup } from '@grafana/ui'; +import { ToolbarButton, ButtonGroup, VerticalGroup, HorizontalGroup } from '@grafana/ui'; import { withCenteredStory } from '../../utils/storybook/withCenteredStory'; import { ToolbarButtonRow } from './ToolbarButtonRow'; import { ToolbarButtonVariant } from './ToolbarButton'; +import { DashboardStoryCanvas } from '../../utils/storybook/DashboardStoryCanvas'; export default { title: 'Buttons/ToolbarButton', @@ -12,11 +13,10 @@ export default { }; export const List = () => { - const theme = useTheme(); const variants: ToolbarButtonVariant[] = ['default', 'active', 'primary', 'destructive']; return ( -
+ Button states @@ -47,6 +47,22 @@ export const List = () => { ))}
+ disabled + + + Disabled + + +
+ Variants + + {variants.map((variant) => ( + + {variant} + + ))} + +
Wrapped in noSpacing ButtonGroup @@ -76,6 +92,6 @@ export const List = () => {
-
+ ); }; diff --git a/packages/grafana-ui/src/components/Button/ToolbarButton.tsx b/packages/grafana-ui/src/components/Button/ToolbarButton.tsx index 6b7506a8974..f7db756cbfe 100644 --- a/packages/grafana-ui/src/components/Button/ToolbarButton.tsx +++ b/packages/grafana-ui/src/components/Button/ToolbarButton.tsx @@ -7,6 +7,7 @@ import { Tooltip } from '../Tooltip/Tooltip'; import { Icon } from '../Icon/Icon'; import { getPropertiesForVariant } from './Button'; import { isString } from 'lodash'; +import { selectors } from '@grafana/e2e-selectors'; export interface Props extends ButtonHTMLAttributes { /** Icon name */ @@ -31,7 +32,20 @@ export type ToolbarButtonVariant = 'default' | 'primary' | 'destructive' | 'acti export const ToolbarButton = forwardRef( ( - { tooltip, icon, className, children, imgSrc, fullWidth, isOpen, narrow, variant = 'default', iconOnly, ...rest }, + { + tooltip, + icon, + className, + children, + imgSrc, + fullWidth, + isOpen, + narrow, + variant = 'default', + iconOnly, + 'aria-label': ariaLabel, + ...rest + }, ref ) => { const styles = useStyles(getStyles); @@ -54,10 +68,10 @@ export const ToolbarButton = forwardRef( }); const body = ( - @@ -73,6 +87,10 @@ export const ToolbarButton = forwardRef( } ); +function getButttonAriaLabel(ariaLabel: string | undefined, tooltip: string | undefined) { + return ariaLabel ? ariaLabel : tooltip ? selectors.components.PageToolbar.item(tooltip) : undefined; +} + function renderIcon(icon: IconName | React.ReactNode) { if (!icon) { return null; @@ -100,16 +118,13 @@ const getStyles = (theme: GrafanaTheme) => { line-height: ${theme.height.md - 2}px; font-weight: ${theme.typography.weight.semibold}; border: 1px solid ${theme.colors.border2}; - &:focus { outline: none; } - &[disabled], &:disabled { cursor: not-allowed; opacity: 0.5; - &:hover { color: ${theme.colors.textWeak}; background: ${theme.colors.bg1}; @@ -119,7 +134,6 @@ const getStyles = (theme: GrafanaTheme) => { default: css` color: ${theme.colors.textWeak}; background-color: ${theme.colors.bg1}; - &:hover { color: ${theme.colors.text}; background: ${styleMixins.hoverColor(theme.colors.bg1, theme)}; @@ -129,7 +143,6 @@ const getStyles = (theme: GrafanaTheme) => { color: ${theme.palette.orangeDark}; border-color: ${theme.palette.orangeDark}; background-color: transparent; - &:hover { color: ${theme.colors.text}; background: ${styleMixins.hoverColor(theme.colors.bg1, theme)}; @@ -156,14 +169,14 @@ const getStyles = (theme: GrafanaTheme) => { `, content: css` flex-grow: 1; - display: none; - - @media only screen and (min-width: ${theme.breakpoints.md}) { - display: block; - } `, contentWithIcon: css` + display: none; padding-left: ${theme.spacing.sm}; + + @media ${styleMixins.mediaUp(theme.breakpoints.md)} { + display: block; + } `, contentWithRightIcon: css` padding-right: ${theme.spacing.xs}; diff --git a/packages/grafana-ui/src/components/Dropdown/ButtonSelect.tsx b/packages/grafana-ui/src/components/Dropdown/ButtonSelect.tsx index 785648345b6..eb65c4bd7ca 100644 --- a/packages/grafana-ui/src/components/Dropdown/ButtonSelect.tsx +++ b/packages/grafana-ui/src/components/Dropdown/ButtonSelect.tsx @@ -11,7 +11,6 @@ export interface Props extends HTMLAttributes { className?: string; options: Array>; value?: SelectableValue; - maxMenuHeight?: number; onChange: (item: SelectableValue) => void; tooltipContent?: PopoverContent; narrow?: boolean; diff --git a/packages/grafana-ui/src/components/Icon/Icon.tsx b/packages/grafana-ui/src/components/Icon/Icon.tsx index c531dcb90a4..f7c60eacdc1 100644 --- a/packages/grafana-ui/src/components/Icon/Icon.tsx +++ b/packages/grafana-ui/src/components/Icon/Icon.tsx @@ -10,7 +10,7 @@ import * as MonoIcon from './assets'; import { customIcons } from './custom'; import { SvgProps } from './assets/types'; -const alwaysMonoIcons = ['grafana', 'favorite', 'heart-break', 'heart']; +const alwaysMonoIcons = ['grafana', 'favorite', 'heart-break', 'heart', 'panel-add']; export interface IconProps extends React.HTMLAttributes { name: IconName; diff --git a/packages/grafana-ui/src/components/Icon/assets/PanelAdd.tsx b/packages/grafana-ui/src/components/Icon/assets/PanelAdd.tsx index d56ea7971da..72dbc8332a0 100644 --- a/packages/grafana-ui/src/components/Icon/assets/PanelAdd.tsx +++ b/packages/grafana-ui/src/components/Icon/assets/PanelAdd.tsx @@ -1,15 +1,15 @@ import React, { FunctionComponent } from 'react'; import { SvgProps } from './types'; -export const PanelAdd: FunctionComponent = ({ size, ...rest }) => { +export const PanelAdd: FunctionComponent = ({ ...rest }) => { return ( diff --git a/packages/grafana-ui/src/components/Menu/Menu.tsx b/packages/grafana-ui/src/components/Menu/Menu.tsx index 29d3444bff3..cc3b5d0a695 100644 --- a/packages/grafana-ui/src/components/Menu/Menu.tsx +++ b/packages/grafana-ui/src/components/Menu/Menu.tsx @@ -179,6 +179,8 @@ const getMenuStyles = (theme: GrafanaTheme) => { color: ${linkColor}; display: flex; cursor: pointer; + padding: 5px 12px 5px 10px; + &:hover { color: ${linkColorHover}; text-decoration: none; @@ -186,7 +188,6 @@ const getMenuStyles = (theme: GrafanaTheme) => { `, item: css` background: none; - padding: 5px 12px 5px 10px; border-left: 2px solid transparent; cursor: pointer; white-space: nowrap; diff --git a/packages/grafana-ui/src/components/PageLayout/PageToolbar.story.tsx b/packages/grafana-ui/src/components/PageLayout/PageToolbar.story.tsx new file mode 100644 index 00000000000..d2d927ababf --- /dev/null +++ b/packages/grafana-ui/src/components/PageLayout/PageToolbar.story.tsx @@ -0,0 +1,53 @@ +import React from 'react'; +import { ToolbarButton, VerticalGroup } from '@grafana/ui'; +import { withCenteredStory } from '../../utils/storybook/withCenteredStory'; +import { PageToolbar } from './PageToolbar'; +import { StoryExample } from '../../utils/storybook/StoryExample'; +import { action } from '@storybook/addon-actions'; +import { IconButton } from '../IconButton/IconButton'; + +export default { + title: 'Layout/PageToolbar', + component: PageToolbar, + decorators: [withCenteredStory], + parameters: {}, +}; + +export const Examples = () => { + return ( + + + + + Sync + + + + action('Title clicked')} + onClickParent={() => action('Parent clicked')} + leftItems={[ + , + , + ]} + > + + + Sync + Settings + + + + action('Go back')}> + + + Discard + Apply + + + + ); +}; diff --git a/packages/grafana-ui/src/components/PageLayout/PageToolbar.tsx b/packages/grafana-ui/src/components/PageLayout/PageToolbar.tsx new file mode 100644 index 00000000000..893d9e0e913 --- /dev/null +++ b/packages/grafana-ui/src/components/PageLayout/PageToolbar.tsx @@ -0,0 +1,202 @@ +import React, { FC, ReactNode } from 'react'; +import { css, cx } from 'emotion'; +import { GrafanaTheme } from '@grafana/data'; +import { useStyles } from '../../themes/ThemeContext'; +import { IconName } from '../../types'; +import { Icon } from '../Icon/Icon'; +import { styleMixins } from '../../themes'; +import { IconButton } from '../IconButton/IconButton'; +import { selectors } from '@grafana/e2e-selectors'; + +export interface Props { + pageIcon?: IconName; + title: string; + parent?: string; + onGoBack?: () => void; + onClickTitle?: () => void; + onClickParent?: () => void; + leftItems?: ReactNode[]; + children?: ReactNode; + className?: string; + isFullscreen?: boolean; +} + +/** @alpha */ +export const PageToolbar: FC = React.memo( + ({ + title, + parent, + pageIcon, + onGoBack, + children, + onClickTitle, + onClickParent, + leftItems, + isFullscreen, + className, + }) => { + const styles = useStyles(getStyles); + + /** + * .page-toolbar css class is used for some legacy css view modes (TV/Kiosk) and + * media queries for mobile view when toolbar needs left padding to make room + * for mobile menu icon. This logic hopefylly can be changed when we move to a full react + * app and change how the app side menu & mobile menu is rendered. + */ + const mainStyle = cx( + 'page-toolbar', + styles.toolbar, + { + ['page-toolbar--fullscreen']: isFullscreen, + }, + className + ); + + return ( +
+
+ {pageIcon && !onGoBack && ( +
+ +
+ )} + {onGoBack && ( +
+ +
+ )} +
+ {parent && onClickParent && ( + + )} + {onClickTitle && ( + + )} + {!onClickTitle &&
{title}
} +
+ {leftItems?.map((child, index) => ( +
+ {child} +
+ ))} +
+
+ {React.Children.toArray(children) + .filter(Boolean) + .map((child, index) => { + return ( +
+ {child} +
+ ); + })} +
+ ); + } +); + +PageToolbar.displayName = 'PageToolbar'; + +const getStyles = (theme: GrafanaTheme) => { + const { spacing, typography } = theme; + + const titleStyles = ` + font-size: ${typography.size.lg}; + padding-left: ${spacing.sm}; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + max-width: 240px; + + // clear default button styles + background: none; + border: none; + + @media ${styleMixins.mediaUp(theme.breakpoints.xl)} { + max-width: unset; + } + `; + + return { + toolbar: css` + display: flex; + background: ${theme.colors.dashboardBg}; + justify-content: flex-end; + flex-wrap: wrap; + padding: 0 ${spacing.md} ${spacing.sm} ${spacing.md}; + `, + toolbarLeft: css` + display: flex; + flex-grow: 1; + min-width: 0; + `, + spacer: css` + flex-grow: 1; + `, + pageIcon: css` + padding-top: ${spacing.sm}; + align-items: center; + display: none; + + @media ${styleMixins.mediaUp(theme.breakpoints.md)} { + display: flex; + } + `, + titleWrapper: css` + display: flex; + align-items: center; + padding-top: ${spacing.sm}; + padding-right: ${spacing.sm}; + min-width: 0; + overflow: hidden; + `, + goBackButton: css` + position: relative; + top: 8px; + `, + parentIcon: css` + margin-left: 4px; + `, + titleText: css` + ${titleStyles}; + `, + titleLink: css` + ${titleStyles}; + `, + parentLink: css` + display: none; + + @media ${styleMixins.mediaUp(theme.breakpoints.md)} { + display: inline-block; + } + `, + actionWrapper: css` + padding-left: ${spacing.sm}; + padding-top: ${spacing.sm}; + `, + leftActionItem: css` + display: none; + height: 40px; + position: relative; + top: 5px; + align-items: center; + padding-left: ${spacing.xs}; + + @media ${styleMixins.mediaUp(theme.breakpoints.md)} { + display: flex; + } + `, + }; +}; diff --git a/packages/grafana-ui/src/components/RefreshPicker/RefreshPicker.tsx b/packages/grafana-ui/src/components/RefreshPicker/RefreshPicker.tsx index af0dbc8fefe..ed18fe8842f 100644 --- a/packages/grafana-ui/src/components/RefreshPicker/RefreshPicker.tsx +++ b/packages/grafana-ui/src/components/RefreshPicker/RefreshPicker.tsx @@ -83,7 +83,6 @@ export class RefreshPicker extends PureComponent { value={selectedValue} options={options} onChange={this.onChangeSelect as any} - maxMenuHeight={380} variant={variant} /> )} diff --git a/packages/grafana-ui/src/components/TimePicker/TimeRangePicker.tsx b/packages/grafana-ui/src/components/TimePicker/TimeRangePicker.tsx index 457075c7efd..14a92c80f25 100644 --- a/packages/grafana-ui/src/components/TimePicker/TimeRangePicker.tsx +++ b/packages/grafana-ui/src/components/TimePicker/TimeRangePicker.tsx @@ -186,7 +186,9 @@ const getStyles = stylesFactory((theme: GrafanaTheme) => { const getLabelStyles = stylesFactory((theme: GrafanaTheme) => { return { container: css` - display: inline-block; + display: flex; + align-items: center; + white-space: nowrap; `, utc: css` color: ${theme.palette.orange}; diff --git a/packages/grafana-ui/src/components/index.ts b/packages/grafana-ui/src/components/index.ts index e6062c01aef..49bb8f21ee4 100644 --- a/packages/grafana-ui/src/components/index.ts +++ b/packages/grafana-ui/src/components/index.ts @@ -45,6 +45,7 @@ export { ModalHeader } from './Modal/ModalHeader'; export { ModalTabsHeader } from './Modal/ModalTabsHeader'; export { ModalTabContent } from './Modal/ModalTabContent'; export { ModalsProvider, ModalRoot, ModalsController } from './Modal/ModalsContext'; +export { PageToolbar } from './PageLayout/PageToolbar'; // Renderless export { SetInterval } from './SetInterval/SetInterval'; diff --git a/packages/grafana-ui/src/themes/mixins.ts b/packages/grafana-ui/src/themes/mixins.ts index 49c3d0142e9..f09be644839 100644 --- a/packages/grafana-ui/src/themes/mixins.ts +++ b/packages/grafana-ui/src/themes/mixins.ts @@ -34,6 +34,10 @@ export function listItemSelected(theme: GrafanaTheme): string { `; } +export function mediaUp(breakpoint: string) { + return `only screen and (min-width: ${breakpoint})`; +} + export const focusCss = (theme: GrafanaTheme) => ` outline: 2px dotted transparent; outline-offset: 2px; diff --git a/public/app/features/dashboard/components/DashNav/DashNav.tsx b/public/app/features/dashboard/components/DashNav/DashNav.tsx index 4023fad0ea0..1b583aab1de 100644 --- a/public/app/features/dashboard/components/DashNav/DashNav.tsx +++ b/public/app/features/dashboard/components/DashNav/DashNav.tsx @@ -1,16 +1,14 @@ // Libaries import React, { PureComponent, FC, ReactNode } from 'react'; import { connect, MapDispatchToProps } from 'react-redux'; -import { css } from 'emotion'; // Utils & Services import { appEvents } from 'app/core/app_events'; import { PlaylistSrv } from 'app/features/playlist/playlist_srv'; // Components import { DashNavButton } from './DashNavButton'; import { DashNavTimeControls } from './DashNavTimeControls'; -import { Icon, ModalsController } from '@grafana/ui'; +import { ButtonGroup, ModalsController, ToolbarButton, PageToolbar } from '@grafana/ui'; import { textUtil } from '@grafana/data'; -import { BackButton } from 'app/core/components/BackButton/BackButton'; // State import { updateLocation } from 'app/core/actions'; import { updateTimeZoneForSession } from 'app/features/profile/state/reducers'; @@ -126,11 +124,23 @@ class DashNav extends PureComponent { }); } + isInKioskMode() { + return !!this.props.location.query.kiosk; + } + + isPlaylistRunning() { + return this.playlistSrv.isPlaying; + } + renderLeftActionsButton() { const { dashboard } = this.props; const { canStar, canShare, isStarred } = dashboard.meta; - const buttons: ReactNode[] = []; + + if (this.isInKioskMode() || this.isPlaylistRunning()) { + return []; + } + if (canStar) { buttons.push( { return buttons; } - renderDashboardTitleSearchButton() { - const { dashboard, isFullscreen } = this.props; - - const folderSymbol = css` - margin-right: 0 4px; - `; - const mainIconClassName = css` - margin-right: 8px; - margin-bottom: 3px; - `; - - const folderTitle = dashboard.meta.folderTitle; - const haveFolder = (dashboard.meta.folderId ?? 0) > 0; - + renderPlaylistControls() { return ( - <> -
-
- {!isFullscreen && } - {haveFolder && ( - <> - - {folderTitle} / - - - )} - {dashboard.title} -
-
-
{this.renderLeftActionsButton()}
-
- - ); - } - - renderBackButton() { - return ( -
- -
+ + + Stop playlist + + ); } renderRightActionsButton() { - const { dashboard, onAddPanel } = this.props; + const { dashboard, onAddPanel, location, updateTimeZoneForSession, isFullscreen } = this.props; const { canEdit, showSettings } = dashboard.meta; const { snapshot } = dashboard; const snapshotUrl = snapshot && snapshot.originalUrl; - const buttons: ReactNode[] = []; - if (canEdit) { - buttons.push( - - ); + const tvButton = ( + + ); + const timeControls = ( + + ); + + if (this.isPlaylistRunning()) { + return [this.renderPlaylistControls(), timeControls]; + } + + if (this.isInKioskMode()) { + return [timeControls, tvButton]; + } + + if (canEdit && !isFullscreen) { + buttons.push(); buttons.push( {({ showModal, hideModal }) => ( - { showModal(SaveDashboardModalProxy, { @@ -255,10 +240,9 @@ class DashNav extends PureComponent { if (snapshotUrl) { buttons.push( - this.gotoSnapshotOrigin(snapshotUrl)} icon="link" key="button-snapshot" /> @@ -267,67 +251,40 @@ class DashNav extends PureComponent { if (showSettings) { buttons.push( - + ); } this.addCustomContent(customRightActions, buttons); + + if (!dashboard.timepicker.hidden) { + buttons.push(timeControls); + } + + buttons.push(tvButton); return buttons; } + gotoSnapshotOrigin(snapshotUrl: string) { + window.location.href = textUtil.sanitizeUrl(snapshotUrl); + } + render() { - const { dashboard, location, isFullscreen, updateTimeZoneForSession } = this.props; + const { dashboard, isFullscreen } = this.props; + const onGoBack = isFullscreen ? this.onClose : undefined; return ( -
- {isFullscreen && this.renderBackButton()} - {this.renderDashboardTitleSearchButton()} - - {this.playlistSrv.isPlaying && ( -
- - - -
- )} - -
{this.renderRightActionsButton()}
- -
- -
- - {!dashboard.timepicker.hidden && ( -
- -
- )} -
+ + {this.renderRightActionsButton()} + ); } } diff --git a/public/app/features/dashboard/components/DashNav/DashNavButton.tsx b/public/app/features/dashboard/components/DashNav/DashNavButton.tsx index 9eca8d3a64f..ae2908c3733 100644 --- a/public/app/features/dashboard/components/DashNav/DashNavButton.tsx +++ b/public/app/features/dashboard/components/DashNav/DashNavButton.tsx @@ -18,13 +18,6 @@ interface Props { noBorder?: boolean; } -const getStyles = stylesFactory((theme: GrafanaTheme) => ({ - noBorderContainer: css` - padding: 0 ${theme.spacing.xs}; - display: flex; - `, -})); - export const DashNavButton: FunctionComponent = ({ icon, iconType, @@ -62,7 +55,7 @@ export const DashNavButton: FunctionComponent = ({ , - , - , +
, ]; } @@ -308,11 +310,9 @@ export class PanelEditorUnconnected extends PureComponent { return (
- } - actions={this.renderEditorActions()} - /> + + {this.renderEditorActions()} +
Date: Wed, 27 Jan 2021 17:47:24 +0100 Subject: [PATCH 20/41] CustomScrollbar: migrated styles from sass to emotion (#30506) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * CustomScrollbar: migrated styles from sass to emotion * fixes frontend test * updated changes * fixed page props and applied changes to all occurences * moved the getStyles function to the bottom of the file * made some changes * fixed snapshot test * Revert "Merge branch 'refactor-customscrollbar-30354' of https://github.com/grafana/grafana into refactor-customscrollbar-30354" This reverts commit c45ee30b6b297991a1628e9b21c4121dc78e376c, reversing changes made to d2645534e39c4ffda30a948f4a892c1c68ec38ca. * improved props name * made use of theme variables for style consistency * fixed snapshot test and updated some theme changes * removed hover effects from customScrollbar style * made some changes * updated some changes * added label to class names * changed to a functional component and improved styling * fixes snapshot test * fixes small nit * minor tweaks Co-authored-by: Torkel Ödegaard --- .../CustomScrollbar/CustomScrollbar.test.tsx | 2 +- .../CustomScrollbar/CustomScrollbar.tsx | 252 ++++++++++-------- .../CustomScrollbar/_CustomScrollbar.scss | 57 ---- .../CustomScrollbar.test.tsx.snap | 4 +- .../src/components/Drawer/Drawer.tsx | 2 +- .../src/components/VizLayout/VizLayout.tsx | 2 +- packages/grafana-ui/src/components/index.scss | 1 - public/app/core/components/Page/Page.tsx | 2 +- .../dashboard/containers/DashboardPage.tsx | 1 - .../__snapshots__/DashboardPage.test.tsx.snap | 12 - public/app/features/explore/Wrapper.tsx | 2 +- .../features/query/components/QueryGroup.tsx | 8 +- 12 files changed, 150 insertions(+), 195 deletions(-) delete mode 100644 packages/grafana-ui/src/components/CustomScrollbar/_CustomScrollbar.scss diff --git a/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.test.tsx b/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.test.tsx index 4edcf7313db..32375a5dc29 100644 --- a/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.test.tsx +++ b/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.test.tsx @@ -1,6 +1,6 @@ import React from 'react'; import renderer from 'react-test-renderer'; -import CustomScrollbar from './CustomScrollbar'; +import { CustomScrollbar } from './CustomScrollbar'; describe('CustomScrollbar', () => { it('renders correctly', () => { diff --git a/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.tsx b/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.tsx index 8e79a21fbbd..509a3681a4f 100644 --- a/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.tsx +++ b/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.tsx @@ -1,19 +1,21 @@ -import React, { Component } from 'react'; +import React, { FC, useCallback, useEffect, useRef } from 'react'; import isNil from 'lodash/isNil'; import classNames from 'classnames'; +import { css } from 'emotion'; import Scrollbars from 'react-custom-scrollbars'; +import { useStyles } from '../../themes'; +import { GrafanaTheme } from '@grafana/data'; interface Props { className?: string; autoHide?: boolean; autoHideTimeout?: number; - autoHideDuration?: number; autoHeightMax?: string; hideTracksWhenNotNeeded?: boolean; hideHorizontalTrack?: boolean; hideVerticalTrack?: boolean; scrollTop?: number; - setScrollTop: (event: any) => void; + setScrollTop?: (event: any) => void; autoHeightMin?: number | string; updateAfterMountMs?: number; } @@ -21,122 +23,152 @@ interface Props { /** * Wraps component into component from `react-custom-scrollbars` */ -export class CustomScrollbar extends Component { - static defaultProps: Partial = { - autoHide: false, - autoHideTimeout: 200, - autoHideDuration: 200, - setScrollTop: () => {}, - hideTracksWhenNotNeeded: false, - autoHeightMin: '0', - autoHeightMax: '100%', +export const CustomScrollbar: FC = ({ + autoHide = false, + autoHideTimeout = 200, + setScrollTop, + className, + autoHeightMin = '0', + autoHeightMax = '100%', + hideTracksWhenNotNeeded = false, + hideHorizontalTrack, + hideVerticalTrack, + updateAfterMountMs, + scrollTop, + children, +}) => { + const ref = useRef(null); + const styles = useStyles(getStyles); + + const updateScroll = () => { + if (ref.current && !isNil(scrollTop)) { + ref.current.scrollTop(scrollTop); + } }; - private ref: React.RefObject; + useEffect(() => { + updateScroll(); + }); - constructor(props: Props) { - super(props); - this.ref = React.createRef(); + /** + * Special logic for doing a update a few milliseconds after mount to check for + * updated height due to dynamic content + */ + if (updateAfterMountMs) { + useEffect(() => { + setTimeout(() => { + const scrollbar = ref.current as any; + if (scrollbar?.update) { + scrollbar.update(); + } + }, updateAfterMountMs); + }, []); } - updateScroll() { - const ref = this.ref.current; - const { scrollTop } = this.props; - - if (ref && !isNil(scrollTop)) { - ref.scrollTop(scrollTop); - } - } - - componentDidMount() { - this.updateScroll(); - - // this logic is to make scrollbar visible when content is added body after mount - if (this.props.updateAfterMountMs) { - setTimeout(() => this.updateAfterMount(), this.props.updateAfterMountMs); - } - } - - updateAfterMount() { - if (this.ref && this.ref.current) { - const scrollbar = this.ref.current as any; - if (scrollbar.update) { - scrollbar.update(); - } - } - } - - componentDidUpdate() { - this.updateScroll(); - } - - renderTrack = (track: 'track-vertical' | 'track-horizontal', hideTrack: boolean | undefined, passedProps: any) => { + function renderTrack(className: string, hideTrack: boolean | undefined, passedProps: any) { if (passedProps.style && hideTrack) { passedProps.style.display = 'none'; } - return
; - }; - - renderThumb = (thumb: 'thumb-horizontal' | 'thumb-vertical', passedProps: any) => { - return
; - }; - - renderTrackHorizontal = (passedProps: any) => { - return this.renderTrack('track-horizontal', this.props.hideHorizontalTrack, passedProps); - }; - - renderTrackVertical = (passedProps: any) => { - return this.renderTrack('track-vertical', this.props.hideVerticalTrack, passedProps); - }; - - renderThumbHorizontal = (passedProps: any) => { - return this.renderThumb('thumb-horizontal', passedProps); - }; - - renderThumbVertical = (passedProps: any) => { - return this.renderThumb('thumb-vertical', passedProps); - }; - - renderView = (passedProps: any) => { - return
; - }; - - render() { - const { - className, - children, - autoHeightMax, - autoHeightMin, - setScrollTop, - autoHide, - autoHideTimeout, - hideTracksWhenNotNeeded, - } = this.props; - - return ( - - {children} - - ); + return
; } -} + + const renderTrackHorizontal = useCallback( + (passedProps: any) => { + return renderTrack('track-horizontal', hideHorizontalTrack, passedProps); + }, + [hideHorizontalTrack] + ); + + const renderTrackVertical = useCallback( + (passedProps: any) => { + return renderTrack('track-vertical', hideVerticalTrack, passedProps); + }, + [hideVerticalTrack] + ); + + const renderThumbHorizontal = useCallback((passedProps: any) => { + return
; + }, []); + + const renderThumbVertical = useCallback((passedProps: any) => { + return
; + }, []); + + const renderView = useCallback((passedProps: any) => { + return
; + }, []); + + return ( + + {children} + + ); +}; export default CustomScrollbar; + +const getStyles = (theme: GrafanaTheme) => { + return { + customScrollbar: css` + // Fix for Firefox. For some reason sometimes .view container gets a height of its content, but in order to + // make scroll working it should fit outer container size (scroll appears only when inner container size is + // greater than outer one). + display: flex; + flex-grow: 1; + .scrollbar-view { + display: flex; + flex-grow: 1; + flex-direction: column; + } + .track-vertical { + border-radius: ${theme.border.radius.md}; + width: ${theme.spacing.sm} !important; + right: 0px; + bottom: ${theme.spacing.xxs}; + top: ${theme.spacing.xxs}; + } + .track-horizontal { + border-radius: ${theme.border.radius.md}; + height: ${theme.spacing.sm} !important; + right: ${theme.spacing.xxs}; + bottom: ${theme.spacing.xxs}; + left: ${theme.spacing.xxs}; + } + .thumb-vertical { + background: ${theme.colors.bg3}; + border-radius: ${theme.border.radius.md}; + opacity: 0; + } + .thumb-horizontal { + background: ${theme.colors.bg3}; + border-radius: ${theme.border.radius.md}; + opacity: 0; + } + &:hover { + .thumb-vertical, + .thumb-horizontal { + opacity: 1; + transition: opacity 0.3s ease-in-out; + } + } + `, + }; +}; diff --git a/packages/grafana-ui/src/components/CustomScrollbar/_CustomScrollbar.scss b/packages/grafana-ui/src/components/CustomScrollbar/_CustomScrollbar.scss deleted file mode 100644 index fd846025534..00000000000 --- a/packages/grafana-ui/src/components/CustomScrollbar/_CustomScrollbar.scss +++ /dev/null @@ -1,57 +0,0 @@ -.custom-scrollbar { - // Fix for Firefox. For some reason sometimes .view container gets a height of its content, but in order to - // make scroll working it should fit outer container size (scroll appears only when inner container size is - // greater than outer one). - display: flex; - flex-grow: 1; - - .view { - display: flex; - flex-grow: 1; - flex-direction: column; - } - - .track-vertical { - border-radius: 3px; - width: 8px !important; - right: 2px; - bottom: 2px; - top: 2px; - } - - .track-horizontal { - border-radius: 3px; - height: 8px !important; - - right: 2px; - bottom: 2px; - left: 2px; - } - - .thumb-vertical { - @include gradient-vertical($scrollbarBackground, $scrollbarBackground2); - border-radius: 6px; - opacity: 0; - } - - .thumb-horizontal { - @include gradient-horizontal($scrollbarBackground, $scrollbarBackground2); - border-radius: 6px; - opacity: 0; - } - - &:hover { - .thumb-vertical, - .thumb-horizontal { - opacity: 0.8; - transition: opacity 0.3s ease-in-out; - } - } - - // page scrollbar should stick to left side to aid hitting it - &--page { - .track-vertical { - right: 0; - } - } -} diff --git a/packages/grafana-ui/src/components/CustomScrollbar/__snapshots__/CustomScrollbar.test.tsx.snap b/packages/grafana-ui/src/components/CustomScrollbar/__snapshots__/CustomScrollbar.test.tsx.snap index dd3f59ad1e1..f709b0e6786 100644 --- a/packages/grafana-ui/src/components/CustomScrollbar/__snapshots__/CustomScrollbar.test.tsx.snap +++ b/packages/grafana-ui/src/components/CustomScrollbar/__snapshots__/CustomScrollbar.test.tsx.snap @@ -2,7 +2,7 @@ exports[`CustomScrollbar renders correctly 1`] = `
{ const { navModel, children, ...otherProps } = this.props; return (
- +
{children} diff --git a/public/app/features/dashboard/containers/DashboardPage.tsx b/public/app/features/dashboard/containers/DashboardPage.tsx index 2cdb866b6c1..502bea5ad5c 100644 --- a/public/app/features/dashboard/containers/DashboardPage.tsx +++ b/public/app/features/dashboard/containers/DashboardPage.tsx @@ -316,7 +316,6 @@ export class DashboardPage extends PureComponent { scrollTop={updateScrollTop} hideHorizontalTrack={true} updateAfterMountMs={500} - className="custom-scrollbar--page" >
{initError && this.renderInitFailedState()} diff --git a/public/app/features/dashboard/containers/__snapshots__/DashboardPage.test.tsx.snap b/public/app/features/dashboard/containers/__snapshots__/DashboardPage.test.tsx.snap index 7f43d1abe91..b81673b2996 100644 --- a/public/app/features/dashboard/containers/__snapshots__/DashboardPage.test.tsx.snap +++ b/public/app/features/dashboard/containers/__snapshots__/DashboardPage.test.tsx.snap @@ -106,14 +106,8 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1` className="dashboard-scroll" > @@ -481,14 +475,8 @@ exports[`DashboardPage When dashboard has editview url state should render setti className="dashboard-scroll" > diff --git a/public/app/features/explore/Wrapper.tsx b/public/app/features/explore/Wrapper.tsx index 469f92c5a29..eac32ca2f2e 100644 --- a/public/app/features/explore/Wrapper.tsx +++ b/public/app/features/explore/Wrapper.tsx @@ -31,7 +31,7 @@ export class Wrapper extends Component { return (
- +
diff --git a/public/app/features/query/components/QueryGroup.tsx b/public/app/features/query/components/QueryGroup.tsx index 8f4727e4b65..086561780e9 100644 --- a/public/app/features/query/components/QueryGroup.tsx +++ b/public/app/features/query/components/QueryGroup.tsx @@ -337,13 +337,7 @@ export class QueryGroup extends PureComponent { const styles = getStyles(); return ( - +
{this.renderTopSection(styles)} {dsSettings && ( From aad7d495ecc6110d25998c3da6129a21fb1a76fc Mon Sep 17 00:00:00 2001 From: Alex Khomenko Date: Wed, 27 Jan 2021 19:10:18 +0200 Subject: [PATCH 21/41] Grafana-UI: Fix setting default value for MultiSelect (#30671) * Grafana-ui: Default value to undefned vs empty array * Grafana-ui: Remove log * Grafana-ui: Update tests --- .../grafana-ui/src/components/Select/SelectBase.tsx | 4 ++-- .../grafana-ui/src/components/Select/utils.test.ts | 10 +++++----- packages/grafana-ui/src/components/Select/utils.ts | 10 ++++------ 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/packages/grafana-ui/src/components/Select/SelectBase.tsx b/packages/grafana-ui/src/components/Select/SelectBase.tsx index 6468a42b44d..70afab8af75 100644 --- a/packages/grafana-ui/src/components/Select/SelectBase.tsx +++ b/packages/grafana-ui/src/components/Select/SelectBase.tsx @@ -150,7 +150,7 @@ export function SelectBase({ let ReactSelectComponent: ReactSelect | Creatable = ReactSelect; const creatableProps: any = {}; let asyncSelectProps: any = {}; - let selectedValue = []; + let selectedValue; if (isMulti && loadOptions) { selectedValue = value as any; } else { @@ -207,7 +207,7 @@ export function SelectBase({ renderControl, showAllSelectedWhenOpen, tabSelectsValue, - value: isMulti ? selectedValue : selectedValue[0], + value: isMulti ? selectedValue : selectedValue?.[0], }; if (allowCustomValue) { diff --git a/packages/grafana-ui/src/components/Select/utils.test.ts b/packages/grafana-ui/src/components/Select/utils.test.ts index 00cd8adf54f..8a48c413ab2 100644 --- a/packages/grafana-ui/src/components/Select/utils.test.ts +++ b/packages/grafana-ui/src/components/Select/utils.test.ts @@ -74,11 +74,11 @@ describe('Select utils', () => { expect(cleanValue('test1', optGroup)).toEqual([{ label: 'Group 4 - Option 1', value: 'test1' }]); expect(cleanValue(3, options)).toEqual([{ label: 'Option 3', value: 3 }]); }); - it('should return empty array for null/undefined/empty values', () => { - expect(cleanValue([undefined], options)).toEqual([]); - expect(cleanValue(undefined, options)).toEqual([]); - expect(cleanValue(null, options)).toEqual([]); - expect(cleanValue('', options)).toEqual([]); + it('should return undefined for null/undefined/empty values', () => { + expect(cleanValue([undefined], options)).toEqual(undefined); + expect(cleanValue(undefined, options)).toEqual(undefined); + expect(cleanValue(null, options)).toEqual(undefined); + expect(cleanValue('', options)).toEqual(undefined); }); }); }); diff --git a/packages/grafana-ui/src/components/Select/utils.ts b/packages/grafana-ui/src/components/Select/utils.ts index daa255722ec..a1615d2fd21 100644 --- a/packages/grafana-ui/src/components/Select/utils.ts +++ b/packages/grafana-ui/src/components/Select/utils.ts @@ -4,12 +4,10 @@ import { SelectableOptGroup } from './types'; /** * Normalize the value format to SelectableValue[] | []. Only used for single select */ -export const cleanValue = ( - value: any, - options: Array -): SelectableValue[] | [] => { +export const cleanValue = (value: any, options: Array) => { if (Array.isArray(value)) { - return value.filter(Boolean); + const filtered = value.filter(Boolean); + return filtered?.length ? filtered : undefined; } if (typeof value === 'object' && value !== null) { return [value]; @@ -20,7 +18,7 @@ export const cleanValue = ( return [selectedValue]; } } - return []; + return undefined; }; /** From 02f8a139dbe0f3a4193d43b3876a210bdea644f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 27 Jan 2021 20:10:03 +0100 Subject: [PATCH 22/41] PanelEdit: Get rid of last remaining usage of navbar-button (#30682) --- .../src/components/Button/ToolbarButton.tsx | 3 + .../src/themes/_variables.dark.scss.tmpl.ts | 3 - .../src/themes/_variables.light.scss.tmpl.ts | 3 - .../dashboard/components/DashNav/DashNav.tsx | 4 - .../components/DashNav/DashNavButton.tsx | 60 +++--------- .../PanelEditor/OptionsPaneContent.tsx | 22 +++-- .../components/PanelEditor/PanelEditor.tsx | 13 +-- public/sass/_variables.dark.generated.scss | 3 - public/sass/_variables.light.generated.scss | 3 - public/sass/components/_navbar.scss | 91 ------------------- 10 files changed, 33 insertions(+), 172 deletions(-) diff --git a/packages/grafana-ui/src/components/Button/ToolbarButton.tsx b/packages/grafana-ui/src/components/Button/ToolbarButton.tsx index f7db756cbfe..ad1df23bee8 100644 --- a/packages/grafana-ui/src/components/Button/ToolbarButton.tsx +++ b/packages/grafana-ui/src/components/Button/ToolbarButton.tsx @@ -118,9 +118,12 @@ const getStyles = (theme: GrafanaTheme) => { line-height: ${theme.height.md - 2}px; font-weight: ${theme.typography.weight.semibold}; border: 1px solid ${theme.colors.border2}; + white-space: nowrap; + &:focus { outline: none; } + &[disabled], &:disabled { cursor: not-allowed; diff --git a/packages/grafana-ui/src/themes/_variables.dark.scss.tmpl.ts b/packages/grafana-ui/src/themes/_variables.dark.scss.tmpl.ts index 6e94110e5da..d71f1ef7e4b 100644 --- a/packages/grafana-ui/src/themes/_variables.dark.scss.tmpl.ts +++ b/packages/grafana-ui/src/themes/_variables.dark.scss.tmpl.ts @@ -240,9 +240,6 @@ $horizontalComponentOffset: 180px; $navbarHeight: 55px; $navbarBorder: 1px solid $dark-6; -$navbarButtonBackground: $panel-bg; -$navbar-button-border: #2f2f32; - // Sidemenu // ------------------------- $side-menu-bg: $panel-bg; diff --git a/packages/grafana-ui/src/themes/_variables.light.scss.tmpl.ts b/packages/grafana-ui/src/themes/_variables.light.scss.tmpl.ts index 38fa74b746b..ab2d11c91e8 100644 --- a/packages/grafana-ui/src/themes/_variables.light.scss.tmpl.ts +++ b/packages/grafana-ui/src/themes/_variables.light.scss.tmpl.ts @@ -234,9 +234,6 @@ $horizontalComponentOffset: 180px; $navbarHeight: 52px; $navbarBorder: 1px solid $gray-5; -$navbarButtonBackground: $panel-bg; -$navbar-button-border: $gray-4; - // Sidemenu // ------------------------- $side-menu-bg: ${theme.palette.gray15}; diff --git a/public/app/features/dashboard/components/DashNav/DashNav.tsx b/public/app/features/dashboard/components/DashNav/DashNav.tsx index 1b583aab1de..083cd91d67c 100644 --- a/public/app/features/dashboard/components/DashNav/DashNav.tsx +++ b/public/app/features/dashboard/components/DashNav/DashNav.tsx @@ -145,11 +145,9 @@ class DashNav extends PureComponent { buttons.push( @@ -162,10 +160,8 @@ class DashNav extends PureComponent { {({ showModal, hideModal }) => ( { showModal(ShareModal, { dashboard, diff --git a/public/app/features/dashboard/components/DashNav/DashNavButton.tsx b/public/app/features/dashboard/components/DashNav/DashNavButton.tsx index ae2908c3733..c1f137700f1 100644 --- a/public/app/features/dashboard/components/DashNav/DashNavButton.tsx +++ b/public/app/features/dashboard/components/DashNav/DashNavButton.tsx @@ -2,71 +2,37 @@ import React, { FunctionComponent } from 'react'; import { css } from 'emotion'; // Components -import { Tooltip, Icon, IconName, IconType, IconSize, IconButton, useTheme, stylesFactory } from '@grafana/ui'; -import { selectors } from '@grafana/e2e-selectors'; +import { IconName, IconType, IconSize, IconButton, useTheme, stylesFactory } from '@grafana/ui'; import { GrafanaTheme } from '@grafana/data'; interface Props { icon?: IconName; tooltip: string; - classSuffix?: string; onClick?: () => void; href?: string; children?: React.ReactNode; iconType?: IconType; iconSize?: IconSize; - noBorder?: boolean; } -export const DashNavButton: FunctionComponent = ({ - icon, - iconType, - iconSize, - tooltip, - classSuffix, - onClick, - href, - children, - noBorder, -}) => { +export const DashNavButton: FunctionComponent = ({ icon, iconType, iconSize, tooltip, onClick, children }) => { const theme = useTheme(); const styles = getStyles(theme); - if (noBorder) { - return ( -
- {icon && ( - - )} - {children} -
- ); - } return ( - - {onClick ? ( - - ) : ( - - {icon && } - {children} - + /> )} - + {children} +
); }; diff --git a/public/app/features/dashboard/components/PanelEditor/OptionsPaneContent.tsx b/public/app/features/dashboard/components/PanelEditor/OptionsPaneContent.tsx index 4b11df0ec39..0121eca9f6f 100644 --- a/public/app/features/dashboard/components/PanelEditor/OptionsPaneContent.tsx +++ b/public/app/features/dashboard/components/PanelEditor/OptionsPaneContent.tsx @@ -2,12 +2,22 @@ import React, { CSSProperties, useCallback, useState } from 'react'; import Transition from 'react-transition-group/Transition'; import { FieldConfigSource, GrafanaTheme, PanelPlugin, SelectableValue } from '@grafana/data'; import { DashboardModel, PanelModel } from '../../state'; -import { CustomScrollbar, Icon, Input, Select, stylesFactory, Tab, TabContent, TabsBar, useTheme } from '@grafana/ui'; +import { + CustomScrollbar, + Icon, + Input, + Select, + stylesFactory, + Tab, + TabContent, + TabsBar, + ToolbarButton, + useTheme, +} from '@grafana/ui'; import { OverrideFieldConfigEditor } from './OverrideFieldConfigEditor'; import { DefaultFieldConfigEditor } from './DefaultFieldConfigEditor'; import { css } from 'emotion'; import { PanelOptionsTab } from './PanelOptionsTab'; -import { DashNavButton } from 'app/features/dashboard/components/DashNav/DashNavButton'; import { usePanelLatestData } from './usePanelLatestData'; import { selectors } from '@grafana/e2e-selectors'; @@ -213,13 +223,7 @@ export const TabsBarContent: React.FC<{ )}
- +
); diff --git a/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx b/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx index 052a628af71..69c5d737ae3 100644 --- a/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx +++ b/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx @@ -6,7 +6,7 @@ import { Subscription } from 'rxjs'; import { FieldConfigSource, GrafanaTheme } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; -import { HorizontalGroup, Icon, PageToolbar, RadioButtonGroup, stylesFactory, ToolbarButton } from '@grafana/ui'; +import { HorizontalGroup, PageToolbar, RadioButtonGroup, stylesFactory, ToolbarButton } from '@grafana/ui'; import config from 'app/core/config'; import { appEvents } from 'app/core/core'; @@ -15,7 +15,6 @@ import { calculatePanelSize } from './utils'; import { PanelEditorTabs } from './PanelEditorTabs'; import { DashNavTimeControls } from '../DashNav/DashNavTimeControls'; import { OptionsPaneContent } from './OptionsPaneContent'; -import { DashNavButton } from 'app/features/dashboard/components/DashNav/DashNavButton'; import { SubMenuItems } from 'app/features/dashboard/components/SubMenu/SubMenuItems'; import { SplitPaneWrapper } from 'app/core/components/SplitPaneWrapper/SplitPaneWrapper'; import { SaveDashboardModalProxy } from '../SaveDashboard/SaveDashboardModalProxy'; @@ -235,13 +234,9 @@ export class PanelEditorUnconnected extends PureComponent { onChangeTimeZone={updateTimeZoneForSession} /> {!uiState.isPanelOptionsVisible && ( - - Show options - + + Show options + )} diff --git a/public/sass/_variables.dark.generated.scss b/public/sass/_variables.dark.generated.scss index c6e439597df..63afd6fddf0 100644 --- a/public/sass/_variables.dark.generated.scss +++ b/public/sass/_variables.dark.generated.scss @@ -242,9 +242,6 @@ $horizontalComponentOffset: 180px; $navbarHeight: 55px; $navbarBorder: 1px solid $dark-6; -$navbarButtonBackground: $panel-bg; -$navbar-button-border: #2f2f32; - // Sidemenu // ------------------------- $side-menu-bg: $panel-bg; diff --git a/public/sass/_variables.light.generated.scss b/public/sass/_variables.light.generated.scss index 4efe9e30605..9eaf954beaa 100644 --- a/public/sass/_variables.light.generated.scss +++ b/public/sass/_variables.light.generated.scss @@ -236,9 +236,6 @@ $horizontalComponentOffset: 180px; $navbarHeight: 52px; $navbarBorder: 1px solid $gray-5; -$navbarButtonBackground: $panel-bg; -$navbar-button-border: $gray-4; - // Sidemenu // ------------------------- $side-menu-bg: #202226; diff --git a/public/sass/components/_navbar.scss b/public/sass/components/_navbar.scss index e1b3e86e222..f19900a21a2 100644 --- a/public/sass/components/_navbar.scss +++ b/public/sass/components/_navbar.scss @@ -30,94 +30,3 @@ } } } - -.navbar-button { - background-color: $panel-bg; - - display: flex; - align-items: center; - font-weight: $btn-font-weight; - padding: 0 $space-sm; - height: 32px; - // 2px less then border - line-height: 30px; - color: $text-muted; - border: 1px solid $navbar-button-border; - margin-left: $space-xs; - white-space: nowrap; - - .gicon { - font-size: 16px; - } - - .fa { - font-size: 16px; - } - - &--add-panel { - padding: 2px 10px; - - .gicon { - font-size: 22px; - } - } - - &--refresh { - padding-left: 8px; - padding-right: 8px; - } - - &--attached { - margin-left: 0; - border-radius: 0 2px 2px 0; - } - - &--settings { - .gicon { - filter: $navbar-btn-gicon-brightness; - } - - &:hover { - .gicon { - filter: brightness(0.8); - } - } - } - - &--danger { - @include buttonBackground($red-base, $red-shade); - } - - &--tight { - padding: 0px 4px; - - .fa { - font-size: 14px; - } - } - - &--primary { - @include buttonBackground($btn-primary-bg, $btn-primary-bg-hl); - } - - &--danger { - @include buttonBackground($red-base, $red-shade); - } - - &:hover { - svg { - color: $text-color; - } - } - - &--danger { - @include buttonBackground($red-base, $red-shade); - } - - @include media-breakpoint-down(lg) { - .btn-title { - margin-left: $space-xs; - display: none; - } - } -} From 0df4b15957828f5706928f6e865842b85e24d673 Mon Sep 17 00:00:00 2001 From: Diana Payton <52059945+oddlittlebird@users.noreply.github.com> Date: Wed, 27 Jan 2021 12:19:19 -0800 Subject: [PATCH 23/41] Docs: 7.4 documentation for expressions (#30524) * Create expressions.md * Update queries.md * Update expressions.md * Update whats-new-in-v7-4.md * remove alerting NG references and alerting examples * Update docs/sources/panels/expressions.md * Update docs/sources/panels/expressions.md * remove empty line Co-authored-by: Diana Payton <52059945+oddlittlebird@users.noreply.github.com> Co-authored-by: kyle --- docs/sources/panels/expressions.md | 151 +++++++++++++++++++++ docs/sources/panels/queries.md | 7 + docs/sources/whatsnew/whats-new-in-v7-4.md | 4 +- 3 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 docs/sources/panels/expressions.md diff --git a/docs/sources/panels/expressions.md b/docs/sources/panels/expressions.md new file mode 100644 index 00000000000..609dd98c716 --- /dev/null +++ b/docs/sources/panels/expressions.md @@ -0,0 +1,151 @@ ++++ +title = "Expressions" +weight = 800 ++++ + +# Server-side expressions + +> **Note:** This documentation is for a beta feature. + +Server-side expressions allow you to manipulate data returned from queries with math and other operations. Expressions create new data and do not manipulate the data returned by data sources, aside from some minor data restructuring to make the data acceptable input for expressions. + +## Using expressions + +The primary use case for expressions is for the upcoming next version of Grafana alerting. Like alerting, processing is done server-side, so expressions can operate without a browser session. However, expressions can be used with backend data sources and visualization as well. + +> **Note:** Expressions do not work with current Grafana alerting. + +Expressions are meant to augment data sources by enabling queries from different data sources to be combined or by providing operations unavailable in a data source. + +> **Note:** When possible, you should do data processing inside the data source. Copying data from storage to the Grafana server for processing is inefficient, so expressions are targeted at lightweight data processing. + +Expressions work with data source queries that return time series or number data. They also operate on [multiple-dimensional data]({{< relref "../getting-started/timeseries-dimensions.md" >}}). For example, a query that returns multiple series, where each series is identified by labels or tags. + +An individual expression takes one or more queries or other expressions as input and adds data to the result. Each individual expression or query is represented by a variable that is a named identifier known as its RefID (e.g., the default letter `A` or `B`). + +To reference the output of an individual expression or a data source query in another expression, this identifier is used as a variable. + +## Types of expression + +Expressions work with two types of data. + +- A collections of time series. +- A collection of numbers, where each collection could be a single series or single number. + +Each collection is returned from a single data source query or expression and represented by the RefID. Each collection is a set, where each item in the set is uniquely identified by it dimensions which are stored as [labels]({{< relref "../getting-started/timeseries-dimensions.md#labels" >}}) or key-value pairs. + +## Data source queries + +Server-side expressions only support data source queries for backend data sources. The data is generally assumed to be labeled time series data. In the future we intended to add an assertion of the query return type (number or time series) data so expressions can handle errors better. + +Data source queries, when used with expressions, are executed by the expression engine. When it does this, it restructures data to be either one time series or one number per data frame. So for example if using a data source that returns multiple series on one frame in the table view, you might notice it looks different when executed with expressions. + +Currently, the only non-time series format (number) is supported when using data frames are you have a table response that returns a data frame with no time, string columns, and one number column: + +Loc | Host | Avg_CPU | +----|------| ------- | +MIA | A | 1 +NYC | B | 2 + +will produce a number that works with expressions. The string columns become labels and the number column the corresponding value. For example `{"Loc": "MIA", "Host": "A"}` with a value of 1. + +## Operations + +You can use the following operations in expressions: math, reduce, and resample. + +### Math + +Math is for free-form math formulas on time series or number data. Math operations take numbers and time series as input and changes them to different numbers and time series. + +Data from other queries or expressions are referenced with the RefID prefixed with a dollar sign, for example `$A`. If the variable has spaces in the name, then you can use a brace syntax like `${my variable}`. + +Numeric constants may be in decimal (`2.24`), octal (with a leading zero like `072`), or hex (with a leading 0x like `0x2A`). Exponentials and signs are also supported (e.g., `-0.8e-2`). + +#### Operators + +The arithmetic (`+`, binary and unary `-`, `*`, `/`, `%`, exponent `**`), relational (`<`, `>`, `==`, `!=`, `>=`, `<=`), and logical (`&&`, `||`, and unary `!`) operators are supported. + +How the operation behaves with data depends on if it is a number or time series data. + +With binary operations, such as `$A + $B` or `$A || $B`, the operator is applied in the following ways depending on the type of data: + +- If both `$A` and `$B` are a number, then the operation is performed between the two numbers. +- If one variable is a number, and the other variable is a time series, then the operation between the value of each point in the time series and the number is performed. +- If both `$A` and `$B` are time series data, then the operation between each value in the two series is performed for each time stamp that exists in both `$A` and `$B`. The Resample operation can be used to line up time stamps. (**Note:** in the future, we plan to add options to the Math operation for different behaviors). + +So in summary: + +- Number OP number = number +- Number OP series = series +- Series OP series = series + +Because expressions work with multiple series or numbers represented by a single variable, binary operations also perform a union (join) between the two variables. This is done based on the identifying labels associated with each individual series or number. + +So if you have numbers with labels like `{host=web01}` in `$A` and another number in `$B` with the same labels then the operation is performed between those two items within each variable, and the result will share the same labels. The rules for the behavior of this union are as follows: + +- An item with no labels will join to anything. +- If both `$A` and `$B` each contain only one item (one series, or one number), they will join. +- If labels are exact math they will join. +- If labels are a subset of the other, for example and item in `$A` is labeled `{host=A,dc=MIA}` and and item in `$B` is labeled `{host=A}` they will join. +- Currently, if within a variable such as `$A` there are different tag _keys_ for each item, the join behavior is undefined. + +The relational and logical operators return 0 for false 1 for true. + +#### Math Functions + +While most functions exist in the own expression operations, the math operation does have some functions that similar to math operators or symbols. When functions can take either numbers or series, than the same type as the argument will be returned. When it is a series, the operation of performed for the value of each point in the series. + +##### abs + +abs returns the absolute value of its argument which can be a number or a series. For example `abs(-1)` or `abs($A)`. + +##### log + +Log returns the natural logarithm of of its argument which can be a number or a series. If the value is less than 0, NaN is returned. For example `log(-1)` or `log($A)`. + +##### inf, nan, and null + +The inf, nan, and null functions all return a single value of the name. They primarily exist for testing. Example: `null()`. (Note: inf always returns positive infinity, should probably change this to take an argument so it can return negative infinity). + +### Reduce + +Reduce takes one or more time series returned from a query or an expression and turns each series into a single number. The labels of the time series are kept as labels on each outputted reduced number. + +**Fields:** + +- **Function -** The reduction function to use +- **Input -** The variable (refID (such as `A`)) to resample + +#### Reduction Functions + +> **Note:** In the future we plan to add options to control empty, NaN, and null behavior for reduction functions. + +##### Count + +Count returns the number of points in each series. + +##### Mean + +Mean returns the total of all values in each series divided by the number of points in that series. If any values in the series are null or nan, or if the series is empty, NaN is returned. + +##### Min and Max + +Min and Max return the smallest or largest value in the series respectively. If any values in the series are null or nan, or if the series is empty, NaN is returned. + +##### Sum + +Sum returns the total of all values in the series. If series is of zero length, the sum will be 0. If there are any NaN or Null values in the series, NaN is returned. + +### Resample + +Resample changes the time stamps in each time series to have a consistent time interval. The main use case is so you can resample time series that do not share the same timestamps so math can be performed between them. This can be done by resample each of the two series, and then in a Math operation referencing the resampled variables. + +**Fields:** + +- **Input -** The variable of time series data (refID (such as `A`)) to resample +- **Resample to -** The duration of time to resample to, for example `10s`. Units may be `s` seconds, `m` for minutes, `h` for hours, `d` for days, `w` for weeks, and `y` of years. +- **Downsample -** The reduction function to use when there are more than one data point per window sample. See the reduction operation for behavior details. +- **Upsample -** The method to use to fill a window sample that has no data points. + - **pad** fills with the last know value + - **backfill** with next known value + - **fillna** to fill empty sample windows with NaNs diff --git a/docs/sources/panels/queries.md b/docs/sources/panels/queries.md index 8c688535131..040747c5443 100644 --- a/docs/sources/panels/queries.md +++ b/docs/sources/panels/queries.md @@ -49,6 +49,7 @@ The Query tab consists of the following elements: - Query options - Query inspector button - Query editor list +- Expressions {{< docs-imagebox img="/img/docs/queries/query-editor-7-2.png" class="docs-image--no-shadow" max-width="1000px" >}} @@ -123,3 +124,9 @@ You can: | {{< docs-imagebox img="/img/docs/queries/hide-query-icon-7-0.png" class="docs-image--no-shadow" max-width="30px" max-height="30px" >}} | Hide a query. Grafana does not send hidden queries to the data source. | | {{< docs-imagebox img="/img/docs/queries/remove-query-icon-7-0.png" class="docs-image--no-shadow" max-width="30px" max-height="30px" >}} | Remove a query. Removing a query permanently deletes it, but sometimes you can recover deleted queries by reverting to previously saved versions of the panel. | | {{< docs-imagebox img="/img/docs/queries/query-drag-icon-7-2.png" class="docs-image--no-shadow" max-width="30px" max-height="30px" >}} | Reorder queries. Change the order of queries by clicking and holding the drag icon, then drag queries where desired. The order of results reflects the order of the queries, so you can often adjust your visual results based on query order. | + +### Expressions + +If your data source supports them, then Grafana displays the **Expression** button and shows any existing expressions in the query editor list. + +For more information about expressions, refer to [Expressions]({{< relref "expressions.md" >}}). \ No newline at end of file diff --git a/docs/sources/whatsnew/whats-new-in-v7-4.md b/docs/sources/whatsnew/whats-new-in-v7-4.md index 2972795796d..c4b47af7d9e 100644 --- a/docs/sources/whatsnew/whats-new-in-v7-4.md +++ b/docs/sources/whatsnew/whats-new-in-v7-4.md @@ -85,10 +85,12 @@ The following topics were updated as a result of this feature: _Server-side expressions_ is an experimental feature that allows you to manipulate data returned from backend data source queries. Expressions allow you to manipulate data with math and other operations when the data source is a backend data source or a **--Mixed--** data source. -The main use case is for [multi-dimensional](https://grafana.com/docs/grafana/latest/getting-started/timeseries-dimensions/#time-series-dimensions) data sources used with the upcoming next generation alerting, but expressions can be used with backend data sources and visualization as well. +The main use case is for [multi-dimensional]({{< relref "../getting-started/timeseries-dimensions.md" >}}) data sources used with the upcoming next generation alerting, but expressions can be used with backend data sources and visualization as well. > **Note:** Queries built with this feature might break with minor version upgrades until Grafana 8 is released. This feature does not work with the current Grafana alerting. +For more information, refer to [Expressions]({{< relref "../panels/expressions.md" >}}). [Queries]({{< relref "../panels/queries.md" >}}) was also updated as a result of this feature. + ### Alert notification query label interpolation You can now provide detailed information to alert notification recipients by injecting alert label data as template variables into an alert notification. Labels that exist from the evaluation of the alert query can be used in the alert rule name and in the alert notification message fields using the `${Label}` syntax. The alert label data is automatically injected into the notification fields when the alert is in the alerting state. When there are multiple unique values for the same label, the values are comma-separated. From bc857986b63f183f3ee9746ecfe2b02db35c078f Mon Sep 17 00:00:00 2001 From: Ryan McKinley Date: Wed, 27 Jan 2021 13:31:41 -0800 Subject: [PATCH 24/41] Chore: remove CSP debug logging line (#30689) --- pkg/middleware/csp.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/middleware/csp.go b/pkg/middleware/csp.go index 6013205e9e5..46acb5a8ce5 100644 --- a/pkg/middleware/csp.go +++ b/pkg/middleware/csp.go @@ -18,7 +18,6 @@ import ( func AddCSPHeader(cfg *setting.Cfg, logger log.Logger) macaron.Handler { return func(w http.ResponseWriter, req *http.Request, c *macaron.Context) { if !cfg.CSPEnabled { - logger.Debug("Not adding CSP header to response since it's disabled") return } From fdd6a84d82e9b0f017f3981295484db9e1b5b8da Mon Sep 17 00:00:00 2001 From: Arve Knudsen Date: Thu, 28 Jan 2021 11:03:18 +0100 Subject: [PATCH 25/41] DeployImage: Switch base images to Debian (#30684) * DeployImage: Switch base images to Debian Signed-off-by: Arve Knudsen --- .drone.yml | 36 ++++++++++++------------- scripts/build/ci-deploy/Dockerfile | 35 +++++++++++++++--------- scripts/build/ci-deploy/build-deploy.sh | 2 +- scripts/lib.star | 2 +- 4 files changed, 43 insertions(+), 32 deletions(-) diff --git a/.drone.yml b/.drone.yml index 24ab83891d8..f5a9cbab3dc 100644 --- a/.drone.yml +++ b/.drone.yml @@ -433,7 +433,7 @@ steps: - package - name: publish-storybook - image: grafana/grafana-ci-deploy:1.2.7 + image: grafana/grafana-ci-deploy:1.3.0 commands: - printenv GCP_KEY | base64 -d > /tmp/gcpkey.json - gcloud auth activate-service-account --key-file=/tmp/gcpkey.json @@ -527,7 +527,7 @@ steps: - end-to-end-tests - name: upload-packages - image: grafana/grafana-ci-deploy:1.2.7 + image: grafana/grafana-ci-deploy:1.3.0 commands: - ./bin/grabpl upload-packages --edition oss environment: @@ -638,7 +638,7 @@ steps: DOCKERIZE_VERSION: 0.6.1 - name: publish-packages-oss - image: grafana/grafana-ci-deploy:1.2.7 + image: grafana/grafana-ci-deploy:1.3.0 commands: - printenv GCP_KEY | base64 -d > /tmp/gcpkey.json - ./bin/grabpl publish-packages --edition oss --gcp-key /tmp/gcpkey.json --build-id ${DRONE_BUILD_NUMBER} @@ -935,7 +935,7 @@ steps: - test-frontend - name: upload-packages - image: grafana/grafana-ci-deploy:1.2.7 + image: grafana/grafana-ci-deploy:1.3.0 commands: - ./bin/grabpl upload-packages --edition oss environment: @@ -948,7 +948,7 @@ steps: - postgres-integration-tests - name: publish-storybook - image: grafana/grafana-ci-deploy:1.2.7 + image: grafana/grafana-ci-deploy:1.3.0 commands: - printenv GCP_KEY | base64 -d > /tmp/gcpkey.json - gcloud auth activate-service-account --key-file=/tmp/gcpkey.json @@ -1326,7 +1326,7 @@ steps: - test-frontend - name: upload-packages - image: grafana/grafana-ci-deploy:1.2.7 + image: grafana/grafana-ci-deploy:1.3.0 commands: - ./bin/grabpl upload-packages --edition enterprise environment: @@ -1379,7 +1379,7 @@ steps: - end-to-end-tests-server-enterprise2 - name: upload-packages-enterprise2 - image: grafana/grafana-ci-deploy:1.2.7 + image: grafana/grafana-ci-deploy:1.3.0 commands: - ./bin/grabpl upload-packages --edition enterprise2 --packages-bucket grafana-downloads-enterprise2 environment: @@ -1508,7 +1508,7 @@ steps: DOCKERIZE_VERSION: 0.6.1 - name: publish-packages-oss - image: grafana/grafana-ci-deploy:1.2.7 + image: grafana/grafana-ci-deploy:1.3.0 commands: - printenv GCP_KEY | base64 -d > /tmp/gcpkey.json - ./bin/grabpl publish-packages --edition oss --gcp-key /tmp/gcpkey.json ${DRONE_TAG} @@ -1527,7 +1527,7 @@ steps: - initialize - name: publish-packages-enterprise - image: grafana/grafana-ci-deploy:1.2.7 + image: grafana/grafana-ci-deploy:1.3.0 commands: - printenv GCP_KEY | base64 -d > /tmp/gcpkey.json - ./bin/grabpl publish-packages --edition enterprise --gcp-key /tmp/gcpkey.json ${DRONE_TAG} @@ -1818,7 +1818,7 @@ steps: - test-frontend - name: upload-packages - image: grafana/grafana-ci-deploy:1.2.7 + image: grafana/grafana-ci-deploy:1.3.0 commands: - ./bin/grabpl upload-packages --edition oss --packages-bucket grafana-downloads-test environment: @@ -1831,7 +1831,7 @@ steps: - postgres-integration-tests - name: publish-storybook - image: grafana/grafana-ci-deploy:1.2.7 + image: grafana/grafana-ci-deploy:1.3.0 commands: - echo Testing release environment: @@ -2198,7 +2198,7 @@ steps: - test-frontend - name: upload-packages - image: grafana/grafana-ci-deploy:1.2.7 + image: grafana/grafana-ci-deploy:1.3.0 commands: - ./bin/grabpl upload-packages --edition enterprise --packages-bucket grafana-downloads-test environment: @@ -2251,7 +2251,7 @@ steps: - end-to-end-tests-server-enterprise2 - name: upload-packages-enterprise2 - image: grafana/grafana-ci-deploy:1.2.7 + image: grafana/grafana-ci-deploy:1.3.0 commands: - ./bin/grabpl upload-packages --edition enterprise2 --packages-bucket grafana-downloads-test environment: @@ -2380,7 +2380,7 @@ steps: DOCKERIZE_VERSION: 0.6.1 - name: publish-packages-oss - image: grafana/grafana-ci-deploy:1.2.7 + image: grafana/grafana-ci-deploy:1.3.0 commands: - printenv GCP_KEY | base64 -d > /tmp/gcpkey.json - ./bin/grabpl publish-packages --edition oss --gcp-key /tmp/gcpkey.json --deb-db-bucket grafana-testing-aptly-db --deb-repo-bucket grafana-testing-repo --packages-bucket grafana-downloads-test --rpm-repo-bucket grafana-testing-repo --simulate-release v7.3.0-test @@ -2399,7 +2399,7 @@ steps: - initialize - name: publish-packages-enterprise - image: grafana/grafana-ci-deploy:1.2.7 + image: grafana/grafana-ci-deploy:1.3.0 commands: - printenv GCP_KEY | base64 -d > /tmp/gcpkey.json - ./bin/grabpl publish-packages --edition enterprise --gcp-key /tmp/gcpkey.json --deb-db-bucket grafana-testing-aptly-db --deb-repo-bucket grafana-testing-repo --packages-bucket grafana-downloads-test --rpm-repo-bucket grafana-testing-repo --simulate-release v7.3.0-test @@ -2686,7 +2686,7 @@ steps: - test-frontend - name: upload-packages - image: grafana/grafana-ci-deploy:1.2.7 + image: grafana/grafana-ci-deploy:1.3.0 commands: - ./bin/grabpl upload-packages --edition oss environment: @@ -3044,7 +3044,7 @@ steps: - test-frontend - name: upload-packages - image: grafana/grafana-ci-deploy:1.2.7 + image: grafana/grafana-ci-deploy:1.3.0 commands: - ./bin/grabpl upload-packages --edition enterprise environment: @@ -3097,7 +3097,7 @@ steps: - end-to-end-tests-server-enterprise2 - name: upload-packages-enterprise2 - image: grafana/grafana-ci-deploy:1.2.7 + image: grafana/grafana-ci-deploy:1.3.0 commands: - ./bin/grabpl upload-packages --edition enterprise2 --packages-bucket grafana-downloads-enterprise2 environment: diff --git a/scripts/build/ci-deploy/Dockerfile b/scripts/build/ci-deploy/Dockerfile index 509317a5541..bb879efb674 100644 --- a/scripts/build/ci-deploy/Dockerfile +++ b/scripts/build/ci-deploy/Dockerfile @@ -1,4 +1,17 @@ -FROM cimg/go:1.15.5 +FROM debian:testing-20210111-slim + +# Use ARG so as not to persist environment variable in image +ARG GOVERSION=1.15.7 \ + GO_CHECKSUM=0d142143794721bb63ce6c8a6180c4062bcf8ef4715e7d6d6609f3a8282629b3 \ + DEBIAN_FRONTEND=noninteractive + +ENV PATH=/usr/local/go/bin:$PATH \ + GOPATH=/go + +RUN apt update && apt install -yq curl git make +RUN curl -fLO https://storage.googleapis.com/golang/go${GOVERSION}.linux-amd64.tar.gz && \ + echo "${GO_CHECKSUM} go${GOVERSION}.linux-amd64.tar.gz" | sha256sum --check --strict --status && \ + tar -xzf go${GOVERSION}.linux-amd64.tar.gz -C /usr/local RUN git clone https://github.com/aptly-dev/aptly $GOPATH/src/github.com/aptly-dev/aptly RUN cd $GOPATH/src/github.com/aptly-dev/aptly && \ @@ -6,27 +19,25 @@ RUN cd $GOPATH/src/github.com/aptly-dev/aptly && \ git reset --hard a64807efdaf5e380bfa878c71bc88eae10d62be1 && \ make install -FROM circleci/python:2.7-stretch-node +FROM debian:testing-20210111-slim -USER root +# Use ARG so as not to persist environment variable in image +ARG DEBIAN_FRONTEND=noninteractive \ + GOOGLE_SDK_VERSION=325.0.0 \ + GOOGLE_SDK_CHECKSUM=374f960c9f384f88b6fc190b268ceac5dcad777301390107af63782bfb5ecbc7 -ARG GOOGLE_SDK_VERSION=319.0.0 -ARG GOOGLE_SDK_CHECKSUM=28048af8fe83a1c80a37258d4e6c00edf22bc93edf570fb9bb6a42cca726d4c5 - -RUN apt-get install -yq python3-pip && pip3 install -U awscli crcmod && \ +RUN apt update && apt install -yq curl python3-pip && pip3 install -U awscli crcmod && \ curl -fLO https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-${GOOGLE_SDK_VERSION}-linux-x86_64.tar.gz && \ echo "${GOOGLE_SDK_CHECKSUM} google-cloud-sdk-${GOOGLE_SDK_VERSION}-linux-x86_64.tar.gz" | sha256sum --check --status && \ tar xzf google-cloud-sdk-${GOOGLE_SDK_VERSION}-linux-x86_64.tar.gz -C /opt && \ rm google-cloud-sdk-${GOOGLE_SDK_VERSION}-linux-x86_64.tar.gz && \ apt update && \ - apt install -y createrepo expect && \ + apt install -y createrepo-c expect && \ apt-get autoremove -y && \ rm -rf /var/lib/apt/lists/* && \ ln -s /opt/google-cloud-sdk/bin/gsutil /usr/bin/gsutil && \ ln -s /opt/google-cloud-sdk/bin/gcloud /usr/bin/gcloud && \ mkdir -p /deb-repo /rpm-repo && \ - chown circleci:circleci /deb-repo /rpm-repo + ln -s /usr/bin/createrepo_c /usr/bin/createrepo -COPY --from=0 /home/circleci/go/bin/aptly /usr/local/bin/aptly - -USER circleci +COPY --from=0 /go/bin/aptly /usr/local/bin/aptly diff --git a/scripts/build/ci-deploy/build-deploy.sh b/scripts/build/ci-deploy/build-deploy.sh index 53cacfc8fa0..e326aba3612 100755 --- a/scripts/build/ci-deploy/build-deploy.sh +++ b/scripts/build/ci-deploy/build-deploy.sh @@ -1,7 +1,7 @@ #!/bin/bash set -eo pipefail -_version="1.2.7" +_version="1.3.0" _tag="grafana/grafana-ci-deploy:${_version}" docker build -t $_tag . diff --git a/scripts/lib.star b/scripts/lib.star index a07d21d5347..c436db02e12 100644 --- a/scripts/lib.star +++ b/scripts/lib.star @@ -1,6 +1,6 @@ grabpl_version = '0.5.35' build_image = 'grafana/build-container:1.3.1' -publish_image = 'grafana/grafana-ci-deploy:1.2.7' +publish_image = 'grafana/grafana-ci-deploy:1.3.0' grafana_docker_image = 'grafana/drone-grafana-docker:0.3.2' alpine_image = 'alpine:3.12' windows_image = 'mcr.microsoft.com/windows:1809' From 4147c3b90715924a137ab182c7059128d9c6bc07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zolt=C3=A1n=20Bedi?= Date: Thu, 28 Jan 2021 11:32:02 +0100 Subject: [PATCH 26/41] Trace: trace to logs design update (#30637) * Add new icon to custom icons * Show button in span detail --- .../grafana-ui/src/components/Icon/custom/index.tsx | 13 +++++++++++++ .../grafana-ui/src/components/Logs/FieldLink.tsx | 9 ++++++--- packages/grafana-ui/src/types/icon.ts | 4 +++- .../src/TraceTimelineViewer/SpanDetail/index.tsx | 11 +++++++++-- .../src/TraceTimelineViewer/SpanDetailRow.tsx | 4 ++++ .../TraceTimelineViewer/VirtualizedTraceView.tsx | 7 ++++--- .../src/TraceTimelineViewer/types.tsx | 9 +++++++++ .../features/explore/TraceView/createSpanLink.tsx | 2 +- 8 files changed, 49 insertions(+), 10 deletions(-) diff --git a/packages/grafana-ui/src/components/Icon/custom/index.tsx b/packages/grafana-ui/src/components/Icon/custom/index.tsx index 7a3637e0094..a7ac22dd718 100644 --- a/packages/grafana-ui/src/components/Icon/custom/index.tsx +++ b/packages/grafana-ui/src/components/Icon/custom/index.tsx @@ -65,6 +65,18 @@ const InterpolationStepAfter: FC = ({ size, ...rest }) => { ); }; +export const Logs: FC = ({ size, ...rest }) => { + return ( + + + + ); +}; + const IconNotFound: FC = ({ size, ...rest }) => { return ; }; @@ -74,5 +86,6 @@ export const customIcons: Record> = { 'gf-interpolation-smooth': InterpolationSmooth, 'gf-interpolation-step-before': InterpolationStepBefore, 'gf-interpolation-step-after': InterpolationStepAfter, + 'gf-logs': Logs, notFoundDummy: IconNotFound, }; diff --git a/packages/grafana-ui/src/components/Logs/FieldLink.tsx b/packages/grafana-ui/src/components/Logs/FieldLink.tsx index b5c65440c11..116f2de2aa4 100644 --- a/packages/grafana-ui/src/components/Logs/FieldLink.tsx +++ b/packages/grafana-ui/src/components/Logs/FieldLink.tsx @@ -1,12 +1,13 @@ import { Field, LinkModel } from '@grafana/data'; import React from 'react'; -import { Button } from '..'; +import { ButtonProps, Button } from '../Button'; type FieldLinkProps = { link: LinkModel; + buttonProps?: ButtonProps; }; -export function FieldLink({ link }: FieldLinkProps) { +export function FieldLink({ link, buttonProps }: FieldLinkProps) { return ( - + ); } diff --git a/packages/grafana-ui/src/types/icon.ts b/packages/grafana-ui/src/types/icon.ts index b9e4d1bf469..72eead3f81c 100644 --- a/packages/grafana-ui/src/types/icon.ts +++ b/packages/grafana-ui/src/types/icon.ts @@ -125,7 +125,8 @@ export type IconName = | 'gf-interpolation-linear' | 'gf-interpolation-smooth' | 'gf-interpolation-step-before' - | 'gf-interpolation-step-after'; + | 'gf-interpolation-step-after' + | 'gf-logs'; export const getAvailableIcons = (): IconName[] => [ 'fa fa-spinner', @@ -249,4 +250,5 @@ export const getAvailableIcons = (): IconName[] => [ 'gf-interpolation-smooth', 'gf-interpolation-step-before', 'gf-interpolation-step-after', + 'gf-logs', ]; diff --git a/packages/jaeger-ui-components/src/TraceTimelineViewer/SpanDetail/index.tsx b/packages/jaeger-ui-components/src/TraceTimelineViewer/SpanDetail/index.tsx index 0619c226f35..f17bc030b43 100644 --- a/packages/jaeger-ui-components/src/TraceTimelineViewer/SpanDetail/index.tsx +++ b/packages/jaeger-ui-components/src/TraceTimelineViewer/SpanDetail/index.tsx @@ -30,7 +30,8 @@ import AccordianReferences from './AccordianReferences'; import { autoColor, createStyle, Theme, useTheme } from '../../Theme'; import { UIDivider } from '../../uiElementsContext'; import { ubFlex, ubFlexAuto, ubItemsCenter, ubM0, ubMb1, ubMy1, ubTxRightAlign } from '../../uberUtilityStyles'; -import { TextArea } from '@grafana/ui'; +import { FieldLink, TextArea } from '@grafana/ui'; +import { CreateSpanLink } from '../types'; const getStyles = createStyle((theme: Theme) => { return { @@ -115,6 +116,7 @@ type SpanDetailProps = { stackTracesToggle: (spanID: string) => void; referencesToggle: (spanID: string) => void; focusSpan: (uiFind: string) => void; + createSpanLink?: CreateSpanLink; }; export default function SpanDetail(props: SpanDetailProps) { @@ -131,6 +133,7 @@ export default function SpanDetail(props: SpanDetailProps) { stackTracesToggle, referencesToggle, focusSpan, + createSpanLink, } = props; const { isTagsOpen, @@ -171,13 +174,17 @@ export default function SpanDetail(props: SpanDetailProps) { ]; const deepLinkCopyText = `${window.location.origin}${window.location.pathname}?uiFind=${spanID}`; const styles = getStyles(useTheme()); + const link = createSpanLink?.(span); return (
-
+

{operationName}

+ {link ? ( + + ) : null}
diff --git a/packages/jaeger-ui-components/src/TraceTimelineViewer/SpanDetailRow.tsx b/packages/jaeger-ui-components/src/TraceTimelineViewer/SpanDetailRow.tsx index 7d4b2b7df79..05656198976 100644 --- a/packages/jaeger-ui-components/src/TraceTimelineViewer/SpanDetailRow.tsx +++ b/packages/jaeger-ui-components/src/TraceTimelineViewer/SpanDetailRow.tsx @@ -22,6 +22,7 @@ import TimelineRow from './TimelineRow'; import { autoColor, createStyle, Theme, withTheme } from '../Theme'; import { TraceLog, TraceSpan, TraceKeyValuePair, TraceLink } from '@grafana/data'; +import { CreateSpanLink } from './types'; const getStyles = createStyle((theme: Theme) => { return { @@ -85,6 +86,7 @@ type SpanDetailRowProps = { addHoverIndentGuideId: (spanID: string) => void; removeHoverIndentGuideId: (spanID: string) => void; theme: Theme; + createSpanLink?: CreateSpanLink; }; export class UnthemedSpanDetailRow extends React.PureComponent { @@ -116,6 +118,7 @@ export class UnthemedSpanDetailRow extends React.PureComponent
diff --git a/packages/jaeger-ui-components/src/TraceTimelineViewer/VirtualizedTraceView.tsx b/packages/jaeger-ui-components/src/TraceTimelineViewer/VirtualizedTraceView.tsx index 6e2e0b94f47..0104e3a4bd8 100644 --- a/packages/jaeger-ui-components/src/TraceTimelineViewer/VirtualizedTraceView.tsx +++ b/packages/jaeger-ui-components/src/TraceTimelineViewer/VirtualizedTraceView.tsx @@ -33,6 +33,7 @@ import { TraceLog, TraceSpan, Trace, TraceKeyValuePair, TraceLink } from '@grafa import TTraceTimeline from '../types/TTraceTimeline'; import { createStyle, Theme, withTheme } from '../Theme'; +import { CreateSpanLink } from './types'; type TExtractUiFindFromStateReturn = { uiFind: string | undefined; @@ -79,9 +80,7 @@ type TVirtualizedTraceViewOwnProps = { addHoverIndentGuideId: (spanID: string) => void; removeHoverIndentGuideId: (spanID: string) => void; theme: Theme; - createSpanLink?: ( - span: TraceSpan - ) => { href: string; onClick?: (e: React.MouseEvent) => void; content: React.ReactNode }; + createSpanLink?: CreateSpanLink; scrollElement?: Element; }; @@ -411,6 +410,7 @@ export class UnthemedVirtualizedTraceView extends React.Component
); diff --git a/packages/jaeger-ui-components/src/TraceTimelineViewer/types.tsx b/packages/jaeger-ui-components/src/TraceTimelineViewer/types.tsx index c427b0ecd3d..f7854cd275f 100644 --- a/packages/jaeger-ui-components/src/TraceTimelineViewer/types.tsx +++ b/packages/jaeger-ui-components/src/TraceTimelineViewer/types.tsx @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +import { TraceSpan } from '@grafana/data'; import { TNil } from '../types'; interface TimeCursorUpdate { @@ -51,3 +52,11 @@ export interface ViewRangeTime { export interface ViewRange { time: ViewRangeTime; } + +export type CreateSpanLink = ( + span: TraceSpan +) => { + href: string; + onClick?: (e: React.MouseEvent) => void; + content: React.ReactNode; +}; diff --git a/public/app/features/explore/TraceView/createSpanLink.tsx b/public/app/features/explore/TraceView/createSpanLink.tsx index b9d91b5c7ff..46133f20c35 100644 --- a/public/app/features/explore/TraceView/createSpanLink.tsx +++ b/public/app/features/explore/TraceView/createSpanLink.tsx @@ -56,7 +56,7 @@ export function createSpanLinkFactory(splitOpenFn: SplitOpen, traceToLogsOptions return { href: link.href, onClick: link.onClick, - content: , + content: , }; }; } From 1bdd3eb3dd096862bebf6af59d68ff344cf3693c Mon Sep 17 00:00:00 2001 From: David Date: Thu, 28 Jan 2021 11:36:17 +0100 Subject: [PATCH 27/41] Influx: Show all datapoints for dynamically windowed flux query (#30688) --- pkg/tsdb/influxdb/flux/executor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/tsdb/influxdb/flux/executor.go b/pkg/tsdb/influxdb/flux/executor.go index 18e54865536..256678e4f99 100644 --- a/pkg/tsdb/influxdb/flux/executor.go +++ b/pkg/tsdb/influxdb/flux/executor.go @@ -27,7 +27,7 @@ func executeQuery(ctx context.Context, query queryModel, runner queryRunner, max glog.Warn("Flux query failed", "err", err, "query", flux) dr.Error = err } else { - dr = readDataFrames(tables, int(float64(query.MaxDataPoints)*1.5), maxSeries) + dr = readDataFrames(tables, int(float64(query.MaxDataPoints)*2), maxSeries) } // Make sure there is at least one frame From 0a8eae2c12454485f79ac16779b400372673982a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Thu, 28 Jan 2021 12:36:28 +0100 Subject: [PATCH 28/41] PanelLibrary: changes casing of responses and adds meta property (#30668) * PanelLibrary: changes casing of responses and adds meta property * Chore: updates comments * Chore: updates after PR comments * Chore: changes casing of orgId --- pkg/services/librarypanels/database.go | 175 +++++++++++++++--- .../librarypanels/librarypanels_test.go | 19 +- pkg/services/librarypanels/models.go | 50 +++++ 3 files changed, 206 insertions(+), 38 deletions(-) diff --git a/pkg/services/librarypanels/database.go b/pkg/services/librarypanels/database.go index 89fdf277e13..b140b91e63c 100644 --- a/pkg/services/librarypanels/database.go +++ b/pkg/services/librarypanels/database.go @@ -5,17 +5,15 @@ import ( "fmt" "time" - "github.com/grafana/grafana/pkg/services/sqlstore/migrator" - - "github.com/grafana/grafana/pkg/util" - + "github.com/grafana/grafana/pkg/api/dtos" "github.com/grafana/grafana/pkg/models" - "github.com/grafana/grafana/pkg/services/sqlstore" + "github.com/grafana/grafana/pkg/services/sqlstore/migrator" + "github.com/grafana/grafana/pkg/util" ) // createLibraryPanel adds a Library Panel. -func (lps *LibraryPanelService) createLibraryPanel(c *models.ReqContext, cmd createLibraryPanelCommand) (LibraryPanel, error) { +func (lps *LibraryPanelService) createLibraryPanel(c *models.ReqContext, cmd createLibraryPanelCommand) (LibraryPanelDTO, error) { libraryPanel := LibraryPanel{ OrgID: c.SignedInUser.OrgId, FolderID: cmd.FolderID, @@ -39,7 +37,31 @@ func (lps *LibraryPanelService) createLibraryPanel(c *models.ReqContext, cmd cre return nil }) - return libraryPanel, err + dto := LibraryPanelDTO{ + ID: libraryPanel.ID, + OrgID: libraryPanel.OrgID, + FolderID: libraryPanel.FolderID, + UID: libraryPanel.UID, + Name: libraryPanel.Name, + Model: libraryPanel.Model, + Meta: LibraryPanelDTOMeta{ + CanEdit: true, + Created: libraryPanel.Created, + Updated: libraryPanel.Updated, + CreatedBy: LibraryPanelDTOMetaUser{ + ID: libraryPanel.CreatedBy, + Name: c.SignedInUser.Login, + AvatarUrl: dtos.GetGravatarUrl(c.SignedInUser.Email), + }, + UpdatedBy: LibraryPanelDTOMetaUser{ + ID: libraryPanel.UpdatedBy, + Name: c.SignedInUser.Login, + AvatarUrl: dtos.GetGravatarUrl(c.SignedInUser.Email), + }, + }, + } + + return dto, err } func connectDashboard(session *sqlstore.DBSession, dialect migrator.Dialect, user *models.SignedInUser, uid string, dashboardID int64) error { @@ -148,42 +170,90 @@ func (lps *LibraryPanelService) disconnectLibraryPanelsForDashboard(dashboardID }) } -func getLibraryPanel(session *sqlstore.DBSession, uid string, orgID int64) (LibraryPanel, error) { - libraryPanels := make([]LibraryPanel, 0) - session.Table("library_panel") - session.Where("uid=? AND org_id=?", uid, orgID) - err := session.Find(&libraryPanels) +func getLibraryPanel(session *sqlstore.DBSession, uid string, orgID int64) (LibraryPanelWithMeta, error) { + libraryPanels := make([]LibraryPanelWithMeta, 0) + sql := `SELECT + lp.id, lp.org_id, lp.folder_id, lp.uid, lp.name, lp.model, lp.created, lp.created_by, lp.updated, lp.updated_by + , 0 AS can_edit + , u1.login AS created_by_name + , u1.email AS created_by_email + , u2.login AS updated_by_name + , u2.email AS updated_by_email + FROM library_panel AS lp + LEFT JOIN user AS u1 ON lp.created_by = u1.id + LEFT JOIN user AS u2 ON lp.updated_by = u2.id + WHERE lp.uid=? AND lp.org_id=?` + + sess := session.SQL(sql, uid, orgID) + err := sess.Find(&libraryPanels) if err != nil { - return LibraryPanel{}, err + return LibraryPanelWithMeta{}, err } if len(libraryPanels) == 0 { - return LibraryPanel{}, errLibraryPanelNotFound + return LibraryPanelWithMeta{}, errLibraryPanelNotFound } if len(libraryPanels) > 1 { - return LibraryPanel{}, fmt.Errorf("found %d panels, while expecting at most one", len(libraryPanels)) + return LibraryPanelWithMeta{}, fmt.Errorf("found %d panels, while expecting at most one", len(libraryPanels)) } return libraryPanels[0], nil } // getLibraryPanel gets a Library Panel. -func (lps *LibraryPanelService) getLibraryPanel(c *models.ReqContext, uid string) (LibraryPanel, error) { - var libraryPanel LibraryPanel +func (lps *LibraryPanelService) getLibraryPanel(c *models.ReqContext, uid string) (LibraryPanelDTO, error) { + var libraryPanel LibraryPanelWithMeta err := lps.SQLStore.WithDbSession(context.Background(), func(session *sqlstore.DBSession) error { var err error libraryPanel, err = getLibraryPanel(session, uid, c.SignedInUser.OrgId) return err }) - return libraryPanel, err + dto := LibraryPanelDTO{ + ID: libraryPanel.ID, + OrgID: libraryPanel.OrgID, + FolderID: libraryPanel.FolderID, + UID: libraryPanel.UID, + Name: libraryPanel.Name, + Model: libraryPanel.Model, + Meta: LibraryPanelDTOMeta{ + CanEdit: true, + Created: libraryPanel.Created, + Updated: libraryPanel.Updated, + CreatedBy: LibraryPanelDTOMetaUser{ + ID: libraryPanel.CreatedBy, + Name: libraryPanel.CreatedByName, + AvatarUrl: dtos.GetGravatarUrl(libraryPanel.CreatedByEmail), + }, + UpdatedBy: LibraryPanelDTOMetaUser{ + ID: libraryPanel.UpdatedBy, + Name: libraryPanel.UpdatedByName, + AvatarUrl: dtos.GetGravatarUrl(libraryPanel.UpdatedByEmail), + }, + }, + } + + return dto, err } // getAllLibraryPanels gets all library panels. -func (lps *LibraryPanelService) getAllLibraryPanels(c *models.ReqContext) ([]LibraryPanel, error) { +func (lps *LibraryPanelService) getAllLibraryPanels(c *models.ReqContext) ([]LibraryPanelDTO, error) { orgID := c.SignedInUser.OrgId - libraryPanels := make([]LibraryPanel, 0) + libraryPanels := make([]LibraryPanelWithMeta, 0) err := lps.SQLStore.WithDbSession(context.Background(), func(session *sqlstore.DBSession) error { - err := session.SQL("SELECT * FROM library_panel WHERE org_id=?", orgID).Find(&libraryPanels) + sql := `SELECT + lp.id, lp.org_id, lp.folder_id, lp.uid, lp.name, lp.model, lp.created, lp.created_by, lp.updated, lp.updated_by + , 0 AS can_edit + , u1.login AS created_by_name + , u1.email AS created_by_email + , u2.login AS updated_by_name + , u2.email AS updated_by_email + FROM library_panel AS lp + LEFT JOIN user AS u1 ON lp.created_by = u1.id + LEFT JOIN user AS u2 ON lp.updated_by = u2.id + WHERE lp.org_id=?` + + sess := session.SQL(sql, orgID) + err := sess.Find(&libraryPanels) if err != nil { return err } @@ -191,7 +261,34 @@ func (lps *LibraryPanelService) getAllLibraryPanels(c *models.ReqContext) ([]Lib return nil }) - return libraryPanels, err + retDTOs := make([]LibraryPanelDTO, 0) + for _, panel := range libraryPanels { + retDTOs = append(retDTOs, LibraryPanelDTO{ + ID: panel.ID, + OrgID: panel.OrgID, + FolderID: panel.FolderID, + UID: panel.UID, + Name: panel.Name, + Model: panel.Model, + Meta: LibraryPanelDTOMeta{ + CanEdit: true, + Created: panel.Created, + Updated: panel.Updated, + CreatedBy: LibraryPanelDTOMetaUser{ + ID: panel.CreatedBy, + Name: panel.CreatedByName, + AvatarUrl: dtos.GetGravatarUrl(panel.CreatedByEmail), + }, + UpdatedBy: LibraryPanelDTOMetaUser{ + ID: panel.UpdatedBy, + Name: panel.UpdatedByName, + AvatarUrl: dtos.GetGravatarUrl(panel.UpdatedByEmail), + }, + }, + }) + } + + return retDTOs, err } // getConnectedDashboards gets all dashboards connected to a Library Panel. @@ -225,7 +322,7 @@ func (lps *LibraryPanelService) getLibraryPanelsForDashboardID(dashboardID int64 libraryPanelMap := make(map[string]LibraryPanel) err := lps.SQLStore.WithDbSession(context.Background(), func(session *sqlstore.DBSession) error { sql := `SELECT - lp.id, lp.org_id, lp.folder_id, lp.uid, lp.name, lp.model, lp.created, lp.created_by, lp.updated, updated_by + lp.id, lp.org_id, lp.folder_id, lp.uid, lp.name, lp.model, lp.created, lp.created_by, lp.updated, lp.updated_by FROM library_panel_dashboard AS lpd INNER JOIN @@ -249,15 +346,15 @@ func (lps *LibraryPanelService) getLibraryPanelsForDashboardID(dashboardID int64 } // patchLibraryPanel updates a Library Panel. -func (lps *LibraryPanelService) patchLibraryPanel(c *models.ReqContext, cmd patchLibraryPanelCommand, uid string) (LibraryPanel, error) { - var libraryPanel LibraryPanel +func (lps *LibraryPanelService) patchLibraryPanel(c *models.ReqContext, cmd patchLibraryPanelCommand, uid string) (LibraryPanelDTO, error) { + var dto LibraryPanelDTO err := lps.SQLStore.WithTransactionalDbSession(context.Background(), func(session *sqlstore.DBSession) error { panelInDB, err := getLibraryPanel(session, uid, c.SignedInUser.OrgId) if err != nil { return err } - libraryPanel = LibraryPanel{ + var libraryPanel = LibraryPanel{ ID: panelInDB.ID, OrgID: c.SignedInUser.OrgId, FolderID: cmd.FolderID, @@ -289,8 +386,32 @@ func (lps *LibraryPanelService) patchLibraryPanel(c *models.ReqContext, cmd patc return errLibraryPanelNotFound } + dto = LibraryPanelDTO{ + ID: libraryPanel.ID, + OrgID: libraryPanel.OrgID, + FolderID: libraryPanel.FolderID, + UID: libraryPanel.UID, + Name: libraryPanel.Name, + Model: libraryPanel.Model, + Meta: LibraryPanelDTOMeta{ + CanEdit: true, + Created: libraryPanel.Created, + Updated: libraryPanel.Updated, + CreatedBy: LibraryPanelDTOMetaUser{ + ID: libraryPanel.CreatedBy, + Name: panelInDB.CreatedByName, + AvatarUrl: dtos.GetGravatarUrl(panelInDB.CreatedByEmail), + }, + UpdatedBy: LibraryPanelDTOMetaUser{ + ID: libraryPanel.UpdatedBy, + Name: c.SignedInUser.Login, + AvatarUrl: dtos.GetGravatarUrl(c.SignedInUser.Email), + }, + }, + } + return nil }) - return libraryPanel, err + return dto, err } diff --git a/pkg/services/librarypanels/librarypanels_test.go b/pkg/services/librarypanels/librarypanels_test.go index 867a2296255..bd9eebc9442 100644 --- a/pkg/services/librarypanels/librarypanels_test.go +++ b/pkg/services/librarypanels/librarypanels_test.go @@ -449,7 +449,7 @@ func TestPatchLibraryPanel(t *testing.T) { var result libraryPanelResult err = json.Unmarshal(response.Body(), &result) require.NoError(t, err) - existing.Result.UpdatedBy = int64(2) + existing.Result.Meta.UpdatedBy.ID = int64(2) if diff := cmp.Diff(existing.Result, result.Result, getCompareOptions()...); diff != "" { t.Fatalf("Result mismatch (-want +got):\n%s", diff) } @@ -1092,16 +1092,13 @@ func TestDisconnectLibraryPanelsForDashboard(t *testing.T) { } type libraryPanel struct { - ID int64 `json:"id"` - OrgID int64 `json:"orgId"` - FolderID int64 `json:"folderId"` - UID string `json:"uid"` - Name string `json:"name"` - Model map[string]interface{} `json:"model"` - Created time.Time `json:"created"` - Updated time.Time `json:"updated"` - CreatedBy int64 `json:"createdBy"` - UpdatedBy int64 `json:"updatedBy"` + ID int64 `json:"id"` + OrgID int64 `json:"orgId"` + FolderID int64 `json:"folderId"` + UID string `json:"uid"` + Name string `json:"name"` + Model map[string]interface{} `json:"model"` + Meta LibraryPanelDTOMeta `json:"meta"` } type libraryPanelResult struct { diff --git a/pkg/services/librarypanels/models.go b/pkg/services/librarypanels/models.go index 1482db8ba8d..b998b8dc3f7 100644 --- a/pkg/services/librarypanels/models.go +++ b/pkg/services/librarypanels/models.go @@ -22,6 +22,56 @@ type LibraryPanel struct { UpdatedBy int64 } +// LibraryPanelWithMeta is the model used to retrieve library panels with additional meta information. +type LibraryPanelWithMeta struct { + ID int64 `xorm:"pk autoincr 'id'"` + OrgID int64 `xorm:"org_id"` + FolderID int64 `xorm:"folder_id"` + UID string `xorm:"uid"` + Name string + Model json.RawMessage + + Created time.Time + Updated time.Time + + CanEdit bool + CreatedBy int64 + UpdatedBy int64 + CreatedByName string + CreatedByEmail string + UpdatedByName string + UpdatedByEmail string +} + +// LibraryPanelDTO is the frontend DTO for library panels. +type LibraryPanelDTO struct { + ID int64 `json:"id"` + OrgID int64 `json:"orgId"` + FolderID int64 `json:"folderId"` + UID string `json:"uid"` + Name string `json:"name"` + Model json.RawMessage `json:"model"` + Meta LibraryPanelDTOMeta `json:"meta"` +} + +// LibraryPanelDTOMeta is the meta information for LibraryPanelDTO. +type LibraryPanelDTOMeta struct { + CanEdit bool `json:"canEdit"` + + Created time.Time `json:"created"` + Updated time.Time `json:"updated"` + + CreatedBy LibraryPanelDTOMetaUser `json:"createdBy"` + UpdatedBy LibraryPanelDTOMetaUser `json:"updatedBy"` +} + +// LibraryPanelDTOMetaUser is the meta information for user that creates/changes the library panel. +type LibraryPanelDTOMetaUser struct { + ID int64 `json:"id"` + Name string `json:"name"` + AvatarUrl string `json:"avatarUrl"` +} + // libraryPanelDashboard is the model for library panel connections. type libraryPanelDashboard struct { ID int64 `xorm:"pk autoincr 'id'"` From af6893e41dc1a3e633ad30d2b6e4df9a9f6a0db7 Mon Sep 17 00:00:00 2001 From: Fabien Wernli Date: Thu, 28 Jan 2021 13:35:49 +0100 Subject: [PATCH 29/41] Fix documentation for streaming data sources (#30704) The added code is now mandatory since 7.4.x See https://github.com/grafana/grafana/issues/30686 --- .../plugins/build-a-streaming-data-source-plugin.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/sources/developers/plugins/build-a-streaming-data-source-plugin.md b/docs/sources/developers/plugins/build-a-streaming-data-source-plugin.md index ec9126d5555..c68e5dfdd76 100644 --- a/docs/sources/developers/plugins/build-a-streaming-data-source-plugin.md +++ b/docs/sources/developers/plugins/build-a-streaming-data-source-plugin.md @@ -75,6 +75,10 @@ Grafana uses [RxJS](https://rxjs.dev/) to continuously send data from a data sou 1. Use `subscriber.next()` to send the updated data frame whenever you receive new updates. + ```ts + import { LoadingState } from '@grafana/data'; + ``` + ```ts const intervalId = setInterval(() => { frame.add({ time: Date.now(), value: Math.random() }); @@ -82,6 +86,7 @@ Grafana uses [RxJS](https://rxjs.dev/) to continuously send data from a data sou subscriber.next({ data: [frame], key: query.refId, + state: LoadingState.Streaming, }); }, 500); From 78433032abe35a7bbc1b6e1d2052b87b1c51c997 Mon Sep 17 00:00:00 2001 From: Ivana Huckova <30407135+ivanahuckova@users.noreply.github.com> Date: Thu, 28 Jan 2021 13:58:02 +0100 Subject: [PATCH 30/41] Use connected GraphNG in Explore (#30707) --- public/app/features/explore/ExploreGraphNGPanel.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/public/app/features/explore/ExploreGraphNGPanel.tsx b/public/app/features/explore/ExploreGraphNGPanel.tsx index f914d22ffa7..7c9ac428af1 100644 --- a/public/app/features/explore/ExploreGraphNGPanel.tsx +++ b/public/app/features/explore/ExploreGraphNGPanel.tsx @@ -65,6 +65,7 @@ export function ExploreGraphNGPanel({ drawStyle: DrawStyle.Line, fillOpacity: 0, pointSize: 5, + spanNulls: true, }, }, overrides: [], From e36b035c057ce9158d325d8a15b5623a910aef8b Mon Sep 17 00:00:00 2001 From: Alex Khomenko Date: Thu, 28 Jan 2021 16:57:57 +0200 Subject: [PATCH 31/41] DashboardPicker: switch to promise-based debounce, return dashboard UID (#30706) * Use uid in dashboard picker * Set both id and uid from picker * Use debounce-promise * Simplify logic * Use exact package versions --- package.json | 2 ++ .../core/components/Select/DashboardPicker.tsx | 18 ++++++------------ yarn.lock | 10 ++++++++++ 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index cb546c3b9f6..71242a47f8b 100644 --- a/package.json +++ b/package.json @@ -89,6 +89,7 @@ "@types/d3": "5.7.2", "@types/d3-force": "^2.1.0", "@types/d3-scale-chromatic": "1.3.1", + "@types/debounce-promise": "3.1.3", "@types/enzyme": "3.10.5", "@types/enzyme-adapter-react-16": "1.0.6", "@types/file-saver": "2.0.1", @@ -234,6 +235,7 @@ "d3-force": "^2.1.1", "d3-scale-chromatic": "1.5.0", "dangerously-set-html-content": "1.0.6", + "debounce-promise": "3.1.2", "emotion": "10.0.27", "eventemitter3": "4.0.0", "fast-text-encoding": "^1.0.0", diff --git a/public/app/core/components/Select/DashboardPicker.tsx b/public/app/core/components/Select/DashboardPicker.tsx index 529f7f2cb4a..f8735d78e9f 100644 --- a/public/app/core/components/Select/DashboardPicker.tsx +++ b/public/app/core/components/Select/DashboardPicker.tsx @@ -1,6 +1,5 @@ import React, { FC } from 'react'; -import { debounce } from 'lodash'; -import { useAsyncFn } from 'react-use'; +import debounce from 'debounce-promise'; import { SelectableValue } from '@grafana/data'; import { AsyncSelect } from '@grafana/ui'; import { backendSrv } from 'app/core/services/backend_srv'; @@ -9,7 +8,7 @@ import { DashboardDTO } from 'app/types'; export interface Props { onSelected: (dashboard: DashboardDTO) => void; - currentDashboard?: SelectableValue; + currentDashboard?: SelectableValue; width?: number; isClearable?: boolean; invalid?: boolean; @@ -20,8 +19,9 @@ const getDashboards = (query = '') => { return backendSrv.search({ type: 'dash-db', query }).then((result: DashboardSearchHit[]) => { return result.map((item: DashboardSearchHit) => ({ id: item.id, + uid: item.uid, value: item.id, - label: `${item.folderTitle ? item.folderTitle : 'General'}/${item.title}`, + label: `${item?.folderTitle ?? 'General'}/${item.title}`, })); }); }; @@ -34,20 +34,14 @@ export const DashboardPicker: FC = ({ invalid, disabled, }) => { - const debouncedSearch = debounce(getDashboards, 300, { - leading: true, - trailing: true, - }); - - const [state, searchDashboards] = useAsyncFn(debouncedSearch, []); + const debouncedSearch = debounce(getDashboards, 300); return ( Date: Thu, 28 Jan 2021 11:37:14 -0500 Subject: [PATCH 32/41] Added entry for web server. (#30715) --- contribute/style-guides/documentation-style-guide.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/contribute/style-guides/documentation-style-guide.md b/contribute/style-guides/documentation-style-guide.md index 115856cef3c..a12ff83ef75 100644 --- a/contribute/style-guides/documentation-style-guide.md +++ b/contribute/style-guides/documentation-style-guide.md @@ -303,6 +303,13 @@ When referencing the Prometheus data source exporters, always use "node_exporter **Correct:** node_exporter, windows_exporter **Incorrect:** Node Exporter, node exporter, Windows Exporter, Windows exporter, windows exporter. +#### web server + +Two words, not one. + +**Correct:** webserver +**Incorrect:** web server + ### MS SQL Server Always use "MS SQL" when referring to MS SQL Server application. From 1c73ea17318430fd1eb58675f3ec82a9419cbbea Mon Sep 17 00:00:00 2001 From: Divyam Bhasin Date: Thu, 28 Jan 2021 12:27:28 -0500 Subject: [PATCH 33/41] Dashboard: Top Share URL icon should share panel URL when on viewPanel page (#30000) --- public/app/features/dashboard/components/DashNav/DashNav.tsx | 2 +- public/app/features/dashboard/components/ShareModal/utils.ts | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/public/app/features/dashboard/components/DashNav/DashNav.tsx b/public/app/features/dashboard/components/DashNav/DashNav.tsx index 083cd91d67c..645fcb71d89 100644 --- a/public/app/features/dashboard/components/DashNav/DashNav.tsx +++ b/public/app/features/dashboard/components/DashNav/DashNav.tsx @@ -159,7 +159,7 @@ class DashNav extends PureComponent { {({ showModal, hideModal }) => ( { diff --git a/public/app/features/dashboard/components/ShareModal/utils.ts b/public/app/features/dashboard/components/ShareModal/utils.ts index 86d14c8b7ca..51569ccaac4 100644 --- a/public/app/features/dashboard/components/ShareModal/utils.ts +++ b/public/app/features/dashboard/components/ShareModal/utils.ts @@ -22,8 +22,6 @@ export function buildParams(useCurrentTimeRange: boolean, selectedTheme?: string if (panel && !params.editPanel) { params.viewPanel = panel.id; - } else { - delete params.viewPanel; } return params; From 69a2279bf6a1ec9b517fd502d407c7442155ca8c Mon Sep 17 00:00:00 2001 From: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> Date: Thu, 28 Jan 2021 13:24:59 -0500 Subject: [PATCH 34/41] Deleted menu.yaml file (#30717) --- docs/sources/menu.yaml | 565 ----------------------------------------- 1 file changed, 565 deletions(-) delete mode 100644 docs/sources/menu.yaml diff --git a/docs/sources/menu.yaml b/docs/sources/menu.yaml deleted file mode 100644 index 6580a26bf12..00000000000 --- a/docs/sources/menu.yaml +++ /dev/null @@ -1,565 +0,0 @@ -- name: Getting started - link: /getting-started/ - children: - - name: With Grafana - link: /getting-started/getting-started/ - - name: With Grafana and Prometheus - link: /getting-started/getting-started-prometheus/ - - name: Intro to time series - link: /getting-started/timeseries/ - - name: Time series dimensions - link: /getting-started/timeseries-dimensions/ - - name: Intro to histograms - link: /getting-started/intro-histograms/ - - name: Observability strategies - link: /getting-started/strategies/ - - name: Glossary - link: /getting-started/glossary/ -- name: Best practices - link: /best-practices/ - children: - - name: Best practices for creating dashboards - link: /best-practices/best-practices-for-creating-dashboards/ - - name: Best practices for managing dashboards - link: /best-practices/best-practices-for-managing-dashboards/ - - name: Observability strategies - link: /best-practices/common-observability-strategies/ - - name: Dashboard management maturity model - link: /best-practices/dashboard-management-maturity-levels/ -- name: Installation - link: /installation/ - children: - - name: Installation - link: /installation/installation/ - - name: Requirements - link: /installation/requirements/ - - name: Install on Ubuntu/Debian - link: /installation/debian/ - - name: Install on Centos/RedHat/SUSE - link: /installation/rpm/ - - name: Install on Windows - link: /installation/windows/ - - name: Install on macOS - link: /installation/mac/ - - name: Run Docker image - link: /installation/docker/ - - name: Upgrade Grafana - link: /installation/upgrading/ -- name: Administration - link: /administration/ - children: - - name: Administration tasks - link: /administration/ - - name: Change password - link: /administration/change-your-password/ - - name: Change preferences - link: /administration/preferences/ - - name: Configuration - link: /administration/configuration/ - - name: View server settings - link: /administration/view-server-settings/ - - name: Configure Docker image - link: /administration/configure-docker/ - - name: Security - link: /administration/security/ - - name: Authentication - link: /auth/ - children: - - link: /auth/overview/ - name: Overview - - link: /auth/grafana/ - name: Grafana Authentication - - link: /auth/auth-proxy/ - name: Auth Proxy - - link: /auth/ldap/ - name: LDAP - - link: /auth/enhanced_ldap/ - name: Enhanced LDAP - - link: /auth/generic-oauth/ - name: Generic OAuth - - link: /auth/google/ - name: Google - - link: /auth/azuread/ - name: Azure AD - - link: /auth/github/ - name: GitHub - - link: /auth/gitlab/ - name: GitLab - - link: /auth/okta/ - name: Okta - - link: /auth/saml/ - name: SAML - - link: /auth/team-sync/ - name: Team Sync - - name: Permissions - link: /permissions/ - children: - - link: /permissions/ - name: Overview - - link: /permissions/organization_roles/ - name: Organization Roles - - link: /permissions/dashboard_folder_permissions/ - name: Dashboard and Folder - - link: /permissions/datasource_permissions/ - name: Data source - - name: Provisioning - link: /administration/provisioning/ - - name: Grafana CLI - link: /administration/cli/ - - name: Internal metrics - link: /administration/metrics/ - - name: View server stats - link: /administration/view-server-stats/ - - name: Jaeger instrumentation - link: /administration/jaeger-instrumentation/ - - name: Set up Grafana for high availability - link: /administration/set-up-for-high-availability/ - - name: Change home dashboard - link: /administration/change-home-dashboard/ -- name: Manage users - link: /manage-users - children: - - link: /manage-users/ - name: Overview - - link: /manage-users/add-or-remove-user/ - name: Add or remove a user - - link: /manage-users/enable-or-disable-user/ - name: Enable or disable a user - - link: /manage-users/create-or-remove-team/ - name: Create or remove a team - - link: /manage-users/add-or-remove-user-from-team/ - name: Add or remove user from team -- name: Data sources - link: /datasources/ - children: - - link: /datasources/add-a-data-source/ - name: Add data source - - link: /datasources/cloudwatch/ - name: AWS Cloudwatch - - link: /datasources/azuremonitor/ - name: Azure Monitor - - link: /datasources/elasticsearch/ - name: Elasticsearch - - link: /datasources/cloudmonitoring/ - name: Google Cloud Monitoring - - link: /datasources/graphite/ - name: Graphite - - link: /datasources/influxdb/ - name: InfluxDB - - link: /datasources/jaeger/ - name: Jaeger - - link: /datasources/loki/ - name: Loki - - link: /datasources/mssql/ - name: Microsoft SQL Server - - link: /datasources/mysql/ - name: MySQL - - link: /datasources/opentsdb/ - name: OpenTSDB - - link: /datasources/postgres/ - name: PostgreSQL - - link: /datasources/prometheus/ - name: Prometheus - - link: /datasources/tempo/ - name: Tempo - - link: /datasources/testdata/ - name: TestData DB - - link: /datasources/zipkin/ - name: Zipkin -- name: Panels - link: /panels/ - children: - - link: /panels/panels-overview/ - name: Overview - - link: /panels/add-a-panel/ - name: Add panel - - link: /panels/queries/ - name: Queries - - link: /panels/share-query-results/ - name: Share query results - - link: /panels/transformations/ - name: Transformations - children: - - link: /panels/transformations/ - name: Overview - - link: /panels/transformations/apply-transformations/ - name: Apply transformations - - link: /panels/transformations/types-options/ - name: Transformation types and options - - link: /panels/field-options/ - name: Field options and overrides - children: - - link: /panels/field-options/ - name: Overview - - link: /panels/field-options/configure-all-fields/ - name: Configure all fields - - link: /panels/field-options/configure-specific-fields/ - name: Configure specific fields - - link: /panels/field-options/standard-field-options/ - name: Standard field options - - link: /panels/panel-editor/ - name: Panel editor - - name: Visualizations - link: /panels/visualizations/ - children: - - link: /panels/visualizations/alert-list-panel/ - name: Alert list - - link: /panels/visualizations/bar-gauge-panel/ - name: Bar gauge - - link: /panels/visualizations/dashboard-list-panel/ - name: Dashboard list - - link: /panels/visualizations/gauge-panel/ - name: Gauge - - link: /panels/visualizations/graph-panel/ - name: Graph - - link: /panels/visualizations/heatmap/ - name: Heatmap - - link: /panels/visualizations/logs-panel/ - name: Logs - - link: /panels/visualizations/news-panel/ - name: News - - link: /panels/visualizations/stat-panel/ - name: Stat - - link: /panels/visualizations/table-panel/ - name: Table - children: - - name: Overview - link: /panels/visualizations/table/ - - link: /panels/visualizations/table/table-field-options/ - name: Table field options - - link: /panels/visualizations/table/filter-table-columns/ - name: Filter table columns - - link: /panels/visualizations/text-panel/ - name: Text - - link: /panels/thresholds/ - name: Thresholds - - link: /panels/inspect-panel/ - name: Inspect panel - - link: /panels/calculations-list/ - name: Calculations list -- name: Dashboards - link: /dashboards/ - children: - - link: /dashboards/ - name: Overview - - link: /dashboards/annotations/ - name: Annotations - - link: /dashboards/dashboard_folders/ - name: Folders - - link: /dashboards/playlist/ - name: Playlist - - link: /dashboards/search/ - name: Search - - link: /dashboards/share-dashboard/ - name: Share dashboard - - link: /dashboards/share-panel/ - name: Share a panel - - link: /dashboards/time-range-controls/ - name: Time range controls - - link: /dashboards/export-import/ - name: Export and import - - link: /dashboards/dashboard_history/ - name: Dashboard version history - - name: Keyboard shortcuts - link: /dashboards/shortcuts/ - - name: Reporting - link: /dashboards/reporting/ - - link: /dashboards/json-model/ - name: JSON model - - link: /dashboards/scripted-dashboards/ - name: Scripted dashboards -- name: Explore - link: /explore/ -- name: Alerting - link: /alerting/ - children: - - link: /alerting/alerts-overview/ - name: Overview - - link: /alerting/notifications/ - name: Alert notifications - - link: /alerting/create-alerts/ - name: Create alerts - - link: /alerting/view-alerts/ - name: View alerts - - link: /alerting/pause-an-alert-rule/ - name: Pause alert rule - - link: /alerting/troubleshoot-alerts/ - name: Troubleshoot alerts -- name: Image rendering - link: /administration/image_rendering/ -- name: Linking - link: /linking/ - children: - - name: Overview - link: /linking/linking-overview/ - - name: Dashboard links - link: /linking/dashboard-links/ - - name: Panel links - link: /linking/panel-links/ - - name: Data links - link: /linking/data-links/ - - link: /linking/data-link-variables/ - name: Data link variables -- name: Templates and variables - link: /variables/ - children: - - link: /variables/syntax/ - name: Variables syntax - - link: /variables/variable-examples/ - name: Variable examples - - name: Variable types - link: /variables/variable-types/ - children: - - link: /variables/variable-types/add-query-variable/ - name: Add query variable - - link: /variables/variable-types/add-custom-variable/ - name: Add custom variable - - link: /variables/variable-types/add-text-box-variable/ - name: Add text box variable - - link: /variables/variable-types/add-constant-variable/ - name: Add constant variable - - link: /variables/variable-types/add-data-source-variable/ - name: Add data source variable - - link: /variables/variable-types/add-interval-variable/ - name: Add interval variable - - link: /variables/variable-types/add-ad-hoc-filters/ - name: Add ad hoc filters - - link: /variables/variable-types/chained-variables/ - name: Chained variables - - link: /variables/variable-types/global-variables/ - name: Global variables - - name: Selection options - link: /variables/variable-selection-options/ - - name: Value groups/tags - link: /variables/variable-value-tags/ - - link: /variables/advanced-variable-format-options/ - name: Advanced variable formats - - link: /variables/formatting-multi-value-variables/ - name: Formatting multi-value variables - - link: /variables/filter-variables-with-regex/ - name: Filter variables with regex - - link: /variables/repeat-panels-or-rows/ - name: Repeat panels or rows -- name: What's new in Grafana - link: /whatsnew/ - children: - - name: Version 7.3 - link: /whatsnew/whats-new-in-v7-3/ - - name: Version 7.2 - link: /whatsnew/whats-new-in-v7-2/ - - name: Version 7.1 - link: /whatsnew/whats-new-in-v7-1/ - - name: Version 7.0 - link: /whatsnew/whats-new-in-v7-0/ - - name: Version 6.7 - link: /whatsnew/whats-new-in-v6-7/ - - name: Version 6.6 - link: /whatsnew/whats-new-in-v6-6/ - - name: Version 6.5 - link: /whatsnew/whats-new-in-v6-5/ - - name: Version 6.4 - link: /whatsnew/whats-new-in-v6-4/ - - name: Version 6.3 - link: /whatsnew/whats-new-in-v6-3/ - - name: Version 6.2 - link: /whatsnew/whats-new-in-v6-2/ - - name: Version 6.1 - link: /whatsnew/whats-new-in-v6-1/ - - name: Version 6.0 - link: /whatsnew/whats-new-in-v6-0/ - - name: Old versions - link: /whatsnew/ - children: - - name: Version 5.4 - link: /whatsnew/whats-new-in-v5-4/ - - name: Version 5.3 - link: /whatsnew/whats-new-in-v5-3/ - - name: Version 5.2 - link: /whatsnew/whats-new-in-v5-2/ - - name: Version 5.1 - link: /whatsnew/whats-new-in-v5-1/ - - name: Version 5.0 - link: /whatsnew/whats-new-in-v5/ - - name: Version 4.6 - link: /whatsnew/whats-new-in-v4-6/ - - name: Version 4.5 - link: /whatsnew/whats-new-in-v4-5/ - - name: Version 4.4 - link: /whatsnew/whats-new-in-v4-4/ - - name: Version 4.3 - link: /whatsnew/whats-new-in-v4-3/ - - name: Version 4.2 - link: /whatsnew/whats-new-in-v4-2/ - - name: Version 4.1 - link: /whatsnew/whats-new-in-v4-1/ - - name: Version 4.0 - link: /whatsnew/whats-new-in-v4/ - - name: Version 3.1 - link: /whatsnew/whats-new-in-v3-1/ - - name: Version 3.0 - link: /whatsnew/whats-new-in-v3/ -- name: Grafana Enterprise - link: /enterprise/ - children: - - name: Overview - link: /enterprise/ - - name: Activate license - link: /enterprise/activate-license/ - - name: Auditing - link: /enterprise/auditing/ - - name: Configuration - link: /enterprise/enterprise-configuration/ - - name: Data source permissions - link: /enterprise/datasource_permissions/ - - name: Enhanced LDAP - link: /enterprise/enhanced_ldap/ - - name: Reporting - link: /enterprise/reporting/ - - name: Export dashboard as PDF - link: /enterprise/export-pdf/ - - name: SAML authentication - link: /enterprise/saml/ - - name: Team sync - link: /enterprise/team-sync/ - - name: White labeling - link: /enterprise/white-labeling/ - - name: Usage insights - link: /enterprise/usage-insights/ - - name: Vault integration - link: /enterprise/vault/ - - name: License expiration - link: /enterprise/license-expiration/ -- name: Plugins - link: /plugins/ - children: - - name: Overview - link: /plugins/ - - name: Install plugins - link: /plugins/installation/ - - name: Plugin signatures - link: /plugins/plugin-signatures/ -- name: HTTP APIs - link: /http_api/ - children: - - name: API Authentication - link: /http_api/auth/ - - name: Create API Tokens and Dashboards for a Specific Organization - link: /http_api/create-api-tokens-for-org/ - - name: cURL examples - link: /http_api/curl-examples/ - - name: Admin API - link: /http_api/admin/ - - name: Alerting API - link: /http_api/alerting/ - - name: Alerting Notifications API - link: /http_api/alerting_notification_channels/ - - name: Annotations API - link: /http_api/annotations/ - - name: Dashboard API - link: /http_api/dashboard/ - - name: Dashboard Permissions API - link: /http_api/dashboard_permissions/ - - name: Dashboard Versions API - link: /http_api/dashboard_versions/ - - name: Data Source API - link: /http_api/data_source/ - - name: Data source Permissions API - link: /http_api/datasource_permissions/ - - name: External Group Sync API - link: /http_api/external_group_sync/ - - name: Folder API - link: /http_api/folder/ - - name: Folder Permissions API - link: /http_api/folder_permissions/ - - name: Folder/Dashboard Search API - link: /http_api/folder_dashboard_search/ - - name: Organization API - link: /http_api/org/ - - name: Other APIs - link: /http_api/other/ - - name: Playlist API - link: /http_api/playlist/ - - name: Preferences API - link: /http_api/preferences/ - - name: Reporting API - link: /http_api/reporting/ - - name: Snapshot API - link: /http_api/snapshot/ - - name: Teams API - link: /http_api/team/ - - name: Users API - link: /http_api/user/ -- name: Troubleshooting - children: - - name: Overview - link: /troubleshooting/ - - name: Enable diagnostics - link: /troubleshooting/diagnostics/ - - name: Troubleshoot dashboards - link: /troubleshooting/troubleshoot-dashboards/ - - name: Troubleshoot queries - link: /troubleshooting/troubleshoot-queries/ -- name: Developers - children: - - name: Plugins - children: - - name: Overview - link: /developers/plugins/ - - name: plugin.json - link: /developers/plugins/metadata/ - - name: Data frames - link: /developers/plugins/data-frames/ - - name: Working with data frames - link: /developers/plugins/working-with-data-frames/ - - name: Add support for variables - link: /developers/plugins/add-support-for-variables/ - - name: Add support for annotations - link: /developers/plugins/add-support-for-annotations/ - - name: Add support for Explore queries - link: /developers/plugins/add-support-for-explore-queries/ - - name: Build a logs data source plugin - link: /developers/plugins/build-a-logs-data-source-plugin/ - - name: Build a streaming data source plugin - link: /developers/plugins/build-a-streaming-data-source-plugin/ - - name: Authentication - link: /developers/plugins/authentication/ - - name: Sign a plugin - link: /developers/plugins/sign-a-plugin/ - - name: Add authentication for data source plugins - link: /developers/plugins/add-authentication-for-data-source-plugins/ - - name: Backend plugins - children: - - link: /developers/plugins/backend/ - name: Overview - - link: /developers/plugins/backend/plugin-protocol/ - name: Plugin protocol - - link: /developers/plugins/backend/grafana-plugin-sdk-for-go/ - name: Grafana plugin SDK for Go - - name: Package a plugin - link: /developers/plugins/package-a-plugin/ - - name: Error handling - link: /developers/plugins/error-handling/ - - name: Plugin migration guide - link: /developers/plugins/migration-guide/ - - name: Legacy plugins - children: - - link: /developers/plugins/legacy/ - name: Overview - - link: /developers/plugins/legacy/style-guide/ - name: Code style guide - - link: /developers/plugins/legacy/review-guidelines/ - name: Review guidelines - - link: /developers/plugins/legacy/defaults-and-editor-mode/ - name: Defaults and editor mode - - link: /developers/plugins/legacy/apps/ - name: App plugins - - link: /developers/plugins/legacy/data-sources/ - name: Data source plugins - - link: /developers/plugins/legacy/snapshot-mode/ - name: Snapshot mode - - name: API reference - link: /packages_api/ - - name: Contribute - link: /developers/contribute/ - - name: Contributor License Agreement (CLA) - link: /developers/cla/ From 3390c6a852dda66e53c2c82b271a07637b24a73e Mon Sep 17 00:00:00 2001 From: Besart Berisha Date: Thu, 28 Jan 2021 21:39:06 +0100 Subject: [PATCH 35/41] Add alt text to plugin logos (#30710) --- public/app/core/components/PageHeader/PageHeader.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/app/core/components/PageHeader/PageHeader.tsx b/public/app/core/components/PageHeader/PageHeader.tsx index de2af17f358..ee343356888 100644 --- a/public/app/core/components/PageHeader/PageHeader.tsx +++ b/public/app/core/components/PageHeader/PageHeader.tsx @@ -121,7 +121,7 @@ export default class PageHeader extends React.Component {
{main.icon && } - {main.img && } + {main.img && {`logo}
From db9a8bf04a4f1afe134d2f371c1906f8f2b59d99 Mon Sep 17 00:00:00 2001 From: Ryan McKinley Date: Thu, 28 Jan 2021 14:00:28 -0800 Subject: [PATCH 36/41] Transform: improve the "outer join" performance/behavior (#30407) --- .../grafana-data/src/transformations/index.ts | 2 +- .../transformers/ensureColumns.test.ts | 108 ++-- .../transformers/joinDataFrames.test.ts | 302 ++++++++++ .../transformers/joinDataFrames.ts | 313 ++++++++++ .../transformers/seriesToColumns.test.ts | 548 ++++++++++-------- .../transformers/seriesToColumns.ts | 153 +---- .../src/components/GraphNG/GraphNG.tsx | 17 +- .../src/components/GraphNG/utils.test.ts | 334 ----------- .../src/components/GraphNG/utils.ts | 180 ------ 9 files changed, 1038 insertions(+), 919 deletions(-) create mode 100644 packages/grafana-data/src/transformations/transformers/joinDataFrames.test.ts create mode 100644 packages/grafana-data/src/transformations/transformers/joinDataFrames.ts delete mode 100644 packages/grafana-ui/src/components/GraphNG/utils.test.ts delete mode 100755 packages/grafana-ui/src/components/GraphNG/utils.ts diff --git a/packages/grafana-data/src/transformations/index.ts b/packages/grafana-data/src/transformations/index.ts index 98ffbce03c8..70afc15fceb 100644 --- a/packages/grafana-data/src/transformations/index.ts +++ b/packages/grafana-data/src/transformations/index.ts @@ -11,4 +11,4 @@ export { } from './standardTransformersRegistry'; export { RegexpOrNamesMatcherOptions, ByNamesMatcherOptions, ByNamesMatcherMode } from './matchers/nameMatcher'; export { RenameByRegexTransformerOptions } from './transformers/renameByRegex'; -export { outerJoinDataFrames } from './transformers/seriesToColumns'; +export { outerJoinDataFrames } from './transformers/joinDataFrames'; diff --git a/packages/grafana-data/src/transformations/transformers/ensureColumns.test.ts b/packages/grafana-data/src/transformations/transformers/ensureColumns.test.ts index 954e306bf98..0456b6d4df0 100644 --- a/packages/grafana-data/src/transformations/transformers/ensureColumns.test.ts +++ b/packages/grafana-data/src/transformations/transformers/ensureColumns.test.ts @@ -49,52 +49,82 @@ describe('ensureColumns transformer', () => { const frame = filtered[0]; expect(frame.fields.length).toEqual(5); - expect(filtered[0]).toEqual( - toDataFrame({ - fields: [ - { - name: 'TheTime', - type: 'time', - config: {}, - values: [1000, 2000], - labels: undefined, + expect(filtered[0]).toMatchInlineSnapshot(` + Object { + "fields": Array [ + Object { + "config": Object {}, + "name": "TheTime", + "state": Object { + "displayName": "TheTime", + }, + "type": "time", + "values": Array [ + 1000, + 2000, + ], }, - { - name: 'A', - type: 'number', - config: {}, - values: [1, 100], - labels: {}, + Object { + "config": Object {}, + "labels": Object {}, + "name": "A", + "state": Object { + "displayName": "A", + }, + "type": "number", + "values": Array [ + 1, + 100, + ], }, - { - name: 'B', - type: 'number', - config: {}, - values: [2, 200], - labels: {}, + Object { + "config": Object {}, + "labels": Object {}, + "name": "B", + "state": Object { + "displayName": "B", + }, + "type": "number", + "values": Array [ + 2, + 200, + ], }, - { - name: 'C', - type: 'number', - config: {}, - values: [3, 300], - labels: {}, + Object { + "config": Object {}, + "labels": Object {}, + "name": "C", + "state": Object { + "displayName": "C", + }, + "type": "number", + "values": Array [ + 3, + 300, + ], }, - { - name: 'D', - type: 'string', - config: {}, - values: ['first', 'second'], - labels: {}, + Object { + "config": Object {}, + "labels": Object {}, + "name": "D", + "state": Object { + "displayName": "D", + }, + "type": "string", + "values": Array [ + "first", + "second", + ], }, ], - meta: { - transformations: ['ensureColumns'], + "length": 2, + "meta": Object { + "transformations": Array [ + "ensureColumns", + ], }, - name: undefined, - refId: undefined, - }) - ); + } + `); }); }); diff --git a/packages/grafana-data/src/transformations/transformers/joinDataFrames.test.ts b/packages/grafana-data/src/transformations/transformers/joinDataFrames.test.ts new file mode 100644 index 00000000000..c83613a3460 --- /dev/null +++ b/packages/grafana-data/src/transformations/transformers/joinDataFrames.test.ts @@ -0,0 +1,302 @@ +import { toDataFrame } from '../../dataframe/processDataFrame'; +import { FieldType } from '../../types/dataFrame'; +import { mockTransformationsRegistry } from '../../utils/tests/mockTransformationsRegistry'; +import { ArrayVector } from '../../vector'; +import { calculateFieldTransformer } from './calculateField'; +import { isLikelyAscendingVector, outerJoinDataFrames } from './joinDataFrames'; + +describe('align frames', () => { + beforeAll(() => { + mockTransformationsRegistry([calculateFieldTransformer]); + }); + + it('by first time field', () => { + const series1 = toDataFrame({ + fields: [ + { name: 'TheTime', type: FieldType.time, values: [1000, 2000] }, + { name: 'A', type: FieldType.number, values: [1, 100] }, + ], + }); + + const series2 = toDataFrame({ + fields: [ + { name: '_time', type: FieldType.time, values: [1000, 1500, 2000] }, + { name: 'A', type: FieldType.number, values: [2, 20, 200] }, + { name: 'B', type: FieldType.number, values: [3, 30, 300] }, + { name: 'C', type: FieldType.string, values: ['first', 'second', 'third'] }, + ], + }); + + const out = outerJoinDataFrames({ frames: [series1, series2] })!; + expect( + out.fields.map((f) => ({ + name: f.name, + values: f.values.toArray(), + })) + ).toMatchInlineSnapshot(` + Array [ + Object { + "name": "TheTime", + "values": Array [ + 1000, + 1500, + 2000, + ], + }, + Object { + "name": "A", + "values": Array [ + 1, + undefined, + 100, + ], + }, + Object { + "name": "A", + "values": Array [ + 2, + 20, + 200, + ], + }, + Object { + "name": "B", + "values": Array [ + 3, + 30, + 300, + ], + }, + Object { + "name": "C", + "values": Array [ + "first", + "second", + "third", + ], + }, + ] + `); + }); + + it('unsorted input keep indexes', () => { + //---------- + const series1 = toDataFrame({ + fields: [ + { name: 'TheTime', type: FieldType.time, values: [1000, 2000, 1500] }, + { name: 'A1', type: FieldType.number, values: [1, 2, 15] }, + ], + }); + + const series3 = toDataFrame({ + fields: [ + { name: 'Time', type: FieldType.time, values: [2000, 1000] }, + { name: 'A2', type: FieldType.number, values: [2, 1] }, + ], + }); + + let out = outerJoinDataFrames({ frames: [series1, series3], keepOriginIndices: true })!; + expect( + out.fields.map((f) => ({ + name: f.name, + values: f.values.toArray(), + state: f.state, + })) + ).toMatchInlineSnapshot(` + Array [ + Object { + "name": "TheTime", + "state": Object { + "displayName": "TheTime", + "origin": Object { + "fieldIndex": 0, + "frameIndex": 0, + }, + }, + "values": Array [ + 1000, + 1500, + 2000, + ], + }, + Object { + "name": "A1", + "state": Object { + "displayName": "A1", + "origin": Object { + "fieldIndex": 1, + "frameIndex": 0, + }, + }, + "values": Array [ + 1, + 15, + 2, + ], + }, + Object { + "name": "A2", + "state": Object { + "displayName": "A2", + "origin": Object { + "fieldIndex": 1, + "frameIndex": 1, + }, + }, + "values": Array [ + 1, + undefined, + 2, + ], + }, + ] + `); + + // Fast path still adds origin indecies + out = outerJoinDataFrames({ frames: [series1], keepOriginIndices: true })!; + expect( + out.fields.map((f) => ({ + name: f.name, + state: f.state, + })) + ).toMatchInlineSnapshot(` + Array [ + Object { + "name": "TheTime", + "state": Object { + "displayName": "TheTime", + "origin": Object { + "fieldIndex": 0, + "frameIndex": 0, + }, + }, + }, + Object { + "name": "A1", + "state": Object { + "displayName": "A1", + "origin": Object { + "fieldIndex": 1, + "frameIndex": 0, + }, + }, + }, + ] + `); + }); + + it('sort single frame', () => { + const series1 = toDataFrame({ + fields: [ + { name: 'TheTime', type: FieldType.time, values: [6000, 2000, 1500] }, + { name: 'A1', type: FieldType.number, values: [1, 22, 15] }, + ], + }); + + const out = outerJoinDataFrames({ frames: [series1], enforceSort: true, keepOriginIndices: true })!; + expect( + out.fields.map((f) => ({ + name: f.name, + values: f.values.toArray(), + })) + ).toMatchInlineSnapshot(` + Array [ + Object { + "name": "TheTime", + "values": Array [ + 1500, + 2000, + 6000, + ], + }, + Object { + "name": "A1", + "values": Array [ + 15, + 22, + 1, + ], + }, + ] + `); + }); + + it('supports duplicate times', () => { + //---------- + // NOTE!!! + // * ideally we would *keep* dupicate fields + //---------- + const series1 = toDataFrame({ + fields: [ + { name: 'TheTime', type: FieldType.time, values: [1000, 2000] }, + { name: 'A', type: FieldType.number, values: [1, 100] }, + ], + }); + + const series3 = toDataFrame({ + fields: [ + { name: 'Time', type: FieldType.time, values: [1000, 1000, 1000] }, + { name: 'A', type: FieldType.number, values: [2, 20, 200] }, + ], + }); + + const out = outerJoinDataFrames({ frames: [series1, series3] })!; + expect( + out.fields.map((f) => ({ + name: f.name, + values: f.values.toArray(), + })) + ).toMatchInlineSnapshot(` + Array [ + Object { + "name": "TheTime", + "values": Array [ + 1000, + 2000, + ], + }, + Object { + "name": "A", + "values": Array [ + 1, + 100, + ], + }, + Object { + "name": "A", + "values": Array [ + 200, + undefined, + ], + }, + ] + `); + }); + + describe('check ascending data', () => { + it('simple ascending', () => { + const v = new ArrayVector([1, 2, 3, 4, 5]); + expect(isLikelyAscendingVector(v)).toBeTruthy(); + }); + it('simple ascending with null', () => { + const v = new ArrayVector([null, 2, 3, 4, null]); + expect(isLikelyAscendingVector(v)).toBeTruthy(); + }); + it('single value', () => { + const v = new ArrayVector([null, null, null, 4, null]); + expect(isLikelyAscendingVector(v)).toBeTruthy(); + expect(isLikelyAscendingVector(new ArrayVector([4]))).toBeTruthy(); + expect(isLikelyAscendingVector(new ArrayVector([]))).toBeTruthy(); + }); + + it('middle values', () => { + const v = new ArrayVector([null, null, 5, 4, null]); + expect(isLikelyAscendingVector(v)).toBeFalsy(); + }); + + it('decending', () => { + expect(isLikelyAscendingVector(new ArrayVector([7, 6, null]))).toBeFalsy(); + expect(isLikelyAscendingVector(new ArrayVector([7, 8, 6]))).toBeFalsy(); + }); + }); +}); diff --git a/packages/grafana-data/src/transformations/transformers/joinDataFrames.ts b/packages/grafana-data/src/transformations/transformers/joinDataFrames.ts new file mode 100644 index 00000000000..26aa964d989 --- /dev/null +++ b/packages/grafana-data/src/transformations/transformers/joinDataFrames.ts @@ -0,0 +1,313 @@ +import { DataFrame, Field, FieldMatcher, FieldType, Vector } from '../../types'; +import { ArrayVector } from '../../vector'; +import { fieldMatchers } from '../matchers'; +import { FieldMatcherID } from '../matchers/ids'; +import { getTimeField, sortDataFrame } from '../../dataframe'; +import { getFieldDisplayName } from '../../field'; + +export function pickBestJoinField(data: DataFrame[]): FieldMatcher { + const { timeField } = getTimeField(data[0]); + if (timeField) { + return fieldMatchers.get(FieldMatcherID.firstTimeField).get({}); + } + let common: string[] = []; + for (const f of data[0].fields) { + if (f.type === FieldType.number) { + common.push(f.name); + } + } + + for (let i = 1; i < data.length; i++) { + const names: string[] = []; + for (const f of data[0].fields) { + if (f.type === FieldType.number) { + names.push(f.name); + } + } + common = common.filter((v) => !names.includes(v)); + } + + return fieldMatchers.get(FieldMatcherID.byName).get(common[0]); +} + +/** + * @alpha + */ +export interface JoinOptions { + /** + * The input fields + */ + frames: DataFrame[]; + + /** + * The field to join -- frames that do not have this field will be droppped + */ + joinBy?: FieldMatcher; + + /** + * Optionally filter the non-join fields + */ + keep?: FieldMatcher; + + /** + * When the result is a single frame, this will to a quick check to see if the values are sorted, + * and sort if necessary. If the first/last values are in order the whole vector is assumed to be + * sorted + */ + enforceSort?: boolean; + + /** + * @internal -- used when we need to keep a reference to the original frame/field index + */ + keepOriginIndices?: boolean; +} + +function getJoinMatcher(options: JoinOptions): FieldMatcher { + return options.joinBy ?? pickBestJoinField(options.frames); +} + +/** + * This will return a single frame joined by the first matching field. When a join field is not specified, + * the default will use the first time field + */ +export function outerJoinDataFrames(options: JoinOptions): DataFrame | undefined { + if (!options.frames?.length) { + return undefined; + } + + if (options.frames.length === 1) { + let frame = options.frames[0]; + if (options.keepOriginIndices) { + frame = { + ...frame, + fields: frame.fields.map((f, fieldIndex) => { + const copy = { ...f }; + const origin = { + frameIndex: 0, + fieldIndex, + }; + if (copy.state) { + copy.state.origin = origin; + } else { + copy.state = { origin }; + } + return copy; + }), + }; + } + if (options.enforceSort) { + const joinFieldMatcher = getJoinMatcher(options); + const joinIndex = frame.fields.findIndex((f) => joinFieldMatcher(f, frame, options.frames)); + if (joinIndex >= 0) { + if (!isLikelyAscendingVector(frame.fields[joinIndex].values)) { + return sortDataFrame(frame, joinIndex); + } + } + } + return frame; + } + + const nullModes: JoinNullMode[][] = []; + const allData: AlignedData[] = []; + const originalFields: Field[] = []; + const joinFieldMatcher = getJoinMatcher(options); + + for (let frameIndex = 0; frameIndex < options.frames.length; frameIndex++) { + const frame = options.frames[frameIndex]; + if (!frame || !frame.fields?.length) { + continue; // skip the frame + } + const nullModesFrame: JoinNullMode[] = [NULL_REMOVE]; + + let join: Field | undefined = undefined; + let fields: Field[] = []; + for (let fieldIndex = 0; fieldIndex < frame.fields.length; fieldIndex++) { + const field = frame.fields[fieldIndex]; + getFieldDisplayName(field, frame, options.frames); // cache displayName in state + + if (!join && joinFieldMatcher(field, frame, options.frames)) { + join = field; + } else { + if (options.keep && !options.keep(field, frame, options.frames)) { + continue; // skip field + } + + // Support the standard graph span nulls field config + nullModesFrame.push(field.config.custom?.spanNulls ? NULL_REMOVE : NULL_EXPAND); + + let labels = field.labels ?? {}; + if (frame.name) { + labels = { ...labels, name: frame.name }; + } + + fields.push({ + ...field, + labels, // add the name label from frame + }); + } + + if (options.keepOriginIndices) { + field.state!.origin = { + frameIndex, + fieldIndex, + }; + } + } + + if (!join) { + continue; // skip the frame + } + + if (originalFields.length === 0) { + originalFields.push(join); // first join field + } + nullModes.push(nullModesFrame); + + const a: AlignedData = [join.values.toArray()]; // + for (const field of fields) { + a.push(field.values.toArray()); + originalFields.push(field); + } + allData.push(a); + } + + const joined = join(allData, nullModes); + return { + // ...options.data[0], // keep name, meta? + length: joined[0].length, + fields: originalFields.map((f, index) => ({ + ...f, + values: new ArrayVector(joined[index]), + })), + }; +} + +//-------------------------------------------------------------------------------- +// Below here is copied from uplot (MIT License) +// https://github.com/leeoniya/uPlot/blob/master/src/utils.js#L325 +// This avoids needing to import uplot into the data package +//-------------------------------------------------------------------------------- + +// Copied from uplot +type AlignedData = [number[], ...Array>]; + +// nullModes +const NULL_REMOVE = 0; // nulls are converted to undefined (e.g. for spanGaps: true) +const NULL_RETAIN = 1; // nulls are retained, with alignment artifacts set to undefined (default) +const NULL_EXPAND = 2; // nulls are expanded to include any adjacent alignment artifacts + +type JoinNullMode = number; // NULL_IGNORE | NULL_RETAIN | NULL_EXPAND; + +// sets undefined values to nulls when adjacent to existing nulls (minesweeper) +function nullExpand(yVals: Array, nullIdxs: number[], alignedLen: number) { + for (let i = 0, xi, lastNullIdx = -1; i < nullIdxs.length; i++) { + let nullIdx = nullIdxs[i]; + + if (nullIdx > lastNullIdx) { + xi = nullIdx - 1; + while (xi >= 0 && yVals[xi] == null) { + yVals[xi--] = null; + } + + xi = nullIdx + 1; + while (xi < alignedLen && yVals[xi] == null) { + yVals[(lastNullIdx = xi++)] = null; + } + } + } +} + +// nullModes is a tables-matched array indicating how to treat nulls in each series +function join(tables: AlignedData[], nullModes: number[][]) { + const xVals = new Set(); + + for (let ti = 0; ti < tables.length; ti++) { + let t = tables[ti]; + let xs = t[0]; + let len = xs.length; + + for (let i = 0; i < len; i++) { + xVals.add(xs[i]); + } + } + + let data = [Array.from(xVals).sort((a, b) => a - b)]; + + let alignedLen = data[0].length; + + let xIdxs = new Map(); + + for (let i = 0; i < alignedLen; i++) { + xIdxs.set(data[0][i], i); + } + + for (let ti = 0; ti < tables.length; ti++) { + let t = tables[ti]; + let xs = t[0]; + + for (let si = 1; si < t.length; si++) { + let ys = t[si]; + + let yVals = Array(alignedLen).fill(undefined); + + let nullMode = nullModes ? nullModes[ti][si] : NULL_RETAIN; + + let nullIdxs = []; + + for (let i = 0; i < ys.length; i++) { + let yVal = ys[i]; + let alignedIdx = xIdxs.get(xs[i]); + + if (yVal == null) { + if (nullMode !== NULL_REMOVE) { + yVals[alignedIdx] = yVal; + + if (nullMode === NULL_EXPAND) { + nullIdxs.push(alignedIdx); + } + } + } else { + yVals[alignedIdx] = yVal; + } + } + + nullExpand(yVals, nullIdxs, alignedLen); + + data.push(yVals); + } + } + + return data; +} + +// Quick test if the first and last points look to be ascending +// Only exported for tests +export function isLikelyAscendingVector(data: Vector): boolean { + let first: any = undefined; + + for (let idx = 0; idx < data.length; idx++) { + const v = data.get(idx); + if (v != null) { + if (first != null) { + if (first > v) { + return false; // descending + } + break; + } + first = v; + } + } + + let idx = data.length - 1; + while (idx >= 0) { + const v = data.get(idx--); + if (v != null) { + if (first > v) { + return false; + } + return true; + } + } + + return true; // only one non-null point +} diff --git a/packages/grafana-data/src/transformations/transformers/seriesToColumns.test.ts b/packages/grafana-data/src/transformations/transformers/seriesToColumns.test.ts index 1c526d4982e..451277697c2 100644 --- a/packages/grafana-data/src/transformations/transformers/seriesToColumns.test.ts +++ b/packages/grafana-data/src/transformations/transformers/seriesToColumns.test.ts @@ -2,7 +2,6 @@ import { ArrayVector, DataTransformerConfig, DataTransformerID, - Field, FieldType, toDataFrame, transformDataFrame, @@ -45,58 +44,102 @@ describe('SeriesToColumns Transformer', () => { (received) => { const data = received[0]; const filtered = data[0]; - expect(filtered.fields).toEqual([ - { - name: 'time', - state: { - displayName: 'time', + expect(filtered.fields).toMatchInlineSnapshot(` + Array [ + Object { + "config": Object {}, + "name": "time", + "state": Object { + "displayName": "time", + }, + "type": "time", + "values": Array [ + 1000, + 3000, + 4000, + 5000, + 6000, + 7000, + ], }, - type: FieldType.time, - values: new ArrayVector([1000, 3000, 4000, 5000, 6000, 7000]), - config: {}, - labels: undefined, - }, - { - name: 'temperature', - state: { - displayName: 'temperature even', + Object { + "config": Object {}, + "labels": Object { + "name": "even", + }, + "name": "temperature", + "state": Object { + "displayName": "even temperature", + }, + "type": "number", + "values": Array [ + undefined, + 10.3, + 10.4, + 10.5, + 10.6, + undefined, + ], }, - type: FieldType.number, - values: new ArrayVector([null, 10.3, 10.4, 10.5, 10.6, null]), - config: {}, - labels: { name: 'even' }, - }, - { - name: 'humidity', - state: { - displayName: 'humidity even', + Object { + "config": Object {}, + "labels": Object { + "name": "even", + }, + "name": "humidity", + "state": Object { + "displayName": "even humidity", + }, + "type": "number", + "values": Array [ + undefined, + 10000.3, + 10000.4, + 10000.5, + 10000.6, + undefined, + ], }, - type: FieldType.number, - values: new ArrayVector([null, 10000.3, 10000.4, 10000.5, 10000.6, null]), - config: {}, - labels: { name: 'even' }, - }, - { - name: 'temperature', - state: { - displayName: 'temperature odd', + Object { + "config": Object {}, + "labels": Object { + "name": "odd", + }, + "name": "temperature", + "state": Object { + "displayName": "odd temperature", + }, + "type": "number", + "values": Array [ + 11.1, + 11.3, + undefined, + 11.5, + undefined, + 11.7, + ], }, - type: FieldType.number, - values: new ArrayVector([11.1, 11.3, null, 11.5, null, 11.7]), - config: {}, - labels: { name: 'odd' }, - }, - { - name: 'humidity', - state: { - displayName: 'humidity odd', + Object { + "config": Object {}, + "labels": Object { + "name": "odd", + }, + "name": "humidity", + "state": Object { + "displayName": "odd humidity", + }, + "type": "number", + "values": Array [ + 11000.1, + 11000.3, + undefined, + 11000.5, + undefined, + 11000.7, + ], }, - type: FieldType.number, - values: new ArrayVector([11000.1, 11000.3, null, 11000.5, null, 11000.7]), - config: {}, - labels: { name: 'odd' }, - }, - ]); + ] + `); } ); }); @@ -113,58 +156,7 @@ describe('SeriesToColumns Transformer', () => { (received) => { const data = received[0]; const filtered = data[0]; - expect(filtered.fields).toEqual([ - { - name: 'temperature', - state: { - displayName: 'temperature', - }, - type: FieldType.number, - values: new ArrayVector([10.3, 10.4, 10.5, 10.6, 11.1, 11.3, 11.5, 11.7]), - config: {}, - labels: undefined, - }, - { - name: 'time', - state: { - displayName: 'time even', - }, - type: FieldType.time, - values: new ArrayVector([3000, 4000, 5000, 6000, null, null, null, null]), - config: {}, - labels: { name: 'even' }, - }, - { - name: 'humidity', - state: { - displayName: 'humidity even', - }, - type: FieldType.number, - values: new ArrayVector([10000.3, 10000.4, 10000.5, 10000.6, null, null, null, null]), - config: {}, - labels: { name: 'even' }, - }, - { - name: 'time', - state: { - displayName: 'time odd', - }, - type: FieldType.time, - values: new ArrayVector([null, null, null, null, 1000, 3000, 5000, 7000]), - config: {}, - labels: { name: 'odd' }, - }, - { - name: 'humidity', - state: { - displayName: 'humidity odd', - }, - type: FieldType.number, - values: new ArrayVector([null, null, null, null, 11000.1, 11000.3, 11000.5, 11000.7]), - config: {}, - labels: { name: 'odd' }, - }, - ]); + expect(filtered.fields).toMatchInlineSnapshot(`Array []`); } ); }); @@ -185,58 +177,102 @@ describe('SeriesToColumns Transformer', () => { (received) => { const data = received[0]; const filtered = data[0]; - expect(filtered.fields).toEqual([ - { - name: 'time', - state: { - displayName: 'time', + expect(filtered.fields).toMatchInlineSnapshot(` + Array [ + Object { + "config": Object {}, + "name": "time", + "state": Object { + "displayName": "time", + }, + "type": "time", + "values": Array [ + 1000, + 3000, + 4000, + 5000, + 6000, + 7000, + ], }, - type: FieldType.time, - values: new ArrayVector([1000, 3000, 4000, 5000, 6000, 7000]), - config: {}, - labels: undefined, - }, - { - name: 'temperature', - state: { - displayName: 'temperature even', + Object { + "config": Object {}, + "labels": Object { + "name": "even", + }, + "name": "temperature", + "state": Object { + "displayName": "even temperature", + }, + "type": "number", + "values": Array [ + undefined, + 10.3, + 10.4, + 10.5, + 10.6, + undefined, + ], }, - type: FieldType.number, - values: new ArrayVector([null, 10.3, 10.4, 10.5, 10.6, null]), - config: {}, - labels: { name: 'even' }, - }, - { - name: 'humidity', - state: { - displayName: 'humidity even', + Object { + "config": Object {}, + "labels": Object { + "name": "even", + }, + "name": "humidity", + "state": Object { + "displayName": "even humidity", + }, + "type": "number", + "values": Array [ + undefined, + 10000.3, + 10000.4, + 10000.5, + 10000.6, + undefined, + ], }, - type: FieldType.number, - values: new ArrayVector([null, 10000.3, 10000.4, 10000.5, 10000.6, null]), - config: {}, - labels: { name: 'even' }, - }, - { - name: 'temperature', - state: { - displayName: 'temperature odd', + Object { + "config": Object {}, + "labels": Object { + "name": "odd", + }, + "name": "temperature", + "state": Object { + "displayName": "odd temperature", + }, + "type": "number", + "values": Array [ + 11.1, + 11.3, + undefined, + 11.5, + undefined, + 11.7, + ], }, - type: FieldType.number, - values: new ArrayVector([11.1, 11.3, null, 11.5, null, 11.7]), - config: {}, - labels: { name: 'odd' }, - }, - { - name: 'humidity', - state: { - displayName: 'humidity odd', + Object { + "config": Object {}, + "labels": Object { + "name": "odd", + }, + "name": "humidity", + "state": Object { + "displayName": "odd humidity", + }, + "type": "number", + "values": Array [ + 11000.1, + 11000.3, + undefined, + 11000.5, + undefined, + 11000.7, + ], }, - type: FieldType.number, - values: new ArrayVector([11000.1, 11000.3, null, 11000.5, null, 11000.7]), - config: {}, - labels: { name: 'odd' }, - }, - ]); + ] + `); } ); }); @@ -270,40 +306,58 @@ describe('SeriesToColumns Transformer', () => { (received) => { const data = received[0]; const filtered = data[0]; - const expected: Field[] = [ - { - name: 'time', - state: { - displayName: 'time', + expect(filtered.fields).toMatchInlineSnapshot(` + Array [ + Object { + "config": Object {}, + "name": "time", + "state": Object { + "displayName": "time", + }, + "type": "time", + "values": Array [ + 1000, + 2000, + 3000, + 4000, + ], }, - type: FieldType.time, - values: new ArrayVector([1000, 2000, 3000, 4000]), - config: {}, - labels: undefined, - }, - { - name: 'temperature', - type: FieldType.number, - values: new ArrayVector([1, 3, 5, 7]), - config: {}, - state: { - displayName: 'temperature temperature', + Object { + "config": Object {}, + "labels": Object { + "name": "temperature", + }, + "name": "temperature", + "state": Object { + "displayName": "temperature temperature", + }, + "type": "number", + "values": Array [ + 1, + 3, + 5, + 7, + ], }, - labels: { name: 'temperature' }, - }, - { - name: 'temperature', - state: { - displayName: 'temperature B', + Object { + "config": Object {}, + "labels": Object { + "name": "B", + }, + "name": "temperature", + "state": Object { + "displayName": "B temperature", + }, + "type": "number", + "values": Array [ + 2, + 4, + 6, + 8, + ], }, - type: FieldType.number, - values: new ArrayVector([2, 4, 6, 8]), - config: {}, - labels: { name: 'B' }, - }, - ]; - - expect(filtered.fields).toEqual(expected); + ] + `); } ); }); @@ -341,31 +395,55 @@ describe('SeriesToColumns Transformer', () => { await expect(transformDataFrame([cfg], [frame1, frame2, frame3])).toEmitValuesWith((received) => { const data = received[0]; const filtered = data[0]; - expect(filtered.fields).toEqual([ - { - name: 'time', - state: { displayName: 'time' }, - type: FieldType.time, - values: new ArrayVector([1, 2, 3]), - config: {}, - }, - { - name: 'temperature', - state: { displayName: 'temperature A' }, - type: FieldType.number, - values: new ArrayVector([10, 11, 12]), - config: {}, - labels: { name: 'A' }, - }, - { - name: 'temperature', - state: { displayName: 'temperature C' }, - type: FieldType.number, - values: new ArrayVector([20, 22, 24]), - config: {}, - labels: { name: 'C' }, - }, - ]); + expect(filtered.fields).toMatchInlineSnapshot(` + Array [ + Object { + "config": Object {}, + "name": "time", + "state": Object { + "displayName": "time", + }, + "type": "time", + "values": Array [ + 1, + 2, + 3, + ], + }, + Object { + "config": Object {}, + "labels": Object { + "name": "A", + }, + "name": "temperature", + "state": Object { + "displayName": "A temperature", + }, + "type": "number", + "values": Array [ + 10, + 11, + 12, + ], + }, + Object { + "config": Object {}, + "labels": Object { + "name": "C", + }, + "name": "temperature", + "state": Object { + "displayName": "C temperature", + }, + "type": "number", + "values": Array [ + 20, + 22, + 24, + ], + }, + ] + `); }); }); @@ -394,31 +472,45 @@ describe('SeriesToColumns Transformer', () => { await expect(transformDataFrame([cfg], [frame1, frame2])).toEmitValuesWith((received) => { const data = received[0]; const filtered = data[0]; - expect(filtered.fields).toEqual([ - { - name: 'time', - state: { displayName: 'time' }, - type: FieldType.time, - values: new ArrayVector([1]), - config: {}, - }, - { - name: 'temperature', - state: { displayName: 'temperature 1' }, - type: FieldType.number, - values: new ArrayVector([10]), - config: {}, - labels: {}, - }, - { - name: 'temperature', - state: { displayName: 'temperature 2' }, - type: FieldType.number, - values: new ArrayVector([20]), - config: {}, - labels: {}, - }, - ]); + expect(filtered.fields).toMatchInlineSnapshot(` + Array [ + Object { + "config": Object {}, + "name": "time", + "state": Object { + "displayName": "time", + }, + "type": "time", + "values": Array [ + 1, + ], + }, + Object { + "config": Object {}, + "labels": Object {}, + "name": "temperature", + "state": Object { + "displayName": "temperature", + }, + "type": "number", + "values": Array [ + 10, + ], + }, + Object { + "config": Object {}, + "labels": Object {}, + "name": "temperature", + "state": Object { + "displayName": "temperature", + }, + "type": "number", + "values": Array [ + 20, + ], + }, + ] + `); }); }); }); diff --git a/packages/grafana-data/src/transformations/transformers/seriesToColumns.ts b/packages/grafana-data/src/transformations/transformers/seriesToColumns.ts index 6c0001d10ce..07acaf87a2f 100644 --- a/packages/grafana-data/src/transformations/transformers/seriesToColumns.ts +++ b/packages/grafana-data/src/transformations/transformers/seriesToColumns.ts @@ -1,153 +1,36 @@ import { map } from 'rxjs/operators'; -import { DataFrame, DataTransformerInfo, Field } from '../../types'; +import { DataTransformerInfo, FieldMatcher } from '../../types'; import { DataTransformerID } from './ids'; -import { MutableDataFrame } from '../../dataframe'; -import { ArrayVector } from '../../vector'; -import { getFieldDisplayName } from '../../field/fieldState'; +import { outerJoinDataFrames } from './joinDataFrames'; +import { fieldMatchers } from '../matchers'; +import { FieldMatcherID } from '../matchers/ids'; export interface SeriesToColumnsOptions { - byField?: string; + byField?: string; // empty will pick the field automatically } -const DEFAULT_KEY_FIELD = 'Time'; - export const seriesToColumnsTransformer: DataTransformerInfo = { id: DataTransformerID.seriesToColumns, - name: 'Series as columns', + name: 'Series as columns', // Called 'Outer join' in the UI! description: 'Groups series by field and returns values as columns', defaultOptions: { - byField: DEFAULT_KEY_FIELD, + byField: undefined, // DEFAULT_KEY_FIELD, }, operator: (options) => (source) => source.pipe( map((data) => { - return outerJoinDataFrames(data, options); + if (data.length > 1) { + let joinBy: FieldMatcher | undefined = undefined; + if (options.byField) { + joinBy = fieldMatchers.get(FieldMatcherID.byName).get(options.byField); + } + const joined = outerJoinDataFrames({ frames: data, joinBy }); + if (joined) { + return [joined]; + } + } + return data; }) ), }; - -/** - * @internal - */ -export function outerJoinDataFrames(data: DataFrame[], options: SeriesToColumnsOptions) { - const keyFieldMatch = options.byField || DEFAULT_KEY_FIELD; - const allFields: FieldsToProcess[] = []; - - for (let frameIndex = 0; frameIndex < data.length; frameIndex++) { - const frame = data[frameIndex]; - const keyField = findKeyField(frame, keyFieldMatch); - - if (!keyField) { - continue; - } - - for (let fieldIndex = 0; fieldIndex < frame.fields.length; fieldIndex++) { - const sourceField = frame.fields[fieldIndex]; - - if (sourceField === keyField) { - continue; - } - - let labels = sourceField.labels ?? {}; - - if (frame.name) { - labels = { ...labels, name: frame.name }; - } - - allFields.push({ - keyField, - sourceField, - newField: { - ...sourceField, - state: null, - values: new ArrayVector([]), - labels, - }, - }); - } - } - - // if no key fields or more than one value field - if (allFields.length <= 1) { - return data; - } - - const resultFrame = new MutableDataFrame(); - - resultFrame.addField({ - ...allFields[0].keyField, - values: new ArrayVector([]), - }); - - for (const item of allFields) { - item.newField = resultFrame.addField(item.newField); - } - - const keyFieldTitle = getFieldDisplayName(resultFrame.fields[0], resultFrame); - const byKeyField: { [key: string]: { [key: string]: any } } = {}; - - /* - this loop creates a dictionary object that groups the key fields values - { - "key field first value as string" : { - "key field name": key field first value, - "other series name": other series value - "other series n name": other series n value - }, - "key field n value as string" : { - "key field name": key field n value, - "other series name": other series value - "other series n name": other series n value - } - } - */ - - for (let fieldIndex = 0; fieldIndex < allFields.length; fieldIndex++) { - const { sourceField, keyField, newField } = allFields[fieldIndex]; - const newFieldTitle = getFieldDisplayName(newField, resultFrame); - - for (let valueIndex = 0; valueIndex < sourceField.values.length; valueIndex++) { - const value = sourceField.values.get(valueIndex); - const keyValue = keyField.values.get(valueIndex); - - if (!byKeyField[keyValue]) { - byKeyField[keyValue] = { [newFieldTitle]: value, [keyFieldTitle]: keyValue }; - } else { - byKeyField[keyValue][newFieldTitle] = value; - } - } - } - - const keyValueStrings = Object.keys(byKeyField); - for (let rowIndex = 0; rowIndex < keyValueStrings.length; rowIndex++) { - const keyValueAsString = keyValueStrings[rowIndex]; - - for (let fieldIndex = 0; fieldIndex < resultFrame.fields.length; fieldIndex++) { - const field = resultFrame.fields[fieldIndex]; - const otherColumnName = getFieldDisplayName(field, resultFrame); - const value = byKeyField[keyValueAsString][otherColumnName] ?? null; - field.values.add(value); - } - } - - return [resultFrame]; -} - -function findKeyField(frame: DataFrame, matchTitle: string): Field | null { - for (let fieldIndex = 0; fieldIndex < frame.fields.length; fieldIndex++) { - const field = frame.fields[fieldIndex]; - - if (matchTitle === getFieldDisplayName(field)) { - return field; - } - } - - return null; -} - -interface FieldsToProcess { - newField: Field; - sourceField: Field; - keyField: Field; -} diff --git a/packages/grafana-ui/src/components/GraphNG/GraphNG.tsx b/packages/grafana-ui/src/components/GraphNG/GraphNG.tsx index 923ee5713bc..299a61f9414 100755 --- a/packages/grafana-ui/src/components/GraphNG/GraphNG.tsx +++ b/packages/grafana-ui/src/components/GraphNG/GraphNG.tsx @@ -5,14 +5,16 @@ import { DisplayValue, FieldConfig, FieldMatcher, + FieldMatcherID, + fieldMatchers, fieldReducers, FieldType, formattedValueToString, getFieldDisplayName, + outerJoinDataFrames, reduceField, TimeRange, } from '@grafana/data'; -import { joinDataFrames } from './utils'; import { useTheme } from '../../themes'; import { UPlotChart } from '../uPlot/Plot'; import { PlotProps } from '../uPlot/types'; @@ -64,7 +66,16 @@ export const GraphNG: React.FC = ({ const theme = useTheme(); const hasLegend = useRef(legend && legend.displayMode !== LegendDisplayMode.Hidden); - const frame = useMemo(() => joinDataFrames(data, fields), [data, fields]); + const frame = useMemo(() => { + // Default to timeseries config + if (!fields) { + fields = { + x: fieldMatchers.get(FieldMatcherID.firstTimeField).get({}), + y: fieldMatchers.get(FieldMatcherID.numeric).get({}), + }; + } + return outerJoinDataFrames({ frames: data, joinBy: fields.x, keep: fields.y, keepOriginIndices: true }); + }, [data, fields]); const compareFrames = useCallback((a?: DataFrame | null, b?: DataFrame | null) => { if (a && b) { @@ -107,6 +118,7 @@ export const GraphNG: React.FC = ({ // X is the first field in the aligned frame const xField = frame.fields[0]; + let seriesIndex = 0; if (xField.type === FieldType.time) { builder.addScale({ @@ -150,6 +162,7 @@ export const GraphNG: React.FC = ({ if (field === xField || field.type !== FieldType.number) { continue; } + field.state!.seriesIndex = seriesIndex++; const fmt = field.display ?? defaultFormatter; const scaleKey = config.unit || FIXED_UNIT; diff --git a/packages/grafana-ui/src/components/GraphNG/utils.test.ts b/packages/grafana-ui/src/components/GraphNG/utils.test.ts deleted file mode 100644 index dcc4ffa4c4a..00000000000 --- a/packages/grafana-ui/src/components/GraphNG/utils.test.ts +++ /dev/null @@ -1,334 +0,0 @@ -import { ArrayVector, DataFrame, FieldType, toDataFrame } from '@grafana/data'; -import { joinDataFrames, isLikelyAscendingVector } from './utils'; - -describe('joinDataFrames', () => { - describe('joined frame', () => { - it('should align multiple data frames into one data frame', () => { - const data: DataFrame[] = [ - toDataFrame({ - fields: [ - { name: 'time', type: FieldType.time, values: [1000, 2000, 3000, 4000] }, - { name: 'temperature A', type: FieldType.number, values: [1, 3, 5, 7] }, - ], - }), - toDataFrame({ - fields: [ - { name: 'time', type: FieldType.time, values: [1000, 2000, 3000, 4000] }, - { name: 'temperature B', type: FieldType.number, values: [0, 2, 6, 7] }, - ], - }), - ]; - - const joined = joinDataFrames(data); - - expect(joined?.fields).toMatchInlineSnapshot(` - Array [ - Object { - "config": Object {}, - "name": "time", - "state": Object { - "origin": undefined, - }, - "type": "time", - "values": Array [ - 1000, - 2000, - 3000, - 4000, - ], - }, - Object { - "config": Object {}, - "name": "temperature A", - "state": Object { - "displayName": "temperature A", - "origin": Object { - "fieldIndex": 1, - "frameIndex": 0, - }, - "seriesIndex": 0, - }, - "type": "number", - "values": Array [ - 1, - 3, - 5, - 7, - ], - }, - Object { - "config": Object {}, - "name": "temperature B", - "state": Object { - "displayName": "temperature B", - "origin": Object { - "fieldIndex": 1, - "frameIndex": 1, - }, - "seriesIndex": 1, - }, - "type": "number", - "values": Array [ - 0, - 2, - 6, - 7, - ], - }, - ] - `); - }); - - it('should align multiple data frames into one data frame but only keep first time field', () => { - const data: DataFrame[] = [ - toDataFrame({ - fields: [ - { name: 'time', type: FieldType.time, values: [1000, 2000, 3000, 4000] }, - { name: 'temperature', type: FieldType.number, values: [1, 3, 5, 7] }, - ], - }), - toDataFrame({ - fields: [ - { name: 'time2', type: FieldType.time, values: [1000, 2000, 3000, 4000] }, - { name: 'temperature B', type: FieldType.number, values: [0, 2, 6, 7] }, - ], - }), - ]; - - const aligned = joinDataFrames(data); - - expect(aligned?.fields).toMatchInlineSnapshot(` - Array [ - Object { - "config": Object {}, - "name": "time", - "state": Object { - "origin": undefined, - }, - "type": "time", - "values": Array [ - 1000, - 2000, - 3000, - 4000, - ], - }, - Object { - "config": Object {}, - "name": "temperature", - "state": Object { - "displayName": "temperature", - "origin": Object { - "fieldIndex": 1, - "frameIndex": 0, - }, - "seriesIndex": 0, - }, - "type": "number", - "values": Array [ - 1, - 3, - 5, - 7, - ], - }, - Object { - "config": Object {}, - "name": "temperature B", - "state": Object { - "displayName": "temperature B", - "origin": Object { - "fieldIndex": 1, - "frameIndex": 1, - }, - "seriesIndex": 1, - }, - "type": "number", - "values": Array [ - 0, - 2, - 6, - 7, - ], - }, - ] - `); - }); - - it('should align multiple data frames into one data frame and skip non-numeric fields', () => { - const data: DataFrame[] = [ - toDataFrame({ - fields: [ - { name: 'time', type: FieldType.time, values: [1000, 2000, 3000, 4000] }, - { name: 'temperature', type: FieldType.number, values: [1, 3, 5, 7] }, - { name: 'state', type: FieldType.string, values: ['on', 'off', 'off', 'on'] }, - ], - }), - ]; - - const aligned = joinDataFrames(data); - - expect(aligned?.fields).toMatchInlineSnapshot(` - Array [ - Object { - "config": Object {}, - "name": "time", - "state": Object { - "origin": undefined, - }, - "type": "time", - "values": Array [ - 1000, - 2000, - 3000, - 4000, - ], - }, - Object { - "config": Object {}, - "name": "temperature", - "state": Object { - "displayName": "temperature", - "origin": Object { - "fieldIndex": 1, - "frameIndex": 0, - }, - "seriesIndex": 0, - }, - "type": "number", - "values": Array [ - 1, - 3, - 5, - 7, - ], - }, - ] - `); - }); - - it('should align multiple data frames into one data frame and skip non-numeric fields', () => { - const data: DataFrame[] = [ - toDataFrame({ - fields: [ - { name: 'time', type: FieldType.time, values: [1000, 2000, 3000, 4000] }, - { name: 'temperature', type: FieldType.number, values: [1, 3, 5, 7] }, - { name: 'state', type: FieldType.string, values: ['on', 'off', 'off', 'on'] }, - ], - }), - ]; - - const aligned = joinDataFrames(data); - - expect(aligned?.fields).toMatchInlineSnapshot(` - Array [ - Object { - "config": Object {}, - "name": "time", - "state": Object { - "origin": undefined, - }, - "type": "time", - "values": Array [ - 1000, - 2000, - 3000, - 4000, - ], - }, - Object { - "config": Object {}, - "name": "temperature", - "state": Object { - "displayName": "temperature", - "origin": Object { - "fieldIndex": 1, - "frameIndex": 0, - }, - "seriesIndex": 0, - }, - "type": "number", - "values": Array [ - 1, - 3, - 5, - 7, - ], - }, - ] - `); - }); - }); - - describe('getDataFrameFieldIndex', () => { - let aligned: DataFrame | null; - - beforeAll(() => { - const data: DataFrame[] = [ - toDataFrame({ - fields: [ - { name: 'time', type: FieldType.time, values: [1000, 2000, 3000, 4000] }, - { name: 'temperature A', type: FieldType.number, values: [1, 3, 5, 7] }, - ], - }), - toDataFrame({ - fields: [ - { name: 'time', type: FieldType.time, values: [1000, 2000, 3000, 4000] }, - { name: 'temperature B', type: FieldType.number, values: [0, 2, 6, 7] }, - { name: 'humidity', type: FieldType.number, values: [0, 2, 6, 7] }, - ], - }), - toDataFrame({ - fields: [ - { name: 'time', type: FieldType.time, values: [1000, 2000, 3000, 4000] }, - { name: 'temperature C', type: FieldType.number, values: [0, 2, 6, 7] }, - ], - }), - ]; - - aligned = joinDataFrames(data); - }); - - it.each` - yDim | index - ${1} | ${[0, 1]} - ${2} | ${[1, 1]} - ${3} | ${[1, 2]} - ${4} | ${[2, 1]} - `('should return correct index for yDim', ({ yDim, index }) => { - const [frameIndex, fieldIndex] = index; - - expect(aligned?.fields[yDim].state?.origin).toEqual({ - frameIndex, - fieldIndex, - }); - }); - }); - - describe('check ascending data', () => { - it('simple ascending', () => { - const v = new ArrayVector([1, 2, 3, 4, 5]); - expect(isLikelyAscendingVector(v)).toBeTruthy(); - }); - it('simple ascending with null', () => { - const v = new ArrayVector([null, 2, 3, 4, null]); - expect(isLikelyAscendingVector(v)).toBeTruthy(); - }); - it('single value', () => { - const v = new ArrayVector([null, null, null, 4, null]); - expect(isLikelyAscendingVector(v)).toBeTruthy(); - expect(isLikelyAscendingVector(new ArrayVector([4]))).toBeTruthy(); - expect(isLikelyAscendingVector(new ArrayVector([]))).toBeTruthy(); - }); - - it('middle values', () => { - const v = new ArrayVector([null, null, 5, 4, null]); - expect(isLikelyAscendingVector(v)).toBeFalsy(); - }); - - it('decending', () => { - expect(isLikelyAscendingVector(new ArrayVector([7, 6, null]))).toBeFalsy(); - expect(isLikelyAscendingVector(new ArrayVector([7, 8, 6]))).toBeFalsy(); - }); - }); -}); diff --git a/packages/grafana-ui/src/components/GraphNG/utils.ts b/packages/grafana-ui/src/components/GraphNG/utils.ts deleted file mode 100755 index e0602a543f9..00000000000 --- a/packages/grafana-ui/src/components/GraphNG/utils.ts +++ /dev/null @@ -1,180 +0,0 @@ -import { - DataFrame, - ArrayVector, - NullValueMode, - getFieldDisplayName, - Field, - fieldMatchers, - FieldMatcherID, - FieldType, - FieldState, - DataFrameFieldIndex, - sortDataFrame, - Vector, -} from '@grafana/data'; -import uPlot, { AlignedData, JoinNullMode } from 'uplot'; -import { XYFieldMatchers } from './GraphNG'; - -// the results ofter passing though data -export interface XYDimensionFields { - x: Field; // independent axis (cause) - y: Field[]; // dependent axis (effect) -} - -export function mapDimesions(match: XYFieldMatchers, frame: DataFrame, frames?: DataFrame[]): XYDimensionFields { - let x: Field | undefined; - const y: Field[] = []; - - for (const field of frame.fields) { - if (!x && match.x(field, frame, frames ?? [])) { - x = field; - } - if (match.y(field, frame, frames ?? [])) { - y.push(field); - } - } - return { x: x as Field, y }; -} - -/** - * Returns a single DataFrame with: - * - A shared time column - * - only numeric fields - * - * @alpha - */ -export function joinDataFrames(frames: DataFrame[], fields?: XYFieldMatchers): DataFrame | null { - const valuesFromFrames: AlignedData[] = []; - const sourceFields: Field[] = []; - const sourceFieldsRefs: Record = {}; - const nullModes: JoinNullMode[][] = []; - - // Default to timeseries config - if (!fields) { - fields = { - x: fieldMatchers.get(FieldMatcherID.firstTimeField).get({}), - y: fieldMatchers.get(FieldMatcherID.numeric).get({}), - }; - } - - for (let frameIndex = 0; frameIndex < frames.length; frameIndex++) { - let frame = frames[frameIndex]; - let dims = mapDimesions(fields, frame, frames); - - if (!(dims.x && dims.y.length)) { - continue; // no numeric and no time fields - } - - // Quick check that x is ascending order - if (!isLikelyAscendingVector(dims.x.values)) { - const xIndex = frame.fields.indexOf(dims.x); - frame = sortDataFrame(frame, xIndex); - dims = mapDimesions(fields, frame, frames); - } - - let nullModesFrame: JoinNullMode[] = [0]; - - // Add the first X axis - if (!sourceFields.length) { - sourceFields.push(dims.x); - } - - const alignedData: AlignedData = [ - dims.x.values.toArray(), // The x axis (time) - ]; - - for (let fieldIndex = 0; fieldIndex < frame.fields.length; fieldIndex++) { - const field = frame.fields[fieldIndex]; - - if (!fields.y(field, frame, frames)) { - continue; - } - - let values = field.values.toArray(); - let joinNullMode = field.config.custom?.spanNulls ? 0 : 2; - - if (field.config.nullValueMode === NullValueMode.AsZero) { - values = values.map((v) => (v === null ? 0 : v)); - joinNullMode = 0; - } - - sourceFieldsRefs[sourceFields.length] = { frameIndex, fieldIndex }; - - alignedData.push(values); - nullModesFrame.push(joinNullMode); - - // This will cache an appropriate field name in the field state - getFieldDisplayName(field, frame, frames); - sourceFields.push(field); - } - - valuesFromFrames.push(alignedData); - nullModes.push(nullModesFrame); - } - - if (valuesFromFrames.length === 0) { - return null; - } - - // do the actual alignment (outerJoin on the first arrays) - let joinedData = uPlot.join(valuesFromFrames, nullModes); - - if (joinedData!.length !== sourceFields.length) { - throw new Error('outerJoinValues lost a field?'); - } - - let seriesIdx = 0; - // Replace the values from the outer-join field - return { - ...frames[0], - length: joinedData![0].length, - fields: joinedData!.map((vals, idx) => { - let state: FieldState = { - ...sourceFields[idx].state, - origin: sourceFieldsRefs[idx], - }; - - if (sourceFields[idx].type !== FieldType.time) { - state.seriesIndex = seriesIdx; - seriesIdx++; - } - - return { - ...sourceFields[idx], - state, - values: new ArrayVector(vals), - }; - }), - }; -} - -// Quick test if the first and last points look to be ascending -export function isLikelyAscendingVector(data: Vector): boolean { - let first: any = undefined; - - for (let idx = 0; idx < data.length; idx++) { - const v = data.get(idx); - if (v != null) { - if (first != null) { - if (first > v) { - return false; // descending - } - break; - } - first = v; - } - } - - let idx = data.length - 1; - while (idx >= 0) { - const v = data.get(idx--); - if (v != null) { - if (first > v) { - return false; - } - return true; - } - } - - return true; // only one non-null point -} From 507dc436cb9d04a56763a8666ef509bb04fa72dc Mon Sep 17 00:00:00 2001 From: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> Date: Thu, 28 Jan 2021 17:09:26 -0500 Subject: [PATCH 37/41] Added "curated dashboards" information and broke down, rearranged topics. (#30659) * Change to introduction section. * Checkin changes. * Check in changes. * Updated heading levels for better readability. * Checkin changes. * Broke down topic and fixed relrefs. Also, resized images. * Added one more relref from preconfig dashboards to main topic. * Adding Eric's changes. * Added alias. * Updated alias with correct syntax, also updated description typo for "Preconfigured dashboards"s * Checking in changes from Diana. * Update docs/sources/datasources/google-cloud-monitoring/_index.md Co-authored-by: Diana Payton <52059945+oddlittlebird@users.noreply.github.com> * One last change. Co-authored-by: Diana Payton <52059945+oddlittlebird@users.noreply.github.com> --- docs/sources/_index.md | 2 +- docs/sources/datasources/_index.md | 2 +- .../_index.md} | 85 ++++++------------- .../preconfig-cloud-monitoring-dashboards.md | 26 ++++++ docs/sources/whatsnew/whats-new-in-v5-3.md | 2 +- docs/sources/whatsnew/whats-new-in-v5-4.md | 4 +- docs/sources/whatsnew/whats-new-in-v6-0.md | 2 +- docs/sources/whatsnew/whats-new-in-v7-0.md | 2 +- docs/sources/whatsnew/whats-new-in-v7-1.md | 2 +- docs/sources/whatsnew/whats-new-in-v7-3.md | 2 +- .../cloud-monitoring/partials/config.html | 11 ++- 11 files changed, 67 insertions(+), 73 deletions(-) rename docs/sources/datasources/{cloudmonitoring.md => google-cloud-monitoring/_index.md} (86%) create mode 100644 docs/sources/datasources/google-cloud-monitoring/preconfig-cloud-monitoring-dashboards.md diff --git a/docs/sources/_index.md b/docs/sources/_index.md index 6d21b1bd0b9..364b9c91353 100755 --- a/docs/sources/_index.md +++ b/docs/sources/_index.md @@ -86,7 +86,7 @@ aliases = ["/docs/grafana/v1.1", "/docs/grafana/latest/guides/reference/admin",
Prometheus
- }}" class="nav-cards__item nav-cards__item--ds"> + }}" class="nav-cards__item nav-cards__item--ds">
Google Cloud Monitoring
diff --git a/docs/sources/datasources/_index.md b/docs/sources/datasources/_index.md index b58bc45f7c4..8e089e0d768 100644 --- a/docs/sources/datasources/_index.md +++ b/docs/sources/datasources/_index.md @@ -19,7 +19,7 @@ The following data sources are officially supported: - [AWS CloudWatch]({{< relref "cloudwatch.md" >}}) - [Azure Monitor]({{< relref "azuremonitor.md" >}}) - [Elasticsearch]({{< relref "elasticsearch.md" >}}) -- [Google Cloud Monitoring]({{< relref "cloudmonitoring.md" >}}) +- [Google Cloud Monitoring]({{< relref "google-cloud-monitoring/_index.md" >}}) - [Graphite]({{< relref "graphite.md" >}}) - [InfluxDB]({{< relref "influxdb.md" >}}) - [Loki]({{< relref "loki.md" >}}) diff --git a/docs/sources/datasources/cloudmonitoring.md b/docs/sources/datasources/google-cloud-monitoring/_index.md similarity index 86% rename from docs/sources/datasources/cloudmonitoring.md rename to docs/sources/datasources/google-cloud-monitoring/_index.md index 38a97978eba..e0e76e27b35 100644 --- a/docs/sources/datasources/cloudmonitoring.md +++ b/docs/sources/datasources/google-cloud-monitoring/_index.md @@ -1,34 +1,26 @@ +++ -title = "Cloud Monitoring" +title = "Google Cloud Monitoring" description = "Guide for using Google Cloud Monitoring in Grafana" keywords = ["grafana", "stackdriver", "google", "guide", "cloud", "monitoring"] -aliases = ["/docs/grafana/latest/features/datasources/stackdriver", "/docs/grafana/latest/features/datasources/cloudmonitoring/"] +aliases = ["/docs/grafana/latest/features/datasources/stackdriver", "/docs/grafana/latest/datasources/cloudmonitoring/", "/docs/grafana/latest/features/datasources/cloudmonitoring/"] weight = 200 +++ # Using Google Cloud Monitoring in Grafana -> Officially released in Grafana v6.0.0 +Grafana ships with built-in support for Google Cloud Monitoring. Just add it as a data source and you are ready to build dashboards for your Google Cloud Monitoring metrics. Refer to [Add a data source]({{< relref "../add-a-data-source.md" >}}) for instructions on how to add a data source to Grafana. Only users with the organization admin role can add data sources. -> Before Grafana v7.1 this data source was named Google Stackdriver. +> **Note** Before Grafana v7.1, Google Cloud Monitoring was referred to as Google Stackdriver. -Grafana ships with built-in support for Google Cloud Monitoring. Just add it as a data source and you are ready to build dashboards for your Google Cloud Monitoring metrics. +## Google Cloud Monitoring settings -## Adding the data source - -1. Open the side menu by clicking the Grafana icon in the top header. -1. In the side menu under the `Dashboards` link you should find a link named `Data Sources`. -1. Click the `+ Add data source` button in the top header. -1. Select `Google Cloud Monitoring` from the _Type_ dropdown. -1. Upload or paste in the Service Account Key file. See below for steps on how to create a Service Account Key file. - -> **Note:** If you're not seeing the `Data Sources` link in your side menu, then your current user account does not have the `Admin` role for the current organization. +To access Google Cloud Monitoring settings, hover your mouse over the **Configuration** (gear) icon, then click **Data Sources**, and then click the Google Cloud Monitoring data source. | Name | Description | | --------------------- | ------------------------------------------------------------------------------------- | | `Name` | The data source name. This is how you refer to the data source in panels and queries. | | `Default` | Default data source means that it will be pre-selected for new panels. | -| `Service Account Key` | Service Account Key File for a GCP Project. Instructions below on how to create it. | +| `Service Account Key` | Upload or paste in the Service Account Key file for a GCP Project. Refer to [Using a Google Service Account Key File](#using-a-google-service-account-key-file) for details.| ## Authentication @@ -47,31 +39,31 @@ The following APIs need to be enabled first: Click on the links above and click the `Enable` button: -{{< docs-imagebox img="/img/docs/v71/cloudmonitoring_enable_api.png" class="docs-image--no-shadow" caption="Enable GCP APIs" >}} +{{< docs-imagebox img="/img/docs/v71/cloudmonitoring_enable_api.png" max-width="450px" class="docs-image--no-shadow" caption="Enable GCP APIs" >}} #### Create a GCP Service Account for a Project 1. Navigate to the [APIs and Services Credentials page](https://console.cloud.google.com/apis/credentials). 1. Click on the `Create credentials` dropdown/button and choose the `Service account key` option. - {{< docs-imagebox img="/img/docs/v71/cloudmonitoring_create_service_account_button.png" class="docs-image--no-shadow" caption="Create service account button" >}} + {{< docs-imagebox img="/img/docs/v71/cloudmonitoring_create_service_account_button.png" max-width="500px" class="docs-image--no-shadow" caption="Create service account button" >}} 1. On the `Create service account key` page, choose key type `JSON`. Then in the `Service Account` dropdown, choose the `New service account` option: - {{< docs-imagebox img="/img/docs/v71/cloudmonitoring_create_service_account_key.png" class="docs-image--no-shadow" caption="Create service account key" >}} + {{< docs-imagebox img="/img/docs/v71/cloudmonitoring_create_service_account_key.png" max-width="500px" class="docs-image--no-shadow" caption="Create service account key" >}} 1. Some new fields will appear. Fill in a name for the service account in the `Service account name` field and then choose the `Monitoring Viewer` role from the `Role` dropdown: - {{< docs-imagebox img="/img/docs/v71/cloudmonitoring_service_account_choose_role.png" class="docs-image--no-shadow" caption="Choose role" >}} + {{< docs-imagebox img="/img/docs/v71/cloudmonitoring_service_account_choose_role.png" max-width="600px" class="docs-image--no-shadow" caption="Choose role" >}} 1. Click the Create button. A JSON key file will be created and downloaded to your computer. Store this file in a secure place as it allows access to your Google Cloud Monitoring data. 1. Upload it to Grafana on the data source Configuration page. You can either upload the file or paste in the contents of the file. - {{< docs-imagebox img="/img/docs/v71/cloudmonitoring_grafana_upload_key.png" class="docs-image--no-shadow" caption="Upload service key file to Grafana" >}} + {{< docs-imagebox img="/img/docs/v71/cloudmonitoring_grafana_upload_key.png" max-width="550px" class="docs-image--no-shadow" caption="Upload service key file to Grafana" >}} 1. The file contents will be encrypted and saved in the Grafana database. Don't forget to save after uploading the file! - {{< docs-imagebox img="/img/docs/v71/cloudmonitoring_grafana_key_uploaded.png" class="docs-image--no-shadow" caption="Service key file is uploaded to Grafana" >}} + {{< docs-imagebox img="/img/docs/v71/cloudmonitoring_grafana_key_uploaded.png" max-width="600px" class="docs-image--no-shadow" caption="Service key file is uploaded to Grafana" >}} ### Using GCE Default Service Account @@ -181,9 +173,18 @@ Example Alias By: `{{resource.type}} - {{metric.type}}` Example Result: `gce_instance - compute.googleapis.com/instance/cpu/usage_time` +#### Deep linking from Grafana panels to the Metrics Explorer in Google Cloud Console + +> **Note:** Available in Grafana v7.1 and later versions. + +{{< docs-imagebox img="/img/docs/v71/cloudmonitoring_deep_linking.png" max-width="500px" class="docs-image--right" caption="Google Cloud Monitoring deep linking" >}} + +Click on a time series in the panel to see a context menu with a link to View in Metrics Explorer in Google Cloud Console. Clicking that link opens the Metrics Explorer in the Google Cloud Console and runs the query from the Grafana panel there. +The link navigates the user first to the Google Account Chooser and after successfully selecting an account, the user is redirected to the Metrics Explorer. The provided link is valid for any account, but it only displays the query if your account has access to the GCP project specified in the query. + ### SLO (Service Level Objective) queries -> Only available in Grafana v7.0+ +> **Note:** Available in Grafana v7.0 and later versions. {{< docs-imagebox img="/img/docs/v70/slo-query-builder.png" max-width= "400px" class="docs-image--right" >}} @@ -224,7 +225,7 @@ SLO queries use the same [alignment period functionality as metric queries]({{< ### MQL (Monitoring Query Language) queries -> **Note:** Only available in Grafana v7.4+. +> **Note:** Available in Grafana v7.4 and later versions. The MQL query builder in the Google Cloud Monitoring data source allows you to display MQL results in time series format. To get an understanding of the basic concepts in MQL, refer to [Introduction to Monitoring Query Language](https://cloud.google.com/monitoring/mql). @@ -249,7 +250,7 @@ Instead of hard-coding things like server, application and sensor name in your m Variables are shown as dropdown select boxes at the top of the dashboard. These dropdowns make it easy to change the data being displayed in your dashboard. -Check out the [Templating]({{< relref "../variables/_index.md" >}}) documentation for an introduction to the templating feature and the different +Check out the [Templating]({{< relref "../../variables/_index.md" >}}) documentation for an introduction to the templating feature and the different types of template variables. ### Query Variable @@ -282,7 +283,7 @@ Why two ways? The first syntax is easier to read and write but does not allow yo {{< docs-imagebox img="/img/docs/v71/cloudmonitoring_annotations_query_editor.png" max-width= "400px" class="docs-image--right" >}} -[Annotations]({{< relref "../dashboards/annotations.md" >}}) allow you to overlay rich event information on top of graphs. You add annotation +[Annotations]({{< relref "../../dashboards/annotations.md" >}}) allow you to overlay rich event information on top of graphs. You add annotation queries via the Dashboard menu / Annotations view. Annotation rendering is expensive so it is important to limit the number of rows returned. There is no support for showing Google Cloud Monitoring annotations and events yet but it works well with [custom metrics](https://cloud.google.com/monitoring/custom-metrics/) in Google Cloud Monitoring. With the query editor for annotations, you can select a metric and filters. The `Title` and `Text` fields support templating and can use data returned from the query. For example, the Title field could have the following text: @@ -304,7 +305,7 @@ Example Result: `monitoring.googleapis.com/uptime_check/http_status has this val ## Configure the data source with provisioning -It's now possible to configure data sources using config files with Grafana's provisioning system. You can read more about how it works and all the settings you can set for data sources on the [provisioning docs page]({{< relref "../administration/provisioning/#datasources" >}}) +You can configure data sources using config files with Grafana's provisioning system. Read more about how it works and all the settings you can set for data sources on the [provisioning docs page]({{< relref "../../administration/provisioning/#datasources" >}}) Here is a provisioning example using the JWT (Service Account key file) authentication type. @@ -341,35 +342,3 @@ datasources: jsonData: authenticationType: gce ``` - -## Deep linking from Grafana panels to the Metrics Explorer in Google Cloud Console - -Only available in Grafana v7.1+. - -{{< docs-imagebox img="/img/docs/v71/cloudmonitoring_deep_linking.png" max-width="500px" class="docs-image--right" caption="Google Cloud Monitoring deep linking" >}} - -> **Note:** This feature is only available for Metric queries. - -Click on a time series in the panel to see a context menu with a link to View in Metrics Explorer in Google Cloud Console. Clicking that link opens the Metrics Explorer in the Google Cloud Console and runs the query from the Grafana panel there. -The link navigates the user first to the Google Account Chooser and after successfully selecting an account, the user is redirected to the Metrics Explorer. The provided link is valid for any account, but it only displays the query if your account has access to the GCP project specified in the query. - -## Out-of-the-box dashboards - -> Only available in Grafana v7.3+. - -The updated Cloud Monitoring data source ships with pre-configured dashboards for five of the most popular GCP services: - -1. BigQuery -1. Cloud Load Balancing -1. Cloud SQL -1. Google Compute Engine `GCE` -1. Google Kubernetes Engine `GKE` - -To import the pre-configured dashboards, go to the configuration page of a Cloud monitoring data source and click on the `Dashboards` tab. Click `Import` for the dashboard you would like to use. -The datasource of the newly created dashboard panels will be the one selected above. - -The dashboards have a template variable which is populated with the projects accessible by the configured service account every time the dashboard is loaded. After the dashboard is loaded, you can select the project you prefer from the drop-down list. - -To customize the dashboard, we recommend saving the dashboard under a different name, because otherwise the dashboard will be overwritten when a new version of the dashboard is released. - -{{< docs-imagebox img="/img/docs/v73/cloud-monitoring-dashboard-import.png" caption="Cloud Monitoring dashboard import" >}} diff --git a/docs/sources/datasources/google-cloud-monitoring/preconfig-cloud-monitoring-dashboards.md b/docs/sources/datasources/google-cloud-monitoring/preconfig-cloud-monitoring-dashboards.md new file mode 100644 index 00000000000..2160f914cd1 --- /dev/null +++ b/docs/sources/datasources/google-cloud-monitoring/preconfig-cloud-monitoring-dashboards.md @@ -0,0 +1,26 @@ ++++ +title = "Preconfigured dashboards" +description = "Guide for using Google Cloud Monitoring in Grafana" +keywords = ["grafana", "stackdriver", "google", "guide", "cloud", "monitoring"] +aliases = ["/docs/grafana/latest/features/datasources/stackdriver", "/docs/grafana/latest/features/datasources/cloudmonitoring/"] +weight = 10 ++++ + +# Preconfigured Cloud Monitoring dashboards + +Google Cloud Monitoring data source ships with pre-configured dashboards for some of the most popular GCP services. These curated dashboards are based on similar dashboards in the GCP dashboard samples repository. See also, [Using Google Cloud Monitoring in Grafana]({{< relref "./_index.md" >}}) for detailed instructions on how to add and configure the Google Cloud Monitoring data source. +## Curated dashboards + +The curated dashboards are based on similar dashboards in the GCP dashboard samples repository. + +To import the curated dashboards: + +1. On the configuration page of your Cloud Monitoring data source, click the **Dashboards** tab. + +1. Click **Import** for the dashboard you would like to use. + +The data source of the newly created dashboard panels will be the one selected above. The dashboards have a template variable that is populated with the projects accessible by the configured service account every time the dashboard is loaded. After the dashboard is loaded, you can select the project you prefer from the drop-down list. + +In case you want to customize a dashboard, we recommend that you save it under a different name. Otherwise the dashboard will be overwritten when a new version of the dashboard is released. + +{{< docs-imagebox img="/img/docs/google-cloud-monitoring/curated-dashboards-7-4.png" max-width= "650px" >}} diff --git a/docs/sources/whatsnew/whats-new-in-v5-3.md b/docs/sources/whatsnew/whats-new-in-v5-3.md index 25d52fa0315..2befd1ef09a 100644 --- a/docs/sources/whatsnew/whats-new-in-v5-3.md +++ b/docs/sources/whatsnew/whats-new-in-v5-3.md @@ -37,7 +37,7 @@ The Grafana Stackdriver plugin comes with support for automatic unit detection. The data source is still in the `beta` phase, meaning it's currently in active development and is still missing one important feature - templating queries. Please try it out, but be aware of that it might be subject to changes and possible bugs. We would love to hear your feedback. -Please read [Using Google Stackdriver in Grafana]({{< relref "../datasources/cloudmonitoring/" >}}) for more detailed information on how to get started and use it. +Refer to [Using Google Stackdriver in Grafana]({{< relref "../datasources/google-cloud-monitoring/_index.md" >}}) for more detailed information on how to get started and use it. ## TV and Kiosk Mode diff --git a/docs/sources/whatsnew/whats-new-in-v5-4.md b/docs/sources/whatsnew/whats-new-in-v5-4.md index 3d7b32e6953..96312c59801 100644 --- a/docs/sources/whatsnew/whats-new-in-v5-4.md +++ b/docs/sources/whatsnew/whats-new-in-v5-4.md @@ -45,9 +45,9 @@ Stackdriver is the first data source which has support for a custom templating q create their very own templating query editor. Additionally, if Grafana is running on a Google Compute Engine (GCE) virtual machine, it is now possible for Grafana to automatically retrieve default credentials from the metadata server. -This has the advantage of not needing to generate a private key file for the service account and also not having to upload the file to Grafana. [Learn more]({{< relref "../datasources/cloudmonitoring/#using-gce-default-service-account" >}}). +This has the advantage of not needing to generate a private key file for the service account and also not having to upload the file to Grafana. [Learn more]({{< relref "../datasources/google-cloud-monitoring/_index.md/#using-gce-default-service-account" >}}). -Please read [Using Google Stackdriver in Grafana]({{< relref "../datasources/cloudmonitoring/" >}}) for more detailed information on how to get started and use it. +Please read [Using Google Stackdriver in Grafana]({{< relref "../datasources/google-cloud-monitoring/_index.md/" >}}) for more detailed information on how to get started and use it.
diff --git a/docs/sources/whatsnew/whats-new-in-v6-0.md b/docs/sources/whatsnew/whats-new-in-v6-0.md index ac9872fbc59..671b27ca6fe 100644 --- a/docs/sources/whatsnew/whats-new-in-v6-0.md +++ b/docs/sources/whatsnew/whats-new-in-v6-0.md @@ -114,7 +114,7 @@ will be shared soon. Built-in support for [Google Stackdriver](https://cloud.google.com/stackdriver/) is officially released in Grafana 6.0. Beta support was added in Grafana 5.3 and we have added lots of improvements since then. -To get started read the guide: [Using Google Stackdriver in Grafana]({{< relref "../datasources/cloudmonitoring/" >}}). +To get started read the guide: [Using Google Stackdriver in Grafana]({{< relref "../datasources/google-cloud-monitoring/_index.md/" >}}). ## Azure Monitor data source diff --git a/docs/sources/whatsnew/whats-new-in-v7-0.md b/docs/sources/whatsnew/whats-new-in-v7-0.md index 93feae3b051..9a2139d5f2b 100644 --- a/docs/sources/whatsnew/whats-new-in-v7-0.md +++ b/docs/sources/whatsnew/whats-new-in-v7-0.md @@ -179,7 +179,7 @@ It was released as a beta feature in Grafana 6.7. The feedback has been really p ## Stackdriver data source supports Service Monitoring -[Service monitoring](https://cloud.google.com/service-monitoring) in Google Cloud Platform (GCP) enables you to monitor based on Service Level Objectives (SLOs) for your GCP services. The new SLO query builder in the Stackdriver data source allows you to display SLO data in Grafana. Read more about it in the [Stackdriver data source documentation]({{< relref "../datasources/cloudmonitoring/#slo-service-level-objective-queries" >}}). +[Service monitoring](https://cloud.google.com/service-monitoring) in Google Cloud Platform (GCP) enables you to monitor based on Service Level Objectives (SLOs) for your GCP services. The new SLO query builder in the Stackdriver data source allows you to display SLO data in Grafana. Read more about it in the [Stackdriver data source documentation]({{< relref "../datasources/google-cloud-monitoring/_index.md/#slo-service-level-objective-queries" >}}). ## Time zone support diff --git a/docs/sources/whatsnew/whats-new-in-v7-1.md b/docs/sources/whatsnew/whats-new-in-v7-1.md index 33f7ad16e16..65a1c26b16a 100644 --- a/docs/sources/whatsnew/whats-new-in-v7-1.md +++ b/docs/sources/whatsnew/whats-new-in-v7-1.md @@ -83,7 +83,7 @@ Additionally, the Raw Edit mode for Application Insights Analytics has been repl ## Deep linking for Google Cloud Monitoring (formerly named Google Stackdriver) data source -A new feature in Grafana 7.1 is [deep linking from Grafana panels to the Metrics Explorer in Google Cloud Console]({{}}). Click on a time series in the panel to see a context menu with a link to View in Metrics explorer in Google Cloud Console. Clicking that link opens the Metrics explorer in the Monitoring Google Cloud Console and runs the query from the Grafana panel there. +A new feature in Grafana 7.1 is [deep linking from Grafana panels to the Metrics Explorer in Google Cloud Console]({{}}). Click on a time series in the panel to see a context menu with a link to View in Metrics explorer in Google Cloud Console. Clicking that link opens the Metrics explorer in the Monitoring Google Cloud Console and runs the query from the Grafana panel there. ## Time range picker update diff --git a/docs/sources/whatsnew/whats-new-in-v7-3.md b/docs/sources/whatsnew/whats-new-in-v7-3.md index b38f6e34f2f..3a8d9a36727 100644 --- a/docs/sources/whatsnew/whats-new-in-v7-3.md +++ b/docs/sources/whatsnew/whats-new-in-v7-3.md @@ -75,7 +75,7 @@ The updated Google Cloud monitoring data source is shipped with pre-configured d To import the pre-configured dashboards, go to the configuration page of your Google Cloud Monitoring data source and click on the `Dashboards` tab. Click `Import` for the dashboard you would like to use. To customize the dashboard, we recommend to save the dashboard under a different name, because otherwise the dashboard will be overwritten when a new version of the dashboard is released. -For more details, see the [Google Cloud Monitoring docs]({{}}) +For more details, see the [Google Cloud Monitoring docs]({{}}) ## Shorten URL for dashboards and Explore diff --git a/public/app/plugins/datasource/cloud-monitoring/partials/config.html b/public/app/plugins/datasource/cloud-monitoring/partials/config.html index df4e95a82ca..84e61d1eda4 100644 --- a/public/app/plugins/datasource/cloud-monitoring/partials/config.html +++ b/public/app/plugins/datasource/cloud-monitoring/partials/config.html @@ -2,20 +2,19 @@

Google Cloud Monitoring Authentication

- There are two ways to authenticate the Google Cloud Monitoring plugin - either by uploading a Service Account key file, or by + There are two ways to authenticate the Google Cloud Monitoring plugin - either by uploading a Service Account key file or by automatically retrieving credentials from the Google metadata server. The latter option is only available when running Grafana on a GCE virtual machine.

Uploading a Service Account Key File

- First you need to create a Google Cloud Platform (GCP) Service Account for the Project you want to show data for. - A Grafana datasource integrates with one GCP Project. If you want to visualize data from multiple GCP Projects - then you need to create one datasource per GCP Project. + There are two ways to authenticate the Google Cloud Monitoring plugin. You can upload a Service Account key file or automatically retrieve + credentials from the Google metadata server. The latter option is only available when running Grafana on a GCE virtual machine.

The Monitoring Viewer role provides all the permissions that Grafana needs. The following API - needs to be enabled on GCP for the datasource to work: + needs to be enabled on GCP for the data source to work: Detailed instructions on how to create a Service Account can be found - in the documentation.

From 2028f89c4e7c2778a304069f705f34c0cbde5170 Mon Sep 17 00:00:00 2001 From: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> Date: Thu, 28 Jan 2021 18:27:49 -0500 Subject: [PATCH 38/41] Added section "Curated dashboards for Google Cloud Monitoring" for 7.4 What's New (#30724) * Added content for what's new, removed one duplicate line from preconfigured-cloud-monitoring topic * Update docs/sources/whatsnew/whats-new-in-v7-4.md Co-authored-by: Diana Payton <52059945+oddlittlebird@users.noreply.github.com> Co-authored-by: Diana Payton <52059945+oddlittlebird@users.noreply.github.com> --- .../preconfig-cloud-monitoring-dashboards.md | 2 -- docs/sources/whatsnew/whats-new-in-v7-4.md | 10 +++++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/sources/datasources/google-cloud-monitoring/preconfig-cloud-monitoring-dashboards.md b/docs/sources/datasources/google-cloud-monitoring/preconfig-cloud-monitoring-dashboards.md index 2160f914cd1..7b9b2e07fdf 100644 --- a/docs/sources/datasources/google-cloud-monitoring/preconfig-cloud-monitoring-dashboards.md +++ b/docs/sources/datasources/google-cloud-monitoring/preconfig-cloud-monitoring-dashboards.md @@ -11,8 +11,6 @@ weight = 10 Google Cloud Monitoring data source ships with pre-configured dashboards for some of the most popular GCP services. These curated dashboards are based on similar dashboards in the GCP dashboard samples repository. See also, [Using Google Cloud Monitoring in Grafana]({{< relref "./_index.md" >}}) for detailed instructions on how to add and configure the Google Cloud Monitoring data source. ## Curated dashboards -The curated dashboards are based on similar dashboards in the GCP dashboard samples repository. - To import the curated dashboards: 1. On the configuration page of your Cloud Monitoring data source, click the **Dashboards** tab. diff --git a/docs/sources/whatsnew/whats-new-in-v7-4.md b/docs/sources/whatsnew/whats-new-in-v7-4.md index c4b47af7d9e..338c3392d62 100644 --- a/docs/sources/whatsnew/whats-new-in-v7-4.md +++ b/docs/sources/whatsnew/whats-new-in-v7-4.md @@ -139,10 +139,18 @@ Unlike the visual query builder, MQL allows you to control the time range and pe MQL uses a set of operations and functions. Operations are linked together using the common pipe mechanism, where the output of one operation becomes the input to the next. Linking operations makes it possible to build up complex queries incrementally. -Once query type Metrics is selected in the Cloud Monitoring query editor, you can toggle between the editor modes for visual query builder and MQL. +Once query type Metrics is selected in the Cloud Monitoring query editor, you can toggle between the editor modes for visual query builder and MQL. For more information, refer to the [Google Cloud Monitoring docs]({{}}). Many thanks to [mtanda](https://github.com/mtanda) this contribution! +## Curated dashboards for Google Cloud Monitoring + +Google Cloud Monitoring data source ships with pre-configured dashboards for some of the most popular GCP services. These curated dashboards are based on similar dashboards in the GCP dashboard samples repository. In this release, we have expanded the set of pre-configured dashboards. + +{{< docs-imagebox img="/img/docs/google-cloud-monitoring/curated-dashboards-7-4.png" max-width= "650px" >}} + +If you want to customize a dashboard, we recommend that you save it under a different name. Otherwise the dashboard will be overwritten when a new version of the dashboard is released. For more information, refer to the [Google Cloud Monitoring docs]({{}}). + ### Query Editor Help The feature previously referred to as DataSource Start Pages or Cheat Sheets has been renamed to Query Editor Help, and is now supported in panel query editors (depending on the data source), as well as in Explore. From 0b1f5c5e326bc6bf0e6ff7d23abe5b7b49aff2c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Fri, 29 Jan 2021 06:11:13 +0100 Subject: [PATCH 39/41] PanelLibrary: better handling of deleted panels (#30709) --- .../panel-library/panel-library.json | 6 ++-- pkg/services/librarypanels/database.go | 11 ++++-- pkg/services/librarypanels/librarypanels.go | 11 +++++- .../librarypanels/librarypanels_test.go | 35 +++++++++++++++++-- 4 files changed, 56 insertions(+), 7 deletions(-) diff --git a/devenv/dev-dashboards/panel-library/panel-library.json b/devenv/dev-dashboards/panel-library/panel-library.json index caa684a6b39..e73259bda52 100644 --- a/devenv/dev-dashboards/panel-library/panel-library.json +++ b/devenv/dev-dashboards/panel-library/panel-library.json @@ -142,7 +142,8 @@ }, "id": 3, "libraryPanel": { - "uid": "MAnX2ifMk" + "uid": "MAnX2ifMk", + "name": "React Table" } }, { @@ -154,7 +155,8 @@ }, "id": 2, "libraryPanel": { - "uid": "g1sNpCaMz" + "uid": "g1sNpCaMz", + "name": "React Gauge" } } ], diff --git a/pkg/services/librarypanels/database.go b/pkg/services/librarypanels/database.go index b140b91e63c..b53a2b59c08 100644 --- a/pkg/services/librarypanels/database.go +++ b/pkg/services/librarypanels/database.go @@ -113,13 +113,20 @@ func (lps *LibraryPanelService) connectLibraryPanelsForDashboard(c *models.ReqCo // deleteLibraryPanel deletes a Library Panel. func (lps *LibraryPanelService) deleteLibraryPanel(c *models.ReqContext, uid string) error { - orgID := c.SignedInUser.OrgId return lps.SQLStore.WithTransactionalDbSession(context.Background(), func(session *sqlstore.DBSession) error { - result, err := session.Exec("DELETE FROM library_panel WHERE uid=? and org_id=?", uid, orgID) + panel, err := getLibraryPanel(session, uid, c.SignedInUser.OrgId) if err != nil { return err } + if _, err := session.Exec("DELETE FROM library_panel_dashboard WHERE librarypanel_id=?", panel.ID); err != nil { + return err + } + + result, err := session.Exec("DELETE FROM library_panel WHERE id=?", panel.ID) + if err != nil { + return err + } if rowsAffected, err := result.RowsAffected(); err != nil { return err } else if rowsAffected != 1 { diff --git a/pkg/services/librarypanels/librarypanels.go b/pkg/services/librarypanels/librarypanels.go index 171a5e51872..de6340b7099 100644 --- a/pkg/services/librarypanels/librarypanels.go +++ b/pkg/services/librarypanels/librarypanels.go @@ -71,7 +71,16 @@ func (lps *LibraryPanelService) LoadLibraryPanelsForDashboard(dash *models.Dashb libraryPanelInDB, ok := libraryPanels[uid] if !ok { - return fmt.Errorf("found connection to library panel %q that isn't in database", uid) + name := libraryPanel.Get("name").MustString() + elem := dash.Data.Get("panels").GetIndex(i) + elem.Set("gridPos", panelAsJSON.Get("gridPos").MustMap()) + elem.Set("id", panelAsJSON.Get("id").MustInt64()) + elem.Set("type", fmt.Sprintf("Name: \"%s\", UID: \"%s\"", name, uid)) + elem.Set("libraryPanel", map[string]interface{}{ + "uid": uid, + "name": name, + }) + continue } // we have a match between what is stored in db and in dashboard json diff --git a/pkg/services/librarypanels/librarypanels_test.go b/pkg/services/librarypanels/librarypanels_test.go index bd9eebc9442..4b398ea096e 100644 --- a/pkg/services/librarypanels/librarypanels_test.go +++ b/pkg/services/librarypanels/librarypanels_test.go @@ -650,7 +650,7 @@ func TestLoadLibraryPanelsForDashboard(t *testing.T) { require.EqualError(t, err, errLibraryPanelHeaderUIDMissing.Error()) }) - testScenario(t, "When an admin tries to load a dashboard with a library panel that is not connected, it should fail", + testScenario(t, "When an admin tries to load a dashboard with a library panel that is not connected, it should set correct JSON and continue", func(t *testing.T, sc scenarioContext) { command := getCreateCommand(1, "Text - Library Panel1") response := sc.service.createHandler(sc.reqContext, command) @@ -692,7 +692,38 @@ func TestLoadLibraryPanelsForDashboard(t *testing.T) { } err = sc.service.LoadLibraryPanelsForDashboard(&dash) - require.EqualError(t, err, fmt.Errorf("found connection to library panel %q that isn't in database", existing.Result.UID).Error()) + require.NoError(t, err) + expectedJSON := map[string]interface{}{ + "panels": []interface{}{ + map[string]interface{}{ + "id": int64(1), + "gridPos": map[string]interface{}{ + "h": 6, + "w": 6, + "x": 0, + "y": 0, + }, + }, + map[string]interface{}{ + "id": int64(2), + "gridPos": map[string]interface{}{ + "h": 6, + "w": 6, + "x": 6, + "y": 0, + }, + "libraryPanel": map[string]interface{}{ + "uid": existing.Result.UID, + "name": existing.Result.Name, + }, + "type": fmt.Sprintf("Name: \"%s\", UID: \"%s\"", existing.Result.Name, existing.Result.UID), + }, + }, + } + expected := simplejson.NewFromAny(expectedJSON) + if diff := cmp.Diff(expected.Interface(), dash.Data.Interface(), getCompareOptions()...); diff != "" { + t.Fatalf("Result mismatch (-want +got):\n%s", diff) + } }) } From 8744ad361bfabfe6e7cba95f43b1f3d0eecf3e85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Fri, 29 Jan 2021 09:24:25 +0100 Subject: [PATCH 40/41] Variables: Fixes so text format will show All instead of custom all (#30730) --- .../app/features/templating/formatRegistry.ts | 7 ++++--- .../features/templating/template_srv.test.ts | 19 +++++++++++++++++++ .../app/features/templating/template_srv.ts | 8 ++++---- .../test/core/utils/silenceConsoleOutput.ts | 2 ++ 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/public/app/features/templating/formatRegistry.ts b/public/app/features/templating/formatRegistry.ts index ce8dbafb2bc..c981c25df44 100644 --- a/public/app/features/templating/formatRegistry.ts +++ b/public/app/features/templating/formatRegistry.ts @@ -1,7 +1,8 @@ import kbn from 'app/core/utils/kbn'; -import { Registry, RegistryItem, VariableModel, textUtil, dateTime } from '@grafana/data'; -import { map, isArray, replace } from 'lodash'; +import { dateTime, Registry, RegistryItem, textUtil, VariableModel } from '@grafana/data'; +import { isArray, map, replace } from 'lodash'; import { formatVariableLabel } from '../variables/shared/formatVariable'; +import { ALL_VARIABLE_TEXT, ALL_VARIABLE_VALUE } from '../variables/state/types'; export interface FormatOptions { value: any; @@ -204,7 +205,7 @@ export const formatRegistry = new Registry(() => { description: 'Format variables in their text representation. Example in multi variable scenario A + B + C.', formatter: (options, variable) => { if (typeof options.text === 'string') { - return options.text; + return options.value === ALL_VARIABLE_VALUE ? ALL_VARIABLE_TEXT : options.text; } const current = (variable as any)?.current; diff --git a/public/app/features/templating/template_srv.test.ts b/public/app/features/templating/template_srv.test.ts index ab973a3301f..1c433f277cc 100644 --- a/public/app/features/templating/template_srv.test.ts +++ b/public/app/features/templating/template_srv.test.ts @@ -1,7 +1,9 @@ import { dateTime, TimeRange } from '@grafana/data'; import { initTemplateSrv } from '../../../test/helpers/initTemplateSrv'; +import { silenceConsoleOutput } from '../../../test/core/utils/silenceConsoleOutput'; describe('templateSrv', () => { + silenceConsoleOutput(); let _templateSrv: any; describe('init', () => { @@ -253,6 +255,11 @@ describe('templateSrv', () => { expect(target).toBe('this.*.filters'); }); + it('should replace ${test:text} with "all" value', () => { + const target = _templateSrv.replace('this.${test:text}.filters', {}); + expect(target).toBe('this.All.filters'); + }); + it('should not escape custom all value', () => { const target = _templateSrv.replace('this.$test', {}, 'regex'); expect(target).toBe('this.*'); @@ -524,6 +531,13 @@ describe('templateSrv', () => { current: { value: '$__all', text: '' }, options: [{ value: '$__all' }, { value: 'db1', text: 'Database 1' }, { value: 'db2', text: 'Database 2' }], }, + { + type: 'custom', + name: 'custom_all_value', + allValue: 'CUSTOM_ALL', + current: { value: '$__all', text: '' }, + options: [{ value: '$__all' }, { value: 'A-Value', text: 'This A' }, { value: 'B-Value', text: 'This B' }], + }, ]); _templateSrv.updateIndex(); }); @@ -542,6 +556,11 @@ describe('templateSrv', () => { const target = _templateSrv.replaceWithText('Db: $databases'); expect(target).toBe('Db: All'); }); + + it('should replace $__all with All for values with custom all', () => { + const target = _templateSrv.replaceWithText('Custom: $custom_all_value'); + expect(target).toBe('Custom: All'); + }); }); describe('built in interval variables', () => { diff --git a/public/app/features/templating/template_srv.ts b/public/app/features/templating/template_srv.ts index a0174f56d08..0a881f69174 100644 --- a/public/app/features/templating/template_srv.ts +++ b/public/app/features/templating/template_srv.ts @@ -5,8 +5,8 @@ import { variableRegex } from '../variables/utils'; import { isAdHoc } from '../variables/guard'; import { VariableModel } from '../variables/types'; import { setTemplateSrv, TemplateSrv as BaseTemplateSrv } from '@grafana/runtime'; -import { formatRegistry, FormatOptions } from './formatRegistry'; -import { ALL_VARIABLE_TEXT } from '../variables/state/types'; +import { FormatOptions, formatRegistry } from './formatRegistry'; +import { ALL_VARIABLE_TEXT, ALL_VARIABLE_VALUE } from '../variables/state/types'; interface FieldAccessorCache { [key: string]: (obj: any) => any; @@ -282,7 +282,7 @@ export class TemplateSrv implements BaseTemplateSrv { value = this.getAllValue(variable); text = ALL_VARIABLE_TEXT; // skip formatting of custom all values - if (variable.allValue) { + if (variable.allValue && fmt !== 'text') { return this.replace(value); } } @@ -302,7 +302,7 @@ export class TemplateSrv implements BaseTemplateSrv { } isAllValue(value: any) { - return value === '$__all' || (Array.isArray(value) && value[0] === '$__all'); + return value === ALL_VARIABLE_VALUE || (Array.isArray(value) && value[0] === ALL_VARIABLE_VALUE); } replaceWithText(target: string, scopedVars?: ScopedVars) { diff --git a/public/test/core/utils/silenceConsoleOutput.ts b/public/test/core/utils/silenceConsoleOutput.ts index 3205c7db7aa..cd63508ccbf 100644 --- a/public/test/core/utils/silenceConsoleOutput.ts +++ b/public/test/core/utils/silenceConsoleOutput.ts @@ -4,6 +4,7 @@ export const silenceConsoleOutput = () => { jest.spyOn(console, 'error').mockImplementation(jest.fn()); jest.spyOn(console, 'debug').mockImplementation(jest.fn()); jest.spyOn(console, 'info').mockImplementation(jest.fn()); + jest.spyOn(console, 'warn').mockImplementation(jest.fn()); }); afterEach(() => { @@ -11,5 +12,6 @@ export const silenceConsoleOutput = () => { jest.spyOn(console, 'error').mockRestore(); jest.spyOn(console, 'debug').mockRestore(); jest.spyOn(console, 'info').mockRestore(); + jest.spyOn(console, 'warn').mockRestore(); }); }; From 52a8f2bf7e65cfe7ae17663d6b9d4fed5d5b4574 Mon Sep 17 00:00:00 2001 From: Arve Knudsen Date: Fri, 29 Jan 2021 10:26:29 +0100 Subject: [PATCH 41/41] PluginCiE2E: Upgrade base images (#30696) Signed-off-by: Arve Knudsen --- .../docker/grafana-plugin-ci-e2e/Dockerfile | 3 +-- .../docker/grafana-plugin-ci-e2e/common.sh | 2 +- .../docker/grafana-plugin-ci-e2e/scripts/deploy.sh | 8 ++++---- .../docker/grafana-plugin-ci-e2e/test/docker-compose.yml | 2 +- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/grafana-toolkit/docker/grafana-plugin-ci-e2e/Dockerfile b/packages/grafana-toolkit/docker/grafana-plugin-ci-e2e/Dockerfile index 23fd259ae22..0b336851a0f 100644 --- a/packages/grafana-toolkit/docker/grafana-plugin-ci-e2e/Dockerfile +++ b/packages/grafana-toolkit/docker/grafana-plugin-ci-e2e/Dockerfile @@ -1,6 +1,5 @@ -FROM debian:buster-slim +FROM debian:testing-20210111-slim -USER root ENV DEBIAN_FRONTEND=noninteractive COPY scripts scripts diff --git a/packages/grafana-toolkit/docker/grafana-plugin-ci-e2e/common.sh b/packages/grafana-toolkit/docker/grafana-plugin-ci-e2e/common.sh index c55a8135fd2..08da2709cc5 100755 --- a/packages/grafana-toolkit/docker/grafana-plugin-ci-e2e/common.sh +++ b/packages/grafana-toolkit/docker/grafana-plugin-ci-e2e/common.sh @@ -5,5 +5,5 @@ ## DOCKER_IMAGE_BASE_NAME="grafana/grafana-plugin-ci-e2e" -DOCKER_IMAGE_VERSION="1.0.2" +DOCKER_IMAGE_VERSION="1.1.0" DOCKER_IMAGE_NAME="${DOCKER_IMAGE_BASE_NAME}:${DOCKER_IMAGE_VERSION}" diff --git a/packages/grafana-toolkit/docker/grafana-plugin-ci-e2e/scripts/deploy.sh b/packages/grafana-toolkit/docker/grafana-plugin-ci-e2e/scripts/deploy.sh index e274c311a98..1ec55dffd4e 100755 --- a/packages/grafana-toolkit/docker/grafana-plugin-ci-e2e/scripts/deploy.sh +++ b/packages/grafana-toolkit/docker/grafana-plugin-ci-e2e/scripts/deploy.sh @@ -22,16 +22,16 @@ source "/etc/profile" npm i -g yarn # Install Go -filename="go1.15.1.linux-amd64.tar.gz" -get_file "https://dl.google.com/go/$filename" "/tmp/$filename" "70ac0dbf60a8ee9236f337ed0daa7a4c3b98f6186d4497826f68e97c0c0413f6" +filename="go1.15.7.linux-amd64.tar.gz" +get_file "https://dl.google.com/go/$filename" "/tmp/$filename" "0d142143794721bb63ce6c8a6180c4062bcf8ef4715e7d6d6609f3a8282629b3" untar_file "/tmp/$filename" # Install golangci-lint -GOLANGCILINT_VERSION=1.31.0 +GOLANGCILINT_VERSION=1.36.0 filename="golangci-lint-${GOLANGCILINT_VERSION}-linux-amd64" get_file "https://github.com/golangci/golangci-lint/releases/download/v${GOLANGCILINT_VERSION}/$filename.tar.gz" \ "/tmp/$filename.tar.gz" \ - "9a5d47b51442d68b718af4c7350f4406cdc087e2236a5b9ae52f37aebede6cb3" + "9b8856b3a1c9bfbcf3a06b78e94611763b79abd9751c245246787cd3bf0e78a5" untar_file "/tmp/$filename.tar.gz" ln -s /usr/local/${filename}/golangci-lint /usr/local/bin/golangci-lint ln -s /usr/local/go/bin/go /usr/local/bin/go diff --git a/packages/grafana-toolkit/docker/grafana-plugin-ci-e2e/test/docker-compose.yml b/packages/grafana-toolkit/docker/grafana-plugin-ci-e2e/test/docker-compose.yml index c29a5ad89ca..5d6297c4833 100644 --- a/packages/grafana-toolkit/docker/grafana-plugin-ci-e2e/test/docker-compose.yml +++ b/packages/grafana-toolkit/docker/grafana-plugin-ci-e2e/test/docker-compose.yml @@ -9,7 +9,7 @@ services: - ${HOME}/.ssh:/root/.ssh - ../../..:/root/grafana-toolkit cibuilt: - image: "srclosson/grafana-plugin-ci-e2e" + image: "grafana/grafana-plugin-ci-e2e" user: root volumes: - ../scripts:/root/scripts