feat(filter): support temporarily disabling filter rules

Co-authored-by: staff <staff@qimaos-MacBook-Pro.local>
This commit is contained in:
zipg 2026-06-24 18:09:09 +08:00 committed by GitHub
parent 7b47edde3d
commit ded3fdde32
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 19 additions and 7 deletions

View File

@ -7,6 +7,7 @@ type CachedStructuredFilterRule = {
mode: "equals" | "not-equals" | "is-null" | "is-not-null" | "like" | "not-like" | "less-than" | "greater-than";
rawValue: string;
conjunction: "AND" | "OR";
disabled?: boolean;
};
type StructuredFilterCacheState = {
scopeKey: string;
@ -39,6 +40,7 @@ import {
Code2,
Copy,
Eye,
EyeOff,
Loader2,
X,
Undo2,
@ -518,6 +520,7 @@ type StructuredFilterRule = {
mode: FilterMode;
rawValue: string;
conjunction: "AND" | "OR";
disabled?: boolean;
};
const localColumnFilters = ref<Record<number, Set<string>>>({});
@ -544,7 +547,7 @@ const structuredFilterCacheKey = computed(() => props.cacheKey || [props.connect
const structuredFilterScopeKey = computed(() => [props.connectionId ?? "", props.database ?? "", props.schema ?? "", props.context ?? "", props.tableMeta?.schema ?? "", props.tableMeta?.tableName ?? "", filterBuilderColumnOptions.value.join("\0")].join("\u0001"));
const structuredFilterRules = ref<StructuredFilterRule[]>([]);
const appliedStructuredWhereInput = ref("");
const structuredFilterCount = computed(() => structuredFilterRules.value.filter((rule) => !!rule.columnName && (!filterModeNeedsValue(rule.mode) || rule.rawValue.trim().length > 0)).length);
const structuredFilterCount = computed(() => structuredFilterRules.value.filter((rule) => !rule.disabled && !!rule.columnName && (!filterModeNeedsValue(rule.mode) || rule.rawValue.trim().length > 0)).length);
const hasStructuredFilters = computed(() => !!combineWhereInputs(undefined, appliedStructuredWhereInput.value));
const formatterOpenColumn = ref<number | null>(null);
type FormatterDraftKind = Exclude<ColumnFormatterConfig["kind"], "custom-ref">;
@ -1002,6 +1005,7 @@ async function buildStructuredWhereFromRules(rules: StructuredFilterRule[]): Pro
const rulesWithConditions = (
await Promise.all(
rules.map(async (rule) => {
if (rule.disabled) return { rule, condition: null };
if (!rule.columnName) return { rule, condition: null };
if (filterModeNeedsValue(rule.mode) && !rule.rawValue.trim()) return { rule, condition: null };
const columnInfo = filterBuilderColumns.value.find((column) => column.name === rule.columnName);
@ -6615,7 +6619,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
</Button>
</div>
<div class="grid grid-cols-[minmax(0,1.2fr)_minmax(0,1fr)_minmax(0,1.2fr)_auto] items-center gap-2">
<Select :model-value="rule.columnName" @update:model-value="(value: any) => updateStructuredFilterRule(rule.id, { columnName: String(value) })">
<Select :model-value="rule.columnName" :disabled="rule.disabled" :class="rule.disabled ? 'opacity-45' : ''" @update:model-value="(value: any) => updateStructuredFilterRule(rule.id, { columnName: String(value) })">
<SelectTrigger class="h-8 w-full min-w-0 overflow-hidden text-xs [&_[data-slot=select-value]]:min-w-0 [&_[data-slot=select-value]]:truncate">
<SelectValue :placeholder="t('grid.filterBuilderColumn')" />
</SelectTrigger>
@ -6626,7 +6630,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
</SelectContent>
</Select>
<Select :model-value="rule.mode" @update:model-value="(value: any) => updateStructuredFilterRule(rule.id, { mode: value as FilterMode })">
<Select :model-value="rule.mode" :disabled="rule.disabled" :class="rule.disabled ? 'opacity-45' : ''" @update:model-value="(value: any) => updateStructuredFilterRule(rule.id, { mode: value as FilterMode })">
<SelectTrigger class="h-8 w-full min-w-0 overflow-hidden text-xs [&_[data-slot=select-value]]:min-w-0 [&_[data-slot=select-value]]:truncate">
<SelectValue />
</SelectTrigger>
@ -6641,17 +6645,25 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
v-if="filterModeNeedsValue(rule.mode)"
:model-value="rule.rawValue"
class="h-8 min-w-0 text-xs"
:class="rule.disabled ? 'opacity-45' : ''"
:disabled="rule.disabled"
:placeholder="t('grid.filterBuilderValue')"
@update:model-value="(value) => updateStructuredFilterRule(rule.id, { rawValue: String(value ?? '') })"
@keydown.enter.prevent="applyStructuredFilters"
/>
<div v-else class="flex h-8 min-w-0 items-center overflow-hidden rounded-md border border-dashed px-2 text-xs text-muted-foreground">
<div v-else class="flex h-8 min-w-0 items-center overflow-hidden rounded-md border border-dashed px-2 text-xs text-muted-foreground" :class="rule.disabled ? 'opacity-45' : ''">
<span class="truncate">{{ t("grid.filterBuilderNoValue") }}</span>
</div>
<Button variant="ghost" size="icon" class="h-8 w-8 shrink-0 text-muted-foreground hover:text-destructive" :disabled="structuredFilterRules.length === 1" @click="removeStructuredFilterRule(rule.id)">
<Trash2 class="h-3.5 w-3.5" />
</Button>
<div class="flex items-center gap-1">
<Button variant="ghost" size="icon" class="h-8 w-8 shrink-0 text-muted-foreground hover:text-foreground" @click="updateStructuredFilterRule(rule.id, { disabled: !rule.disabled })">
<EyeOff v-if="rule.disabled" class="h-3.5 w-3.5" />
<Eye v-else class="h-3.5 w-3.5" />
</Button>
<Button variant="ghost" size="icon" class="h-8 w-8 shrink-0 text-muted-foreground hover:text-destructive" :disabled="structuredFilterRules.length === 1" @click="removeStructuredFilterRule(rule.id)">
<Trash2 class="h-3.5 w-3.5" />
</Button>
</div>
</div>
</template>
</div>