Merge branch 'main' into next

This commit is contained in:
xilesun 2024-10-30 10:54:41 +08:00
commit c4b6a004e6
12 changed files with 1173 additions and 231 deletions

View File

@ -32,8 +32,8 @@
"@nocobase/utils": "1.4.0-alpha", "@nocobase/utils": "1.4.0-alpha",
"ahooks": "^3.7.2", "ahooks": "^3.7.2",
"antd": "5.12.8", "antd": "5.12.8",
"antd-style": "3.4.5",
"axios": "^1.7.0", "axios": "^1.7.0",
"antd-style": "3.7.1",
"bignumber.js": "^9.1.2", "bignumber.js": "^9.1.2",
"classnames": "^2.3.1", "classnames": "^2.3.1",
"cronstrue": "^2.11.0", "cronstrue": "^2.11.0",

View File

@ -7,11 +7,18 @@
* For more information, please refer to: https://www.nocobase.com/agreement. * For more information, please refer to: https://www.nocobase.com/agreement.
*/ */
import { useForm } from '@formily/react';
import { useCollectionRecordData } from '../../../../../data-source/collection-record/CollectionRecordProvider'; import { useCollectionRecordData } from '../../../../../data-source/collection-record/CollectionRecordProvider';
import { useSatisfiedActionValues } from '../../../../../schema-settings/LinkageRules/useActionValues'; import { useSatisfiedActionValues } from '../../../../../schema-settings/LinkageRules/useActionValues';
import { useFormBlockContext } from '../../../../../block-provider';
import { useSubFormValue } from '../../../../../schema-component/antd/association-field/hooks';
export function useDataFormItemProps() { export function useDataFormItemProps() {
const data = useCollectionRecordData(); const record = useCollectionRecordData();
const { valueMap: style } = useSatisfiedActionValues({ category: 'style', formValues: data }); const { form } = useFormBlockContext();
const subForm = useSubFormValue();
const { valueMap: style } = useSatisfiedActionValues({
category: 'style',
formValues: subForm?.formValue || form?.values || record,
form,
});
return { wrapperStyle: style }; return { wrapperStyle: style };
} }

View File

@ -936,7 +936,7 @@ test.describe('actions schema settings', () => {
).toBeVisible(); ).toBeVisible();
}); });
test('open mode', async ({ page, mockPage }) => { test.skip('open mode', async ({ page, mockPage }) => {
const nocoPage = await mockPage(testingOfOpenModeForAddChild).waitForInit(); const nocoPage = await mockPage(testingOfOpenModeForAddChild).waitForInit();
await nocoPage.goto(); await nocoPage.goto();

View File

@ -45,7 +45,7 @@ describe('CollectionSelect', () => {
expect(container).toMatchInlineSnapshot(` expect(container).toMatchInlineSnapshot(`
<div> <div>
<div <div
class="css-dev-only-do-not-override-wwtqkl ant-app" class="css-dev-only-do-not-override-11aiz3o ant-app"
style="height: 100%;" style="height: 100%;"
> >
<div <div
@ -54,7 +54,7 @@ describe('CollectionSelect', () => {
role="button" role="button"
> >
<div <div
class="css-1yh5po ant-formily-item ant-formily-item-layout-horizontal ant-formily-item-feedback-layout-loose ant-formily-item-label-align-right ant-formily-item-control-align-left css-dev-only-do-not-override-wwtqkl" class="css-1yh5po ant-formily-item ant-formily-item-layout-horizontal ant-formily-item-feedback-layout-loose ant-formily-item-label-align-right ant-formily-item-control-align-left css-dev-only-do-not-override-11aiz3o"
> >
<div <div
class="ant-formily-item-label" class="ant-formily-item-label"
@ -84,7 +84,7 @@ describe('CollectionSelect', () => {
class="ant-formily-item-control-content-component" class="ant-formily-item-control-content-component"
> >
<div <div
class="ant-select css-dev-only-do-not-override-wwtqkl ant-select-focused ant-select-single ant-select-show-arrow ant-select-show-search" class="ant-select css-dev-only-do-not-override-11aiz3o ant-select-focused ant-select-single ant-select-show-arrow ant-select-show-search"
data-testid="select-collection" data-testid="select-collection"
role="button" role="button"
> >
@ -182,7 +182,7 @@ describe('CollectionSelect', () => {
expect(container).toMatchInlineSnapshot(` expect(container).toMatchInlineSnapshot(`
<div> <div>
<div <div
class="css-dev-only-do-not-override-wwtqkl ant-app" class="css-dev-only-do-not-override-11aiz3o ant-app"
style="height: 100%;" style="height: 100%;"
> >
<div <div
@ -191,7 +191,7 @@ describe('CollectionSelect', () => {
role="button" role="button"
> >
<div <div
class="css-1yh5po ant-formily-item ant-formily-item-layout-horizontal ant-formily-item-feedback-layout-loose ant-formily-item-label-align-right ant-formily-item-control-align-left css-dev-only-do-not-override-wwtqkl" class="css-1yh5po ant-formily-item ant-formily-item-layout-horizontal ant-formily-item-feedback-layout-loose ant-formily-item-label-align-right ant-formily-item-control-align-left css-dev-only-do-not-override-11aiz3o"
> >
<div <div
class="ant-formily-item-label" class="ant-formily-item-label"
@ -222,7 +222,7 @@ describe('CollectionSelect', () => {
> >
<div> <div>
<span <span
class="ant-tag css-dev-only-do-not-override-wwtqkl" class="ant-tag css-dev-only-do-not-override-11aiz3o"
> >
Users Users
</span> </span>

View File

@ -26,7 +26,7 @@ describe('ColorPicker', () => {
expect(container).toMatchInlineSnapshot(` expect(container).toMatchInlineSnapshot(`
<div> <div>
<div <div
class="css-dev-only-do-not-override-wwtqkl ant-app" class="css-dev-only-do-not-override-11aiz3o ant-app"
style="height: 100%;" style="height: 100%;"
> >
<div <div
@ -35,7 +35,7 @@ describe('ColorPicker', () => {
style="display: inline-block;" style="display: inline-block;"
> >
<div <div
class="ant-color-picker-trigger css-dev-only-do-not-override-wwtqkl" class="ant-color-picker-trigger css-dev-only-do-not-override-11aiz3o"
> >
<div <div
class="ant-color-picker-color-block" class="ant-color-picker-color-block"
@ -90,7 +90,7 @@ describe('ColorPicker', () => {
expect(container).toMatchInlineSnapshot(` expect(container).toMatchInlineSnapshot(`
<div> <div>
<div <div
class="css-dev-only-do-not-override-wwtqkl ant-app" class="css-dev-only-do-not-override-11aiz3o ant-app"
style="height: 100%;" style="height: 100%;"
> >
<div <div
@ -99,7 +99,7 @@ describe('ColorPicker', () => {
role="button" role="button"
> >
<div <div
class="ant-color-picker-trigger ant-color-picker-sm css-dev-only-do-not-override-wwtqkl ant-color-picker-trigger-disabled" class="ant-color-picker-trigger ant-color-picker-sm css-dev-only-do-not-override-11aiz3o ant-color-picker-trigger-disabled"
> >
<div <div
class="ant-color-picker-color-block" class="ant-color-picker-color-block"

View File

@ -21,12 +21,12 @@ describe('Pagination', () => {
expect(container).toMatchInlineSnapshot(` expect(container).toMatchInlineSnapshot(`
<div> <div>
<div <div
class="css-dev-only-do-not-override-wwtqkl ant-app" class="css-dev-only-do-not-override-11aiz3o ant-app"
style="height: 100%;" style="height: 100%;"
> >
<div> <div>
<ul <ul
class="ant-pagination css-dev-only-do-not-override-wwtqkl" class="ant-pagination css-dev-only-do-not-override-11aiz3o"
> >
<li <li
aria-disabled="true" aria-disabled="true"
@ -131,7 +131,7 @@ describe('Pagination', () => {
expect(container).toMatchInlineSnapshot(` expect(container).toMatchInlineSnapshot(`
<div> <div>
<div <div
class="css-dev-only-do-not-override-wwtqkl ant-app" class="css-dev-only-do-not-override-11aiz3o ant-app"
style="height: 100%;" style="height: 100%;"
/> />
</div> </div>

View File

@ -20,11 +20,11 @@ describe('UnixTimestamp', () => {
expect(container).toMatchInlineSnapshot(` expect(container).toMatchInlineSnapshot(`
<div> <div>
<div <div
class="css-dev-only-do-not-override-wwtqkl ant-app" class="css-dev-only-do-not-override-11aiz3o ant-app"
style="height: 100%;" style="height: 100%;"
> >
<div <div
class="ant-picker css-dev-only-do-not-override-wwtqkl" class="ant-picker css-dev-only-do-not-override-11aiz3o"
> >
<div <div
class="ant-picker-input" class="ant-picker-input"
@ -77,7 +77,7 @@ describe('UnixTimestamp', () => {
expect(container).toMatchInlineSnapshot(` expect(container).toMatchInlineSnapshot(`
<div> <div>
<div <div
class="css-dev-only-do-not-override-wwtqkl ant-app" class="css-dev-only-do-not-override-11aiz3o ant-app"
style="height: 100%;" style="height: 100%;"
> >
<div <div

View File

@ -7,7 +7,9 @@
* For more information, please refer to: https://www.nocobase.com/agreement. * For more information, please refer to: https://www.nocobase.com/agreement.
*/ */
import { useState, useEffect } from 'react'; import { useState, useEffect, useCallback } from 'react';
import { uid } from '@formily/shared';
import { Form, onFormValuesChange } from '@formily/core';
import { useVariables, useLocalVariables } from '../../variables'; import { useVariables, useLocalVariables } from '../../variables';
import { useFieldSchema } from '@formily/react'; import { useFieldSchema } from '@formily/react';
import { LinkageRuleCategory, LinkageRuleDataKeyMap } from './type'; import { LinkageRuleCategory, LinkageRuleDataKeyMap } from './type';
@ -18,11 +20,13 @@ export function useSatisfiedActionValues({
category = 'default', category = 'default',
rules, rules,
schema, schema,
form,
}: { }: {
category: `${LinkageRuleCategory}`; category: `${LinkageRuleCategory}`;
formValues: Record<string, any>; formValues: Record<string, any>;
rules?: any; rules?: any;
schema?: any; schema?: any;
form?: Form;
}) { }) {
const [valueMap, setValueMap] = useState({}); const [valueMap, setValueMap] = useState({});
const fieldSchema = useFieldSchema(); const fieldSchema = useFieldSchema();
@ -30,8 +34,7 @@ export function useSatisfiedActionValues({
const localVariables = useLocalVariables({ currentForm: { values: formValues } as any }); const localVariables = useLocalVariables({ currentForm: { values: formValues } as any });
const localSchema = schema ?? fieldSchema; const localSchema = schema ?? fieldSchema;
const linkageRules = rules ?? localSchema[LinkageRuleDataKeyMap[category]]; const linkageRules = rules ?? localSchema[LinkageRuleDataKeyMap[category]];
const compute = useCallback(() => {
useEffect(() => {
if (linkageRules && formValues) { if (linkageRules && formValues) {
getSatisfiedValueMap({ rules: linkageRules, variables, localVariables }) getSatisfiedValueMap({ rules: linkageRules, variables, localVariables })
.then((valueMap) => { .then((valueMap) => {
@ -43,6 +46,22 @@ export function useSatisfiedActionValues({
throw new Error(err.message); throw new Error(err.message);
}); });
} }
}, [variables, localVariables, formValues, linkageRules]); }, [variables, localVariables, linkageRules, formValues]);
useEffect(() => {
compute();
}, [compute]);
useEffect(() => {
if (form) {
const id = uid();
form.addEffects(id, () => {
onFormValuesChange(() => {
compute();
});
});
return () => {
form.removeEffects(id);
};
}
}, [form, compute]);
return { valueMap }; return { valueMap };
} }

View File

@ -17,7 +17,7 @@
"@formily/react": "2.x", "@formily/react": "2.x",
"@formily/shared": "2.x", "@formily/shared": "2.x",
"antd": "5.x", "antd": "5.x",
"antd-style": "3.4.5", "antd-style": "3.7.1",
"cron-parser": "4.4.0", "cron-parser": "4.4.0",
"dayjs": "^1.11.8", "dayjs": "^1.11.8",
"lodash": "^4.17.21", "lodash": "^4.17.21",

View File

@ -31,7 +31,6 @@ class PluginCollectionTreeServer extends Plugin {
if (!condition(collection.options)) { if (!condition(collection.options)) {
return; return;
} }
const tk = collection.filterTargetKey as string;
const name = `${dataSource.name}_${collection.name}_path`; const name = `${dataSource.name}_${collection.name}_path`;
const parentForeignKey = collection.treeParentField?.foreignKey || 'parentId'; const parentForeignKey = collection.treeParentField?.foreignKey || 'parentId';
@ -51,8 +50,9 @@ class PluginCollectionTreeServer extends Plugin {
//afterCreate //afterCreate
this.db.on(`${collection.name}.afterCreate`, async (model: Model, options) => { this.db.on(`${collection.name}.afterCreate`, async (model: Model, options) => {
const { transaction } = options; const { transaction } = options;
const tk = collection.filterTargetKey as string;
let path = `/${model.get(tk)}`; let path = `/${model.get(tk)}`;
path = await this.getTreePath(model, path, collection, tk, name, transaction); path = await this.getTreePath(model, path, collection, name, transaction);
const rootPk = path.split('/')[1]; const rootPk = path.split('/')[1];
await this.app.db.getRepository(name).create({ await this.app.db.getRepository(name).create({
values: { values: {
@ -66,16 +66,18 @@ class PluginCollectionTreeServer extends Plugin {
//afterUpdate //afterUpdate
this.db.on(`${collection.name}.afterUpdate`, async (model: Model, options) => { this.db.on(`${collection.name}.afterUpdate`, async (model: Model, options) => {
const tk = collection.filterTargetKey;
// only update parentId and filterTargetKey // only update parentId and filterTargetKey
if (!(model._changed.has(tk) || model._changed.has(parentForeignKey))) { if (!(model._changed.has(tk) || model._changed.has(parentForeignKey))) {
return; return;
} }
const { transaction } = options; const { transaction } = options;
await this.updateTreePath(model, collection, tk, name, transaction); await this.updateTreePath(model, collection, name, transaction);
}); });
// after remove // after remove
this.db.on(`${collection.name}.afterBulkUpdate`, async (options) => { this.db.on(`${collection.name}.afterBulkUpdate`, async (options) => {
const tk = collection.filterTargetKey as string;
if (!(options.where && options.where[tk])) { if (!(options.where && options.where[tk])) {
return; return;
} }
@ -86,12 +88,13 @@ class PluginCollectionTreeServer extends Plugin {
transaction: options.transaction, transaction: options.transaction,
}); });
for (const model of instances) { for (const model of instances) {
await this.updateTreePath(model, collection, tk, name, options.transaction); await this.updateTreePath(model, collection, name, options.transaction);
} }
}); });
//afterDestroy //afterDestroy
this.db.on(`${collection.name}.afterDestroy`, async (model: Model, options: DestroyOptions) => { this.db.on(`${collection.name}.afterDestroy`, async (model: Model, options: DestroyOptions) => {
const tk = collection.filterTargetKey as string;
await this.app.db.getRepository(name).destroy({ await this.app.db.getRepository(name).destroy({
filter: { filter: {
nodePk: model.get(tk), nodePk: model.get(tk),
@ -139,10 +142,10 @@ class PluginCollectionTreeServer extends Plugin {
model: Model, model: Model,
path: string, path: string,
collection: Collection, collection: Collection,
tk: string,
pathCollectionName: string, pathCollectionName: string,
transaction?: Transaction, transaction?: Transaction,
) { ) {
const tk = collection.filterTargetKey as string;
const parentForeignKey = collection.treeParentField?.foreignKey || 'parentId'; const parentForeignKey = collection.treeParentField?.foreignKey || 'parentId';
if (model.get(parentForeignKey) && model.get(parentForeignKey) !== null) { if (model.get(parentForeignKey) && model.get(parentForeignKey) !== null) {
const parent = await this.app.db.getRepository(collection.name).findOne({ const parent = await this.app.db.getRepository(collection.name).findOne({
@ -164,7 +167,7 @@ class PluginCollectionTreeServer extends Plugin {
}); });
const parentPath = lodash.get(parentPathData, 'path', null); const parentPath = lodash.get(parentPathData, 'path', null);
if (parentPath == null) { if (parentPath == null) {
path = await this.getTreePath(parent, path, collection, tk, pathCollectionName, transaction); path = await this.getTreePath(parent, path, collection, pathCollectionName, transaction);
} else { } else {
path = `${parentPath}/${model.get(tk)}`; path = `${parentPath}/${model.get(tk)}`;
} }
@ -177,12 +180,12 @@ class PluginCollectionTreeServer extends Plugin {
private async updateTreePath( private async updateTreePath(
model: Model, model: Model,
collection: Collection, collection: Collection,
tk: string,
pathCollectionName: string, pathCollectionName: string,
transaction: Transaction, transaction: Transaction,
) { ) {
const tk = collection.filterTargetKey as string;
let path = `/${model.get(tk)}`; let path = `/${model.get(tk)}`;
path = await this.getTreePath(model, path, collection, tk, pathCollectionName, transaction); path = await this.getTreePath(model, path, collection, pathCollectionName, transaction);
const collectionTreePath = this.db.getCollection(pathCollectionName); const collectionTreePath = this.db.getCollection(pathCollectionName);
const nodePkColumnName = collectionTreePath.getField('nodePk').columnName(); const nodePkColumnName = collectionTreePath.getField('nodePk').columnName();
const pathData = await this.app.db.getRepository(pathCollectionName).findOne({ const pathData = await this.app.db.getRepository(pathCollectionName).findOne({

View File

@ -10,7 +10,7 @@
"homepage": "https://docs.nocobase.com/handbook/block-gantt", "homepage": "https://docs.nocobase.com/handbook/block-gantt",
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/block-gantt", "homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/block-gantt",
"devDependencies": { "devDependencies": {
"antd-style": "3.4.5" "antd-style": "3.7.1"
}, },
"peerDependencies": { "peerDependencies": {
"@nocobase/client": "1.x", "@nocobase/client": "1.x",

1305
yarn.lock

File diff suppressed because it is too large Load Diff