feat(client): improve acl module
This commit is contained in:
parent
6f2069e918
commit
d1ac62ddaf
@ -3,6 +3,8 @@ export interface AvailableActionOptions {
|
|||||||
type: 'new-data' | 'old-data';
|
type: 'new-data' | 'old-data';
|
||||||
displayName?: string;
|
displayName?: string;
|
||||||
resource?: string;
|
resource?: string;
|
||||||
|
onNewRecord?: boolean;
|
||||||
|
allowConfigureFields?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AclAvailableAction {
|
export class AclAvailableAction {
|
||||||
|
@ -47,7 +47,7 @@ export const RoleConfigure = () => {
|
|||||||
'x-component': 'Checkbox',
|
'x-component': 'Checkbox',
|
||||||
'x-content': '允许配置系统,包括界面配置、数据表配置、权限配置、系统配置等全部配置项',
|
'x-content': '允许配置系统,包括界面配置、数据表配置、权限配置、系统配置等全部配置项',
|
||||||
},
|
},
|
||||||
strategy: {
|
'strategy.actions': {
|
||||||
title: '通用数据操作权限',
|
title: '通用数据操作权限',
|
||||||
description: '所有数据表都默认使用通用数据操作权限;同时,可以针对每个数据表单独配置权限。',
|
description: '所有数据表都默认使用通用数据操作权限;同时,可以针对每个数据表单独配置权限。',
|
||||||
'x-component': 'StrategyActions',
|
'x-component': 'StrategyActions',
|
||||||
|
@ -1,15 +1,62 @@
|
|||||||
import { FormItem, FormLayout } from '@formily/antd';
|
import { FormItem, FormLayout } from '@formily/antd';
|
||||||
import { Checkbox, Select, Table } from 'antd';
|
import { ArrayField } from '@formily/core';
|
||||||
|
import { connect, useField, useForm } from '@formily/react';
|
||||||
|
import { Checkbox, Select, Table, Tag } from 'antd';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useAvailableActions } from '.';
|
import { useAvailableActions } from '.';
|
||||||
import { useCollectionManager, useCompile, useRecord } from '../..';
|
import { useCollectionManager, useCompile, useRecord } from '../..';
|
||||||
|
|
||||||
export const RolesResourcesActions = () => {
|
const toActionMap = (arr: any[]) => {
|
||||||
|
const obj = {};
|
||||||
|
arr?.forEach((action) => {
|
||||||
|
obj[action.name] = action;
|
||||||
|
});
|
||||||
|
return obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const RolesResourcesActions = connect((props) => {
|
||||||
|
const { onChange } = props;
|
||||||
|
const form = useForm();
|
||||||
const roleCollection = useRecord();
|
const roleCollection = useRecord();
|
||||||
const availableActions = useAvailableActions();
|
const availableActions = useAvailableActions();
|
||||||
const { getCollection } = useCollectionManager();
|
const { getCollection } = useCollectionManager();
|
||||||
const collection = getCollection(roleCollection.name);
|
const collection = getCollection(roleCollection.name);
|
||||||
const compile = useCompile();
|
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 = collection?.fields?.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: collection?.fields?.map?.((item) => item.name),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
onChange(Object.values(actionMap));
|
||||||
|
};
|
||||||
|
const allChecked = {};
|
||||||
|
for (const action of availableActionsWithFields) {
|
||||||
|
allChecked[action.name] = collection?.fields?.length === actionMap?.[action.name]?.fields?.length;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<FormLayout layout={'vertical'}>
|
<FormLayout layout={'vertical'}>
|
||||||
@ -24,13 +71,26 @@ export const RolesResourcesActions = () => {
|
|||||||
render: (value) => compile(value),
|
render: (value) => compile(value),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
dataIndex: 'type',
|
dataIndex: 'onNewRecord',
|
||||||
title: '类型',
|
title: '类型',
|
||||||
|
render: (onNewRecord) =>
|
||||||
|
onNewRecord ? (
|
||||||
|
<Tag color={'green'}>{t('Operate on new record')}</Tag>
|
||||||
|
) : (
|
||||||
|
<Tag color={'geekblue'}>{t('Operate on existing record')}</Tag>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
dataIndex: 'enable',
|
dataIndex: 'enabled',
|
||||||
title: '允许操作',
|
title: '允许操作',
|
||||||
render: () => <Checkbox />,
|
render: (enabled, action) => (
|
||||||
|
<Checkbox
|
||||||
|
checked={enabled}
|
||||||
|
onChange={() => {
|
||||||
|
toggleAction(action.name);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
dataIndex: 'scope',
|
dataIndex: 'scope',
|
||||||
@ -38,36 +98,81 @@ export const RolesResourcesActions = () => {
|
|||||||
render: () => <Select size={'small'} />,
|
render: () => <Select size={'small'} />,
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
dataSource={availableActions}
|
dataSource={availableActions?.map((item) => {
|
||||||
|
let enabled = false;
|
||||||
|
let scope = null;
|
||||||
|
if (actionMap[item.name]) {
|
||||||
|
enabled = true;
|
||||||
|
scope = actionMap[item.name]['scope'];
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
enabled,
|
||||||
|
scope,
|
||||||
|
};
|
||||||
|
})}
|
||||||
/>
|
/>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem label={'字段权限'}>
|
<FormItem label={'字段权限'}>
|
||||||
<Table
|
<Table
|
||||||
dataSource={collection?.fields}
|
pagination={false}
|
||||||
|
dataSource={fieldPermissions}
|
||||||
columns={[
|
columns={[
|
||||||
{
|
{
|
||||||
dataIndex: ['uiSchema', 'title'],
|
dataIndex: ['uiSchema', 'title'],
|
||||||
title: '字段名称',
|
title: '字段名称',
|
||||||
|
render: (value) => compile(value),
|
||||||
},
|
},
|
||||||
{
|
...availableActionsWithFields.map((action) => {
|
||||||
dataIndex: 'view',
|
const checked = allChecked?.[action.name];
|
||||||
title: '查看',
|
return {
|
||||||
render: () => <Checkbox />,
|
dataIndex: action.name,
|
||||||
},
|
title: (
|
||||||
{
|
<>
|
||||||
dataIndex: 'update',
|
<Checkbox
|
||||||
title: '编辑',
|
checked={checked}
|
||||||
render: () => <Checkbox />,
|
onChange={() => {
|
||||||
},
|
const item = actionMap[action.name] || {
|
||||||
{
|
name: action.name,
|
||||||
dataIndex: 'create',
|
};
|
||||||
title: '添加',
|
if (checked) {
|
||||||
render: () => <Checkbox />,
|
item.fields = [];
|
||||||
},
|
} else {
|
||||||
|
item.fields = collection?.fields?.map?.((item) => item.name);
|
||||||
|
}
|
||||||
|
actionMap[action.name] = item;
|
||||||
|
onChange(Object.values(actionMap));
|
||||||
|
}}
|
||||||
|
/>{' '}
|
||||||
|
{compile(action.displayName)}
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
render: (checked, field) => (
|
||||||
|
<Checkbox
|
||||||
|
checked={checked}
|
||||||
|
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>
|
</FormItem>
|
||||||
</FormLayout>
|
</FormLayout>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
@ -1,11 +1,45 @@
|
|||||||
import { Checkbox, Select, Table } from 'antd';
|
import { ArrayField } from '@formily/core';
|
||||||
|
import { connect, useField } from '@formily/react';
|
||||||
|
import { Checkbox, Select, Table, Tag } from 'antd';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useAvailableActions } from '.';
|
import { useAvailableActions } from '.';
|
||||||
import { useCompile } from '../..';
|
import { useCompile } from '../..';
|
||||||
|
|
||||||
export const StrategyActions = () => {
|
const toScopes = (value) => {
|
||||||
|
if (!value) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const scopes = {};
|
||||||
|
value?.forEach?.((item) => {
|
||||||
|
const [name, scope] = item.split(':');
|
||||||
|
scopes[name] = scope || 'all';
|
||||||
|
});
|
||||||
|
return scopes;
|
||||||
|
};
|
||||||
|
|
||||||
|
const toFieldValue = (scopes) => {
|
||||||
|
const values = [];
|
||||||
|
for (const name in scopes) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(scopes, name)) {
|
||||||
|
const scope = scopes[name];
|
||||||
|
if (scope === 'all') {
|
||||||
|
values.push(name);
|
||||||
|
} else {
|
||||||
|
values.push(`${name}:${scope}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const StrategyActions = connect((props) => {
|
||||||
|
const { onChange } = props;
|
||||||
const availableActions = useAvailableActions();
|
const availableActions = useAvailableActions();
|
||||||
const compile = useCompile();
|
const compile = useCompile();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const field = useField<ArrayField>();
|
||||||
|
const scopes = toScopes(field.value);
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Table
|
<Table
|
||||||
@ -18,22 +52,66 @@ export const StrategyActions = () => {
|
|||||||
render: (value) => compile(value),
|
render: (value) => compile(value),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
dataIndex: 'type',
|
dataIndex: 'onNewRecord',
|
||||||
title: '类型',
|
title: '类型',
|
||||||
|
render: (onNewRecord) =>
|
||||||
|
onNewRecord ? (
|
||||||
|
<Tag color={'green'}>{t('Operate on new record')}</Tag>
|
||||||
|
) : (
|
||||||
|
<Tag color={'geekblue'}>{t('Operate on existing record')}</Tag>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
dataIndex: 'enable',
|
dataIndex: 'enabled',
|
||||||
title: '允许操作',
|
title: '允许操作',
|
||||||
render: () => <Checkbox />,
|
render: (enabled, action) => (
|
||||||
|
<Checkbox
|
||||||
|
checked={enabled}
|
||||||
|
onChange={(e) => {
|
||||||
|
if (enabled) {
|
||||||
|
delete scopes[action.name];
|
||||||
|
} else {
|
||||||
|
scopes[action.name] = 'all';
|
||||||
|
}
|
||||||
|
onChange(toFieldValue(scopes));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
dataIndex: 'scope',
|
dataIndex: 'scope',
|
||||||
title: '可操作的数据范围',
|
title: '可操作的数据范围',
|
||||||
render: () => <Select size={'small'} />,
|
render: (scope, action) =>
|
||||||
|
!action.onNewRecord && (
|
||||||
|
<Select
|
||||||
|
size={'small'}
|
||||||
|
value={scope}
|
||||||
|
options={[
|
||||||
|
{ label: 'All records', value: 'all' },
|
||||||
|
{ label: 'Own records', value: 'own' },
|
||||||
|
]}
|
||||||
|
onChange={(value) => {
|
||||||
|
scopes[action.name] = value;
|
||||||
|
onChange(toFieldValue(scopes));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
dataSource={availableActions}
|
dataSource={availableActions?.map((item) => {
|
||||||
|
let scope = 'all';
|
||||||
|
let enabled = false;
|
||||||
|
if (scopes[item.name]) {
|
||||||
|
enabled = true;
|
||||||
|
scope = scopes[item.name];
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
enabled,
|
||||||
|
scope,
|
||||||
|
};
|
||||||
|
})}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
@ -29,6 +29,20 @@ const collection = {
|
|||||||
description: '使用英文',
|
description: '使用英文',
|
||||||
} as ISchema,
|
} as ISchema,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
type: 'string',
|
||||||
|
name: 'usingConfig',
|
||||||
|
interface: 'input',
|
||||||
|
uiSchema: {
|
||||||
|
title: '权限策略',
|
||||||
|
type: 'string',
|
||||||
|
'x-component': 'Select',
|
||||||
|
enum: [
|
||||||
|
{ label: '单独配置', value: 'resourceAction', color: 'orange' },
|
||||||
|
{ label: '通用配置', value: 'strategy', color: 'default' },
|
||||||
|
],
|
||||||
|
} as ISchema,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
type: 'hasMany',
|
type: 'hasMany',
|
||||||
name: 'fields',
|
name: 'fields',
|
||||||
@ -100,6 +114,18 @@ export const roleCollectionsSchema: ISchema = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
column3: {
|
column3: {
|
||||||
|
type: 'void',
|
||||||
|
'x-decorator': 'Table.Column.Decorator',
|
||||||
|
'x-component': 'Table.Column',
|
||||||
|
properties: {
|
||||||
|
usingConfig: {
|
||||||
|
type: 'string',
|
||||||
|
'x-component': 'CollectionField',
|
||||||
|
'x-read-pretty': true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
column4: {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
title: 'Actions',
|
title: 'Actions',
|
||||||
'x-component': 'Table.Column',
|
'x-component': 'Table.Column',
|
||||||
@ -136,6 +162,14 @@ export const roleCollectionsSchema: ISchema = {
|
|||||||
{ value: false, label: '使用通用权限' },
|
{ value: false, label: '使用通用权限' },
|
||||||
{ value: true, label: '单独配置权限' },
|
{ value: true, label: '单独配置权限' },
|
||||||
],
|
],
|
||||||
|
'x-reactions': {
|
||||||
|
target: 'actions',
|
||||||
|
fulfill: {
|
||||||
|
state: {
|
||||||
|
hidden: '{{!$self.value}}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
'x-component': 'RolesResourcesActions',
|
'x-component': 'RolesResourcesActions',
|
||||||
|
@ -28,6 +28,16 @@ const collection = {
|
|||||||
description: '使用英文',
|
description: '使用英文',
|
||||||
} as ISchema,
|
} as ISchema,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
type: 'boolean',
|
||||||
|
name: 'default',
|
||||||
|
interface: 'boolean',
|
||||||
|
uiSchema: {
|
||||||
|
title: '默认角色',
|
||||||
|
type: 'boolean',
|
||||||
|
'x-component': 'Checkbox',
|
||||||
|
} as ISchema,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -44,7 +54,7 @@ export const roleSchema: ISchema = {
|
|||||||
resource: 'roles',
|
resource: 'roles',
|
||||||
action: 'list',
|
action: 'list',
|
||||||
params: {
|
params: {
|
||||||
pageSize: 5,
|
pageSize: 50,
|
||||||
filter: {},
|
filter: {},
|
||||||
sort: ['createdAt'],
|
sort: ['createdAt'],
|
||||||
appends: [],
|
appends: [],
|
||||||
@ -92,6 +102,10 @@ export const roleSchema: ISchema = {
|
|||||||
'x-component': 'CollectionField',
|
'x-component': 'CollectionField',
|
||||||
'x-decorator': 'FormItem',
|
'x-decorator': 'FormItem',
|
||||||
},
|
},
|
||||||
|
default: {
|
||||||
|
'x-component': 'CollectionField',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
},
|
||||||
footer: {
|
footer: {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-component': 'Action.Drawer.Footer',
|
'x-component': 'Action.Drawer.Footer',
|
||||||
@ -156,6 +170,18 @@ export const roleSchema: ISchema = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
column3: {
|
column3: {
|
||||||
|
type: 'void',
|
||||||
|
'x-decorator': 'Table.Column.Decorator',
|
||||||
|
'x-component': 'Table.Column',
|
||||||
|
properties: {
|
||||||
|
default: {
|
||||||
|
type: 'string',
|
||||||
|
'x-component': 'CollectionField',
|
||||||
|
'x-read-pretty': true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
column4: {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
title: 'Actions',
|
title: 'Actions',
|
||||||
'x-component': 'Table.Column',
|
'x-component': 'Table.Column',
|
||||||
@ -246,6 +272,10 @@ export const roleSchema: ISchema = {
|
|||||||
'x-decorator': 'FormItem',
|
'x-decorator': 'FormItem',
|
||||||
'x-disabled': true,
|
'x-disabled': true,
|
||||||
},
|
},
|
||||||
|
default: {
|
||||||
|
'x-component': 'CollectionField',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
},
|
||||||
footer: {
|
footer: {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-component': 'Action.Drawer.Footer',
|
'x-component': 'Action.Drawer.Footer',
|
||||||
|
@ -10,6 +10,7 @@ export const useRoleResourceValues = (options) => {
|
|||||||
resourceOf: record.roleName,
|
resourceOf: record.roleName,
|
||||||
action: 'get',
|
action: 'get',
|
||||||
params: {
|
params: {
|
||||||
|
appends: ['actions', 'actions.scope'],
|
||||||
filterByTk: record.name,
|
filterByTk: record.name,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -17,6 +18,9 @@ export const useRoleResourceValues = (options) => {
|
|||||||
);
|
);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (record.usingConfig === 'strategy') {
|
if (record.usingConfig === 'strategy') {
|
||||||
|
options.onSuccess({
|
||||||
|
data: {},
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (visible) {
|
if (visible) {
|
||||||
|
@ -1,18 +1,23 @@
|
|||||||
import { useForm } from '@formily/react';
|
import { useForm } from '@formily/react';
|
||||||
import { useAPIClient, useRecord } from '../../../';
|
import { useActionContext, useAPIClient, useRecord, useResourceActionContext } from '../../../';
|
||||||
|
|
||||||
export const useSaveRoleResourceAction = () => {
|
export const useSaveRoleResourceAction = () => {
|
||||||
const form = useForm();
|
const form = useForm();
|
||||||
const api = useAPIClient();
|
const api = useAPIClient();
|
||||||
const record = useRecord();
|
const record = useRecord();
|
||||||
|
const ctx = useActionContext();
|
||||||
|
const { refresh } = useResourceActionContext();
|
||||||
return {
|
return {
|
||||||
async run() {
|
async run() {
|
||||||
await api.resource('roles.resources', record.roleName).create({
|
await api.resource('roles.resources', record.roleName)[record.exists ? 'update' : 'create']({
|
||||||
|
filterByTk: record.name,
|
||||||
values: {
|
values: {
|
||||||
...form.values,
|
...form.values,
|
||||||
name: record.name,
|
name: record.name,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
ctx.setVisible(false);
|
||||||
|
refresh();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -3,7 +3,6 @@ import { observer, useField } from '@formily/react';
|
|||||||
import { Button, Modal } from 'antd';
|
import { Button, Modal } from 'antd';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import { GeneralSchemaDesigner, SchemaSettings } from '../../../schema-settings';
|
import { GeneralSchemaDesigner, SchemaSettings } from '../../../schema-settings';
|
||||||
import { SortableItem } from '../../common';
|
import { SortableItem } from '../../common';
|
||||||
import { useDesigner } from '../../hooks';
|
import { useDesigner } from '../../hooks';
|
||||||
@ -114,7 +113,7 @@ Action.Designer = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Action.Link = observer((props) => {
|
Action.Link = observer((props) => {
|
||||||
return <Action {...props} component={Link} className={'nb-action-link'} />;
|
return <Action {...props} component={'a'} className={'nb-action-link'} />;
|
||||||
});
|
});
|
||||||
|
|
||||||
Action.Drawer = ActionDrawer;
|
Action.Drawer = ActionDrawer;
|
||||||
|
@ -4,28 +4,34 @@ const availableActions: {
|
|||||||
[key: string]: AvailableActionOptions;
|
[key: string]: AvailableActionOptions;
|
||||||
} = {
|
} = {
|
||||||
create: {
|
create: {
|
||||||
displayName: '{{ t("Create") }}',
|
displayName: '{{t("Add new")}}',
|
||||||
type: 'new-data',
|
|
||||||
},
|
|
||||||
import: {
|
|
||||||
displayName: '{{ t("Import") }}',
|
|
||||||
type: 'new-data',
|
type: 'new-data',
|
||||||
|
onNewRecord: true,
|
||||||
|
allowConfigureFields: true,
|
||||||
},
|
},
|
||||||
|
// import: {
|
||||||
|
// displayName: '{{t("Import")}}',
|
||||||
|
// type: 'new-data',
|
||||||
|
// scope: false,
|
||||||
|
// },
|
||||||
export: {
|
export: {
|
||||||
displayName: '{{ t("Export") }}',
|
displayName: '{{t("Export")}}',
|
||||||
type: 'new-data',
|
type: 'old-data',
|
||||||
|
allowConfigureFields: true,
|
||||||
},
|
},
|
||||||
view: {
|
view: {
|
||||||
displayName: '{{ t("View") }}',
|
displayName: '{{t("View")}}',
|
||||||
type: 'old-data',
|
type: 'old-data',
|
||||||
aliases: ['get', 'list'],
|
aliases: ['get', 'list'],
|
||||||
|
allowConfigureFields: true,
|
||||||
},
|
},
|
||||||
update: {
|
update: {
|
||||||
displayName: '{{ t("Edit") }}',
|
displayName: '{{t("Edit")}}',
|
||||||
type: 'old-data',
|
type: 'old-data',
|
||||||
|
allowConfigureFields: true,
|
||||||
},
|
},
|
||||||
destroy: {
|
destroy: {
|
||||||
displayName: '{{ t("Delete") }}',
|
displayName: '{{t("Delete")}}',
|
||||||
type: 'old-data',
|
type: 'old-data',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user