Merge branch 'main' into next

This commit is contained in:
nocobase[bot]
2026-07-02 07:45:31 +00:00
2 changed files with 72 additions and 1 deletions
@@ -64,6 +64,40 @@ describe('normalizeDataScopeFilter', () => {
});
});
it('prunes a missing URL search param variable', () => {
const rawFilter = {
logic: '$and',
items: [{ path: 'departmentId', operator: '$eq', value: '{{ ctx.urlSearchParams.departmentId }}' }],
};
const resolvedFilter = {
logic: '$and',
items: [{ path: 'departmentId', operator: '$eq', value: undefined }],
};
expect(normalizeDataScopeFilter(rawFilter, resolvedFilter)).toBeUndefined();
});
it('only prunes the missing URL search param condition from mixed filters', () => {
const rawFilter = {
logic: '$and',
items: [
{ path: 'status', operator: '$eq', value: 'active' },
{ path: 'departmentId', operator: '$eq', value: '{{ ctx.urlSearchParams.departmentId }}' },
],
};
const resolvedFilter = {
logic: '$and',
items: [
{ path: 'status', operator: '$eq', value: 'active' },
{ path: 'departmentId', operator: '$eq', value: undefined },
],
};
expect(normalizeDataScopeFilter(rawFilter, resolvedFilter)).toEqual({
$and: [{ status: { $eq: 'active' } }],
});
});
it('still prunes empty constant values', () => {
const filter = {
logic: '$and',
@@ -139,6 +173,34 @@ describe('normalizeDataScopeFilter', () => {
expect(resource.removeFilterGroup).not.toHaveBeenCalled();
});
it('dataScope handler removes data scope when a URL search param is missing', async () => {
const resource = {
addFilterGroup: vi.fn(),
removeFilterGroup: vi.fn(),
};
const ctx = {
model: {
uid: 'field-1',
resource,
},
resolveJsonTemplate: vi.fn(async (template) => ({
...template,
items: [{ ...template.items[0], value: undefined }],
})),
};
const params = {
filter: {
logic: '$and',
items: [{ path: 'departmentId', operator: '$eq', value: '{{ ctx.urlSearchParams.departmentId }}' }],
},
};
await (dataScope as any).handler(ctx, params);
expect(resource.removeFilterGroup).toHaveBeenCalledWith('field-1');
expect(resource.addFilterGroup).not.toHaveBeenCalled();
});
it('dataScope handler preserves current role as server-side variable', async () => {
const engine = new FlowEngine();
const resource = {
@@ -7,7 +7,7 @@
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
import { isVariableExpression, pruneFilter } from '@nocobase/flow-engine';
import { extractPropertyPath, isVariableExpression, pruneFilter } from '@nocobase/flow-engine';
import { transformFilter } from '@nocobase/utils/client';
import _ from 'lodash';
@@ -45,6 +45,14 @@ function restorePreservedNull(value: any): any {
return value;
}
function isUrlSearchParamsExpression(value: any) {
if (!isVariableExpression(value)) {
return false;
}
return extractPropertyPath(value)?.[0] === 'urlSearchParams';
}
function markEmptyVariableValues(rawNode: any, resolvedNode: any) {
if (!rawNode || !resolvedNode || typeof rawNode !== 'object' || typeof resolvedNode !== 'object') {
return;
@@ -57,6 +65,7 @@ function markEmptyVariableValues(rawNode: any, resolvedNode: any) {
}
if (
isVariableExpression(rawNode.value) &&
!isUrlSearchParamsExpression(rawNode.value) &&
(resolvedNode.value === undefined || resolvedNode.value === null || resolvedNode.value === '')
) {
resolvedNode.value = PRESERVE_NULL;