diff --git a/CHANGELOG.md b/CHANGELOG.md index ed5c3a62e..1f67eece4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ NOTE: As semantic versioning states all 0.y.z releases can contain breaking chan - [#149](https://github.com/kobsio/kobs/pull/149): Add SQL plugin to run queries against a configured SQL database instance. For now we are supporting the `clickhouse`, `postgres` and `mysql` driver. - [#151](https://github.com/kobsio/kobs/pull/151): Add actions for in log details view of the ClickHouse, so that users can filter based on the value of a field. - [#156](https://github.com/kobsio/kobs/pull/156): Add tags for applications. +- [#159](https://github.com/kobsio/kobs/pull/159): Allow users to select a time range within the logs chart in the ClickHouse plugin. ### Fixed diff --git a/plugins/clickhouse/package.json b/plugins/clickhouse/package.json index 39c787174..a3138ffa4 100644 --- a/plugins/clickhouse/package.json +++ b/plugins/clickhouse/package.json @@ -11,8 +11,7 @@ }, "dependencies": { "@kobsio/plugin-core": "*", - "@nivo/bar": "^0.73.1", - "@nivo/tooltip": "^0.73.0", + "@patternfly/react-charts": "^6.15.23", "@patternfly/react-core": "^4.128.2", "@patternfly/react-icons": "^4.10.11", "@patternfly/react-table": "^4.27.24", @@ -21,6 +20,7 @@ "@types/react-router-dom": "^5.1.7", "react": "^17.0.2", "react-dom": "^17.0.2", + "react-intersection-observer": "^8.32.1", "react-query": "^3.17.2", "react-router-dom": "^5.2.0", "typescript": "^4.3.4" diff --git a/plugins/clickhouse/pkg/instance/instance.go b/plugins/clickhouse/pkg/instance/instance.go index 4f0067492..5b83c343f 100644 --- a/plugins/clickhouse/pkg/instance/instance.go +++ b/plugins/clickhouse/pkg/instance/instance.go @@ -82,11 +82,8 @@ func (i *Instance) GetLogs(ctx context.Context, query, order, orderBy string, ti } buckets = append(buckets, Bucket{ - Interval: intervalData.Unix(), - IntervalFormatted: "", - Count: countData, - // Formatting is handled on the client side. - // IntervalFormatted: intervalData.Format("01-02 15:04:05"), + Interval: intervalData.Unix(), + Count: countData, }) } diff --git a/plugins/clickhouse/pkg/instance/structs.go b/plugins/clickhouse/pkg/instance/structs.go index cbe2f0e18..f244202bc 100644 --- a/plugins/clickhouse/pkg/instance/structs.go +++ b/plugins/clickhouse/pkg/instance/structs.go @@ -33,7 +33,6 @@ type Row struct { // Bucket is the struct which is used to represent the distribution of the returned rows for a logs query for the given // time range. type Bucket struct { - Interval int64 `json:"interval"` - IntervalFormatted string `json:"intervalFormatted"` - Count int64 `json:"count"` + Interval int64 `json:"interval"` + Count int64 `json:"count"` } diff --git a/plugins/clickhouse/src/components/page/Logs.tsx b/plugins/clickhouse/src/components/page/Logs.tsx index 4b3229b72..dffc2f7f8 100644 --- a/plugins/clickhouse/src/components/page/Logs.tsx +++ b/plugins/clickhouse/src/components/page/Logs.tsx @@ -29,6 +29,7 @@ interface IPageLogsProps { orderBy: string; query: string; addFilter: (filter: string) => void; + changeTime: (times: IPluginTimes) => void; selectField: (field: string) => void; times: IPluginTimes; } @@ -41,6 +42,7 @@ const PageLogs: React.FunctionComponent = ({ query, addFilter, selectField, + changeTime, times, }: IPageLogsProps) => { const history = useHistory(); @@ -136,7 +138,7 @@ const PageLogs: React.FunctionComponent = ({ {isFetching && } - + diff --git a/plugins/clickhouse/src/components/page/LogsToolbar.tsx b/plugins/clickhouse/src/components/page/LogsToolbar.tsx index 5b0ee78b7..4af72fdb2 100644 --- a/plugins/clickhouse/src/components/page/LogsToolbar.tsx +++ b/plugins/clickhouse/src/components/page/LogsToolbar.tsx @@ -80,9 +80,9 @@ const LogsToolbar: React.FunctionComponent = ({ }; useEffect(() => { - setData({ ...data, query: query }); + setData({ ...data, query: query, times: times }); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [query]); + }, [query, times]); return ( diff --git a/plugins/clickhouse/src/components/page/Page.tsx b/plugins/clickhouse/src/components/page/Page.tsx index 230367c17..819a842c3 100644 --- a/plugins/clickhouse/src/components/page/Page.tsx +++ b/plugins/clickhouse/src/components/page/Page.tsx @@ -2,8 +2,8 @@ import { PageSection, PageSectionVariants, Title } from '@patternfly/react-core' import React, { useEffect, useState } from 'react'; import { useHistory, useLocation } from 'react-router-dom'; +import { IPluginPageProps, IPluginTimes } from '@kobsio/plugin-core'; import { IOptions } from '../../utils/interfaces'; -import { IPluginPageProps } from '@kobsio/plugin-core'; import Logs from './Logs'; import LogsToolbar from './LogsToolbar'; import { getOptionsFromSearch } from '../../utils/helpers'; @@ -47,6 +47,10 @@ const Page: React.FunctionComponent = ({ name, displayName, de changeOptions({ ...options, query: `${options.query} ${filter}` }); }; + const changeTime = (times: IPluginTimes): void => { + changeOptions({ ...options, times: times }); + }; + // useEffect is used to set the options every time the search location for the current URL changes. The URL is changed // via the changeOptions function. When the search location is changed we modify the options state. useEffect(() => { @@ -84,6 +88,7 @@ const Page: React.FunctionComponent = ({ name, displayName, de order={options.order} orderBy={options.orderBy} addFilter={addFilter} + changeTime={changeTime} selectField={selectField} times={options.times} /> diff --git a/plugins/clickhouse/src/components/panel/LogsChart.tsx b/plugins/clickhouse/src/components/panel/LogsChart.tsx index 20daeec23..b87ce5390 100644 --- a/plugins/clickhouse/src/components/panel/LogsChart.tsx +++ b/plugins/clickhouse/src/components/panel/LogsChart.tsx @@ -1,97 +1,101 @@ -import React from 'react'; -import { ResponsiveBarCanvas } from '@nivo/bar'; -import { SquareIcon } from '@patternfly/react-icons'; -import { TooltipWrapper } from '@nivo/tooltip'; +import { + Chart, + ChartAxis, + ChartBar, + ChartLegendTooltip, + ChartThemeColor, + createContainer, +} from '@patternfly/react-charts'; +import React, { useEffect, useRef, useState } from 'react'; -import { IBucket } from '../../utils/interfaces'; +import { IBucket, IDatum, IDomain, ILabel } from '../../utils/interfaces'; +import { IPluginTimes, formatTime } from '@kobsio/plugin-core'; interface ILogsChartProps { buckets?: IBucket[]; + changeTime?: (times: IPluginTimes) => void; } -const LogsChart: React.FunctionComponent = ({ buckets }: ILogsChartProps) => { - if (!buckets || buckets.length === 0) { +const LogsChart: React.FunctionComponent = ({ buckets, changeTime }: ILogsChartProps) => { + const refChart = useRef(null); + const [width, setWidth] = useState(0); + const [height, setHeight] = useState(0); + + // useEffect is executed on every render of this component. This is needed, so that we are able to use a width of 100% + // and a static height for the chart. + useEffect(() => { + if (refChart && refChart.current) { + setWidth(refChart.current.getBoundingClientRect().width); + setHeight(refChart.current.getBoundingClientRect().height); + } + }, []); + + const data: IDatum[] | undefined = + !buckets || buckets.length === 0 + ? undefined + : buckets.map((bucket) => { + return { + x: new Date(bucket.interval * 1000), + y: bucket.count, + }; + }); + + if (!data) { return
; } - const data: IBucket[] = buckets.map((bucket) => { - const d = new Date(bucket.interval * 1000); - - return { - count: bucket.count, - interval: bucket.interval, - intervalFormatted: `${('0' + (d.getMonth() + 1)).slice(-2)}-${('0' + d.getDate()).slice(-2)} ${( - '0' + d.getHours() - ).slice(-2)}:${('0' + d.getMinutes()).slice(-2)}:${('0' + d.getSeconds()).slice(-2)}`, - }; - }); + const CursorVoronoiContainer = changeTime + ? createContainer('voronoi', 'brush') + : createContainer('voronoi', 'cursor'); + const legendData = [{ childName: 'count', name: 'Document Count' }]; return ( -
- index % 2 === 0).map((bucket) => bucket.intervalFormatted), - }} - axisLeft={{ - format: '>-.0s', - legend: 'Count', - legendOffset: -40, - legendPosition: 'middle', - }} - borderColor={{ from: 'color', modifiers: [['darker', 1.6]] }} - borderRadius={0} - borderWidth={0} - colorBy="id" - colors={['#0066cc']} - data={data} - enableLabel={false} - enableGridX={false} - enableGridY={true} - groupMode="stacked" - indexBy="intervalFormatted" - indexScale={{ round: true, type: 'band' }} - isInteractive={true} - keys={['count']} - layout="vertical" - margin={{ bottom: 25, left: 50, right: 0, top: 0 }} - maxValue="auto" - minValue="auto" - reverse={false} - theme={{ - background: '#ffffff', - fontFamily: 'RedHatDisplay, Overpass, overpass, helvetica, arial, sans-serif', - fontSize: 10, - textColor: '#000000', - }} - // eslint-disable-next-line @typescript-eslint/explicit-function-return-type - tooltip={(tooltip) => { - const isFirstHalf = tooltip.index < data.length / 2; - - return ( - -
-
- {tooltip.data.intervalFormatted} -
-
- Documents: {tooltip.data.count || 0} -
-
-
- ); - }} - valueFormat="" - valueScale={{ type: 'linear' }} - /> +
+ `${datum.y}`} + labelComponent={ + formatTime(Math.floor(datum.x.getTime() / 1000))} + /> + } + mouseFollowTooltips={true} + onBrushDomainChangeEnd={(domain: IDomain): void => { + if (changeTime && domain.x.length === 2) { + changeTime({ + time: 'custom', + timeEnd: Math.floor(domain.x[1].getTime() / 1000), + timeStart: Math.floor(domain.x[0].getTime() / 1000), + }); + } + }} + voronoiDimension="x" + voronoiPadding={0} + /> + } + height={height} + legendData={legendData} + legendPosition={undefined} + padding={{ bottom: 30, left: 0, right: 0, top: 0 }} + scale={{ x: 'time', y: 'linear' }} + themeColor={ChartThemeColor.multiOrdered} + width={width} + > + + `${('0' + (tick.getMonth() + 1)).slice(-2)}-${('0' + tick.getDate()).slice(-2)} ${( + '0' + tick.getHours() + ).slice(-2)}:${('0' + tick.getMinutes()).slice(-2)}:${('0' + tick.getSeconds()).slice(-2)}` + } + showGrid={false} + /> + +
); }; diff --git a/plugins/clickhouse/src/utils/interfaces.ts b/plugins/clickhouse/src/utils/interfaces.ts index 2c67271ab..16abe8bbc 100644 --- a/plugins/clickhouse/src/utils/interfaces.ts +++ b/plugins/clickhouse/src/utils/interfaces.ts @@ -1,5 +1,3 @@ -import { BarDatum } from '@nivo/bar'; - import { IPluginTimes } from '@kobsio/plugin-core'; // IOptions is the interface for all options, which can be set for an ClickHouse query. @@ -41,8 +39,24 @@ export interface IDocument { [key: string]: any; } -export interface IBucket extends BarDatum { +export interface IBucket { interval: number; - intervalFormatted: string; count: number; } + +// IDatum, ILabel and IDomain interfaces are used for the logs chart. IDatum is the formate of the data points required +// by '@patternfly/react-charts. ILabel is the formate of the label and IDomain is the formate returned by the +// onBrushDomainChangeEnd function. +export interface IDatum { + x: Date; + y: number; +} + +export interface ILabel { + datum: IDatum; +} + +export interface IDomain { + x: Date[]; + y: number[]; +} diff --git a/yarn.lock b/yarn.lock index 5a25da9f2..f0764d5d4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2513,6 +2513,32 @@ resolved "https://registry.yarnpkg.com/@patternfly/patternfly/-/patternfly-4.132.2.tgz#6ec662e6b21a28302a52c5c1d702c9616d4cea04" integrity sha512-66qBgIpwPPeTUMTUUO6Z73XApvNXxn3uFaXMeVa09viYGDKzEX3L1FIfc4VzVk2okhk/9KJIYYgxofeuGi5v6A== +"@patternfly/react-charts@^6.15.23": + version "6.15.23" + resolved "https://registry.yarnpkg.com/@patternfly/react-charts/-/react-charts-6.15.23.tgz#0f0326ba59692b405081e38170879edbcdfc8eff" + integrity sha512-X8ou27onHXrkpcvv9AZhyinlw8vXzd9MFesDIKuXRwaQESdaPEznKIVg55ciVBj3tdAYBk5mQmxegh4UJFWSig== + dependencies: + "@patternfly/react-styles" "^4.11.16" + "@patternfly/react-tokens" "^4.12.18" + hoist-non-react-statics "^3.3.0" + lodash "^4.17.19" + tslib "^2.0.0" + victory-area "^35.9.0" + victory-axis "^35.9.0" + victory-bar "^35.9.0" + victory-chart "^35.9.0" + victory-core "^35.9.0" + victory-create-container "^35.9.1" + victory-group "^35.9.0" + victory-legend "^35.9.0" + victory-line "^35.9.0" + victory-pie "^35.9.0" + victory-scatter "^35.9.0" + victory-stack "^35.9.0" + victory-tooltip "^35.9.1" + victory-voronoi-container "^35.9.1" + victory-zoom-container "^35.9.0" + "@patternfly/react-core@^4.128.2", "@patternfly/react-core@^4.152.4": version "4.152.4" resolved "https://registry.yarnpkg.com/@patternfly/react-core/-/react-core-4.152.4.tgz#fa008d155ab0c4161aab27bb67ad88fb8689dee2" @@ -2536,6 +2562,11 @@ resolved "https://registry.yarnpkg.com/@patternfly/react-styles/-/react-styles-4.11.13.tgz#6595adc5ff40585add0128d27d420322b65b86a9" integrity sha512-svhnWIqZwJt1cOxwYjvz6lVYeL+c9D17xpKqlkJapXRxJL3ppTfIqwBrT3o9+02ElaXUTKt4xjMkSnEVjw4qxA== +"@patternfly/react-styles@^4.11.16": + version "4.11.16" + resolved "https://registry.yarnpkg.com/@patternfly/react-styles/-/react-styles-4.11.16.tgz#55327c57d086aadb9f0f4c0e67ab38856c3ca165" + integrity sha512-4ZFynQuJmRF7VbZeQSs44MX6MEvW7l7ZR8lMeChd8mxnQpG8pWtVUbcHdj9FFHPZVa+sPrgrZQl8QmhbqYyOsg== + "@patternfly/react-table@^4.27.24": version "4.29.58" resolved "https://registry.yarnpkg.com/@patternfly/react-table/-/react-table-4.29.58.tgz#be77a6eee6a60c26e1f6939aaae007f21be52355" @@ -2553,6 +2584,11 @@ resolved "https://registry.yarnpkg.com/@patternfly/react-tokens/-/react-tokens-4.12.15.tgz#af760a1b378edce85fd2f7394553911b6ee3c4f0" integrity sha512-lRW0qxGjuFEPMweBSQFHNRNoxavx5uR8b28f0lPN0Jlz4QsaCFVTmHM2XqflOHDpjE8SPJW/hJMSsyUrqnM5dw== +"@patternfly/react-tokens@^4.12.18": + version "4.12.18" + resolved "https://registry.yarnpkg.com/@patternfly/react-tokens/-/react-tokens-4.12.18.tgz#e8c75f19ecc33de180cef6cb3e9a6679c5ffeb7c" + integrity sha512-3bNUOSOMLmhxPku4fvopxt3StotaHGqHvlIDMxp9pGIgb0o02RyZ8JIioCCO1GkvPPIn6pKs/cGJDlB7zHV48Q== + "@pmmmwh/react-refresh-webpack-plugin@0.4.3": version "0.4.3" resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.4.3.tgz#1eec460596d200c0236bf195b078a5d1df89b766" @@ -5566,6 +5602,21 @@ d3-array@2, d3-array@^2.3.0: dependencies: internmap "^1.0.0" +d3-array@^1.2.0: + version "1.2.4" + resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.4.tgz#635ce4d5eea759f6f605863dbcfc30edc737f71f" + integrity sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw== + +d3-collection@1: + version "1.0.7" + resolved "https://registry.yarnpkg.com/d3-collection/-/d3-collection-1.0.7.tgz#349bd2aa9977db071091c13144d5e4f16b5b310e" + integrity sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A== + +d3-color@1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-1.4.1.tgz#c52002bf8846ada4424d55d97982fef26eb3bc8a" + integrity sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q== + "d3-color@1 - 2", d3-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-2.0.0.tgz#8d625cab42ed9b8f601a1760a389f7ea9189d62e" @@ -5578,21 +5629,33 @@ d3-delaunay@^5.3.0: dependencies: delaunator "4" -"d3-format@1 - 2": - version "2.0.0" - resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-2.0.0.tgz#a10bcc0f986c372b729ba447382413aabf5b0767" - integrity sha512-Ab3S6XuE/Q+flY96HXT0jOXcM4EAClYFnRGY5zsjRGNy6qCYrQsMffs7cV5Q9xejb35zxW5hf/guKw34kvIKsA== +d3-ease@^1.0.0: + version "1.0.7" + resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-1.0.7.tgz#9a834890ef8b8ae8c558b2fe55bd57f5993b85e2" + integrity sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ== -d3-format@^1.4.4: +d3-format@1, d3-format@^1.4.4: version "1.4.5" resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-1.4.5.tgz#374f2ba1320e3717eb74a9356c67daee17a7edb4" integrity sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ== +"d3-format@1 - 2": + version "2.0.0" + resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-2.0.0.tgz#a10bcc0f986c372b729ba447382413aabf5b0767" + integrity sha512-Ab3S6XuE/Q+flY96HXT0jOXcM4EAClYFnRGY5zsjRGNy6qCYrQsMffs7cV5Q9xejb35zxW5hf/guKw34kvIKsA== + d3-hierarchy@^1.1.8: version "1.1.9" resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz#2f6bee24caaea43f8dc37545fa01628559647a83" integrity sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ== +d3-interpolate@1, d3-interpolate@^1.1.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-1.4.0.tgz#526e79e2d80daa383f9e0c1c1c7dcc0f0583e987" + integrity sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA== + dependencies: + d3-color "1" + "d3-interpolate@1 - 2", "d3-interpolate@1.2.0 - 2", d3-interpolate@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-2.0.1.tgz#98be499cfb8a3b94d4ff616900501a64abc91163" @@ -5613,6 +5676,19 @@ d3-scale-chromatic@^2.0.0: d3-color "1 - 2" d3-interpolate "1 - 2" +d3-scale@^1.0.0: + version "1.0.7" + resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-1.0.7.tgz#fa90324b3ea8a776422bd0472afab0b252a0945d" + integrity sha512-KvU92czp2/qse5tUfGms6Kjig0AhHOwkzXG0+PqIJB3ke0WUv088AHMZI0OssO9NCkXt4RP8yju9rpH8aGB7Lw== + dependencies: + d3-array "^1.2.0" + d3-collection "1" + d3-color "1" + d3-format "1" + d3-interpolate "1" + d3-time "1" + d3-time-format "2" + d3-scale@^3.2.3: version "3.3.0" resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-3.3.0.tgz#28c600b29f47e5b9cd2df9749c206727966203f3" @@ -5624,13 +5700,20 @@ d3-scale@^3.2.3: d3-time "^2.1.1" d3-time-format "2 - 3" -d3-shape@^1.2.2, d3-shape@^1.3.5: +d3-shape@^1.0.0, d3-shape@^1.2.0, d3-shape@^1.2.2, d3-shape@^1.3.5: version "1.3.7" resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.3.7.tgz#df63801be07bc986bc54f63789b4fe502992b5d7" integrity sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw== dependencies: d3-path "1" +d3-time-format@2: + version "2.3.0" + resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-2.3.0.tgz#107bdc028667788a8924ba040faf1fbccd5a7850" + integrity sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ== + dependencies: + d3-time "1" + "d3-time-format@2 - 3", d3-time-format@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-3.0.0.tgz#df8056c83659e01f20ac5da5fdeae7c08d5f1bb6" @@ -5638,6 +5721,11 @@ d3-shape@^1.2.2, d3-shape@^1.3.5: dependencies: d3-time "1 - 2" +d3-time@1, d3-time@^1.0.11: + version "1.1.0" + resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-1.1.0.tgz#b1e19d307dae9c900b7e5b25ffc5dcc249a8a0f1" + integrity sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA== + "d3-time@1 - 2", d3-time@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-2.1.1.tgz#e9d8a8a88691f4548e68ca085e5ff956724a6682" @@ -5645,10 +5733,10 @@ d3-shape@^1.2.2, d3-shape@^1.3.5: dependencies: d3-array "2" -d3-time@^1.0.11: - version "1.1.0" - resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-1.1.0.tgz#b1e19d307dae9c900b7e5b25ffc5dcc249a8a0f1" - integrity sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA== +d3-timer@^1.0.0: + version "1.0.10" + resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-1.0.10.tgz#dfe76b8a91748831b13b6d9c793ffbd508dd9de5" + integrity sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw== d@1, d@^1.0.1: version "1.0.1" @@ -5842,11 +5930,18 @@ del@^4.1.1: pify "^4.0.1" rimraf "^2.6.3" -delaunator@4: +delaunator@4, delaunator@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-4.0.1.tgz#3d779687f57919a7a418f8ab947d3bddb6846957" integrity sha512-WNPWi1IRKZfCt/qIDMfERkDp93+iZEmOxN2yy4Jg+Xhv8SLk2UTqqbe1sfiipn0and9QrE914/ihdx82Y/Giag== +delaunay-find@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/delaunay-find/-/delaunay-find-0.0.6.tgz#2ed017a79410013717fa7d9422e082c2502d4ae3" + integrity sha512-1+almjfrnR7ZamBk0q3Nhg6lqSe6Le4vL0WJDSMx4IDbQwTpUTXPjxC00lqLBT8MYsJpPCbI16sIkw9cPsbi7Q== + dependencies: + delaunator "^4.0.0" + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -7637,7 +7732,7 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -hoist-non-react-statics@^3.1.0: +hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== @@ -12434,6 +12529,11 @@ react-error-overlay@^6.0.9: resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.9.tgz#3c743010c9359608c375ecd6bc76f35d93995b0a" integrity sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew== +react-fast-compare@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9" + integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw== + react-intersection-observer@^8.32.1: version "8.32.1" resolved "https://registry.yarnpkg.com/react-intersection-observer/-/react-intersection-observer-8.32.1.tgz#9b949871eb35eb1fc730732bbf8fcfaaaf3f5b02" @@ -14994,6 +15094,213 @@ vfile@^5.0.0: unist-util-stringify-position "^3.0.0" vfile-message "^3.0.0" +victory-area@^35.9.0: + version "35.11.4" + resolved "https://registry.yarnpkg.com/victory-area/-/victory-area-35.11.4.tgz#a8cc8193c72fc91b9cd75f5cfac8c83253a9c42c" + integrity sha512-i3rN4Jvn1uwA3YvCuv3EIPEcK2SWSOq3c+TvLvVj1BKFQug11C06UjyQje+3EEzffZ/EMkvGqj2+YudIjrGEzA== + dependencies: + d3-shape "^1.2.0" + lodash "^4.17.19" + prop-types "^15.5.8" + victory-core "^35.11.4" + +victory-axis@^35.11.4, victory-axis@^35.9.0: + version "35.11.4" + resolved "https://registry.yarnpkg.com/victory-axis/-/victory-axis-35.11.4.tgz#5145184e0ca3368d573b624d190b125eeab378ba" + integrity sha512-KmPXC/vgbiiWckhK0LruZvsFQqESg6BflhIqS/Xemc50ymWetqbT9VZhjPWbU0arOIP5E8xcFnGUimDN//Jffw== + dependencies: + lodash "^4.17.19" + prop-types "^15.5.8" + victory-core "^35.11.4" + +victory-bar@^35.9.0: + version "35.11.4" + resolved "https://registry.yarnpkg.com/victory-bar/-/victory-bar-35.11.4.tgz#94da9511062462ef814f4c1f78f3e56eab9a86be" + integrity sha512-EZC+6VGwHkIcOYEppVFBIC5JymYnfF+RLF+NM0Uys7q5+AwaLx36LS9a2xBUBYO/gx20Wd1HVH8kjSHzw1rTqQ== + dependencies: + d3-shape "^1.2.0" + lodash "^4.17.19" + prop-types "^15.5.8" + victory-core "^35.11.4" + +victory-brush-container@^35.11.4: + version "35.11.4" + resolved "https://registry.yarnpkg.com/victory-brush-container/-/victory-brush-container-35.11.4.tgz#499c1d16cdaf26fce9d734fb18fc2ce7f8334fb0" + integrity sha512-KpFYU2LxKbLIjZDhXTdveok1SWLFlG5s2R214IRq+ukYRz21CoxlvZCWhFL60lSPilD+ZD1Udv3sK/RW9CFMxA== + dependencies: + lodash "^4.17.19" + prop-types "^15.5.8" + react-fast-compare "^2.0.0" + victory-core "^35.11.4" + +victory-chart@^35.9.0: + version "35.11.4" + resolved "https://registry.yarnpkg.com/victory-chart/-/victory-chart-35.11.4.tgz#1d729be0f7891d257396daa371e34770ac8cc303" + integrity sha512-oBTjx6ytp+/s6zswCuOUQotiISePQKuDUdOsjnbINBPSNvJuE2W9GXHD+B7ibDkCh4ZWXm8obHz7mnrRGbCGFQ== + dependencies: + lodash "^4.17.19" + prop-types "^15.5.8" + react-fast-compare "^2.0.0" + victory-axis "^35.11.4" + victory-core "^35.11.4" + victory-polar-axis "^35.11.4" + victory-shared-events "^35.11.4" + +victory-core@^35.11.4, victory-core@^35.9.0: + version "35.11.4" + resolved "https://registry.yarnpkg.com/victory-core/-/victory-core-35.11.4.tgz#0f7d4b26140f14a53695d8be452e42567a2bafe5" + integrity sha512-PuqrOIn/a6GQgsp/DKvACiJBAJo71P77jltn56mlDZjAAzz+58BL4E0hx7x908GdodLXo2n9gEeuDdjOAlOt0Q== + dependencies: + d3-ease "^1.0.0" + d3-interpolate "^1.1.1" + d3-scale "^1.0.0" + d3-shape "^1.2.0" + d3-timer "^1.0.0" + lodash "^4.17.21" + prop-types "^15.5.8" + react-fast-compare "^2.0.0" + +victory-create-container@^35.9.1: + version "35.11.4" + resolved "https://registry.yarnpkg.com/victory-create-container/-/victory-create-container-35.11.4.tgz#66107c6ff5e9971b4ecb7cb510711192424b2cd0" + integrity sha512-baDLO4GSk/7eTVEYkhikwgwV5BtrSMuNPjKZBjZrIA3Ka9Fn5shklRG9PWg+26JIBFxqZdM6zOvpF7xhjxi37Q== + dependencies: + lodash "^4.17.19" + victory-brush-container "^35.11.4" + victory-core "^35.11.4" + victory-cursor-container "^35.11.4" + victory-selection-container "^35.11.4" + victory-voronoi-container "^35.11.4" + victory-zoom-container "^35.11.4" + +victory-cursor-container@^35.11.4: + version "35.11.4" + resolved "https://registry.yarnpkg.com/victory-cursor-container/-/victory-cursor-container-35.11.4.tgz#5d3bb6bd62d9f615c86a600eb3f5682fca342989" + integrity sha512-gs6bwRd/qbGTN78w2QgshIFxlyOsss5qWOMdCcY9i0Oi99l9OJ6UFQDBzSgKsgD53KGs7JxiKevmUqc3qSZZBg== + dependencies: + lodash "^4.17.19" + prop-types "^15.5.8" + victory-core "^35.11.4" + +victory-group@^35.9.0: + version "35.11.4" + resolved "https://registry.yarnpkg.com/victory-group/-/victory-group-35.11.4.tgz#6e6c0be195b24bfff466950bd5ae0691d265b9a3" + integrity sha512-ceFBll9h1sPpdMjNcvdgEhnYELVHfx9ymmk8iMEjOKpxa4fVvapMhegPmL0/zTemJ/NCu71W2xIr0VqyqK0DaA== + dependencies: + lodash "^4.17.19" + prop-types "^15.5.8" + react-fast-compare "^2.0.0" + victory-core "^35.11.4" + victory-shared-events "^35.11.4" + +victory-legend@^35.9.0: + version "35.11.4" + resolved "https://registry.yarnpkg.com/victory-legend/-/victory-legend-35.11.4.tgz#da22dd5ac26650382ec1914f27a405627ed3756a" + integrity sha512-JZzQARjxYorWlNf9RmZRPAzlgPjukiUV1aTBaeC8YA2S4PhP4PWhNwO/Pb3aCdkifpumpgsm3JULpJiCGOPdBQ== + dependencies: + lodash "^4.17.19" + prop-types "^15.5.8" + victory-core "^35.11.4" + +victory-line@^35.9.0: + version "35.11.4" + resolved "https://registry.yarnpkg.com/victory-line/-/victory-line-35.11.4.tgz#f8b8a4b098d7a8123845b0fcf102a23b08febb53" + integrity sha512-uKX6/1b1OmlqJZOsVDCCDlyc9QItgb39vRssTwP4CJX1NLU4Sfgq2i4VVUbHXCo/I2sMEczjf3cdnxdZtC6IFA== + dependencies: + d3-shape "^1.2.0" + lodash "^4.17.19" + prop-types "^15.5.8" + victory-core "^35.11.4" + +victory-pie@^35.9.0: + version "35.11.4" + resolved "https://registry.yarnpkg.com/victory-pie/-/victory-pie-35.11.4.tgz#2fb8a37fd37826f5a6654b0e43ebf472cc2c8d95" + integrity sha512-EruxP3PIkrTPTzsC5YhiRKg2s+0UtaRU1ZHZUWK8qi+zlbMDFKYg2AlHqsEnctu5AOdOWLLiye6qUG3oxjiURg== + dependencies: + d3-shape "^1.0.0" + lodash "^4.17.19" + prop-types "^15.5.8" + victory-core "^35.11.4" + +victory-polar-axis@^35.11.4: + version "35.11.4" + resolved "https://registry.yarnpkg.com/victory-polar-axis/-/victory-polar-axis-35.11.4.tgz#1b362c37bbe961f123a621ad61a764a57a0285af" + integrity sha512-mnIRpfARn36TG6ZdCgKR+oWY+pIX6wLHYS0un5xM1TTObKk4IyAR3dnQhEp+3KM1SGoLg0mENFR1Ac8xrus6nQ== + dependencies: + lodash "^4.17.19" + prop-types "^15.5.8" + victory-core "^35.11.4" + +victory-scatter@^35.9.0: + version "35.11.4" + resolved "https://registry.yarnpkg.com/victory-scatter/-/victory-scatter-35.11.4.tgz#fbd4f3cf12e64d75d6903cd8ae29b30fb09ee8b7" + integrity sha512-8n9rmXmVju2SqA6Xd90rRTmboaU7WStOnj1QUg4q96DDiAVf6kGPdolzCwbUBbiECLyluGoFNJ043WLXztGpiA== + dependencies: + lodash "^4.17.19" + prop-types "^15.5.8" + victory-core "^35.11.4" + +victory-selection-container@^35.11.4: + version "35.11.4" + resolved "https://registry.yarnpkg.com/victory-selection-container/-/victory-selection-container-35.11.4.tgz#9311adea36d2da75d782dcd6da7e293b15f2e89b" + integrity sha512-Olxnjp9tvHUHeFr4zU/K1dzp0zbeqQRMr2Qqpr85Dd4pWV9bIReE/DanxGhjNg9s3KB5Vsn1GC46PXSTMM1XIQ== + dependencies: + lodash "^4.17.19" + prop-types "^15.5.8" + victory-core "^35.11.4" + +victory-shared-events@^35.11.4: + version "35.11.4" + resolved "https://registry.yarnpkg.com/victory-shared-events/-/victory-shared-events-35.11.4.tgz#05a5dd960062010e7a1ffa0a042dcac04620b2f8" + integrity sha512-flvI27J9K+09BAbuVJf2w51D4OkXlDxE/5BlaHSKzM5jNDYsbcQ6djXa4pqa7NQtMGPOApTBkOSmVRyWRqVoYA== + dependencies: + json-stringify-safe "^5.0.1" + lodash "^4.17.19" + prop-types "^15.5.8" + react-fast-compare "^2.0.0" + victory-core "^35.11.4" + +victory-stack@^35.9.0: + version "35.11.4" + resolved "https://registry.yarnpkg.com/victory-stack/-/victory-stack-35.11.4.tgz#b3f973a6aedf9d00de0cf81e30428766f214c320" + integrity sha512-fNTY50fN+DCHcK/9AgMUEq0uJ8IXGnMlRtkSCzMB9ZpEzB7Edx3jLM2Gl970zOkwVaDYXTlikPd1dwf+h3m0dA== + dependencies: + lodash "^4.17.19" + prop-types "^15.5.8" + react-fast-compare "^2.0.0" + victory-core "^35.11.4" + victory-shared-events "^35.11.4" + +victory-tooltip@^35.11.4, victory-tooltip@^35.9.1: + version "35.11.4" + resolved "https://registry.yarnpkg.com/victory-tooltip/-/victory-tooltip-35.11.4.tgz#3b69abc5e39422364012522c887930263539d699" + integrity sha512-B+UUqzryurtMghJGiE34tg5eI44vHxyOOcuPIM3IpJLujnNIJXVykBjgQZnFq1CT/63TtDCOlzPkOjSbecPtXQ== + dependencies: + lodash "^4.17.19" + prop-types "^15.5.8" + victory-core "^35.11.4" + +victory-voronoi-container@^35.11.4, victory-voronoi-container@^35.9.1: + version "35.11.4" + resolved "https://registry.yarnpkg.com/victory-voronoi-container/-/victory-voronoi-container-35.11.4.tgz#708d38d4d703a47926fbb48affc9413cfbe8849a" + integrity sha512-vmwHBm/+nZ9qdRcaNd7r08AVRkus/ER6UA4KAYWkKUe50ZT9NYjDxy0wW/Y7PHQldfL9q/VxAyIE/M6jSFWkEA== + dependencies: + delaunay-find "0.0.6" + lodash "^4.17.19" + prop-types "^15.5.8" + react-fast-compare "^2.0.0" + victory-core "^35.11.4" + victory-tooltip "^35.11.4" + +victory-zoom-container@^35.11.4, victory-zoom-container@^35.9.0: + version "35.11.4" + resolved "https://registry.yarnpkg.com/victory-zoom-container/-/victory-zoom-container-35.11.4.tgz#5fd6d29db4cd3b2eac22c59cd7c4d1bff48bbe89" + integrity sha512-8D4hTdvGZqyZdgWjkz/pDRVy/kijWhptFbK0KWl5J1Tt4YuCGiRC9oxQOpEjlqr8TSyeVnpyuF4QuIp9YOIrAw== + dependencies: + lodash "^4.17.19" + prop-types "^15.5.8" + victory-core "^35.11.4" + vm-browserify@^1.0.1: version "1.1.2" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"