fix(grid): clear filter state with empty WHERE clause
This commit is contained in:
parent
1a78287656
commit
097d97905e
|
|
@ -1560,11 +1560,6 @@ function onSearchKeydown(e: KeyboardEvent) {
|
|||
}
|
||||
}
|
||||
|
||||
function clearWhereFilterInput() {
|
||||
whereFilterInput.value = "";
|
||||
void applyWhereFilter();
|
||||
}
|
||||
|
||||
watch(whereFilterInput, () => {
|
||||
emit("update:whereInput", currentWhereInput() ?? "");
|
||||
persistStructuredFilterState();
|
||||
|
|
@ -7446,7 +7441,6 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
|
|||
:mode-options="filterModeOptions"
|
||||
:column-search="filterBuilderColumnSearch"
|
||||
:apply-where="applyWhereFilter"
|
||||
:clear-where="clearWhereFilterInput"
|
||||
:apply-order-by="applyOrderBySearch"
|
||||
:clear-order-by="clearOrderByInput"
|
||||
@update:column-search="filterBuilderColumnSearch = $event"
|
||||
|
|
|
|||
|
|
@ -9,16 +9,19 @@ import type { DataGridContextFilterMode } from "@/lib/dataGrid/dataGridSql";
|
|||
import type { DataGridStructuredFilterRule } from "@/composables/useDataGridFilterBuilder";
|
||||
|
||||
const { t } = useI18n();
|
||||
const props = defineProps<{
|
||||
rules: DataGridStructuredFilterRule[];
|
||||
columns: string[];
|
||||
filteredColumns: string[];
|
||||
modeOptions: Array<{ value: DataGridContextFilterMode; labelKey: string }>;
|
||||
columnSearch: string;
|
||||
disabled?: boolean;
|
||||
showHeader?: boolean;
|
||||
showFooter?: boolean;
|
||||
}>();
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
rules: DataGridStructuredFilterRule[];
|
||||
columns: string[];
|
||||
filteredColumns: string[];
|
||||
modeOptions: Array<{ value: DataGridContextFilterMode; labelKey: string }>;
|
||||
columnSearch: string;
|
||||
disabled?: boolean;
|
||||
showHeader?: boolean;
|
||||
showFooter?: boolean;
|
||||
}>(),
|
||||
{ showHeader: true, showFooter: true },
|
||||
);
|
||||
const emit = defineEmits<{
|
||||
add: [];
|
||||
apply: [];
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ const props = defineProps<{
|
|||
modeOptions: Array<{ value: DataGridContextFilterMode; labelKey: string }>;
|
||||
columnSearch: string;
|
||||
applyWhere: (value?: string) => void | boolean | Promise<void | boolean>;
|
||||
clearWhere: () => void | Promise<void>;
|
||||
applyOrderBy: (value?: string) => void | boolean | Promise<void | boolean>;
|
||||
clearOrderBy: () => void | Promise<void>;
|
||||
}>();
|
||||
|
|
@ -108,6 +107,10 @@ function updateRule(id: string, patch: Partial<DataGridStructuredFilterRule>) {
|
|||
emit("updateRule", id, patch);
|
||||
}
|
||||
|
||||
function clearWhere() {
|
||||
emit("clearFilters");
|
||||
}
|
||||
|
||||
onUnmounted(onResizeEnd);
|
||||
</script>
|
||||
|
||||
|
|
@ -162,7 +165,6 @@ onUnmounted(onResizeEnd);
|
|||
:column-search="columnSearch"
|
||||
:disabled="!canUseWhereSearch"
|
||||
:show-header="false"
|
||||
:show-footer="false"
|
||||
@add="emit('addRule')"
|
||||
@apply="emit('applyFilters')"
|
||||
@reset="emit('resetFilters')"
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ vi.mock("vue-i18n", () => ({ useI18n: () => ({ t: (key: string) => key }) }));
|
|||
vi.mock("@lucide/vue", async () => {
|
||||
const { createPassthroughStub } = await import("./vueHostHarness");
|
||||
const icon = createPassthroughStub("Icon", "i");
|
||||
return { Check: icon, ChevronLeft: icon, ChevronRight: icon, ChevronsLeft: icon, ChevronsRight: icon, Loader2: icon, Upload: icon, Search: icon, X: icon, Code2: icon, Copy: icon, Eye: icon, EyeOff: icon, Info: icon, Pencil: icon, Plus: icon, Trash2: icon };
|
||||
return { Check: icon, ChevronDown: icon, ChevronLeft: icon, ChevronRight: icon, ChevronsLeft: icon, ChevronsRight: icon, Filter: icon, Loader2: icon, Upload: icon, Search: icon, X: icon, Code2: icon, Copy: icon, Eye: icon, EyeOff: icon, Info: icon, Pencil: icon, Plus: icon, Trash2: icon };
|
||||
});
|
||||
|
||||
vi.mock("@/components/ui/button", async () => ({ Button: (await import("./vueHostHarness")).createPassthroughStub("Button", "button") }));
|
||||
|
|
@ -65,6 +65,7 @@ import DataGridCellDetailPanel from "@/components/grid/DataGridCellDetailPanel.v
|
|||
import DataGridColumnHeader from "@/components/grid/DataGridColumnHeader.vue";
|
||||
import DataGridFilterBuilder from "@/components/grid/DataGridFilterBuilder.vue";
|
||||
import DataGridPagination from "@/components/grid/DataGridPagination.vue";
|
||||
import DataGridQueryControls from "@/components/grid/DataGridQueryControls.vue";
|
||||
import DataGridSearchBar from "@/components/grid/DataGridSearchBar.vue";
|
||||
|
||||
function detail(patch: Partial<DataGridCellDetail> = {}): DataGridCellDetail {
|
||||
|
|
@ -287,6 +288,62 @@ describe("DataGridFilterBuilder", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("DataGridQueryControls", () => {
|
||||
it("keeps filter actions available in the popover", () => {
|
||||
const clearFilters = vi.fn();
|
||||
const applyFilters = vi.fn();
|
||||
const resetFilters = vi.fn();
|
||||
const mounted = mountComponent(DataGridQueryControls, {
|
||||
whereInput: "id = 1",
|
||||
orderByInput: "",
|
||||
columns: ["id"],
|
||||
conditionColumns: ["id"],
|
||||
historyScope: {},
|
||||
canUseWhereSearch: true,
|
||||
compact: false,
|
||||
leadingBorder: false,
|
||||
filterBuilderOpen: true,
|
||||
filterButtonActive: true,
|
||||
filterButtonCount: 1,
|
||||
hasLocalColumnFilters: false,
|
||||
localFilterCount: 0,
|
||||
localFilterSummaries: [],
|
||||
rules: [{ id: "r1", columnName: "id", mode: "equals", rawValue: "1", rawEndValue: "", conjunction: "AND" }],
|
||||
filteredColumns: ["id"],
|
||||
modeOptions: [{ value: "equals", labelKey: "equals" }],
|
||||
columnSearch: "",
|
||||
applyWhere: vi.fn(),
|
||||
applyOrderBy: vi.fn(),
|
||||
clearOrderBy: vi.fn(),
|
||||
onClearFilters: clearFilters,
|
||||
onApplyFilters: applyFilters,
|
||||
onResetFilters: resetFilters,
|
||||
});
|
||||
|
||||
dispatch(
|
||||
findOne(mounted.root, (node) => node.type === "button" && hostText(node) === "grid.clearFilter"),
|
||||
"click",
|
||||
);
|
||||
dispatch(
|
||||
findOne(mounted.root, (node) => node.type === "button" && hostText(node) === "grid.resetFilterBuilder"),
|
||||
"click",
|
||||
);
|
||||
dispatch(
|
||||
findOne(mounted.root, (node) => node.type === "button" && hostText(node) === "grid.applyFilter"),
|
||||
"click",
|
||||
);
|
||||
const whereInput = findOne(mounted.root, (node) => node.type === "textarea" && node.props.placeholder === "WHERE");
|
||||
const whereControl = whereInput.parent?.parent;
|
||||
expect(whereControl).toBeTruthy();
|
||||
const whereButtons = findAll(whereControl!, (node) => node.type === "button");
|
||||
dispatch(whereButtons[whereButtons.length - 1], "click");
|
||||
|
||||
expect(clearFilters).toHaveBeenCalledTimes(2);
|
||||
expect(resetFilters).toHaveBeenCalledOnce();
|
||||
expect(applyFilters).toHaveBeenCalledOnce();
|
||||
});
|
||||
});
|
||||
|
||||
describe("cell detail surfaces", () => {
|
||||
it("copies the presented value, emits edit, closes, and replaces the JSON result", async () => {
|
||||
const copyText = vi.fn();
|
||||
|
|
|
|||
Loading…
Reference in New Issue