tachybase_todo/packages/plugins/@nocobase/plugin-snapshot-field/src/client/interface.ts
jack zhang 705b7449f0
feat: new plugin manager, supports adding plugins through UI (#2430)
* refactor: plugin manager page

* fix: bug

* feat: addByNpm api

* fix: improve the addByNpm

* feat: improve applicationPlugins:list api

* fix: re-download npm package when restart app

* fix: plugin delete api

* feat: plugin detail api

* feat: zipUrl add api

* fix: upload api bug

* fix: plugin detail info

* feat: upgrade api

* fix: upload api

* feat: handle plugin load error

* feat: support authToken

* feat: muti lang

* fix: build error

* fix: self review

* Update plugin-manager.ts

* fix: bug

* fix: bug

* fix: bug

* fix: bug

* fix: bug

* fix: bugs

* fix: detail click and remove isOfficial

* fix: upgrade no refresh

* fix: file size and type check

* fix: bug

* fix: upgrade error

* fix: bug

* fix: bug

* fix: plugin card layout

* fix: handling exceptional cases

* fix: tgz file support

* fix: macos compress file

* fix: bug

* fix: bug

* fix: bug

* fix: bug

* fix: add upgrade npm type

* fix: bugs

* fix: bug

* fix: change plugins static expose url

* fix: api prefix

* fix: bug

* fix: add nginx `/static/plugin/` path

* fix: bugs and pr docker build no dts

* fix: bug

* fix: build tools bug

* fix: improve code

* fix: build bug

* feat: improve plugin info

* fix: ui bug

* fix: plugin document bug

* feat: improve code

* feat: improve code

* feat: process dev deps check

* feat: improve code

* feat: process.env.IS_DEV_CMD

* fix: do not delete the plugin package

* feat: plugin symlink

* fix: tsx watch --ignore=./storage/plugins/**

* fix: test error

* fix: improve code

* fix: improve code

* fix: emitStartedEvent

* fix: improve code

* fix: type error

* fix: test error

* test: console.log

* fix: createStoragePluginSymLink

* fix: clientStaticMiddleware rename to clientStaticUtils

* feat: build tools support plugins folder

* fix: 350px

* fix: error

* feat: client dev support plugin folder

* fix: clear cli options

* fix: typeError: Converting circular structure to JSON

* fix: plugin name

* chore: restart application after command

* feat: upgrade error & docs

* Update v14-changelog.md

* Update v14-changelog.md

* Update v14-changelog.md

* fix: gateway test

* refactor(plugin-workflow): add ready state for gracefully tearing down

* Revert "chore: restart application after command"

This reverts commit 5015274f8e4e06e506e15754b672330330e8c7f8.

* chore: stop application whe restart

* T 1218 change plugin folder (#2629)

* feat: change folder name

* feat: change `pm create` command

* feat:  revert plugin name change

* fix: delete samples

* feat: change plugins folder

* fix: pm create

* feat: update docs

* fix: link package error

* fix: docs

* fix: create command

* fix: pm add error

* fix: create  add build

* fix: pm creatre + add

* feat: add tar command

* fix: docs

* fix: bug

* fix: docs

---------

Co-authored-by: chenos <chenlinxh@gmail.com>

* feat: docs

* Update your-fisrt-plugin.md

* Update your-fisrt-plugin.md

* chore: application reload

* chore: test

* fix: pm add error

* chore: preset install skip exists plugin

* fix: createIfNotExists

---------

Co-authored-by: chenos <chenlinxh@gmail.com>
Co-authored-by: chareice <chareice@live.com>
Co-authored-by: Zhou <zhou.working@gmail.com>
Co-authored-by: mytharcher <mytharcher@gmail.com>
2023-09-12 22:39:23 +08:00

187 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 'lodash';
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': {
multiple: true,
useCollection: useRecordCollection,
},
'x-reactions': [
{
dependencies: [TARGET_FIELD],
when: '{{$deps[0]}}',
fulfill: {
run: '{{$self.setValue($self.value)}}',
},
},
],
},
},
};