mirror of https://github.com/apache/druid.git
Web console: don't crash if cookies are totally disabled (#13013)
* fix local storage detection * fix numeric input dialog
This commit is contained in:
parent
85d2a6d879
commit
0ae515bd3c
|
@ -27,7 +27,7 @@ export async function createBrowser(): Promise<playwright.Browser> {
|
|||
const headless = process.env['DRUID_E2E_TEST_HEADLESS'] || TRUE;
|
||||
const debug = headless !== TRUE;
|
||||
const launchOptions: any = {
|
||||
args: [`--window-size=${WIDTH},${HEIGHT + PADDING}`],
|
||||
args: [`--window-size=${WIDTH},${HEIGHT + PADDING}`, `--disable-local-storage`],
|
||||
};
|
||||
if (debug) {
|
||||
launchOptions.headless = false;
|
||||
|
|
|
@ -26,6 +26,7 @@ interface NumericInputDialogProps {
|
|||
message?: JSX.Element;
|
||||
minValue?: number;
|
||||
initValue: number;
|
||||
integer?: boolean;
|
||||
onSubmit(value: number): void;
|
||||
onClose(): void;
|
||||
}
|
||||
|
@ -33,9 +34,19 @@ interface NumericInputDialogProps {
|
|||
export const NumericInputDialog = React.memo(function NumericInputDialog(
|
||||
props: NumericInputDialogProps,
|
||||
) {
|
||||
const { title, message, minValue, initValue, onSubmit, onClose } = props;
|
||||
const { title, message, minValue, initValue, integer, onSubmit, onClose } = props;
|
||||
const effectiveMinValue = minValue ?? DEFAULT_MIN_VALUE;
|
||||
|
||||
const [value, setValue] = useState<number>(initValue);
|
||||
const [valueString, setValueString] = useState<string>(String(initValue));
|
||||
|
||||
function done() {
|
||||
let value = Math.max(Number(valueString) || 0, effectiveMinValue);
|
||||
if (integer) {
|
||||
value = Math.round(value);
|
||||
}
|
||||
onSubmit(value);
|
||||
onClose();
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
|
@ -48,30 +59,41 @@ export const NumericInputDialog = React.memo(function NumericInputDialog(
|
|||
<div className={Classes.DIALOG_BODY}>
|
||||
{message}
|
||||
<NumericInput
|
||||
value={value}
|
||||
onValueChange={(v: number) => {
|
||||
if (isNaN(v)) return;
|
||||
setValue(Math.max(v, DEFAULT_MIN_VALUE));
|
||||
value={valueString}
|
||||
onValueChange={(_, v) => {
|
||||
// Constrain to only simple numeric characters
|
||||
v = v.replace(/[^\d\-.]/, '');
|
||||
|
||||
if (integer) {
|
||||
// If in integer mode throw away the decimal point
|
||||
v = v.replace(/\./, '');
|
||||
}
|
||||
|
||||
if (effectiveMinValue >= 0) {
|
||||
// If in non-negative mode throw away the minus
|
||||
v = v.replace(/-/, '');
|
||||
}
|
||||
|
||||
setValueString(v);
|
||||
}}
|
||||
min={minValue ?? DEFAULT_MIN_VALUE}
|
||||
onKeyDown={(e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
if (e.key !== 'Enter') return;
|
||||
done();
|
||||
}}
|
||||
min={effectiveMinValue}
|
||||
stepSize={1}
|
||||
minorStepSize={null}
|
||||
majorStepSize={10}
|
||||
fill
|
||||
autoFocus
|
||||
selectAllOnFocus
|
||||
allowNumericCharactersOnly
|
||||
/>
|
||||
</div>
|
||||
<div className={Classes.DIALOG_FOOTER}>
|
||||
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
|
||||
<Button text="Close" onClick={onClose} />
|
||||
<Button
|
||||
text="OK"
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={() => {
|
||||
onSubmit(value);
|
||||
onClose();
|
||||
}}
|
||||
/>
|
||||
<Button text="OK" intent={Intent.PRIMARY} onClick={done} />
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
|
|
|
@ -18,6 +18,14 @@
|
|||
|
||||
import * as JSONBig from 'json-bigint-native';
|
||||
|
||||
function noLocalStorage(): boolean {
|
||||
try {
|
||||
return typeof localStorage === 'undefined';
|
||||
} catch {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export const LocalStorageKeys = {
|
||||
CAPABILITIES_OVERRIDE: 'capabilities-override' as const,
|
||||
INGESTION_SPEC: 'ingestion-spec' as const,
|
||||
|
@ -65,7 +73,7 @@ function prependNamespace(key: string): string {
|
|||
}
|
||||
|
||||
export function localStorageSet(key: LocalStorageKeys, value: string): void {
|
||||
if (typeof localStorage === 'undefined') return;
|
||||
if (noLocalStorage()) return;
|
||||
try {
|
||||
localStorage.setItem(prependNamespace(key), value);
|
||||
} catch (e) {
|
||||
|
@ -78,7 +86,7 @@ export function localStorageSetJson(key: LocalStorageKeys, value: any): void {
|
|||
}
|
||||
|
||||
export function localStorageGet(key: LocalStorageKeys): string | undefined {
|
||||
if (typeof localStorage === 'undefined') return;
|
||||
if (noLocalStorage()) return;
|
||||
try {
|
||||
return localStorage.getItem(prependNamespace(key)) || localStorage.getItem(key) || undefined;
|
||||
} catch (e) {
|
||||
|
@ -98,7 +106,7 @@ export function localStorageGetJson(key: LocalStorageKeys): any {
|
|||
}
|
||||
|
||||
export function localStorageRemove(key: LocalStorageKeys): void {
|
||||
if (typeof localStorage === 'undefined') return;
|
||||
if (noLocalStorage()) return;
|
||||
try {
|
||||
localStorage.removeItem(prependNamespace(key));
|
||||
} catch (e) {
|
||||
|
|
|
@ -103,6 +103,7 @@ export const MaxTasksButton = function MaxTasksButton(props: MaxTasksButtonProps
|
|||
</>
|
||||
}
|
||||
minValue={2}
|
||||
integer
|
||||
initValue={maxNumTasks}
|
||||
onSubmit={p => {
|
||||
changeQueryContext(changeMaxNumTasks(queryContext, p));
|
||||
|
|
Loading…
Reference in New Issue