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;
+}