diff --git a/packages/core/acl/src/acl.ts b/packages/core/acl/src/acl.ts index 3fe5452cb..6f08a98ef 100644 --- a/packages/core/acl/src/acl.ts +++ b/packages/core/acl/src/acl.ts @@ -265,6 +265,7 @@ export class ACL extends EventEmitter { state, }, $user: async () => state.currentUser, + $nRole: () => state.currentRole, }, }); json.filter = filter; diff --git a/packages/core/client/src/acl/Configuration/FilterDynamicComponent.tsx b/packages/core/client/src/acl/Configuration/FilterDynamicComponent.tsx deleted file mode 100644 index 0751dfabb..000000000 --- a/packages/core/client/src/acl/Configuration/FilterDynamicComponent.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import React from 'react'; -import { useCompile } from '../../schema-component'; -import { useGetFilterOptions } from '../../schema-component/antd/filter'; -import { useValues } from '../../schema-component/antd/filter/useValues'; -import { Variable } from '../../schema-component/antd/variable'; - -interface GetOptionsParams { - schema: any; - operator: string; - maxDepth: number; - getFilterOptions: (collectionName: string) => any[]; - count?: number; -} - -const getOptions = ( - collectionName: string, - { schema, operator, maxDepth, getFilterOptions, count = 1 }: GetOptionsParams, -) => { - if (count > maxDepth) { - return []; - } - - const result = getFilterOptions(collectionName).map((option) => { - if ((option.type !== 'belongsTo' && option.type !== 'hasOne') || !option.target) { - return { - key: option.name, - value: option.name, - label: option.title, - // TODO: 现在是通过组件的名称来过滤能够被选择的选项,这样的坏处是不够精确,后续可以优化 - disabled: schema?.['x-component'] !== option.schema?.['x-component'], - }; - } - - const children = - getOptions(option.target, { - schema, - operator, - maxDepth, - count: count + 1, - getFilterOptions, - }) || []; - - return { - key: option.name, - value: option.name, - label: option.title, - children, - disabled: children.every((child) => child.disabled), - }; - }); - - return result; -}; - -const useUserVariable = ({ schema, operator }) => { - const getFilterOptions = useGetFilterOptions(); - const options = getOptions('users', { schema, operator, maxDepth: 1, getFilterOptions }) || []; - - return { - label: `{{t("Current user")}}`, - value: '$user', - key: '$user', - disabled: options.every((option) => option.disabled), - children: options, - }; -}; - -const useVariableOptions = () => { - const { operator, schema } = useValues(); - const userVariable = useUserVariable({ schema, operator }); - - if (!operator || !schema) return []; - - return [userVariable]; -}; - -export function FilterDynamicComponent(props) { - const { value, onChange, renderSchemaComponent } = props; - const options = useVariableOptions(); - const compile = useCompile(); - const scope = compile(options); - - return ( - - {renderSchemaComponent()} - - ); -} diff --git a/packages/core/client/src/acl/Configuration/RoleTable.tsx b/packages/core/client/src/acl/Configuration/RoleTable.tsx index 9465f2675..a216c106d 100644 --- a/packages/core/client/src/acl/Configuration/RoleTable.tsx +++ b/packages/core/client/src/acl/Configuration/RoleTable.tsx @@ -1,7 +1,7 @@ import { Spin } from 'antd'; import React, { createContext, useContext } from 'react'; import { useRequest } from '../../api-client'; -import { SchemaComponent } from '../../schema-component'; +import { SchemaComponent, SchemaComponentContext } from '../../schema-component'; import { MenuItemsProvider } from '../Configuration/MenuItemsProvider'; import { PermissionProvider, SettingCenterPermissionProvider } from '../Configuration/PermisionProvider'; import { roleSchema } from './schemas/roles'; @@ -28,12 +28,14 @@ export const useAvailableActions = () => { export const RoleTable = () => { return (
- - - + + + + +
); }; diff --git a/packages/core/client/src/acl/Configuration/schemas/roleCollections.ts b/packages/core/client/src/acl/Configuration/schemas/roleCollections.ts index ddf4ca098..60f448dbe 100644 --- a/packages/core/client/src/acl/Configuration/schemas/roleCollections.ts +++ b/packages/core/client/src/acl/Configuration/schemas/roleCollections.ts @@ -1,4 +1,5 @@ import { ISchema } from '@formily/react'; +import { uid } from '@formily/shared'; import { useRoleResourceValues } from './useRoleResourceValues'; import { useSaveRoleResourceAction } from './useSaveRoleResourceAction'; @@ -90,6 +91,31 @@ export const roleCollectionsSchema: ISchema = { }, }, properties: { + [uid()]: { + type: 'void', + 'x-component': 'ActionBar', + 'x-component-props': { + style: { + marginBottom: 16, + }, + }, + properties: { + filter: { + type: 'void', + title: '{{ t("Filter") }}', + default: { + $and: [{ title: { $includes: '' } }, { name: { $includes: '' } }], + }, + 'x-action': 'filter', + 'x-component': 'Filter.Action', + 'x-component-props': { + icon: 'FilterOutlined', + useProps: '{{ cm.useFilterActionProps }}', + }, + 'x-align': 'left', + }, + }, + }, table1: { type: 'void', 'x-uid': 'input', diff --git a/packages/core/client/src/acl/Configuration/schemas/scopes.ts b/packages/core/client/src/acl/Configuration/schemas/scopes.ts index dbeb28178..1960c28fc 100644 --- a/packages/core/client/src/acl/Configuration/schemas/scopes.ts +++ b/packages/core/client/src/acl/Configuration/schemas/scopes.ts @@ -2,7 +2,7 @@ import { ISchema } from '@formily/react'; import { useContext, useEffect } from 'react'; import { useFormBlockContext } from '../../../block-provider'; import { useFilterOptions } from '../../../schema-component'; -import { FilterDynamicComponent } from '../FilterDynamicComponent'; +import { VariableInput } from '../../../schema-settings'; import { RoleResourceCollectionContext } from '../RolesResourcesActions'; export const rolesResourcesScopesCollection = { @@ -140,11 +140,10 @@ export const scopesSchema: ISchema = { 'x-decorator': 'FormItem', 'x-component': 'Filter', 'x-component-props': { - dynamicComponent: FilterDynamicComponent, + dynamicComponent: VariableInput, useProps() { const ctx = useContext(RoleResourceCollectionContext); const options = useFilterOptions(ctx.name); - console.log('ctx.name', ctx.name, options); return { options, }; @@ -269,7 +268,7 @@ export const scopesSchema: ISchema = { 'x-decorator': 'FormItem', 'x-component': 'Filter', 'x-component-props': { - dynamicComponent: FilterDynamicComponent, + dynamicComponent: VariableInput, useProps() { const ctx = useContext(RoleResourceCollectionContext); const options = useFilterOptions(ctx.name); diff --git a/packages/core/client/src/collection-manager/ResourceActionProvider.tsx b/packages/core/client/src/collection-manager/ResourceActionProvider.tsx index ca12d385e..6b68e706c 100644 --- a/packages/core/client/src/collection-manager/ResourceActionProvider.tsx +++ b/packages/core/client/src/collection-manager/ResourceActionProvider.tsx @@ -78,7 +78,7 @@ const AssociationResourceActionProvider = (props) => { ); const resource = api.resource(request.resource, resourceOf); return ( - + {props.children} diff --git a/packages/core/client/src/collection-manager/action-hooks.ts b/packages/core/client/src/collection-manager/action-hooks.ts index 0f6c80a60..0e150afdf 100644 --- a/packages/core/client/src/collection-manager/action-hooks.ts +++ b/packages/core/client/src/collection-manager/action-hooks.ts @@ -579,7 +579,8 @@ export const useFilterActionProps = () => { const options = useFilterFieldOptions(collection.fields); const service = useResourceActionContext(); return useFilterFieldProps({ - options, + // 目前仅需要支持筛选 title 和 name,其它字段可能会报错。详见:https://nocobase.height.app/T-2745 + options: options.filter((option) => ['title', 'name'].includes(option.name)), params: service.state?.params?.[0] || service.params, service, }); diff --git a/packages/core/client/src/schema-settings/DataTemplates/FormDataTemplates.tsx b/packages/core/client/src/schema-settings/DataTemplates/FormDataTemplates.tsx index c247e1c7f..1fe771e14 100644 --- a/packages/core/client/src/schema-settings/DataTemplates/FormDataTemplates.tsx +++ b/packages/core/client/src/schema-settings/DataTemplates/FormDataTemplates.tsx @@ -9,6 +9,7 @@ import { mergeFilter } from '../../block-provider'; import { useCollectionManager } from '../../collection-manager'; import { SchemaComponent, SchemaComponentContext, removeNullCondition } from '../../schema-component'; import { ITemplate } from '../../schema-component/antd/form-v2/Templates'; +import { VariableInput } from '../VariableInput'; import { AsDefaultTemplate } from './components/AsDefaultTemplate'; import { ArrayCollapse } from './components/DataTemplateTitle'; import { getSelectedIdFilter } from './components/Designer'; @@ -143,6 +144,9 @@ export const FormDataTemplates = observer( title: '{{ t("Assign data scope for the template") }}', 'x-decorator': 'FormItem', 'x-component': 'Filter', + 'x-component-props': { + dynamicComponent: VariableInput, + }, 'x-decorator-props': { style: { marginBottom: '0px',