@nocobase/flow-engine 2.1.7 → 2.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2294,6 +2294,36 @@ const _BaseFlowModelContext = class _BaseFlowModelContext extends BaseFlowEngine
2294
2294
  };
2295
2295
  __name(_BaseFlowModelContext, "BaseFlowModelContext");
2296
2296
  let BaseFlowModelContext = _BaseFlowModelContext;
2297
+ const OPEN_VIEW_INHERITED_INPUT_ARG_KEYS = [
2298
+ "dataSourceKey",
2299
+ "collectionName",
2300
+ "associationName",
2301
+ "filterByTk",
2302
+ "sourceId",
2303
+ "tabUid"
2304
+ ];
2305
+ function pickDefinedKeys(source, keys) {
2306
+ const res = {};
2307
+ for (const key of keys) {
2308
+ if (typeof (source == null ? void 0 : source[key]) !== "undefined") {
2309
+ res[key] = source[key];
2310
+ }
2311
+ }
2312
+ return res;
2313
+ }
2314
+ __name(pickDefinedKeys, "pickDefinedKeys");
2315
+ function pickDefinedOpenViewInputArgs(source) {
2316
+ return pickDefinedKeys(source, OPEN_VIEW_INHERITED_INPUT_ARG_KEYS);
2317
+ }
2318
+ __name(pickDefinedOpenViewInputArgs, "pickDefinedOpenViewInputArgs");
2319
+ function applyDefinedDefaults(target, defaults) {
2320
+ for (const [key, value] of Object.entries(defaults)) {
2321
+ if (typeof target[key] === "undefined") {
2322
+ target[key] = value;
2323
+ }
2324
+ }
2325
+ }
2326
+ __name(applyDefinedDefaults, "applyDefinedDefaults");
2297
2327
  const _FlowEngineContext = class _FlowEngineContext extends BaseFlowEngineContext {
2298
2328
  // public dataSourceManager: DataSourceManager;
2299
2329
  constructor(engine) {
@@ -2791,23 +2821,19 @@ const _FlowModelContext = class _FlowModelContext extends BaseFlowModelContext {
2791
2821
  }
2792
2822
  });
2793
2823
  this.defineMethod("openView", async function(uid, options) {
2794
- var _a, _b, _c, _d, _e;
2795
- const opts = { ...options };
2824
+ var _a, _b, _c, _d;
2825
+ const inheritedInputArgs = {
2826
+ ...typeof ((_a = this.model) == null ? void 0 : _a["getInputArgs"]) === "function" ? pickDefinedOpenViewInputArgs(this.model["getInputArgs"]()) : {},
2827
+ ...pickDefinedOpenViewInputArgs(this.inputArgs)
2828
+ };
2829
+ const opts = { ...options || {} };
2830
+ applyDefinedDefaults(opts, inheritedInputArgs);
2796
2831
  if (opts.defineProperties || opts.defineMethods) {
2797
2832
  opts.navigation = false;
2798
2833
  }
2799
2834
  let model2 = null;
2800
2835
  model2 = await this.engine.loadModel({ uid });
2801
2836
  if (!model2) {
2802
- const pickDefined = /* @__PURE__ */ __name((src, keys) => {
2803
- const res = {};
2804
- for (const k of keys) {
2805
- if (typeof (src == null ? void 0 : src[k]) !== "undefined") {
2806
- res[k] = src[k];
2807
- }
2808
- }
2809
- return res;
2810
- }, "pickDefined");
2811
2837
  model2 = this.engine.createModel({
2812
2838
  uid,
2813
2839
  // 注意: 新建的 model 应该使用 ${parentModel.uid}-xxx 形式的 uid
@@ -2819,7 +2845,7 @@ const _FlowModelContext = class _FlowModelContext extends BaseFlowModelContext {
2819
2845
  popupSettings: {
2820
2846
  openView: {
2821
2847
  // 仅在创建时持久化一份默认配置;运行时以本次 opts 为准,避免多个 opener 互相覆盖。
2822
- ...pickDefined(opts, ["dataSourceKey", "collectionName", "associationName", "mode", "size"])
2848
+ ...pickDefinedKeys(opts, ["dataSourceKey", "collectionName", "associationName", "mode", "size"])
2823
2849
  }
2824
2850
  }
2825
2851
  }
@@ -2827,12 +2853,10 @@ const _FlowModelContext = class _FlowModelContext extends BaseFlowModelContext {
2827
2853
  await model2.save();
2828
2854
  }
2829
2855
  model2.setParent(this.model);
2830
- const viewUid = (opts == null ? void 0 : opts.routeViewUid) ?? (opts == null ? void 0 : opts.viewUid) ?? (((_b = (_a = model2.stepParams) == null ? void 0 : _a.popupSettings) == null ? void 0 : _b.openView) ? model2.uid : this.model.uid);
2856
+ const viewUid = (opts == null ? void 0 : opts.routeViewUid) ?? (opts == null ? void 0 : opts.viewUid) ?? (((_c = (_b = model2.stepParams) == null ? void 0 : _b.popupSettings) == null ? void 0 : _c.openView) ? model2.uid : this.model.uid);
2831
2857
  const parentView = this.view;
2832
2858
  const pendingType = (opts == null ? void 0 : opts.isMobileLayout) ? "embed" : (opts == null ? void 0 : opts.mode) || "drawer";
2833
2859
  const pendingInputArgs = { ...opts, viewUid, navigation: opts.navigation };
2834
- pendingInputArgs.filterByTk = pendingInputArgs.filterByTk || ((_c = this.inputArgs) == null ? void 0 : _c.filterByTk);
2835
- pendingInputArgs.sourceId = pendingInputArgs.sourceId || ((_d = this.inputArgs) == null ? void 0 : _d.sourceId);
2836
2860
  const pendingView = {
2837
2861
  type: pendingType,
2838
2862
  inputArgs: pendingInputArgs,
@@ -2841,7 +2865,7 @@ const _FlowModelContext = class _FlowModelContext extends BaseFlowModelContext {
2841
2865
  engineCtx: this.engine.context
2842
2866
  };
2843
2867
  model2.context.defineProperty("view", { value: pendingView });
2844
- const popupFlow = (_e = model2.getFlow) == null ? void 0 : _e.call(model2, "popupSettings");
2868
+ const popupFlow = (_d = model2.getFlow) == null ? void 0 : _d.call(model2, "popupSettings");
2845
2869
  const on = popupFlow == null ? void 0 : popupFlow.on;
2846
2870
  let openEventName = "click";
2847
2871
  if (typeof on === "string" && on) {
@@ -2849,17 +2873,10 @@ const _FlowModelContext = class _FlowModelContext extends BaseFlowModelContext {
2849
2873
  } else if (on && typeof on === "object" && typeof on.eventName === "string" && on.eventName) {
2850
2874
  openEventName = on.eventName;
2851
2875
  }
2852
- await model2.dispatchEvent(
2853
- openEventName,
2854
- {
2855
- // navigation: false, // TODO: 路由模式有bug,不支持多层同样viewId的弹窗,因此这里默认先用false
2856
- // ...this.model?.['getInputArgs']?.(), // 避免部分关系字段信息丢失, 仿照 ClickableCollectionField 做法
2857
- ...opts
2858
- },
2859
- {
2860
- debounce: true
2861
- }
2862
- );
2876
+ await model2.dispatchEvent(openEventName, {
2877
+ // navigation: false, // TODO: 路由模式有bug,不支持多层同样viewId的弹窗,因此这里默认先用false
2878
+ ...opts
2879
+ });
2863
2880
  });
2864
2881
  this.defineMethod("getEvents", function() {
2865
2882
  return this.model.getEvents();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocobase/flow-engine",
3
- "version": "2.1.7",
3
+ "version": "2.1.9",
4
4
  "private": false,
5
5
  "description": "A standalone flow engine for NocoBase, managing workflows, models, and actions.",
6
6
  "main": "lib/index.js",
@@ -8,8 +8,8 @@
8
8
  "dependencies": {
9
9
  "@formily/antd-v5": "1.x",
10
10
  "@formily/reactive": "2.x",
11
- "@nocobase/sdk": "2.1.7",
12
- "@nocobase/shared": "2.1.7",
11
+ "@nocobase/sdk": "2.1.9",
12
+ "@nocobase/shared": "2.1.9",
13
13
  "ahooks": "^3.7.2",
14
14
  "axios": "^1.7.0",
15
15
  "dayjs": "^1.11.9",
@@ -37,5 +37,5 @@
37
37
  ],
38
38
  "author": "NocoBase Team",
39
39
  "license": "Apache-2.0",
40
- "gitHead": "fc3bc8bf6ef0c185a456cb5241abc4716af8c20c"
40
+ "gitHead": "2b612d81c6f6115af75ea7b279384751af869510"
41
41
  }
@@ -104,4 +104,32 @@ describe('FlowModelContext.openView - navigation enforcement', () => {
104
104
  expect(child.dispatchEvent).toHaveBeenCalledTimes(1);
105
105
  expect(child.dispatchEvent.mock.calls[0][0]).toBe('click');
106
106
  });
107
+
108
+ it('inherits current model input args when opening an external popup', async () => {
109
+ const { parent, child } = setup();
110
+ parent['getInputArgs'] = vi.fn(() => ({
111
+ filterByTk: 2,
112
+ sourceId: 10,
113
+ defaultInputKeys: ['filterByTk', 'sourceId'],
114
+ }));
115
+
116
+ await (parent.context as any).openView('child-uid', { mode: 'dialog' });
117
+
118
+ expect(child.dispatchEvent).toHaveBeenCalledTimes(1);
119
+ expect(child.dispatchEvent.mock.calls[0][1]).toMatchObject({
120
+ mode: 'dialog',
121
+ filterByTk: 2,
122
+ sourceId: 10,
123
+ });
124
+ expect(child.dispatchEvent.mock.calls[0][1]).not.toHaveProperty('defaultInputKeys');
125
+ });
126
+
127
+ it('does not debounce external popup dispatches', async () => {
128
+ const { parent, child } = setup();
129
+
130
+ await (parent.context as any).openView('child-uid', { mode: 'dialog', filterByTk: 1 });
131
+
132
+ expect(child.dispatchEvent).toHaveBeenCalledTimes(1);
133
+ expect(child.dispatchEvent.mock.calls[0][2]).toBeUndefined();
134
+ });
107
135
  });
@@ -3139,6 +3139,37 @@ class BaseFlowModelContext extends BaseFlowEngineContext {
3139
3139
  declare makeResource: <T extends FlowResource = FlowResource>(resourceType: ResourceType<T>) => T;
3140
3140
  }
3141
3141
 
3142
+ const OPEN_VIEW_INHERITED_INPUT_ARG_KEYS = [
3143
+ 'dataSourceKey',
3144
+ 'collectionName',
3145
+ 'associationName',
3146
+ 'filterByTk',
3147
+ 'sourceId',
3148
+ 'tabUid',
3149
+ ];
3150
+
3151
+ function pickDefinedKeys(source: Record<string, unknown> | null | undefined, keys: string[]) {
3152
+ const res: Record<string, unknown> = {};
3153
+ for (const key of keys) {
3154
+ if (typeof source?.[key] !== 'undefined') {
3155
+ res[key] = source[key];
3156
+ }
3157
+ }
3158
+ return res;
3159
+ }
3160
+
3161
+ function pickDefinedOpenViewInputArgs(source?: Record<string, unknown> | null) {
3162
+ return pickDefinedKeys(source, OPEN_VIEW_INHERITED_INPUT_ARG_KEYS);
3163
+ }
3164
+
3165
+ function applyDefinedDefaults(target: Record<string, unknown>, defaults: Record<string, unknown>) {
3166
+ for (const [key, value] of Object.entries(defaults)) {
3167
+ if (typeof target[key] === 'undefined') {
3168
+ target[key] = value;
3169
+ }
3170
+ }
3171
+ }
3172
+
3142
3173
  export class FlowEngineContext extends BaseFlowEngineContext {
3143
3174
  // public dataSourceManager: DataSourceManager;
3144
3175
  constructor(public engine: FlowEngine) {
@@ -3687,7 +3718,14 @@ export class FlowModelContext extends BaseFlowModelContext {
3687
3718
  },
3688
3719
  });
3689
3720
  this.defineMethod('openView', async function (uid: string, options) {
3690
- const opts = { ...options };
3721
+ const inheritedInputArgs = {
3722
+ ...(typeof this.model?.['getInputArgs'] === 'function'
3723
+ ? pickDefinedOpenViewInputArgs(this.model['getInputArgs']())
3724
+ : {}),
3725
+ ...pickDefinedOpenViewInputArgs(this.inputArgs),
3726
+ };
3727
+ const opts = { ...(options || {}) };
3728
+ applyDefinedDefaults(opts, inheritedInputArgs);
3691
3729
  // NOTE: when custom context is passed, route navigation must be disabled to avoid losing it after refresh.
3692
3730
  if (opts.defineProperties || opts.defineMethods) {
3693
3731
  opts.navigation = false; // 强制不使用路由导航, 避免刷新页面时丢失上下文
@@ -3695,15 +3733,6 @@ export class FlowModelContext extends BaseFlowModelContext {
3695
3733
  let model: FlowModel | null = null;
3696
3734
  model = await this.engine.loadModel({ uid });
3697
3735
  if (!model) {
3698
- const pickDefined = (src: Record<string, any>, keys: string[]) => {
3699
- const res: Record<string, any> = {};
3700
- for (const k of keys) {
3701
- if (typeof src?.[k] !== 'undefined') {
3702
- res[k] = src[k];
3703
- }
3704
- }
3705
- return res;
3706
- };
3707
3736
  model = this.engine.createModel({
3708
3737
  uid, // 注意: 新建的 model 应该使用 ${parentModel.uid}-xxx 形式的 uid
3709
3738
  use: 'PopupActionModel',
@@ -3714,7 +3743,7 @@ export class FlowModelContext extends BaseFlowModelContext {
3714
3743
  popupSettings: {
3715
3744
  openView: {
3716
3745
  // 仅在创建时持久化一份默认配置;运行时以本次 opts 为准,避免多个 opener 互相覆盖。
3717
- ...pickDefined(opts, ['dataSourceKey', 'collectionName', 'associationName', 'mode', 'size']),
3746
+ ...pickDefinedKeys(opts, ['dataSourceKey', 'collectionName', 'associationName', 'mode', 'size']),
3718
3747
  },
3719
3748
  },
3720
3749
  },
@@ -3734,8 +3763,6 @@ export class FlowModelContext extends BaseFlowModelContext {
3734
3763
  // 统一语义:为即将打开的外部视图定义一个 PendingView(占位视图)
3735
3764
  const pendingType = (opts?.isMobileLayout ? 'embed' : opts?.mode || 'drawer') as any;
3736
3765
  const pendingInputArgs = { ...opts, viewUid, navigation: opts.navigation };
3737
- pendingInputArgs.filterByTk = pendingInputArgs.filterByTk || this.inputArgs?.filterByTk;
3738
- pendingInputArgs.sourceId = pendingInputArgs.sourceId || this.inputArgs?.sourceId;
3739
3766
 
3740
3767
  const pendingView = {
3741
3768
  type: pendingType,
@@ -3754,17 +3781,10 @@ export class FlowModelContext extends BaseFlowModelContext {
3754
3781
  } else if (on && typeof on === 'object' && typeof (on as any).eventName === 'string' && (on as any).eventName) {
3755
3782
  openEventName = (on as any).eventName;
3756
3783
  }
3757
- await model.dispatchEvent(
3758
- openEventName,
3759
- {
3760
- // navigation: false, // TODO: 路由模式有bug,不支持多层同样viewId的弹窗,因此这里默认先用false
3761
- // ...this.model?.['getInputArgs']?.(), // 避免部分关系字段信息丢失, 仿照 ClickableCollectionField 做法
3762
- ...opts,
3763
- },
3764
- {
3765
- debounce: true,
3766
- },
3767
- );
3784
+ await model.dispatchEvent(openEventName, {
3785
+ // navigation: false, // TODO: 路由模式有bug,不支持多层同样viewId的弹窗,因此这里默认先用false
3786
+ ...opts,
3787
+ });
3768
3788
  });
3769
3789
  this.defineMethod('getEvents', function (this: BaseFlowModelContext) {
3770
3790
  return this.model.getEvents();