From d67b38365d7f97a6ba334135d45535e8525f5979 Mon Sep 17 00:00:00 2001 From: Pierre Jeambrun Date: Thu, 1 Jun 2023 23:17:40 +0200 Subject: [PATCH] UI Add Cluster Activity Page (#31123) * Dashboard init view * Live metrics and first page layout * Rebase and UI improvements * Add DagRun to dashboard * Update wording. * Add filter bar * Add historical data metrics * Drop colors for now fix type * Update following code review * Use State colors * Handle data fetch errors * Add simple top component test * Add cluster_activity tests * Add labels to filter bar and period duration for visualization * FilterBar style * Sort legend in PieChart * Add triggerer to health card * Update UI and wording following Jed review --- airflow/security/permissions.py | 20 +- .../www/extensions/init_appbuilder_links.py | 4 +- airflow/www/jest-setup.js | 1 + airflow/www/package.json | 4 +- airflow/www/security.py | 2 + airflow/www/static/js/api/index.ts | 16 +- airflow/www/static/js/api/useDagRuns.tsx | 50 + airflow/www/static/js/api/useDags.tsx | 40 + airflow/www/static/js/api/useHealth.ts | 37 + .../static/js/api/useHistoricalMetricsData.ts | 40 + airflow/www/static/js/api/usePools.ts | 41 + .../historical-metrics/PieChart.tsx | 147 ++ .../historical-metrics/index.tsx | 95 ++ .../static/js/cluster-activity/index.test.tsx | 153 +++ .../www/static/js/cluster-activity/index.tsx | 64 + .../cluster-activity/live-metrics/DagRuns.tsx | 121 ++ .../js/cluster-activity/live-metrics/Dags.tsx | 69 + .../cluster-activity/live-metrics/Health.tsx | 116 ++ .../cluster-activity/live-metrics/Pools.tsx | 132 ++ .../cluster-activity/live-metrics/index.tsx | 61 + .../js/cluster-activity/nav/FilterBar.tsx | 101 ++ .../static/js/cluster-activity/useFilters.tsx | 95 ++ .../static/js/components/LoadingWrapper.tsx | 53 + .../www/static/js/components/ReactECharts.tsx | 93 ++ airflow/www/static/js/dag/nav/FilterBar.tsx | 7 +- airflow/www/static/js/types/index.ts | 16 +- .../templates/airflow/cluster_activity.html | 48 + airflow/www/templates/airflow/datasets.html | 2 + airflow/www/views.py | 83 +- airflow/www/webpack.config.js | 1 + airflow/www/yarn.lock | 1177 ++++++++++------- .../endpoints/test_dag_run_endpoint.py | 1 + tests/www/test_security.py | 5 +- .../www/views/test_views_cluster_activity.py | 143 ++ 34 files changed, 2549 insertions(+), 489 deletions(-) create mode 100644 airflow/www/static/js/api/useDagRuns.tsx create mode 100644 airflow/www/static/js/api/useDags.tsx create mode 100644 airflow/www/static/js/api/useHealth.ts create mode 100644 airflow/www/static/js/api/useHistoricalMetricsData.ts create mode 100644 airflow/www/static/js/api/usePools.ts create mode 100644 airflow/www/static/js/cluster-activity/historical-metrics/PieChart.tsx create mode 100644 airflow/www/static/js/cluster-activity/historical-metrics/index.tsx create mode 100644 airflow/www/static/js/cluster-activity/index.test.tsx create mode 100644 airflow/www/static/js/cluster-activity/index.tsx create mode 100644 airflow/www/static/js/cluster-activity/live-metrics/DagRuns.tsx create mode 100644 airflow/www/static/js/cluster-activity/live-metrics/Dags.tsx create mode 100644 airflow/www/static/js/cluster-activity/live-metrics/Health.tsx create mode 100644 airflow/www/static/js/cluster-activity/live-metrics/Pools.tsx create mode 100644 airflow/www/static/js/cluster-activity/live-metrics/index.tsx create mode 100644 airflow/www/static/js/cluster-activity/nav/FilterBar.tsx create mode 100644 airflow/www/static/js/cluster-activity/useFilters.tsx create mode 100644 airflow/www/static/js/components/LoadingWrapper.tsx create mode 100644 airflow/www/static/js/components/ReactECharts.tsx create mode 100644 airflow/www/templates/airflow/cluster_activity.html create mode 100644 tests/www/views/test_views_cluster_activity.py diff --git a/airflow/security/permissions.py b/airflow/security/permissions.py index adf7af964e571..3259b48dc3545 100644 --- a/airflow/security/permissions.py +++ b/airflow/security/permissions.py @@ -22,25 +22,27 @@ RESOURCE_AIRFLOW = "Airflow" RESOURCE_AUDIT_LOG = "Audit Logs" RESOURCE_BROWSE_MENU = "Browse" -RESOURCE_DAG = "DAGs" -RESOURCE_DAG_PREFIX = "DAG:" -RESOURCE_LOGIN = "Logins" -RESOURCE_DOCS_MENU = "Docs" -RESOURCE_DOCS = "Documentation" RESOURCE_CONFIG = "Configurations" RESOURCE_CONNECTION = "Connections" -RESOURCE_DAG_DEPENDENCIES = "DAG Dependencies" +RESOURCE_DAG = "DAGs" RESOURCE_DAG_CODE = "DAG Code" +RESOURCE_DAG_DEPENDENCIES = "DAG Dependencies" +RESOURCE_DAG_PREFIX = "DAG:" RESOURCE_DAG_RUN = "DAG Runs" -RESOURCE_IMPORT_ERROR = "ImportError" RESOURCE_DAG_WARNING = "DAG Warnings" +RESOURCE_CLUSTER_ACTIVITY = "Cluster Activity" +RESOURCE_DATASET = "Datasets" +RESOURCE_DOCS = "Documentation" +RESOURCE_DOCS_MENU = "Docs" +RESOURCE_IMPORT_ERROR = "ImportError" RESOURCE_JOB = "Jobs" +RESOURCE_LOGIN = "Logins" RESOURCE_MY_PASSWORD = "My Password" RESOURCE_MY_PROFILE = "My Profile" RESOURCE_PASSWORD = "Passwords" RESOURCE_PERMISSION = "Permission Views" # Refers to a Perm <-> View mapping, not an MVC View. -RESOURCE_POOL = "Pools" RESOURCE_PLUGIN = "Plugins" +RESOURCE_POOL = "Pools" RESOURCE_PROVIDER = "Providers" RESOURCE_RESOURCE = "View Menus" RESOURCE_ROLE = "Roles" @@ -54,8 +56,6 @@ RESOURCE_VARIABLE = "Variables" RESOURCE_WEBSITE = "Website" RESOURCE_XCOM = "XComs" -RESOURCE_DATASET = "Datasets" - # Action Constants ACTION_CAN_CREATE = "can_create" diff --git a/airflow/www/extensions/init_appbuilder_links.py b/airflow/www/extensions/init_appbuilder_links.py index f7d747013d58c..6ae049edcd131 100644 --- a/airflow/www/extensions/init_appbuilder_links.py +++ b/airflow/www/extensions/init_appbuilder_links.py @@ -26,8 +26,10 @@ def init_appbuilder_links(app): appbuilder.add_link(name="DAGs", href="Airflow.index") appbuilder.menu.menu.insert(0, appbuilder.menu.menu.pop()) # Place in the first menu slot - appbuilder.add_link(name="Datasets", href="Airflow.datasets") + appbuilder.add_link(name="Cluster Activity", href="Airflow.cluster_activity") appbuilder.menu.menu.insert(1, appbuilder.menu.menu.pop()) # Place in the second menu slot + appbuilder.add_link(name="Datasets", href="Airflow.datasets") + appbuilder.menu.menu.insert(2, appbuilder.menu.menu.pop()) # Place in the third menu slot # Docs links appbuilder.add_link(name="Documentation", label="Documentation", href=get_docs_url(), category="Docs") diff --git a/airflow/www/jest-setup.js b/airflow/www/jest-setup.js index 0a13d7c6444de..fcab19bc8f418 100644 --- a/airflow/www/jest-setup.js +++ b/airflow/www/jest-setup.js @@ -22,6 +22,7 @@ import "@testing-library/jest-dom"; import axios from "axios"; import { setLogger } from "react-query"; +import "jest-canvas-mock"; // eslint-disable-next-line import/no-extraneous-dependencies import moment from "moment-timezone"; diff --git a/airflow/www/package.json b/airflow/www/package.json index 15d9279740895..5eac3744663ae 100644 --- a/airflow/www/package.json +++ b/airflow/www/package.json @@ -66,6 +66,7 @@ "file-loader": "^6.0.0", "imports-loader": "^1.1.0", "jest": "^27.3.1", + "jest-canvas-mock": "^2.5.1", "mini-css-extract-plugin": "^1.6.2", "moment": "^2.29.4", "moment-locales-webpack-plugin": "^1.2.0", @@ -86,7 +87,7 @@ "webpack-manifest-plugin": "^4.0.0" }, "dependencies": { - "@chakra-ui/react": "^2.2.0", + "@chakra-ui/react": "2.4.2", "@emotion/cache": "^11.9.3", "@emotion/react": "^11.9.3", "@emotion/styled": "^11", @@ -107,6 +108,7 @@ "dagre-d3": "^0.6.4", "datatables.net": "^1.11.4", "datatables.net-bs": "^1.11.4", + "echarts": "^5.4.2", "elkjs": "^0.7.1", "eonasdan-bootstrap-datetimepicker": "^4.17.47", "framer-motion": "^6.0.0", diff --git a/airflow/www/security.py b/airflow/www/security.py index b6bc48104c55a..890648009c83f 100644 --- a/airflow/www/security.py +++ b/airflow/www/security.py @@ -72,6 +72,7 @@ class AirflowSecurityManager(SecurityManager, LoggingMixin): (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG_CODE), (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG_RUN), (permissions.ACTION_CAN_READ, permissions.RESOURCE_DATASET), + (permissions.ACTION_CAN_READ, permissions.RESOURCE_CLUSTER_ACTIVITY), (permissions.ACTION_CAN_READ, permissions.RESOURCE_IMPORT_ERROR), (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG_WARNING), (permissions.ACTION_CAN_READ, permissions.RESOURCE_JOB), @@ -90,6 +91,7 @@ class AirflowSecurityManager(SecurityManager, LoggingMixin): (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_DAG_DEPENDENCIES), (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_DAG_RUN), (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_DATASET), + (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_CLUSTER_ACTIVITY), (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_DOCS), (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_DOCS_MENU), (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_JOB), diff --git a/airflow/www/static/js/api/index.ts b/airflow/www/static/js/api/index.ts index 016ad3b48db45..cd7b9dd5af258 100644 --- a/airflow/www/static/js/api/index.ts +++ b/airflow/www/static/js/api/index.ts @@ -42,6 +42,11 @@ import useUpstreamDatasetEvents from "./useUpstreamDatasetEvents"; import useTaskInstance from "./useTaskInstance"; import useDag from "./useDag"; import useDagCode from "./useDagCode"; +import useHealth from "./useHealth"; +import usePools from "./usePools"; +import useDags from "./useDags"; +import useDagRuns from "./useDagRuns"; +import useHistoricalMetricsData from "./useHistoricalMetricsData"; axios.interceptors.response.use((res: AxiosResponse) => res.data ? camelcaseKeys(res.data, { deep: true }) : res @@ -52,7 +57,10 @@ axios.defaults.headers.common.Accept = "application/json"; export { useClearRun, useClearTask, - useMarkTaskDryRun, + useDag, + useDagCode, + useDagRuns, + useDags, useDataset, useDatasetDependencies, useDatasetEvents, @@ -60,16 +68,18 @@ export { useExtraLinks, useGraphData, useGridData, + useHealth, useMappedInstances, useMarkFailedRun, useMarkFailedTask, useMarkSuccessRun, useMarkSuccessTask, + useMarkTaskDryRun, + usePools, useQueueRun, useSetDagRunNote, useSetTaskInstanceNote, useTaskInstance, useUpstreamDatasetEvents, - useDag, - useDagCode, + useHistoricalMetricsData, }; diff --git a/airflow/www/static/js/api/useDagRuns.tsx b/airflow/www/static/js/api/useDagRuns.tsx new file mode 100644 index 0000000000000..5bc1a43748862 --- /dev/null +++ b/airflow/www/static/js/api/useDagRuns.tsx @@ -0,0 +1,50 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import axios, { AxiosResponse } from "axios"; +import { useQuery } from "react-query"; +import type { API } from "src/types"; + +import { getMetaValue } from "src/utils"; + +const useDagRuns = ({ + dagId, + state, + limit, + orderBy, +}: API.GetDagRunsVariables) => { + const dagRunsUrl = getMetaValue("dag_runs_url").replace("__DAG_ID__", dagId); + + return useQuery( + ["dagRuns", state, dagId, limit], + async () => + axios.get(dagRunsUrl, { + params: { + state: state ? state.join(",") : state, + limit, + order_by: orderBy, + }, + }), + { + refetchInterval: (autoRefreshInterval || 1) * 1000, + } + ); +}; + +export default useDagRuns; diff --git a/airflow/www/static/js/api/useDags.tsx b/airflow/www/static/js/api/useDags.tsx new file mode 100644 index 0000000000000..8939da21d96c7 --- /dev/null +++ b/airflow/www/static/js/api/useDags.tsx @@ -0,0 +1,40 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import axios, { AxiosResponse } from "axios"; +import { useQuery } from "react-query"; +import type { API } from "src/types"; + +import { getMetaValue } from "src/utils"; + +const dagsUrl = getMetaValue("dags_url"); + +const useDags = ({ paused }: API.GetDagsVariables) => + useQuery( + ["dags", paused], + async () => + axios.get(dagsUrl, { + params: { paused }, + }), + { + refetchInterval: (autoRefreshInterval || 1) * 1000, + } + ); + +export default useDags; diff --git a/airflow/www/static/js/api/useHealth.ts b/airflow/www/static/js/api/useHealth.ts new file mode 100644 index 0000000000000..ab86698507cb2 --- /dev/null +++ b/airflow/www/static/js/api/useHealth.ts @@ -0,0 +1,37 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import axios, { AxiosResponse } from "axios"; +import { useQuery } from "react-query"; +import type { API } from "src/types"; + +import { getMetaValue } from "src/utils"; + +const healthUrl = getMetaValue("health_url"); + +const useHealth = () => + useQuery( + ["health"], + async () => axios.get(healthUrl), + { + refetchInterval: (autoRefreshInterval || 1) * 1000, + } + ); + +export default useHealth; diff --git a/airflow/www/static/js/api/useHistoricalMetricsData.ts b/airflow/www/static/js/api/useHistoricalMetricsData.ts new file mode 100644 index 0000000000000..d14ce13fb6937 --- /dev/null +++ b/airflow/www/static/js/api/useHistoricalMetricsData.ts @@ -0,0 +1,40 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import axios, { AxiosResponse } from "axios"; +import { useQuery } from "react-query"; +import type { HistoricalMetricsData } from "src/types"; + +import { getMetaValue } from "src/utils"; + +const url = getMetaValue("historical_metrics_data_url"); + +const useHistoricalMetricsData = (startDate: string, endDate: string) => + useQuery( + ["historical_metrics_data", startDate, endDate], + async () => + axios.get(url, { + params: { start_date: startDate, end_date: endDate }, + }), + { + refetchInterval: (autoRefreshInterval || 1) * 1000, + } + ); + +export default useHistoricalMetricsData; diff --git a/airflow/www/static/js/api/usePools.ts b/airflow/www/static/js/api/usePools.ts new file mode 100644 index 0000000000000..664626a2ab4be --- /dev/null +++ b/airflow/www/static/js/api/usePools.ts @@ -0,0 +1,41 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import axios, { AxiosResponse } from "axios"; +import { useQuery } from "react-query"; +import { useAutoRefresh } from "src/context/autorefresh"; +import type { API } from "src/types"; + +import { getMetaValue } from "src/utils"; + +const poolsUrl = getMetaValue("pools_url"); + +const usePools = () => { + const { isRefreshOn } = useAutoRefresh(); + + return useQuery( + ["pools"], + async () => axios.get(poolsUrl), + { + refetchInterval: isRefreshOn && (autoRefreshInterval || 1) * 1000, + } + ); +}; + +export default usePools; diff --git a/airflow/www/static/js/cluster-activity/historical-metrics/PieChart.tsx b/airflow/www/static/js/cluster-activity/historical-metrics/PieChart.tsx new file mode 100644 index 0000000000000..a1aa86cc5ac43 --- /dev/null +++ b/airflow/www/static/js/cluster-activity/historical-metrics/PieChart.tsx @@ -0,0 +1,147 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from "react"; +import { + Box, + BoxProps, + Card, + CardBody, + CardHeader, + Heading, + useTheme, +} from "@chakra-ui/react"; +import ReactECharts, { ReactEChartsProps } from "src/components/ReactECharts"; +import type { HistoricalMetricsData } from "src/types"; +import { camelCase, mapKeys } from "lodash"; + +interface SeriesPoint { + name: string; + value: number; +} + +type SeriesData = Array; + +const camelCaseColorPalette = mapKeys(stateColors, (_, k) => camelCase(k)); + +const formatData = ( + data: HistoricalMetricsData[keyof HistoricalMetricsData] | undefined +): [number, SeriesData] => { + if (data === undefined) return [0, []]; + + let sum = 0; + const formattedData: { name: string; value: number }[] = []; + Object.entries(data).forEach(([k, v]) => { + sum += v; + formattedData.push({ + name: k, + value: v, + }); + }); + formattedData.sort((a: SeriesPoint, b: SeriesPoint) => b.value - a.value); + return [sum, formattedData]; +}; + +interface Props extends BoxProps { + title: string; + data?: HistoricalMetricsData[keyof HistoricalMetricsData]; + colorPalette?: { + [key: string]: string; + }; +} + +const PieChart = ({ + title, + data, + colorPalette = camelCaseColorPalette, + ...rest +}: Props) => { + const theme = useTheme(); + const [sum, formattedData] = formatData(data); + const option: ReactEChartsProps["option"] = { + title: { + text: `on a total of ${sum}`, + left: "right", + top: "bottom", + textStyle: { + fontSize: "14px", + color: theme.colors.gray["500"], + }, + }, + tooltip: { + trigger: "item", + }, + legend: { + left: "center", + type: "scroll", + }, + color: formattedData?.map((d) => { + let color = colorPalette[d.name]; + if (color === undefined) { + // eslint-disable-next-line no-console + console.warn( + `The color for ${d.name} is missing from the palette, defaulting to black` + ); + color = "black"; + } + return color; + }), + series: [ + { + name: title, + type: "pie", + radius: ["35%", "60%"], + avoidLabelOverlap: false, + top: "0%", + itemStyle: { + borderRadius: 5, + borderColor: "#fff", + borderWidth: 2, + }, + label: { + show: false, + position: "center", + }, + emphasis: { + label: { + show: true, + fontSize: 16, + fontWeight: "bold", + }, + }, + data: formattedData, + }, + ], + }; + + return ( + + + + {title} + + + + + + + ); +}; + +export default PieChart; diff --git a/airflow/www/static/js/cluster-activity/historical-metrics/index.tsx b/airflow/www/static/js/cluster-activity/historical-metrics/index.tsx new file mode 100644 index 0000000000000..5e319c9c3effe --- /dev/null +++ b/airflow/www/static/js/cluster-activity/historical-metrics/index.tsx @@ -0,0 +1,95 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from "react"; +import { Card, CardBody, CardHeader, Flex, Heading } from "@chakra-ui/react"; +import InfoTooltip from "src/components/InfoTooltip"; +import FilterBar from "src/cluster-activity/nav/FilterBar"; +import useFilters from "src/cluster-activity/useFilters"; +import { useHistoricalMetricsData } from "src/api"; +import PieChart from "src/cluster-activity/historical-metrics/PieChart"; +import LoadingWrapper from "src/components/LoadingWrapper"; + +const HistoricalMetrics = () => { + const { + filters: { startDate, endDate }, + } = useFilters(); + const { data, isError } = useHistoricalMetricsData(startDate, endDate); + return ( + + + + + Historical metrics + + + + + + + + + + + + + + + + + + ); +}; + +export default HistoricalMetrics; diff --git a/airflow/www/static/js/cluster-activity/index.test.tsx b/airflow/www/static/js/cluster-activity/index.test.tsx new file mode 100644 index 0000000000000..f12c4c159abc2 --- /dev/null +++ b/airflow/www/static/js/cluster-activity/index.test.tsx @@ -0,0 +1,153 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* global describe */ + +import React from "react"; +import * as useHistoricalMetricsDataModule from "src/api/useHistoricalMetricsData"; +import * as useDagsModule from "src/api/useDags"; +import * as useDagRunsModule from "src/api/useDagRuns"; +import * as usePoolsModule from "src/api/usePools"; +import * as useHealthModule from "src/api/useHealth"; + +import { render } from "@testing-library/react"; + +import { Wrapper } from "src/utils/testUtils"; +import ClusterActivity from "."; + +const mockHistoricalMetricsData = { + dag_run_states: { failed: 0, queued: 0, running: 0, success: 306 }, + dag_run_types: { + backfill: 0, + dataset_triggered: 0, + manual: 14, + scheduled: 292, + }, + task_instance_states: { + deferred: 0, + failed: 0, + no_status: 0, + queued: 0, + removed: 0, + restarting: 0, + running: 0, + scheduled: 0, + shutdown: 0, + skipped: 0, + success: 1634, + up_for_reschedule: 0, + up_for_retry: 0, + upstream_failed: 0, + }, +}; + +const mockHealthData = { + metadatabase: { + status: "healthy", + }, + scheduler: { + latest_scheduler_heartbeat: "2023-05-19T12:00:36.109924+00:00", + status: "healthy", + }, +}; + +const mockPoolsData = { + pools: [ + { + description: "Default pool", + name: "default_pool", + occupied_slots: 0, + open_slots: 128, + queued_slots: 0, + running_slots: 0, + scheduled_slots: 0, + slots: 128, + }, + ], + total_entries: 1, +}; + +const mockDagsData = { + dags: ["fake-dag-payload1", "fake-dag-payload2"], + total_entries: 2, +}; + +const mockDagRunsData = { + dags: [], + total_entries: 0, +}; + +describe("Test ToggleGroups", () => { + beforeEach(() => { + jest.spyOn(useHistoricalMetricsDataModule, "default").mockImplementation( + () => + ({ + data: mockHistoricalMetricsData, + isSuccess: true, + } as any) + ); + + jest.spyOn(useHealthModule, "default").mockImplementation( + () => + ({ + data: mockHealthData, + isSuccess: true, + } as any) + ); + + jest.spyOn(useDagsModule, "default").mockImplementation( + () => + ({ + data: mockDagsData, + isSuccess: true, + } as any) + ); + + jest.spyOn(useDagRunsModule, "default").mockImplementation( + () => + ({ + data: mockDagRunsData, + isSuccess: true, + } as any) + ); + + jest.spyOn(usePoolsModule, "default").mockImplementation( + () => + ({ + data: mockPoolsData, + isSuccess: true, + } as any) + ); + }); + + test("Components renders properly", () => { + const { getByText, getAllByTestId, getAllByText } = render( + , + { + wrapper: Wrapper, + } + ); + + expect(getAllByTestId("echart-container")).toHaveLength(4); + + expect(getAllByText("healthy")).toHaveLength(2); + expect(getByText("Unpaused DAGs")).toBeInTheDocument(); + expect(getByText("No dag running")).toBeInTheDocument(); + }); +}); diff --git a/airflow/www/static/js/cluster-activity/index.tsx b/airflow/www/static/js/cluster-activity/index.tsx new file mode 100644 index 0000000000000..01b21b0dd8403 --- /dev/null +++ b/airflow/www/static/js/cluster-activity/index.tsx @@ -0,0 +1,64 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* global document */ + +import React from "react"; +import { createRoot } from "react-dom/client"; +import createCache from "@emotion/cache"; +import { Flex, Heading } from "@chakra-ui/react"; + +import App from "src/App"; +import LiveMetrics from "./live-metrics"; +import HistoricalMetrics from "./historical-metrics"; + +// create shadowRoot +const root = document.querySelector("#root"); +const shadowRoot = root?.attachShadow({ mode: "open" }); +const cache = createCache({ + container: shadowRoot, + key: "c", +}); +const mainElement = document.getElementById("react-container"); + +const ClusterActivity = () => ( + + + Cluster Activity + + + + +); + +export default ClusterActivity; + +if (mainElement) { + shadowRoot?.appendChild(mainElement); + const reactRoot = createRoot(mainElement); + reactRoot.render( + + + + ); +} diff --git a/airflow/www/static/js/cluster-activity/live-metrics/DagRuns.tsx b/airflow/www/static/js/cluster-activity/live-metrics/DagRuns.tsx new file mode 100644 index 0000000000000..7f2b169359e2f --- /dev/null +++ b/airflow/www/static/js/cluster-activity/live-metrics/DagRuns.tsx @@ -0,0 +1,121 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from "react"; +import { + Box, + BoxProps, + Card, + CardBody, + CardHeader, + Center, + Flex, + Heading, + Link, + Table, + Tbody, + Td, + Text, + Th, + Thead, + Tr, +} from "@chakra-ui/react"; +import { useDagRuns } from "src/api"; +import { formatDuration, getDuration } from "src/datetime_utils"; +import LoadingWrapper from "src/components/LoadingWrapper"; + +const DagRuns = (props: BoxProps) => { + const { data, isError } = useDagRuns({ + dagId: "~", + state: ["running"], + orderBy: "start_date", + limit: 5, + }); + + return ( +
+ + + + Top 5 longest Dag Runs to finish + + + + {data?.totalEntries !== undefined && data.totalEntries > 0 ? ( + + + + + + + + + + {data?.dagRuns?.map((dagRun) => ( + + + + + + ))} + +
Dag IdRun TypeDuration
+ + {dagRun.dagId} + + {dagRun.runType} + {formatDuration( + getDuration(dagRun.startDate, dagRun.endDate) + )} +
+ ) : ( + + + No dag running + + + )} +
+ + + out of {data?.totalEntries} total running + Dag Runs + + +
+
+
+
+ ); +}; + +export default DagRuns; diff --git a/airflow/www/static/js/cluster-activity/live-metrics/Dags.tsx b/airflow/www/static/js/cluster-activity/live-metrics/Dags.tsx new file mode 100644 index 0000000000000..abe36b6e52c62 --- /dev/null +++ b/airflow/www/static/js/cluster-activity/live-metrics/Dags.tsx @@ -0,0 +1,69 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from "react"; +import { + BoxProps, + Card, + CardBody, + CardHeader, + Center, + Flex, + Heading, + Text, +} from "@chakra-ui/react"; +import { useDags } from "src/api"; +import LoadingWrapper from "src/components/LoadingWrapper"; + +const Dags = (props: BoxProps) => { + const { data: dataOnlyUnpaused, isError: isErrorUnpaused } = useDags({ + paused: false, + }); + + const { data, isError } = useDags({}); + + return ( +
+ + + + Unpaused DAGs + + + + + {dataOnlyUnpaused?.totalEntries} + + + + + out of {data?.totalEntries} total DAGs + + + + + +
+ ); +}; + +export default Dags; diff --git a/airflow/www/static/js/cluster-activity/live-metrics/Health.tsx b/airflow/www/static/js/cluster-activity/live-metrics/Health.tsx new file mode 100644 index 0000000000000..fb59439c4b750 --- /dev/null +++ b/airflow/www/static/js/cluster-activity/live-metrics/Health.tsx @@ -0,0 +1,116 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from "react"; +import { + Badge, + CenterProps, + Card, + CardBody, + CardHeader, + Center, + Flex, + Heading, + Stack, + Text, + FlexProps, +} from "@chakra-ui/react"; +import { useHealth } from "src/api"; +import type { API } from "src/types"; +import Time from "src/components/Time"; +import LoadingWrapper from "src/components/LoadingWrapper"; + +const HealthSection = ({ + title, + status, + latestHeartbeat, + ...rest +}: { + title: string; + status?: API.HealthStatus; + latestHeartbeat?: string | null; +} & FlexProps) => ( + + + {title} + + + status: +
+ + {status || "unknown"} + +
+
+ {latestHeartbeat && ( + + + last heartbeat:{" "} + +
+ + +
+
+ )} +
+); + +const Health = (props: CenterProps) => { + const { data, isError } = useHealth(); + + return ( +
+ + + + Health + + + + + + + + +
+ ); +}; + +export default Health; diff --git a/airflow/www/static/js/cluster-activity/live-metrics/Pools.tsx b/airflow/www/static/js/cluster-activity/live-metrics/Pools.tsx new file mode 100644 index 0000000000000..36434eb079c93 --- /dev/null +++ b/airflow/www/static/js/cluster-activity/live-metrics/Pools.tsx @@ -0,0 +1,132 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from "react"; +import { + Box, + BoxProps, + Card, + CardBody, + CardHeader, + Center, + Heading, +} from "@chakra-ui/react"; +import { usePools } from "src/api"; +import ReactECharts, { ReactEChartsProps } from "src/components/ReactECharts"; +import type { API } from "src/types"; +import LoadingWrapper from "src/components/LoadingWrapper"; + +const formatData = ( + data?: API.PoolCollection +): Array<[string, number, number, number, number]> => + data?.pools?.map((pool) => [ + pool.name || "", + pool.openSlots || 0, + pool.queuedSlots || 0, + pool.runningSlots || 0, + pool.scheduledSlots || 0, + ]) || []; + +const Pools = (props: BoxProps) => { + const { data, isError } = usePools(); + + const option: ReactEChartsProps["option"] = { + dataset: { + source: [ + ["pool", "open", "queued", "running", "scheduled"], + ...formatData(data), + ], + }, + tooltip: { + trigger: "axis", + axisPointer: { + type: "shadow", + }, + }, + legend: { + data: ["open", "queued", "running", "scheduled"], + }, + grid: { + left: "0%", + right: "5%", + top: "30%", + bottom: "0%", + containLabel: true, + }, + xAxis: { + type: "value", + }, + yAxis: { + type: "category", + }, + series: [ + { + type: "bar", + stack: "total", + barMaxWidth: 10, + itemStyle: { + color: stateColors.success, + }, + }, + { + type: "bar", + stack: "total", + barMaxWidth: 10, + itemStyle: { + color: stateColors.queued, + }, + }, + { + type: "bar", + stack: "total", + barMaxWidth: 10, + itemStyle: { + color: stateColors.running, + }, + }, + { + type: "bar", + stack: "total", + barMaxWidth: 10, + itemStyle: { + color: stateColors.scheduled, + }, + }, + ], + }; + + return ( +
+ + + + Pools Slots + + + + + + + + +
+ ); +}; + +export default Pools; diff --git a/airflow/www/static/js/cluster-activity/live-metrics/index.tsx b/airflow/www/static/js/cluster-activity/live-metrics/index.tsx new file mode 100644 index 0000000000000..6b7f3c7668e21 --- /dev/null +++ b/airflow/www/static/js/cluster-activity/live-metrics/index.tsx @@ -0,0 +1,61 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from "react"; +import { Card, CardBody, CardHeader, Flex, Heading } from "@chakra-ui/react"; +import InfoTooltip from "src/components/InfoTooltip"; +import Health from "./Health"; +import Pools from "./Pools"; +import Dags from "./Dags"; +import DagRuns from "./DagRuns"; + +const LiveMetrics = () => ( + + + + + Live Metrics + + + + + + + + + + + + + + + +); + +export default LiveMetrics; diff --git a/airflow/www/static/js/cluster-activity/nav/FilterBar.tsx b/airflow/www/static/js/cluster-activity/nav/FilterBar.tsx new file mode 100644 index 0000000000000..29fa456df44a8 --- /dev/null +++ b/airflow/www/static/js/cluster-activity/nav/FilterBar.tsx @@ -0,0 +1,101 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* global moment */ + +import { Box, Button, Flex, Input, Text } from "@chakra-ui/react"; +import React from "react"; + +import { useTimezone } from "src/context/timezone"; +import { + isoFormatWithoutTZ, + formatDuration, + getDuration, +} from "src/datetime_utils"; +import useFilters from "src/cluster-activity/useFilters"; + +const FilterBar = () => { + const { filters, onStartDateChange, onEndDateChange, clearFilters } = + useFilters(); + + const { timezone } = useTimezone(); + const startDate = moment(filters.startDate); + const endDate = moment(filters.endDate); + const formattedStartDate = startDate.tz(timezone).format(isoFormatWithoutTZ); + const formattedEndDate = endDate.tz(timezone).format(isoFormatWithoutTZ); + + const inputStyles = { backgroundColor: "white", size: "lg" }; + + return ( + + + + + Start Date + + onStartDateChange(e.target.value)} + /> + + + + End Date + + onEndDateChange(e.target.value)} + /> + + + + over the last{" "} + {formatDuration(getDuration(formattedStartDate, formattedEndDate))} + + + + + + + + ); +}; + +export default FilterBar; diff --git a/airflow/www/static/js/cluster-activity/useFilters.tsx b/airflow/www/static/js/cluster-activity/useFilters.tsx new file mode 100644 index 0000000000000..414745d0de14a --- /dev/null +++ b/airflow/www/static/js/cluster-activity/useFilters.tsx @@ -0,0 +1,95 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* global moment */ + +import { useSearchParams } from "react-router-dom"; +import URLSearchParamsWrapper from "src/utils/URLSearchParamWrapper"; + +export interface Filters { + startDate: string; + endDate: string; +} + +export interface UtilFunctions { + onStartDateChange: (value: string) => void; + onEndDateChange: (value: string) => void; + clearFilters: () => void; +} + +export interface FilterHookReturn extends UtilFunctions { + filters: Filters; +} + +// Params names +export const START_DATE_PARAM = "start_date"; +export const END_DATE_PARAM = "end_date"; + +const date = new Date(); +date.setMilliseconds(0); + +export const now = date.toISOString(); + +const useFilters = (): FilterHookReturn => { + const [searchParams, setSearchParams] = useSearchParams(); + + const endDate = searchParams.get(END_DATE_PARAM) || now; + const startDate = + searchParams.get(START_DATE_PARAM) || + moment(endDate).subtract(1, "d").toISOString(); + + const makeOnChangeFn = + (paramName: string, formatFn?: (arg: string) => string) => + (value: string) => { + const formattedValue = formatFn ? formatFn(value) : value; + const params = new URLSearchParamsWrapper(searchParams); + + if (formattedValue) params.set(paramName, formattedValue); + else params.delete(paramName); + + setSearchParams(params); + }; + + const onStartDateChange = makeOnChangeFn( + START_DATE_PARAM, + (localDate: string) => moment(localDate).utc().format() + ); + + const onEndDateChange = makeOnChangeFn(END_DATE_PARAM, (localDate: string) => + moment(localDate).utc().format() + ); + + const clearFilters = () => { + searchParams.delete(START_DATE_PARAM); + searchParams.delete(END_DATE_PARAM); + setSearchParams(searchParams); + }; + + return { + filters: { + startDate, + endDate, + }, + onStartDateChange, + onEndDateChange, + clearFilters, + }; +}; + +export default useFilters; diff --git a/airflow/www/static/js/components/LoadingWrapper.tsx b/airflow/www/static/js/components/LoadingWrapper.tsx new file mode 100644 index 0000000000000..b85febc402ed5 --- /dev/null +++ b/airflow/www/static/js/components/LoadingWrapper.tsx @@ -0,0 +1,53 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Badge, Spinner } from "@chakra-ui/react"; +import React, { PropsWithChildren } from "react"; + +interface Props extends PropsWithChildren { + hasData: boolean; + isError: boolean; +} + +const LoadingWrapper = ({ children, hasData, isError }: Props) => { + if (isError) { + return ( + + Failed to fetch data + + ); + } + + // using hasData and not isFetching to now show a spinner on + // every refresh (autoRefresh) + if (!hasData) { + return ; + } + + // Allows to not wrap children in an extra wrapper when it is already + // a valid component. + if (React.isValidElement(children)) { + return children; + } + + // children is a str, int, etc. + return {children}; +}; + +export default LoadingWrapper; diff --git a/airflow/www/static/js/components/ReactECharts.tsx b/airflow/www/static/js/components/ReactECharts.tsx new file mode 100644 index 0000000000000..b6a26b2047535 --- /dev/null +++ b/airflow/www/static/js/components/ReactECharts.tsx @@ -0,0 +1,93 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { useRef, useEffect } from "react"; +import { init, getInstanceByDom } from "echarts"; +import type { CSSProperties } from "react"; +import type { EChartsOption, ECharts, SetOptionOpts } from "echarts"; + +export interface ReactEChartsProps { + loading?: boolean; + option: EChartsOption; + settings?: SetOptionOpts; + style?: CSSProperties; + theme?: "light" | "dark"; +} + +const ReactECharts = ({ + loading, + option, + settings, + style, + theme, +}: ReactEChartsProps) => { + const ref = useRef(null); + + useEffect(() => { + // Init Chart + let chart: ECharts | undefined; + if (ref.current !== null) { + chart = init(ref.current, theme, { + renderer: "svg", + }); + } + + const resizeChart = () => { + chart?.resize(); + }; + + window.addEventListener("resize", resizeChart); + + return () => { + chart?.dispose(); + window.removeEventListener("resize", resizeChart); + }; + }, [theme]); + + useEffect(() => { + // Handle chart loading + if (ref.current !== null) { + const chart = getInstanceByDom(ref.current); + if (loading === true) { + chart?.showLoading(); + } else { + chart?.hideLoading(); + } + } + }, [loading]); + + useEffect(() => { + // Handle option and theme updates + if (ref.current !== null) { + const chartInstance = getInstanceByDom(ref.current); + if (chartInstance) { + chartInstance.setOption(option, settings); + } + } + }, [option, settings, theme]); + + return ( +
+ ); +}; +export default ReactECharts; diff --git a/airflow/www/static/js/dag/nav/FilterBar.tsx b/airflow/www/static/js/dag/nav/FilterBar.tsx index 4b5e2f3be34b1..f76e20b270700 100644 --- a/airflow/www/static/js/dag/nav/FilterBar.tsx +++ b/airflow/www/static/js/dag/nav/FilterBar.tsx @@ -52,7 +52,12 @@ const FilterBar = () => { const inputStyles = { backgroundColor: "white", size: "lg" }; return ( - + ]: number; + }; + dagRunTypes: { + [K in CamelCase]: number; + }; + taskInstanceStates: { + [K in TaskState extends string ? CamelCase : never]: number; + }; +} + export type { API, - MinimalTaskInstance, Dag, DagRun, DatasetListItem, DepEdge, DepNode, + HistoricalMetricsData, + MinimalTaskInstance, RunOrdering, RunState, Task, diff --git a/airflow/www/templates/airflow/cluster_activity.html b/airflow/www/templates/airflow/cluster_activity.html new file mode 100644 index 0000000000000..03ba1fe34fbcb --- /dev/null +++ b/airflow/www/templates/airflow/cluster_activity.html @@ -0,0 +1,48 @@ +{# + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + #} + +{% extends base_template %} +{% block page_title %}Cluster Activity - {{ appbuilder.app_name }}{% endblock %} +{% from 'appbuilder/loading_dots.html' import loading_dots %} + +{% block head_meta %} + {{ super() }} + + + + + +{% endblock %} + +{% block content %} + {{ super() }} +
+
+ {{ loading_dots(id='react-loading') }} +
+{% endblock %} + +{% block tail_js %} + {{ super()}} + + +{% endblock %} diff --git a/airflow/www/templates/airflow/datasets.html b/airflow/www/templates/airflow/datasets.html index 6b3555c616b32..0ffd11444a3fa 100644 --- a/airflow/www/templates/airflow/datasets.html +++ b/airflow/www/templates/airflow/datasets.html @@ -19,6 +19,7 @@ {% extends base_template %} {% block page_title %}Datasets - {{ appbuilder.app_name }}{% endblock %} +{% from 'appbuilder/loading_dots.html' import loading_dots %} {% block head_meta %} {{ super() }} @@ -34,6 +35,7 @@ {{ super() }}
+ {{ loading_dots(id='react-loading') }}
{% endblock %} diff --git a/airflow/www/views.py b/airflow/www/views.py index 9b8a8ee72c4f1..592812e841d98 100644 --- a/airflow/www/views.py +++ b/airflow/www/views.py @@ -70,7 +70,7 @@ from pendulum.parsing.exceptions import ParserError from pygments import highlight, lexers from pygments.formatters import HtmlFormatter -from sqlalchemy import Date, and_, case, desc, func, inspect, union_all +from sqlalchemy import Date, and_, case, desc, func, inspect, or_, union_all from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import Session, joinedload from wtforms import SelectField, validators @@ -974,6 +974,22 @@ def datasets(self): state_color_mapping=state_color_mapping, ) + @expose("/cluster_activity") + @auth.has_access( + [ + (permissions.ACTION_CAN_READ, permissions.RESOURCE_CLUSTER_ACTIVITY), + ] + ) + def cluster_activity(self): + """Cluster Activity view.""" + state_color_mapping = State.state_color.copy() + state_color_mapping["no_status"] = state_color_mapping.pop(None) + return self.render_template( + "airflow/cluster_activity.html", + auto_refresh_interval=conf.getint("webserver", "auto_refresh_interval"), + state_color_mapping=state_color_mapping, + ) + @expose("/next_run_datasets_summary", methods=["POST"]) @auth.has_access([(permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG)]) @provide_session @@ -3791,6 +3807,71 @@ def grid_data(self): {"Content-Type": "application/json; charset=utf-8"}, ) + @expose("/object/historical_metrics_data") + @auth.has_access( + [ + (permissions.ACTION_CAN_READ, permissions.RESOURCE_CLUSTER_ACTIVITY), + ] + ) + def historical_metrics_data(self): + """Returns cluster activity historical metrics""" + start_date = _safe_parse_datetime(request.args.get("start_date")) + end_date = _safe_parse_datetime(request.args.get("end_date")) + with create_session() as session: + # DagRuns + dag_runs_type = ( + session.query(DagRun.run_type, func.count(DagRun.run_id)) + .filter( + DagRun.start_date >= start_date, + or_(DagRun.end_date.is_(None), DagRun.end_date <= end_date), + ) + .group_by(DagRun.run_type) + .all() + ) + + dag_run_states = ( + session.query(DagRun.state, func.count(DagRun.run_id)) + .filter( + DagRun.start_date >= start_date, + or_(DagRun.end_date.is_(None), DagRun.end_date <= end_date), + ) + .group_by(DagRun.state) + .all() + ) + + # TaskInstances + task_instance_states = ( + session.query(TaskInstance.state, func.count(TaskInstance.run_id)) + .join(TaskInstance.dag_run) + .filter( + DagRun.start_date >= start_date, + or_(DagRun.end_date.is_(None), DagRun.end_date <= end_date), + ) + .group_by(TaskInstance.state) + .all() + ) + + data = { + "dag_run_types": { + **{dag_run_type.value: 0 for dag_run_type in DagRunType}, + **{run_type: sum_value for run_type, sum_value in dag_runs_type}, + }, + "dag_run_states": { + **{dag_run_state.value: 0 for dag_run_state in DagRunState}, + **{run_state: sum_value for run_state, sum_value in dag_run_states}, + }, + "task_instance_states": { + "no_status": 0, + **{ti_state.value: 0 for ti_state in TaskInstanceState}, + **{ti_state or "no_status": sum_value for ti_state, sum_value in task_instance_states}, + }, + } + + return ( + htmlsafe_json_dumps(data, separators=(",", ":"), dumps=flask.json.dumps), + {"Content-Type": "application/json; charset=utf-8"}, + ) + @expose("/object/next_run_datasets/") @auth.has_access([(permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG)]) def next_run_datasets(self, dag_id): diff --git a/airflow/www/webpack.config.js b/airflow/www/webpack.config.js index 82344e3b03e96..e61947707dbf1 100644 --- a/airflow/www/webpack.config.js +++ b/airflow/www/webpack.config.js @@ -76,6 +76,7 @@ const config = { taskInstances: `${JS_DIR}/task_instances.js`, tiLog: `${JS_DIR}/ti_log.js`, grid: `${JS_DIR}/dag/index.tsx`, + clusterActivity: `${JS_DIR}/cluster-activity/index.tsx`, datasets: `${JS_DIR}/datasets/index.tsx`, calendar: [`${CSS_DIR}/calendar.css`, `${JS_DIR}/calendar.js`], durationChart: `${JS_DIR}/duration_chart.js`, diff --git a/airflow/www/yarn.lock b/airflow/www/yarn.lock index 3f8de910ccb28..6e1fce53343c5 100644 --- a/airflow/www/yarn.lock +++ b/airflow/www/yarn.lock @@ -1493,562 +1493,753 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@chakra-ui/accordion@2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@chakra-ui/accordion/-/accordion-2.0.3.tgz#4f9db1459698fd91d68f913fe7f6d1687cefabbd" - integrity sha512-3fu5q6I6QtYVfpBHK+xxIkZ3b/spHgDongXuKuLEJZswcSU8+X5B9YmNfv73ZMRKO3PboYtyHAmZZo4pYqzbbA== - dependencies: - "@chakra-ui/descendant" "3.0.2" - "@chakra-ui/hooks" "2.0.2" - "@chakra-ui/icon" "3.0.2" - "@chakra-ui/react-utils" "2.0.1" - "@chakra-ui/transition" "2.0.2" - "@chakra-ui/utils" "2.0.2" +"@chakra-ui/accordion@2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@chakra-ui/accordion/-/accordion-2.1.4.tgz#a3eca38f8e52d5a5f4b9528fb9d269dcdcb035ac" + integrity sha512-PQFW6kr+Bdru0DjKA8akC4BAz1VAJisLgo4TsJwjPO2gTS0zr99C+3bBs9uoDnjSJAf18/Q5zdXv11adA8n2XA== + dependencies: + "@chakra-ui/descendant" "3.0.11" + "@chakra-ui/icon" "3.0.13" + "@chakra-ui/react-context" "2.0.5" + "@chakra-ui/react-use-controllable-state" "2.0.6" + "@chakra-ui/react-use-merge-refs" "2.0.5" + "@chakra-ui/transition" "2.0.12" + +"@chakra-ui/alert@2.0.13": + version "2.0.13" + resolved "https://registry.yarnpkg.com/@chakra-ui/alert/-/alert-2.0.13.tgz#11d48346e501988074affe12a448add1a6060296" + integrity sha512-7LqPv6EUBte4XM/Q2qBFIT5o4BC0dSlni9BHOH2BgAc5B1NF+pBAMDTUH7JNBiN7RHTV7EHAIWDziiX/NK28+Q== + dependencies: + "@chakra-ui/icon" "3.0.13" + "@chakra-ui/react-context" "2.0.5" + "@chakra-ui/spinner" "2.0.11" + +"@chakra-ui/anatomy@2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@chakra-ui/anatomy/-/anatomy-2.1.0.tgz#8aeb9b753f0412f262743adf68519dfa85120b3e" + integrity sha512-E3jMPGqKuGTbt7mKtc8g/MOOenw2c4wqRC1vOypyFgmC8wsewdY+DJJNENF3atXAK7p5VMBKQfZ7ipNlHnDAwA== -"@chakra-ui/alert@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/alert/-/alert-2.0.2.tgz#e8230e24b974f3dc31ecb7106038e16e3f392811" - integrity sha512-QqXFYeX74mHSVp5Peqc+0CkYGQlvKQzpvOKkn00M3ZczsgVxoDNrUv0PI2V3fuZDwo1ziLBGJsjgMFbJ+JrYgA== +"@chakra-ui/avatar@2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@chakra-ui/avatar/-/avatar-2.2.1.tgz#3946d8c3b1d49dc425aa80f22d2f53661395e394" + integrity sha512-sgiogfLM8vas8QJTt7AJI4XxNXYdViCWj+xYJwyOwUN93dWKImqqx3O2ihCXoXTIqQWg1rcEgoJ5CxCg6rQaQQ== dependencies: - "@chakra-ui/icon" "3.0.2" - "@chakra-ui/react-utils" "2.0.1" - "@chakra-ui/spinner" "^2.0.2" - "@chakra-ui/utils" "2.0.2" + "@chakra-ui/image" "2.0.12" + "@chakra-ui/react-children-utils" "2.0.4" + "@chakra-ui/react-context" "2.0.5" -"@chakra-ui/anatomy@2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/anatomy/-/anatomy-2.0.1.tgz#3be152b6eaef93e0727cd12d3269b2e4374335d2" - integrity sha512-lbOUfPmCtgIe0G7Iu6C2MaFP3FKOHgKWxDrYc3498TQ7/z5N1r7AO6jB+gFRGDbxJNLjRGOLG7tV0bufagGTUw== +"@chakra-ui/breadcrumb@2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@chakra-ui/breadcrumb/-/breadcrumb-2.1.1.tgz#e8a682a4909cf8ee5771f7b287524df2be383b8a" + integrity sha512-OSa+F9qJ1xmF0zVxC1GU46OWbbhGf0kurHioSB729d+tRw/OMzmqrrfCJ7KVUUN8NEnTZXT5FIgokMvHGEt+Hg== dependencies: - "@chakra-ui/theme-tools" "^2.0.2" + "@chakra-ui/react-children-utils" "2.0.4" + "@chakra-ui/react-context" "2.0.5" -"@chakra-ui/avatar@2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@chakra-ui/avatar/-/avatar-2.0.3.tgz#952ce697edf65b48959f1eb6c08b0395ee628458" - integrity sha512-LbCQBJzDLkx2jqOjuEG5zOWA5njEAhUlQ3GnSkqOGaiDQWgM6eSLxWkgpI5fKhBlZ2OvMxjSSFaCCpf8wvU+YQ== - dependencies: - "@chakra-ui/image" "2.0.3" - "@chakra-ui/react-utils" "2.0.1" - "@chakra-ui/utils" "2.0.2" +"@chakra-ui/breakpoint-utils@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@chakra-ui/breakpoint-utils/-/breakpoint-utils-2.0.5.tgz#55b571038b66e9f6d41633c102ea904c679dac5c" + integrity sha512-8uhrckMwoR/powlAhxiFZPM0s8vn0B2yEyEaRcwpy5NmRAJSTEotC2WkSyQl/Cjysx9scredumB5g+fBX7IqGQ== -"@chakra-ui/breadcrumb@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/breadcrumb/-/breadcrumb-2.0.2.tgz#1c214a6971d65f4a355e0807eba07c0b84ae2daa" - integrity sha512-rJOkgaWqtxaPfISNXjhl9J4efD96FBnQnAKQJZtlG3WpWmIse/BPv1Pg4OCexPTBQQSwFkbTBgBD0lWD/i2UUw== +"@chakra-ui/button@2.0.13": + version "2.0.13" + resolved "https://registry.yarnpkg.com/@chakra-ui/button/-/button-2.0.13.tgz#5db6aa3425a6bebc2102cd9f58e434d5508dd999" + integrity sha512-T9W/zHpHZVcbx/BMg0JIXCgRycut/eYoTYee/E+eBxyPCH45n308AsYU2bZ8TgZxUwbYNRgMp4qRL/KHUQDv5g== dependencies: - "@chakra-ui/react-utils" "2.0.1" - "@chakra-ui/utils" "2.0.2" + "@chakra-ui/react-context" "2.0.5" + "@chakra-ui/react-use-merge-refs" "2.0.5" + "@chakra-ui/spinner" "2.0.11" -"@chakra-ui/button@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/button/-/button-2.0.2.tgz#a5ef09324e4dbf95e1814a1755b2a35c365470ea" - integrity sha512-l2RE1031HR+vVqNQhfrJCuC1OzKTTLmyA8+ScGZhjV6G4LWGzU5LfsyGAXq53l1lFcx6O9XJzfgnxAvnGGKJsw== +"@chakra-ui/card@2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@chakra-ui/card/-/card-2.1.1.tgz#b981a68d81d0f6447eb0d4d3fdcd7846bab2111f" + integrity sha512-vvmfuNn6gkfv6bGcXQe6kvWHspziPZgYnnffiEjPaZYtaf98WRszpjyPbFv0oQR/2H1RSE1oaTqa/J1rHrzw3A== dependencies: - "@chakra-ui/hooks" "2.0.2" - "@chakra-ui/react-utils" "2.0.1" - "@chakra-ui/spinner" "2.0.2" - "@chakra-ui/utils" "2.0.2" + "@chakra-ui/react-context" "2.0.5" -"@chakra-ui/checkbox@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/checkbox/-/checkbox-2.1.0.tgz#5df4917b06d8e671a9822c46f5e2ec259ef40c85" - integrity sha512-LPKhJM/IMp8LKdr52PVfSGAnmqcgwTMPcjyWT8jXQ3OhEXRUKc5rSUORmPtJmffNLjLq1nPCcSMWQsVHhJ9MXw== - dependencies: - "@chakra-ui/form-control" "2.0.2" - "@chakra-ui/hooks" "2.0.2" - "@chakra-ui/react-utils" "2.0.1" - "@chakra-ui/utils" "2.0.2" - "@chakra-ui/visually-hidden" "2.0.2" +"@chakra-ui/checkbox@2.2.5": + version "2.2.5" + resolved "https://registry.yarnpkg.com/@chakra-ui/checkbox/-/checkbox-2.2.5.tgz#ce1c409647d11bf947ff0316bc397bc7cf25316c" + integrity sha512-7fNH+Q2nB2uMSnYAPtYxnuwZ1MOJqblZHa/ScfZ/fjiPDyEae1m068ZP/l9yJ5zlawYMTkp83m/JVcu5QFYurA== + dependencies: + "@chakra-ui/form-control" "2.0.13" + "@chakra-ui/react-context" "2.0.5" + "@chakra-ui/react-types" "2.0.5" + "@chakra-ui/react-use-callback-ref" "2.0.5" + "@chakra-ui/react-use-controllable-state" "2.0.6" + "@chakra-ui/react-use-merge-refs" "2.0.5" + "@chakra-ui/react-use-safe-layout-effect" "2.0.3" + "@chakra-ui/react-use-update-effect" "2.0.5" + "@chakra-ui/visually-hidden" "2.0.13" "@zag-js/focus-visible" "0.1.0" -"@chakra-ui/clickable@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/clickable/-/clickable-2.0.2.tgz#21cb225df159b488ee4c407729ef5a3cfcb4a5a5" - integrity sha512-Zn0Hd9BCGVNMOXerUlfmOdCeVAyl6XYo5WC/Skm/REAQygk22/WjV42sLeT+1+bpOLpSvO4ZnheXfD5sIuDdfA== +"@chakra-ui/clickable@2.0.11": + version "2.0.11" + resolved "https://registry.yarnpkg.com/@chakra-ui/clickable/-/clickable-2.0.11.tgz#d0afcdb40ed1b1ceeabb4ac3e9f2f51fd3cbdac7" + integrity sha512-5Y2dl5cxNgOxHbjxyxsL6Vdze4wUUvwsMCCW3kXwgz2OUI2y5UsBZNcvhNJx3RchJEd0fylMKiKoKmnZMHN2aw== dependencies: - "@chakra-ui/react-utils" "2.0.1" - "@chakra-ui/utils" "2.0.2" + "@chakra-ui/react-use-merge-refs" "2.0.5" -"@chakra-ui/close-button@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/close-button/-/close-button-2.0.2.tgz#5ac6bee78032d77017299650971624dd9498acca" - integrity sha512-aIpkIQdmbuKTiM1IuZRI4iUPzcaWla8mXysKIL+M6g0QbpaO/Xw3eucnAS0qO24djCzkcCZSLnHsEimBOBJdgA== +"@chakra-ui/close-button@2.0.13": + version "2.0.13" + resolved "https://registry.yarnpkg.com/@chakra-ui/close-button/-/close-button-2.0.13.tgz#c549d682c66f3e08b1f37e98a83ebe0421846496" + integrity sha512-ZI/3p84FPlW0xoDCZYqsnIvR6bTc2d/TlhwyTHsDDxq9ZOWp9c2JicVn6WTdWGdshk8itnZZdG50IcnizGnimA== dependencies: - "@chakra-ui/icon" "3.0.2" - "@chakra-ui/utils" "2.0.2" + "@chakra-ui/icon" "3.0.13" -"@chakra-ui/color-mode@2.0.4": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@chakra-ui/color-mode/-/color-mode-2.0.4.tgz#143c1c0baa5f8b21a491776fc58107675075c5f8" - integrity sha512-DIR6CSPlkmi92LDR3IhjIediLk7GFWttlTUvJQP06ZUvN+iCpd5TjgchxOYzqlP4T9W0L62eZXsluOxmRF/JSQ== +"@chakra-ui/color-mode@2.1.10": + version "2.1.10" + resolved "https://registry.yarnpkg.com/@chakra-ui/color-mode/-/color-mode-2.1.10.tgz#8d446550af80cf01a2ccd7470861cb0180112049" + integrity sha512-aUPouOUPn7IPm1v00/9AIkRuNrkCwJlbjVL1kJzLzxijYjbHvEHPxntITt+JWjtXPT8xdOq6mexLYCOGA67JwQ== dependencies: - "@chakra-ui/hooks" "2.0.2" - "@chakra-ui/utils" "2.0.2" + "@chakra-ui/react-use-safe-layout-effect" "2.0.3" -"@chakra-ui/control-box@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/control-box/-/control-box-2.0.2.tgz#9c2ffb3d766737447b9fbb1f1af028ad9f9eed2d" - integrity sha512-D3vQoyCRjAwCmB39jFvTv+fAXmALLhScXe6s/S7rdgSYxuSEksuGlNjvBUYAVwDXeE2sjDoeWMvrHydRGv44Bw== - dependencies: - "@chakra-ui/utils" "2.0.2" +"@chakra-ui/control-box@2.0.11": + version "2.0.11" + resolved "https://registry.yarnpkg.com/@chakra-ui/control-box/-/control-box-2.0.11.tgz#b2deec368fc83f6675964785f823e4c0c1f5d4ac" + integrity sha512-UJb4vqq+/FPuwTCuaPeHa2lwtk6u7eFvLuwDCST2e/sBWGJC1R+1/Il5pHccnWs09FWxyZ9v/Oxkg/CG3jZR4Q== -"@chakra-ui/counter@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/counter/-/counter-2.0.2.tgz#e27312d61bc6d8bcd1eb913383ca1db1af6b99bd" - integrity sha512-mRYrnu1924spsPU5GaHSbaoX28Gbzf8PDkO6Y1R6r6MQKTLjpdbkFmyG0QyEixD8aoaSaCO7iVbJRnUJ+dhlww== +"@chakra-ui/counter@2.0.11": + version "2.0.11" + resolved "https://registry.yarnpkg.com/@chakra-ui/counter/-/counter-2.0.11.tgz#b49aa76423e5f4a4a8e717750c190fa5050a3dca" + integrity sha512-1YRt/jom+m3iWw9J9trcM6rAHDvD4lwThiO9raxUK7BRsYUhnPZvsMpcXU1Moax218C4rRpbI9KfPLaig0m1xQ== dependencies: - "@chakra-ui/hooks" "2.0.2" - "@chakra-ui/utils" "2.0.2" + "@chakra-ui/number-utils" "2.0.5" + "@chakra-ui/react-use-callback-ref" "2.0.5" -"@chakra-ui/css-reset@2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/css-reset/-/css-reset-2.0.1.tgz#53bbc2c48dd9fdfb59af8cb8e20390ad7ddb3688" - integrity sha512-8RhAC7l5RHp9hNDN2M2feZ2wPaoSrgxzqx6VqLTIul2lwucpp1LTlrDlPCBMJe8fp51Q83IOCW4882ktsXxktA== +"@chakra-ui/css-reset@2.0.10": + version "2.0.10" + resolved "https://registry.yarnpkg.com/@chakra-ui/css-reset/-/css-reset-2.0.10.tgz#cb6cd97ee38f8069789f08c31a828bf3a7e339ea" + integrity sha512-FwHOfw2P4ckbpSahDZef2KoxcvHPUg09jlicWdp24/MjdsOO5PAB/apm2UBvQflY4WAJyOqYaOdnXFlR6nF4cQ== -"@chakra-ui/descendant@3.0.2": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/descendant/-/descendant-3.0.2.tgz#1cf2584989160d93d8983bca7e237dd9368cc0c5" - integrity sha512-BV4IpONYr52V7rJnEYj5Ej946HD2BTOgOQpSB/LMeITfkp51/O9pOayNoVghYW7cFts+Opy4YmvLcuxFhWrD3Q== +"@chakra-ui/descendant@3.0.11": + version "3.0.11" + resolved "https://registry.yarnpkg.com/@chakra-ui/descendant/-/descendant-3.0.11.tgz#cb8bca7b6e8915afc58cdb1444530a2d1b03efd3" + integrity sha512-sNLI6NS6uUgrvYS6Imhoc1YlI6bck6pfxMBJcnXVSfdIjD6XjCmeY2YgzrtDS+o+J8bB3YJeIAG/vsVy5USE5Q== dependencies: - "@chakra-ui/react-utils" "^2.0.1" + "@chakra-ui/react-context" "2.0.5" + "@chakra-ui/react-use-merge-refs" "2.0.5" -"@chakra-ui/editable@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/editable/-/editable-2.0.2.tgz#473dfc05245debae7d1e336870a4e0b466d6373a" - integrity sha512-hZBD4K1i3a8+RnW5jaoVfHeEm0zDKcyZ7yZCNGmmM7sz2LAw/LdE6+IKBoEbXc5Gf8KnEs9eH/TBcPDhS9KUQg== - dependencies: - "@chakra-ui/hooks" "2.0.2" - "@chakra-ui/react-utils" "2.0.1" - "@chakra-ui/utils" "2.0.2" +"@chakra-ui/dom-utils@2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@chakra-ui/dom-utils/-/dom-utils-2.0.4.tgz#367fffecbd287e16836e093d4030dc6e3785d402" + integrity sha512-P936+WKinz5fgHzfwiUQjE/t7NC8bU89Tceim4tbn8CIm/9b+CsHX64eNw4vyJqRwt78TXQK7aGBIbS18R0q5Q== + +"@chakra-ui/editable@2.0.16": + version "2.0.16" + resolved "https://registry.yarnpkg.com/@chakra-ui/editable/-/editable-2.0.16.tgz#8a45ff26d77f06841ea986484d71ede312b4c22e" + integrity sha512-kIFPufzIlViNv7qi2PxxWWBvjLb+3IP5hUGmqOA9qcYz5TAdqblQqDClm0iajlIDNUFWnS4h056o8jKsQ42a5A== + dependencies: + "@chakra-ui/react-context" "2.0.5" + "@chakra-ui/react-types" "2.0.5" + "@chakra-ui/react-use-callback-ref" "2.0.5" + "@chakra-ui/react-use-controllable-state" "2.0.6" + "@chakra-ui/react-use-focus-on-pointer-down" "2.0.4" + "@chakra-ui/react-use-merge-refs" "2.0.5" + "@chakra-ui/react-use-safe-layout-effect" "2.0.3" + "@chakra-ui/react-use-update-effect" "2.0.5" + "@chakra-ui/shared-utils" "2.0.3" + +"@chakra-ui/event-utils@2.0.6": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@chakra-ui/event-utils/-/event-utils-2.0.6.tgz#5e04d68ea070ef52ce212c2a99be9afcc015cfaf" + integrity sha512-ZIoqUbgJ5TcCbZRchMv4n7rOl1JL04doMebED88LO5mux36iVP9er/nnOY4Oke1bANKKURMrQf5VTT9hoYeA7A== -"@chakra-ui/focus-lock@2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@chakra-ui/focus-lock/-/focus-lock-2.0.3.tgz#8fa0fad83256d79b31ec7970751f74f519ecf123" - integrity sha512-QcKUy0n26T1qOEoqk9rDmr9tumZs/+VXh9gIhWYKlmScm8Dy87qCMfOJ2M8/sUCQcqypl8SwlONQdiCZ99FUFQ== +"@chakra-ui/focus-lock@2.0.13": + version "2.0.13" + resolved "https://registry.yarnpkg.com/@chakra-ui/focus-lock/-/focus-lock-2.0.13.tgz#19d6ca35555965a9aaa241b991a67bbc875ee53d" + integrity sha512-AVSJt+3Ukia/m9TCZZgyWvTY7pw88jArivWVJ2gySGYYIs6z/FJMnlwbCVldV2afS0g3cYaii7aARb/WrlG34Q== dependencies: - "@chakra-ui/utils" "2.0.2" + "@chakra-ui/dom-utils" "2.0.4" react-focus-lock "^2.9.1" -"@chakra-ui/form-control@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/form-control/-/form-control-2.0.2.tgz#14f32407a69559805c91d6ef6695d1056a5e4b59" - integrity sha512-uelLKIZgrcahvodEAd2WjdCJUus9q9Wq++KliN+8VIhPti89s8eewyDh3xWvurbgby+oGkHyjDMmxHrkfa3YYQ== +"@chakra-ui/form-control@2.0.13": + version "2.0.13" + resolved "https://registry.yarnpkg.com/@chakra-ui/form-control/-/form-control-2.0.13.tgz#51831f981a2e937b0258b4fd2dd4ceacda03c01a" + integrity sha512-J964JlgrxP+LP3kYmLk1ttbl73u6ghT+JQDjEjkEUc8lSS9Iv4u9XkRDQHuz2t2y0KHjQdH12PUfUfBqcITbYw== dependencies: - "@chakra-ui/hooks" "2.0.2" - "@chakra-ui/icon" "3.0.2" - "@chakra-ui/react-utils" "2.0.1" - "@chakra-ui/utils" "2.0.2" + "@chakra-ui/icon" "3.0.13" + "@chakra-ui/react-context" "2.0.5" + "@chakra-ui/react-types" "2.0.5" + "@chakra-ui/react-use-merge-refs" "2.0.5" -"@chakra-ui/hooks@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/hooks/-/hooks-2.0.2.tgz#6153f33957f23b8f156b7ce4ce1605f89e67c1b5" - integrity sha512-3B4zsl51tevmO6T6xUKcclwxf4FClKtScaNvb8jMmVczTGRL7WhZ6LxXeYUJMms11C8W9uZczE5yXSP0qweeAw== +"@chakra-ui/hooks@2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@chakra-ui/hooks/-/hooks-2.1.2.tgz#1e413f6624e97b854569e8a19846c9162a4ec153" + integrity sha512-/vDBOqqnho9q++lay0ZcvnH8VuE0wT2OkZj+qDwFwjiHAtGPVxHCSpu9KC8BIHME5TlWjyO6riVyUCb2e2ip6w== dependencies: - "@chakra-ui/react-utils" "2.0.1" - "@chakra-ui/utils" "2.0.2" + "@chakra-ui/react-utils" "2.0.9" + "@chakra-ui/utils" "2.0.12" compute-scroll-into-view "1.0.14" copy-to-clipboard "3.3.1" -"@chakra-ui/icon@3.0.2": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/icon/-/icon-3.0.2.tgz#e8b380981690a543382f56f9d184f6b28f4b3d83" - integrity sha512-sas37byldn5O/TTIKHzxHBujEYqVPXegisoMqutLtF60fpXnb62aG1JTyorXSG3zJxJWQW7+AvjbOGyWKHXc0Q== - dependencies: - "@chakra-ui/utils" "2.0.2" - -"@chakra-ui/image@2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@chakra-ui/image/-/image-2.0.3.tgz#49a73c39aacbec1c956503adf1b20cd945889593" - integrity sha512-GLMJXLdR0y7CCZ0hKHf6YZLb8dlPpx4vdXWTbtLnIU5EfGIOSiCU4N3+0KcjvMtDB69hBr5W4h1XMJNpetP1EA== +"@chakra-ui/icon@3.0.13": + version "3.0.13" + resolved "https://registry.yarnpkg.com/@chakra-ui/icon/-/icon-3.0.13.tgz#1782f8bd81946eabb39d4dde9eccebba1e5571ba" + integrity sha512-RaDLC4psd8qyInY2RX4AlYRfpLBNw3VsMih17BFf8EESVhBXNJcYy7Q9eMV/K4NvZfZT42vuVqGVNFmkG89lBQ== dependencies: - "@chakra-ui/hooks" "2.0.2" - "@chakra-ui/utils" "2.0.2" + "@chakra-ui/shared-utils" "2.0.3" -"@chakra-ui/input@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/input/-/input-2.0.2.tgz#fd14044f31aad687387e40043438f5b96a9a2d70" - integrity sha512-ODwdlsLha+EBPFSnCEqWjlndeXaL4cXvCk4rrKuvs9vexhOBr+X9V6KNn5Rmn/bXah+Wsrn+5g6T9V7BvRES3Q== +"@chakra-ui/image@2.0.12": + version "2.0.12" + resolved "https://registry.yarnpkg.com/@chakra-ui/image/-/image-2.0.12.tgz#e90b1d2a5f87fff90b1ef86ca75bfe6b44ac545d" + integrity sha512-uclFhs0+wq2qujGu8Wk4eEWITA3iZZQTitGiFSEkO9Ws5VUH+Gqtn3mUilH0orubrI5srJsXAmjVTuVwge1KJQ== dependencies: - "@chakra-ui/form-control" "2.0.2" - "@chakra-ui/react-utils" "2.0.1" - "@chakra-ui/utils" "2.0.2" + "@chakra-ui/react-use-safe-layout-effect" "2.0.3" -"@chakra-ui/layout@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/layout/-/layout-2.0.2.tgz#556ab483f01e33efd4bf4a7a2105ea7d272b4c05" - integrity sha512-iElUGxj8YmVGcaCQlQovJJC4APHMh5vwlZU37IC6W3FdJzv+orVhzbuB98tuzfWHxjKQZeGhcz7+npIkN87D5w== - dependencies: - "@chakra-ui/icon" "3.0.2" - "@chakra-ui/react-utils" "2.0.1" - "@chakra-ui/utils" "2.0.2" +"@chakra-ui/input@2.0.14": + version "2.0.14" + resolved "https://registry.yarnpkg.com/@chakra-ui/input/-/input-2.0.14.tgz#eec3d04834ab1ac7dab344e9bf14d779c4f4da31" + integrity sha512-CkSrUJeKWogOSt2pUf2vVv5s0bUVcAi4/XGj1JVCCfyIX6a6h1m8R69MShTPxPiQ0Mdebq5ATrW/aZQQXZzRGQ== + dependencies: + "@chakra-ui/form-control" "2.0.13" + "@chakra-ui/object-utils" "2.0.5" + "@chakra-ui/react-children-utils" "2.0.4" + "@chakra-ui/react-context" "2.0.5" + "@chakra-ui/shared-utils" "2.0.3" + +"@chakra-ui/layout@2.1.11": + version "2.1.11" + resolved "https://registry.yarnpkg.com/@chakra-ui/layout/-/layout-2.1.11.tgz#6b0005dd897a901f2fded99c19fe47f60db80cb3" + integrity sha512-UP19V8EeI/DEODbWrZlqC0sg248bpFaWpMiM/+g9Bsxs9aof3yexpMD/7gb0yrfbIrkdvSBrcQeqxXGzbfoopw== + dependencies: + "@chakra-ui/breakpoint-utils" "2.0.5" + "@chakra-ui/icon" "3.0.13" + "@chakra-ui/object-utils" "2.0.5" + "@chakra-ui/react-children-utils" "2.0.4" + "@chakra-ui/react-context" "2.0.5" + "@chakra-ui/shared-utils" "2.0.3" + +"@chakra-ui/lazy-utils@2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@chakra-ui/lazy-utils/-/lazy-utils-2.0.3.tgz#5ba459a2541ad0c98cd98b20a8054664c129e9b4" + integrity sha512-SQ5I5rJrcHpVUcEftHLOh8UyeY+06R8Gv3k2RjcpvM6mb2Gktlz/4xl2GcUh3LWydgGQDW/7Rse5rQhKWgzmcg== -"@chakra-ui/live-region@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/live-region/-/live-region-2.0.2.tgz#811655e68347237ae7c75b280e3306d197f0c25a" - integrity sha512-aRJRaJInqNkFRRIjW57SPNhj7ngxh0xkdQZeOohvOcd7VbjvHNgXO1glKjIXRzSRHyteCdGUzb/jo68NizE3bQ== - dependencies: - "@chakra-ui/utils" "2.0.2" +"@chakra-ui/live-region@2.0.11": + version "2.0.11" + resolved "https://registry.yarnpkg.com/@chakra-ui/live-region/-/live-region-2.0.11.tgz#1008c5b629aa4120e5158be53f13d8d34bc2d71a" + integrity sha512-ltObaKQekP75GCCbN+vt1/mGABSCaRdQELmotHTBc5AioA3iyCDHH69ev+frzEwLvKFqo+RomAdAAgqBIMJ02Q== -"@chakra-ui/media-query@3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/media-query/-/media-query-3.1.0.tgz#421dc60a9c2226d65bb7eb8772de283227fc3724" - integrity sha512-E05PUom+izNILJff0Yje8OMWHVN5C2H2A/F0aaptIJ+600YNWn5CuGvdlSMb/VWHziHT7u5xyrtv0mdbxMlYBA== +"@chakra-ui/media-query@3.2.8": + version "3.2.8" + resolved "https://registry.yarnpkg.com/@chakra-ui/media-query/-/media-query-3.2.8.tgz#7d5feccb7ac52891426c060dd2ed1df37420956d" + integrity sha512-djmEg/eJ5Qrjn7SArTqjsvlwF6mNeMuiawrTwnU+0EKq9Pq/wVSb7VaIhxdQYJLA/DbRhE/KPMogw1LNVKa4Rw== dependencies: - "@chakra-ui/react-env" "2.0.2" - "@chakra-ui/utils" "2.0.2" + "@chakra-ui/breakpoint-utils" "2.0.5" + "@chakra-ui/react-env" "2.0.11" -"@chakra-ui/menu@2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@chakra-ui/menu/-/menu-2.0.3.tgz#b1d02fc20856315eb50db54de40d5a07eaf68368" - integrity sha512-hW1XBK0ZOEvnrwurqZiQ7+CFW8Olfk82BilNOulQ7LxQ2hQAAg4JBQxs755jVEtqhSAP+oe/yuWEabWtCWLGQw== - dependencies: - "@chakra-ui/clickable" "2.0.2" - "@chakra-ui/descendant" "3.0.2" - "@chakra-ui/hooks" "2.0.2" - "@chakra-ui/popper" "3.0.2" - "@chakra-ui/react-utils" "2.0.1" - "@chakra-ui/transition" "2.0.2" - "@chakra-ui/utils" "2.0.2" - -"@chakra-ui/modal@2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@chakra-ui/modal/-/modal-2.0.3.tgz#2291837bf0cb5b15b7baabde2632be2144224b1e" - integrity sha512-GS1Apvrsr8scM1d/awVgJdcheITja4fMKTKwWljstw7SfAMOPc4skKIg+MzriLvtIialm1WFxOWYfiQ5MKAAcQ== - dependencies: - "@chakra-ui/close-button" "2.0.2" - "@chakra-ui/focus-lock" "2.0.3" - "@chakra-ui/hooks" "2.0.2" - "@chakra-ui/portal" "2.0.2" - "@chakra-ui/react-utils" "2.0.1" - "@chakra-ui/transition" "2.0.2" - "@chakra-ui/utils" "2.0.2" +"@chakra-ui/menu@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@chakra-ui/menu/-/menu-2.1.5.tgz#73b6db93d6dec9d04ab7c2630a7984e3180fd769" + integrity sha512-2UusrQtxHcqcO9n/0YobNN3RJC8yAZU6oJbRPuvsQ9IL89scEWCTIxXEYrnIjeh/5zikcSEDGo9zM9Udg/XcsA== + dependencies: + "@chakra-ui/clickable" "2.0.11" + "@chakra-ui/descendant" "3.0.11" + "@chakra-ui/lazy-utils" "2.0.3" + "@chakra-ui/popper" "3.0.10" + "@chakra-ui/react-children-utils" "2.0.4" + "@chakra-ui/react-context" "2.0.5" + "@chakra-ui/react-use-animation-state" "2.0.6" + "@chakra-ui/react-use-controllable-state" "2.0.6" + "@chakra-ui/react-use-disclosure" "2.0.6" + "@chakra-ui/react-use-focus-effect" "2.0.7" + "@chakra-ui/react-use-merge-refs" "2.0.5" + "@chakra-ui/react-use-outside-click" "2.0.5" + "@chakra-ui/react-use-update-effect" "2.0.5" + "@chakra-ui/transition" "2.0.12" + +"@chakra-ui/modal@2.2.4": + version "2.2.4" + resolved "https://registry.yarnpkg.com/@chakra-ui/modal/-/modal-2.2.4.tgz#dbe884a9245ed840b6511a4f06b4a622fa86de4c" + integrity sha512-K2cafyNI0b4OSAB55qIXt5DLZqj7E1G0+Fza02ZOBZpgTCNQyDtc0KzdVMJZ9ryxKd16LUk5UmKHugY/VpHEWQ== + dependencies: + "@chakra-ui/close-button" "2.0.13" + "@chakra-ui/focus-lock" "2.0.13" + "@chakra-ui/portal" "2.0.11" + "@chakra-ui/react-context" "2.0.5" + "@chakra-ui/react-types" "2.0.5" + "@chakra-ui/react-use-merge-refs" "2.0.5" + "@chakra-ui/transition" "2.0.12" aria-hidden "^1.1.1" react-remove-scroll "^2.5.4" -"@chakra-ui/number-input@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/number-input/-/number-input-2.0.2.tgz#9b3a8c054307d5e6d251851ab14f2d55307f83b3" - integrity sha512-7RT5TMCSPtghX7M2Uy2cruLwO0uYCzIa49tQFDzQ2YCGMuRimzma9i0nuOqQz2yGHxa3C8WJJoO91jPKzCjIbg== - dependencies: - "@chakra-ui/counter" "2.0.2" - "@chakra-ui/form-control" "2.0.2" - "@chakra-ui/hooks" "2.0.2" - "@chakra-ui/icon" "3.0.2" - "@chakra-ui/react-utils" "2.0.1" - "@chakra-ui/utils" "2.0.2" +"@chakra-ui/number-input@2.0.14": + version "2.0.14" + resolved "https://registry.yarnpkg.com/@chakra-ui/number-input/-/number-input-2.0.14.tgz#e6336228b9210f9543fe440bfc6478537810d59c" + integrity sha512-IARUAbP4pn1gP5fY2dK4wtbR3ONjzHgTjH4Zj3ErZvdu/yTURLaZmlb6UGHwgqjWLyioactZ/+n4Njj5CRjs8w== + dependencies: + "@chakra-ui/counter" "2.0.11" + "@chakra-ui/form-control" "2.0.13" + "@chakra-ui/icon" "3.0.13" + "@chakra-ui/react-context" "2.0.5" + "@chakra-ui/react-types" "2.0.5" + "@chakra-ui/react-use-callback-ref" "2.0.5" + "@chakra-ui/react-use-event-listener" "2.0.5" + "@chakra-ui/react-use-interval" "2.0.3" + "@chakra-ui/react-use-merge-refs" "2.0.5" + "@chakra-ui/react-use-safe-layout-effect" "2.0.3" + "@chakra-ui/react-use-update-effect" "2.0.5" + +"@chakra-ui/number-utils@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@chakra-ui/number-utils/-/number-utils-2.0.5.tgz#c7595fc919fca7c43fe172bfd6c5197c653ee572" + integrity sha512-Thhohnlqze0i5HBJO9xkfOPq1rv3ji/hNPf2xh1fh4hxrNzdm3HCkz0c6lyRQwGuVoeltEHysYZLH/uWLFTCSQ== -"@chakra-ui/pin-input@2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@chakra-ui/pin-input/-/pin-input-2.0.3.tgz#b647f825683b889b1cabc18dc49ccc17ea1a460d" - integrity sha512-tnISIFno2Nqmh5ZjXyRnUiyuw94xLpFWoVK9tTo/yoR5Llbh58BqRyybOZZpu3DIjuK9qy9M67KBhRdqkOLUFQ== +"@chakra-ui/object-utils@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@chakra-ui/object-utils/-/object-utils-2.0.5.tgz#231602066ddb96ae91dcc7da243b97ad46972398" + integrity sha512-/rIMoYI3c2uLtFIrnTFOPRAI8StUuu335WszqKM0KAW1lwG9H6uSbxqlpZT1Pxi/VQqZKfheGiMQOx5lfTmM/A== + +"@chakra-ui/pin-input@2.0.16": + version "2.0.16" + resolved "https://registry.yarnpkg.com/@chakra-ui/pin-input/-/pin-input-2.0.16.tgz#d31a6e2bce85aa2d1351ccb4cd9bf7a5134d3fb9" + integrity sha512-51cioNYpBSgi9/jq6CrzoDvo8fpMwFXu3SaFRbKO47s9Dz/OAW0MpjyabTfSpwOv0xKZE+ayrYGJopCzZSWXPg== + dependencies: + "@chakra-ui/descendant" "3.0.11" + "@chakra-ui/react-children-utils" "2.0.4" + "@chakra-ui/react-context" "2.0.5" + "@chakra-ui/react-use-controllable-state" "2.0.6" + "@chakra-ui/react-use-merge-refs" "2.0.5" + +"@chakra-ui/popover@2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@chakra-ui/popover/-/popover-2.1.4.tgz#c44df775875faabe09ef13ce32150a2631c768dd" + integrity sha512-NXVtyMxYzDKzzQph/+GFRSM3tEj3gNvlCX/xGRsCOt9I446zJ1InCd/boXQKAc813coEN9McSOjNWgo+NCBD+Q== + dependencies: + "@chakra-ui/close-button" "2.0.13" + "@chakra-ui/lazy-utils" "2.0.3" + "@chakra-ui/popper" "3.0.10" + "@chakra-ui/react-context" "2.0.5" + "@chakra-ui/react-types" "2.0.5" + "@chakra-ui/react-use-animation-state" "2.0.6" + "@chakra-ui/react-use-disclosure" "2.0.6" + "@chakra-ui/react-use-focus-effect" "2.0.7" + "@chakra-ui/react-use-focus-on-pointer-down" "2.0.4" + "@chakra-ui/react-use-merge-refs" "2.0.5" + +"@chakra-ui/popper@3.0.10": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@chakra-ui/popper/-/popper-3.0.10.tgz#5d382c36359615e349e679445eb58c139dbb4d4f" + integrity sha512-6LacbBGX0piHWY/DYxOGCTTFAoRGRHpGIRzTgfNy8jxw4f+rukaVudd4Pc2fwjCTdobJKM8nGNYIYNv9/Dmq9Q== dependencies: - "@chakra-ui/descendant" "3.0.2" - "@chakra-ui/hooks" "2.0.2" - "@chakra-ui/react-utils" "2.0.1" - "@chakra-ui/utils" "2.0.2" + "@chakra-ui/react-types" "2.0.5" + "@chakra-ui/react-use-merge-refs" "2.0.5" + "@popperjs/core" "^2.9.3" -"@chakra-ui/popover@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/popover/-/popover-2.0.2.tgz#14265da8007352497b914e3d9338e9333bb8927c" - integrity sha512-i9Tsx+gpN470V7eLPng+lVK25DfUdQ44OAzWMUavIiutCtVJknZEPYbSr72JnT4NHBnr7b8rqUBEYq9+36LmlQ== +"@chakra-ui/portal@2.0.11": + version "2.0.11" + resolved "https://registry.yarnpkg.com/@chakra-ui/portal/-/portal-2.0.11.tgz#7a6b3ebc621bb28b46550fcfb36b94926d0111a5" + integrity sha512-Css61i4WKzKO8ou1aGjBzcsXMy9LnfnpkOFfvaNCpUUNEd6c47z6+FhZNq7Gc38PGNjSfMLAd4LmH+H0ZanYIA== dependencies: - "@chakra-ui/close-button" "2.0.2" - "@chakra-ui/hooks" "2.0.2" - "@chakra-ui/popper" "3.0.2" - "@chakra-ui/react-utils" "2.0.1" - "@chakra-ui/utils" "2.0.2" + "@chakra-ui/react-context" "2.0.5" + "@chakra-ui/react-use-safe-layout-effect" "2.0.3" -"@chakra-ui/popper@3.0.2": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/popper/-/popper-3.0.2.tgz#63994c39c316b03f68597099113e0719ac70ac8f" - integrity sha512-oEUsaFR4EPY3CvhEVeZNoa+mA/w+TvLlG3xlicIwv/3Fcfl6LD2Jhr6utnqAvHFxE/qRcUcXLX20ovy0Zrgm/Q== +"@chakra-ui/progress@2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@chakra-ui/progress/-/progress-2.1.1.tgz#b94399af12e9324737f9e690201f78546572ac59" + integrity sha512-ddAXaYGNObGqH1stRAYxkdospf6J4CDOhB0uyw9BeHRSsYkCUQWkUBd/melJuZeGHEH2ItF9T7FZ4JhcepP3GA== dependencies: - "@chakra-ui/react-utils" "2.0.1" - "@popperjs/core" "^2.9.3" + "@chakra-ui/react-context" "2.0.5" -"@chakra-ui/portal@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/portal/-/portal-2.0.2.tgz#403dc6bb2d13dfc8a89acc47dd79ba4da8f20658" - integrity sha512-bk8P/hxvGbKhEZSI2LAFwk98W7ivff3NwpFOHjsna0uuBPG772mEOXnxsHBsr2moGroMXdBOS++czHn1T3cHhw== +"@chakra-ui/provider@2.0.24": + version "2.0.24" + resolved "https://registry.yarnpkg.com/@chakra-ui/provider/-/provider-2.0.24.tgz#733f0eacf779d39029cee164027af7bf5c6c66c3" + integrity sha512-32+DGfoXAOUOXwjLstdGQ+k/YoCwdFxWbwnEAp7WleislYsMcl0JeINDAbvksQH0piBty77swTuWfUU5cIox7g== dependencies: - "@chakra-ui/hooks" "2.0.2" - "@chakra-ui/react-utils" "2.0.1" - "@chakra-ui/utils" "2.0.2" + "@chakra-ui/css-reset" "2.0.10" + "@chakra-ui/portal" "2.0.11" + "@chakra-ui/react-env" "2.0.11" + "@chakra-ui/system" "2.3.4" + "@chakra-ui/utils" "2.0.12" -"@chakra-ui/progress@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/progress/-/progress-2.0.2.tgz#b3f3912dae4cf9196c72f6d8bd234b710a0dbd72" - integrity sha512-nx/aDZGEAnRx6jC4RLbfoXTTEeHoHGVlwBTUx7OKPus+hopBVvXHpA/UH+H8OJ5nq0PJ6XaDPCHc1FTrK+j0aw== +"@chakra-ui/radio@2.0.14": + version "2.0.14" + resolved "https://registry.yarnpkg.com/@chakra-ui/radio/-/radio-2.0.14.tgz#f214f728235782a2ac49c0eb507f151612e31b2e" + integrity sha512-e/hY1g92Xdu5d5A27NFfa1+ccE2q/A5H7sc/M7p0fId6KO33Dst25Hy+HThtqnYN0Y3Om58fiXEKo5SsdtvSfA== dependencies: - "@chakra-ui/theme-tools" "2.0.2" - "@chakra-ui/utils" "2.0.2" + "@chakra-ui/form-control" "2.0.13" + "@chakra-ui/react-context" "2.0.5" + "@chakra-ui/react-types" "2.0.5" + "@chakra-ui/react-use-merge-refs" "2.0.5" + "@zag-js/focus-visible" "0.1.0" + +"@chakra-ui/react-children-utils@2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-children-utils/-/react-children-utils-2.0.4.tgz#6e4284297a8a9b4e6f5f955b099bb6c2c6bbf8b9" + integrity sha512-qsKUEfK/AhDbMexWo5JhmdlkxLg5WEw2dFh4XorvU1/dTYsRfP6cjFfO8zE+X3F0ZFNsgKz6rbN5oU349GLEFw== + +"@chakra-ui/react-context@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-context/-/react-context-2.0.5.tgz#c434013ecc46c780539791d756dafdfc7c64320e" + integrity sha512-WYS0VBl5Q3/kNShQ26BP+Q0OGMeTQWco3hSiJWvO2wYLY7N1BLq6dKs8vyKHZfpwKh2YL2bQeAObi+vSkXp6tQ== + +"@chakra-ui/react-env@2.0.11": + version "2.0.11" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-env/-/react-env-2.0.11.tgz#d9d65fb695de7aff15e1d0e97d57bb7bedce5fa2" + integrity sha512-rPwUHReSWh7rbCw0HePa8Pvc+Q82fUFvVjHTIbXKnE6d+01cCE7j4f1NLeRD9pStKPI6sIZm9xTGvOCzl8F8iw== + +"@chakra-ui/react-types@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-types/-/react-types-2.0.5.tgz#1e4c99ef0e59b5fe9263d0e186cd66afdfb6c87b" + integrity sha512-GApp+R/VjS1UV5ms5irrij5LOIgUM0dqSVHagyEFEz88LRKkqMD9RuO577ZsVd4Gn0ULsacVJCUA0HtNUBJNzA== -"@chakra-ui/provider@2.0.6": +"@chakra-ui/react-use-animation-state@2.0.6": version "2.0.6" - resolved "https://registry.yarnpkg.com/@chakra-ui/provider/-/provider-2.0.6.tgz#cf018e2c45797e68a1d262f5ff70c7bef5f103d7" - integrity sha512-EwwFF8ib9L5OYTRJq450Uvk7DqQJA/W6TyBo2f7mUE0j56GmV8ZRdsaXGqqag/aopCS/1n+ZfpQvQr/qNhAQBQ== + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-animation-state/-/react-use-animation-state-2.0.6.tgz#2a324d3c67015a542ed589f899672d681889e1e7" + integrity sha512-M2kUzZkSBgDpfvnffh3kTsMIM3Dvn+CTMqy9zfY97NL4P3LAWL1MuFtKdlKfQ8hs/QpwS/ew8CTmCtaywn4sKg== dependencies: - "@chakra-ui/css-reset" "2.0.1" - "@chakra-ui/portal" "2.0.2" - "@chakra-ui/react-env" "2.0.2" - "@chakra-ui/system" "2.1.3" - "@chakra-ui/utils" "2.0.2" + "@chakra-ui/dom-utils" "2.0.4" + "@chakra-ui/react-use-event-listener" "2.0.5" -"@chakra-ui/radio@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/radio/-/radio-2.0.2.tgz#810b30204d04cc6fb54079394484a654d56f39e1" - integrity sha512-f3YF7sL13qpbiqlFF8eGcL8lZeAmY3ZwqJk8m2v3Ofi0M7Et/CV00E1TxY5kK3tvDtmMXC5lILf5QlHHNgH6wQ== +"@chakra-ui/react-use-callback-ref@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-callback-ref/-/react-use-callback-ref-2.0.5.tgz#862430dfbab8e1f0b8e04476e5e25469bd044ec9" + integrity sha512-vKnXleD2PzB0nGabY35fRtklMid4z7cecbMG0fkasNNsgWmrQcXJOuEKUUVCynL6FBU6gBnpKFi5Aqj6x+K4tw== + +"@chakra-ui/react-use-controllable-state@2.0.6": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-controllable-state/-/react-use-controllable-state-2.0.6.tgz#ec62aff9b9c00324a0a4c9a4523824a9ad5ef9aa" + integrity sha512-7WuKrhQkpSRoiI5PKBvuIsO46IIP0wsRQgXtStSaIXv+FIvIJl9cxQXTbmZ5q1Ds641QdAUKx4+6v0K/zoZEHg== dependencies: - "@chakra-ui/form-control" "2.0.2" - "@chakra-ui/hooks" "2.0.2" - "@chakra-ui/react-utils" "2.0.1" - "@chakra-ui/utils" "2.0.2" - "@chakra-ui/visually-hidden" "2.0.2" + "@chakra-ui/react-use-callback-ref" "2.0.5" -"@chakra-ui/react-env@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-env/-/react-env-2.0.2.tgz#fada8d098c5de95562a8b723e24cbebc6e3018da" - integrity sha512-iQdc58d1HjfkPi+CEoZNqY77oX94bsWpMie30UYIaTonc9OOH6r1WCGQc8cyQa3jKiX2m9v9IbnxZa9Z0rYrHw== +"@chakra-ui/react-use-disclosure@2.0.6": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-disclosure/-/react-use-disclosure-2.0.6.tgz#db707ee119db829e9b21ff1c05e867938f1e27ba" + integrity sha512-4UPePL+OcCY37KZ585iLjg8i6J0sjpLm7iZG3PUwmb97oKHVHq6DpmWIM0VfSjcT6AbSqyGcd5BXZQBgwt8HWQ== dependencies: - "@chakra-ui/utils" "2.0.2" + "@chakra-ui/react-use-callback-ref" "2.0.5" -"@chakra-ui/react-utils@2.0.1", "@chakra-ui/react-utils@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-utils/-/react-utils-2.0.1.tgz#aebf12ee9f71fb7a27183d556131177f9ce745c8" - integrity sha512-xLiTn7WeUo2e3zvo8zUGpICgIGsLCPpkVbjEKhr1jAV41urqEtwlLc6uGir595OYqAC8zFDqs4HXhHouqNEtiw== +"@chakra-ui/react-use-event-listener@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-event-listener/-/react-use-event-listener-2.0.5.tgz#949aa99878b25b23709452d3c80a1570c99747cc" + integrity sha512-etLBphMigxy/cm7Yg22y29gQ8u/K3PniR5ADZX7WVX61Cgsa8ciCqjTE9sTtlJQWAQySbWxt9+mjlT5zaf+6Zw== dependencies: - "@chakra-ui/utils" "^2.0.2" + "@chakra-ui/react-use-callback-ref" "2.0.5" -"@chakra-ui/react@^2.2.0": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/react/-/react-2.2.1.tgz#606a112350145e1bbd722db970dac7114a973d88" - integrity sha512-m2vFICTUO3GivTkJROnTTJT+w8otcYMraKqOSdrAGmsjqtZAp8/FaGS+1bxzeZnZTszMn65LoLvlgBUDrTHhQA== - dependencies: - "@chakra-ui/accordion" "2.0.3" - "@chakra-ui/alert" "2.0.2" - "@chakra-ui/avatar" "2.0.3" - "@chakra-ui/breadcrumb" "2.0.2" - "@chakra-ui/button" "2.0.2" - "@chakra-ui/checkbox" "2.1.0" - "@chakra-ui/close-button" "2.0.2" - "@chakra-ui/control-box" "2.0.2" - "@chakra-ui/counter" "2.0.2" - "@chakra-ui/css-reset" "2.0.1" - "@chakra-ui/editable" "2.0.2" - "@chakra-ui/form-control" "2.0.2" - "@chakra-ui/hooks" "2.0.2" - "@chakra-ui/icon" "3.0.2" - "@chakra-ui/image" "2.0.3" - "@chakra-ui/input" "2.0.2" - "@chakra-ui/layout" "2.0.2" - "@chakra-ui/live-region" "2.0.2" - "@chakra-ui/media-query" "3.1.0" - "@chakra-ui/menu" "2.0.3" - "@chakra-ui/modal" "2.0.3" - "@chakra-ui/number-input" "2.0.2" - "@chakra-ui/pin-input" "2.0.3" - "@chakra-ui/popover" "2.0.2" - "@chakra-ui/popper" "3.0.2" - "@chakra-ui/portal" "2.0.2" - "@chakra-ui/progress" "2.0.2" - "@chakra-ui/provider" "2.0.6" - "@chakra-ui/radio" "2.0.2" - "@chakra-ui/react-env" "2.0.2" - "@chakra-ui/select" "2.0.2" - "@chakra-ui/skeleton" "2.0.6" - "@chakra-ui/slider" "2.0.2" - "@chakra-ui/spinner" "2.0.2" - "@chakra-ui/stat" "2.0.2" - "@chakra-ui/switch" "2.0.3" - "@chakra-ui/system" "2.1.3" - "@chakra-ui/table" "2.0.2" - "@chakra-ui/tabs" "2.0.3" - "@chakra-ui/tag" "2.0.2" - "@chakra-ui/textarea" "2.0.3" - "@chakra-ui/theme" "2.1.0" - "@chakra-ui/toast" "2.1.0" - "@chakra-ui/tooltip" "2.0.2" - "@chakra-ui/transition" "2.0.2" - "@chakra-ui/utils" "2.0.2" - "@chakra-ui/visually-hidden" "2.0.2" - -"@chakra-ui/select@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/select/-/select-2.0.2.tgz#35f7fa0d4422f9a49b6577c2259b71e6d1ad9603" - integrity sha512-aXYRJFsi3xrcacPI+FDZ1fxRQc9PMFnYXvqTug4I7wIwZUE467vD4G90c6/b/tUzrerDkVcPhHbqFy8ENbrvdA== +"@chakra-ui/react-use-focus-effect@2.0.7": + version "2.0.7" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-focus-effect/-/react-use-focus-effect-2.0.7.tgz#bd03290cac32e0de6a71ce987f939a5e697bca04" + integrity sha512-wI8OUNwfbkusajLac8QtjfSyNmsNu1D5pANmnSHIntHhui6Jwv75Pxx7RgmBEnfBEpleBndhR9E75iCjPLhZ/A== dependencies: - "@chakra-ui/form-control" "2.0.2" - "@chakra-ui/utils" "2.0.2" + "@chakra-ui/dom-utils" "2.0.4" + "@chakra-ui/react-use-event-listener" "2.0.5" + "@chakra-ui/react-use-safe-layout-effect" "2.0.3" + "@chakra-ui/react-use-update-effect" "2.0.5" -"@chakra-ui/skeleton@2.0.6": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@chakra-ui/skeleton/-/skeleton-2.0.6.tgz#0700f118d31782b2a0f8764b3a22ed3d722f33c8" - integrity sha512-nbZEfA7vSxJ8qXM0sb+e/Dh8t2ZcAkjWUzScMvO8FWfblk3wkoeUT0ocTwJ4eDyTzEVBu+ym7Uc+ACZmBheabQ== +"@chakra-ui/react-use-focus-on-pointer-down@2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-focus-on-pointer-down/-/react-use-focus-on-pointer-down-2.0.4.tgz#aeba543c451ac1b0138093234e71d334044daf84" + integrity sha512-L3YKouIi77QbXH9mSLGEFzJbJDhyrPlcRcuu+TSC7mYaK9E+3Ap+RVSAVxj+CfQz7hCWpikPecKDuspIPWlyuA== dependencies: - "@chakra-ui/hooks" "2.0.2" - "@chakra-ui/media-query" "3.1.0" - "@chakra-ui/system" "2.1.3" - "@chakra-ui/utils" "2.0.2" + "@chakra-ui/react-use-event-listener" "2.0.5" -"@chakra-ui/slider@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/slider/-/slider-2.0.2.tgz#e772721d350523a2dbfba188383b2b66d7e67ac3" - integrity sha512-aWpjqFGN61fv3dKyBrP6c68MXmkYtZ6jeDWIKkgzc7ntb6Nnf6KDK8seZM0SmQR2F3GIejLt8AgnuIW/UBUa/Q== +"@chakra-ui/react-use-interval@2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-interval/-/react-use-interval-2.0.3.tgz#d5c7bce117fb25edb54e3e2c666e900618bb5bb2" + integrity sha512-Orbij5c5QkL4NuFyU4mfY/nyRckNBgoGe9ic8574VVNJIXfassevZk0WB+lvqBn5XZeLf2Tj+OGJrg4j4H9wzw== dependencies: - "@chakra-ui/hooks" "2.0.2" - "@chakra-ui/react-utils" "2.0.1" - "@chakra-ui/utils" "2.0.2" + "@chakra-ui/react-use-callback-ref" "2.0.5" -"@chakra-ui/spinner@2.0.2", "@chakra-ui/spinner@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/spinner/-/spinner-2.0.2.tgz#4dc529bac5208e28a64e9fbde9d3f40b62cce629" - integrity sha512-jC6+pwkCQb5vfGsS/55EhH2UzsToeCvpfXLQ6TPWDPA2NHMTRskilHwKQT/i0nAgRcCq400FvcfIr5uAPs+Igg== +"@chakra-ui/react-use-latest-ref@2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-latest-ref/-/react-use-latest-ref-2.0.3.tgz#27cf703858e65ecb5a0eef26215c794ad2a5353d" + integrity sha512-exNSQD4rPclDSmNwtcChUCJ4NuC2UJ4amyNGBqwSjyaK5jNHk2kkM7rZ6I0I8ul+26lvrXlSuhyv6c2PFwbFQQ== + +"@chakra-ui/react-use-merge-refs@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-merge-refs/-/react-use-merge-refs-2.0.5.tgz#13181e1a43219c6a04a01f84de0188df042ee92e" + integrity sha512-uc+MozBZ8asaUpO8SWcK6D4svRPACN63jv5uosUkXJR+05jQJkUofkfQbf2HeGVbrWCr0XZsftLIm4Mt/QMoVw== + +"@chakra-ui/react-use-outside-click@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-outside-click/-/react-use-outside-click-2.0.5.tgz#6a9896d2c2d35f3c301c3bb62bed1bf5290d1e60" + integrity sha512-WmtXUeVaMtxP9aUGGG+GQaDeUn/Bvf8TI3EU5mE1+TtqLHxyA9wtvQurynrogvpilLaBADwn/JeBeqs2wHpvqA== dependencies: - "@chakra-ui/utils" "2.0.2" - "@chakra-ui/visually-hidden" "2.0.2" + "@chakra-ui/react-use-callback-ref" "2.0.5" -"@chakra-ui/stat@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/stat/-/stat-2.0.2.tgz#8e211270d31bab8d64209f737cde23c50b5fe98b" - integrity sha512-GrQgiof8olOEVFAUtq5GA2cCUJqcSLMpS/6StBFR4fesrg5MAblfVYYY7uayqX/RnJU1BNElLOl/JAQ965LGXw== +"@chakra-ui/react-use-pan-event@2.0.6": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-pan-event/-/react-use-pan-event-2.0.6.tgz#e489d61672e6f473b7fd362d816e2e27ed3b2af6" + integrity sha512-Vtgl3c+Mj4hdehFRFIgruQVXctwnG1590Ein1FiU8sVnlqO6bpug6Z+B14xBa+F+X0aK+DxnhkJFyWI93Pks2g== dependencies: - "@chakra-ui/icon" "3.0.2" - "@chakra-ui/utils" "2.0.2" - "@chakra-ui/visually-hidden" "2.0.2" + "@chakra-ui/event-utils" "2.0.6" + "@chakra-ui/react-use-latest-ref" "2.0.3" + framesync "5.3.0" -"@chakra-ui/styled-system@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/styled-system/-/styled-system-2.2.0.tgz#d7fdca558db05100ea26ae8352b13c5840da9cc3" - integrity sha512-5THQlrMr6CsiulNtjzZV3DqYD85eQ+S8G6rsnjAKqFVJ1G29R392RKK/67R96WIRUJRtsHPq2REeTgAxGLDhOQ== +"@chakra-ui/react-use-previous@2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-previous/-/react-use-previous-2.0.3.tgz#9da3d53fd75f1c3da902bd6af71dcb1a7be37f31" + integrity sha512-A2ODOa0rm2HM4aqXfxxI0zPLcn5Q7iBEjRyfIQhb+EH+d2OFuj3L2slVoIpp6e/km3Xzv2d+u/WbjgTzdQ3d0w== + +"@chakra-ui/react-use-safe-layout-effect@2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-safe-layout-effect/-/react-use-safe-layout-effect-2.0.3.tgz#bf63ac8c94460aa1b20b6b601a0ea873556ffb1b" + integrity sha512-dlTvQURzmdfyBbNdydgO4Wy2/HV8aJN8LszTtyb5vRZsyaslDM/ftcxo8E8QjHwRLD/V1Epb/A8731QfimfVaQ== + +"@chakra-ui/react-use-size@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-size/-/react-use-size-2.0.5.tgz#4bbffb64f97dcfe1d7edeb0f03bb1d5fbc48df64" + integrity sha512-4arAApdiXk5uv5ZeFKltEUCs5h3yD9dp6gTIaXbAdq+/ENK3jMWTwlqzNbJtCyhwoOFrblLSdBrssBMIsNQfZQ== dependencies: - "@chakra-ui/utils" "2.0.2" - csstype "^3.0.11" + "@zag-js/element-size" "0.1.0" -"@chakra-ui/switch@2.0.3": +"@chakra-ui/react-use-timeout@2.0.3": version "2.0.3" - resolved "https://registry.yarnpkg.com/@chakra-ui/switch/-/switch-2.0.3.tgz#363e828af5ed9ad39458f7258a33d8af0e4cf7c0" - integrity sha512-k7HLnKBM9GsY/RdqUWqe233QNFa2JtE+G4UyX8BsYLquWOkBfgJvI+f2gSUye1zLS8e1bFwz5BBIljTQMb/Smw== + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-timeout/-/react-use-timeout-2.0.3.tgz#16ca397dbca55a64811575884cb81a348d86d4e2" + integrity sha512-rBBUkZSQq3nJQ8fuMkgZNY2Sgg4vKiKNp05GxAwlT7TitOfVZyoTriqQpqz296bWlmkICTZxlqCWfE5fWpsTsg== dependencies: - "@chakra-ui/checkbox" "2.1.0" - "@chakra-ui/utils" "2.0.2" + "@chakra-ui/react-use-callback-ref" "2.0.5" -"@chakra-ui/system@2.1.3": - version "2.1.3" - resolved "https://registry.yarnpkg.com/@chakra-ui/system/-/system-2.1.3.tgz#a140335f56087f761d0a8cef6e4c77f971f054da" - integrity sha512-f9GfJr7HGxxhyAbXmka/k/mPsLl8wl+5fZUWglfRg4iddmsuYQcJEYg8+ewCyr7MA1Ddw9bPVgsC5uf/KYlo3w== +"@chakra-ui/react-use-update-effect@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-update-effect/-/react-use-update-effect-2.0.5.tgz#aede8f13f2b3de254b4ffa3b8cec1b70bd2876c5" + integrity sha512-y9tCMr1yuDl8ATYdh64Gv8kge5xE1DMykqPDZw++OoBsTaWr3rx40wblA8NIWuSyJe5ErtKP2OeglvJkYhryJQ== + +"@chakra-ui/react-utils@2.0.9": + version "2.0.9" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-utils/-/react-utils-2.0.9.tgz#5cdf0bc8dee57c15f15ace04fbba574ec8aa6ecc" + integrity sha512-nlwPBVlQmcl1PiLzZWyrT3FSnt3vKSkBMzQ0EF4SJWA/nOIqTvmffb5DCzCqPzgQaE/Da1Xgus+JufFGM8GLCQ== dependencies: - "@chakra-ui/color-mode" "2.0.4" - "@chakra-ui/react-utils" "2.0.1" - "@chakra-ui/styled-system" "2.2.0" - "@chakra-ui/utils" "2.0.2" - react-fast-compare "3.2.0" + "@chakra-ui/utils" "2.0.12" -"@chakra-ui/table@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/table/-/table-2.0.2.tgz#328b61abe3209a8ed215031cfea8a92c885400a5" - integrity sha512-VkcXAmvNlhWXZ5qPUAVqW4DKARSNdCN4Ib8ViiX8lXqBUHK+IBAe2s6iB70FwzdaPqwrw2LndqRrLg/4w4FE3w== +"@chakra-ui/react@2.4.2": + version "2.4.2" + resolved "https://registry.yarnpkg.com/@chakra-ui/react/-/react-2.4.2.tgz#60d0cf80965d77ab6e280e28124b800a0d7a5f8c" + integrity sha512-lPDCCuY3S7XSeIK+P+ypGIL+lFqEZQt8H3Iyq4coblULMsj8skdSUqaoQ4I9fGgOi1koTPe4OlXb+rmqwQQ9MQ== + dependencies: + "@chakra-ui/accordion" "2.1.4" + "@chakra-ui/alert" "2.0.13" + "@chakra-ui/avatar" "2.2.1" + "@chakra-ui/breadcrumb" "2.1.1" + "@chakra-ui/button" "2.0.13" + "@chakra-ui/card" "2.1.1" + "@chakra-ui/checkbox" "2.2.5" + "@chakra-ui/close-button" "2.0.13" + "@chakra-ui/control-box" "2.0.11" + "@chakra-ui/counter" "2.0.11" + "@chakra-ui/css-reset" "2.0.10" + "@chakra-ui/editable" "2.0.16" + "@chakra-ui/form-control" "2.0.13" + "@chakra-ui/hooks" "2.1.2" + "@chakra-ui/icon" "3.0.13" + "@chakra-ui/image" "2.0.12" + "@chakra-ui/input" "2.0.14" + "@chakra-ui/layout" "2.1.11" + "@chakra-ui/live-region" "2.0.11" + "@chakra-ui/media-query" "3.2.8" + "@chakra-ui/menu" "2.1.5" + "@chakra-ui/modal" "2.2.4" + "@chakra-ui/number-input" "2.0.14" + "@chakra-ui/pin-input" "2.0.16" + "@chakra-ui/popover" "2.1.4" + "@chakra-ui/popper" "3.0.10" + "@chakra-ui/portal" "2.0.11" + "@chakra-ui/progress" "2.1.1" + "@chakra-ui/provider" "2.0.24" + "@chakra-ui/radio" "2.0.14" + "@chakra-ui/react-env" "2.0.11" + "@chakra-ui/select" "2.0.14" + "@chakra-ui/skeleton" "2.0.18" + "@chakra-ui/slider" "2.0.14" + "@chakra-ui/spinner" "2.0.11" + "@chakra-ui/stat" "2.0.13" + "@chakra-ui/styled-system" "2.4.0" + "@chakra-ui/switch" "2.0.17" + "@chakra-ui/system" "2.3.4" + "@chakra-ui/table" "2.0.12" + "@chakra-ui/tabs" "2.1.5" + "@chakra-ui/tag" "2.0.13" + "@chakra-ui/textarea" "2.0.14" + "@chakra-ui/theme" "2.2.2" + "@chakra-ui/theme-utils" "2.0.5" + "@chakra-ui/toast" "4.0.4" + "@chakra-ui/tooltip" "2.2.2" + "@chakra-ui/transition" "2.0.12" + "@chakra-ui/utils" "2.0.12" + "@chakra-ui/visually-hidden" "2.0.13" + +"@chakra-ui/select@2.0.14": + version "2.0.14" + resolved "https://registry.yarnpkg.com/@chakra-ui/select/-/select-2.0.14.tgz#b2230702e31d2b9b4cc7848b18ba7ae8e4c89bdb" + integrity sha512-fvVGxAtLaIXGOMicrzSa6imMw5h26S1ar3xyNmXgR40dbpTPHmtQJkbHBf9FwwQXgSgKWgBzsztw5iDHCpPVzA== dependencies: - "@chakra-ui/utils" "2.0.2" + "@chakra-ui/form-control" "2.0.13" -"@chakra-ui/tabs@2.0.3": +"@chakra-ui/shared-utils@2.0.3": version "2.0.3" - resolved "https://registry.yarnpkg.com/@chakra-ui/tabs/-/tabs-2.0.3.tgz#678a1814384c949a1b8bf725c21f2e840060f9e5" - integrity sha512-iBi7hSiNv7y9Zu0eR0b4SCBdKoY/5aOKhToZIm0iv5qJPunN3ap3zVAHL36ucPAIv19rC0GaOwqLsNQErMkMYQ== + resolved "https://registry.yarnpkg.com/@chakra-ui/shared-utils/-/shared-utils-2.0.3.tgz#97cbc11282e381ebd9f581c603088f9d60ead451" + integrity sha512-pCU+SUGdXzjAuUiUT8mriekL3tJVfNdwSTIaNeip7k/SWDzivrKGMwAFBxd3XVTDevtVusndkO4GJuQ3yILzDg== + +"@chakra-ui/skeleton@2.0.18": + version "2.0.18" + resolved "https://registry.yarnpkg.com/@chakra-ui/skeleton/-/skeleton-2.0.18.tgz#a2af241f0b1b692db4d10b90a887107a5e401c7d" + integrity sha512-qjcD8BgVx4kL8Lmb8EvmmDGM2ICl6CqhVE2LShJrgG7PDM6Rt6rYM617kqLurLYZjbJUiwgf9VXWifS0IpT31Q== dependencies: - "@chakra-ui/clickable" "2.0.2" - "@chakra-ui/descendant" "3.0.2" - "@chakra-ui/hooks" "2.0.2" - "@chakra-ui/react-utils" "2.0.1" - "@chakra-ui/utils" "2.0.2" + "@chakra-ui/media-query" "3.2.8" + "@chakra-ui/react-use-previous" "2.0.3" -"@chakra-ui/tag@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/tag/-/tag-2.0.2.tgz#d989d1e64ed89f92447ca4f2316506282d16518f" - integrity sha512-/TqjwPNTUjDofvTEulrNELS6/ls1n54YMFXMwGNwrEbNlJPgoE555t1N3jpdoNKH4kLhvkFcC6lfkDdWwnZ1BA== +"@chakra-ui/slider@2.0.14": + version "2.0.14" + resolved "https://registry.yarnpkg.com/@chakra-ui/slider/-/slider-2.0.14.tgz#8fa8fb5df292525d8b97ea3c3c666e400fb365f2" + integrity sha512-z4Q5rWtYVTdFgBVvR6aUhSMg3CQuAgjJGHvLHEGDCUjYCuBXrb3SmWyvv03uKyjSbwRyKqSsvAnSCxtmHODt/w== + dependencies: + "@chakra-ui/number-utils" "2.0.5" + "@chakra-ui/react-context" "2.0.5" + "@chakra-ui/react-types" "2.0.5" + "@chakra-ui/react-use-callback-ref" "2.0.5" + "@chakra-ui/react-use-controllable-state" "2.0.6" + "@chakra-ui/react-use-latest-ref" "2.0.3" + "@chakra-ui/react-use-merge-refs" "2.0.5" + "@chakra-ui/react-use-pan-event" "2.0.6" + "@chakra-ui/react-use-size" "2.0.5" + "@chakra-ui/react-use-update-effect" "2.0.5" + +"@chakra-ui/spinner@2.0.11": + version "2.0.11" + resolved "https://registry.yarnpkg.com/@chakra-ui/spinner/-/spinner-2.0.11.tgz#a5dd76b6cb0f3524d9b90b73fa4acfb6adc69f33" + integrity sha512-piO2ghWdJzQy/+89mDza7xLhPnW7pA+ADNbgCb1vmriInWedS41IBKe+pSPz4IidjCbFu7xwKE0AerFIbrocCA== + +"@chakra-ui/stat@2.0.13": + version "2.0.13" + resolved "https://registry.yarnpkg.com/@chakra-ui/stat/-/stat-2.0.13.tgz#1805817ab54f9d9b663b465fcb255285d22d0152" + integrity sha512-6XeuE/7w0BjyCHSxMbsf6/rNOOs8BSit1NS7g7+Jd/40Pc/SKlNWLd3kxXPid4eT3RwyNIdMPtm30OActr9nqQ== + dependencies: + "@chakra-ui/icon" "3.0.13" + "@chakra-ui/react-context" "2.0.5" + +"@chakra-ui/styled-system@2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@chakra-ui/styled-system/-/styled-system-2.4.0.tgz#4b50079606331e4e8fda7ea59da9db51b446d40c" + integrity sha512-G4HpbFERq4C1cBwKNDNkpCiliOICLXjYwKI/e/6hxNY+GlPxt8BCzz3uhd3vmEoG2vRM4qjidlVjphhWsf6vRQ== dependencies: - "@chakra-ui/icon" "3.0.2" - "@chakra-ui/utils" "2.0.2" + csstype "^3.0.11" + lodash.mergewith "4.6.2" -"@chakra-ui/textarea@2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@chakra-ui/textarea/-/textarea-2.0.3.tgz#0629fbdb1f9af6721edae07b5098e3fc4d1af44c" - integrity sha512-esOJa0vSrSsgDJGjPAbnPNPvemN1QUKYFYLFTOM/LR6BzI21EL8PX4Bh3AJM6aJK0GjeR0+SeKMuuuLL4oFnmw== +"@chakra-ui/switch@2.0.17": + version "2.0.17" + resolved "https://registry.yarnpkg.com/@chakra-ui/switch/-/switch-2.0.17.tgz#1d6904b6cde2469212bbd8311b749b96c653a9a3" + integrity sha512-BQabfC6qYi5xBJvEFPzKq0yl6fTtTNNEHTid5r7h0PWcCnAiHwQJTpQRpxp+AjK569LMLtTXReTZvNBrzEwOrA== dependencies: - "@chakra-ui/form-control" "2.0.2" - "@chakra-ui/utils" "2.0.2" + "@chakra-ui/checkbox" "2.2.5" -"@chakra-ui/theme-tools@2.0.2", "@chakra-ui/theme-tools@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/theme-tools/-/theme-tools-2.0.2.tgz#2f59f14f553dcb5ccc8e8492cb9524954fe1bf89" - integrity sha512-E01ZJZB4XVqkvn2hOXKQ/uVkvaPLQN1SyxAYXjFZGyZ1ppBLl362EWfY9IgWNzDITgq9MCJyQFfm2mXwQDUNzA== +"@chakra-ui/system@2.3.4": + version "2.3.4" + resolved "https://registry.yarnpkg.com/@chakra-ui/system/-/system-2.3.4.tgz#425bf7eebf61bd92aa68f60a6b62c380274fbe4e" + integrity sha512-/2m8hFfFzOMO2OlwHxTWqINOBJMjxWwU5V/AcB7C0qS51Dcj9c7kupilM6QdqiOLLdMS7mIVRSYr8jn8gMw9fA== + dependencies: + "@chakra-ui/color-mode" "2.1.10" + "@chakra-ui/react-utils" "2.0.9" + "@chakra-ui/styled-system" "2.4.0" + "@chakra-ui/theme-utils" "2.0.5" + "@chakra-ui/utils" "2.0.12" + react-fast-compare "3.2.0" + +"@chakra-ui/table@2.0.12": + version "2.0.12" + resolved "https://registry.yarnpkg.com/@chakra-ui/table/-/table-2.0.12.tgz#387653cf660318b13086b6497aca2b671deb055a" + integrity sha512-TSxzpfrOoB+9LTdNTMnaQC6OTsp36TlCRxJ1+1nAiCmlk+m+FiNzTQsmBalDDhc29rm+6AdRsxSPsjGWB8YVwg== dependencies: - "@chakra-ui/utils" "2.0.2" - "@ctrl/tinycolor" "^3.4.0" + "@chakra-ui/react-context" "2.0.5" -"@chakra-ui/theme@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/theme/-/theme-2.1.0.tgz#2a71da8c7f4c191e3711ef6139cec398a4fd7ad4" - integrity sha512-OHvKCQ/QUHc3ZVgKKshYkvholiDhPf7vEPZcNOi5rnaFSP4PzWd00d1i7HOXYSyv/TGDOBRzs1IcodKfG6FzgA== +"@chakra-ui/tabs@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@chakra-ui/tabs/-/tabs-2.1.5.tgz#827b0e71eb173c09c31dcbbe05fc1146f4267229" + integrity sha512-XmnKDclAJe0FoW4tdC8AlnZpPN5fcj92l4r2sqiL9WyYVEM71hDxZueETIph/GTtfMelG7Z8e5vBHP4rh1RT5g== + dependencies: + "@chakra-ui/clickable" "2.0.11" + "@chakra-ui/descendant" "3.0.11" + "@chakra-ui/lazy-utils" "2.0.3" + "@chakra-ui/react-children-utils" "2.0.4" + "@chakra-ui/react-context" "2.0.5" + "@chakra-ui/react-use-controllable-state" "2.0.6" + "@chakra-ui/react-use-merge-refs" "2.0.5" + "@chakra-ui/react-use-safe-layout-effect" "2.0.3" + +"@chakra-ui/tag@2.0.13": + version "2.0.13" + resolved "https://registry.yarnpkg.com/@chakra-ui/tag/-/tag-2.0.13.tgz#ad7349bfcdd5642d3894fadb43728acc0f061101" + integrity sha512-W1urf+tvGMt6J3cc31HudybYSl+B5jYUP5DJxzXM9p+n3JrvXWAo4D6LmpLBHY5zT2mNne14JF1rVeRcG4Rtdg== + dependencies: + "@chakra-ui/icon" "3.0.13" + "@chakra-ui/react-context" "2.0.5" + +"@chakra-ui/textarea@2.0.14": + version "2.0.14" + resolved "https://registry.yarnpkg.com/@chakra-ui/textarea/-/textarea-2.0.14.tgz#a79a3fdd850a3303e6ebb68d64b7c334de03da4d" + integrity sha512-r8hF1rCi+GseLtY/IGeVWXFN0Uve2b820UQumRj4qxj7PsPqw1hFg7Cecbbb9zwF38K/m+D3IdwFeJzI1MtgRA== dependencies: - "@chakra-ui/anatomy" "2.0.1" - "@chakra-ui/theme-tools" "2.0.2" - "@chakra-ui/utils" "2.0.2" + "@chakra-ui/form-control" "2.0.13" -"@chakra-ui/toast@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/toast/-/toast-2.1.0.tgz#8e0c8ea20493f17b541bf964b2c64e114acce4ec" - integrity sha512-xXgwzff/gtNrq2HGGG3fuqcfRQEIObluHzHhqgS3gesf8KYut/5ZJoLdgV4RKE+NYgJIi77BFUcQDiLJttxxPA== - dependencies: - "@chakra-ui/alert" "2.0.2" - "@chakra-ui/close-button" "2.0.2" - "@chakra-ui/hooks" "2.0.2" - "@chakra-ui/portal" "2.0.2" - "@chakra-ui/react-utils" "2.0.1" - "@chakra-ui/system" "2.1.3" - "@chakra-ui/theme" "2.1.0" - "@chakra-ui/transition" "2.0.2" - "@chakra-ui/utils" "2.0.2" - -"@chakra-ui/tooltip@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/tooltip/-/tooltip-2.0.2.tgz#ac3993aea85abce94b882bebc20e23af57498c80" - integrity sha512-oK6gXybFe/MmHBXbd9w3XgNChVHQ9BeLW0IAtFeDyeHn5gJg0iKul/SNmJkD73Iyv/j+BsmBMn98mbNYQkeMQA== +"@chakra-ui/theme-tools@2.0.14": + version "2.0.14" + resolved "https://registry.yarnpkg.com/@chakra-ui/theme-tools/-/theme-tools-2.0.14.tgz#6c523284ab384ca57a3aef1fcfa7c32ed357fbde" + integrity sha512-lVcDmq5pyU0QbsIFKjt/iVUFDap7di2QHvPvGChA1YSjtg1PtuUi+BxEXWzp3Nfgw/N4rMvlBs+S0ynJypdwbg== dependencies: - "@chakra-ui/hooks" "2.0.2" - "@chakra-ui/popper" "3.0.2" - "@chakra-ui/portal" "2.0.2" - "@chakra-ui/react-utils" "2.0.1" - "@chakra-ui/utils" "2.0.2" - "@chakra-ui/visually-hidden" "2.0.2" + "@chakra-ui/anatomy" "2.1.0" + color2k "^2.0.0" -"@chakra-ui/transition@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/transition/-/transition-2.0.2.tgz#f2713814990d31cbe2a647d3baa09f32646c9810" - integrity sha512-s98gDFIGbv60WMyniVjy381NXxgS1Y/6RACR1Z1pReC5XZLY5GyMqeRYyFCAeE78qKkqon77Y8EDPQXl6X78dw== +"@chakra-ui/theme-utils@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@chakra-ui/theme-utils/-/theme-utils-2.0.5.tgz#ad1e53fc7f71326d15b9b01a157c7e2a029f3dda" + integrity sha512-QQowSM8fvQlTmT0w9wtqUlWOB4i+9eA7P4XRm4bfhBMZ7XpK4ctV95sPeGqaXVccsz5m0q1AuGWa+j6eMCbrrg== dependencies: - "@chakra-ui/utils" "2.0.2" + "@chakra-ui/styled-system" "2.4.0" + "@chakra-ui/theme" "2.2.2" + lodash.mergewith "4.6.2" -"@chakra-ui/utils@2.0.2", "@chakra-ui/utils@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/utils/-/utils-2.0.2.tgz#130ba1647ea2b94ad956ae4cbcf685838d350593" - integrity sha512-9AC/ir9zm0shgFG7kdzOKUH2Wx5VB71M3uRMEsMZf75YlhhiU7AvBNtWXnJu+CBiTi41rKa5A+2ImMOsuPfGbA== +"@chakra-ui/theme@2.2.2": + version "2.2.2" + resolved "https://registry.yarnpkg.com/@chakra-ui/theme/-/theme-2.2.2.tgz#5ea69adde78ee6ea59f9dce674947ed8be2ebc62" + integrity sha512-7DlOQiXmnaqYyqXwqmfFSCWGkUonuqmNC5mmUCwxI435KgHNCaE2bIm6DI7N2NcIcuVcfc8Vn0UqrDoGU3zJBg== + dependencies: + "@chakra-ui/anatomy" "2.1.0" + "@chakra-ui/theme-tools" "2.0.14" + +"@chakra-ui/toast@4.0.4": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@chakra-ui/toast/-/toast-4.0.4.tgz#254fb5c4c5bde0a373aab574927c654442fb0411" + integrity sha512-Gv52UQ4fJtziL9Qg0Yterb76C1GgzViryPDf2dxSzTlnCcKIbY4ktEhehyFBjDXYoGkFb47NZUEyhy+u8p3GUA== + dependencies: + "@chakra-ui/alert" "2.0.13" + "@chakra-ui/close-button" "2.0.13" + "@chakra-ui/portal" "2.0.11" + "@chakra-ui/react-use-timeout" "2.0.3" + "@chakra-ui/react-use-update-effect" "2.0.5" + "@chakra-ui/styled-system" "2.4.0" + "@chakra-ui/theme" "2.2.2" + +"@chakra-ui/tooltip@2.2.2": + version "2.2.2" + resolved "https://registry.yarnpkg.com/@chakra-ui/tooltip/-/tooltip-2.2.2.tgz#8ac0759fbc5adacec6e0ac7419c8055a67a95b5c" + integrity sha512-WDgQVEMHdsyUpKG9Nogy2FKLBgfdJG7hTSrSbH1WLvHsPkpPLknL4i5Z/pCvpa4A7SzTa6ps350mxtJ054MeMg== + dependencies: + "@chakra-ui/popper" "3.0.10" + "@chakra-ui/portal" "2.0.11" + "@chakra-ui/react-types" "2.0.5" + "@chakra-ui/react-use-disclosure" "2.0.6" + "@chakra-ui/react-use-event-listener" "2.0.5" + "@chakra-ui/react-use-merge-refs" "2.0.5" + +"@chakra-ui/transition@2.0.12": + version "2.0.12" + resolved "https://registry.yarnpkg.com/@chakra-ui/transition/-/transition-2.0.12.tgz#876c6ed24e442a720a8570490a93cb1f87008700" + integrity sha512-ff6eU+m08ccYfCkk0hKfY/XlmGxCrfbBgsKgV4mirZ4SKUL1GVye8CYuHwWQlBJo+8s0yIpsTNxAuX4n/cW9/w== + +"@chakra-ui/utils@2.0.12": + version "2.0.12" + resolved "https://registry.yarnpkg.com/@chakra-ui/utils/-/utils-2.0.12.tgz#5ab8a4529fca68d9f8c6722004f6a5129b0b75e9" + integrity sha512-1Z1MgsrfMQhNejSdrPJk8v5J4gCefHo+1wBmPPHTz5bGEbAAbZ13aXAfXy8w0eFy0Nvnawn0EHW7Oynp/MdH+Q== dependencies: "@types/lodash.mergewith" "4.6.6" css-box-model "1.2.1" framesync "5.3.0" lodash.mergewith "4.6.2" -"@chakra-ui/visually-hidden@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/visually-hidden/-/visually-hidden-2.0.2.tgz#741f0c25d0574d9903617c9e7ea901cf00b699f2" - integrity sha512-zYeLzaeouPbBBPDBAdRwj+jyxLJbtU6vW6r4kSQKfHoQPxJ+1A1HxRmDrj4FZJXk0CnBc4m7HF6Zuy7A5eCokg== - dependencies: - "@chakra-ui/utils" "2.0.2" - -"@ctrl/tinycolor@^3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@ctrl/tinycolor/-/tinycolor-3.4.0.tgz#c3c5ae543c897caa9c2a68630bed355be5f9990f" - integrity sha512-JZButFdZ1+/xAfpguQHoabIXkcqRRKpMrWKBkpEZZyxfY9C1DpADFB8PEqGSTeFr135SaTRfKqGKx5xSCLI7ZQ== +"@chakra-ui/visually-hidden@2.0.13": + version "2.0.13" + resolved "https://registry.yarnpkg.com/@chakra-ui/visually-hidden/-/visually-hidden-2.0.13.tgz#6553467d93f206d17716bcbe6e895a84eef87472" + integrity sha512-sDEeeEjLfID333EC46NdCbhK2HyMXlpl5HzcJjuwWIpyVz4E1gKQ9hlwpq6grijvmzeSywQ5D3tTwUrvZck4KQ== "@discoveryjs/json-ext@^0.5.0": version "0.5.7" @@ -3625,6 +3816,11 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== +"@zag-js/element-size@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@zag-js/element-size/-/element-size-0.1.0.tgz#dfdb3f66a70328d0c3149aae29b8f99c10590c22" + integrity sha512-QF8wp0+V8++z+FHXiIw93+zudtubYszOtYbNgK39fg3pi+nCZtuSm4L1jC5QZMatNZ83MfOzyNCfgUubapagJQ== + "@zag-js/focus-visible@0.1.0": version "0.1.0" resolved "https://registry.yarnpkg.com/@zag-js/focus-visible/-/focus-visible-0.1.0.tgz#9777bbaff8316d0b3a14a9095631e1494f69dbc7" @@ -3784,11 +3980,11 @@ argparse@^2.0.1: integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== aria-hidden@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.1.3.tgz#bb48de18dc84787a3c6eee113709c473c64ec254" - integrity sha512-RhVWFtKH5BiGMycI72q2RAFMLQi8JP9bLuQXgR5a8Znp7P5KOIADSJeyfI8PCVxLEp067B2HbP5JIiI/PXIZeA== + version "1.2.3" + resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.3.tgz#14aeb7fb692bbb72d69bebfa47279c1fd725e954" + integrity sha512-xcLxITLe2HYa1cnYnwCjkOO1PqUHQpozB8x9AR0OgWN2woOBi5kSDVxKfd0b7sb1hw5qFeJhXm9H1nu3xSfLeQ== dependencies: - tslib "^1.0.0" + tslib "^2.0.0" aria-query@^4.2.2: version "4.2.2" @@ -4493,7 +4689,7 @@ color-name@1.1.3: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= -color-name@^1.0.0, color-name@~1.1.4: +color-name@^1.0.0, color-name@^1.1.4, color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== @@ -4506,6 +4702,11 @@ color-string@^1.9.0: color-name "^1.0.0" simple-swizzle "^0.2.2" +color2k@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/color2k/-/color2k-2.0.2.tgz#ac2b4aea11c822a6bcb70c768b5a289f4fffcebb" + integrity sha512-kJhwH5nAwb34tmyuqq/lgjEKzlFXn1U99NlnB6Ws4qVaERcRUYeYP1cBw6BJ4vxaWStAUEef4WMr7WjOCnBt8w== + color@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/color/-/color-4.2.3.tgz#d781ecb5e57224ee43ea9627560107c0e0c6463a" @@ -4760,6 +4961,11 @@ cssesc@^3.0.0: resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== +cssfontparser@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/cssfontparser/-/cssfontparser-1.2.1.tgz#f4022fc8f9700c68029d542084afbaf425a3f3e3" + integrity sha512-6tun4LoZnj7VN6YeegOVb67KBX/7JJsqvj+pv3ZA7F878/eN33AbGa5b/S/wXxS/tcp8nc40xRUrsPlxIyNUPg== + cssnano-preset-default@^5.2.11: version "5.2.11" resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.2.11.tgz#28350471bc1af9df14052472b61340347f453a53" @@ -5550,6 +5756,14 @@ domutils@^2.8.0: domelementtype "^2.2.0" domhandler "^4.2.0" +echarts@^5.4.2: + version "5.4.2" + resolved "https://registry.yarnpkg.com/echarts/-/echarts-5.4.2.tgz#9f38781c9c6ae323e896956178f6956952c77a48" + integrity sha512-2W3vw3oI2tWJdyAz+b8DuWS0nfXtSDqlDmqgin/lfzbkB01cuMEN66KWBlmur3YMp5nEDEEt5s23pllnAzB4EA== + dependencies: + tslib "2.3.0" + zrender "5.4.3" + electron-to-chromium@^1.4.147: version "1.4.156" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.156.tgz#fc398e1bfbe586135351ebfaf198473a82923af5" @@ -6278,10 +6492,10 @@ flux@^4.0.1: fbemitter "^3.0.0" fbjs "^3.0.1" -focus-lock@^0.11.2: - version "0.11.2" - resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-0.11.2.tgz#aeef3caf1cea757797ac8afdebaec8fd9ab243ed" - integrity sha512-pZ2bO++NWLHhiKkgP1bEXHhR1/OjVcSvlCJ98aNJDFeb7H5OOQaO+SKOZle6041O9rv2tmbrO4JzClAvDUHf0g== +focus-lock@^0.11.6: + version "0.11.6" + resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-0.11.6.tgz#e8821e21d218f03e100f7dc27b733f9c4f61e683" + integrity sha512-KSuV3ur4gf2KqMNoZx3nXNVhqCkn42GuTYCX4tXPEwf0MjpFQmNMiN6m7dXaUXgIoivL6/65agoUMg4RLS0Vbg== dependencies: tslib "^2.0.3" @@ -7243,6 +7457,14 @@ istanbul-reports@^3.1.3: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" +jest-canvas-mock@^2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/jest-canvas-mock/-/jest-canvas-mock-2.5.1.tgz#81509af658ef485e9a1bf39c64e06761517bdbcb" + integrity sha512-IVnRiz+v4EYn3ydM/pBo8GW/J+nU/Hg5gHBQQOUQhdRyNfvHnabB8ReqARLO0p+kvQghqr4V0tA92CF3JcUSRg== + dependencies: + cssfontparser "^1.2.1" + moo-color "^1.0.2" + jest-changed-files@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.5.1.tgz#a348aed00ec9bf671cc58a66fcbe7c3dfd6a68f5" @@ -8767,6 +8989,13 @@ moment-timezone@^0.5.43: resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== +moo-color@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/moo-color/-/moo-color-1.0.3.tgz#d56435f8359c8284d83ac58016df7427febece74" + integrity sha512-i/+ZKXMDf6aqYtBhuOcej71YSlbjT3wCO/4H1j8rPvxDJEifdwgg5MaFyu6iYAT8GBZJg2z0dkgK4YMzvURALQ== + dependencies: + color-name "^1.1.4" + mri@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" @@ -9834,12 +10063,12 @@ react-fast-compare@3.2.0: integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA== react-focus-lock@^2.9.1: - version "2.9.1" - resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-2.9.1.tgz#094cfc19b4f334122c73bb0bff65d77a0c92dd16" - integrity sha512-pSWOQrUmiKLkffPO6BpMXN7SNKXMsuOakl652IBuALAu1esk+IcpJyM+ALcYzPTTFz1rD0R54aB9A4HuP5t1Wg== + version "2.9.4" + resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-2.9.4.tgz#4753f6dcd167c39050c9d84f9c63c71b3ff8462e" + integrity sha512-7pEdXyMseqm3kVjhdVH18sovparAzLg5h6WvIx7/Ck3ekjhrrDMEegHSa3swwC8wgfdd7DIdUVRGeiHT9/7Sgg== dependencies: "@babel/runtime" "^7.0.0" - focus-lock "^0.11.2" + focus-lock "^0.11.6" prop-types "^15.6.2" react-clientside-effect "^1.2.6" use-callback-ref "^1.3.0" @@ -9919,9 +10148,9 @@ react-remove-scroll-bar@^2.3.3: tslib "^2.0.0" react-remove-scroll@^2.5.4: - version "2.5.4" - resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.5.4.tgz#afe6491acabde26f628f844b67647645488d2ea0" - integrity sha512-xGVKJJr0SJGQVirVFAUZ2k1QLyO6m+2fy0l8Qawbp5Jgrv3DeLalrfMNBFSlmz5kriGGzsVBtGVnf4pTKIhhWA== + version "2.5.5" + resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz#1e31a1260df08887a8a0e46d09271b52b3a37e77" + integrity sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw== dependencies: react-remove-scroll-bar "^2.3.3" react-style-singleton "^2.2.1" @@ -11266,7 +11495,12 @@ tsconfig-paths@^3.14.1, tsconfig-paths@^3.14.2: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^1.0.0, tslib@^1.8.1: +tslib@2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e" + integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== + +tslib@^1.8.1: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== @@ -12005,6 +12239,13 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== +zrender@5.4.3: + version "5.4.3" + resolved "https://registry.yarnpkg.com/zrender/-/zrender-5.4.3.tgz#41ffaf835f3a3210224abd9d6964b48ff01e79f5" + integrity sha512-DRUM4ZLnoaT0PBVvGBDO9oWIDBKFdAVieNWxWwK0niYzJCMwGchRk21/hsE+RKkIveH3XHCyvXcJDkgLVvfizQ== + dependencies: + tslib "2.3.0" + zustand@^4.1.1: version "4.1.5" resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.1.5.tgz#7402b511f5b23ccb0f9ba6d20ae01ec817e16eb6" diff --git a/tests/api_connexion/endpoints/test_dag_run_endpoint.py b/tests/api_connexion/endpoints/test_dag_run_endpoint.py index 7510b41e0a8d2..434511b9e9560 100644 --- a/tests/api_connexion/endpoints/test_dag_run_endpoint.py +++ b/tests/api_connexion/endpoints/test_dag_run_endpoint.py @@ -50,6 +50,7 @@ def configured_app(minimal_app_for_api): permissions=[ (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG), (permissions.ACTION_CAN_READ, permissions.RESOURCE_DATASET), + (permissions.ACTION_CAN_READ, permissions.RESOURCE_CLUSTER_ACTIVITY), (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_DAG), (permissions.ACTION_CAN_CREATE, permissions.RESOURCE_DAG_RUN), (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG_RUN), diff --git a/tests/www/test_security.py b/tests/www/test_security.py index 31e6ca3b46874..48e02a3cbb105 100644 --- a/tests/www/test_security.py +++ b/tests/www/test_security.py @@ -388,6 +388,7 @@ def test_get_user_roles_for_anonymous_user(app, security_manager): (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG_CODE), (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG_RUN), (permissions.ACTION_CAN_READ, permissions.RESOURCE_DATASET), + (permissions.ACTION_CAN_READ, permissions.RESOURCE_CLUSTER_ACTIVITY), (permissions.ACTION_CAN_READ, permissions.RESOURCE_IMPORT_ERROR), (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG_WARNING), (permissions.ACTION_CAN_READ, permissions.RESOURCE_JOB), @@ -406,6 +407,7 @@ def test_get_user_roles_for_anonymous_user(app, security_manager): (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_DAG_DEPENDENCIES), (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_DAG_RUN), (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_DATASET), + (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_CLUSTER_ACTIVITY), (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_JOB), (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_AUDIT_LOG), (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_PLUGIN), @@ -463,7 +465,6 @@ def test_get_accessible_dag_ids(app, security_manager, session): (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG), ], ) as user: - dag_model = DagModel(dag_id=dag_id, fileloc="/tmp/dag_.py", schedule_interval="2 2 * * *") session.add(dag_model) session.commit() @@ -491,7 +492,6 @@ def test_dont_get_inaccessible_dag_ids_for_dag_resource_permission(app, security (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_DAG), ], ) as user: - dag_model = DagModel(dag_id=dag_id, fileloc="/tmp/dag_.py", schedule_interval="2 2 * * *") session.add(dag_model) session.commit() @@ -711,7 +711,6 @@ def test_correct_roles_have_perms_to_read_config(security_manager): def test_create_dag_specific_permissions(session, security_manager, monkeypatch, sample_dags): - access_control = {"Public": {permissions.ACTION_CAN_READ}} collect_dags_from_db_mock = mock.Mock() diff --git a/tests/www/views/test_views_cluster_activity.py b/tests/www/views/test_views_cluster_activity.py new file mode 100644 index 0000000000000..13105eb28a118 --- /dev/null +++ b/tests/www/views/test_views_cluster_activity.py @@ -0,0 +1,143 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +from __future__ import annotations + +import pendulum +import pytest + +from airflow.models import DagBag +from airflow.operators.empty import EmptyOperator +from airflow.utils.state import DagRunState, TaskInstanceState +from airflow.utils.types import DagRunType +from tests.test_utils.db import clear_db_runs + + +@pytest.fixture(autouse=True, scope="module") +def examples_dag_bag(): + # Speed up: We don't want example dags for this module + + return DagBag(include_examples=False, read_dags_from_db=True) + + +@pytest.fixture(autouse=True) +def clean(): + clear_db_runs() + yield + clear_db_runs() + + +# freeze time fixture so that it is applied before `make_dag_runs` is! +@pytest.fixture +def freeze_time_for_dagruns(time_machine): + time_machine.move_to("2023-05-02T00:00:00+00:00", tick=False) + yield + + +@pytest.fixture +def make_dag_runs(dag_maker, session): + with dag_maker( + dag_id="test_dag_id", + serialized=True, + session=session, + start_date=pendulum.DateTime(2023, 2, 1, 0, 0, 0, tzinfo=pendulum.UTC), + ): + EmptyOperator(task_id="task_1") >> EmptyOperator(task_id="task_2") + + date = dag_maker.dag.start_date + + run1 = dag_maker.create_dagrun( + run_id="run_1", + state=DagRunState.SUCCESS, + run_type=DagRunType.SCHEDULED, + execution_date=date, + start_date=date, + ) + + run2 = dag_maker.create_dagrun( + run_id="run_2", + state=DagRunState.FAILED, + run_type=DagRunType.DATASET_TRIGGERED, + execution_date=dag_maker.dag.next_dagrun_info(date).logical_date, + start_date=dag_maker.dag.next_dagrun_info(date).logical_date, + ) + + for ti in run1.task_instances: + ti.state = TaskInstanceState.SUCCESS + + for ti in run2.task_instances: + ti.state = TaskInstanceState.FAILED + + session.flush() + + +@pytest.mark.usefixtures("freeze_time_for_dagruns", "make_dag_runs") +def test_historical_metrics_data(admin_client, session): + resp = admin_client.get( + "/object/historical_metrics_data?start_date=2023-01-01T00:00&end_date=2023-05-02T00:00", + follow_redirects=True, + ) + assert resp.status_code == 200 + assert resp.json == { + "dag_run_states": {"failed": 1, "queued": 0, "running": 0, "success": 1}, + "dag_run_types": {"backfill": 0, "dataset_triggered": 1, "manual": 0, "scheduled": 1}, + "task_instance_states": { + "deferred": 0, + "failed": 2, + "no_status": 0, + "queued": 0, + "removed": 0, + "restarting": 0, + "running": 0, + "scheduled": 0, + "shutdown": 0, + "skipped": 0, + "success": 2, + "up_for_reschedule": 0, + "up_for_retry": 0, + "upstream_failed": 0, + }, + } + + +@pytest.mark.usefixtures("freeze_time_for_dagruns", "make_dag_runs") +def test_historical_metrics_data_date_filters(admin_client, session): + resp = admin_client.get( + "/object/historical_metrics_data?start_date=2023-02-02T00:00&end_date=2023-05-02T00:00", + follow_redirects=True, + ) + assert resp.status_code == 200 + assert resp.json == { + "dag_run_states": {"failed": 1, "queued": 0, "running": 0, "success": 0}, + "dag_run_types": {"backfill": 0, "dataset_triggered": 1, "manual": 0, "scheduled": 0}, + "task_instance_states": { + "deferred": 0, + "failed": 2, + "no_status": 0, + "queued": 0, + "removed": 0, + "restarting": 0, + "running": 0, + "scheduled": 0, + "shutdown": 0, + "skipped": 0, + "success": 0, + "up_for_reschedule": 0, + "up_for_retry": 0, + "upstream_failed": 0, + }, + }