mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-19 18:19:09 +08:00
feat: preferences framework generalised scaffolded
This commit is contained in:
parent
c7db85f44c
commit
5d52731c77
@ -240,6 +240,7 @@ function ExplorerOptions({
|
||||
dataSource: sourcepage,
|
||||
aggregateOperator: StringOperators.NOOP,
|
||||
});
|
||||
console.log('uncaught options in saved views', options);
|
||||
|
||||
const getUpdatedExtraData = (
|
||||
extraData: string | undefined,
|
||||
@ -338,6 +339,12 @@ function ExplorerOptions({
|
||||
backwardCompatibleOptions = omit(options, 'version');
|
||||
}
|
||||
|
||||
console.log('uncaught backwardCompatibleOptions', {
|
||||
backwardCompatibleOptions,
|
||||
esc: extraData?.selectColumns,
|
||||
osc: options.selectColumns,
|
||||
});
|
||||
|
||||
if (extraData.selectColumns?.length) {
|
||||
handleOptionsChange({
|
||||
...backwardCompatibleOptions,
|
||||
@ -419,6 +426,7 @@ function ExplorerOptions({
|
||||
|
||||
updatePreservedViewInLocalStorage(option);
|
||||
|
||||
console.log('uncaught options in saved views before call', options);
|
||||
updateOrRestoreSelectColumns(
|
||||
option.key,
|
||||
viewsData?.data?.data,
|
||||
|
@ -23,6 +23,7 @@ import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||
import useUrlQueryData from 'hooks/useUrlQueryData';
|
||||
import { isEqual, isNull } from 'lodash-es';
|
||||
import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback';
|
||||
import { usePreferenceContext } from 'providers/preferences/context/PreferenceContextProvider';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
@ -35,6 +36,9 @@ function LogsExplorer(): JSX.Element {
|
||||
const [selectedView, setSelectedView] = useState<SELECTED_VIEWS>(
|
||||
SELECTED_VIEWS.SEARCH,
|
||||
);
|
||||
const { preferences, updateFormatting } = usePreferenceContext();
|
||||
|
||||
console.log('uncaught preferences', preferences);
|
||||
const [showFilters, setShowFilters] = useState<boolean>(() => {
|
||||
const localStorageValue = getLocalStorageKey(
|
||||
LOCALSTORAGE.SHOW_LOGS_QUICK_FILTERS,
|
||||
@ -222,6 +226,21 @@ function LogsExplorer(): JSX.Element {
|
||||
</section>
|
||||
)}
|
||||
<section className={cx('log-module-right-section')}>
|
||||
{/* dummy button to test the updateFormatting function */}
|
||||
<div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={(): void => updateFormatting({ maxLines: 10 })}
|
||||
>
|
||||
<h1>Update formatting</h1>
|
||||
</button>
|
||||
</div>
|
||||
{preferences && (
|
||||
<div>
|
||||
<h1>Preferences</h1>
|
||||
<pre>{JSON.stringify(preferences, null, 2)}</pre>
|
||||
</div>
|
||||
)}
|
||||
<Toolbar
|
||||
showAutoRefresh={false}
|
||||
leftActions={
|
||||
|
@ -4,9 +4,14 @@ import { Compass, TowerControl, Workflow } from 'lucide-react';
|
||||
import LogsExplorer from 'pages/LogsExplorer';
|
||||
import Pipelines from 'pages/Pipelines';
|
||||
import SaveView from 'pages/SaveView';
|
||||
import { PreferenceContextProvider } from 'providers/preferences/context/PreferenceContextProvider';
|
||||
|
||||
export const logsExplorer: TabRoutes = {
|
||||
Component: LogsExplorer,
|
||||
Component: (): JSX.Element => (
|
||||
<PreferenceContextProvider>
|
||||
<LogsExplorer />
|
||||
</PreferenceContextProvider>
|
||||
),
|
||||
name: (
|
||||
<div className="tab-item">
|
||||
<Compass size={16} /> Explorer
|
||||
|
@ -0,0 +1,66 @@
|
||||
/* eslint-disable no-empty */
|
||||
import getLocalStorageKey from 'api/browser/localstorage/get';
|
||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||
import { defaultLogsSelectedColumns } from 'container/OptionsMenu/constants';
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
|
||||
import { FormattingOptions } from '../types';
|
||||
|
||||
// --- LOGS preferences loader config ---
|
||||
const logsLoaders = {
|
||||
local: async (): Promise<{
|
||||
columns: BaseAutocompleteData[];
|
||||
formatting: FormattingOptions;
|
||||
}> => {
|
||||
const local = getLocalStorageKey(LOCALSTORAGE.LOGS_LIST_OPTIONS);
|
||||
if (local) {
|
||||
try {
|
||||
const parsed = JSON.parse(local);
|
||||
return {
|
||||
columns: parsed.selectColumns || [],
|
||||
formatting: {
|
||||
maxLines: parsed.maxLines ?? 2,
|
||||
format: parsed.format ?? 'table',
|
||||
fontSize: parsed.fontSize ?? 'small',
|
||||
version: parsed.version ?? 1,
|
||||
},
|
||||
};
|
||||
} catch {}
|
||||
}
|
||||
return { columns: [], formatting: undefined } as any;
|
||||
},
|
||||
url: async (): Promise<{
|
||||
columns: BaseAutocompleteData[];
|
||||
formatting: FormattingOptions;
|
||||
}> => {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
try {
|
||||
const options = JSON.parse(urlParams.get('options') || '{}');
|
||||
return {
|
||||
columns: options.selectColumns || [],
|
||||
formatting: {
|
||||
maxLines: options.maxLines ?? 2,
|
||||
format: options.format ?? 'table',
|
||||
fontSize: options.fontSize ?? 'small',
|
||||
version: options.version ?? 1,
|
||||
},
|
||||
};
|
||||
} catch {}
|
||||
return { columns: [], formatting: undefined } as any;
|
||||
},
|
||||
default: async (): Promise<{
|
||||
columns: BaseAutocompleteData[];
|
||||
formatting: FormattingOptions;
|
||||
}> => ({
|
||||
columns: defaultLogsSelectedColumns as BaseAutocompleteData[],
|
||||
formatting: {
|
||||
maxLines: 2,
|
||||
format: 'table',
|
||||
fontSize: 'small',
|
||||
version: 1,
|
||||
},
|
||||
}),
|
||||
priority: ['local', 'url', 'default'] as const,
|
||||
};
|
||||
|
||||
export default logsLoaders;
|
@ -0,0 +1,45 @@
|
||||
import setLocalStorageKey from 'api/browser/localstorage/set';
|
||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
|
||||
import { FormattingOptions } from '../types';
|
||||
|
||||
// --- LOGS preferences updater config ---
|
||||
const logsUpdater = {
|
||||
updateColumns: (newColumns: BaseAutocompleteData[], mode: string): void => {
|
||||
// Always update URL
|
||||
const url = new URL(window.location.href);
|
||||
const options = JSON.parse(url.searchParams.get('options') || '{}');
|
||||
options.selectColumns = newColumns;
|
||||
url.searchParams.set('options', JSON.stringify(options));
|
||||
window.history.replaceState({}, '', url.toString());
|
||||
|
||||
if (mode === 'direct') {
|
||||
// Also update local storage
|
||||
const local = JSON.parse(
|
||||
localStorage.getItem(LOCALSTORAGE.LOGS_LIST_OPTIONS) || '{}',
|
||||
);
|
||||
local.selectColumns = newColumns;
|
||||
setLocalStorageKey(LOCALSTORAGE.LOGS_LIST_OPTIONS, JSON.stringify(local));
|
||||
}
|
||||
},
|
||||
updateFormatting: (newFormatting: FormattingOptions, mode: string): void => {
|
||||
// Always update URL
|
||||
const url = new URL(window.location.href);
|
||||
const options = JSON.parse(url.searchParams.get('options') || '{}');
|
||||
Object.assign(options, newFormatting);
|
||||
url.searchParams.set('options', JSON.stringify(options));
|
||||
window.history.replaceState({}, '', url.toString());
|
||||
|
||||
if (mode === 'direct') {
|
||||
// Also update local storage
|
||||
const local = JSON.parse(
|
||||
localStorage.getItem(LOCALSTORAGE.LOGS_LIST_OPTIONS) || '{}',
|
||||
);
|
||||
Object.assign(local, newFormatting);
|
||||
setLocalStorageKey(LOCALSTORAGE.LOGS_LIST_OPTIONS, JSON.stringify(local));
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default logsUpdater;
|
@ -0,0 +1,43 @@
|
||||
/* eslint-disable no-empty */
|
||||
import getLocalStorageKey from 'api/browser/localstorage/get';
|
||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||
import { defaultTraceSelectedColumns } from 'container/OptionsMenu/constants';
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
|
||||
// --- TRACES preferences loader config ---
|
||||
const tracesLoaders = {
|
||||
local: async (): Promise<{
|
||||
columns: BaseAutocompleteData[];
|
||||
}> => {
|
||||
const local = getLocalStorageKey(LOCALSTORAGE.TRACES_LIST_OPTIONS);
|
||||
if (local) {
|
||||
try {
|
||||
const parsed = JSON.parse(local);
|
||||
return {
|
||||
columns: parsed.selectColumns || [],
|
||||
};
|
||||
} catch {}
|
||||
}
|
||||
return { columns: [] };
|
||||
},
|
||||
url: async (): Promise<{
|
||||
columns: BaseAutocompleteData[];
|
||||
}> => {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
try {
|
||||
const options = JSON.parse(urlParams.get('options') || '{}');
|
||||
return {
|
||||
columns: options.selectColumns || [],
|
||||
};
|
||||
} catch {}
|
||||
return { columns: [] };
|
||||
},
|
||||
default: async (): Promise<{
|
||||
columns: BaseAutocompleteData[];
|
||||
}> => ({
|
||||
columns: defaultTraceSelectedColumns as BaseAutocompleteData[],
|
||||
}),
|
||||
priority: ['local', 'url', 'default'] as const,
|
||||
};
|
||||
|
||||
export default tracesLoaders;
|
@ -0,0 +1,25 @@
|
||||
import setLocalStorageKey from 'api/browser/localstorage/set';
|
||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
|
||||
// --- TRACES preferences updater config ---
|
||||
const tracesUpdater = {
|
||||
updateColumns: (newColumns: BaseAutocompleteData[], mode: string): void => {
|
||||
const url = new URL(window.location.href);
|
||||
const options = JSON.parse(url.searchParams.get('options') || '{}');
|
||||
options.selectColumns = newColumns;
|
||||
url.searchParams.set('options', JSON.stringify(options));
|
||||
window.history.replaceState({}, '', url.toString());
|
||||
|
||||
if (mode === 'direct') {
|
||||
const local = JSON.parse(
|
||||
localStorage.getItem(LOCALSTORAGE.TRACES_LIST_OPTIONS) || '{}',
|
||||
);
|
||||
local.selectColumns = newColumns;
|
||||
setLocalStorageKey(LOCALSTORAGE.TRACES_LIST_OPTIONS, JSON.stringify(local));
|
||||
}
|
||||
},
|
||||
updateFormatting: (): void => {}, // no-op for traces
|
||||
};
|
||||
|
||||
export default tracesUpdater;
|
@ -0,0 +1,78 @@
|
||||
import { PreferenceContextValue } from 'providers/preferences/types';
|
||||
import React, { createContext, useContext, useMemo } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
import { usePreferenceSync } from '../sync/usePreferenceSync';
|
||||
|
||||
// This will help in identifying the mode of the preference context
|
||||
// savedView - when the preference is loaded from a saved view
|
||||
// direct - when the preference is loaded from a direct query
|
||||
|
||||
export type PreferenceMode = 'savedView' | 'direct';
|
||||
|
||||
const PreferenceContext = createContext<PreferenceContextValue | undefined>(
|
||||
undefined,
|
||||
);
|
||||
|
||||
export function PreferenceContextProvider({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}): JSX.Element {
|
||||
const location = useLocation();
|
||||
const params = new URLSearchParams(location.search);
|
||||
|
||||
const savedViewId = params.get('view');
|
||||
let dataSource: DataSource = DataSource.LOGS;
|
||||
if (location.pathname.includes('traces')) dataSource = DataSource.TRACES;
|
||||
|
||||
const {
|
||||
preferences,
|
||||
loading,
|
||||
error,
|
||||
updateColumns,
|
||||
updateFormatting,
|
||||
} = usePreferenceSync({
|
||||
mode: savedViewId ? 'savedView' : 'direct',
|
||||
savedViewId: savedViewId || undefined,
|
||||
dataSource,
|
||||
});
|
||||
|
||||
const value = useMemo<PreferenceContextValue>(
|
||||
() => ({
|
||||
preferences,
|
||||
loading,
|
||||
error,
|
||||
mode: savedViewId ? 'savedView' : 'direct',
|
||||
savedViewId: savedViewId || undefined,
|
||||
dataSource,
|
||||
updateColumns,
|
||||
updateFormatting,
|
||||
}),
|
||||
[
|
||||
savedViewId,
|
||||
dataSource,
|
||||
preferences,
|
||||
loading,
|
||||
error,
|
||||
updateColumns,
|
||||
updateFormatting,
|
||||
],
|
||||
);
|
||||
|
||||
return (
|
||||
<PreferenceContext.Provider value={value}>
|
||||
{children}
|
||||
</PreferenceContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function usePreferenceContext(): PreferenceContextValue {
|
||||
const ctx = useContext(PreferenceContext);
|
||||
if (!ctx)
|
||||
throw new Error(
|
||||
'usePreferenceContext must be used within PreferenceContextProvider',
|
||||
);
|
||||
return ctx;
|
||||
}
|
130
frontend/src/providers/preferences/loader/usePreferenceLoader.ts
Normal file
130
frontend/src/providers/preferences/loader/usePreferenceLoader.ts
Normal file
@ -0,0 +1,130 @@
|
||||
/* eslint-disable sonarjs/cognitive-complexity */
|
||||
/* eslint-disable no-empty */
|
||||
import {
|
||||
defaultLogsSelectedColumns,
|
||||
defaultTraceSelectedColumns,
|
||||
} from 'container/OptionsMenu/constants';
|
||||
import { useGetAllViews } from 'hooks/saveViews/useGetAllViews';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
import logsLoaderConfig from '../configs/logsLoaderConfig';
|
||||
import tracesLoaderConfig from '../configs/tracesLoaderConfig';
|
||||
import { FormattingOptions, PreferenceMode, Preferences } from '../types';
|
||||
|
||||
// Generic preferences loader that works with any config
|
||||
async function preferencesLoader<T>(config: {
|
||||
priority: readonly string[];
|
||||
[key: string]: any;
|
||||
}): Promise<T> {
|
||||
const findValidLoader = async (): Promise<T> => {
|
||||
// Try each loader in priority order
|
||||
const results = await Promise.all(
|
||||
config.priority.map(async (source) => ({
|
||||
source,
|
||||
result: await config[source](),
|
||||
})),
|
||||
);
|
||||
// Find the first result with columns
|
||||
const validResult = results.find(({ result }) => result.columns.length);
|
||||
if (validResult) {
|
||||
return validResult.result;
|
||||
}
|
||||
// fallback to default
|
||||
return config.default();
|
||||
};
|
||||
|
||||
return findValidLoader();
|
||||
}
|
||||
|
||||
// Use the generic loader with specific configs
|
||||
async function logsPreferencesLoader(): Promise<{
|
||||
columns: BaseAutocompleteData[];
|
||||
formatting: FormattingOptions;
|
||||
}> {
|
||||
return preferencesLoader(logsLoaderConfig);
|
||||
}
|
||||
|
||||
async function tracesPreferencesLoader(): Promise<{
|
||||
columns: BaseAutocompleteData[];
|
||||
}> {
|
||||
return preferencesLoader(tracesLoaderConfig);
|
||||
}
|
||||
|
||||
export function usePreferenceLoader({
|
||||
mode,
|
||||
savedViewId,
|
||||
dataSource,
|
||||
reSync,
|
||||
}: {
|
||||
mode: PreferenceMode;
|
||||
savedViewId: string;
|
||||
dataSource: DataSource;
|
||||
reSync: number;
|
||||
}): {
|
||||
preferences: Preferences | null;
|
||||
loading: boolean;
|
||||
error: Error | null;
|
||||
} {
|
||||
const [preferences, setPreferences] = useState<Preferences | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
const location = useLocation();
|
||||
|
||||
const { data: viewsData } = useGetAllViews(dataSource);
|
||||
|
||||
console.log('uncaught viewsData', viewsData);
|
||||
|
||||
useEffect((): void => {
|
||||
async function loadPreferences(): Promise<void> {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
if (mode === 'savedView' && savedViewId) {
|
||||
// we can also switch to the URL options params
|
||||
// as we are essentially setting the options in the URL
|
||||
// in ExplorerOptions.tsx#430 (updateOrRestoreSelectColumns)
|
||||
const extraData = viewsData?.data?.data?.find(
|
||||
(view) => view.id === savedViewId,
|
||||
)?.extraData;
|
||||
|
||||
const parsedExtraData = JSON.parse(extraData || '{}');
|
||||
let columns: BaseAutocompleteData[] = [];
|
||||
let formatting: FormattingOptions | undefined;
|
||||
if (dataSource === DataSource.LOGS) {
|
||||
columns = parsedExtraData?.selectColumns || defaultLogsSelectedColumns;
|
||||
formatting = {
|
||||
maxLines: parsedExtraData?.maxLines ?? 2,
|
||||
format: parsedExtraData?.format ?? 'table',
|
||||
fontSize: parsedExtraData?.fontSize ?? 'small',
|
||||
version: parsedExtraData?.version ?? 1,
|
||||
};
|
||||
} else if (dataSource === DataSource.TRACES) {
|
||||
columns = parsedExtraData?.selectColumns || defaultTraceSelectedColumns;
|
||||
}
|
||||
setPreferences({ columns, formatting });
|
||||
} else {
|
||||
if (dataSource === DataSource.LOGS) {
|
||||
const { columns, formatting } = await logsPreferencesLoader();
|
||||
setPreferences({ columns, formatting });
|
||||
}
|
||||
|
||||
if (dataSource === DataSource.TRACES) {
|
||||
const { columns } = await tracesPreferencesLoader();
|
||||
setPreferences({ columns });
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
setError(e as Error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
loadPreferences();
|
||||
}, [mode, savedViewId, dataSource, location, reSync, viewsData]);
|
||||
|
||||
return { preferences, loading, error };
|
||||
}
|
41
frontend/src/providers/preferences/sync/usePreferenceSync.ts
Normal file
41
frontend/src/providers/preferences/sync/usePreferenceSync.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import { useState } from 'react';
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
import { usePreferenceLoader } from '../loader/usePreferenceLoader';
|
||||
import { FormattingOptions, PreferenceMode, Preferences } from '../types';
|
||||
import { usePreferenceUpdater } from '../updater/usePreferenceUpdater';
|
||||
|
||||
export function usePreferenceSync({
|
||||
mode,
|
||||
dataSource,
|
||||
savedViewId,
|
||||
}: {
|
||||
mode: PreferenceMode;
|
||||
dataSource: DataSource;
|
||||
savedViewId: string | undefined;
|
||||
}): {
|
||||
preferences: Preferences | null;
|
||||
loading: boolean;
|
||||
error: Error | null;
|
||||
updateColumns: (newColumns: BaseAutocompleteData[]) => void;
|
||||
updateFormatting: (newFormatting: FormattingOptions) => void;
|
||||
} {
|
||||
// We are using a reSync state because we have URL updates as well as local storage updates
|
||||
// and we want to make sure we are always using the latest preferences
|
||||
const [reSync, setReSync] = useState(0);
|
||||
const { preferences, loading, error } = usePreferenceLoader({
|
||||
mode,
|
||||
savedViewId: savedViewId || '',
|
||||
dataSource,
|
||||
reSync,
|
||||
});
|
||||
|
||||
const { updateColumns, updateFormatting } = usePreferenceUpdater({
|
||||
dataSource,
|
||||
mode,
|
||||
setReSync,
|
||||
});
|
||||
|
||||
return { preferences, loading, error, updateColumns, updateFormatting };
|
||||
}
|
27
frontend/src/providers/preferences/types/index.ts
Normal file
27
frontend/src/providers/preferences/types/index.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
export type PreferenceMode = 'savedView' | 'direct';
|
||||
|
||||
export interface PreferenceContextValue {
|
||||
preferences: Preferences | null;
|
||||
loading: boolean;
|
||||
error: Error | null;
|
||||
mode: PreferenceMode;
|
||||
savedViewId?: string;
|
||||
dataSource: DataSource;
|
||||
updateColumns: (newColumns: BaseAutocompleteData[]) => void;
|
||||
updateFormatting: (newFormatting: FormattingOptions) => void;
|
||||
}
|
||||
|
||||
export interface FormattingOptions {
|
||||
maxLines?: number;
|
||||
format?: 'raw' | 'table';
|
||||
fontSize?: 'small' | 'medium' | 'large';
|
||||
version?: number;
|
||||
}
|
||||
|
||||
export interface Preferences {
|
||||
columns: BaseAutocompleteData[];
|
||||
formatting?: FormattingOptions;
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
import { Dispatch, SetStateAction } from 'react';
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
import logsUpdater from '../configs/logsUpdaterConfig';
|
||||
import tracesUpdater from '../configs/tracesUpdaterConfig';
|
||||
import { FormattingOptions } from '../types';
|
||||
|
||||
const metricsUpdater = {
|
||||
updateColumns: (): void => {}, // no-op for metrics
|
||||
updateFormatting: (): void => {}, // no-op for metrics
|
||||
};
|
||||
|
||||
const updaterConfig: Record<
|
||||
DataSource,
|
||||
{
|
||||
updateColumns: (newColumns: BaseAutocompleteData[], mode: string) => void;
|
||||
updateFormatting: (newFormatting: FormattingOptions, mode: string) => void;
|
||||
}
|
||||
> = {
|
||||
[DataSource.LOGS]: logsUpdater,
|
||||
[DataSource.TRACES]: tracesUpdater,
|
||||
[DataSource.METRICS]: metricsUpdater,
|
||||
};
|
||||
|
||||
export function usePreferenceUpdater({
|
||||
dataSource,
|
||||
mode,
|
||||
setReSync,
|
||||
}: {
|
||||
dataSource: DataSource;
|
||||
mode: string;
|
||||
setReSync: Dispatch<SetStateAction<number>>;
|
||||
}): {
|
||||
updateColumns: (newColumns: BaseAutocompleteData[]) => void;
|
||||
updateFormatting: (newFormatting: FormattingOptions) => void;
|
||||
} {
|
||||
const updater = updaterConfig[dataSource];
|
||||
|
||||
return {
|
||||
updateColumns: (newColumns: BaseAutocompleteData[]): void => {
|
||||
updater.updateColumns(newColumns, mode);
|
||||
setReSync((prev: number) => prev + 1);
|
||||
},
|
||||
updateFormatting: (newFormatting: FormattingOptions): void => {
|
||||
updater.updateFormatting(newFormatting, mode);
|
||||
setReSync((prev: number) => prev + 1);
|
||||
},
|
||||
};
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user