[ML] Fix date picker for the Log pattern analysis (#143684) (#143732)

* url state provider

* update url state provider for explain_log_rate_spikes_app_state.tsx

(cherry picked from commit f61dec4c3d)

Co-authored-by: Dima Arnautov <dmitrii.arnautov@elastic.co>
This commit is contained in:
Kibana Machine 2022-10-20 04:47:52 -06:00 committed by GitHub
parent 8ab7e717a8
commit 0147ec5396
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 86 additions and 84 deletions

View file

@ -5,11 +5,7 @@
* 2.0.
*/
import React, { FC, useCallback } from 'react';
import { parse, stringify } from 'query-string';
import { isEqual } from 'lodash';
import { encode } from 'rison-node';
import { useHistory, useLocation } from 'react-router-dom';
import React, { FC } from 'react';
import { EuiCallOut } from '@elastic/eui';
@ -24,15 +20,7 @@ import {
SearchQueryLanguage,
SavedSearchSavedObject,
} from '../../application/utils/search_utils';
import {
Accessor,
Dictionary,
parseUrlState,
Provider as UrlStateContextProvider,
isRisonSerializationRequired,
getNestedProperty,
SetUrlState,
} from '../../hooks/use_url_state';
import { UrlStateProvider } from '../../hooks/use_url_state';
import type { AiopsAppDependencies } from '../../hooks/use_aiops_app_context';
import { AiopsAppContext } from '../../hooks/use_aiops_app_context';
@ -77,71 +65,6 @@ export const ExplainLogRateSpikesAppState: FC<ExplainLogRateSpikesAppStateProps>
savedSearch,
appDependencies,
}) => {
const history = useHistory();
const { search: urlSearchString } = useLocation();
const setUrlState: SetUrlState = useCallback(
(
accessor: Accessor,
attribute: string | Dictionary<any>,
value?: any,
replaceState?: boolean
) => {
const prevSearchString = urlSearchString;
const urlState = parseUrlState(prevSearchString);
const parsedQueryString = parse(prevSearchString, { sort: false });
if (!Object.prototype.hasOwnProperty.call(urlState, accessor)) {
urlState[accessor] = {};
}
if (typeof attribute === 'string') {
if (isEqual(getNestedProperty(urlState, `${accessor}.${attribute}`), value)) {
return prevSearchString;
}
urlState[accessor][attribute] = value;
} else {
const attributes = attribute;
Object.keys(attributes).forEach((a) => {
urlState[accessor][a] = attributes[a];
});
}
try {
const oldLocationSearchString = stringify(parsedQueryString, {
sort: false,
encode: false,
});
Object.keys(urlState).forEach((a) => {
if (isRisonSerializationRequired(a)) {
parsedQueryString[a] = encode(urlState[a]);
} else {
parsedQueryString[a] = urlState[a];
}
});
const newLocationSearchString = stringify(parsedQueryString, {
sort: false,
encode: false,
});
if (oldLocationSearchString !== newLocationSearchString) {
const newSearchString = stringify(parsedQueryString, { sort: false });
if (replaceState) {
history.replace({ search: newSearchString });
} else {
history.push({ search: newSearchString });
}
}
} catch (error) {
// eslint-disable-next-line no-console
console.error('Could not save url state', error);
}
},
[history, urlSearchString]
);
if (!dataView) return null;
if (!dataView.isTimeBased()) {
@ -165,11 +88,11 @@ export const ExplainLogRateSpikesAppState: FC<ExplainLogRateSpikesAppStateProps>
return (
<AiopsAppContext.Provider value={appDependencies}>
<UrlStateContextProvider value={{ searchString: urlSearchString, setUrlState }}>
<UrlStateProvider>
<SpikeAnalysisTableRowStateProvider>
<ExplainLogRateSpikesPage dataView={dataView} savedSearch={savedSearch} />
</SpikeAnalysisTableRowStateProvider>
</UrlStateContextProvider>
</UrlStateProvider>
</AiopsAppContext.Provider>
);
};

View file

@ -11,6 +11,7 @@ import { LogCategorizationPage } from './log_categorization_page';
import { SavedSearchSavedObject } from '../../application/utils/search_utils';
import type { AiopsAppDependencies } from '../../hooks/use_aiops_app_context';
import { AiopsAppContext } from '../../hooks/use_aiops_app_context';
import { UrlStateProvider } from '../../hooks/use_url_state';
export interface LogCategorizationAppStateProps {
dataView: DataView;
@ -25,7 +26,9 @@ export const LogCategorizationAppState: FC<LogCategorizationAppStateProps> = ({
}) => {
return (
<AiopsAppContext.Provider value={appDependencies}>
<LogCategorizationPage dataView={dataView} savedSearch={savedSearch} />
<UrlStateProvider>
<LogCategorizationPage dataView={dataView} savedSearch={savedSearch} />
</UrlStateProvider>
</AiopsAppContext.Provider>
);
};

View file

@ -5,9 +5,12 @@
* 2.0.
*/
import { parse } from 'query-string';
import React, { FC } from 'react';
import { parse, stringify } from 'query-string';
import { createContext, useCallback, useContext, useMemo } from 'react';
import { decode } from 'rison-node';
import { decode, encode } from 'rison-node';
import { useHistory, useLocation } from 'react-router-dom';
import { isEqual } from 'lodash';
export interface Dictionary<TValue> {
[id: string]: TValue;
@ -87,6 +90,79 @@ export const aiopsUrlStateStore = createContext<UrlState>({
export const { Provider } = aiopsUrlStateStore;
export const UrlStateProvider: FC = ({ children }) => {
const { Provider: StateProvider } = aiopsUrlStateStore;
const history = useHistory();
const { search: urlSearchString } = useLocation();
const setUrlState: SetUrlState = useCallback(
(
accessor: Accessor,
attribute: string | Dictionary<any>,
value?: any,
replaceState?: boolean
) => {
const prevSearchString = urlSearchString;
const urlState = parseUrlState(prevSearchString);
const parsedQueryString = parse(prevSearchString, { sort: false });
if (!Object.prototype.hasOwnProperty.call(urlState, accessor)) {
urlState[accessor] = {};
}
if (typeof attribute === 'string') {
if (isEqual(getNestedProperty(urlState, `${accessor}.${attribute}`), value)) {
return prevSearchString;
}
urlState[accessor][attribute] = value;
} else {
const attributes = attribute;
Object.keys(attributes).forEach((a) => {
urlState[accessor][a] = attributes[a];
});
}
try {
const oldLocationSearchString = stringify(parsedQueryString, {
sort: false,
encode: false,
});
Object.keys(urlState).forEach((a) => {
if (isRisonSerializationRequired(a)) {
parsedQueryString[a] = encode(urlState[a]);
} else {
parsedQueryString[a] = urlState[a];
}
});
const newLocationSearchString = stringify(parsedQueryString, {
sort: false,
encode: false,
});
if (oldLocationSearchString !== newLocationSearchString) {
const newSearchString = stringify(parsedQueryString, { sort: false });
if (replaceState) {
history.replace({ search: newSearchString });
} else {
history.push({ search: newSearchString });
}
}
} catch (error) {
// eslint-disable-next-line no-console
console.error('Could not save url state', error);
}
},
[history, urlSearchString]
);
return (
<StateProvider value={{ searchString: urlSearchString, setUrlState }}>{children}</StateProvider>
);
};
export const useUrlState = (accessor: Accessor) => {
const { searchString, setUrlState: setUrlStateContext } = useContext(aiopsUrlStateStore);