diff --git a/packages/ui/src/ui/pages/tablet-errors-by-bundle/TabletErrorsByBundle.tsx b/packages/ui/src/ui/pages/tablet-errors-by-bundle/TabletErrorsByBundle.tsx index 0f018213ac..4a365952b8 100644 --- a/packages/ui/src/ui/pages/tablet-errors-by-bundle/TabletErrorsByBundle.tsx +++ b/packages/ui/src/ui/pages/tablet-errors-by-bundle/TabletErrorsByBundle.tsx @@ -18,7 +18,9 @@ import { getTabletErrorsByBundleError, getTabletErrorsByBundleLoaded, getTabletErrorsByBundleLoading, + getTabletErrorsByBundleMethodsFilter, getTabletErrorsByBundlePageFilter, + getTabletErrorsByBundleTimeRangeFilter, } from '../../store/selectors/tablet-errors/tablet-errors-by-bundle'; import Link from '../../components/Link/Link'; @@ -63,6 +65,8 @@ export function TabletErrorsByBundle({bundle}: {bundle: string}) { function useTabletErrorsColumns(loading: boolean) { const {errors: data = []} = useSelector(getTabletErrorsByBundle) ?? {}; const pageFilter = useSelector(getTabletErrorsByBundlePageFilter); + const teMethods = useSelector(getTabletErrorsByBundleMethodsFilter); + const teTime = useSelector(getTabletErrorsByBundleTimeRangeFilter); const columns = React.useMemo(() => { type Method = keyof (typeof data)[number]['method_counts']; @@ -86,7 +90,15 @@ function useTabletErrorsColumns(loading: boolean) { ), render({row}) { return ( - + {row.table_path} ); @@ -114,7 +126,7 @@ function useTabletErrorsColumns(loading: boolean) { ]; return res; - }, [data, loading]); + }, [data, loading, teMethods, teTime]); return {data, columns}; } diff --git a/packages/ui/src/ui/store/reducers/navigation/tabs/tablet-errors/tablet-errors-by-path.ts b/packages/ui/src/ui/store/reducers/navigation/tabs/tablet-errors/tablet-errors-by-path.ts index 411966a662..4b560b70db 100644 --- a/packages/ui/src/ui/store/reducers/navigation/tabs/tablet-errors/tablet-errors-by-path.ts +++ b/packages/ui/src/ui/store/reducers/navigation/tabs/tablet-errors/tablet-errors-by-path.ts @@ -3,7 +3,7 @@ import {YTError} from '../../../../../types'; import {TabletErrorsApi} from '../../../../../../shared/tablet-errors-manager'; import {mergeStateOnClusterChange} from '../../../utils'; -export type TabletErrorsFromApiState = { +export type TabletErrorsByPathState = { loading: boolean; loaded: boolean; error: YTError | undefined; @@ -24,7 +24,7 @@ export type TabletErrorsFromApiState = { }; const persistentState: Pick< - TabletErrorsFromApiState, + TabletErrorsByPathState, 'timeRangeFilter' | 'methodsFilter' | 'pageFilter' | 'tabletIdFilter' > = { timeRangeFilter: {shortcutValue: '1d'}, @@ -33,7 +33,7 @@ const persistentState: Pick< tabletIdFilter: '', }; -const ephemeralState: Omit = { +const ephemeralState: Omit = { loading: false, loaded: false, error: undefined, @@ -44,7 +44,7 @@ const ephemeralState: Omit>, + {payload}: PayloadAction>, ) { const {table_path, table_id} = payload; if (table_path != state.table_path || table_id !== state.table_id) { @@ -65,12 +65,12 @@ const tabletErrorsByPathSlice = createSlice({ { payload, }: PayloadAction< - Pick + Pick >, ) { return {...state, ...payload, loading: false, loaded: true, error: undefined}; }, - onError(state, {payload: {error}}: PayloadAction>) { + onError(state, {payload: {error}}: PayloadAction>) { return {...state, error, loading: false}; }, updateFilter(state, {payload}: PayloadAction>) { diff --git a/packages/ui/src/ui/store/reducers/tablet-errors/tablet-errors-by-bundle.ts b/packages/ui/src/ui/store/reducers/tablet-errors/tablet-errors-by-bundle.ts index 0003d61f14..0952b024aa 100644 --- a/packages/ui/src/ui/store/reducers/tablet-errors/tablet-errors-by-bundle.ts +++ b/packages/ui/src/ui/store/reducers/tablet-errors/tablet-errors-by-bundle.ts @@ -12,7 +12,7 @@ export type TabletErrorsByBundleState = { data: TabletErrorsApi['tablet_errors_by_bundle']['response'] | undefined; timeRangeFilter: - | {shortcutValue?: string; from?: number; to?: number} + | {shortcutValue: string; from?: number; to?: number} | {from: number; to: number; shortcutValue?: undefined}; methodsFilter: Array; @@ -36,7 +36,7 @@ const ephemeralState: Omit { + return updateByLocationParams({draft, query}, tabletErrorsByBundleParams); + }); +} diff --git a/packages/ui/src/ui/store/reducers/tablet_cell_bundles/url-mapping.ts b/packages/ui/src/ui/store/reducers/tablet_cell_bundles/url-mapping.ts index 0d22c812ad..681ec033ea 100644 --- a/packages/ui/src/ui/store/reducers/tablet_cell_bundles/url-mapping.ts +++ b/packages/ui/src/ui/store/reducers/tablet_cell_bundles/url-mapping.ts @@ -4,12 +4,17 @@ import {produce} from 'immer'; import {updateIfChanged} from '../../../utils/utils'; import {aclFiltersParams, getAclFiltersPreparedState} from '../acl/url-mapping'; import {parseSortState} from '../../../utils'; +import { + getTabletErrorsByBundlereparedState, + tabletErrorsByBundleParams, +} from '../tablet-errors/url-mapping'; export const tabletsBundlesParams = { activeBundle: { stateKey: 'tablet_cell_bundles.activeBundle', initialState: initialState.activeBundle, }, + ...tabletErrorsByBundleParams, }; export function getTabletsBundlesPreparedState( @@ -17,7 +22,7 @@ export function getTabletsBundlesPreparedState( {query}: {query: RootState}, ): RootState { const queryTcb = query.tablet_cell_bundles; - return produce(state, (draft) => { + const res = produce(state, (draft) => { const draftTcb = draft.tablet_cell_bundles; updateIfChanged(draftTcb, 'activeBundle', queryTcb.activeBundle); @@ -27,6 +32,7 @@ export function getTabletsBundlesPreparedState( updateIfChanged(draftTcb, 'bundlesSort', queryTcb.bundlesSort); updateIfChanged(draftTcb, 'bundlesTableMode', queryTcb.bundlesTableMode); }); + return getTabletErrorsByBundlereparedState(res, {query}); } export const tabletsAllBundlesParams = { diff --git a/packages/ui/src/ui/utils/app-url.ts b/packages/ui/src/ui/utils/app-url/index.ts similarity index 56% rename from packages/ui/src/ui/utils/app-url.ts rename to packages/ui/src/ui/utils/app-url/index.ts index e710d4b726..c619b862b7 100644 --- a/packages/ui/src/ui/utils/app-url.ts +++ b/packages/ui/src/ui/utils/app-url/index.ts @@ -1,8 +1,8 @@ -import {Page} from '../../shared/constants/settings'; -import {Tab as ComponentsTab} from '../constants/components/main'; -import YT from '../config/yt-config'; -import type {Tab as NavigationTab} from '../constants/navigation'; -import {ValueOf} from '../types'; +import {Page} from '../../../shared/constants/settings'; +import {Tab as ComponentsTab} from '../../constants/components/main'; +import YT from '../../config/yt-config'; + +export * from './navigation'; export function makeComponentsNodesUrl({host, cluster}: {host?: string; cluster?: string} = {}) { return host @@ -14,18 +14,6 @@ export function makeProxyUrl(cluster: string, address: string) { return `/${cluster}/${Page.COMPONENTS}/${ComponentsTab.RPC_PROXIES}?host=${address}`; } -export function makeNavigationLink(params: { - path: string; - cluster?: string; - navmode?: ValueOf; - teMode?: 'request_errors'; -}) { - const {cluster, ...rest} = params; - const res = `/${cluster || YT.cluster}/${Page.NAVIGATION}`; - const search = new URLSearchParams(rest).toString(); - return search ? `${res}?${search}` : res; -} - export function makeSchedulingUrl({ pool, poolTree, diff --git a/packages/ui/src/ui/utils/app-url/navigation.ts b/packages/ui/src/ui/utils/app-url/navigation.ts new file mode 100644 index 0000000000..c6b415711c --- /dev/null +++ b/packages/ui/src/ui/utils/app-url/navigation.ts @@ -0,0 +1,22 @@ +import {Page} from '../../../shared/constants/settings'; +import YT from '../../config/yt-config'; +import type {Tab as NavigationTab} from '../../constants/navigation'; +import {ValueOf} from '../../types'; + +import {TabletErrorsByPathState} from '../../store/reducers/navigation/tabs/tablet-errors/tablet-errors-by-path'; +import {navigationParams} from '../../store/reducers/navigation/url-mapping'; +import {makeURLSearchParams} from './utils'; + +export function makeNavigationLink(params: { + path: string; + cluster?: string; + navmode?: ValueOf; + teMode?: 'request_errors'; + teTime?: TabletErrorsByPathState['timeRangeFilter']; + teMethods?: Array; +}) { + const {cluster, ...rest} = params; + const res = `/${cluster || YT.cluster}/${Page.NAVIGATION}`; + const search = makeURLSearchParams(rest, navigationParams).toString(); + return search ? `${res}?${search}` : res; +} diff --git a/packages/ui/src/ui/utils/app-url/utils.ts b/packages/ui/src/ui/utils/app-url/utils.ts new file mode 100644 index 0000000000..0d7b17e3bf --- /dev/null +++ b/packages/ui/src/ui/utils/app-url/utils.ts @@ -0,0 +1,20 @@ +import {LocationParameters} from '../../store/location'; + +export function makeURLSearchParams(params: T, info: LocationParameters) { + const res = new URLSearchParams(); + Object.keys(params).reduce((acc, k) => { + const value = params[k as keyof T]; + if (k in info) { + if (info[k].options?.serialize) { + const tmp = info[k].options?.serialize?.(value); + if (tmp !== undefined) { + res.append(k, tmp + ''); + } + } else { + res.append(k, value + ''); + } + } + return acc; + }, res); + return res; +}