jack zhang 454d1d34ed
fix: add displayName (#3628)
* fix: context add displayName

* fix: observer add displayName

* fix: memo component add displayName

* fix: forwordRef component add displayName
2024-03-06 18:22:31 +08:00

231 lines
8.0 KiB
TypeScript

import { FormItem, FormLayout } from '@formily/antd-v5';
import { ArrayField } from '@formily/core';
import { connect, useField, useForm } from '@formily/react';
import {
useCollectionManager,
useCollectionManager_deprecated,
useCompile,
useCollectionRecord,
useRecord,
} from '@nocobase/client';
import { Checkbox, Table, Tag } from 'antd';
import { isEmpty } from 'lodash';
import React, { createContext } from 'react';
import { useTranslation } from 'react-i18next';
import { useAvailableActions } from './AvailableActions';
import { ScopeSelect } from './ScopeSelect';
import { useStyles } from './style';
const toActionMap = (arr: any[]) => {
const obj = {};
arr?.forEach?.((action) => {
if (action.name) {
obj[action.name] = action;
obj[action.name]['scope'] = isEmpty(action.scope) ? null : action.scope;
}
});
return obj;
};
export const RoleResourceCollectionContext = createContext<any>({});
RoleResourceCollectionContext.displayName = 'RoleResourceCollectionContext';
export const RolesResourcesActions = connect((props) => {
const { styles } = useStyles();
// const { onChange } = props;
const onChange = (values) => {
const items = values.map((item) => {
return {
...item,
scope: isEmpty(item.scope) ? null : item.scope,
};
});
props.onChange(items);
};
const form = useForm();
const roleCollection = useRecord();
const availableActions = useAvailableActions();
const { getCollection, getCollectionFields } = useCollectionManager_deprecated();
const collection = getCollection(roleCollection.collectionName);
const collectionFields = getCollectionFields(roleCollection.collectionName);
const compile = useCompile();
const { t } = useTranslation();
const field = useField<ArrayField>();
const actionMap: any = toActionMap(field.value || []);
const inAction = (actionName, fieldName) => {
const action = actionMap?.[actionName];
if (!action) {
return false;
}
return action?.fields?.includes(fieldName);
};
const availableActionsWithFields = availableActions.filter((action) => action.allowConfigureFields);
const fieldPermissions = collectionFields
?.filter((field) => field.interface)
?.map((field) => {
const permission = { ...field };
for (const action of availableActionsWithFields) {
permission[action.name] = inAction(action.name, field.name);
}
return permission;
});
const toggleAction = (actionName: string) => {
if (actionMap[actionName]) {
delete actionMap[actionName];
} else {
actionMap[actionName] = {
name: actionName,
fields: collectionFields?.filter((field) => field.interface)?.map?.((item) => item.name),
};
}
onChange(Object.values(actionMap));
};
const setScope = (actionName, scope) => {
if (!actionMap[actionName]) {
toggleAction(actionName);
actionMap[actionName]['scope'] = scope;
} else {
actionMap[actionName]['scope'] = scope;
onChange(Object.values(actionMap));
}
};
const allChecked = {};
for (const action of availableActionsWithFields) {
allChecked[action.name] =
collectionFields?.filter((field) => field.interface)?.length === actionMap?.[action.name]?.fields?.length;
}
return (
<div>
<RoleResourceCollectionContext.Provider value={collection}>
<FormLayout layout={'vertical'}>
<FormItem label={t('Action permission')}>
<Table
className={styles}
size={'small'}
pagination={false}
columns={[
{
dataIndex: 'displayName',
title: t('Action display name'),
render: (value) => compile(value),
},
{
dataIndex: 'onNewRecord',
title: t('Action type'),
render: (onNewRecord) =>
onNewRecord ? (
<Tag color={'green'}>{t('Action on new records')}</Tag>
) : (
<Tag color={'geekblue'}>{t('Action on existing records')}</Tag>
),
},
{
dataIndex: 'enabled',
title: t('Allow'),
render: (enabled, action) => (
<Checkbox
checked={enabled}
onChange={() => {
toggleAction(action.name);
}}
/>
),
},
{
dataIndex: 'scope',
title: t('Data scope'),
render: (value, action) =>
!action.onNewRecord && (
<ScopeSelect
value={value}
onChange={(scope) => {
setScope(action.name, scope);
}}
/>
),
},
]}
dataSource={availableActions?.map((item) => {
let enabled = false;
let scope = null;
if (actionMap[item.name]) {
enabled = true;
if (!item.onNewRecord) {
scope = actionMap[item.name]['scope'];
}
}
return {
...item,
enabled,
scope,
};
})}
/>
</FormItem>
<FormItem label={t('Field permission')}>
<Table
className={styles}
pagination={false}
dataSource={fieldPermissions}
columns={[
{
dataIndex: ['uiSchema', 'title'],
title: t('Field display name'),
render: (value) => compile(value),
},
...availableActionsWithFields.map((action) => {
const checked = allChecked?.[action.name];
return {
dataIndex: action.name,
title: (
<>
<Checkbox
checked={checked}
onChange={() => {
const item = actionMap[action.name] || {
name: action.name,
};
if (checked) {
item.fields = [];
} else {
item.fields = collectionFields?.map?.((item) => item.name);
}
actionMap[action.name] = item;
onChange(Object.values(actionMap));
}}
/>{' '}
{compile(action.displayName)}
</>
),
render: (checked, field) => (
<Checkbox
checked={checked}
aria-label={`${action.name}_checkbox`}
onChange={() => {
const item = actionMap[action.name] || {
name: action.name,
};
const fields: string[] = item.fields || [];
if (checked) {
const index = fields.indexOf(field.name);
fields.splice(index, 1);
} else {
fields.push(field.name);
}
item.fields = fields;
actionMap[action.name] = item;
onChange(Object.values(actionMap));
}}
/>
),
};
}),
]}
/>
</FormItem>
</FormLayout>
</RoleResourceCollectionContext.Provider>
</div>
);
});