mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-05 16:10:43 +00:00
fix(ui): Auto Run does not wait on the filter builder's resting picker
The builder reopens its field list after each condition, and live preview held any open listbox for up to 5 s, so a PromQL label pick ran the chart about 5 s late instead of right away as on main. The resting list is now marked and not waited on; a list mid-edit still is.
This commit is contained in:
@@ -123,6 +123,33 @@ async function addEq(field: string, value: string) {
|
||||
}
|
||||
|
||||
describe("FilterBuilder", () => {
|
||||
describe("resting list signal for live preview", () => {
|
||||
const listbox = () => document.body.querySelector<HTMLElement>('[role="listbox"]');
|
||||
const resting = () => listbox()?.hasAttribute("data-list-resting");
|
||||
|
||||
it("marks only the list reopened after a commit as resting, never one mid-edit", async () => {
|
||||
mountBuilder("promql-builder", []);
|
||||
await find("input").trigger("click");
|
||||
await flushPromises();
|
||||
expect(resting()).toBe(true);
|
||||
await type("lev");
|
||||
expect(resting()).toBe(false);
|
||||
await type("level");
|
||||
await press("Enter");
|
||||
expect(listbox()).not.toBeNull();
|
||||
expect(resting()).toBe(false);
|
||||
await pickRow("eq");
|
||||
expect(resting()).toBe(false);
|
||||
await type("error");
|
||||
await press("Enter");
|
||||
expect(listbox()).not.toBeNull();
|
||||
expect(resting()).toBe(true);
|
||||
await find("chip-level-value").trigger("click");
|
||||
await flushPromises();
|
||||
expect(resting()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("server switch for the extended engine operators", () => {
|
||||
const EXTENDED = ["in", "not_in", "starts_with", "ends_with", "regex", "not_regex"];
|
||||
|
||||
|
||||
@@ -202,6 +202,11 @@ const emptyText = computed(() => {
|
||||
return t("filterBar.noOperators");
|
||||
});
|
||||
|
||||
// Reopened for the next condition with nothing typed: offering a pick, not holding an edit.
|
||||
const resting = computed(
|
||||
() => step.value === "field" && !text.value && !editingId.value && !draft.value,
|
||||
);
|
||||
|
||||
const multiStep = computed(() => step.value === "value" && editor.multiValue.value);
|
||||
const selectedCount = computed(() => draft.value?.values.length ?? 0);
|
||||
|
||||
@@ -370,6 +375,7 @@ const draftOperator = computed(() => {
|
||||
:loading="step === 'value' ? valuesLoading : step === 'field' && fieldsLoading"
|
||||
:auto-highlight="autoHighlight"
|
||||
:multiple="multiStep"
|
||||
:resting="resting"
|
||||
:placeholder="placeholderText"
|
||||
:aria-label="t('filterBar.ariaLabel')"
|
||||
:disabled="disabled"
|
||||
|
||||
@@ -185,6 +185,12 @@ describe("usePanelLivePreview", () => {
|
||||
'<div data-reka-popper-content-wrapper><div role="listbox"></div></div>';
|
||||
expect(isPopupOpen()).toBe(true);
|
||||
});
|
||||
|
||||
it("does not hold for a resting list that only offers the next pick", () => {
|
||||
document.body.innerHTML =
|
||||
'<div data-reka-popper-content-wrapper><div role="listbox" data-list-resting></div></div>';
|
||||
expect(isPopupOpen()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("live runs", () => {
|
||||
|
||||
@@ -98,10 +98,10 @@ const withoutEditorMode = (panel: any) =>
|
||||
queries: (panel.queries ?? []).map((query: any) => ({ ...query, customQuery: false })),
|
||||
};
|
||||
|
||||
/** An open select list (field or function picker), but not menus, popovers or tooltips. */
|
||||
/** An open select list mid-pick (field or function picker), but not a resting list, menus, popovers or tooltips. */
|
||||
export const isPopupOpen = (): boolean =>
|
||||
Array.from(document.querySelectorAll("[data-reka-popper-content-wrapper]")).some((wrapper) =>
|
||||
wrapper.querySelector('[role="listbox"]'),
|
||||
wrapper.querySelector('[role="listbox"]:not([data-list-resting])'),
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
@@ -58,6 +58,8 @@ export interface ChipInputProps {
|
||||
/** `plain` drops the input frame, for a field that sits inside an editor surface. */
|
||||
appearance?: "field" | "plain";
|
||||
ariaLabel?: I18nText;
|
||||
/** The open list only offers a next pick and nothing is mid-edit; its listbox carries `data-list-resting` so watchers need not wait on it. */
|
||||
resting?: boolean;
|
||||
/** The default slot places the caret itself, by rendering its `caret` slot prop where typing should land. */
|
||||
inlineCaret?: boolean;
|
||||
/** Lines of chips shown before the field scrolls inside itself; it grows freely when unset. */
|
||||
|
||||
@@ -53,6 +53,7 @@ const props = withDefaults(defineProps<ChipInputProps>(), {
|
||||
appearance: "field",
|
||||
ariaLabel: undefined,
|
||||
inlineCaret: false,
|
||||
resting: false,
|
||||
maxRows: undefined,
|
||||
dataTest: undefined,
|
||||
});
|
||||
@@ -611,6 +612,7 @@ function onFieldFocusOut() {
|
||||
ref="listRef"
|
||||
role="listbox"
|
||||
:aria-multiselectable="multiple || undefined"
|
||||
:data-list-resting="resting ? '' : undefined"
|
||||
:aria-label="searchPlaceholder ?? ariaLabel"
|
||||
class="min-h-0 flex-1 overflow-y-auto p-1"
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user