@nocobase/flow-engine 2.4.0-alpha.8 → 2.4.0-alpha.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.
@@ -360,7 +360,9 @@ function createPopupMeta(ctx, anchorView) {
360
360
  const view = getPopupView(ctx, anchorView);
361
361
  const inputArgs = view == null ? void 0 : view.inputArgs;
362
362
  const srcId = inputArgs == null ? void 0 : inputArgs.sourceId;
363
- let assoc = inputArgs == null ? void 0 : inputArgs.associationName;
363
+ const hasSourceId = srcId != null && srcId !== "";
364
+ const pendingSourceAssoc = !hasSourceId && typeof (inputArgs == null ? void 0 : inputArgs.sourceAssociationName) === "string" ? inputArgs.sourceAssociationName : void 0;
365
+ let assoc = (inputArgs == null ? void 0 : inputArgs.associationName) || pendingSourceAssoc;
364
366
  let dsKey = (inputArgs == null ? void 0 : inputArgs.dataSourceKey) || "main";
365
367
  if (!assoc || typeof assoc !== "string" || !assoc.includes(".")) {
366
368
  const stack = getViewStack(view);
@@ -376,7 +378,7 @@ function createPopupMeta(ctx, anchorView) {
376
378
  dsKey = (p == null ? void 0 : p.dataSourceKey) || dsKey;
377
379
  }
378
380
  }
379
- if (srcId != null && srcId !== "" && assoc && typeof assoc === "string") {
381
+ if ((hasSourceId || pendingSourceAssoc) && assoc && typeof assoc === "string") {
380
382
  const parentCollectionName = String(assoc).includes(".") ? String(assoc).split(".")[0] : void 0;
381
383
  if (parentCollectionName) {
382
384
  const parentCollectionAccessor = /* @__PURE__ */ __name(() => {
@@ -388,11 +390,15 @@ function createPopupMeta(ctx, anchorView) {
388
390
  return null;
389
391
  }
390
392
  }, "parentCollectionAccessor");
391
- const srcMeta = await (0, import_variablesParams.buildRecordMeta)(parentCollectionAccessor, t("Current popup parent record"), () => ({
392
- collection: parentCollectionName,
393
- dataSourceKey: dsKey,
394
- filterByTk: srcId
395
- }));
393
+ const srcMeta = await (0, import_variablesParams.buildRecordMeta)(
394
+ parentCollectionAccessor,
395
+ t("Current popup parent record"),
396
+ () => hasSourceId ? {
397
+ collection: parentCollectionName,
398
+ dataSourceKey: dsKey,
399
+ filterByTk: srcId
400
+ } : void 0
401
+ );
396
402
  if (srcMeta) {
397
403
  props.sourceRecord = srcMeta;
398
404
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocobase/flow-engine",
3
- "version": "2.4.0-alpha.8",
3
+ "version": "2.4.0-alpha.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.4.0-alpha.8",
12
- "@nocobase/shared": "2.4.0-alpha.8",
11
+ "@nocobase/sdk": "2.4.0-alpha.9",
12
+ "@nocobase/shared": "2.4.0-alpha.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": "e8ec2bff07f4b405e08f984c9e92b44491bde462"
40
+ "gitHead": "d383bdb224c62d1ba21c3dffd682165f3385a11b"
41
41
  }
@@ -8,7 +8,7 @@
8
8
  */
9
9
 
10
10
  import { describe, it, expect, vi } from 'vitest';
11
- import { FlowContext } from '../flowContext';
11
+ import { FlowContext, type PropertyMeta } from '../flowContext';
12
12
  import { FlowEngine } from '../flowEngine';
13
13
  import type { FlowView } from '../views/FlowView';
14
14
  import { buildPopupRuntime, createPopupMeta, registerPopupVariable } from '../views/createViewMeta';
@@ -397,4 +397,86 @@ describe('createPopupMeta - popup variables', () => {
397
397
 
398
398
  expect(ctx.getPropertyOptions('popup')?.resolveOnServer?.('sourceRecord.department.title')).toBe(true);
399
399
  });
400
+
401
+ describe('popup sourceRecord meta for quick create popups', () => {
402
+ function makeCtxWithUsers() {
403
+ const engine = new FlowEngine();
404
+ const ds = engine.context.dataSourceManager.getDataSource('main');
405
+ ds.addCollection({
406
+ name: 'orgs',
407
+ filterTargetKey: 'id',
408
+ fields: [{ name: 'id', type: 'integer', interface: 'number' }],
409
+ });
410
+ ds.addCollection({
411
+ name: 'users',
412
+ filterTargetKey: 'id',
413
+ fields: [
414
+ { name: 'id', type: 'integer', interface: 'number' },
415
+ { name: 'nickname', type: 'string', interface: 'input' },
416
+ { name: 'orgs', type: 'hasMany', target: 'orgs', interface: 'o2m' },
417
+ ],
418
+ });
419
+ return engine.context;
420
+ }
421
+
422
+ function makeQuickCreatePopupView(inputArgs: Record<string, unknown>): FlowView {
423
+ return {
424
+ type: 'drawer',
425
+ inputArgs: {
426
+ openerUids: ['approval-form-uid'],
427
+ scene: 'create',
428
+ dataSourceKey: 'main',
429
+ collectionName: 'orgs',
430
+ ...inputArgs,
431
+ },
432
+ Header: null,
433
+ Footer: null,
434
+ close: () => void 0,
435
+ update: () => void 0,
436
+ } as unknown as FlowView;
437
+ }
438
+
439
+ async function getPopupProps(ctx: FlowContext, view: FlowView) {
440
+ const meta = await createPopupMeta(ctx, view)();
441
+ const props = typeof meta?.properties === 'function' ? await meta.properties() : meta?.properties;
442
+ return { meta, props: props || {} };
443
+ }
444
+
445
+ it('exposes the parent record meta from sourceAssociationName before the parent record has a primary key', async () => {
446
+ const ctx = makeCtxWithUsers();
447
+ const view = makeQuickCreatePopupView({ sourceAssociationName: 'users.orgs' });
448
+
449
+ const { meta, props } = await getPopupProps(ctx, view);
450
+ const sourceRecordMeta = props.sourceRecord as PropertyMeta;
451
+ expect(sourceRecordMeta?.title).toBe('Current popup parent record');
452
+ const fields =
453
+ typeof sourceRecordMeta.properties === 'function'
454
+ ? await sourceRecordMeta.properties()
455
+ : sourceRecordMeta.properties;
456
+ expect(fields).toHaveProperty('nickname');
457
+
458
+ // 父记录尚无主键时仅用于配置变量,不应生成服务端取值参数
459
+ const vars = (await meta?.buildVariablesParams?.(ctx)) as { sourceRecord?: unknown } | undefined;
460
+ expect(vars?.sourceRecord).toBeUndefined();
461
+ });
462
+
463
+ it('does not expose the parent record meta without sourceId or sourceAssociationName', async () => {
464
+ const ctx = makeCtxWithUsers();
465
+ const view = makeQuickCreatePopupView({});
466
+
467
+ const { props } = await getPopupProps(ctx, view);
468
+ expect(props.sourceRecord).toBeUndefined();
469
+ });
470
+
471
+ it('keeps resolving the parent record by sourceId once the parent record is persisted', async () => {
472
+ const ctx = makeCtxWithUsers();
473
+ const view = makeQuickCreatePopupView({ associationName: 'users.orgs', sourceId: 7 });
474
+
475
+ const { meta, props } = await getPopupProps(ctx, view);
476
+ expect((props.sourceRecord as PropertyMeta)?.title).toBe('Current popup parent record');
477
+
478
+ const vars = (await meta?.buildVariablesParams?.(ctx)) as { sourceRecord?: unknown } | undefined;
479
+ expect(vars?.sourceRecord).toEqual({ collection: 'users', dataSourceKey: 'main', filterByTk: 7 });
480
+ });
481
+ });
400
482
  });
@@ -390,7 +390,13 @@ export function createPopupMeta(ctx: FlowContext, anchorView?: FlowView): Proper
390
390
  const view = getPopupView(ctx, anchorView);
391
391
  const inputArgs = view?.inputArgs;
392
392
  const srcId = inputArgs?.sourceId;
393
- let assoc: string | undefined = inputArgs?.associationName;
393
+ const hasSourceId = srcId != null && srcId !== '';
394
+ // 上级记录暂无主键时(如审批配置态表单里的快速创建弹窗),只会传 sourceAssociationName:仍展示变量结构,取值依赖运行时的 sourceId
395
+ const pendingSourceAssoc =
396
+ !hasSourceId && typeof inputArgs?.sourceAssociationName === 'string'
397
+ ? inputArgs.sourceAssociationName
398
+ : undefined;
399
+ let assoc: string | undefined = inputArgs?.associationName || pendingSourceAssoc;
394
400
  let dsKey: string = inputArgs?.dataSourceKey || 'main';
395
401
 
396
402
  // 兜底:若 associationName 缺失或不含“.”,尝试从当前视图模型的 openView 参数推断
@@ -409,7 +415,7 @@ export function createPopupMeta(ctx: FlowContext, anchorView?: FlowView): Proper
409
415
  }
410
416
  }
411
417
 
412
- if (srcId != null && srcId !== '' && assoc && typeof assoc === 'string') {
418
+ if ((hasSourceId || pendingSourceAssoc) && assoc && typeof assoc === 'string') {
413
419
  const parentCollectionName = String(assoc).includes('.') ? String(assoc).split('.')[0] : undefined;
414
420
  if (parentCollectionName) {
415
421
  const parentCollectionAccessor = () => {
@@ -420,11 +426,15 @@ export function createPopupMeta(ctx: FlowContext, anchorView?: FlowView): Proper
420
426
  return null;
421
427
  }
422
428
  };
423
- const srcMeta = await buildRecordMeta(parentCollectionAccessor, t('Current popup parent record'), () => ({
424
- collection: parentCollectionName,
425
- dataSourceKey: dsKey,
426
- filterByTk: srcId,
427
- }));
429
+ const srcMeta = await buildRecordMeta(parentCollectionAccessor, t('Current popup parent record'), () =>
430
+ hasSourceId
431
+ ? {
432
+ collection: parentCollectionName,
433
+ dataSourceKey: dsKey,
434
+ filterByTk: srcId,
435
+ }
436
+ : undefined,
437
+ );
428
438
  if (srcMeta) {
429
439
  props.sourceRecord = srcMeta;
430
440
  }