Web console: make it possible to namespace local storage, auto flatten spec generator should deal better with bad data (#12238)

* improve computeFlattenExprsForData

* allow local storage namespacing

* add test
This commit is contained in:
Vadim Ogievetsky 2022-02-07 18:52:41 -08:00 committed by GitHub
parent ced1389d4c
commit 090c429c8c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 30 additions and 15 deletions

View File

@ -49,6 +49,7 @@ describe('spec-utils', () => {
],
value: 2,
},
'Curveball' as any,
];
it('works for path, ignore-arrays', () => {

View File

@ -82,13 +82,15 @@ export function computeFlattenExprsForData(
data: Record<string, any>[],
exprType: ExprType,
arrayHandling: ArrayHandling,
includeTopLevel = false,
): string[] {
const seenPaths: Record<string, boolean> = {};
for (const datum of data) {
if (!datum || typeof datum !== 'object') continue;
const datumKeys = Object.keys(datum);
for (const datumKey of datumKeys) {
const datumValue = datum[datumKey];
if (isNested(datumValue)) {
if (includeTopLevel || isNested(datumValue)) {
addPath(
seenPaths,
exprType === 'path' ? `$.${datumKey}` : `.${datumKey}`,

View File

@ -29,6 +29,7 @@ import { bootstrapReactTable } from './bootstrap/react-table-defaults';
import { ConsoleApplication } from './console-application';
import { Links, setLinkOverrides } from './links';
import { Api, UrlBaser } from './singletons';
import { setLocalStorageNamespace } from './utils';
import './entry.scss';
@ -63,6 +64,9 @@ interface ConsoleConfig {
// Allow for link overriding to different docs
linkOverrides?: Links;
// Allow for namespacing the local storage in case multiple clusters share a URL due to proxying
localStorageNamespace?: string;
}
const consoleConfig: ConsoleConfig = (window as any).consoleConfig;
@ -89,6 +93,10 @@ if (consoleConfig.linkOverrides) {
setLinkOverrides(consoleConfig.linkOverrides);
}
if (consoleConfig.localStorageNamespace) {
setLocalStorageNamespace(consoleConfig.localStorageNamespace);
}
QueryRunner.defaultQueryExecutor = (payload, isSql, cancelToken) => {
return Api.instance.post(`/druid/v2${isSql ? '/sql' : ''}`, payload, { cancelToken });
};

View File

@ -16,28 +16,22 @@
* limitations under the License.
*/
import * as JSONBig from 'json-bigint-native';
import { Dispatch, SetStateAction, useState } from 'react';
import { localStorageGetJson, LocalStorageKeys, localStorageSetJson } from '../utils';
export function useLocalStorageState<T>(
key: string,
key: LocalStorageKeys,
initialValue?: T,
): [T, Dispatch<SetStateAction<T>>] {
const [state, setState] = useState(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSONBig.parse(item) : initialValue;
} catch {
return initialValue;
}
return localStorageGetJson(key) || initialValue;
});
const setValue: Dispatch<SetStateAction<T>> = (value: T | ((prevState: T) => T)) => {
const valueToStore = value instanceof Function ? value(state) : value;
setState(valueToStore);
try {
window.localStorage.setItem(key, JSONBig.stringify(valueToStore));
} catch {}
localStorageSetJson(key, valueToStore);
};
return [state, setValue];
}

View File

@ -44,10 +44,20 @@ export type LocalStorageKeys = typeof LocalStorageKeys[keyof typeof LocalStorage
// ----------------------------
let localStorageNamespace: string | undefined;
export function setLocalStorageNamespace(namespace: string) {
localStorageNamespace = namespace;
}
function prependNamespace(key: string): string {
return localStorageNamespace ? `${localStorageNamespace}:${key}` : key;
}
export function localStorageSet(key: LocalStorageKeys, value: string): void {
if (typeof localStorage === 'undefined') return;
try {
localStorage.setItem(key, value);
localStorage.setItem(prependNamespace(key), value);
} catch (e) {
console.error('Issue setting local storage key', e);
}
@ -60,7 +70,7 @@ export function localStorageSetJson(key: LocalStorageKeys, value: any): void {
export function localStorageGet(key: LocalStorageKeys): string | undefined {
if (typeof localStorage === 'undefined') return;
try {
return localStorage.getItem(key) || undefined;
return localStorage.getItem(prependNamespace(key)) || localStorage.getItem(key) || undefined;
} catch (e) {
console.error('Issue getting local storage key', e);
return;
@ -80,7 +90,7 @@ export function localStorageGetJson(key: LocalStorageKeys): any {
export function localStorageRemove(key: LocalStorageKeys): void {
if (typeof localStorage === 'undefined') return;
try {
localStorage.removeItem(key);
localStorage.removeItem(prependNamespace(key));
} catch (e) {
console.error('Issue removing local storage key', e);
}