diff --git a/package.json b/package.json index c34818e0f39..1b8daf17eea 100644 --- a/package.json +++ b/package.json @@ -121,7 +121,7 @@ "@types/react-grid-layout": "1.1.1", "@types/react-highlight-words": "^0.16.2", "@types/react-loadable": "5.5.2", - "@types/react-redux": "7.1.7", + "@types/react-redux": "7.1.18", "@types/react-router-dom": "^5.1.7", "@types/react-select": "4.0.13", "@types/react-test-renderer": "17.0.1", @@ -232,7 +232,7 @@ "@opentelemetry/exporter-collector": "0.23.0", "@opentelemetry/semantic-conventions": "0.23.0", "@popperjs/core": "2.5.4", - "@reduxjs/toolkit": "1.5.0", + "@reduxjs/toolkit": "1.6.1", "@sentry/browser": "5.25.0", "@sentry/types": "5.24.2", "@sentry/utils": "5.24.2", @@ -268,7 +268,7 @@ "file-saver": "2.0.2", "history": "4.10.1", "hoist-non-react-statics": "3.3.2", - "immer": "8.0.1", + "immer": "9.0.6", "jquery": "3.5.1", "json-source-map": "0.6.1", "jsurl": "^0.1.5", @@ -299,7 +299,7 @@ "react-highlight-words": "0.17.0", "react-loadable": "5.5.0", "react-popper": "2.2.4", - "react-redux": "7.2.0", + "react-redux": "7.2.5", "react-reverse-portal": "^2.0.1", "react-router-dom": "^5.2.0", "react-select": "4.3.0", @@ -308,7 +308,7 @@ "react-use": "17.2.4", "react-virtualized-auto-sizer": "1.0.2", "react-window": "1.8.5", - "redux": "4.0.5", + "redux": "4.1.1", "redux-thunk": "2.3.0", "regenerator-runtime": "0.13.3", "reselect": "4.0.0", diff --git a/public/app/features/alerting/unified/state/actions.ts b/public/app/features/alerting/unified/state/actions.ts index f13f0598658..6a0ba4fa4ac 100644 --- a/public/app/features/alerting/unified/state/actions.ts +++ b/public/app/features/alerting/unified/state/actions.ts @@ -563,7 +563,7 @@ export const fetchAlertGroupsAction = createAsyncThunk( } ); -export const checkIfLotexSupportsEditingRulesAction = createAsyncThunk( +export const checkIfLotexSupportsEditingRulesAction = createAsyncThunk( 'unifiedalerting/checkIfLotexRuleEditingSupported', async (rulesSourceName: string): Promise => withAppEvents( diff --git a/public/app/features/alerting/unified/utils/redux.ts b/public/app/features/alerting/unified/utils/redux.ts index f6e71cfa651..868bc9fa863 100644 --- a/public/app/features/alerting/unified/utils/redux.ts +++ b/public/app/features/alerting/unified/utils/redux.ts @@ -1,8 +1,10 @@ -import { AnyAction, AsyncThunk, createSlice, Draft, isAsyncThunkAction, SerializedError } from '@reduxjs/toolkit'; -import { FetchError } from '@grafana/runtime'; import { isArray } from 'angular'; -import { appEvents } from 'app/core/core'; +import { AsyncThunk, createSlice, Draft, isAsyncThunkAction, PayloadAction, SerializedError } from '@reduxjs/toolkit'; +import { FetchError } from '@grafana/runtime'; import { AppEvents } from '@grafana/data'; + +import { appEvents } from 'app/core/core'; + export interface AsyncRequestState { result?: T; loading: boolean; @@ -18,10 +20,12 @@ export const initialAsyncRequestState: AsyncRequestState = Object.freeze({ export type AsyncRequestMapSlice = Record>; +export type AsyncRequestAction = PayloadAction, string, any, any>; + function requestStateReducer( asyncThunk: AsyncThunk, state: Draft> = initialAsyncRequestState, - action: AnyAction + action: AsyncRequestAction ): Draft> { if (asyncThunk.pending.match(action)) { return { @@ -35,7 +39,7 @@ function requestStateReducer( if (state.requestId === undefined || state.requestId === action.meta.requestId) { return { ...state, - result: action.payload as Draft, + result: action.payload, loading: false, error: undefined, }; @@ -45,7 +49,7 @@ function requestStateReducer( return { ...state, loading: false, - error: (action as any).error, + error: action.error, }; } } @@ -65,7 +69,9 @@ export function createAsyncSlice( initialState: initialAsyncRequestState as AsyncRequestState, reducers: {}, extraReducers: (builder) => - builder.addDefaultCase((state, action) => requestStateReducer(asyncThunk, state, action)), + builder.addDefaultCase((state, action) => + requestStateReducer(asyncThunk, state, (action as unknown) as AsyncRequestAction) + ), }); } @@ -86,10 +92,11 @@ export function createAsyncMapSlice( extraReducers: (builder) => builder.addDefaultCase((state, action) => { if (isAsyncThunkAction(asyncThunk)(action)) { - const entityId = getEntityId(action.meta.arg); + const asyncAction = (action as unknown) as AsyncRequestAction; + const entityId = getEntityId(asyncAction.meta.arg); return { ...state, - [entityId]: requestStateReducer(asyncThunk, state[entityId], action), + [entityId]: requestStateReducer(asyncThunk, state[entityId], asyncAction), }; } return state; diff --git a/public/app/features/dashboard/components/PanelEditor/PanelNotSupported.test.tsx b/public/app/features/dashboard/components/PanelEditor/PanelNotSupported.test.tsx index deae9f5e640..3140999328a 100644 --- a/public/app/features/dashboard/components/PanelEditor/PanelNotSupported.test.tsx +++ b/public/app/features/dashboard/components/PanelEditor/PanelNotSupported.test.tsx @@ -2,24 +2,13 @@ import { locationService } from '@grafana/runtime'; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; -import { Provider } from 'react-redux'; -import createMockStore from 'redux-mock-store'; import { PanelNotSupported, Props } from './PanelNotSupported'; import { PanelEditorTabId } from './types'; const setupTestContext = (options: Partial) => { - const defaults: Props = { - message: '', - dispatch: jest.fn(), - }; - const store = createMockStore(); - + const defaults: Props = { message: '' }; const props = { ...defaults, ...options }; - render( - - - - ); + render(); return { props }; }; diff --git a/public/app/features/dashboard/components/PanelEditor/PanelNotSupported.tsx b/public/app/features/dashboard/components/PanelEditor/PanelNotSupported.tsx index d4c25bc8709..3c0bcdcc0a6 100644 --- a/public/app/features/dashboard/components/PanelEditor/PanelNotSupported.tsx +++ b/public/app/features/dashboard/components/PanelEditor/PanelNotSupported.tsx @@ -1,6 +1,4 @@ -import React, { FC, useCallback } from 'react'; -import { useDispatch } from 'react-redux'; -import { Dispatch } from 'redux'; +import React, { useCallback } from 'react'; import { Button, VerticalGroup } from '@grafana/ui'; import { Layout } from '@grafana/ui/src/components/Layout/Layout'; @@ -9,12 +7,9 @@ import { locationService } from '@grafana/runtime'; export interface Props { message: string; - dispatch?: Dispatch; } -export const PanelNotSupported: FC = ({ message, dispatch: propsDispatch }) => { - let dispatch = useDispatch(); - dispatch = propsDispatch ?? dispatch; +export function PanelNotSupported({ message }: Props): JSX.Element { const onBackToQueries = useCallback(() => { locationService.partial({ tab: PanelEditorTabId.Query }); }, []); @@ -31,4 +26,4 @@ export const PanelNotSupported: FC = ({ message, dispatch: propsDispatch ); -}; +} diff --git a/public/app/features/explore/state/explorePane.test.ts b/public/app/features/explore/state/explorePane.test.ts index 11a0aefaac3..84f916bc000 100644 --- a/public/app/features/explore/state/explorePane.test.ts +++ b/public/app/features/explore/state/explorePane.test.ts @@ -1,5 +1,5 @@ import { DataQuery, DefaultTimeZone, EventBusExtended, serializeStateToUrlParam, toUtc } from '@grafana/data'; -import { ExploreId } from 'app/types'; +import { ExploreId, StoreState, ThunkDispatch } from 'app/types'; import { refreshExplore } from './explorePane'; import { setDataSourceSrv } from '@grafana/runtime'; import { configureStore } from '../../../store/configureStore'; @@ -92,37 +92,38 @@ function setup(state?: any) { }, } as any); - const store = setupStore({ + const { dispatch, getState }: { dispatch: ThunkDispatch; getState: () => StoreState } = setupStore({ datasourceInstance: datasources.someDs, ...(state || {}), }); return { - store, + dispatch, + getState, datasources, }; } describe('refreshExplore', () => { it('should change data source when datasource in url changes', async () => { - const { store } = setup(); - await store.dispatch( + const { dispatch, getState } = setup(); + await dispatch( refreshExplore(ExploreId.left, serializeStateToUrlParam({ datasource: 'newDs', queries: [], range: testRange })) ); - expect(store.getState().explore[ExploreId.left].datasourceInstance?.name).toBe('newDs'); + expect(getState().explore[ExploreId.left].datasourceInstance?.name).toBe('newDs'); }); it('should change and run new queries from the URL', async () => { - const { store, datasources } = setup(); + const { dispatch, getState, datasources } = setup(); datasources.someDs.query.mockReturnValueOnce(of({})); - await store.dispatch( + await dispatch( refreshExplore( ExploreId.left, serializeStateToUrlParam({ datasource: 'someDs', queries: [{ expr: 'count()' }], range: testRange }) ) ); // same - const state = store.getState().explore[ExploreId.left]; + const state = getState().explore[ExploreId.left]; expect(state.datasourceInstance?.name).toBe('someDs'); expect(state.queries.length).toBe(1); expect(state.queries).toMatchObject([{ expr: 'count()' }]); @@ -130,17 +131,17 @@ describe('refreshExplore', () => { }); it('should not do anything if pane is not initialized', async () => { - const { store } = setup({ + const { dispatch, getState } = setup({ initialized: false, }); - const state = store.getState(); - await store.dispatch( + const state = getState(); + await dispatch( refreshExplore( ExploreId.left, serializeStateToUrlParam({ datasource: 'newDs', queries: [{ expr: 'count()' }], range: testRange }) ) ); - expect(state).toEqual(store.getState()); + expect(state).toEqual(getState()); }); }); diff --git a/public/app/features/explore/state/query.test.ts b/public/app/features/explore/state/query.test.ts index 518a0db0d73..54d8f52e907 100644 --- a/public/app/features/explore/state/query.test.ts +++ b/public/app/features/explore/state/query.test.ts @@ -1,31 +1,31 @@ import { addQueryRowAction, addResultsToCache, - clearCache, cancelQueries, cancelQueriesAction, + clearCache, + importQueries, queryReducer, removeQueryRowAction, - importQueries, runQueries, scanStartAction, scanStopAction, } from './query'; -import { ExploreId, ExploreItemState } from 'app/types'; +import { ExploreId, ExploreItemState, StoreState, ThunkDispatch } from 'app/types'; import { interval, of } from 'rxjs'; import { ArrayVector, - DataQueryResponse, - DefaultTimeZone, - MutableDataFrame, - RawTimeRange, - toUtc, - PanelData, DataFrame, - LoadingState, + DataQuery, + DataQueryResponse, DataSourceApi, DataSourceJsonData, - DataQuery, + DefaultTimeZone, + LoadingState, + MutableDataFrame, + PanelData, + RawTimeRange, + toUtc, } from '@grafana/data'; import { thunkTester } from 'test/core/thunk/thunkTester'; import { makeExplorePaneState } from './utils'; @@ -76,10 +76,10 @@ describe('runQueries', () => { setTimeSrv({ init() {}, } as any); - const store = configureStore({ + const { dispatch, getState }: { dispatch: ThunkDispatch; getState: () => StoreState } = configureStore({ ...(defaultInitialState as any), }); - (store.getState().explore[ExploreId.left].datasourceInstance?.query as Mock).mockReturnValueOnce( + (getState().explore[ExploreId.left].datasourceInstance?.query as Mock).mockReturnValueOnce( of({ error: { message: 'test error' }, data: [ @@ -92,9 +92,9 @@ describe('runQueries', () => { ], } as DataQueryResponse) ); - await store.dispatch(runQueries(ExploreId.left)); - expect(store.getState().explore[ExploreId.left].showMetrics).toBeTruthy(); - expect(store.getState().explore[ExploreId.left].graphResult).toBeDefined(); + await dispatch(runQueries(ExploreId.left)); + expect(getState().explore[ExploreId.left].showMetrics).toBeTruthy(); + expect(getState().explore[ExploreId.left].graphResult).toBeDefined(); }); }); @@ -131,7 +131,7 @@ describe('running queries', () => { describe('importing queries', () => { describe('when importing queries between the same type of data source', () => { it('remove datasource property from all of the queries', async () => { - const store = configureStore({ + const { dispatch, getState }: { dispatch: ThunkDispatch; getState: () => StoreState } = configureStore({ ...(defaultInitialState as any), explore: { [ExploreId.left]: { @@ -141,7 +141,7 @@ describe('importing queries', () => { }, }); - await store.dispatch( + await dispatch( importQueries( ExploreId.left, [ @@ -153,10 +153,10 @@ describe('importing queries', () => { ) ); - expect(store.getState().explore[ExploreId.left].queries[0]).toHaveProperty('refId', 'refId_A'); - expect(store.getState().explore[ExploreId.left].queries[1]).toHaveProperty('refId', 'refId_B'); - expect(store.getState().explore[ExploreId.left].queries[0]).not.toHaveProperty('datasource'); - expect(store.getState().explore[ExploreId.left].queries[1]).not.toHaveProperty('datasource'); + expect(getState().explore[ExploreId.left].queries[0]).toHaveProperty('refId', 'refId_A'); + expect(getState().explore[ExploreId.left].queries[1]).toHaveProperty('refId', 'refId_B'); + expect(getState().explore[ExploreId.left].queries[0]).not.toHaveProperty('datasource'); + expect(getState().explore[ExploreId.left].queries[1]).not.toHaveProperty('datasource'); }); }); }); @@ -266,7 +266,7 @@ describe('reducer', () => { describe('caching', () => { it('should add response to cache', async () => { - const store = configureStore({ + const { dispatch, getState }: { dispatch: ThunkDispatch; getState: () => StoreState } = configureStore({ ...(defaultInitialState as any), explore: { [ExploreId.left]: { @@ -280,15 +280,15 @@ describe('reducer', () => { }, }); - await store.dispatch(addResultsToCache(ExploreId.left)); + await dispatch(addResultsToCache(ExploreId.left)); - expect(store.getState().explore[ExploreId.left].cache).toEqual([ + expect(getState().explore[ExploreId.left].cache).toEqual([ { key: 'from=1621348027000&to=1621348050000', value: { series: [{ name: 'test name' }], state: 'Done' } }, ]); }); it('should not add response to cache if response is still loading', async () => { - const store = configureStore({ + const { dispatch, getState }: { dispatch: ThunkDispatch; getState: () => StoreState } = configureStore({ ...(defaultInitialState as any), explore: { [ExploreId.left]: { @@ -299,13 +299,13 @@ describe('reducer', () => { }, }); - await store.dispatch(addResultsToCache(ExploreId.left)); + await dispatch(addResultsToCache(ExploreId.left)); - expect(store.getState().explore[ExploreId.left].cache).toEqual([]); + expect(getState().explore[ExploreId.left].cache).toEqual([]); }); it('should not add duplicate response to cache', async () => { - const store = configureStore({ + const { dispatch, getState }: { dispatch: ThunkDispatch; getState: () => StoreState } = configureStore({ ...(defaultInitialState as any), explore: { [ExploreId.left]: { @@ -325,16 +325,16 @@ describe('reducer', () => { }, }); - await store.dispatch(addResultsToCache(ExploreId.left)); + await dispatch(addResultsToCache(ExploreId.left)); - expect(store.getState().explore[ExploreId.left].cache).toHaveLength(1); - expect(store.getState().explore[ExploreId.left].cache).toEqual([ + expect(getState().explore[ExploreId.left].cache).toHaveLength(1); + expect(getState().explore[ExploreId.left].cache).toEqual([ { key: 'from=1621348027000&to=1621348050000', value: { series: [{ name: 'old test name' }], state: 'Done' } }, ]); }); it('should clear cache', async () => { - const store = configureStore({ + const { dispatch, getState }: { dispatch: ThunkDispatch; getState: () => StoreState } = configureStore({ ...(defaultInitialState as any), explore: { [ExploreId.left]: { @@ -349,9 +349,9 @@ describe('reducer', () => { }, }); - await store.dispatch(clearCache(ExploreId.left)); + await dispatch(clearCache(ExploreId.left)); - expect(store.getState().explore[ExploreId.left].cache).toEqual([]); + expect(getState().explore[ExploreId.left].cache).toEqual([]); }); }); }); diff --git a/public/app/features/plugins/state/selectors.test.ts b/public/app/features/plugins/state/selectors.test.ts index 09b1ce4c259..4f2f77efe8a 100644 --- a/public/app/features/plugins/state/selectors.test.ts +++ b/public/app/features/plugins/state/selectors.test.ts @@ -3,7 +3,7 @@ import { initialState } from './reducers'; import { getMockPlugins } from '../__mocks__/pluginMocks'; describe('Selectors', () => { - const mockState = initialState; + const mockState = { ...initialState }; it('should return search query', () => { mockState.searchQuery = 'test'; diff --git a/public/app/plugins/datasource/alertmanager/types.ts b/public/app/plugins/datasource/alertmanager/types.ts index 7c26a65aa38..5cc6134904a 100644 --- a/public/app/plugins/datasource/alertmanager/types.ts +++ b/public/app/plugins/datasource/alertmanager/types.ts @@ -64,8 +64,8 @@ export type GrafanaManagedReceiverConfig = { uid?: string; disableResolveMessage: boolean; secureFields?: Record; - secureSettings?: Record; - settings: Record; + secureSettings?: Record; + settings: Record; type: string; name: string; updated?: string; @@ -76,15 +76,15 @@ export type Receiver = { name: string; email_configs?: EmailConfig[]; - pagerduty_configs?: unknown[]; - pushover_configs?: unknown[]; - slack_configs?: unknown[]; - opsgenie_configs?: unknown[]; + pagerduty_configs?: any[]; + pushover_configs?: any[]; + slack_configs?: any[]; + opsgenie_configs?: any[]; webhook_configs?: WebhookConfig[]; - victorops_configs?: unknown[]; - wechat_configs?: unknown[]; + victorops_configs?: any[]; + wechat_configs?: any[]; grafana_managed_receiver_configs?: GrafanaManagedReceiverConfig[]; - [key: string]: unknown; + [key: string]: any; }; export type Route = { diff --git a/public/app/store/configureStore.ts b/public/app/store/configureStore.ts index 8bca0a4c237..851c4d883e3 100644 --- a/public/app/store/configureStore.ts +++ b/public/app/store/configureStore.ts @@ -1,9 +1,10 @@ -import { configureStore as reduxConfigureStore, getDefaultMiddleware } from '@reduxjs/toolkit'; -import { ThunkMiddleware } from 'redux-thunk'; +import { configureStore as reduxConfigureStore } from '@reduxjs/toolkit'; import { setStore } from './store'; import { StoreState } from 'app/types/store'; import { addReducer, createRootReducer } from '../core/reducers/root'; import { buildInitialState } from '../core/reducers/navModel'; +import { ThunkMiddlewareFor } from '@reduxjs/toolkit/src/getDefaultMiddleware'; +import { AnyAction } from 'redux'; export function addRootReducer(reducers: any) { // this is ok now because we add reducers before configureStore is called @@ -13,15 +14,14 @@ export function addRootReducer(reducers: any) { } export function configureStore(initialState?: Partial) { - const reduxDefaultMiddleware = getDefaultMiddleware({ - thunk: true, - serializableCheck: false, - immutableCheck: false, - } as any); - - const store = reduxConfigureStore({ + const store = reduxConfigureStore< + StoreState, + AnyAction, + ReadonlyArray> + >({ reducer: createRootReducer(), - middleware: (reduxDefaultMiddleware as unknown) as [ThunkMiddleware], + middleware: (getDefaultMiddleware) => + getDefaultMiddleware({ thunk: true, serializableCheck: false, immutableCheck: false }), devTools: process.env.NODE_ENV !== 'production', preloadedState: { navIndex: buildInitialState(), diff --git a/public/app/types/store.ts b/public/app/types/store.ts index bdb99fe3078..7c5c245cf74 100644 --- a/public/app/types/store.ts +++ b/public/app/types/store.ts @@ -2,7 +2,6 @@ import { ThunkAction, ThunkDispatch as GenericThunkDispatch } from 'redux-thunk' import { Action, PayloadAction } from '@reduxjs/toolkit'; import { NavIndex } from '@grafana/data'; import { AlertRulesState, NotificationChannelState } from './alerting'; -import { UnifiedAlertingState } from '../features/alerting/unified/state/reducers'; import { TeamsState, TeamState } from './teams'; import { FolderState } from './folders'; import { DashboardState } from './dashboard'; @@ -18,6 +17,7 @@ import { ApiKeysState } from './apiKeys'; import { TemplatingState } from '../features/variables/state/reducers'; import { ImportDashboardState } from '../features/manage-dashboards/state/reducers'; import { UserState } from 'app/features/profile/state/reducers'; +import { UnifiedAlertingState } from 'app/features/alerting/unified/state/reducers'; export interface StoreState { navIndex: NavIndex; diff --git a/yarn.lock b/yarn.lock index 8cda54eb7d0..c4b4eb4cce7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3191,13 +3191,13 @@ prop-types "^15.6.1" react-lifecycles-compat "^3.0.4" -"@reduxjs/toolkit@1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-1.5.0.tgz#1025c1ccb224d1fc06d8d98a61f6717d57e6d477" - integrity sha512-E/FUraRx+8guw9Hlg/Ja8jI/hwCrmIKed8Annt9YsZw3BQp+F24t5I5b2OWR6pkEHY4hn1BgP08FrTZFRKsdaQ== +"@reduxjs/toolkit@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-1.6.1.tgz#7bc83b47352a663bf28db01e79d17ba54b98ade9" + integrity sha512-pa3nqclCJaZPAyBhruQtiRwtTjottRrVJqziVZcWzI73i6L3miLTtUyWfauwv08HWtiXLx1xGyGt+yLFfW/d0A== dependencies: - immer "^8.0.0" - redux "^4.0.0" + immer "^9.0.1" + redux "^4.1.0" redux-thunk "^2.3.0" reselect "^4.0.0" @@ -5315,17 +5315,7 @@ "@types/react" "*" "@types/webpack" "*" -"@types/react-redux@7.1.7": - version "7.1.7" - resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.7.tgz#12a0c529aba660696947384a059c5c6e08185c7a" - integrity sha512-U+WrzeFfI83+evZE2dkZ/oF/1vjIYgqrb5dGgedkqVV8HEfDFujNgWCwHL89TDuWKb47U0nTBT6PLGq4IIogWg== - dependencies: - "@types/hoist-non-react-statics" "^3.3.0" - "@types/react" "*" - hoist-non-react-statics "^3.3.0" - redux "^4.0.0" - -"@types/react-redux@^7.1.16": +"@types/react-redux@7.1.18", "@types/react-redux@^7.1.16": version "7.1.18" resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.18.tgz#2bf8fd56ebaae679a90ebffe48ff73717c438e04" integrity sha512-9iwAsPyJ9DLTRH+OFeIrm9cAbIj1i2ANL3sKQFATqnPWRbg+jEFXyZOKHiQK/N86pNRXbb4HRxAxo0SIX1XwzQ== @@ -13354,11 +13344,16 @@ image-size@~0.5.0: resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c" integrity sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w= -immer@8.0.1, immer@^8.0.0: +immer@8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/immer/-/immer-8.0.1.tgz#9c73db683e2b3975c424fb0572af5889877ae656" integrity sha512-aqXhGP7//Gui2+UrEtvxZxSquQVXTpZ7KDxfCcKAF3Vysvw0CViVaW9RZ1j1xlIYqaaaipBoqdqeibkc18PNvA== +immer@9.0.6, immer@^9.0.1: + version "9.0.6" + resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.6.tgz#7a96bf2674d06c8143e327cbf73539388ddf1a73" + integrity sha512-G95ivKpy+EvVAnAab4fVa4YGYn24J1SpEktnJX7JJ45Bd7xqME/SCplFzYFmTbrkwZbQ4xJK1xMTUYBkN6pWsQ== + immutable@3.8.2, immutable@^3.8.2: version "3.8.2" resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.8.2.tgz#c2439951455bb39913daf281376f1530e104adf3" @@ -20067,7 +20062,7 @@ react-is@16.8.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.0.tgz#518db476214f3fb0716af9f82dfd420225ae970f" integrity sha512-LOy+3La39aduxaPfuj+lCXC5RQ8ukjVPAAsFJ3yQ+DIOLf4eR9OMKeWKF0IzjRyE95xMj5QELwiXGgfQsIJguA== -react-is@^16.12.0, react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.9.0: +react-is@^16.12.0, react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== @@ -20114,16 +20109,17 @@ react-popper@^2.2.4: react-fast-compare "^3.0.1" warning "^4.0.2" -react-redux@7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.0.tgz#f970f62192b3981642fec46fd0db18a074fe879d" - integrity sha512-EvCAZYGfOLqwV7gh849xy9/pt55rJXPwmYvI4lilPM5rUT/1NxuuN59ipdBksRVSvz0KInbPnp4IfoXJXCqiDA== +react-redux@7.2.5: + version "7.2.5" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.5.tgz#213c1b05aa1187d9c940ddfc0b29450957f6a3b8" + integrity sha512-Dt29bNyBsbQaysp6s/dN0gUodcq+dVKKER8Qv82UrpeygwYeX1raTtil7O/fftw/rFqzaf6gJhDZRkkZnn6bjg== dependencies: - "@babel/runtime" "^7.5.5" - hoist-non-react-statics "^3.3.0" + "@babel/runtime" "^7.12.1" + "@types/react-redux" "^7.1.16" + hoist-non-react-statics "^3.3.2" loose-envify "^1.4.0" prop-types "^15.7.2" - react-is "^16.9.0" + react-is "^16.13.1" react-redux@^7.2.0: version "7.2.4" @@ -20617,7 +20613,14 @@ redux-thunk@2.3.0, redux-thunk@^2.3.0: resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622" integrity sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw== -redux@4.0.5, redux@^4.0.0, redux@^4.0.4, redux@^4.0.5: +redux@4.1.1, redux@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/redux/-/redux-4.1.1.tgz#76f1c439bb42043f985fbd9bf21990e60bd67f47" + integrity sha512-hZQZdDEM25UY2P493kPYuKqviVwZ58lEmGQNeQ+gXa+U0gYPUBf7NKYazbe3m+bs/DzM/ahN12DbF+NG8i0CWw== + dependencies: + "@babel/runtime" "^7.9.2" + +redux@^4.0.0, redux@^4.0.4, redux@^4.0.5: version "4.0.5" resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f" integrity sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==