mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-07-02 03:02:19 +08:00
feat: add operator options management for field interfaces
This commit is contained in:
parent
9d430d4378
commit
945c2c686c
@ -0,0 +1,154 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the NocoBase (R) project.
|
||||||
|
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
||||||
|
* Authors: NocoBase Team.
|
||||||
|
*
|
||||||
|
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||||
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { vi } from 'vitest';
|
||||||
|
import { Application, CollectionFieldInterface, CollectionFieldInterfaceManager, DataSourceManager } from '..';
|
||||||
|
|
||||||
|
// 创建测试用的字段接口类
|
||||||
|
class TestFieldInterface extends CollectionFieldInterface {
|
||||||
|
name = 'test';
|
||||||
|
group = 'test';
|
||||||
|
filterable = {
|
||||||
|
operators: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Field Interface Operator', () => {
|
||||||
|
describe('CollectionFieldInterface.addOperator', () => {
|
||||||
|
let fieldInterface: TestFieldInterface;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
// 创建测试环境
|
||||||
|
const mockCollectionFieldInterfaceManager = {} as CollectionFieldInterfaceManager;
|
||||||
|
fieldInterface = new TestFieldInterface(mockCollectionFieldInterfaceManager);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should add a new operator', () => {
|
||||||
|
const testOperator: any = {
|
||||||
|
label: 'Test Operator',
|
||||||
|
value: 'test-op',
|
||||||
|
};
|
||||||
|
|
||||||
|
fieldInterface.addOperator(testOperator);
|
||||||
|
|
||||||
|
expect(fieldInterface.filterable.operators).toContainEqual(testOperator);
|
||||||
|
expect(fieldInterface.filterable.operators.length).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not add duplicate operators', () => {
|
||||||
|
const testOperator: any = {
|
||||||
|
label: 'Test Operator',
|
||||||
|
value: 'test-op',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add the same operator twice
|
||||||
|
fieldInterface.addOperator(testOperator);
|
||||||
|
fieldInterface.addOperator(testOperator);
|
||||||
|
|
||||||
|
// Ensure it was only added once
|
||||||
|
expect(fieldInterface.filterable.operators.length).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should initialize operators array if it does not exist', () => {
|
||||||
|
// Clear the operators array
|
||||||
|
// @ts-ignore
|
||||||
|
fieldInterface.filterable = {};
|
||||||
|
|
||||||
|
const testOperator: any = {
|
||||||
|
label: 'Test Operator',
|
||||||
|
value: 'test-op',
|
||||||
|
};
|
||||||
|
|
||||||
|
fieldInterface.addOperator(testOperator);
|
||||||
|
|
||||||
|
expect(Array.isArray(fieldInterface.filterable.operators)).toBeTruthy();
|
||||||
|
expect(fieldInterface.filterable.operators).toContainEqual(testOperator);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('CollectionFieldInterfaceManager.addFieldInterfaceOperator', () => {
|
||||||
|
let manager: CollectionFieldInterfaceManager;
|
||||||
|
let mockDataSourceManager: any;
|
||||||
|
let testFieldInterface: TestFieldInterface;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
mockDataSourceManager = {} as DataSourceManager;
|
||||||
|
testFieldInterface = new TestFieldInterface({} as any);
|
||||||
|
|
||||||
|
// Create manager
|
||||||
|
manager = new CollectionFieldInterfaceManager([], {}, mockDataSourceManager);
|
||||||
|
|
||||||
|
// Mock getFieldInterface method
|
||||||
|
manager.getFieldInterface = vi.fn().mockImplementation((name) => {
|
||||||
|
if (name === 'test') {
|
||||||
|
return testFieldInterface;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should add operator to specified field interface', () => {
|
||||||
|
const testOperator: any = {
|
||||||
|
label: 'Test Operator',
|
||||||
|
value: 'test-op',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add operator to the test field interface
|
||||||
|
manager.addFieldInterfaceOperator('test', testOperator);
|
||||||
|
|
||||||
|
// Verify the operator was added correctly
|
||||||
|
expect(testFieldInterface.filterable.operators).toContainEqual(testOperator);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not throw error when field interface does not exist', () => {
|
||||||
|
const testOperator: any = {
|
||||||
|
label: 'Test Operator',
|
||||||
|
value: 'test-op',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Should not throw an exception
|
||||||
|
expect(() => {
|
||||||
|
manager.addFieldInterfaceOperator('non-exist', testOperator);
|
||||||
|
}).not.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Application.addFieldInterfaceOperator', () => {
|
||||||
|
let app: Application;
|
||||||
|
let mockDataSourceManager: any;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
mockDataSourceManager = {
|
||||||
|
collectionFieldInterfaceManager: {
|
||||||
|
addFieldInterfaceOperator: vi.fn(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create application instance
|
||||||
|
app = new Application({ dataSourceManager: mockDataSourceManager });
|
||||||
|
// Replace the dataSourceManager in the application
|
||||||
|
app.dataSourceManager = mockDataSourceManager as any;
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should delegate call to dataSourceManager.collectionFieldInterfaceManager', () => {
|
||||||
|
const testOperator: any = {
|
||||||
|
label: 'Test Operator',
|
||||||
|
value: 'test-op',
|
||||||
|
};
|
||||||
|
|
||||||
|
app.addFieldInterfaceOperator('test', testOperator);
|
||||||
|
|
||||||
|
// Verify the method was called correctly
|
||||||
|
expect(mockDataSourceManager.collectionFieldInterfaceManager.addFieldInterfaceOperator).toHaveBeenCalledWith(
|
||||||
|
'test',
|
||||||
|
testOperator,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -495,6 +495,23 @@ export class Application {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 为指定的字段接口添加操作符选项
|
||||||
|
*
|
||||||
|
* @param name 字段接口的名称
|
||||||
|
* @param operatorOption 要添加的操作符选项
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* // 为"单行文本"类型字段添加"等于任意一个"操作符
|
||||||
|
* app.addFieldInterfaceOperator('input', {
|
||||||
|
* label: '{{t("equals any of")}}',
|
||||||
|
* value: '$in',
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
addFieldInterfaceOperator(name: string, operatorOption: any) {
|
||||||
|
return this.dataSourceManager.collectionFieldInterfaceManager.addFieldInterfaceOperator(name, operatorOption);
|
||||||
|
}
|
||||||
|
|
||||||
addGlobalVar(key: string, value: any, varCtx?: any) {
|
addGlobalVar(key: string, value: any, varCtx?: any) {
|
||||||
set(this.globalVars, key, value);
|
set(this.globalVars, key, value);
|
||||||
if (varCtx) {
|
if (varCtx) {
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { ISchema } from '@formily/react';
|
import type { ISchema } from '@formily/react';
|
||||||
import { cloneDeep, capitalize } from 'lodash';
|
import { cloneDeep, capitalize, set } from 'lodash';
|
||||||
import type { CollectionFieldOptions } from '../collection';
|
import type { CollectionFieldOptions } from '../collection';
|
||||||
import { CollectionFieldInterfaceManager } from './CollectionFieldInterfaceManager';
|
import { CollectionFieldInterfaceManager } from './CollectionFieldInterfaceManager';
|
||||||
import { defaultProps } from '../../collection-manager/interfaces/properties';
|
import { defaultProps } from '../../collection-manager/interfaces/properties';
|
||||||
@ -161,4 +161,14 @@ export abstract class CollectionFieldInterface {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addOperator(operatorOption: any) {
|
||||||
|
set(this, 'filterable.operators', this.filterable.operators || []);
|
||||||
|
|
||||||
|
if (this.filterable.operators.find((item) => item.value === operatorOption.value)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.filterable.operators.push(operatorOption);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,6 +61,24 @@ export class CollectionFieldInterfaceManager {
|
|||||||
fieldInterface.addComponentOption(componentOption);
|
fieldInterface.addComponentOption(componentOption);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 为指定的字段接口添加操作符选项
|
||||||
|
*
|
||||||
|
* @param name 字段接口的名称
|
||||||
|
* @param operatorOption 要添加的操作符选项
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* // 为"单行文本"类型字段添加"等于任意一个"操作符
|
||||||
|
* fieldInterfaceManager.addFieldInterfaceOperator('input', {
|
||||||
|
* label: '{{t("equals any of")}}',
|
||||||
|
* value: '$in',
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
addFieldInterfaceOperator(name: string, operatorOption: any) {
|
||||||
|
const fieldInterface = this.getFieldInterface(name);
|
||||||
|
fieldInterface?.addOperator(operatorOption);
|
||||||
|
}
|
||||||
|
|
||||||
getFieldInterface<T extends CollectionFieldInterface>(name: string) {
|
getFieldInterface<T extends CollectionFieldInterface>(name: string) {
|
||||||
return this.collectionFieldInterfaceInstances[name] as T;
|
return this.collectionFieldInterfaceInstances[name] as T;
|
||||||
}
|
}
|
||||||
|
@ -18,12 +18,7 @@ export class PluginFilterOperatorMultipleKeywordsClient extends Plugin {
|
|||||||
|
|
||||||
// You can get and modify the app instance here
|
// You can get and modify the app instance here
|
||||||
async load() {
|
async load() {
|
||||||
console.log(this.app);
|
|
||||||
// this.app.addComponents({})
|
|
||||||
// this.app.addScopes({})
|
|
||||||
// this.app.addProvider()
|
|
||||||
// this.app.addProviders()
|
|
||||||
// this.app.router.add()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user