mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[Synthetics] Sorting and infinite scroll (#139254)
* unskip monitor state scoping tests * add describe.only * unskip monitor state scoping test * add retry logic * add sort order * add alphabetical and modified on sorting * adjust styling * adjust overview state * add infinite scroll and sort by status * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * adjust test * adjust tests * adjust tests * adjust ux * update infinite scroll behavior * adjust ux * adjust test * adjust i18n * Update x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_grid.tsx * Update x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_monitors_sorted_by_status.tsx * adjust hook * update scroll logic * adjust sort field markup * fix/synthetics-preserve-id-field-on-monitor-attributes * add overview sorting e2e tests * add scroll test * adjust tests * adjust synthetics version * ensure test monitors are cleaned up * remove monitor id from use_monitors_sorted_by_status hook * remove unnecessary comments * update code formatting * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * adjust overview sorting logic * adjust tests * Update x-pack/plugins/synthetics/e2e/journeys/synthetics/overview_scrolling.journey.ts * adjust test * fix duplicate overview request Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
74f6554b51
commit
f1f1b5789d
37 changed files with 1799 additions and 351 deletions
|
@ -708,7 +708,7 @@
|
|||
"@cypress/webpack-preprocessor": "^5.12.2",
|
||||
"@elastic/eslint-plugin-eui": "0.0.2",
|
||||
"@elastic/makelogs": "^6.1.1",
|
||||
"@elastic/synthetics": "^1.0.0-beta.22",
|
||||
"@elastic/synthetics": "^1.0.0-beta.23",
|
||||
"@emotion/babel-preset-css-prop": "^11.10.0",
|
||||
"@emotion/jest": "^11.10.0",
|
||||
"@istanbuljs/nyc-config-typescript": "^1.0.2",
|
||||
|
@ -1089,7 +1089,7 @@
|
|||
"pirates": "^4.0.1",
|
||||
"piscina": "^3.2.0",
|
||||
"pixelmatch": "^5.3.0",
|
||||
"playwright": "^1.17.1",
|
||||
"playwright": "^1.26.0",
|
||||
"pngjs": "^3.4.0",
|
||||
"postcss": "^8.4.14",
|
||||
"postcss-loader": "^4.2.0",
|
||||
|
|
|
@ -400,7 +400,7 @@ export type MonitorOverviewItem = t.TypeOf<typeof MonitorOverviewItemCodec>;
|
|||
export const MonitorOverviewResultCodec = t.type({
|
||||
total: t.number,
|
||||
allMonitorIds: t.array(t.string),
|
||||
pages: t.record(t.string, t.array(MonitorOverviewItemCodec)),
|
||||
monitors: t.array(MonitorOverviewItemCodec),
|
||||
});
|
||||
|
||||
export type MonitorOverviewResult = t.TypeOf<typeof MonitorOverviewResultCodec>;
|
||||
|
|
|
@ -7,10 +7,19 @@
|
|||
|
||||
import * as t from 'io-ts';
|
||||
|
||||
export const OverviewStatusMetaDataCodec = t.interface({
|
||||
heartbeatId: t.string,
|
||||
configId: t.string,
|
||||
location: t.string,
|
||||
});
|
||||
|
||||
export const OverviewStatusType = t.type({
|
||||
up: t.number,
|
||||
down: t.number,
|
||||
disabledCount: t.number,
|
||||
upConfigs: t.array(OverviewStatusMetaDataCodec),
|
||||
downConfigs: t.array(OverviewStatusMetaDataCodec),
|
||||
});
|
||||
|
||||
export type OverviewStatus = t.TypeOf<typeof OverviewStatusType>;
|
||||
export type OverviewStatusMetaData = t.TypeOf<typeof OverviewStatusMetaDataCodec>;
|
||||
|
|
|
@ -8,3 +8,5 @@
|
|||
export * from './getting_started.journey';
|
||||
export * from './add_monitor.journey';
|
||||
export * from './monitor_selector.journey';
|
||||
export * from './overview_sorting.journey';
|
||||
export * from './overview_scrolling.journey';
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { journey, step, expect, before } from '@elastic/synthetics';
|
||||
import { journey, step, expect, before, after } from '@elastic/synthetics';
|
||||
import {
|
||||
addTestMonitor,
|
||||
cleanTestMonitors,
|
||||
|
@ -28,6 +28,10 @@ journey(`MonitorSelector`, async ({ page, params }) => {
|
|||
await addTestMonitor(params.kibanaUrl, testMonitor3);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await cleanTestMonitors(params);
|
||||
});
|
||||
|
||||
step('Go to monitor-management', async () => {
|
||||
await syntheticsApp.navigateToMonitorManagement();
|
||||
});
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { before, after, expect, journey, step } from '@elastic/synthetics';
|
||||
import {
|
||||
addTestMonitor,
|
||||
cleanTestMonitors,
|
||||
enableMonitorManagedViaApi,
|
||||
} from './services/add_monitor';
|
||||
import { syntheticsAppPageProvider } from '../../page_objects/synthetics_app';
|
||||
|
||||
journey('Overview Scrolling', async ({ page, params }) => {
|
||||
const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl });
|
||||
|
||||
before(async () => {
|
||||
await enableMonitorManagedViaApi(params.kibanaUrl);
|
||||
await cleanTestMonitors(params);
|
||||
|
||||
for (let i = 0; i < 100; i++) {
|
||||
await addTestMonitor(params.kibanaUrl, `test monitor ${i}`);
|
||||
}
|
||||
|
||||
await syntheticsApp.waitForLoadingToFinish();
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await cleanTestMonitors(params);
|
||||
});
|
||||
|
||||
step('Go to overview', async () => {
|
||||
await syntheticsApp.navigateToOverview();
|
||||
});
|
||||
|
||||
step('login to Kibana', async () => {
|
||||
await syntheticsApp.loginToKibana();
|
||||
const invalid = await page.locator(`text=Username or password is incorrect. Please try again.`);
|
||||
expect(await invalid.isVisible()).toBeFalsy();
|
||||
});
|
||||
|
||||
step('scroll until you see showing all monitors', async () => {
|
||||
let showingAllMonitorsNode;
|
||||
|
||||
const gridItems = await page.locator(`[data-test-subj="syntheticsOverviewGridItem"]`);
|
||||
await page.waitForSelector(`text="test monitor 0"`);
|
||||
let count = await gridItems.count();
|
||||
|
||||
expect(count).toBe(32);
|
||||
|
||||
while (!showingAllMonitorsNode) {
|
||||
await page.mouse.wheel(0, 100);
|
||||
showingAllMonitorsNode = await page.$(`text="Showing all monitors"`);
|
||||
}
|
||||
|
||||
expect(await showingAllMonitorsNode.isVisible()).toBe(true);
|
||||
|
||||
count = await gridItems.count();
|
||||
expect(count).toBe(100);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { before, expect, journey, step } from '@elastic/synthetics';
|
||||
import {
|
||||
addTestMonitor,
|
||||
cleanTestMonitors,
|
||||
enableMonitorManagedViaApi,
|
||||
} from './services/add_monitor';
|
||||
import { syntheticsAppPageProvider } from '../../page_objects/synthetics_app';
|
||||
|
||||
journey('Overview Sorting', async ({ page, params }) => {
|
||||
const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl });
|
||||
const testMonitor1 = 'acb'; // second alpha, first created
|
||||
const testMonitor2 = 'aCd'; // third alpha, second created
|
||||
const testMonitor3 = 'Abc'; // first alpha, last created
|
||||
|
||||
before(async () => {
|
||||
await enableMonitorManagedViaApi(params.kibanaUrl);
|
||||
await cleanTestMonitors(params);
|
||||
|
||||
await addTestMonitor(params.kibanaUrl, testMonitor1);
|
||||
await addTestMonitor(params.kibanaUrl, testMonitor2);
|
||||
await addTestMonitor(params.kibanaUrl, testMonitor3);
|
||||
|
||||
await syntheticsApp.waitForLoadingToFinish();
|
||||
});
|
||||
|
||||
step('Go to monitor-management', async () => {
|
||||
await syntheticsApp.navigateToOverview();
|
||||
});
|
||||
|
||||
step('login to Kibana', async () => {
|
||||
await syntheticsApp.loginToKibana();
|
||||
const invalid = await page.locator(`text=Username or password is incorrect. Please try again.`);
|
||||
expect(await invalid.isVisible()).toBeFalsy();
|
||||
});
|
||||
|
||||
step('sort alpbhaetical asc', async () => {
|
||||
await syntheticsApp.navigateToOverview();
|
||||
await page.waitForSelector(`[data-test-subj="syntheticsOverviewGridItem"]`);
|
||||
await page.click('[data-test-subj="syntheticsOverviewSortButton"]');
|
||||
await page.click('button:has-text("Alphabetical")');
|
||||
await page.waitForSelector('text=Loading');
|
||||
await page.waitForSelector(`text=${testMonitor1}`);
|
||||
await page.waitForSelector(`text=${testMonitor2}`);
|
||||
await page.waitForSelector(`text=${testMonitor3}`);
|
||||
const gridItems = await page.locator(`[data-test-subj="syntheticsOverviewGridItem"]`);
|
||||
const first = await gridItems.nth(0);
|
||||
const second = await gridItems.nth(1);
|
||||
const third = await gridItems.nth(2);
|
||||
const correctFirstMonitor = await first.locator(`button:has-text('${testMonitor3}')`);
|
||||
const correctSecondMonitor = await second.locator(`button:has-text('${testMonitor1}')`);
|
||||
const correctThirdMonitor = await third.locator(`button:has-text('${testMonitor2}')`);
|
||||
expect(await correctFirstMonitor.count()).toBe(1);
|
||||
expect(await correctSecondMonitor.count()).toBe(1);
|
||||
expect(await correctThirdMonitor.count()).toBe(1);
|
||||
});
|
||||
|
||||
step('sort alpbhaetical desc', async () => {
|
||||
await page.waitForSelector(`[data-test-subj="syntheticsOverviewGridItem"]`);
|
||||
await page.click('[data-test-subj="syntheticsOverviewSortButton"]');
|
||||
await page.click('button:has-text("Z -> A")');
|
||||
await page.waitForSelector('text=Loading');
|
||||
await page.waitForSelector(`text=${testMonitor1}`);
|
||||
await page.waitForSelector(`text=${testMonitor2}`);
|
||||
await page.waitForSelector(`text=${testMonitor3}`);
|
||||
const gridItems = await page.locator(`[data-test-subj="syntheticsOverviewGridItem"]`);
|
||||
const first = await gridItems.nth(0);
|
||||
const second = await gridItems.nth(1);
|
||||
const third = await gridItems.nth(2);
|
||||
const correctFirstMonitor = await first.locator(`button:has-text('${testMonitor2}')`);
|
||||
const correctSecondMonitor = await second.locator(`button:has-text('${testMonitor1}')`);
|
||||
const correctThirdMonitor = await third.locator(`button:has-text('${testMonitor3}')`);
|
||||
expect(await correctFirstMonitor.count()).toBe(1);
|
||||
expect(await correctSecondMonitor.count()).toBe(1);
|
||||
expect(await correctThirdMonitor.count()).toBe(1);
|
||||
});
|
||||
|
||||
step('sort last updated asc', async () => {
|
||||
await page.waitForSelector(`[data-test-subj="syntheticsOverviewGridItem"]`);
|
||||
await page.click('[data-test-subj="syntheticsOverviewSortButton"]');
|
||||
await page.click('button:has-text("Last modified")');
|
||||
await page.waitForSelector('text=Loading');
|
||||
await page.waitForSelector(`text=${testMonitor1}`);
|
||||
await page.waitForSelector(`text=${testMonitor2}`);
|
||||
await page.waitForSelector(`text=${testMonitor3}`);
|
||||
const gridItems = await page.locator(`[data-test-subj="syntheticsOverviewGridItem"]`);
|
||||
const first = await gridItems.nth(0);
|
||||
const second = await gridItems.nth(1);
|
||||
const third = await gridItems.nth(2);
|
||||
const correctFirstMonitor = await first.locator(`button:has-text('${testMonitor3}')`);
|
||||
const correctSecondMonitor = await second.locator(`button:has-text('${testMonitor2}')`);
|
||||
const correctThirdMonitor = await third.locator(`button:has-text('${testMonitor1}')`);
|
||||
expect(await correctFirstMonitor.count()).toBe(1);
|
||||
expect(await correctSecondMonitor.count()).toBe(1);
|
||||
expect(await correctThirdMonitor.count()).toBe(1);
|
||||
await page.waitForTimeout(30000);
|
||||
});
|
||||
|
||||
step('sort last updated desc', async () => {
|
||||
await page.waitForSelector(`[data-test-subj="syntheticsOverviewGridItem"]`);
|
||||
await page.click('[data-test-subj="syntheticsOverviewSortButton"]');
|
||||
await page.click('button:has-text("Oldest first")');
|
||||
await page.waitForSelector('text=Loading');
|
||||
await page.waitForSelector(`text=${testMonitor1}`);
|
||||
await page.waitForSelector(`text=${testMonitor2}`);
|
||||
await page.waitForSelector(`text=${testMonitor3}`);
|
||||
const gridItems = await page.locator(`[data-test-subj="syntheticsOverviewGridItem"]`);
|
||||
const first = await gridItems.nth(0);
|
||||
const second = await gridItems.nth(1);
|
||||
const third = await gridItems.nth(2);
|
||||
const correctFirstMonitor = await first.locator(`button:has-text('${testMonitor1}')`);
|
||||
const correctSecondMonitor = await second.locator(`button:has-text('${testMonitor2}')`);
|
||||
const correctThirdMonitor = await third.locator(`button:has-text('${testMonitor3}')`);
|
||||
expect(await correctFirstMonitor.count()).toBe(1);
|
||||
expect(await correctSecondMonitor.count()).toBe(1);
|
||||
expect(await correctThirdMonitor.count()).toBe(1);
|
||||
await page.waitForTimeout(30000);
|
||||
});
|
||||
|
||||
step('delete monitors', async () => {
|
||||
await syntheticsApp.navigateToMonitorManagement();
|
||||
expect(await syntheticsApp.deleteMonitors()).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -21,6 +21,7 @@ export function syntheticsAppPageProvider({ page, kibanaUrl }: { page: Page; kib
|
|||
const basePath = isRemote ? remoteKibanaUrl : kibanaUrl;
|
||||
const monitorManagement = `${basePath}/app/synthetics/monitors`;
|
||||
const addMonitor = `${basePath}/app/synthetics/add-monitor`;
|
||||
const overview = `${basePath}/app/synthetics`;
|
||||
return {
|
||||
...loginPageProvider({
|
||||
page,
|
||||
|
@ -37,6 +38,10 @@ export function syntheticsAppPageProvider({ page, kibanaUrl }: { page: Page; kib
|
|||
await this.waitForMonitorManagementLoadingToFinish();
|
||||
},
|
||||
|
||||
async navigateToOverview() {
|
||||
await page.goto(overview, { waitUntil: 'networkidle' });
|
||||
},
|
||||
|
||||
async waitForMonitorManagementLoadingToFinish() {
|
||||
while (true) {
|
||||
if ((await page.$(this.byTestId('uptimeLoader'))) === null) break;
|
||||
|
|
|
@ -7,13 +7,14 @@
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import React, { useState } from 'react';
|
||||
import { Chart, Settings, Metric, MetricTrendShape } from '@elastic/charts';
|
||||
import { EuiPanel, EuiLoadingChart } from '@elastic/eui';
|
||||
import { EuiPanel } from '@elastic/eui';
|
||||
import { DARK_THEME } from '@elastic/charts';
|
||||
import { useTheme } from '@kbn/observability-plugin/public';
|
||||
import { useLocationName, useStatusByLocation } from '../../../../hooks';
|
||||
import { formatDuration } from '../../../../utils/formatting';
|
||||
import { MonitorOverviewItem, Ping } from '../../../../../../../common/runtime_types';
|
||||
import { ActionsPopover } from './actions_popover';
|
||||
import { OverviewGridItemLoader } from './overview_grid_item_loader';
|
||||
|
||||
export const getColor = (theme: ReturnType<typeof useTheme>, isEnabled: boolean, ping?: Ping) => {
|
||||
if (!isEnabled) {
|
||||
|
@ -101,7 +102,7 @@ export const MetricItem = ({
|
|||
)}
|
||||
</EuiPanel>
|
||||
) : (
|
||||
<EuiLoadingChart mono />
|
||||
<OverviewGridItemLoader />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -48,22 +48,21 @@ describe('Overview Grid', () => {
|
|||
return hits;
|
||||
};
|
||||
|
||||
const perPage = 20;
|
||||
|
||||
it('renders correctly', async () => {
|
||||
jest
|
||||
.spyOn(hooks, 'useLast50DurationChart')
|
||||
.mockReturnValue({ data: getMockChart(), averageDuration: 30000, loading: false });
|
||||
|
||||
const { getByText, getAllByTestId } = render(<OverviewGrid />, {
|
||||
const { getByText, getAllByTestId, queryByText } = render(<OverviewGrid />, {
|
||||
state: {
|
||||
overview: {
|
||||
pageState: {
|
||||
perPage: 20,
|
||||
perPage,
|
||||
},
|
||||
data: {
|
||||
pages: {
|
||||
0: getMockData().slice(0, 20),
|
||||
1: getMockData().slice(20, 40),
|
||||
},
|
||||
monitors: getMockData(),
|
||||
allMonitorIds: [], // not critical for this test
|
||||
total: getMockData().length,
|
||||
},
|
||||
|
@ -87,9 +86,49 @@ describe('Overview Grid', () => {
|
|||
},
|
||||
});
|
||||
|
||||
expect(getByText(/1-20/)).toBeInTheDocument();
|
||||
expect(getByText(/of 40/)).toBeInTheDocument();
|
||||
expect(getByText('Rows per page: 20')).toBeInTheDocument();
|
||||
expect(getAllByTestId('syntheticsOverviewGridItem').length).toEqual(20);
|
||||
expect(getByText('Showing')).toBeInTheDocument();
|
||||
expect(getByText('40')).toBeInTheDocument();
|
||||
expect(getByText('Monitors')).toBeInTheDocument();
|
||||
expect(queryByText('Showing all monitors')).not.toBeInTheDocument();
|
||||
expect(getAllByTestId('syntheticsOverviewGridItem').length).toEqual(perPage);
|
||||
});
|
||||
|
||||
it('displays showing all monitors label when reaching the end of the list', async () => {
|
||||
jest
|
||||
.spyOn(hooks, 'useLast50DurationChart')
|
||||
.mockReturnValue({ data: getMockChart(), averageDuration: 30000, loading: false });
|
||||
|
||||
const { getByText } = render(<OverviewGrid />, {
|
||||
state: {
|
||||
overview: {
|
||||
pageState: {
|
||||
perPage,
|
||||
},
|
||||
data: {
|
||||
monitors: getMockData().slice(0, 16),
|
||||
allMonitorIds: [], // not critical for this test
|
||||
total: getMockData().length,
|
||||
},
|
||||
loaded: true,
|
||||
loading: false,
|
||||
},
|
||||
serviceLocations: {
|
||||
locations: [
|
||||
{
|
||||
id: 'us_central',
|
||||
label: 'Us Central',
|
||||
},
|
||||
{
|
||||
id: 'us_east',
|
||||
label: 'US East',
|
||||
},
|
||||
],
|
||||
locationsLoaded: true,
|
||||
loading: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(getByText('Showing all monitors')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,40 +4,77 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import React, { useState } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import useThrottle from 'react-use/lib/useThrottle';
|
||||
import { useSelector } from 'react-redux';
|
||||
import useIntersection from 'react-use/lib/useIntersection';
|
||||
import {
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFlexGrid,
|
||||
EuiSpacer,
|
||||
EuiTablePagination,
|
||||
EuiFlexGroup,
|
||||
EuiButtonEmpty,
|
||||
EuiText,
|
||||
} from '@elastic/eui';
|
||||
import { selectOverviewState, setOverviewPerPageAction } from '../../../../state/overview';
|
||||
import { selectOverviewState } from '../../../../state/overview';
|
||||
import { MonitorOverviewItem } from '../../../../../../../common/runtime_types';
|
||||
import { OverviewPaginationInfo } from './overview_pagination_info';
|
||||
import { OverviewGridItem } from './overview_grid_item';
|
||||
import { SortFields } from './sort_fields';
|
||||
import { useMonitorsSortedByStatus } from '../../../../hooks/use_monitors_sorted_by_status';
|
||||
import { OverviewLoader } from './overview_loader';
|
||||
import { OverviewStatus } from './overview_status';
|
||||
|
||||
export const OverviewGrid = () => {
|
||||
const {
|
||||
data: { pages },
|
||||
data: { monitors },
|
||||
loaded,
|
||||
pageState: { perPage },
|
||||
pageState,
|
||||
} = useSelector(selectOverviewState);
|
||||
const dispatch = useDispatch();
|
||||
const [page, setPage] = useState(0);
|
||||
const currentMonitors = pages[page] || [];
|
||||
const { perPage, sortField } = pageState;
|
||||
const [loadNextPage, setLoadNextPage] = useState(false);
|
||||
const [page, setPage] = useState(1);
|
||||
|
||||
const goToPage = (pageNumber: number) => {
|
||||
setPage(pageNumber);
|
||||
};
|
||||
const { monitorsSortedByStatus } = useMonitorsSortedByStatus(
|
||||
sortField === 'status' && monitors.length !== 0
|
||||
);
|
||||
const currentMonitors = getCurrentMonitors({
|
||||
monitors,
|
||||
monitorsSortedByStatus,
|
||||
perPage,
|
||||
page,
|
||||
sortField,
|
||||
});
|
||||
|
||||
const changeItemsPerPage = (itemsPerPage: number) => {
|
||||
dispatch(setOverviewPerPageAction(itemsPerPage));
|
||||
};
|
||||
const intersectionRef = useRef(null);
|
||||
const intersection = useIntersection(intersectionRef, {
|
||||
root: null,
|
||||
rootMargin: '640px', // Height of 4 rows of monitors, minus the gutters
|
||||
threshold: 0.1,
|
||||
});
|
||||
const hasIntersected = intersection && intersection.intersectionRatio > 0;
|
||||
|
||||
return loaded ? (
|
||||
useThrottle(() => {
|
||||
if (
|
||||
hasIntersected &&
|
||||
currentMonitors.length === page * perPage &&
|
||||
currentMonitors.length !== monitors.length
|
||||
) {
|
||||
setLoadNextPage(true);
|
||||
} else {
|
||||
setLoadNextPage(false);
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
useEffect(() => {
|
||||
if (loadNextPage) {
|
||||
setPage((p) => p + 1);
|
||||
setLoadNextPage(false);
|
||||
}
|
||||
}, [loadNextPage]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<EuiFlexGroup gutterSize="none">
|
||||
<EuiFlexItem grow={false}>
|
||||
|
@ -45,29 +82,82 @@ export const OverviewGrid = () => {
|
|||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer />
|
||||
<OverviewPaginationInfo page={page} />
|
||||
<EuiFlexGroup justifyContent="spaceBetween" alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<OverviewPaginationInfo page={page} loading={!loaded} />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<SortFields onSortChange={() => setPage(1)} />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer />
|
||||
<EuiFlexGrid columns={4}>
|
||||
{currentMonitors.map((monitor) => (
|
||||
<EuiFlexItem
|
||||
key={`${monitor.id}-${monitor.location?.id}`}
|
||||
data-test-subj="syntheticsOverviewGridItem"
|
||||
>
|
||||
<OverviewGridItem monitor={monitor} />
|
||||
{loaded && currentMonitors.length ? (
|
||||
<EuiFlexGrid columns={4} data-test-subj="syntheticsOverviewGridItemContainer">
|
||||
{currentMonitors.map((monitor) => (
|
||||
<EuiFlexItem
|
||||
key={`${monitor.id}-${monitor.location?.id}`}
|
||||
data-test-subj="syntheticsOverviewGridItem"
|
||||
>
|
||||
<OverviewGridItem monitor={monitor} />
|
||||
</EuiFlexItem>
|
||||
))}
|
||||
</EuiFlexGrid>
|
||||
) : (
|
||||
<OverviewLoader />
|
||||
)}
|
||||
<span ref={intersectionRef}>
|
||||
<EuiSpacer size="l" />
|
||||
</span>
|
||||
<EuiFlexGroup justifyContent="spaceBetween" alignItems="center">
|
||||
{currentMonitors.length === monitors.length && (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiText size="xs">{SHOWING_ALL_MONITORS_LABEL}</EuiText>
|
||||
</EuiFlexItem>
|
||||
))}
|
||||
</EuiFlexGrid>
|
||||
<EuiTablePagination
|
||||
aria-label={i18n.translate('xpack.synthetics.overview.pagination.ariaLabel', {
|
||||
defaultMessage: 'Pagination for monitor overview',
|
||||
})}
|
||||
pageCount={Object.keys(pages).length}
|
||||
activePage={page}
|
||||
onChangePage={goToPage}
|
||||
itemsPerPage={perPage}
|
||||
onChangeItemsPerPage={changeItemsPerPage}
|
||||
itemsPerPageOptions={[10, 20, 40]}
|
||||
/>
|
||||
)}
|
||||
{currentMonitors.length === monitors.length && currentMonitors.length > perPage && (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonEmpty
|
||||
onClick={() => window.scrollTo(0, 0)}
|
||||
iconType="sortUp"
|
||||
iconSide="right"
|
||||
size="xs"
|
||||
>
|
||||
{SCROLL_TO_TOP_LABEL}
|
||||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
</EuiFlexGroup>
|
||||
</>
|
||||
) : null;
|
||||
);
|
||||
};
|
||||
|
||||
const getCurrentMonitors = ({
|
||||
sortField,
|
||||
perPage,
|
||||
page,
|
||||
monitors,
|
||||
monitorsSortedByStatus,
|
||||
}: {
|
||||
sortField: string;
|
||||
perPage: number;
|
||||
page: number;
|
||||
monitors: MonitorOverviewItem[];
|
||||
monitorsSortedByStatus: MonitorOverviewItem[];
|
||||
}) => {
|
||||
if (sortField === 'status') {
|
||||
return monitorsSortedByStatus.slice(0, perPage * page);
|
||||
} else {
|
||||
return monitors.slice(0, perPage * page);
|
||||
}
|
||||
};
|
||||
|
||||
const SHOWING_ALL_MONITORS_LABEL = i18n.translate(
|
||||
'xpack.synthetics.overview.grid.showingAllMonitors.label',
|
||||
{
|
||||
defaultMessage: 'Showing all monitors',
|
||||
}
|
||||
);
|
||||
|
||||
const SCROLL_TO_TOP_LABEL = i18n.translate('xpack.synthetics.overview.grid.scrollToTop.label', {
|
||||
defaultMessage: 'Back to top',
|
||||
});
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { EuiPanel, EuiLoadingContent } from '@elastic/eui';
|
||||
|
||||
export const OverviewGridItemLoader = () => {
|
||||
return (
|
||||
<EuiPanel
|
||||
style={{
|
||||
height: '160px',
|
||||
}}
|
||||
hasBorder={true}
|
||||
>
|
||||
<EuiLoadingContent lines={2} />
|
||||
</EuiPanel>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { EuiFlexGrid, EuiFlexItem } from '@elastic/eui';
|
||||
import { OverviewGridItemLoader } from './overview_grid_item_loader';
|
||||
|
||||
export const OverviewLoader = () => {
|
||||
const ROWS = 4;
|
||||
const COLUMNS = 4;
|
||||
const loaders = Array(ROWS * COLUMNS).fill(null);
|
||||
return (
|
||||
<>
|
||||
<EuiFlexGrid columns={COLUMNS}>
|
||||
{loaders.map((_, i) => (
|
||||
<EuiFlexItem key={i}>
|
||||
<OverviewGridItemLoader />
|
||||
</EuiFlexItem>
|
||||
))}
|
||||
</EuiFlexGrid>
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -5,42 +5,88 @@
|
|||
* 2.0.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { EuiText } from '@elastic/eui';
|
||||
import { EuiText, EuiLoadingSpinner, EuiI18nNumber, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { selectOverviewState } from '../../../../state/overview';
|
||||
|
||||
export const OverviewPaginationInfo = ({ page }: { page: number }) => {
|
||||
export const OverviewPaginationInfo = ({
|
||||
page,
|
||||
loading,
|
||||
startRange,
|
||||
endRange,
|
||||
}: {
|
||||
page: number;
|
||||
loading: boolean;
|
||||
startRange?: number;
|
||||
endRange?: number;
|
||||
}) => {
|
||||
const {
|
||||
data: { total, pages },
|
||||
data: { total, monitors },
|
||||
loaded,
|
||||
pageState: { perPage },
|
||||
} = useSelector(selectOverviewState);
|
||||
const startRange = (page + 1) * perPage - perPage + 1;
|
||||
const endRange = startRange + (pages[`${page}`]?.length || 0) - 1;
|
||||
|
||||
if (loaded && !Object.keys(pages).length) {
|
||||
if (loaded && !monitors.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return loaded ? (
|
||||
<EuiText size="xs">
|
||||
<FormattedMessage
|
||||
id="xpack.synthetics.overview.pagination.description"
|
||||
defaultMessage="Showing {currentCount} of {total} {monitors}"
|
||||
values={{
|
||||
currentCount: <strong>{`${startRange}-${endRange}`}</strong>,
|
||||
total,
|
||||
monitors: (
|
||||
<strong>
|
||||
<FormattedMessage
|
||||
id="xpack.synthetics.overview.monitors.label"
|
||||
defaultMessage="Monitors"
|
||||
/>
|
||||
</strong>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
{startRange && endRange ? (
|
||||
<FormattedMessage
|
||||
id="xpack.synthetics.overview.pagination.description"
|
||||
defaultMessage="Showing {currentCount} of {total} {monitors}"
|
||||
values={{
|
||||
currentCount: <strong>{`${startRange}-${endRange}`}</strong>,
|
||||
total,
|
||||
monitors: (
|
||||
<strong>
|
||||
<FormattedMessage
|
||||
id="xpack.synthetics.overview.monitors.label"
|
||||
defaultMessage="Monitors"
|
||||
/>
|
||||
</strong>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<FormattedMessage
|
||||
id="xpack.synthetics.management.monitorList.recordTotal"
|
||||
defaultMessage="Showing {total} {monitorsLabel}"
|
||||
values={{
|
||||
total: (
|
||||
<strong>
|
||||
<EuiI18nNumber value={total} />
|
||||
</strong>
|
||||
),
|
||||
monitorsLabel: (
|
||||
<strong>
|
||||
<FormattedMessage
|
||||
id="xpack.synthetics.management.monitorList.recordRangeLabel"
|
||||
defaultMessage="{monitorCount, plural, one {Monitor} other {Monitors}}"
|
||||
values={{
|
||||
monitorCount: total,
|
||||
}}
|
||||
/>
|
||||
</strong>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</EuiText>
|
||||
) : null;
|
||||
) : (
|
||||
<EuiText size="xs">
|
||||
<EuiFlexGroup alignItems="center" gutterSize="s">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiLoadingSpinner size="m" />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<FormattedMessage
|
||||
id="xpack.synthetics.overview.pagination.loading"
|
||||
defaultMessage="Loading Monitors..."
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiText>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import React from 'react';
|
||||
import type { PayloadAction } from '@reduxjs/toolkit';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui';
|
||||
import { ConfigKey } from '../../../../../../../common/runtime_types';
|
||||
|
||||
import { selectOverviewState, setOverviewPageStateAction } from '../../../../state/overview';
|
||||
import { SortMenu } from './sort_menu';
|
||||
|
||||
export const SortFields = ({ onSortChange }: { onSortChange?: () => void }) => {
|
||||
const {
|
||||
pageState: { sortOrder, sortField },
|
||||
} = useSelector(selectOverviewState);
|
||||
const dispatch = useDispatch();
|
||||
const { asc, desc, label } = getOrderContent(sortField);
|
||||
const handleSortChange = (payloadAction: PayloadAction<unknown>) => {
|
||||
if (onSortChange) {
|
||||
onSortChange();
|
||||
}
|
||||
dispatch(payloadAction);
|
||||
};
|
||||
|
||||
const orderByOptions = [
|
||||
{
|
||||
label: asc,
|
||||
value: 'asc',
|
||||
checked: sortOrder === 'asc',
|
||||
onClick: () => {
|
||||
handleSortChange(
|
||||
setOverviewPageStateAction({
|
||||
sortOrder: 'asc',
|
||||
})
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: desc,
|
||||
value: 'desc',
|
||||
checked: sortOrder === 'desc',
|
||||
onClick: () => {
|
||||
handleSortChange(
|
||||
setOverviewPageStateAction({
|
||||
sortOrder: 'desc',
|
||||
})
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
const sortByOptions = [
|
||||
{
|
||||
label: STATUS_LABEL,
|
||||
value: 'status',
|
||||
checked: sortField === 'status',
|
||||
defaultSortOrder: 'asc',
|
||||
onClick: () => {
|
||||
handleSortChange(
|
||||
setOverviewPageStateAction({
|
||||
sortField: 'status',
|
||||
sortOrder: 'asc',
|
||||
})
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: ALPHABETICAL_LABEL,
|
||||
value: `${ConfigKey.NAME}.keyword`,
|
||||
checked: sortField === `${ConfigKey.NAME}.keyword`,
|
||||
defaultSortOrder: 'asc',
|
||||
onClick: () => {
|
||||
handleSortChange(
|
||||
setOverviewPageStateAction({
|
||||
sortField: `${ConfigKey.NAME}.keyword`,
|
||||
sortOrder: 'asc',
|
||||
})
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: LAST_MODIFIED_LABEL,
|
||||
value: 'updated_at',
|
||||
checked: sortField === 'updated_at',
|
||||
defaultSortOrder: 'desc',
|
||||
onClick: () => {
|
||||
handleSortChange(
|
||||
setOverviewPageStateAction({
|
||||
sortField: 'updated_at',
|
||||
sortOrder: 'desc',
|
||||
})
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<EuiFlexGroup gutterSize="s" alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFlexGroup responsive={false} gutterSize="none" alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiTitle size="xxxs">
|
||||
<span>{SORT_TITLE}</span>
|
||||
</EuiTitle>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false} data-test-subj="syntheticsOverviewSortButton">
|
||||
<SortMenu sortOptions={sortByOptions} orderOptions={orderByOptions} sortField={label} />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
};
|
||||
|
||||
const getOrderContent = (sortField: string) => {
|
||||
switch (sortField) {
|
||||
case `${ConfigKey.NAME}.keyword`:
|
||||
return {
|
||||
asc: SORT_ALPHABETICAL_ASC,
|
||||
desc: SORT_ALPHABETICAL_DESC,
|
||||
label: ALPHABETICAL_LABEL,
|
||||
};
|
||||
case 'updated_at':
|
||||
return {
|
||||
asc: SORT_UPDATED_ASC,
|
||||
desc: SORT_UPDATED_DESC,
|
||||
label: LAST_MODIFIED_LABEL,
|
||||
};
|
||||
case 'status':
|
||||
return {
|
||||
asc: SORT_STATUS_ASC,
|
||||
desc: SORT_STATUS_DESC,
|
||||
label: STATUS_LABEL,
|
||||
};
|
||||
default:
|
||||
return {
|
||||
asc: ASCENDING_LABEL,
|
||||
desc: DESCENDING_LABEL,
|
||||
label: '',
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const SORT_TITLE = i18n.translate('xpack.synthetics.overview.sortPopover.sort.title', {
|
||||
defaultMessage: 'Sort',
|
||||
});
|
||||
|
||||
const SORT_ALPHABETICAL_ASC = i18n.translate(
|
||||
'xpack.synthetics.overview.sortPopover.alphabetical.asc',
|
||||
{
|
||||
defaultMessage: 'A -> Z',
|
||||
description: 'Describes ascending alphabetical sort order',
|
||||
}
|
||||
);
|
||||
|
||||
const SORT_ALPHABETICAL_DESC = i18n.translate(
|
||||
'xpack.synthetics.overview.sortPopover.alphabetical.desc',
|
||||
{
|
||||
defaultMessage: 'Z -> A',
|
||||
description: 'Describes descending alphabetical sort order',
|
||||
}
|
||||
);
|
||||
|
||||
const SORT_UPDATED_ASC = i18n.translate('xpack.synthetics.overview.sortPopover.lastModified.asc', {
|
||||
defaultMessage: 'Oldest first',
|
||||
});
|
||||
|
||||
const SORT_UPDATED_DESC = i18n.translate(
|
||||
'xpack.synthetics.overview.sortPopover.lastModified.desc',
|
||||
{
|
||||
defaultMessage: 'Newest first',
|
||||
}
|
||||
);
|
||||
|
||||
const SORT_STATUS_ASC = i18n.translate('xpack.synthetics.overview.sortPopover.status.asc', {
|
||||
defaultMessage: 'Down first',
|
||||
});
|
||||
|
||||
const SORT_STATUS_DESC = i18n.translate('xpack.synthetics.overview.sortPopover.status.desc', {
|
||||
defaultMessage: 'Up first',
|
||||
});
|
||||
|
||||
const ASCENDING_LABEL = i18n.translate('xpack.synthetics.overview.sortPopover.ascending.label', {
|
||||
defaultMessage: 'Ascending',
|
||||
});
|
||||
|
||||
const DESCENDING_LABEL = i18n.translate('xpack.synthetics.overview.sortPopover.descending.label', {
|
||||
defaultMessage: 'Descending',
|
||||
});
|
||||
|
||||
const STATUS_LABEL = i18n.translate('xpack.synthetics.overview.sortPopover.status.label', {
|
||||
defaultMessage: 'Status',
|
||||
});
|
||||
|
||||
const ALPHABETICAL_LABEL = i18n.translate(
|
||||
'xpack.synthetics.overview.sortPopover.alphabetical.label',
|
||||
{
|
||||
defaultMessage: 'Alphabetical',
|
||||
}
|
||||
);
|
||||
|
||||
const LAST_MODIFIED_LABEL = i18n.translate(
|
||||
'xpack.synthetics.overview.sortPopover.lastModified.label',
|
||||
{
|
||||
defaultMessage: 'Last modified',
|
||||
}
|
||||
);
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import {
|
||||
EuiButtonEmpty,
|
||||
EuiContextMenuPanel,
|
||||
EuiContextMenuItem,
|
||||
EuiPopover,
|
||||
useGeneratedHtmlId,
|
||||
EuiText,
|
||||
EuiPanel,
|
||||
EuiHorizontalRule,
|
||||
} from '@elastic/eui';
|
||||
|
||||
interface Option {
|
||||
label: string;
|
||||
value: string;
|
||||
checked: boolean;
|
||||
defaultSortOrder?: string;
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
sortOptions: Option[];
|
||||
orderOptions: Option[];
|
||||
sortField: string;
|
||||
}
|
||||
|
||||
export const SortMenu = ({ sortOptions, orderOptions, sortField }: Props) => {
|
||||
const [isPopoverOpen, setPopover] = useState(false);
|
||||
|
||||
const singleContextMenuPopoverId = useGeneratedHtmlId({
|
||||
prefix: 'singleContextMenuPopover',
|
||||
});
|
||||
|
||||
const onButtonClick = () => {
|
||||
setPopover(!isPopoverOpen);
|
||||
};
|
||||
|
||||
const closePopover = () => {
|
||||
setPopover(false);
|
||||
};
|
||||
|
||||
const button = (
|
||||
<EuiButtonEmpty size="xs" iconType="arrowDown" iconSide="right" onClick={onButtonClick}>
|
||||
{sortField}
|
||||
</EuiButtonEmpty>
|
||||
);
|
||||
|
||||
const items = [
|
||||
<EuiPanel paddingSize="s" hasShadow={false}>
|
||||
<EuiText size="xs">
|
||||
<h4>{SORT_BY_TITLE}</h4>
|
||||
</EuiText>
|
||||
</EuiPanel>,
|
||||
...sortOptions.map((option) => (
|
||||
<ContextMenuItem option={option} onClosePopover={closePopover} />
|
||||
)),
|
||||
<EuiHorizontalRule key="hr" margin="none" />,
|
||||
|
||||
<EuiPanel paddingSize="s" hasShadow={false}>
|
||||
<EuiText size="xs">
|
||||
<h4>{ORDER_BY_TITLE}</h4>
|
||||
</EuiText>
|
||||
</EuiPanel>,
|
||||
|
||||
...orderOptions.map((option) => (
|
||||
<ContextMenuItem option={option} onClosePopover={closePopover} />
|
||||
)),
|
||||
];
|
||||
|
||||
return (
|
||||
<EuiPopover
|
||||
id={singleContextMenuPopoverId}
|
||||
button={button}
|
||||
isOpen={isPopoverOpen}
|
||||
closePopover={closePopover}
|
||||
panelPaddingSize="none"
|
||||
anchorPosition="downLeft"
|
||||
>
|
||||
<EuiContextMenuPanel size="s" items={items} />
|
||||
</EuiPopover>
|
||||
);
|
||||
};
|
||||
|
||||
const ContextMenuItem = ({
|
||||
option,
|
||||
onClosePopover,
|
||||
}: {
|
||||
option: Option;
|
||||
onClosePopover: () => void;
|
||||
}) => {
|
||||
const getIconType = (checked: boolean) => {
|
||||
return checked ? 'check' : 'empty';
|
||||
};
|
||||
|
||||
return (
|
||||
<EuiContextMenuItem
|
||||
key={option.value}
|
||||
icon={getIconType(option.checked)}
|
||||
onClick={() => {
|
||||
onClosePopover();
|
||||
option.onClick();
|
||||
}}
|
||||
style={{
|
||||
marginRight: 24,
|
||||
}}
|
||||
>
|
||||
{option.label}
|
||||
</EuiContextMenuItem>
|
||||
);
|
||||
};
|
||||
|
||||
const SORT_BY_TITLE = i18n.translate('xpack.synthetics.overview.sortPopover.sortBy.title', {
|
||||
defaultMessage: 'Sort by',
|
||||
});
|
||||
|
||||
const ORDER_BY_TITLE = i18n.translate('xpack.synthetics.overview.sortPopover.orderBy.title', {
|
||||
defaultMessage: 'Order',
|
||||
});
|
|
@ -7,13 +7,13 @@
|
|||
|
||||
import React, { useEffect } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { EuiLoadingElastic, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
|
||||
import { useTrackPageview } from '@kbn/observability-plugin/public';
|
||||
import { Redirect } from 'react-router-dom';
|
||||
import { useEnablement } from '../../../hooks';
|
||||
import { useSyntheticsRefreshContext } from '../../../contexts/synthetics_refresh_context';
|
||||
import {
|
||||
fetchMonitorOverviewAction,
|
||||
quietFetchOverviewAction,
|
||||
selectOverviewState,
|
||||
selectServiceLocationsState,
|
||||
} from '../../../state';
|
||||
|
@ -34,7 +34,7 @@ export const OverviewPage: React.FC = () => {
|
|||
|
||||
const { refreshApp, lastRefresh } = useSyntheticsRefreshContext();
|
||||
|
||||
const { loading, pageState } = useSelector(selectOverviewState);
|
||||
const { pageState } = useSelector(selectOverviewState);
|
||||
const { loading: locationsLoading, locationsLoaded } = useSelector(selectServiceLocationsState);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -48,10 +48,14 @@ export const OverviewPage: React.FC = () => {
|
|||
if (!locationsLoading && !locationsLoaded) {
|
||||
dispatch(getServiceLocations());
|
||||
}
|
||||
}, [dispatch, locationsLoaded, locationsLoading, pageState]);
|
||||
}, [dispatch, locationsLoaded, locationsLoading]);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(fetchMonitorOverviewAction.get(pageState));
|
||||
}, [dispatch, pageState]);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(quietFetchOverviewAction.get(pageState));
|
||||
}, [dispatch, pageState, lastRefresh]);
|
||||
|
||||
const {
|
||||
|
@ -69,14 +73,5 @@ export const OverviewPage: React.FC = () => {
|
|||
return <Redirect to={MONITORS_ROUTE} />;
|
||||
}
|
||||
|
||||
return !loading ? (
|
||||
<OverviewGrid />
|
||||
) : (
|
||||
<EuiFlexGroup alignItems="center" justifyContent="center">
|
||||
<EuiSpacer size="xxl" />
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiLoadingElastic size="xxl" />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
return <OverviewGrid />;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { renderHook } from '@testing-library/react-hooks';
|
||||
import { useLocationNames } from './use_location_names';
|
||||
import { WrappedHelper } from '../utils/testing';
|
||||
|
||||
describe('useMonitorListFilters', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('returns map of id to name', () => {
|
||||
const WrapperWithState = ({ children }: { children: React.ReactElement }) => {
|
||||
return (
|
||||
<WrappedHelper
|
||||
state={{
|
||||
serviceLocations: {
|
||||
locationsLoaded: true,
|
||||
loading: false,
|
||||
locations: [
|
||||
{
|
||||
url: 'mockUrl',
|
||||
id: 'us_central',
|
||||
label: 'US Central',
|
||||
isServiceManaged: true,
|
||||
},
|
||||
{
|
||||
url: 'mockUrl',
|
||||
id: 'us_east',
|
||||
label: 'US East',
|
||||
isServiceManaged: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</WrappedHelper>
|
||||
);
|
||||
};
|
||||
|
||||
const { result } = renderHook(() => useLocationNames(), { wrapper: WrapperWithState });
|
||||
expect(result.current).toEqual({
|
||||
us_central: 'US Central',
|
||||
us_east: 'US East',
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { useMemo, useEffect } from 'react';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { selectServiceLocationsState, getServiceLocations } from '../state';
|
||||
|
||||
export function useLocationNames() {
|
||||
const dispatch = useDispatch();
|
||||
const { locationsLoaded, locations } = useSelector(selectServiceLocationsState);
|
||||
useEffect(() => {
|
||||
if (!locationsLoaded) {
|
||||
dispatch(getServiceLocations());
|
||||
}
|
||||
});
|
||||
|
||||
return useMemo(
|
||||
() =>
|
||||
locations.reduce<Record<string, string>>((acc, location) => {
|
||||
acc[location.id] = location.label;
|
||||
return acc;
|
||||
}, {}),
|
||||
[locations]
|
||||
);
|
||||
}
|
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { renderHook } from '@testing-library/react-hooks';
|
||||
import { useMonitorsSortedByStatus } from './use_monitors_sorted_by_status';
|
||||
import { WrappedHelper } from '../utils/testing';
|
||||
|
||||
describe('useMonitorsSortedByStatus', () => {
|
||||
const location1 = {
|
||||
url: 'mockUrl',
|
||||
id: 'us_central',
|
||||
label: 'US Central',
|
||||
isServiceManaged: true,
|
||||
};
|
||||
|
||||
const location2 = {
|
||||
url: 'mockUrl',
|
||||
id: 'us_east',
|
||||
label: 'US East',
|
||||
isServiceManaged: true,
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
const WrapperWithState = ({
|
||||
children,
|
||||
sortOrder = 'asc',
|
||||
}: {
|
||||
children: React.ReactElement;
|
||||
sortOrder: 'asc' | 'desc';
|
||||
}) => {
|
||||
return (
|
||||
<WrappedHelper
|
||||
state={{
|
||||
serviceLocations: {
|
||||
locationsLoaded: true,
|
||||
loading: false,
|
||||
locations: [location1, location2],
|
||||
},
|
||||
overview: {
|
||||
pageState: {
|
||||
perPage: 10,
|
||||
sortOrder,
|
||||
sortField: 'name.keyword',
|
||||
},
|
||||
status: {
|
||||
upConfigs: [
|
||||
{
|
||||
configId: 'test-monitor-1',
|
||||
heartbeatId: 'test-monitor-1',
|
||||
location: location2.label,
|
||||
},
|
||||
{
|
||||
configId: 'test-monitor-2',
|
||||
heartbeatId: 'test-monitor-2',
|
||||
location: location2.label,
|
||||
},
|
||||
{
|
||||
configId: 'test-monitor-3',
|
||||
heartbeatId: 'test-monitor-3',
|
||||
location: location2.label,
|
||||
},
|
||||
],
|
||||
downConfigs: [
|
||||
{
|
||||
configId: 'test-monitor-1',
|
||||
heartbeatId: 'test-monitor-1',
|
||||
location: location1.label,
|
||||
},
|
||||
{
|
||||
configId: 'test-monitor-2',
|
||||
heartbeatId: 'test-monitor-2',
|
||||
location: location1.label,
|
||||
},
|
||||
{
|
||||
configId: 'test-monitor-3',
|
||||
heartbeatId: 'test-monitor-3',
|
||||
location: location1.label,
|
||||
},
|
||||
],
|
||||
},
|
||||
data: {
|
||||
total: 0,
|
||||
allMonitorIds: [],
|
||||
monitors: [
|
||||
{
|
||||
id: 'test-monitor-1',
|
||||
name: 'Test monitor 1',
|
||||
location: location1,
|
||||
isEnabled: false,
|
||||
},
|
||||
{
|
||||
id: 'test-monitor-1',
|
||||
name: 'Test monitor 1',
|
||||
location: location2,
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: 'test-monitor-2',
|
||||
name: 'Test monitor 2',
|
||||
location: location1,
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: 'test-monitor-2',
|
||||
name: 'Test monitor 2',
|
||||
location: location2,
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: 'test-monitor-3',
|
||||
name: 'Test monitor 3',
|
||||
location: location1,
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: 'test-monitor-3',
|
||||
name: 'Test monitor 3',
|
||||
location: location2,
|
||||
isEnabled: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
error: null,
|
||||
loaded: false,
|
||||
loading: false,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</WrappedHelper>
|
||||
);
|
||||
};
|
||||
|
||||
it('returns monitors down first when sort order is asc', () => {
|
||||
const { result } = renderHook(() => useMonitorsSortedByStatus(true), {
|
||||
wrapper: WrapperWithState,
|
||||
});
|
||||
expect(result.current).toEqual({
|
||||
monitorsSortedByStatus: [
|
||||
{
|
||||
id: 'test-monitor-2',
|
||||
name: 'Test monitor 2',
|
||||
location: location1,
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: 'test-monitor-3',
|
||||
name: 'Test monitor 3',
|
||||
location: location1,
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: 'test-monitor-1',
|
||||
name: 'Test monitor 1',
|
||||
location: location2,
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: 'test-monitor-2',
|
||||
name: 'Test monitor 2',
|
||||
location: location2,
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: 'test-monitor-3',
|
||||
name: 'Test monitor 3',
|
||||
location: location2,
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: 'test-monitor-1',
|
||||
name: 'Test monitor 1',
|
||||
location: location1,
|
||||
isEnabled: false,
|
||||
},
|
||||
],
|
||||
downMonitors: {
|
||||
'test-monitor-1': ['US Central'],
|
||||
'test-monitor-2': ['US Central'],
|
||||
'test-monitor-3': ['US Central'],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('returns monitors up first when sort order is desc', () => {
|
||||
const { result } = renderHook(() => useMonitorsSortedByStatus(true), {
|
||||
wrapper: ({ children }: { children: React.ReactElement }) => (
|
||||
<WrapperWithState sortOrder="desc">{children}</WrapperWithState>
|
||||
),
|
||||
});
|
||||
expect(result.current).toEqual({
|
||||
monitorsSortedByStatus: [
|
||||
{
|
||||
id: 'test-monitor-1',
|
||||
name: 'Test monitor 1',
|
||||
location: location2,
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: 'test-monitor-2',
|
||||
name: 'Test monitor 2',
|
||||
location: location2,
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: 'test-monitor-3',
|
||||
name: 'Test monitor 3',
|
||||
location: location2,
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: 'test-monitor-2',
|
||||
name: 'Test monitor 2',
|
||||
location: location1,
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: 'test-monitor-3',
|
||||
name: 'Test monitor 3',
|
||||
location: location1,
|
||||
isEnabled: true,
|
||||
},
|
||||
{
|
||||
id: 'test-monitor-1',
|
||||
name: 'Test monitor 1',
|
||||
location: location1,
|
||||
isEnabled: false,
|
||||
},
|
||||
],
|
||||
downMonitors: {
|
||||
'test-monitor-1': ['US Central'],
|
||||
'test-monitor-2': ['US Central'],
|
||||
'test-monitor-3': ['US Central'],
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { useEffect, useMemo, useState, useRef } from 'react';
|
||||
import { isEqual } from 'lodash';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { MonitorOverviewItem } from '../../../../common/runtime_types';
|
||||
import { selectOverviewState } from '../state/overview';
|
||||
import { useLocationNames } from './use_location_names';
|
||||
|
||||
export function useMonitorsSortedByStatus(shouldUpdate: boolean) {
|
||||
const {
|
||||
pageState: { sortOrder },
|
||||
data: { monitors },
|
||||
status,
|
||||
} = useSelector(selectOverviewState);
|
||||
const [monitorsSortedByStatus, setMonitorsSortedByStatus] = useState<
|
||||
Record<string, MonitorOverviewItem[]>
|
||||
>({ up: [], down: [], disabled: [] });
|
||||
const downMonitors = useRef<Record<string, string[]> | null>(null);
|
||||
const currentMonitors = useRef<MonitorOverviewItem[] | null>(monitors);
|
||||
const locationNames = useLocationNames();
|
||||
|
||||
useEffect(() => {
|
||||
if (!status) {
|
||||
return;
|
||||
}
|
||||
const { downConfigs } = status;
|
||||
const downMonitorMap: Record<string, string[]> = {};
|
||||
downConfigs.forEach(({ location, configId }) => {
|
||||
if (downMonitorMap[configId]) {
|
||||
downMonitorMap[configId].push(location);
|
||||
} else {
|
||||
downMonitorMap[configId] = [location];
|
||||
}
|
||||
});
|
||||
|
||||
if (
|
||||
!isEqual(downMonitorMap, downMonitors.current) ||
|
||||
!isEqual(monitors, currentMonitors.current)
|
||||
) {
|
||||
const orderedDownMonitors: MonitorOverviewItem[] = [];
|
||||
const orderedUpMonitors: MonitorOverviewItem[] = [];
|
||||
const orderedDisabledMonitors: MonitorOverviewItem[] = [];
|
||||
monitors.forEach((monitor) => {
|
||||
const monitorLocation = locationNames[monitor.location.id];
|
||||
if (!monitor.isEnabled) {
|
||||
orderedDisabledMonitors.push(monitor);
|
||||
} else if (
|
||||
Object.keys(downMonitorMap).includes(monitor.id) &&
|
||||
downMonitorMap[monitor.id].includes(monitorLocation)
|
||||
) {
|
||||
orderedDownMonitors.push(monitor);
|
||||
} else {
|
||||
orderedUpMonitors.push(monitor);
|
||||
}
|
||||
});
|
||||
downMonitors.current = downMonitorMap;
|
||||
currentMonitors.current = monitors;
|
||||
setMonitorsSortedByStatus({
|
||||
down: orderedDownMonitors,
|
||||
up: orderedUpMonitors,
|
||||
disabled: orderedDisabledMonitors,
|
||||
});
|
||||
}
|
||||
}, [monitors, locationNames, downMonitors, status]);
|
||||
|
||||
return useMemo(() => {
|
||||
const upAndDownMonitors =
|
||||
sortOrder === 'asc'
|
||||
? [...monitorsSortedByStatus.down, ...monitorsSortedByStatus.up]
|
||||
: [...monitorsSortedByStatus.up, ...monitorsSortedByStatus.down];
|
||||
|
||||
return {
|
||||
monitorsSortedByStatus: [...upAndDownMonitors, ...monitorsSortedByStatus.disabled],
|
||||
downMonitors: downMonitors.current,
|
||||
};
|
||||
}, [downMonitors, monitorsSortedByStatus, sortOrder]);
|
||||
}
|
|
@ -148,7 +148,7 @@ const getRoutes = (
|
|||
values: { baseTitle },
|
||||
}),
|
||||
path: OVERVIEW_ROUTE,
|
||||
component: () => <OverviewPage />,
|
||||
component: OverviewPage,
|
||||
dataTestSubj: 'syntheticsOverviewPage',
|
||||
pageHeader: {
|
||||
pageTitle: (
|
||||
|
|
|
@ -15,7 +15,9 @@ export const fetchMonitorOverviewAction = createAsyncAction<
|
|||
MonitorOverviewResult
|
||||
>('fetchMonitorOverviewAction');
|
||||
|
||||
export const setOverviewPerPageAction = createAction<number>('setOverviewPerPageAction');
|
||||
export const setOverviewPageStateAction = createAction<Partial<MonitorOverviewPageState>>(
|
||||
'setOverviewPageStateAction'
|
||||
);
|
||||
|
||||
export const quietFetchOverviewAction = createAsyncAction<
|
||||
MonitorOverviewPageState,
|
||||
|
|
|
@ -21,7 +21,7 @@ export const fetchMonitorOverview = async (
|
|||
): Promise<MonitorOverviewResult> => {
|
||||
return await apiService.get(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_OVERVIEW,
|
||||
{ perPage: pageState.perPage },
|
||||
{ perPage: pageState.perPage, sortOrder: pageState.sortOrder, sortField: pageState.sortField },
|
||||
MonitorOverviewResultCodec
|
||||
);
|
||||
};
|
||||
|
|
|
@ -17,7 +17,7 @@ import { fetchMonitorOverview, fetchOverviewStatus } from './api';
|
|||
|
||||
export function* fetchMonitorOverviewEffect() {
|
||||
yield takeLeading(
|
||||
fetchMonitorOverviewAction.get,
|
||||
[fetchMonitorOverviewAction.get, quietFetchOverviewAction.get],
|
||||
fetchEffectFactory(
|
||||
fetchMonitorOverview,
|
||||
fetchMonitorOverviewAction.success,
|
||||
|
@ -26,17 +26,6 @@ export function* fetchMonitorOverviewEffect() {
|
|||
);
|
||||
}
|
||||
|
||||
export function* quietFetchOverviewEffect() {
|
||||
yield takeLeading(
|
||||
quietFetchOverviewAction.get,
|
||||
fetchEffectFactory(
|
||||
fetchMonitorOverview,
|
||||
quietFetchOverviewAction.success,
|
||||
quietFetchOverviewAction.fail
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export function* fetchOverviewStatusEffect() {
|
||||
yield takeLatest(
|
||||
[fetchOverviewStatusAction.get, fetchUpsertSuccessAction],
|
||||
|
|
|
@ -17,7 +17,7 @@ import {
|
|||
fetchMonitorOverviewAction,
|
||||
fetchOverviewStatusAction,
|
||||
quietFetchOverviewAction,
|
||||
setOverviewPerPageAction,
|
||||
setOverviewPageStateAction,
|
||||
} from './actions';
|
||||
|
||||
export interface MonitorOverviewState {
|
||||
|
@ -34,10 +34,12 @@ const initialState: MonitorOverviewState = {
|
|||
data: {
|
||||
total: 0,
|
||||
allMonitorIds: [],
|
||||
pages: {},
|
||||
monitors: [],
|
||||
},
|
||||
pageState: {
|
||||
perPage: 20,
|
||||
perPage: 16,
|
||||
sortOrder: 'asc',
|
||||
sortField: 'status',
|
||||
},
|
||||
loading: false,
|
||||
loaded: false,
|
||||
|
@ -68,10 +70,10 @@ export const monitorOverviewReducer = createReducer(initialState, (builder) => {
|
|||
.addCase(quietFetchOverviewAction.fail, (state, action) => {
|
||||
state.error = action.payload;
|
||||
})
|
||||
.addCase(setOverviewPerPageAction, (state, action) => {
|
||||
.addCase(setOverviewPageStateAction, (state, action) => {
|
||||
state.pageState = {
|
||||
...state.pageState,
|
||||
perPage: action.payload,
|
||||
...action.payload,
|
||||
};
|
||||
state.loaded = false;
|
||||
})
|
||||
|
|
|
@ -7,4 +7,6 @@
|
|||
|
||||
export interface MonitorOverviewPageState {
|
||||
perPage: number;
|
||||
sortOrder: 'asc' | 'desc';
|
||||
sortField: string;
|
||||
}
|
||||
|
|
|
@ -11,11 +11,7 @@ import { fetchSyntheticsMonitorEffect } from './monitor_details';
|
|||
import { fetchIndexStatusEffect } from './index_status';
|
||||
import { fetchSyntheticsEnablementEffect } from './synthetics_enablement';
|
||||
import { fetchMonitorListEffect, upsertMonitorEffect } from './monitor_list';
|
||||
import {
|
||||
fetchMonitorOverviewEffect,
|
||||
quietFetchOverviewEffect,
|
||||
fetchOverviewStatusEffect,
|
||||
} from './overview';
|
||||
import { fetchMonitorOverviewEffect, fetchOverviewStatusEffect } from './overview';
|
||||
import { fetchServiceLocationsEffect } from './service_locations';
|
||||
import { browserJourneyEffects } from './browser_journey';
|
||||
|
||||
|
@ -28,7 +24,6 @@ export const rootEffect = function* root(): Generator {
|
|||
fork(fetchMonitorListEffect),
|
||||
fork(fetchSyntheticsMonitorEffect),
|
||||
fork(fetchMonitorOverviewEffect),
|
||||
fork(quietFetchOverviewEffect),
|
||||
fork(browserJourneyEffects),
|
||||
fork(fetchOverviewStatusEffect),
|
||||
fork(fetchNetworkEventsEffect),
|
||||
|
|
|
@ -87,11 +87,13 @@ export const mockState: SyntheticsAppState = {
|
|||
overview: {
|
||||
pageState: {
|
||||
perPage: 10,
|
||||
sortOrder: 'asc',
|
||||
sortField: 'name.keyword',
|
||||
},
|
||||
data: {
|
||||
total: 0,
|
||||
allMonitorIds: [],
|
||||
pages: {},
|
||||
monitors: [],
|
||||
},
|
||||
error: null,
|
||||
loaded: false,
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { SavedObjectsErrorHelpers } from '@kbn/core/server';
|
||||
import { ConfigKey } from '../../../common/runtime_types';
|
||||
import { ConfigKey, MonitorOverviewItem, SyntheticsMonitor } from '../../../common/runtime_types';
|
||||
import { UMServerLibs } from '../../legacy_uptime/lib/lib';
|
||||
import { SyntheticsRestApiRouteFactory } from '../../legacy_uptime/routes/types';
|
||||
import { API_URLS, SYNTHETICS_API_URLS } from '../../../common/constants';
|
||||
|
@ -112,55 +112,42 @@ export const getSyntheticsMonitorOverviewRoute: SyntheticsRestApiRouteFactory =
|
|||
query: querySchema,
|
||||
},
|
||||
handler: async ({ request, savedObjectsClient, syntheticsMonitorClient }): Promise<any> => {
|
||||
const { perPage = 5 } = request.query;
|
||||
const { saved_objects: monitors } = await getMonitors(
|
||||
{
|
||||
perPage: 1000,
|
||||
sortField: 'name.keyword',
|
||||
sortOrder: 'asc',
|
||||
page: 1,
|
||||
},
|
||||
syntheticsMonitorClient.syntheticsService,
|
||||
savedObjectsClient
|
||||
);
|
||||
|
||||
const allMonitorIds: string[] = [];
|
||||
const pages: Record<number, unknown[]> = {};
|
||||
let currentPage = 0;
|
||||
let currentItem = 0;
|
||||
let total = 0;
|
||||
|
||||
monitors.forEach((monitor) => {
|
||||
/* collect all monitor ids for use
|
||||
* in filtering overview requests */
|
||||
const id = monitor.id;
|
||||
allMonitorIds.push(id);
|
||||
|
||||
/* for reach location, add a config item */
|
||||
const locations = monitor.attributes[ConfigKey.LOCATIONS];
|
||||
locations.forEach((location) => {
|
||||
const config = {
|
||||
id,
|
||||
name: monitor.attributes[ConfigKey.NAME],
|
||||
location,
|
||||
isEnabled: monitor.attributes[ConfigKey.ENABLED],
|
||||
};
|
||||
if (!pages[currentPage]) {
|
||||
pages[currentPage] = [config];
|
||||
} else {
|
||||
pages[currentPage].push(config);
|
||||
}
|
||||
currentItem++;
|
||||
total++;
|
||||
if (currentItem % perPage === 0) {
|
||||
currentPage++;
|
||||
currentItem = 0;
|
||||
}
|
||||
});
|
||||
const { sortField, sortOrder } = request.query;
|
||||
const finder = savedObjectsClient.createPointInTimeFinder<SyntheticsMonitor>({
|
||||
type: syntheticsMonitorType,
|
||||
sortField: sortField === 'status' ? `${ConfigKey.NAME}.keyword` : sortField,
|
||||
sortOrder,
|
||||
perPage: 500,
|
||||
});
|
||||
|
||||
const allMonitorIds: string[] = [];
|
||||
let total = 0;
|
||||
const allMonitors: MonitorOverviewItem[] = [];
|
||||
|
||||
for await (const result of finder.find()) {
|
||||
/* collect all monitor ids for use
|
||||
* in filtering overview requests */
|
||||
result.saved_objects.forEach((monitor) => {
|
||||
const id = monitor.id;
|
||||
allMonitorIds.push(id);
|
||||
|
||||
/* for reach location, add a config item */
|
||||
const locations = monitor.attributes[ConfigKey.LOCATIONS];
|
||||
locations.forEach((location) => {
|
||||
const config = {
|
||||
id,
|
||||
name: monitor.attributes[ConfigKey.NAME],
|
||||
location,
|
||||
isEnabled: monitor.attributes[ConfigKey.ENABLED],
|
||||
};
|
||||
allMonitors.push(config);
|
||||
total++;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
pages,
|
||||
monitors: allMonitors,
|
||||
total,
|
||||
allMonitorIds,
|
||||
};
|
||||
|
|
|
@ -78,11 +78,18 @@ describe('current status route', () => {
|
|||
'@timestamp': '2022-09-15T16:08:16.724Z',
|
||||
monitor: {
|
||||
status: 'up',
|
||||
id: 'id1',
|
||||
},
|
||||
summary: {
|
||||
up: 1,
|
||||
down: 0,
|
||||
},
|
||||
config_id: 'id1',
|
||||
observer: {
|
||||
geo: {
|
||||
name: 'test-location',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
|
@ -106,11 +113,18 @@ describe('current status route', () => {
|
|||
'@timestamp': '2022-09-15T16:09:16.724Z',
|
||||
monitor: {
|
||||
status: 'up',
|
||||
id: 'id2',
|
||||
},
|
||||
summary: {
|
||||
up: 1,
|
||||
down: 0,
|
||||
},
|
||||
config_id: 'id2',
|
||||
observer: {
|
||||
geo: {
|
||||
name: 'test-location',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
|
@ -127,11 +141,18 @@ describe('current status route', () => {
|
|||
'@timestamp': '2022-09-15T16:19:16.724Z',
|
||||
monitor: {
|
||||
status: 'down',
|
||||
id: 'id2',
|
||||
},
|
||||
summary: {
|
||||
down: 1,
|
||||
up: 0,
|
||||
},
|
||||
config_id: 'id2',
|
||||
observer: {
|
||||
geo: {
|
||||
name: 'test-location',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
|
@ -146,6 +167,25 @@ describe('current status route', () => {
|
|||
expect(await queryMonitorStatus(uptimeEsClient, 3, 140000, ['id1', 'id2'])).toEqual({
|
||||
down: 1,
|
||||
up: 2,
|
||||
upConfigs: [
|
||||
{
|
||||
configId: 'id1',
|
||||
heartbeatId: 'id1',
|
||||
location: 'test-location',
|
||||
},
|
||||
{
|
||||
configId: 'id2',
|
||||
heartbeatId: 'id2',
|
||||
location: 'test-location',
|
||||
},
|
||||
],
|
||||
downConfigs: [
|
||||
{
|
||||
configId: 'id2',
|
||||
heartbeatId: 'id2',
|
||||
location: 'test-location',
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -167,11 +207,18 @@ describe('current status route', () => {
|
|||
'@timestamp': '2022-09-15T16:08:16.724Z',
|
||||
monitor: {
|
||||
status: 'up',
|
||||
id: 'id1',
|
||||
},
|
||||
summary: {
|
||||
up: 1,
|
||||
down: 0,
|
||||
},
|
||||
config_id: 'id1',
|
||||
observer: {
|
||||
geo: {
|
||||
name: 'test-location',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
|
@ -195,11 +242,18 @@ describe('current status route', () => {
|
|||
'@timestamp': '2022-09-15T16:09:16.724Z',
|
||||
monitor: {
|
||||
status: 'up',
|
||||
id: 'id2',
|
||||
},
|
||||
summary: {
|
||||
up: 1,
|
||||
down: 0,
|
||||
},
|
||||
config_id: 'id2',
|
||||
observer: {
|
||||
geo: {
|
||||
name: 'test-location',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
|
@ -216,11 +270,18 @@ describe('current status route', () => {
|
|||
'@timestamp': '2022-09-15T16:19:16.724Z',
|
||||
monitor: {
|
||||
status: 'down',
|
||||
id: 'id2',
|
||||
},
|
||||
summary: {
|
||||
up: 0,
|
||||
down: 1,
|
||||
},
|
||||
config_id: 'id2',
|
||||
observer: {
|
||||
geo: {
|
||||
name: 'test-location',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
|
@ -242,6 +303,25 @@ describe('current status route', () => {
|
|||
expect(await queryMonitorStatus(uptimeEsClient, 10000, 2500, ['id1', 'id2'])).toEqual({
|
||||
down: 1,
|
||||
up: 2,
|
||||
upConfigs: [
|
||||
{
|
||||
configId: 'id1',
|
||||
heartbeatId: 'id1',
|
||||
location: 'test-location',
|
||||
},
|
||||
{
|
||||
configId: 'id2',
|
||||
heartbeatId: 'id2',
|
||||
location: 'test-location',
|
||||
},
|
||||
],
|
||||
downConfigs: [
|
||||
{
|
||||
configId: 'id2',
|
||||
heartbeatId: 'id2',
|
||||
location: 'test-location',
|
||||
},
|
||||
],
|
||||
});
|
||||
expect(esClient.search).toHaveBeenCalledTimes(2);
|
||||
// These assertions are to ensure that we are paginating through the IDs we use for filtering
|
||||
|
|
|
@ -15,7 +15,7 @@ import { SyntheticsRestApiRouteFactory } from '../../legacy_uptime/routes';
|
|||
import { getMonitors } from '../common';
|
||||
import { UptimeEsClient } from '../../legacy_uptime/lib/lib';
|
||||
import { SyntheticsMonitorClient } from '../../synthetics_service/synthetics_monitor/synthetics_monitor_client';
|
||||
import { ConfigKey, OverviewStatus } from '../../../common/runtime_types';
|
||||
import { ConfigKey, OverviewStatus, OverviewStatusMetaData } from '../../../common/runtime_types';
|
||||
|
||||
/**
|
||||
* Helper function that converts a monitor's schedule to a value to use to generate
|
||||
|
@ -36,7 +36,7 @@ export async function queryMonitorStatus(
|
|||
maxLocations: number,
|
||||
maxPeriod: number,
|
||||
ids: Array<string | undefined>
|
||||
): Promise<Pick<OverviewStatus, 'up' | 'down'>> {
|
||||
): Promise<Omit<OverviewStatus, 'disabledCount'>> {
|
||||
const idSize = Math.trunc(DEFAULT_MAX_ES_BUCKET_SIZE / maxLocations);
|
||||
const pageCount = Math.ceil(ids.length / idSize);
|
||||
const promises: Array<Promise<any>> = [];
|
||||
|
@ -92,7 +92,7 @@ export async function queryMonitorStatus(
|
|||
},
|
||||
],
|
||||
_source: {
|
||||
includes: ['@timestamp', 'summary'],
|
||||
includes: ['@timestamp', 'summary', 'monitor', 'observer', 'config_id'],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -107,20 +107,35 @@ export async function queryMonitorStatus(
|
|||
}
|
||||
let up = 0;
|
||||
let down = 0;
|
||||
const upConfigs: OverviewStatusMetaData[] = [];
|
||||
const downConfigs: OverviewStatusMetaData[] = [];
|
||||
for await (const response of promises) {
|
||||
response.aggregations?.id.buckets.forEach(({ location }: { key: string; location: any }) => {
|
||||
location.buckets.forEach(({ status }: { key: string; status: any }) => {
|
||||
const downCount = status.hits.hits[0]._source.summary.down;
|
||||
const upCount = status.hits.hits[0]._source.summary.up;
|
||||
const configId = status.hits.hits[0]._source.config_id;
|
||||
const heartbeatId = status.hits.hits[0]._source.monitor.id;
|
||||
const locationName = status.hits.hits[0]._source.observer?.geo?.name;
|
||||
if (upCount > 0) {
|
||||
up += 1;
|
||||
upConfigs.push({
|
||||
configId,
|
||||
heartbeatId,
|
||||
location: locationName,
|
||||
});
|
||||
} else if (downCount > 0) {
|
||||
down += 1;
|
||||
downConfigs.push({
|
||||
configId,
|
||||
heartbeatId,
|
||||
location: locationName,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
return { up, down };
|
||||
return { up, down, upConfigs, downConfigs };
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -169,7 +184,7 @@ export async function getStatus(
|
|||
});
|
||||
} while (monitors.saved_objects.length === monitors.per_page);
|
||||
|
||||
const { up, down } = await queryMonitorStatus(
|
||||
const { up, down, upConfigs, downConfigs } = await queryMonitorStatus(
|
||||
uptimeEsClient,
|
||||
maxLocations,
|
||||
maxPeriod,
|
||||
|
@ -180,6 +195,8 @@ export async function getStatus(
|
|||
disabledCount,
|
||||
up,
|
||||
down,
|
||||
upConfigs,
|
||||
downConfigs,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -31216,7 +31216,6 @@
|
|||
"xpack.synthetics.overview.heading": "Moniteurs",
|
||||
"xpack.synthetics.overview.monitors.label": "Moniteurs",
|
||||
"xpack.synthetics.overview.pageHeader.title": "Aperçu",
|
||||
"xpack.synthetics.overview.pagination.ariaLabel": "Pagination pour l’aperçu du moniteur",
|
||||
"xpack.synthetics.overviewPage.overviewCrumb": "Aperçu",
|
||||
"xpack.synthetics.overviewPageLink.disabled.ariaLabel": "Bouton de pagination désactivé indiquant qu'aucune autre navigation ne peut être effectuée dans la liste des moniteurs.",
|
||||
"xpack.synthetics.overviewPageLink.next.ariaLabel": "Page de résultats suivante",
|
||||
|
|
|
@ -31192,7 +31192,6 @@
|
|||
"xpack.synthetics.overview.heading": "監視",
|
||||
"xpack.synthetics.overview.monitors.label": "監視",
|
||||
"xpack.synthetics.overview.pageHeader.title": "概要",
|
||||
"xpack.synthetics.overview.pagination.ariaLabel": "監視概要のページネーション",
|
||||
"xpack.synthetics.overviewPage.overviewCrumb": "概要",
|
||||
"xpack.synthetics.overviewPageLink.disabled.ariaLabel": "無効になったページ付けボタンです。モニターリストがこれ以上ナビゲーションできないことを示しています。",
|
||||
"xpack.synthetics.overviewPageLink.next.ariaLabel": "次の結果ページ",
|
||||
|
|
|
@ -31227,7 +31227,6 @@
|
|||
"xpack.synthetics.overview.heading": "监测",
|
||||
"xpack.synthetics.overview.monitors.label": "监测",
|
||||
"xpack.synthetics.overview.pageHeader.title": "概览",
|
||||
"xpack.synthetics.overview.pagination.ariaLabel": "监测概述的分页",
|
||||
"xpack.synthetics.overviewPage.overviewCrumb": "概览",
|
||||
"xpack.synthetics.overviewPageLink.disabled.ariaLabel": "禁用的分页按钮表示在监测列表中无法进行进一步导航。",
|
||||
"xpack.synthetics.overviewPageLink.next.ariaLabel": "下页结果",
|
||||
|
|
|
@ -82,33 +82,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
expect(apiResponse.body.allMonitorIds.sort()).eql(
|
||||
savedMonitors.map((monitor) => monitor.id).sort()
|
||||
);
|
||||
expect(apiResponse.body.pages).to.have.keys(['0', '1']);
|
||||
expect(apiResponse.body.pages[1].length).eql(20);
|
||||
} finally {
|
||||
await Promise.all(
|
||||
savedMonitors.map((monitor) => {
|
||||
return deleteMonitor(monitor.id);
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('adjusts pagination correctly', async () => {
|
||||
let savedMonitors: SimpleSavedObject[] = [];
|
||||
try {
|
||||
const savedResponse = await Promise.all(monitors.map(saveMonitor));
|
||||
savedMonitors = savedResponse;
|
||||
|
||||
const apiResponse = await supertest.get(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_OVERVIEW + '?perPage=5'
|
||||
);
|
||||
|
||||
expect(apiResponse.body.total).eql(monitors.length * 2);
|
||||
expect(apiResponse.body.allMonitorIds.sort()).eql(
|
||||
savedMonitors.map((monitor) => monitor.id).sort()
|
||||
);
|
||||
expect(apiResponse.body.pages).to.have.keys(['0', '1', '2', '3', '4']);
|
||||
expect(apiResponse.body.pages[1].length).eql(5);
|
||||
expect(apiResponse.body.monitors.length).eql(40);
|
||||
} finally {
|
||||
await Promise.all(
|
||||
savedMonitors.map((monitor) => {
|
||||
|
|
523
yarn.lock
523
yarn.lock
|
@ -1297,17 +1297,12 @@
|
|||
resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
|
||||
integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==
|
||||
|
||||
"@cspotcode/source-map-consumer@0.8.0":
|
||||
version "0.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b"
|
||||
integrity sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==
|
||||
|
||||
"@cspotcode/source-map-support@0.7.0":
|
||||
version "0.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz#4789840aa859e46d2f3173727ab707c66bf344f5"
|
||||
integrity sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==
|
||||
"@cspotcode/source-map-support@^0.8.0", "@cspotcode/source-map-support@^0.8.1":
|
||||
version "0.8.1"
|
||||
resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1"
|
||||
integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==
|
||||
dependencies:
|
||||
"@cspotcode/source-map-consumer" "0.8.0"
|
||||
"@jridgewell/trace-mapping" "0.3.9"
|
||||
|
||||
"@csstools/selector-specificity@^2.0.1":
|
||||
version "2.0.1"
|
||||
|
@ -1658,24 +1653,31 @@
|
|||
history "^4.9.0"
|
||||
qs "^6.7.0"
|
||||
|
||||
"@elastic/synthetics@^1.0.0-beta.22":
|
||||
version "1.0.0-beta.22"
|
||||
resolved "https://registry.yarnpkg.com/@elastic/synthetics/-/synthetics-1.0.0-beta.22.tgz#1ec60e212e925ffaf7fd63619858ad6ce6dfa85d"
|
||||
integrity sha512-hDFPqBuY30naAZct8UNRMhKNtsVbPV5nYApkwRf/7y3/SgQBXPnMkxUBlxy+2vkPR4QnKusvWROUxMMwgVnXyA==
|
||||
"@elastic/synthetics@^1.0.0-beta.23":
|
||||
version "1.0.0-beta.37"
|
||||
resolved "https://registry.yarnpkg.com/@elastic/synthetics/-/synthetics-1.0.0-beta.37.tgz#ba89918107c7aa166bcf43bbd0cbe4ad6a3b4430"
|
||||
integrity sha512-MSYu+n4SuZ31AbxWpha5WBS33Y/YTVEvOc8g3WkCIxSqa8iSAPgGEAOZimk/pHOzPZNXJcRKIpL01HnKvqd14g==
|
||||
dependencies:
|
||||
commander "^9.0.0"
|
||||
"@cspotcode/source-map-support" "^0.8.1"
|
||||
"@esbuild-plugins/node-resolve" "^0.1.4"
|
||||
archiver "^5.3.1"
|
||||
commander "^9.4.0"
|
||||
deepmerge "^4.2.2"
|
||||
expect "^27.0.2"
|
||||
enquirer "^2.3.6"
|
||||
esbuild "^0.14.54"
|
||||
expect "^28.1.3"
|
||||
http-proxy "^1.18.1"
|
||||
kleur "^4.1.4"
|
||||
micromatch "^4.0.4"
|
||||
playwright-chromium "=1.14.0"
|
||||
sharp "^0.30.1"
|
||||
snakecase-keys "^3.2.1"
|
||||
sonic-boom "^2.6.0"
|
||||
source-map-support "^0.5.21"
|
||||
ts-node "^10.5.0"
|
||||
typescript "^4.5.5"
|
||||
kleur "^4.1.5"
|
||||
micromatch "^4.0.5"
|
||||
playwright-chromium "=1.26.0"
|
||||
playwright-core "=1.26.0"
|
||||
sharp "^0.31.1"
|
||||
snakecase-keys "^4.0.0"
|
||||
sonic-boom "^3.2.0"
|
||||
ts-node "^10.9.1"
|
||||
typescript "^4.8.3"
|
||||
undici "^5.10.0"
|
||||
yaml "^2.1.1"
|
||||
|
||||
"@elastic/transport@^8.2.0":
|
||||
version "8.2.0"
|
||||
|
@ -1919,6 +1921,21 @@
|
|||
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz#ea89004119dc42db2e1dba0f97d553f7372f6fcb"
|
||||
integrity sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg==
|
||||
|
||||
"@esbuild-plugins/node-resolve@^0.1.4":
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild-plugins/node-resolve/-/node-resolve-0.1.4.tgz#2257ef3b233c9cb3acd2ebde7d5a3d6874046d38"
|
||||
integrity sha512-haFQ0qhxEpqtWWY0kx1Y5oE3sMyO1PcoSiWEPrAw6tm/ZOOLXjSs6Q+v1v9eyuVF0nNt50YEvrcrvENmyoMv5g==
|
||||
dependencies:
|
||||
"@types/resolve" "^1.17.1"
|
||||
debug "^4.3.1"
|
||||
escape-string-regexp "^4.0.0"
|
||||
resolve "^1.19.0"
|
||||
|
||||
"@esbuild/linux-loong64@0.14.54":
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.14.54.tgz#de2a4be678bd4d0d1ffbb86e6de779cde5999028"
|
||||
integrity sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==
|
||||
|
||||
"@eslint/eslintrc@^0.4.3":
|
||||
version "0.4.3"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c"
|
||||
|
@ -2403,6 +2420,13 @@
|
|||
dependencies:
|
||||
jest-get-type "^28.0.2"
|
||||
|
||||
"@jest/expect-utils@^28.1.3":
|
||||
version "28.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-28.1.3.tgz#58561ce5db7cd253a7edddbc051fb39dda50f525"
|
||||
integrity sha512-wvbi9LUrHJLn3NlDW6wF2hvIMtd4JUl2QNVrjq+IBSHirgfrR3o9RnVtxzdEGO2n9JyIWwHnLfby5KzqBGg2YA==
|
||||
dependencies:
|
||||
jest-get-type "^28.0.2"
|
||||
|
||||
"@jest/fake-timers@^27.5.1":
|
||||
version "27.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.5.1.tgz#76979745ce0579c8a94a4678af7a748eda8ada74"
|
||||
|
@ -2462,6 +2486,13 @@
|
|||
dependencies:
|
||||
"@sinclair/typebox" "^0.23.3"
|
||||
|
||||
"@jest/schemas@^28.1.3":
|
||||
version "28.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-28.1.3.tgz#ad8b86a66f11f33619e3d7e1dcddd7f2d40ff905"
|
||||
integrity sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==
|
||||
dependencies:
|
||||
"@sinclair/typebox" "^0.24.1"
|
||||
|
||||
"@jest/source-map@^27.5.1":
|
||||
version "27.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.5.1.tgz#6608391e465add4205eae073b55e7f279e04e8cf"
|
||||
|
@ -2555,12 +2586,12 @@
|
|||
"@types/yargs" "^16.0.0"
|
||||
chalk "^4.0.0"
|
||||
|
||||
"@jest/types@^28.1.1":
|
||||
version "28.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@jest/types/-/types-28.1.1.tgz#d059bbc80e6da6eda9f081f293299348bd78ee0b"
|
||||
integrity sha512-vRXVqSg1VhDnB8bWcmvLzmg0Bt9CRKVgHPXqYwvWMX3TvAjeO+nRuK6+VdTKCtWOvYlmkF/HqNAL/z+N3B53Kw==
|
||||
"@jest/types@^28.1.1", "@jest/types@^28.1.3":
|
||||
version "28.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@jest/types/-/types-28.1.3.tgz#b05de80996ff12512bc5ceb1d208285a7d11748b"
|
||||
integrity sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==
|
||||
dependencies:
|
||||
"@jest/schemas" "^28.0.2"
|
||||
"@jest/schemas" "^28.1.3"
|
||||
"@types/istanbul-lib-coverage" "^2.0.0"
|
||||
"@types/istanbul-reports" "^3.0.0"
|
||||
"@types/node" "*"
|
||||
|
@ -2599,6 +2630,14 @@
|
|||
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz#771a1d8d744eeb71b6adb35808e1a6c7b9b8c8ec"
|
||||
integrity sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==
|
||||
|
||||
"@jridgewell/trace-mapping@0.3.9":
|
||||
version "0.3.9"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9"
|
||||
integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==
|
||||
dependencies:
|
||||
"@jridgewell/resolve-uri" "^3.0.3"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||
|
||||
"@jridgewell/trace-mapping@^0.3.0", "@jridgewell/trace-mapping@^0.3.14", "@jridgewell/trace-mapping@^0.3.8", "@jridgewell/trace-mapping@^0.3.9":
|
||||
version "0.3.15"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz#aba35c48a38d3fd84b37e66c9c0423f9744f9774"
|
||||
|
@ -4863,6 +4902,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.23.5.tgz#93f7b9f4e3285a7a9ade7557d9a8d36809cbc47d"
|
||||
integrity sha512-AFBVi/iT4g20DHoujvMH1aEDn8fGJh4xsRGCP6d8RpLPMqsNPvW01Jcn0QysXTsg++/xj25NmJsGyH9xug/wKg==
|
||||
|
||||
"@sinclair/typebox@^0.24.1":
|
||||
version "0.24.46"
|
||||
resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.46.tgz#57501b58023776dbbae9e25619146286440be34c"
|
||||
integrity sha512-ng4ut1z2MCBhK/NwDVwIQp3pAUOCs/KNaW3cBxdFB2xTDrOuo1xuNmpr/9HHFhxqIvHrs1NTH3KJg6q+JSy1Kw==
|
||||
|
||||
"@sindresorhus/is@^0.14.0":
|
||||
version "0.14.0"
|
||||
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea"
|
||||
|
@ -7397,7 +7441,7 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/resize-observer-browser/-/resize-observer-browser-0.1.5.tgz#36d897708172ac2380cd486da7a3daf1161c1e23"
|
||||
integrity sha512-8k/67Z95Goa6Lznuykxkfhq9YU3l1Qe6LNZmwde1u7802a3x8v44oq0j91DICclxatTr0rNnhXx7+VTIetSrSQ==
|
||||
|
||||
"@types/resolve@^1.20.1":
|
||||
"@types/resolve@^1.17.1", "@types/resolve@^1.20.1":
|
||||
version "1.20.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.20.1.tgz#3727e48042fda81e374f5d5cf2fa92288bf698f8"
|
||||
integrity sha512-Ku5+GPFa12S3W26Uwtw+xyrtIpaZsGYHH6zxNbZlstmlvMYSZRzOwzwsXbxlVUbHyUucctSyuFtu6bNxwYomIw==
|
||||
|
@ -9835,6 +9879,13 @@ builtin-status-codes@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
|
||||
integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=
|
||||
|
||||
busboy@^1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893"
|
||||
integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==
|
||||
dependencies:
|
||||
streamsearch "^1.1.0"
|
||||
|
||||
byte-size@^8.1.0:
|
||||
version "8.1.0"
|
||||
resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-8.1.0.tgz#6353d0bc14ab7a69abcefbf11f8db0145a862cb5"
|
||||
|
@ -10655,20 +10706,15 @@ commander@^5.0.0, commander@^5.1.0:
|
|||
resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
|
||||
integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==
|
||||
|
||||
commander@^6.1.0, commander@^6.2.1:
|
||||
commander@^6.2.1:
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
|
||||
integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
|
||||
|
||||
commander@^8.2.0:
|
||||
version "8.3.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
|
||||
integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
|
||||
|
||||
commander@^9.0.0:
|
||||
version "9.0.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-9.0.0.tgz#86d58f24ee98126568936bd1d3574e0308a99a40"
|
||||
integrity sha512-JJfP2saEKbQqvW+FI93OYUB4ByV5cizMpFMiiJI8xDbBvQvSkIk0VvQdn1CZ8mqAO8Loq2h0gYTYtDFUZUeERw==
|
||||
commander@^9.4.0:
|
||||
version "9.4.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-9.4.1.tgz#d1dd8f2ce6faf93147295c0df13c7c21141cfbdd"
|
||||
integrity sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==
|
||||
|
||||
common-path-prefix@^3.0.0:
|
||||
version "3.0.0"
|
||||
|
@ -12514,6 +12560,14 @@ dot-case@^3.0.3:
|
|||
no-case "^3.0.3"
|
||||
tslib "^1.10.0"
|
||||
|
||||
dot-case@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751"
|
||||
integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==
|
||||
dependencies:
|
||||
no-case "^3.0.4"
|
||||
tslib "^2.0.3"
|
||||
|
||||
dot-prop@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.2.0.tgz#c34ecc29556dc45f1f4c22697b6f4904e0cc4fcb"
|
||||
|
@ -13078,6 +13132,133 @@ es6-weak-map@^2.0.2:
|
|||
es6-iterator "^2.0.1"
|
||||
es6-symbol "^3.1.1"
|
||||
|
||||
esbuild-android-64@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.54.tgz#505f41832884313bbaffb27704b8bcaa2d8616be"
|
||||
integrity sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==
|
||||
|
||||
esbuild-android-arm64@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.54.tgz#8ce69d7caba49646e009968fe5754a21a9871771"
|
||||
integrity sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==
|
||||
|
||||
esbuild-darwin-64@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.54.tgz#24ba67b9a8cb890a3c08d9018f887cc221cdda25"
|
||||
integrity sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==
|
||||
|
||||
esbuild-darwin-arm64@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.54.tgz#3f7cdb78888ee05e488d250a2bdaab1fa671bf73"
|
||||
integrity sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==
|
||||
|
||||
esbuild-freebsd-64@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.54.tgz#09250f997a56ed4650f3e1979c905ffc40bbe94d"
|
||||
integrity sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==
|
||||
|
||||
esbuild-freebsd-arm64@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.54.tgz#bafb46ed04fc5f97cbdb016d86947a79579f8e48"
|
||||
integrity sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==
|
||||
|
||||
esbuild-linux-32@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.54.tgz#e2a8c4a8efdc355405325033fcebeb941f781fe5"
|
||||
integrity sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==
|
||||
|
||||
esbuild-linux-64@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.54.tgz#de5fdba1c95666cf72369f52b40b03be71226652"
|
||||
integrity sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==
|
||||
|
||||
esbuild-linux-arm64@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.54.tgz#dae4cd42ae9787468b6a5c158da4c84e83b0ce8b"
|
||||
integrity sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==
|
||||
|
||||
esbuild-linux-arm@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.54.tgz#a2c1dff6d0f21dbe8fc6998a122675533ddfcd59"
|
||||
integrity sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==
|
||||
|
||||
esbuild-linux-mips64le@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.54.tgz#d9918e9e4cb972f8d6dae8e8655bf9ee131eda34"
|
||||
integrity sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==
|
||||
|
||||
esbuild-linux-ppc64le@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.54.tgz#3f9a0f6d41073fb1a640680845c7de52995f137e"
|
||||
integrity sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==
|
||||
|
||||
esbuild-linux-riscv64@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.54.tgz#618853c028178a61837bc799d2013d4695e451c8"
|
||||
integrity sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==
|
||||
|
||||
esbuild-linux-s390x@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.54.tgz#d1885c4c5a76bbb5a0fe182e2c8c60eb9e29f2a6"
|
||||
integrity sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==
|
||||
|
||||
esbuild-netbsd-64@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.54.tgz#69ae917a2ff241b7df1dbf22baf04bd330349e81"
|
||||
integrity sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==
|
||||
|
||||
esbuild-openbsd-64@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.54.tgz#db4c8495287a350a6790de22edea247a57c5d47b"
|
||||
integrity sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==
|
||||
|
||||
esbuild-sunos-64@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.54.tgz#54287ee3da73d3844b721c21bc80c1dc7e1bf7da"
|
||||
integrity sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==
|
||||
|
||||
esbuild-windows-32@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.54.tgz#f8aaf9a5667630b40f0fb3aa37bf01bbd340ce31"
|
||||
integrity sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==
|
||||
|
||||
esbuild-windows-64@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.54.tgz#bf54b51bd3e9b0f1886ffdb224a4176031ea0af4"
|
||||
integrity sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==
|
||||
|
||||
esbuild-windows-arm64@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.54.tgz#937d15675a15e4b0e4fafdbaa3a01a776a2be982"
|
||||
integrity sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==
|
||||
|
||||
esbuild@^0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.54.tgz#8b44dcf2b0f1a66fc22459943dccf477535e9aa2"
|
||||
integrity sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==
|
||||
optionalDependencies:
|
||||
"@esbuild/linux-loong64" "0.14.54"
|
||||
esbuild-android-64 "0.14.54"
|
||||
esbuild-android-arm64 "0.14.54"
|
||||
esbuild-darwin-64 "0.14.54"
|
||||
esbuild-darwin-arm64 "0.14.54"
|
||||
esbuild-freebsd-64 "0.14.54"
|
||||
esbuild-freebsd-arm64 "0.14.54"
|
||||
esbuild-linux-32 "0.14.54"
|
||||
esbuild-linux-64 "0.14.54"
|
||||
esbuild-linux-arm "0.14.54"
|
||||
esbuild-linux-arm64 "0.14.54"
|
||||
esbuild-linux-mips64le "0.14.54"
|
||||
esbuild-linux-ppc64le "0.14.54"
|
||||
esbuild-linux-riscv64 "0.14.54"
|
||||
esbuild-linux-s390x "0.14.54"
|
||||
esbuild-netbsd-64 "0.14.54"
|
||||
esbuild-openbsd-64 "0.14.54"
|
||||
esbuild-sunos-64 "0.14.54"
|
||||
esbuild-windows-32 "0.14.54"
|
||||
esbuild-windows-64 "0.14.54"
|
||||
esbuild-windows-arm64 "0.14.54"
|
||||
|
||||
escalade@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
|
||||
|
@ -13647,7 +13828,7 @@ expect@^26.6.2:
|
|||
jest-message-util "^26.6.2"
|
||||
jest-regex-util "^26.0.0"
|
||||
|
||||
expect@^27.0.2, expect@^27.5.1:
|
||||
expect@^27.5.1:
|
||||
version "27.5.1"
|
||||
resolved "https://registry.yarnpkg.com/expect/-/expect-27.5.1.tgz#83ce59f1e5bdf5f9d2b94b61d2050db48f3fef74"
|
||||
integrity sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==
|
||||
|
@ -13668,6 +13849,17 @@ expect@^28.1.1:
|
|||
jest-message-util "^28.1.1"
|
||||
jest-util "^28.1.1"
|
||||
|
||||
expect@^28.1.3:
|
||||
version "28.1.3"
|
||||
resolved "https://registry.yarnpkg.com/expect/-/expect-28.1.3.tgz#90a7c1a124f1824133dd4533cce2d2bdcb6603ec"
|
||||
integrity sha512-eEh0xn8HlsuOBxFgIss+2mX85VAS4Qy3OSkjV7rlBWljtA4oWH37glVGyOZSZvErDT/yBywZdPGwCXuTvSG85g==
|
||||
dependencies:
|
||||
"@jest/expect-utils" "^28.1.3"
|
||||
jest-get-type "^28.0.2"
|
||||
jest-matcher-utils "^28.1.3"
|
||||
jest-message-util "^28.1.3"
|
||||
jest-util "^28.1.3"
|
||||
|
||||
expiry-js@0.1.7:
|
||||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/expiry-js/-/expiry-js-0.1.7.tgz#76be8c05e572bf936df40c1766448d0b3b2f555f"
|
||||
|
@ -16921,6 +17113,16 @@ jest-diff@^28.1.1:
|
|||
jest-get-type "^28.0.2"
|
||||
pretty-format "^28.1.1"
|
||||
|
||||
jest-diff@^28.1.3:
|
||||
version "28.1.3"
|
||||
resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-28.1.3.tgz#948a192d86f4e7a64c5264ad4da4877133d8792f"
|
||||
integrity sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw==
|
||||
dependencies:
|
||||
chalk "^4.0.0"
|
||||
diff-sequences "^28.1.1"
|
||||
jest-get-type "^28.0.2"
|
||||
pretty-format "^28.1.3"
|
||||
|
||||
jest-docblock@^27.5.1:
|
||||
version "27.5.1"
|
||||
resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.5.1.tgz#14092f364a42c6108d42c33c8cf30e058e25f6c0"
|
||||
|
@ -17091,6 +17293,16 @@ jest-matcher-utils@^28.1.1:
|
|||
jest-get-type "^28.0.2"
|
||||
pretty-format "^28.1.1"
|
||||
|
||||
jest-matcher-utils@^28.1.3:
|
||||
version "28.1.3"
|
||||
resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-28.1.3.tgz#5a77f1c129dd5ba3b4d7fc20728806c78893146e"
|
||||
integrity sha512-kQeJ7qHemKfbzKoGjHHrRKH6atgxMk8Enkk2iPQ3XwO6oE/KYD8lMYOziCkeSB9G4adPM4nR1DE8Tf5JeWH6Bw==
|
||||
dependencies:
|
||||
chalk "^4.0.0"
|
||||
jest-diff "^28.1.3"
|
||||
jest-get-type "^28.0.2"
|
||||
pretty-format "^28.1.3"
|
||||
|
||||
jest-message-util@^26.6.2:
|
||||
version "26.6.2"
|
||||
resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.6.2.tgz#58173744ad6fc0506b5d21150b9be56ef001ca07"
|
||||
|
@ -17121,18 +17333,18 @@ jest-message-util@^27.5.1:
|
|||
slash "^3.0.0"
|
||||
stack-utils "^2.0.3"
|
||||
|
||||
jest-message-util@^28.1.1:
|
||||
version "28.1.1"
|
||||
resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-28.1.1.tgz#60aa0b475cfc08c8a9363ed2fb9108514dd9ab89"
|
||||
integrity sha512-xoDOOT66fLfmTRiqkoLIU7v42mal/SqwDKvfmfiWAdJMSJiU+ozgluO7KbvoAgiwIrrGZsV7viETjc8GNrA/IQ==
|
||||
jest-message-util@^28.1.1, jest-message-util@^28.1.3:
|
||||
version "28.1.3"
|
||||
resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-28.1.3.tgz#232def7f2e333f1eecc90649b5b94b0055e7c43d"
|
||||
integrity sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.12.13"
|
||||
"@jest/types" "^28.1.1"
|
||||
"@jest/types" "^28.1.3"
|
||||
"@types/stack-utils" "^2.0.0"
|
||||
chalk "^4.0.0"
|
||||
graceful-fs "^4.2.9"
|
||||
micromatch "^4.0.4"
|
||||
pretty-format "^28.1.1"
|
||||
pretty-format "^28.1.3"
|
||||
slash "^3.0.0"
|
||||
stack-utils "^2.0.3"
|
||||
|
||||
|
@ -17389,6 +17601,18 @@ jest-util@^28.1.1:
|
|||
graceful-fs "^4.2.9"
|
||||
picomatch "^2.2.3"
|
||||
|
||||
jest-util@^28.1.3:
|
||||
version "28.1.3"
|
||||
resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-28.1.3.tgz#f4f932aa0074f0679943220ff9cbba7e497028b0"
|
||||
integrity sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==
|
||||
dependencies:
|
||||
"@jest/types" "^28.1.3"
|
||||
"@types/node" "*"
|
||||
chalk "^4.0.0"
|
||||
ci-info "^3.2.0"
|
||||
graceful-fs "^4.2.9"
|
||||
picomatch "^2.2.3"
|
||||
|
||||
jest-validate@^27.5.1:
|
||||
version "27.5.1"
|
||||
resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.5.1.tgz#9197d54dc0bdb52260b8db40b46ae668e04df067"
|
||||
|
@ -17462,11 +17686,6 @@ jpeg-js@^0.3.2:
|
|||
resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.3.7.tgz#471a89d06011640592d314158608690172b1028d"
|
||||
integrity sha512-9IXdWudL61npZjvLuVe/ktHiA41iE8qFyLB+4VDTblEsWBzeg8WQTlktdUK4CdncUqtUgUg0bbOmTE2bKBKaBQ==
|
||||
|
||||
jpeg-js@^0.4.2:
|
||||
version "0.4.3"
|
||||
resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.3.tgz#6158e09f1983ad773813704be80680550eff977b"
|
||||
integrity sha512-ru1HWKek8octvUHFHvE5ZzQ1yAsJmIvRdGWvSoKV52XKyuyYA437QWDttXT8eZXDSbuMpHlLzPDZUPd6idIz+Q==
|
||||
|
||||
jquery@^3.5.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.0.tgz#c72a09f15c1bdce142f49dbf1170bdf8adac2470"
|
||||
|
@ -17864,10 +18083,10 @@ kleur@^3.0.3:
|
|||
resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
|
||||
integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
|
||||
|
||||
kleur@^4.1.4:
|
||||
version "4.1.4"
|
||||
resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.4.tgz#8c202987d7e577766d039a8cd461934c01cda04d"
|
||||
integrity sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==
|
||||
kleur@^4.1.5:
|
||||
version "4.1.5"
|
||||
resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780"
|
||||
integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==
|
||||
|
||||
klona@^2.0.4:
|
||||
version "2.0.4"
|
||||
|
@ -18460,6 +18679,13 @@ lower-case@^2.0.1:
|
|||
dependencies:
|
||||
tslib "^1.10.0"
|
||||
|
||||
lower-case@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28"
|
||||
integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==
|
||||
dependencies:
|
||||
tslib "^2.0.3"
|
||||
|
||||
lowercase-keys@^1.0.0, lowercase-keys@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f"
|
||||
|
@ -19099,7 +19325,7 @@ mime@1.6.0, mime@^1.4.1:
|
|||
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
|
||||
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
|
||||
|
||||
mime@^2.4.4, mime@^2.4.6:
|
||||
mime@^2.4.4:
|
||||
version "2.5.2"
|
||||
resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe"
|
||||
integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==
|
||||
|
@ -19660,6 +19886,14 @@ no-case@^3.0.3:
|
|||
lower-case "^2.0.1"
|
||||
tslib "^1.10.0"
|
||||
|
||||
no-case@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d"
|
||||
integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==
|
||||
dependencies:
|
||||
lower-case "^2.0.2"
|
||||
tslib "^2.0.3"
|
||||
|
||||
nock@12.0.3:
|
||||
version "12.0.3"
|
||||
resolved "https://registry.yarnpkg.com/nock/-/nock-12.0.3.tgz#83f25076dbc4c9aa82b5cdf54c9604c7a778d1c9"
|
||||
|
@ -20979,54 +21213,29 @@ platform@^1.3.0:
|
|||
resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.5.tgz#fb6958c696e07e2918d2eeda0f0bc9448d733444"
|
||||
integrity sha512-TuvHS8AOIZNAlE77WUDiR4rySV/VMptyMfcfeoMgs4P8apaZM3JrnbzBiixKUv+XR6i+BXrQh8WAnjaSPFO65Q==
|
||||
|
||||
playwright-chromium@=1.14.0:
|
||||
version "1.14.0"
|
||||
resolved "https://registry.yarnpkg.com/playwright-chromium/-/playwright-chromium-1.14.0.tgz#b153eb96412fd6a4fa8d9233a4fdf694fc9f3139"
|
||||
integrity sha512-qWQN9VTPhvEZdRpn1564EOtiNU+hRHhogKg1heBX9VsfGy6WHytR9XPFJjD4M6fhNAV1WKM2McVPYIbi1EOYww==
|
||||
playwright-chromium@=1.26.0:
|
||||
version "1.26.0"
|
||||
resolved "https://registry.yarnpkg.com/playwright-chromium/-/playwright-chromium-1.26.0.tgz#fa4e75a2034a016b9e2e825fc6577f3efb0d2792"
|
||||
integrity sha512-4hDiVmMKmtuHW5ne11S1HCQTdL+wytprQMhWYecEjMSIKBR1DJ3JLrcUDgqA0L5Jzi/CBKYQQk6TOVlTjXybXQ==
|
||||
dependencies:
|
||||
commander "^6.1.0"
|
||||
debug "^4.1.1"
|
||||
extract-zip "^2.0.1"
|
||||
https-proxy-agent "^5.0.0"
|
||||
jpeg-js "^0.4.2"
|
||||
mime "^2.4.6"
|
||||
pngjs "^5.0.0"
|
||||
progress "^2.0.3"
|
||||
proper-lockfile "^4.1.1"
|
||||
proxy-from-env "^1.1.0"
|
||||
rimraf "^3.0.2"
|
||||
stack-utils "^2.0.3"
|
||||
ws "^7.4.6"
|
||||
yazl "^2.5.1"
|
||||
playwright-core "1.26.0"
|
||||
|
||||
playwright-core@=1.17.1:
|
||||
version "1.17.1"
|
||||
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.17.1.tgz#a16e0f89284a0ed8ae6d77e1c905c84b8a2ba022"
|
||||
integrity sha512-C3c8RpPiC3qr15fRDN6dx6WnUkPLFmST37gms2aoHPDRvp7EaGDPMMZPpqIm/QWB5J40xDrQCD4YYHz2nBTojQ==
|
||||
dependencies:
|
||||
commander "^8.2.0"
|
||||
debug "^4.1.1"
|
||||
extract-zip "^2.0.1"
|
||||
https-proxy-agent "^5.0.0"
|
||||
jpeg-js "^0.4.2"
|
||||
mime "^2.4.6"
|
||||
pngjs "^5.0.0"
|
||||
progress "^2.0.3"
|
||||
proper-lockfile "^4.1.1"
|
||||
proxy-from-env "^1.1.0"
|
||||
rimraf "^3.0.2"
|
||||
socks-proxy-agent "^6.1.0"
|
||||
stack-utils "^2.0.3"
|
||||
ws "^7.4.6"
|
||||
yauzl "^2.10.0"
|
||||
yazl "^2.5.1"
|
||||
playwright-core@1.26.0, playwright-core@=1.26.0:
|
||||
version "1.26.0"
|
||||
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.26.0.tgz#850228f0638d410a5cdd69800d552f60e4d295cd"
|
||||
integrity sha512-p8huU8eU4gD3VkJd3DA1nA7R3XA6rFvFL+1RYS96cSljCF2yJE9CWEHTPF4LqX8KN9MoWCrAfVKP5381X3CZqg==
|
||||
|
||||
playwright@^1.17.1:
|
||||
version "1.17.1"
|
||||
resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.17.1.tgz#a6d63302ee40f41283c4bf869de261c4743a787c"
|
||||
integrity sha512-DisCkW9MblDJNS3rG61p8LiLA2WA7IY/4A4W7DX4BphWe/HuWjKmGQptuk4NVIh5UuSwXpW/jaH2+ZgjHs3GMA==
|
||||
playwright-core@1.27.1:
|
||||
version "1.27.1"
|
||||
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.27.1.tgz#840ef662e55a3ed759d8b5d3d00a5f885a7184f4"
|
||||
integrity sha512-9EmeXDncC2Pmp/z+teoVYlvmPWUC6ejSSYZUln7YaP89Z6lpAaiaAnqroUt/BoLo8tn7WYShcfaCh+xofZa44Q==
|
||||
|
||||
playwright@^1.26.0:
|
||||
version "1.27.1"
|
||||
resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.27.1.tgz#4eecac5899566c589d4220ca8acc16abe8a67450"
|
||||
integrity sha512-xXYZ7m36yTtC+oFgqH0eTgullGztKSRMb4yuwLPl8IYSmgBM88QiB+3IWb1mRIC9/NNwcgbG0RwtFlg+EAFQHQ==
|
||||
dependencies:
|
||||
playwright-core "=1.17.1"
|
||||
playwright-core "1.27.1"
|
||||
|
||||
plugin-error@^1.0.1:
|
||||
version "1.0.1"
|
||||
|
@ -21065,11 +21274,6 @@ pngjs@^3.3.3, pngjs@^3.4.0:
|
|||
resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f"
|
||||
integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==
|
||||
|
||||
pngjs@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-5.0.0.tgz#e79dd2b215767fd9c04561c01236df960bce7fbb"
|
||||
integrity sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==
|
||||
|
||||
pngjs@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-6.0.0.tgz#ca9e5d2aa48db0228a52c419c3308e87720da821"
|
||||
|
@ -21521,6 +21725,16 @@ pretty-format@^28.1.1:
|
|||
ansi-styles "^5.0.0"
|
||||
react-is "^18.0.0"
|
||||
|
||||
pretty-format@^28.1.3:
|
||||
version "28.1.3"
|
||||
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-28.1.3.tgz#c9fba8cedf99ce50963a11b27d982a9ae90970d5"
|
||||
integrity sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==
|
||||
dependencies:
|
||||
"@jest/schemas" "^28.1.3"
|
||||
ansi-regex "^5.0.1"
|
||||
ansi-styles "^5.0.0"
|
||||
react-is "^18.0.0"
|
||||
|
||||
pretty-format@^3.8.0:
|
||||
version "3.8.0"
|
||||
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-3.8.0.tgz#bfbed56d5e9a776645f4b1ff7aa1a3ac4fa3c385"
|
||||
|
@ -21572,7 +21786,7 @@ process@^0.11.10:
|
|||
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
|
||||
integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=
|
||||
|
||||
progress@2.0.3, progress@^2.0.0, progress@^2.0.3:
|
||||
progress@2.0.3, progress@^2.0.0:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
|
||||
integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
|
||||
|
@ -21657,15 +21871,6 @@ propagate@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/propagate/-/propagate-2.0.1.tgz#40cdedab18085c792334e64f0ac17256d38f9a45"
|
||||
integrity sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==
|
||||
|
||||
proper-lockfile@^4.1.1:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-4.1.2.tgz#c8b9de2af6b2f1601067f98e01ac66baa223141f"
|
||||
integrity sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==
|
||||
dependencies:
|
||||
graceful-fs "^4.2.4"
|
||||
retry "^0.12.0"
|
||||
signal-exit "^3.0.2"
|
||||
|
||||
property-information@^5.0.0, property-information@^5.0.1, property-information@^5.3.0:
|
||||
version "5.5.0"
|
||||
resolved "https://registry.yarnpkg.com/property-information/-/property-information-5.5.0.tgz#4dc075d493061a82e2b7d096f406e076ed859943"
|
||||
|
@ -23990,10 +24195,10 @@ shallowequal@^1.1.0:
|
|||
resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8"
|
||||
integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==
|
||||
|
||||
sharp@^0.30.1:
|
||||
version "0.30.7"
|
||||
resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.30.7.tgz#7862bda98804fdd1f0d5659c85e3324b90d94c7c"
|
||||
integrity sha512-G+MY2YW33jgflKPTXXptVO28HvNOo9G3j0MybYAHeEmby+QuD2U98dT6ueht9cv/XDqZspSpIhoSW+BAKJ7Hig==
|
||||
sharp@^0.31.1:
|
||||
version "0.31.1"
|
||||
resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.31.1.tgz#b2f7076d381a120761aa93700cadefcf90a22458"
|
||||
integrity sha512-GR8M1wBwOiFKLkm9JPun27OQnNRZdHfSf9VwcdZX6UrRmM1/XnOrLFTF0GAil+y/YK4E6qcM/ugxs80QirsHxg==
|
||||
dependencies:
|
||||
color "^4.2.3"
|
||||
detect-libc "^2.0.1"
|
||||
|
@ -24147,13 +24352,21 @@ smart-buffer@^4.1.0:
|
|||
resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae"
|
||||
integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==
|
||||
|
||||
snakecase-keys@^3.2.1:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/snakecase-keys/-/snakecase-keys-3.2.1.tgz#ce5d1a2de8a93c939d7992f76f2743aa59f3d5ad"
|
||||
integrity sha512-CjU5pyRfwOtaOITYv5C8DzpZ8XA/ieRsDpr93HI2r6e3YInC6moZpSQbmUtg8cTk58tq2x3jcG2gv+p1IZGmMA==
|
||||
snake-case@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c"
|
||||
integrity sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==
|
||||
dependencies:
|
||||
dot-case "^3.0.4"
|
||||
tslib "^2.0.3"
|
||||
|
||||
snakecase-keys@^4.0.0:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/snakecase-keys/-/snakecase-keys-4.0.2.tgz#72e28112b77753a68a4eeb110efec05ab391e190"
|
||||
integrity sha512-ZFCo3zZtNN43cy2j4fQDHPxS557Uuzn887FBmDdaSB41D8l/MayuvaSrIlCXGFhZ8sXwrHiNaZiIPpKzi88gog==
|
||||
dependencies:
|
||||
map-obj "^4.1.0"
|
||||
to-snake-case "^1.0.0"
|
||||
snake-case "^3.0.4"
|
||||
|
||||
snap-shot-compare@2.8.3:
|
||||
version "2.8.3"
|
||||
|
@ -24218,7 +24431,7 @@ sockjs@^0.3.24:
|
|||
uuid "^8.3.2"
|
||||
websocket-driver "^0.7.4"
|
||||
|
||||
socks-proxy-agent@^6.0.0, socks-proxy-agent@^6.1.0:
|
||||
socks-proxy-agent@^6.0.0:
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz#e664e8f1aaf4e1fb3df945f09e3d94f911137f87"
|
||||
integrity sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew==
|
||||
|
@ -24243,10 +24456,10 @@ sonic-boom@^1.0.2:
|
|||
atomic-sleep "^1.0.0"
|
||||
flatstr "^1.0.12"
|
||||
|
||||
sonic-boom@^2.6.0:
|
||||
version "2.6.0"
|
||||
resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-2.6.0.tgz#8786fc78be07c18a90381acd816d1d4afe3537a2"
|
||||
integrity sha512-6xYZFRmDEtxGqfOKcDQ4cPLrNa0SPEDI+wlzDAHowXE6YV42NeXqg9mP2KkiM8JVu3lHfZ2iQKYlGOz+kTpphg==
|
||||
sonic-boom@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-3.2.0.tgz#ce9f2de7557e68be2e52c8df6d9b052e7d348143"
|
||||
integrity sha512-SbbZ+Kqj/XIunvIAgUZRlqd6CGQYq71tRRbXR92Za8J/R3Yh4Av+TWENiSiEgnlwckYLyP0YZQWVfyNC0dzLaA==
|
||||
dependencies:
|
||||
atomic-sleep "^1.0.0"
|
||||
|
||||
|
@ -24296,7 +24509,7 @@ source-map-support@0.5.9:
|
|||
buffer-from "^1.0.0"
|
||||
source-map "^0.6.0"
|
||||
|
||||
source-map-support@^0.5.16, source-map-support@^0.5.19, source-map-support@^0.5.20, source-map-support@^0.5.21, source-map-support@^0.5.6, source-map-support@~0.5.12, source-map-support@~0.5.20:
|
||||
source-map-support@^0.5.16, source-map-support@^0.5.19, source-map-support@^0.5.20, source-map-support@^0.5.6, source-map-support@~0.5.12, source-map-support@~0.5.20:
|
||||
version "0.5.21"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
|
||||
integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==
|
||||
|
@ -24685,6 +24898,11 @@ stream-to-async-iterator@^0.2.0:
|
|||
resolved "https://registry.yarnpkg.com/stream-to-async-iterator/-/stream-to-async-iterator-0.2.0.tgz#bef5c885e9524f98b2fa5effecc357bd58483780"
|
||||
integrity sha1-vvXIhelST5iy+l7/7MNXvVhIN4A=
|
||||
|
||||
streamsearch@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764"
|
||||
integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==
|
||||
|
||||
strict-uri-encode@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
|
||||
|
@ -25608,13 +25826,6 @@ to-regex@^3.0.1, to-regex@^3.0.2:
|
|||
regex-not "^1.0.2"
|
||||
safe-regex "^1.1.0"
|
||||
|
||||
to-snake-case@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/to-snake-case/-/to-snake-case-1.0.0.tgz#ce746913897946019a87e62edfaeaea4c608ab8c"
|
||||
integrity sha1-znRpE4l5RgGah+Yu366upMYIq4w=
|
||||
dependencies:
|
||||
to-space-case "^1.0.0"
|
||||
|
||||
to-source-code@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/to-source-code/-/to-source-code-1.0.2.tgz#dd136bdb1e1dbd80bbeacf088992678e9070bfea"
|
||||
|
@ -25788,12 +25999,12 @@ ts-morph@^13.0.2:
|
|||
"@ts-morph/common" "~0.12.2"
|
||||
code-block-writer "^11.0.0"
|
||||
|
||||
ts-node@^10.5.0:
|
||||
version "10.7.0"
|
||||
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.7.0.tgz#35d503d0fab3e2baa672a0e94f4b40653c2463f5"
|
||||
integrity sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==
|
||||
ts-node@^10.9.1:
|
||||
version "10.9.1"
|
||||
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b"
|
||||
integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==
|
||||
dependencies:
|
||||
"@cspotcode/source-map-support" "0.7.0"
|
||||
"@cspotcode/source-map-support" "^0.8.0"
|
||||
"@tsconfig/node10" "^1.0.7"
|
||||
"@tsconfig/node12" "^1.0.7"
|
||||
"@tsconfig/node14" "^1.0.0"
|
||||
|
@ -25804,7 +26015,7 @@ ts-node@^10.5.0:
|
|||
create-require "^1.1.0"
|
||||
diff "^4.0.1"
|
||||
make-error "^1.1.1"
|
||||
v8-compile-cache-lib "^3.0.0"
|
||||
v8-compile-cache-lib "^3.0.1"
|
||||
yn "3.1.1"
|
||||
|
||||
ts-pnp@^1.1.6:
|
||||
|
@ -25976,7 +26187,7 @@ typescript-tuple@^2.2.1:
|
|||
dependencies:
|
||||
typescript-compare "^0.0.2"
|
||||
|
||||
typescript@4.6.3, typescript@^3.3.3333, typescript@^3.5.3, typescript@^4.5.5:
|
||||
typescript@4.6.3, typescript@^3.3.3333, typescript@^3.5.3, typescript@^4.8.3:
|
||||
version "4.6.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.3.tgz#eefeafa6afdd31d725584c67a0eaba80f6fc6c6c"
|
||||
integrity sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==
|
||||
|
@ -26029,6 +26240,13 @@ undici@^5.1.1:
|
|||
resolved "https://registry.yarnpkg.com/undici/-/undici-5.8.2.tgz#071fc8a6a5d24db0ad510ad442f607d9b09d5eec"
|
||||
integrity sha512-3KLq3pXMS0Y4IELV045fTxqz04Nk9Ms7yfBBHum3yxsTR4XNn+ZCaUbf/mWitgYDAhsplQ0B1G4S5D345lMO3A==
|
||||
|
||||
undici@^5.10.0:
|
||||
version "5.11.0"
|
||||
resolved "https://registry.yarnpkg.com/undici/-/undici-5.11.0.tgz#1db25f285821828fc09d3804b9e2e934ae86fc13"
|
||||
integrity sha512-oWjWJHzFet0Ow4YZBkyiJwiK5vWqEYoH7BINzJAJOLedZ++JpAlCbUktW2GQ2DS2FpKmxD/JMtWUUWl1BtghGw==
|
||||
dependencies:
|
||||
busboy "^1.6.0"
|
||||
|
||||
unfetch@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/unfetch/-/unfetch-4.2.0.tgz#7e21b0ef7d363d8d9af0fb929a5555f6ef97a3be"
|
||||
|
@ -26519,10 +26737,10 @@ uuid@^8.3.0, uuid@^8.3.2:
|
|||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
|
||||
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
|
||||
|
||||
v8-compile-cache-lib@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz#0582bcb1c74f3a2ee46487ceecf372e46bce53e8"
|
||||
integrity sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA==
|
||||
v8-compile-cache-lib@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"
|
||||
integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==
|
||||
|
||||
v8-compile-cache@^2.0.3, v8-compile-cache@^2.3.0:
|
||||
version "2.3.0"
|
||||
|
@ -27764,6 +27982,11 @@ yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2:
|
|||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
|
||||
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
|
||||
|
||||
yaml@^2.1.1:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.1.3.tgz#9b3a4c8aff9821b696275c79a8bee8399d945207"
|
||||
integrity sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==
|
||||
|
||||
yargs-parser@20.2.4, yargs-parser@^20.2.2, yargs-parser@^20.2.3:
|
||||
version "20.2.4"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue