mirror of
https://github.com/nocobase/nocobase.git
synced 2026-09-01 14:57:36 +08:00
Merge branch 'main' into next
This commit is contained in:
+57
-4
@@ -8,23 +8,76 @@
|
||||
*/
|
||||
|
||||
import type { ButtonProps } from 'antd/es/button';
|
||||
import { reaction } from '@formily/reactive';
|
||||
import { tExpr } from '@nocobase/flow-engine';
|
||||
import { FilterFormActionModel } from './FilterFormActionModel';
|
||||
|
||||
type FilterFormBlockState = {
|
||||
autoTriggerFilter: boolean;
|
||||
};
|
||||
|
||||
const mountedSubmitActions = new WeakSet<object>();
|
||||
const visibleSubmitActionsByBlock = new WeakMap<FilterFormBlockState, Set<object>>();
|
||||
const hiddenReactionDisposers = new WeakMap<object, () => void>();
|
||||
|
||||
const syncAutoTriggerFilter = (blockModel: FilterFormBlockState, lifecycleAction: object & { hidden?: boolean }) => {
|
||||
let visibleSubmitActions = visibleSubmitActionsByBlock.get(blockModel);
|
||||
|
||||
if (mountedSubmitActions.has(lifecycleAction) && !lifecycleAction.hidden) {
|
||||
if (!visibleSubmitActions) {
|
||||
visibleSubmitActions = new Set<object>();
|
||||
visibleSubmitActionsByBlock.set(blockModel, visibleSubmitActions);
|
||||
}
|
||||
visibleSubmitActions.add(lifecycleAction);
|
||||
} else {
|
||||
visibleSubmitActions?.delete(lifecycleAction);
|
||||
}
|
||||
|
||||
blockModel.autoTriggerFilter = Boolean(!visibleSubmitActions?.size);
|
||||
if (!visibleSubmitActions?.size) {
|
||||
visibleSubmitActionsByBlock.delete(blockModel);
|
||||
}
|
||||
};
|
||||
|
||||
export class FilterFormSubmitActionModel extends FilterFormActionModel {
|
||||
defaultProps: ButtonProps = {
|
||||
title: tExpr('Filter'),
|
||||
type: 'primary',
|
||||
};
|
||||
|
||||
onInit(options): void {
|
||||
super.onInit(options);
|
||||
this.context.blockModel.autoTriggerFilter = false;
|
||||
private getLifecycleAction(): object & { hidden?: boolean } {
|
||||
return this.context.model || this;
|
||||
}
|
||||
|
||||
private syncAutoTriggerFilter(): void {
|
||||
const blockModel = this.context.blockModel as FilterFormBlockState;
|
||||
const lifecycleAction = this.getLifecycleAction();
|
||||
syncAutoTriggerFilter(blockModel, lifecycleAction);
|
||||
}
|
||||
|
||||
onMount(): void {
|
||||
super.onMount();
|
||||
const blockModel = this.context.blockModel as FilterFormBlockState;
|
||||
const lifecycleAction = this.getLifecycleAction();
|
||||
mountedSubmitActions.add(lifecycleAction);
|
||||
hiddenReactionDisposers.get(lifecycleAction)?.();
|
||||
hiddenReactionDisposers.set(
|
||||
lifecycleAction,
|
||||
reaction(
|
||||
() => lifecycleAction.hidden,
|
||||
() => syncAutoTriggerFilter(blockModel, lifecycleAction),
|
||||
),
|
||||
);
|
||||
this.syncAutoTriggerFilter();
|
||||
}
|
||||
|
||||
onUnmount(): void {
|
||||
super.onUnmount();
|
||||
this.context.blockModel.autoTriggerFilter = true;
|
||||
const lifecycleAction = this.getLifecycleAction();
|
||||
hiddenReactionDisposers.get(lifecycleAction)?.();
|
||||
hiddenReactionDisposers.delete(lifecycleAction);
|
||||
mountedSubmitActions.delete(lifecycleAction);
|
||||
this.syncAutoTriggerFilter();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* This file is part of the NocoBase (R) project.
|
||||
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
||||
* Authors: NocoBase Team.
|
||||
*
|
||||
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||
*/
|
||||
|
||||
import { define, observable } from '@formily/reactive';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { FilterFormSubmitActionModel } from '../FilterFormSubmitActionModel';
|
||||
|
||||
describe('FilterFormSubmitActionModel lifecycle', () => {
|
||||
const createAction = (blockModel: { autoTriggerFilter: boolean }, hidden = false, lifecycleAction?: object) => {
|
||||
const action = Object.create(FilterFormSubmitActionModel.prototype) as FilterFormSubmitActionModel;
|
||||
|
||||
Object.defineProperty(action, 'props', {
|
||||
value: {},
|
||||
});
|
||||
Object.defineProperty(action, 'context', {
|
||||
value: { blockModel, model: lifecycleAction || action, defineProperty: () => undefined },
|
||||
});
|
||||
action.hidden = hidden;
|
||||
define(action, {
|
||||
hidden: observable,
|
||||
});
|
||||
action.onInit({});
|
||||
|
||||
return action;
|
||||
};
|
||||
|
||||
it('keeps automatic filtering disabled when the submit action remounts', () => {
|
||||
const blockModel = { autoTriggerFilter: true };
|
||||
const action = createAction(blockModel);
|
||||
|
||||
action.onMount();
|
||||
expect(blockModel.autoTriggerFilter).toBe(false);
|
||||
|
||||
action.onUnmount();
|
||||
expect(blockModel.autoTriggerFilter).toBe(true);
|
||||
|
||||
action.onMount();
|
||||
expect(blockModel.autoTriggerFilter).toBe(false);
|
||||
});
|
||||
|
||||
it('keeps automatic filtering disabled until every mounted submit action unmounts', () => {
|
||||
const blockModel = { autoTriggerFilter: true };
|
||||
const firstAction = createAction(blockModel);
|
||||
const secondAction = createAction(blockModel);
|
||||
|
||||
firstAction.onMount();
|
||||
secondAction.onMount();
|
||||
firstAction.onUnmount();
|
||||
expect(blockModel.autoTriggerFilter).toBe(false);
|
||||
|
||||
secondAction.onUnmount();
|
||||
expect(blockModel.autoTriggerFilter).toBe(true);
|
||||
});
|
||||
|
||||
it('only disables automatic filtering while a visible submit action is mounted', () => {
|
||||
const blockModel = { autoTriggerFilter: true };
|
||||
const action = createAction(blockModel, true);
|
||||
|
||||
action.onMount();
|
||||
expect(blockModel.autoTriggerFilter).toBe(true);
|
||||
|
||||
action.hidden = false;
|
||||
expect(blockModel.autoTriggerFilter).toBe(false);
|
||||
|
||||
action.hidden = true;
|
||||
expect(blockModel.autoTriggerFilter).toBe(true);
|
||||
});
|
||||
|
||||
it('tracks fork lifecycles independently when submit actions share the same uid', () => {
|
||||
const blockModel = { autoTriggerFilter: true };
|
||||
const firstFork = {};
|
||||
const secondFork = {};
|
||||
const firstAction = createAction(blockModel, false, firstFork);
|
||||
const secondAction = createAction(blockModel, false, secondFork);
|
||||
|
||||
firstAction.onMount();
|
||||
secondAction.onMount();
|
||||
firstAction.onUnmount();
|
||||
expect(blockModel.autoTriggerFilter).toBe(false);
|
||||
|
||||
secondAction.onUnmount();
|
||||
expect(blockModel.autoTriggerFilter).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user