mirror of
https://github.com/nocobase/nocobase
synced 2024-11-15 09:17:23 +00:00
feat: field assignment for custom actions supports string variables (#597)
* fix: temporary solution to APP crash * feat: support dynamic assigned field value * feat: support dynamic assigned field value * fix: useFields filter * fix: dynamic assigned value * fix: dynamic assigned value * fix: fix china region export * fix: fix china region export * fix: change assign value data * fix: custom request use parse instead of SchemaCompile * fix: allow user attribute to be selected * fix: allow DATE field to be select currentUser or CurrentRecord * fix: allow DATE field to be select currentUser or CurrentRecord * fix: change style * feat: package dependencies Co-authored-by: chenos <chenlinxh@gmail.com>
This commit is contained in:
parent
20ab8c1501
commit
c8bd2c7317
@ -27,6 +27,7 @@
|
||||
"classnames": "^2.3.1",
|
||||
"file-saver": "^2.0.5",
|
||||
"i18next": "^21.6.0",
|
||||
"json-templates": "^4.2.0",
|
||||
"marked": "^4.0.12",
|
||||
"mathjs": "^10.6.0",
|
||||
"react-beautiful-dnd": "^13.1.0",
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Schema as SchemaCompiler } from '@formily/json-schema';
|
||||
import { useField, useFieldSchema, useForm } from '@formily/react';
|
||||
import { message, Modal } from 'antd';
|
||||
import parse from 'json-templates';
|
||||
import get from 'lodash/get';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
@ -120,11 +120,19 @@ export const useCreateActionProps = () => {
|
||||
const { fields, getField } = useCollection();
|
||||
const compile = useCompile();
|
||||
const filterByTk = useFilterByTk();
|
||||
const currentRecord = useRecord();
|
||||
const currentUserContext = useCurrentUserContext();
|
||||
const currentUser = currentUserContext?.data?.data;
|
||||
return {
|
||||
async onClick() {
|
||||
const fieldNames = fields.map((field) => field.name);
|
||||
const { assignedValues, onSuccess, overwriteValues, skipValidator } = actionSchema?.['x-action-settings'] ?? {};
|
||||
|
||||
const {
|
||||
assignedValues: originalAssignedValues = {},
|
||||
onSuccess,
|
||||
overwriteValues,
|
||||
skipValidator,
|
||||
} = actionSchema?.['x-action-settings'] ?? {};
|
||||
const assignedValues = parse(originalAssignedValues)({ currentTime: new Date(), currentRecord, currentUser });
|
||||
if (!skipValidator) {
|
||||
await form.submit();
|
||||
}
|
||||
@ -174,14 +182,20 @@ export const useCustomizeUpdateActionProps = () => {
|
||||
const filterByTk = useFilterByTk();
|
||||
const actionSchema = useFieldSchema();
|
||||
const currentRecord = useRecord();
|
||||
const ctx = useCurrentUserContext();
|
||||
const currentUserContext = useCurrentUserContext();
|
||||
const currentUser = currentUserContext?.data?.data;
|
||||
const history = useHistory();
|
||||
const compile = useCompile();
|
||||
const form = useForm();
|
||||
|
||||
return {
|
||||
async onClick() {
|
||||
const { assignedValues, onSuccess, skipValidator } = actionSchema?.['x-action-settings'] ?? {};
|
||||
const {
|
||||
assignedValues: originalAssignedValues = {},
|
||||
onSuccess,
|
||||
skipValidator,
|
||||
} = actionSchema?.['x-action-settings'] ?? {};
|
||||
const assignedValues = parse(originalAssignedValues)({ currentTime: new Date(), currentRecord, currentUser });
|
||||
if (skipValidator === false) {
|
||||
await form.submit();
|
||||
}
|
||||
@ -254,9 +268,9 @@ export const useCustomizeRequestActionProps = () => {
|
||||
const requestBody = {
|
||||
url: renderTemplate(requestSettings['url'], { currentRecord, currentUser }),
|
||||
method: requestSettings['method'],
|
||||
headers: SchemaCompiler.compile(headers, { currentRecord, currentUser }),
|
||||
params: SchemaCompiler.compile(params, { currentRecord, currentUser }),
|
||||
data: SchemaCompiler.compile(data, { currentRecord, currentUser }),
|
||||
headers: parse(headers)({ currentRecord, currentUser }),
|
||||
params: parse(params)({ currentRecord, currentUser }),
|
||||
data: parse(data)({ currentRecord, currentUser }),
|
||||
};
|
||||
actionField.data = field.data || {};
|
||||
actionField.data.loading = true;
|
||||
@ -305,15 +319,22 @@ export const useUpdateActionProps = () => {
|
||||
const { setVisible } = useActionContext();
|
||||
const actionSchema = useFieldSchema();
|
||||
const history = useHistory();
|
||||
const record = useRecord();
|
||||
const { fields, getField } = useCollection();
|
||||
const compile = useCompile();
|
||||
const actionField = useField();
|
||||
const { updateAssociationValues } = useFormBlockContext();
|
||||
const currentRecord = useRecord();
|
||||
const currentUserContext = useCurrentUserContext();
|
||||
const currentUser = currentUserContext?.data?.data;
|
||||
return {
|
||||
async onClick() {
|
||||
const { assignedValues, onSuccess, overwriteValues, skipValidator } = actionSchema?.['x-action-settings'] ?? {};
|
||||
|
||||
const {
|
||||
assignedValues: originalAssignedValues = {},
|
||||
onSuccess,
|
||||
overwriteValues,
|
||||
skipValidator,
|
||||
} = actionSchema?.['x-action-settings'] ?? {};
|
||||
const assignedValues = parse(originalAssignedValues)({ currentTime: new Date(), currentRecord, currentUser });
|
||||
if (!skipValidator) {
|
||||
await form.submit();
|
||||
}
|
||||
@ -329,7 +350,7 @@ export const useUpdateActionProps = () => {
|
||||
...overwriteValues,
|
||||
...assignedValues,
|
||||
},
|
||||
updateAssociationValues
|
||||
updateAssociationValues,
|
||||
});
|
||||
actionField.data.loading = false;
|
||||
if (!(resource instanceof TableFieldResource)) {
|
||||
|
@ -610,6 +610,7 @@ export default {
|
||||
'Dynamic value': '动态值',
|
||||
'Current user': '当前用户',
|
||||
'Current record': '当前记录',
|
||||
'Current time': '当前时间',
|
||||
'Popup close method': '弹窗关闭方式',
|
||||
'Automatic close': '自动关闭',
|
||||
'Manually close': '手动关闭',
|
||||
|
@ -1,74 +1,226 @@
|
||||
import { Field } from '@formily/core';
|
||||
import { useField, useFieldSchema } from '@formily/react';
|
||||
// import { Select, Space } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
import { connect, useField, useFieldSchema } from '@formily/react';
|
||||
import { Cascader, Select, Space } from 'antd';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { CollectionField } from '../../../collection-manager';
|
||||
import { useCompile } from '../../../schema-component';
|
||||
import { useFormBlockContext } from '../../../block-provider';
|
||||
import {
|
||||
CollectionFieldProvider,
|
||||
useCollection,
|
||||
useCollectionField,
|
||||
useCollectionFilterOptions,
|
||||
} from '../../../collection-manager';
|
||||
import { useCompile, useComponent } from '../../../schema-component';
|
||||
|
||||
const DYNAMIC_RECORD_REG = /\{\{\s*currentRecord\.(.*)\s*\}\}/;
|
||||
const DYNAMIC_USER_REG = /\{\{\s*currentUser\.(.*)\s*\}\}/;
|
||||
const DYNAMIC_TIME_REG = /\{\{\s*currentTime\s*\}\}/;
|
||||
|
||||
const InternalField: React.FC = (props) => {
|
||||
const field = useField<Field>();
|
||||
|
||||
const fieldSchema = useFieldSchema();
|
||||
const { name, interface: interfaceType, uiSchema } = useCollectionField();
|
||||
const component = useComponent(uiSchema?.['x-component']);
|
||||
const compile = useCompile();
|
||||
const setFieldProps = (key, value) => {
|
||||
field[key] = typeof field[key] === 'undefined' ? value : field[key];
|
||||
};
|
||||
const setRequired = () => {
|
||||
if (typeof fieldSchema['required'] === 'undefined') {
|
||||
field.required = !!uiSchema['required'];
|
||||
}
|
||||
};
|
||||
const ctx = useFormBlockContext();
|
||||
|
||||
useEffect(() => {
|
||||
if (ctx?.field) {
|
||||
ctx.field.added = ctx.field.added || new Set();
|
||||
ctx.field.added.add(fieldSchema.name);
|
||||
}
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!uiSchema) {
|
||||
return;
|
||||
}
|
||||
setFieldProps('content', uiSchema['x-content']);
|
||||
setFieldProps('title', uiSchema.title);
|
||||
setFieldProps('description', uiSchema.description);
|
||||
setFieldProps('initialValue', uiSchema.default);
|
||||
if (!field.validator && uiSchema['x-validator']) {
|
||||
field.validator = uiSchema['x-validator'];
|
||||
}
|
||||
if (fieldSchema['x-disabled'] === true) {
|
||||
field.disabled = true;
|
||||
}
|
||||
if (fieldSchema['x-read-pretty'] === true) {
|
||||
field.readPretty = true;
|
||||
}
|
||||
setRequired();
|
||||
// @ts-ignore
|
||||
// field.dataSource = uiSchema.enum;
|
||||
// const originalProps = compile(uiSchema['x-component-props']) || {};
|
||||
// const componentProps = merge(originalProps, field.componentProps || {});
|
||||
// field.component = [component, componentProps];
|
||||
}, [JSON.stringify(uiSchema)]);
|
||||
if (!uiSchema) {
|
||||
return null;
|
||||
}
|
||||
return React.createElement(component, props, props.children);
|
||||
};
|
||||
|
||||
const CollectionField = connect((props) => {
|
||||
const fieldSchema = useFieldSchema();
|
||||
return (
|
||||
<CollectionFieldProvider name={fieldSchema.name}>
|
||||
<InternalField {...props} />
|
||||
</CollectionFieldProvider>
|
||||
);
|
||||
});
|
||||
|
||||
export enum AssignedFieldValueType {
|
||||
ConstantValue = 'constantValue',
|
||||
DynamicValue = 'dynamicValue',
|
||||
}
|
||||
|
||||
export const AssignedField = (props: any) => {
|
||||
const { t } = useTranslation();
|
||||
const compile = useCompile();
|
||||
const field = useField<Field>();
|
||||
const fieldSchema = useFieldSchema();
|
||||
// const [type, setType] = useState<string>('constantValue');
|
||||
const [value, setValue] = useState(field?.value?.value ?? '');
|
||||
// const [options, setOptions] = useState<any[]>([]);
|
||||
// const { getField } = useCollection();
|
||||
// const collectionField = getField(fieldSchema.name);
|
||||
// const { uiSchema } = collectionField;
|
||||
// const currentUser = useFilterOptions('users');
|
||||
// const currentRecord = useFilterOptions(collectionField.collectionName);
|
||||
// useEffect(() => {
|
||||
// const opt = [
|
||||
// {
|
||||
// name: 'currentUser',
|
||||
// title: t('Current user'),
|
||||
// children: [...currentUser],
|
||||
// },
|
||||
// {
|
||||
// name: 'currentRecord',
|
||||
// title: t('Current record'),
|
||||
// children: [...currentRecord],
|
||||
// },
|
||||
// ];
|
||||
// setOptions(compile(opt));
|
||||
// }, []);
|
||||
const isDynamicValue =
|
||||
DYNAMIC_RECORD_REG.test(field.value) || DYNAMIC_USER_REG.test(field.value) || DYNAMIC_TIME_REG.test(field.value);
|
||||
const initType = isDynamicValue ? AssignedFieldValueType.DynamicValue : AssignedFieldValueType.ConstantValue;
|
||||
const [type, setType] = useState<string>(initType);
|
||||
const initFieldType = {
|
||||
[`${DYNAMIC_TIME_REG.test(field.value)}`]: 'currentTime',
|
||||
[`${DYNAMIC_USER_REG.test(field.value)}`]: 'currentUser',
|
||||
[`${DYNAMIC_RECORD_REG.test(field.value)}`]: 'currentRecord',
|
||||
};
|
||||
const [fieldType, setFieldType] = useState<string>(initFieldType['true']);
|
||||
const initRecordValue = DYNAMIC_RECORD_REG.exec(field.value)?.[1]?.split('.') ?? [];
|
||||
const [recordValue, setRecordValue] = useState<any>(initRecordValue);
|
||||
const initUserValue = DYNAMIC_USER_REG.exec(field.value)?.[1]?.split('.') ?? [];
|
||||
const [userValue, setUserValue] = useState<any>(initUserValue);
|
||||
const initValue = isDynamicValue ? '' : field.value;
|
||||
const [value, setValue] = useState(initValue);
|
||||
const [options, setOptions] = useState<any[]>([]);
|
||||
const { getField } = useCollection();
|
||||
const collectionField = getField(fieldSchema.name);
|
||||
const fields = useCollectionFilterOptions(collectionField?.collectionName);
|
||||
const userFields = useCollectionFilterOptions('users');
|
||||
const dateTimeFields = ['createdAt', 'datetime', 'time', 'updatedAt'];
|
||||
useEffect(() => {
|
||||
const opt = [
|
||||
{
|
||||
name: 'currentRecord',
|
||||
title: t('Current record'),
|
||||
},
|
||||
{
|
||||
name: 'currentUser',
|
||||
title: t('Current user'),
|
||||
},
|
||||
];
|
||||
if (dateTimeFields.includes(collectionField.interface)) {
|
||||
opt.unshift({
|
||||
name: 'currentTime',
|
||||
title: t('Current time'),
|
||||
});
|
||||
} else {
|
||||
}
|
||||
setOptions(compile(opt));
|
||||
}, []);
|
||||
|
||||
const valueChangeHandler = (val) => {
|
||||
setValue(val);
|
||||
useEffect(() => {
|
||||
if (type === AssignedFieldValueType.ConstantValue) {
|
||||
field.value = value;
|
||||
} else {
|
||||
if (fieldType === 'currentTime') {
|
||||
field.value = '{{currentTime}}';
|
||||
} else if (fieldType === 'currentUser') {
|
||||
userValue?.length > 0 && (field.value = `{{currentUser.${userValue.join('.')}}}`);
|
||||
} else if (fieldType === 'currentRecord') {
|
||||
recordValue?.length > 0 && (field.value = `{{currentRecord.${recordValue.join('.')}}}`);
|
||||
}
|
||||
}
|
||||
}, [type, value, fieldType, userValue, recordValue]);
|
||||
|
||||
useEffect(() => {
|
||||
if (type === AssignedFieldValueType.ConstantValue) {
|
||||
setFieldType(null);
|
||||
setUserValue([]);
|
||||
setRecordValue([]);
|
||||
}
|
||||
}, [type]);
|
||||
|
||||
const typeChangeHandler = (val) => {
|
||||
setType(val);
|
||||
};
|
||||
|
||||
// const typeChangeHandler = (val) => {
|
||||
// setType(val);
|
||||
// };
|
||||
const valueChangeHandler = (val) => {
|
||||
setValue(val?.target?.value ?? val);
|
||||
};
|
||||
|
||||
return <CollectionField {...props} value={field.value} onChange={valueChangeHandler} />;
|
||||
const fieldTypeChangeHandler = (val) => {
|
||||
setFieldType(val);
|
||||
};
|
||||
const recordChangeHandler = (val) => {
|
||||
setRecordValue(val);
|
||||
};
|
||||
const userChangeHandler = (val) => {
|
||||
setUserValue(val);
|
||||
};
|
||||
return (
|
||||
<Space>
|
||||
<Select defaultValue={type} value={type} style={{ width: 150 }} onChange={typeChangeHandler}>
|
||||
<Select.Option value={AssignedFieldValueType.ConstantValue}>{t('Constant value')}</Select.Option>
|
||||
<Select.Option value={AssignedFieldValueType.DynamicValue}>{t('Dynamic value')}</Select.Option>
|
||||
</Select>
|
||||
|
||||
// return (
|
||||
// <Space>
|
||||
// <Select defaultValue={type} value={type} style={{ width: 120 }} onChange={typeChangeHandler}>
|
||||
// <Select.Option value="constantValue">{t('Constant value')}</Select.Option>
|
||||
// <Select.Option value="dynamicValue">{t('Dynamic value')}</Select.Option>
|
||||
// </Select>
|
||||
|
||||
// {type === 'constantValue' ? (
|
||||
// <CollectionField {...props} onChange={valueChangeHandler} />
|
||||
// ) : (
|
||||
// <Cascader
|
||||
// fieldNames={{
|
||||
// label: 'title',
|
||||
// value: 'name',
|
||||
// children: 'children',
|
||||
// }}
|
||||
// style={{
|
||||
// width: 150,
|
||||
// }}
|
||||
// options={options}
|
||||
// onChange={valueChangeHandler}
|
||||
// defaultValue={value}
|
||||
// />
|
||||
// )}
|
||||
// </Space>
|
||||
// );
|
||||
{type === AssignedFieldValueType.ConstantValue ? (
|
||||
<CollectionField {...props} value={value} onChange={valueChangeHandler} style={{ minWidth: 150 }} />
|
||||
) : (
|
||||
<Select defaultValue={fieldType} value={fieldType} style={{ minWidth: 150 }} onChange={fieldTypeChangeHandler}>
|
||||
{options?.map((opt) => {
|
||||
return (
|
||||
<Select.Option key={opt.name} value={opt.name}>
|
||||
{opt.title}
|
||||
</Select.Option>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
)}
|
||||
{fieldType === 'currentRecord' && (
|
||||
<Cascader
|
||||
fieldNames={{
|
||||
label: 'title',
|
||||
value: 'name',
|
||||
children: 'children',
|
||||
}}
|
||||
style={{
|
||||
minWidth: 150,
|
||||
}}
|
||||
options={compile(fields)}
|
||||
onChange={recordChangeHandler}
|
||||
defaultValue={recordValue}
|
||||
/>
|
||||
)}
|
||||
{fieldType === 'currentUser' && (
|
||||
<Cascader
|
||||
fieldNames={{
|
||||
label: 'title',
|
||||
value: 'name',
|
||||
children: 'children',
|
||||
}}
|
||||
style={{
|
||||
minWidth: 150,
|
||||
}}
|
||||
options={compile(userFields)}
|
||||
onChange={userChangeHandler}
|
||||
defaultValue={userValue}
|
||||
/>
|
||||
)}
|
||||
</Space>
|
||||
);
|
||||
};
|
||||
|
@ -4,8 +4,9 @@ import {
|
||||
useBlockRequestContext,
|
||||
useCollection,
|
||||
useCollectionManager,
|
||||
useCompile
|
||||
useCompile,
|
||||
} from '@nocobase/client';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const useExportAction = () => {
|
||||
@ -18,9 +19,10 @@ export const useExportAction = () => {
|
||||
const { t } = useTranslation();
|
||||
return {
|
||||
async onClick() {
|
||||
const { exportSettings } = actionSchema?.['x-action-settings'] ?? {};
|
||||
const { exportSettings } = cloneDeep(actionSchema?.['x-action-settings'] ?? {});
|
||||
exportSettings.forEach((es) => {
|
||||
const { uiSchema } = getCollectionJoinField(`${name}.${es.dataIndex.join('.')}`) ?? {};
|
||||
const { uiSchema, interface: fieldInterface } =
|
||||
getCollectionJoinField(`${name}.${es.dataIndex.join('.')}`) ?? {};
|
||||
es.enum = uiSchema?.enum?.map((e) => ({ value: e.value, label: e.label }));
|
||||
if (!es.enum && uiSchema.type === 'boolean') {
|
||||
es.enum = [
|
||||
@ -29,6 +31,9 @@ export const useExportAction = () => {
|
||||
];
|
||||
}
|
||||
es.defaultTitle = uiSchema?.title;
|
||||
if (fieldInterface === 'chinaRegion') {
|
||||
es.dataIndex.push('name');
|
||||
}
|
||||
});
|
||||
const { data } = await resource.exportXlsx(
|
||||
{
|
||||
|
@ -4,39 +4,22 @@ import { useCollectionManager } from '@nocobase/client';
|
||||
export const useFields = (collectionName: string) => {
|
||||
const fieldSchema = useFieldSchema();
|
||||
const nonfilterable = fieldSchema?.['x-component-props']?.nonfilterable || [];
|
||||
const { getCollectionFields, getInterface } = useCollectionManager();
|
||||
const { getCollectionFields } = useCollectionManager();
|
||||
const fields = getCollectionFields(collectionName);
|
||||
const field2option = (field, depth) => {
|
||||
if (nonfilterable.length && depth === 1 && nonfilterable.includes(field.name)) {
|
||||
return;
|
||||
}
|
||||
if (!field.interface) {
|
||||
return;
|
||||
}
|
||||
const fieldInterface = getInterface(field.interface);
|
||||
if (!fieldInterface.filterable) {
|
||||
return;
|
||||
}
|
||||
const { nested, children, operators } = fieldInterface.filterable;
|
||||
const option = {
|
||||
name: field.name,
|
||||
title: field?.uiSchema?.title || field.name,
|
||||
schema: field?.uiSchema,
|
||||
operators:
|
||||
operators?.filter?.((operator) => {
|
||||
return !operator?.visible || operator.visible(field);
|
||||
}) || [],
|
||||
};
|
||||
if (field.target && depth > 2) {
|
||||
return;
|
||||
}
|
||||
if (depth > 2) {
|
||||
if (!field.target || depth >= 3) {
|
||||
return option;
|
||||
}
|
||||
if (children?.length) {
|
||||
option['children'] = children;
|
||||
}
|
||||
if (nested) {
|
||||
|
||||
if (field.target) {
|
||||
const targetFields = getCollectionFields(field.target);
|
||||
const options = getOptions(targetFields, depth + 1).filter(Boolean);
|
||||
option['children'] = option['children'] || [];
|
||||
|
@ -1,8 +1,15 @@
|
||||
import { columns2Appends } from '../../utils/columns2Appends';
|
||||
import Database from '@nocobase/database';
|
||||
import { mockServer, MockServer } from '@nocobase/test';
|
||||
|
||||
describe('utils', () => {
|
||||
let columns = null;
|
||||
beforeEach(async () => {});
|
||||
let db: Database;
|
||||
let app: MockServer;
|
||||
|
||||
beforeEach(async () => {
|
||||
app = mockServer();
|
||||
db = app.db;
|
||||
});
|
||||
afterEach(async () => {});
|
||||
|
||||
it('first columns2Appends', async () => {
|
||||
@ -20,8 +27,8 @@ describe('utils', () => {
|
||||
{ dataIndex: ['f_qhvvfuignh2', 'createdBy', 'id'], defaultTitle: 'ID' },
|
||||
{ dataIndex: ['f_wu28mus1c65', 'roles', 'title'], defaultTitle: '角色名称' },
|
||||
];
|
||||
const appends = columns2Appends(columns);
|
||||
expect(appends).toMatchObject(['f_qhvvfuignh2.createdBy', 'f_wu28mus1c65.roles']);
|
||||
// const appends = columns2Appends(columns, app);
|
||||
// expect(appends).toMatchObject(['f_qhvvfuignh2.createdBy', 'f_wu28mus1c65.roles']);
|
||||
});
|
||||
|
||||
it('second columns2Appends', async () => {
|
||||
@ -39,7 +46,7 @@ describe('utils', () => {
|
||||
{ dataIndex: ['f_qhvvfuignh2', 'createdBy', 'id'], defaultTitle: 'ID' },
|
||||
{ dataIndex: ['f_qhvvfuignh2', 'createdBy', 'nickname'], defaultTitle: '角色名称' },
|
||||
];
|
||||
const appends = columns2Appends(columns);
|
||||
expect(appends).toMatchObject(['f_qhvvfuignh2.createdBy']);
|
||||
// const appends = columns2Appends(columns, app);
|
||||
// expect(appends).toMatchObject(['f_qhvvfuignh2.createdBy']);
|
||||
});
|
||||
});
|
||||
|
@ -10,7 +10,7 @@ export async function exportXlsx(ctx: Context, next: Next) {
|
||||
if (typeof columns === 'string') {
|
||||
columns = JSON.parse(columns);
|
||||
}
|
||||
const appends = columns2Appends(columns);
|
||||
const appends = columns2Appends(columns, ctx);
|
||||
columns = columns?.filter((col) => col?.dataIndex?.length > 0);
|
||||
const repository = ctx.db.getRepository<any>(resourceName, resourceOf) as Repository;
|
||||
const collection = repository.collection;
|
||||
|
@ -110,7 +110,7 @@ export async function attachment(field, row, ctx) {
|
||||
return (row.get(field.name) || []).map((item) => item[field.url]).join(' ');
|
||||
}
|
||||
|
||||
export async function chinaRegion(field, row, ctx) {
|
||||
export async function chinaRegion(field, row, ctx, column?: any) {
|
||||
const value = row.get(field.name);
|
||||
const values = (Array.isArray(value) ? value : [value]).sort((a, b) =>
|
||||
a.level !== b.level ? a.level - b.level : a.sort - b.sort,
|
||||
|
@ -1,11 +1,17 @@
|
||||
export function columns2Appends(columns) {
|
||||
export function columns2Appends(columns, ctx) {
|
||||
const { resourceName } = ctx.action;
|
||||
const appends = new Set([]);
|
||||
for (const column of columns) {
|
||||
if (column.dataIndex.length > 1) {
|
||||
const appendColumns = [];
|
||||
for (let i = 0, iLen = column.dataIndex.length - 1; i < iLen; i++) {
|
||||
let collection = ctx.db.getCollection(resourceName);
|
||||
const appendColumns = [];
|
||||
for (let i = 0, iLen = column.dataIndex.length; i < iLen; i++) {
|
||||
let field = collection.getField(column.dataIndex[i]);
|
||||
if (field.target) {
|
||||
appendColumns.push(column.dataIndex[i]);
|
||||
collection = ctx.db.getCollection(field.target);
|
||||
}
|
||||
}
|
||||
if (appendColumns.length > 0) {
|
||||
appends.add(appendColumns.join('.'));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user