feat(variable): add current role (#3167)

* feat(variable): add current role

* chore: translate

* feat: parsing in the backend

* fix: fix tests
This commit is contained in:
Zeke Zhang 2023-12-08 19:19:53 +08:00 committed by GitHub
parent d782776a8d
commit a2be1a0e33
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 92 additions and 3 deletions

View File

@ -606,6 +606,7 @@
"Constant value": "Constant value",
"Dynamic value": "Dynamic value",
"Current user": "Current user",
"Current role": "Current role",
"Current record": "Current record",
"Parent record": "Parent record",
"Current time": "Current time",

View File

@ -602,6 +602,7 @@
"Constant value": "Valor constante",
"Dynamic value": "Valor dinámico",
"Current user": "Usuario actual",
"Current role": "Rol actual",
"Current record": "Registro actual",
"Parent record": "Registro padre",
"Current time": "Hora actual",

View File

@ -599,6 +599,7 @@
"Constant value": "Valeur constante",
"Dynamic value": "Valeur dynamique",
"Current user": "Utilisateur actuel",
"Current role": "Rôle actuel",
"Current record": "Enregistrement actuel",
"Parent record": "Enregistrement parent",
"Current time": "Heure actuelle",

View File

@ -501,6 +501,7 @@
"Constant value": "定数値",
"Dynamic value": "動的値",
"Current user": "現在のユーザー",
"Current role": "現在の役割",
"Current record": "現在のレコード",
"Popup close method": "ポップアップを閉じる方法",
"Automatic close": "自動で閉じる",

View File

@ -438,6 +438,7 @@
"Constant value": "Постоянное значение",
"Dynamic value": "Динамическое значение",
"Current user": "Текущий пользователь",
"Current role": "Текущая роль",
"Current record": "Текущая запись",
"Parent record": "Родительская запись",
"Popup close method": "Метод закрытия всплывающего окна",

View File

@ -437,6 +437,7 @@
"Constant value": "Sabit değer",
"Dynamic value": "Dinamik değer",
"Current user": "Seçili kullanıcı",
"Current role": "Seçili rol",
"Current record": "Seçili kayıt",
"Parent record": "Üst kayıt",
"Popup close method": "Açılır pencere kapatma metodu",

View File

@ -619,6 +619,7 @@
"Constant value": "Константне значення",
"Dynamic value": "Динамічне значення",
"Current user": "Поточний користувач",
"Current role": "Поточна роль",
"Current record": "Поточний запис",
"Parent record": "Батьківський запис",
"Current time": "Поточний час",

View File

@ -622,6 +622,7 @@
"Constant value": "静态值",
"Dynamic value": "动态值",
"Current user": "当前用户",
"Current role": "当前角色",
"Current record": "当前记录",
"Parent record": "上级记录",
"Current time": "当前时间",

View File

@ -146,6 +146,10 @@ export const getShouldChange = ({
const collectionsInheritChain = collectionField ? getAllCollectionsInheritChain(collectionField.target) : [];
return async (value: any, optionPath: any[]) => {
if (_.isString(value) && value.includes('$nRole')) {
return true;
}
if (!isVariable(value) || !variables || !collectionField) {
return true;
}

View File

@ -49,6 +49,10 @@ interface BaseProps {
* 使
*/
noDisabled?: boolean;
/**
*
*/
noChildren?: boolean;
/**
* fields
* @param fields
@ -131,6 +135,7 @@ export const useBaseVariable = ({
name,
title,
collectionName,
noChildren = false,
// TODO: 等整理完完整测试用例后,再开启该功能
noDisabled = true,
returnFields = (fields) => fields,
@ -202,7 +207,7 @@ export const useBaseVariable = ({
label: title,
value: name,
key: name,
isLeaf: false,
isLeaf: noChildren,
field: {
target: collectionName,
},

View File

@ -0,0 +1,39 @@
import { Schema } from '@formily/json-schema';
import { useTranslation } from 'react-i18next';
import { CollectionFieldOptions } from '../../../collection-manager';
import { useBaseVariable } from './useBaseVariable';
/**
* `当前角色`
* @param param0
* @returns
*/
export const useRoleVariable = ({
collectionField,
uiSchema,
noDisabled,
targetFieldSchema,
maxDepth = 0,
}: {
collectionField: CollectionFieldOptions;
uiSchema: any;
maxDepth?: number;
noDisabled?: boolean;
/** 消费变量值的字段 */
targetFieldSchema?: Schema;
}) => {
const { t } = useTranslation();
const result = useBaseVariable({
collectionField,
uiSchema,
maxDepth,
name: '$nRole',
title: t('Current role'),
collectionName: 'roles',
noDisabled,
targetFieldSchema,
noChildren: true,
});
return result;
};

View File

@ -10,6 +10,7 @@ import { useFormVariable } from './useFormVariable';
import { useIterationVariable } from './useIterationVariable';
import { useParentRecordVariable } from './useParentRecordVariable';
import { useRecordVariable } from './useRecordVariable';
import { useRoleVariable } from './useRoleVariable';
import { useUserVariable } from './useUserVariable';
interface Props {
@ -58,6 +59,12 @@ export const useVariableOptions = ({
noDisabled,
targetFieldSchema,
});
const roleVariable = useRoleVariable({
uiSchema: uiSchema,
collectionField,
noDisabled,
targetFieldSchema,
});
const dateVariable = useDateVariable({ operator, schema: uiSchema, noDisabled });
const formVariable = useFormVariable({
schema: uiSchema,
@ -91,6 +98,7 @@ export const useVariableOptions = ({
return useMemo(() => {
return [
userVariable,
roleVariable,
dateVariable,
form && !form.readPretty && formVariable,
(isInSubForm || isInSubTable) && iterationVariable,
@ -101,6 +109,7 @@ export const useVariableOptions = ({
].filter(Boolean);
}, [
userVariable,
roleVariable,
dateVariable,
form,
formVariable,

View File

@ -14,7 +14,7 @@ interface Props {
}
// TODO: 建议变量名统一命名为 `$n` 开头,以防止与 formily 内置变量冲突
const defaultExclude = ['$user', '$date', '$nDate'];
const defaultExclude = ['$user', '$date', '$nDate', '$nRole'];
const useParseDataScopeFilter = ({ exclude = defaultExclude, currentRecord }: Props = {}) => {
const localVariables = useLocalVariables({ currentRecord });

View File

@ -56,6 +56,10 @@ vi.mock('../../collection-manager', async () => {
});
const { apiClient, mockRequest } = mockAPIClient();
// 用于解析 `$nRole` 的值
apiClient.auth.role = 'root';
mockRequest.onGet('/auth:check').reply(() => {
return [
200,
@ -67,6 +71,16 @@ mockRequest.onGet('/auth:check').reply(() => {
},
];
});
mockRequest.onGet('/roles:check').reply(() => {
return [
200,
{
data: {
role: 'root',
},
},
];
});
mockRequest.onGet('/users/0/belongsToField:get').reply(() => {
return [
200,
@ -194,6 +208,7 @@ describe('useVariables', () => {
"tomorrow": [Function],
"yesterday": [Function],
},
"$nRole": "root",
"$system": {
"now": [Function],
},
@ -404,6 +419,7 @@ describe('useVariables', () => {
"tomorrow": [Function],
"yesterday": [Function],
},
"$nRole": "root",
"$system": {
"now": [Function],
},
@ -487,6 +503,7 @@ describe('useVariables', () => {
"tomorrow": [Function],
"yesterday": [Function],
},
"$nRole": "root",
"$new": {
"name": "new variable",
},

View File

@ -1,11 +1,13 @@
import { dayjs } from '@nocobase/utils/client';
import { useMemo } from 'react';
import { useAPIClient } from '../../api-client';
import { getDateRanges } from '../../schema-component/antd/date-picker/util';
import { useCurrentUserContext } from '../../user';
import { VariableOption } from '../types';
const useBuiltInVariables = () => {
const data = useCurrentUserContext();
const apiClient = useAPIClient();
const currentUser = data?.data?.data;
const dateVars = getDateRanges();
@ -16,6 +18,11 @@ const useBuiltInVariables = () => {
ctx: currentUser,
collectionName: 'users',
},
{
name: '$nRole',
ctx: apiClient.auth?.role,
collectionName: 'roles',
},
/**
* @deprecated
*

View File

@ -1,5 +1,4 @@
import { getDateVars, parseFilter } from '@nocobase/utils';
import lodash from 'lodash';
function getUser(ctx) {
return async ({ fields }) => {
@ -54,6 +53,7 @@ export const parseVariables = async (ctx, next) => {
// 新的命名方式,防止和 formily 内置变量冲突
$nDate: getDateVars(),
$user: getUser(ctx),
$nRole: ctx.state.currentRole,
},
});
await next();