Browse Source

Merge pull request #8396 from nocodb/nc-filter-group-logic-op

Allow only same logical operation in filter group level
pull/8401/head
Pranav C 5 months ago committed by GitHub
parent
commit
6786d374ed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 24
      packages/nc-gui/components/smartsheet/toolbar/ColumnFilter.vue
  2. 8
      packages/nc-gui/composables/useViewFilters.ts
  3. 11
      packages/nocodb/src/helpers/webhookHelpers.ts
  4. 2
      tests/playwright/pages/Dashboard/WebhookForm/index.ts

24
packages/nc-gui/components/smartsheet/toolbar/ColumnFilter.vue

@ -371,6 +371,23 @@ watch(
immediate: true,
},
)
const isLogicalOpChangeAllowed = computed(() => {
return new Set(filters.value.slice(1).map((filter) => filter.logical_op)).size > 1
})
// when logical operation is updated, update all the siblings with the same logical operation only if it's in locked state
const onLogicalOpUpdate = async (filter: Filter, index: number) => {
if (index === 1 && filters.value.slice(2).every((siblingFilter) => siblingFilter.logical_op !== filter.logical_op)) {
await Promise.all(
filters.value.slice(2).map(async (siblingFilter, i) => {
siblingFilter.logical_op = filter.logical_op
await saveOrUpdate(siblingFilter, i + 2, false, false, true)
}),
)
}
await filterUpdateCondition(filter, index)
}
</script>
<template>
@ -403,6 +420,7 @@ watch(
class="min-w-20 capitalize"
placeholder="Group op"
dropdown-class-name="nc-dropdown-filter-logical-op-group"
:disabled="i > 1 && !isLogicalOpChangeAllowed"
@click.stop
@change="saveOrUpdate(filter, i)"
>
@ -455,9 +473,9 @@ watch(
:dropdown-match-select-width="false"
class="h-full !min-w-20 !max-w-20 capitalize"
hide-details
:disabled="filter.readOnly"
:disabled="filter.readOnly || (i > 1 && !isLogicalOpChangeAllowed)"
dropdown-class-name="nc-dropdown-filter-logical-op"
@change="filterUpdateCondition(filter, i)"
@change="onLogicalOpUpdate(filter, i)"
@click.stop
>
<a-select-option v-for="op of logicalOps" :key="op.value" :value="op.value">
@ -601,7 +619,7 @@ watch(
</div>
</NcButton>
<NcButton v-if="!webHook && nestedLevel < 5" type="text" size="small" @click.stop="addFilterGroup()">
<NcButton v-if="nestedLevel < 5" type="text" size="small" @click.stop="addFilterGroup()">
<div class="flex items-center gap-1">
<!-- Add Filter Group -->
<component :is="iconMap.plus" />

8
packages/nc-gui/composables/useViewFilters.ts

@ -198,13 +198,15 @@ export function useViewFilters(
}
const placeholderFilter = (): Filter => {
const logicalOps = new Set(filters.value.slice(1).map((filter) => filter.logical_op))
return {
comparison_op: comparisonOpList(options.value?.[0].uidt as UITypes).filter((compOp) =>
isComparisonOpAllowed({ fk_column_id: options.value?.[0].id }, compOp),
)?.[0].value as FilterType['comparison_op'],
value: '',
status: 'create',
logical_op: 'and',
logical_op: logicalOps.size === 1 ? logicalOps.values().next().value :'and' ,
}
}
@ -307,7 +309,7 @@ export function useViewFilters(
}
}
const saveOrUpdate = async (filter: Filter, i: number, force = false, undo = false) => {
const saveOrUpdate = async (filter: Filter, i: number, force = false, undo = false, skipDataReload = false) => {
if (!view.value) return
if (!undo) {
@ -372,7 +374,7 @@ export function useViewFilters(
lastFilters.value = clone(filters.value)
if (!isWebhook) reloadData?.()
if (!isWebhook && !skipDataReload) reloadData?.()
}
function deleteFilterGroupFromAllFilters(filter: Filter) {

11
packages/nocodb/src/helpers/webhookHelpers.ts

@ -54,8 +54,15 @@ export async function validateCondition(
const column = await filter.getColumn();
const field = column.title;
let val = data[field];
if (
if (filter.is_group) {
res = await validateCondition(
filter.children || (await filter.getChildren()),
data,
{
client,
},
);
} else if (
[
UITypes.Date,
UITypes.DateTime,

2
tests/playwright/pages/Dashboard/WebhookForm/index.ts

@ -70,7 +70,7 @@ export class WebhookFormPage extends BasePage {
await this.get().locator(`.nc-check-box-hook-condition`).click();
const modal = this.get().locator(`.menu-filter-dropdown`).last();
await modal.locator(`button:has-text("Add Filter")`).click();
await modal.locator(`button:has-text("Add Filter")`).first().click();
await modal.locator('.nc-filter-field-select').waitFor({ state: 'visible', timeout: 4000 });
await modal.locator('.nc-filter-field-select').click();

Loading…
Cancel
Save