From 9704f8a342db654e0a5f8da14f3fa4b09d1da053 Mon Sep 17 00:00:00 2001 From: chenos Date: Mon, 28 Feb 2022 22:10:04 +0800 Subject: [PATCH] feat: improve acl module --- .../Configuration/RolesResourcesActions.tsx | 26 ++- .../src/acl/Configuration/ScopeSelect.tsx | 46 ++++ .../src/acl/Configuration/schemas/scopes.ts | 202 ++++++++++++++++++ .../antd/record-picker/RecordPicker.tsx | 125 +++++++---- .../antd/record-picker/demos/demo1.tsx | 64 +++--- .../schema-component/core/FormProvider.tsx | 24 +++ .../src/schema-component/core/index.tsx | 2 + packages/plugin-acl/src/server.ts | 5 +- packages/plugin-users/src/server.ts | 35 +-- packages/server/src/plugin-manager.ts | 2 +- 10 files changed, 448 insertions(+), 83 deletions(-) create mode 100644 packages/client/src/acl/Configuration/ScopeSelect.tsx create mode 100644 packages/client/src/acl/Configuration/schemas/scopes.ts create mode 100644 packages/client/src/schema-component/core/FormProvider.tsx diff --git a/packages/client/src/acl/Configuration/RolesResourcesActions.tsx b/packages/client/src/acl/Configuration/RolesResourcesActions.tsx index 6016538b8..2fac6bd47 100644 --- a/packages/client/src/acl/Configuration/RolesResourcesActions.tsx +++ b/packages/client/src/acl/Configuration/RolesResourcesActions.tsx @@ -1,16 +1,19 @@ import { FormItem, FormLayout } from '@formily/antd'; import { ArrayField } from '@formily/core'; import { connect, useField, useForm } from '@formily/react'; -import { Checkbox, Select, Table, Tag } from 'antd'; +import { Checkbox, Table, Tag } from 'antd'; import React from 'react'; import { useTranslation } from 'react-i18next'; import { useAvailableActions } from '.'; import { useCollectionManager, useCompile, useRecord } from '../..'; +import { ScopeSelect } from './ScopeSelect'; const toActionMap = (arr: any[]) => { const obj = {}; - arr?.forEach((action) => { - obj[action.name] = action; + arr?.forEach?.((action) => { + if (action.name) { + obj[action.name] = action; + } }); return obj; }; @@ -52,11 +55,16 @@ export const RolesResourcesActions = connect((props) => { } onChange(Object.values(actionMap)); }; + const setScope = (actionName, scope) => { + if (!actionMap[actionName]) { + toggleAction(actionName); + } + actionMap[actionName]['scope'] = scope; + }; const allChecked = {}; for (const action of availableActionsWithFields) { allChecked[action.name] = collection?.fields?.length === actionMap?.[action.name]?.fields?.length; } - return (
@@ -95,7 +103,15 @@ export const RolesResourcesActions = connect((props) => { { dataIndex: 'scope', title: '可操作的数据范围', - render: () => { setVisible(true); }} + labelInValue={true} + value={toValue(value)} open={false} > - setVisible(false)} - footer={ - - - - } - > + { - // return s['x-component'] === 'RowSelection'; - // }} + filterProperties={(s) => { + return s['x-component'] === 'RecordPicker.Options'; + }} /> - +
@@ -125,6 +140,44 @@ export const RecordPicker: any = connect( mapReadPretty(ReadPrettyRecordPicker), ); +RecordPicker.Options = observer((props) => { + const field = useField(); + const form = useForm(); + const { visible, setVisible } = useActionContext(); + const { t } = useTranslation(); + return ( + setVisible(false)} + footer={ + + + + + } + /> + ); +}); + RecordPicker.SelectedItem = () => { const ctx = useContext(RowContext); const fieldSchema = useFieldSchema(); diff --git a/packages/client/src/schema-component/antd/record-picker/demos/demo1.tsx b/packages/client/src/schema-component/antd/record-picker/demos/demo1.tsx index 60c44c25d..12d5c6389 100644 --- a/packages/client/src/schema-component/antd/record-picker/demos/demo1.tsx +++ b/packages/client/src/schema-component/antd/record-picker/demos/demo1.tsx @@ -3,7 +3,7 @@ */ import { FormItem } from '@formily/antd'; import { ISchema } from '@formily/react'; -import { Action, Input, RecordPicker, RowSelection, SchemaComponent, SchemaComponentProvider } from '@nocobase/client'; +import { Action, Input, RecordPicker, SchemaComponent, SchemaComponentProvider, Table } from '@nocobase/client'; import React from 'react'; const schema: ISchema = { @@ -18,6 +18,13 @@ const schema: ISchema = { ], 'x-decorator': 'FormItem', 'x-component': 'RecordPicker', + 'x-component-props': { + mode: 'tags', + fieldNames: { + label: 'name', + value: 'id', + }, + }, 'x-reactions': { target: 'read', fulfill: { @@ -27,30 +34,39 @@ const schema: ISchema = { }, }, properties: { - rowSelection: { - 'x-component': 'RowSelection', - 'x-component-props': { - rowKey: 'id', - objectValue: true, - rowSelection: { - type: 'checkbox', - }, - dataSource: [ - { id: 1, name: 'Name1' }, - { id: 2, name: 'Name2' }, - { id: 3, name: 'Name3' }, - ], - }, + options: { + 'x-component': 'RecordPicker.Options', + type: 'void', + title: 'Drawer Title', properties: { - column1: { - type: 'void', - title: 'Name', - 'x-component': 'RowSelection.Column', + input: { + type: 'array', + title: `编辑模式`, + 'x-component': 'Table.RowSelection', + 'x-component-props': { + rowKey: 'id', + objectValue: true, + rowSelection: { + type: 'checkbox', + }, + dataSource: [ + { id: 1, name: 'Name1' }, + { id: 2, name: 'Name2' }, + { id: 3, name: 'Name3' }, + ], + }, properties: { - name: { - type: 'string', - 'x-component': 'Input', - 'x-read-pretty': true, + column1: { + type: 'void', + title: 'Name', + 'x-component': 'Table.Column', + properties: { + name: { + type: 'string', + 'x-component': 'Input', + 'x-read-pretty': true, + }, + }, }, }, }, @@ -102,7 +118,7 @@ const schema: ISchema = { export default () => { return ( - + ); diff --git a/packages/client/src/schema-component/core/FormProvider.tsx b/packages/client/src/schema-component/core/FormProvider.tsx new file mode 100644 index 000000000..312890b4e --- /dev/null +++ b/packages/client/src/schema-component/core/FormProvider.tsx @@ -0,0 +1,24 @@ +import { + FormProvider as FormilyFormProvider, + IProviderProps, + SchemaExpressionScopeContext, + SchemaOptionsContext +} from '@formily/react'; +import React, { useContext } from 'react'; +import { SchemaComponentOptions } from './SchemaComponentOptions'; + +export const FormProvider: React.FC = (props) => { + const { children, ...others } = props; + let options = useContext(SchemaOptionsContext); + const expressionScope = useContext(SchemaExpressionScopeContext); + const scope = { ...options?.scope, ...expressionScope }; + const components = { ...options?.components }; + + return ( + + + {children} + + + ); +}; diff --git a/packages/client/src/schema-component/core/index.tsx b/packages/client/src/schema-component/core/index.tsx index 7f593d796..34a8623ea 100644 --- a/packages/client/src/schema-component/core/index.tsx +++ b/packages/client/src/schema-component/core/index.tsx @@ -1,5 +1,7 @@ export * from './DesignableSwitch'; +export * from './FormProvider'; export * from './RemoteSchemaComponent'; export * from './SchemaComponent'; export * from './SchemaComponentOptions'; export * from './SchemaComponentProvider'; + diff --git a/packages/plugin-acl/src/server.ts b/packages/plugin-acl/src/server.ts index cd7c00d56..dc013ef3e 100644 --- a/packages/plugin-acl/src/server.ts +++ b/packages/plugin-acl/src/server.ts @@ -238,7 +238,10 @@ export class PluginACL extends Plugin { await this.writeRolesToACL(); }); - this.app.on('afterInstallUsersPlugin', async () => { + this.app.on('beforeInstallPlugin', async (plugin) => { + if (plugin.constructor.name !== 'UsersPlugin') { + return; + } const repository = this.app.db.getRepository('roles'); await repository.createMany({ records: [ diff --git a/packages/plugin-users/src/server.ts b/packages/plugin-users/src/server.ts index c526723cb..d1cc9191f 100644 --- a/packages/plugin-users/src/server.ts +++ b/packages/plugin-users/src/server.ts @@ -5,22 +5,6 @@ import * as actions from './actions/users'; import * as middlewares from './middlewares'; export default class UsersPlugin extends Plugin { - async install() { - const { - adminNickname = 'Super Admin', - adminEmail = 'admin@nocobase.com', - adminPassword = 'admin123', - } = this.options; - - const User = this.db.getCollection('users'); - await User.repository.create({ - values: { - nickname: adminNickname, - email: adminEmail, - password: adminPassword, - }, - }); - } async beforeLoad() { this.db.on('users.afterCreateWithAssociations', async (model, options) => { @@ -83,4 +67,23 @@ export default class UsersPlugin extends Plugin { directory: resolve(__dirname, 'collections'), }); } + + async install() { + const { + adminNickname = 'Super Admin', + adminEmail = 'admin@nocobase.com', + adminPassword = 'admin123', + } = this.options; + + const User = this.db.getCollection('users'); + await User.repository.create({ + values: { + nickname: adminNickname, + email: adminEmail, + password: adminPassword, + roles: ['admin'], + }, + }); + } + } diff --git a/packages/server/src/plugin-manager.ts b/packages/server/src/plugin-manager.ts index cf78e3732..be8a1cf6b 100644 --- a/packages/server/src/plugin-manager.ts +++ b/packages/server/src/plugin-manager.ts @@ -1,6 +1,6 @@ +import { CleanOptions, SyncOptions } from '@nocobase/database'; import Application from './application'; import { Plugin } from './plugin'; -import { CleanOptions, SyncOptions } from '@nocobase/database'; interface PluginManagerOptions { app: Application;