tachybase_todo/packages/plugins/snapshot-field/src/client/interface.ts
Junyi 9f8460ca22
feat(plugin-workflow): change to unlimited depth preloading associations in workflow (#2142)
* refactor(plugin-snapshot): move AppendsTreeSelect component into client package

* refactor(plugin-workflow): change all appends fields select to AppendsTreeSelect

* refactor(plugin-workflow): change appends and toJSON logic on server side

* fix(plugin-workflow): fix toJSON logic and build error

* fix(plugin-workflow): fix missing component injection

* fix(plugin-workflow): fix cycle association in variables

* refactor(client): change AppendsTreeSelect to lazy load

* fix(client): fix lazy load in option
2023-07-17 20:36:17 -07:00

186 lines
5.2 KiB
TypeScript

import type { Field } from '@formily/core';
import { ISchema, useForm } from '@formily/react';
import { IField, interfacesProperties, useCollectionManager, useRecord } from '@nocobase/client';
import { lodash } from '@nocobase/utils/client';
import { NAMESPACE } from './locale';
const { defaultProps } = interfacesProperties;
const APPENDS = 'appends';
const TARGET_FIELD = 'targetField';
export const useTopRecord = () => {
let record = useRecord();
while (record && Object.keys(record.__parent).length > 0) {
record = record.__parent;
}
return record;
};
function useRecordCollection() {
const { getCollectionField } = useCollectionManager();
const record = useTopRecord();
const formValues = useForm().values;
return getCollectionField(`${record.name}.${formValues.targetField}`)?.target;
}
const onTargetFieldChange = (field: Field) => {
field.value; // for watch
const targetField = field.query(`.${APPENDS}`).take() as Field | undefined;
console.log(field.path);
if (!targetField) return;
!targetField.getState().disabled && targetField.setValue([]);
};
function MakeFieldsPathOptions(fields, appends = []) {
const { getCollection } = useCollectionManager();
const options = [];
fields.forEach((field) => {
if (['belongsTo', 'hasOne', 'hasMany', 'belongsToMany'].includes(field.type)) {
const currentAppends = appends.filter((key) => `${key}.`.startsWith(`${field.name}.`));
if (currentAppends.length) {
const nextCollection = getCollection(field.target);
const nextAppends = currentAppends
.filter((key) => key !== field.name)
.map((key) => key.replace(`${field.name}.`, ''))
.filter((key) => key);
options.push({
label: field.uiSchema?.title ?? field.name,
value: field.name,
children: MakeFieldsPathOptions(nextCollection.fields, nextAppends),
});
}
} else {
options.push({
label: field.uiSchema?.title ?? field.name,
value: field.name,
});
}
});
return options;
}
const recordPickerViewer = {
type: 'void',
title: `{{t('View record')}}`,
'x-component': 'RecordPicker.Viewer',
'x-component-props': {
className: 'nb-action-popup',
},
properties: {
tabs: {
type: 'void',
'x-component': 'Tabs',
'x-component-props': {},
// 'x-initializer': 'TabPaneInitializers',
properties: {
tab1: {
type: 'void',
title: `{{t('Detail')}}`,
'x-component': 'Tabs.TabPane',
'x-designer': 'Tabs.Designer',
'x-component-props': {},
properties: {
grid: {
type: 'void',
'x-component': 'Grid',
'x-initializer': 'SnapshotBlockInitializers',
properties: {},
},
},
},
},
},
},
};
export const snapshot: IField = {
name: 'snapshot',
type: 'object',
group: 'advanced',
title: `{{t('Snapshot', {ns: '${NAMESPACE}'})}}`,
description: `{{t('When adding a new record, create a snapshot for its relational record and save in the current record. The snapshot is not updated when the record is subsequently updated.', {ns: '${NAMESPACE}'})}}`,
default: {
type: 'snapshot',
// name,
uiSchema: {
// title,
'x-component': 'SnapshotRecordPicker',
'x-component-props': {
multiple: true,
fieldNames: {
label: 'id',
value: 'id',
},
},
},
},
schemaInitialize(schema: ISchema, { field, readPretty, action, block }) {
schema['properties'] = {
viewer: lodash.cloneDeep(recordPickerViewer),
};
},
initialize: (values: any) => {},
usePathOptions(field) {
const { appends = [], targetCollection } = field;
const { getCollection } = useCollectionManager();
const { fields } = getCollection(targetCollection);
const result = MakeFieldsPathOptions(fields, appends);
return [
{
label: `{{t('Snapshot data', { ns: '${NAMESPACE}' })}}`,
value: 'data',
children: result,
},
];
},
properties: {
...defaultProps,
[TARGET_FIELD]: {
type: 'string',
title: `{{t('The association field to snapshot', {ns: '${NAMESPACE}'})}}`,
required: true,
'x-decorator': 'FormItem',
'x-component': 'SnapshotOwnerCollectionFieldsSelect',
'x-disabled': '{{ !createOnly || isOverride }}',
'x-reactions': [
{
target: APPENDS,
when: '{{$self.value != undefined}}',
fulfill: {
state: {
visible: true,
},
},
otherwise: {
state: {
visible: false,
},
},
},
],
},
[APPENDS]: {
type: 'string',
title: `{{t("Snapshot the snapshot's association fields", {ns: "${NAMESPACE}"})}}`,
'x-decorator': 'FormItem',
'x-component': 'AppendsTreeSelect',
'x-component-props': {
useCollection: useRecordCollection,
},
'x-reactions': [
{
dependencies: [TARGET_FIELD],
when: '{{$deps[0]}}',
fulfill: {
run: '{{$self.setValue($self.value)}}',
},
},
],
},
},
};