@nocobase/plugin-flow-engine 2.2.0-beta.7 → 2.2.0-beta.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.
- package/dist/externalVersion.js +9 -9
- package/dist/locale/en-US.json +1 -0
- package/dist/locale/index.d.ts +2 -0
- package/dist/locale/zh-CN.json +1 -0
- package/dist/node_modules/@ant-design/icons-svg/package.json +1 -1
- package/dist/node_modules/acorn/package.json +1 -1
- package/dist/node_modules/acorn-jsx/package.json +1 -1
- package/dist/node_modules/acorn-walk/package.json +1 -1
- package/dist/node_modules/ses/package.json +1 -1
- package/dist/node_modules/zod/package.json +1 -1
- package/dist/server/flow-surfaces/authoring-validation.d.ts +2 -1
- package/dist/server/flow-surfaces/authoring-validation.js +43 -18
- package/dist/server/flow-surfaces/blueprint/compile-plan.js +19 -15
- package/dist/server/flow-surfaces/blueprint/export-document.js +7 -2
- package/dist/server/flow-surfaces/blueprint/normalize-document.js +2 -1
- package/dist/server/flow-surfaces/blueprint/public-types.d.ts +1 -0
- package/dist/server/flow-surfaces/builder.js +24 -4
- package/dist/server/flow-surfaces/catalog.js +10 -1
- package/dist/server/flow-surfaces/configure-options.js +1 -0
- package/dist/server/flow-surfaces/constants.d.ts +2 -2
- package/dist/server/flow-surfaces/service.d.ts +11 -0
- package/dist/server/flow-surfaces/service.js +265 -31
- package/dist/server/flow-surfaces/types.d.ts +2 -1
- package/dist/swagger/flow-surfaces.d.ts +13 -0
- package/dist/swagger/flow-surfaces.examples.d.ts +3 -0
- package/dist/swagger/flow-surfaces.examples.js +3 -0
- package/dist/swagger/flow-surfaces.js +19 -6
- package/dist/swagger/index.d.ts +13 -0
- package/package.json +2 -2
|
@@ -690,6 +690,7 @@ function assertNoFlowSurfaceIdTitleFieldSettings(value, options = {}) {
|
|
|
690
690
|
visit(value, options.basePath || []);
|
|
691
691
|
}
|
|
692
692
|
const DEFAULT_ADMIN_UI_LAYOUT_UID = "admin-layout-model";
|
|
693
|
+
const MOBILE_UI_LAYOUT_TYPE = "mobile";
|
|
693
694
|
class FlowSurfacesService {
|
|
694
695
|
constructor(plugin) {
|
|
695
696
|
this.plugin = plugin;
|
|
@@ -923,12 +924,12 @@ class FlowSurfacesService {
|
|
|
923
924
|
transaction
|
|
924
925
|
});
|
|
925
926
|
}
|
|
926
|
-
async findMenuGroupRoutesByTitle(title, transaction) {
|
|
927
|
+
async findMenuGroupRoutesByTitle(title, transaction, layoutUid) {
|
|
927
928
|
const normalizedTitle = String(title || "").trim();
|
|
928
929
|
if (!normalizedTitle) {
|
|
929
930
|
return [];
|
|
930
931
|
}
|
|
931
|
-
|
|
932
|
+
const routes = import_lodash.default.castArray(
|
|
932
933
|
await this.db.getRepository("desktopRoutes").find({
|
|
933
934
|
filter: {
|
|
934
935
|
type: "group",
|
|
@@ -937,6 +938,18 @@ class FlowSurfacesService {
|
|
|
937
938
|
transaction
|
|
938
939
|
})
|
|
939
940
|
);
|
|
941
|
+
const layoutUidFilter = await this.resolveDesktopRouteLayoutUidFilter(layoutUid, transaction);
|
|
942
|
+
if (!layoutUidFilter.length || !this.hasDesktopRouteUiLayoutsRelation()) {
|
|
943
|
+
return routes;
|
|
944
|
+
}
|
|
945
|
+
const matchedRoutes = [];
|
|
946
|
+
for (const route of routes) {
|
|
947
|
+
const routeLayoutUids = await this.readDesktopRouteUiLayoutUids(this.readRouteField(route, "id"), transaction);
|
|
948
|
+
if (import_lodash.default.intersection(routeLayoutUids, layoutUidFilter).length) {
|
|
949
|
+
matchedRoutes.push(route);
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
return matchedRoutes;
|
|
940
953
|
}
|
|
941
954
|
routeParentIdMatches(routeParentId, parentId) {
|
|
942
955
|
if (import_lodash.default.isNil(routeParentId) && import_lodash.default.isNil(parentId)) {
|
|
@@ -944,28 +957,42 @@ class FlowSurfacesService {
|
|
|
944
957
|
}
|
|
945
958
|
return String(routeParentId ?? "") === String(parentId ?? "");
|
|
946
959
|
}
|
|
947
|
-
async findMenuGroupRoutesByParentIdAndTitle(parentId, title, transaction) {
|
|
948
|
-
const routes = await this.findMenuGroupRoutesByTitle(title, transaction);
|
|
960
|
+
async findMenuGroupRoutesByParentIdAndTitle(parentId, title, transaction, layoutUid) {
|
|
961
|
+
const routes = await this.findMenuGroupRoutesByTitle(title, transaction, layoutUid);
|
|
949
962
|
return routes.filter(
|
|
950
963
|
(route) => this.routeParentIdMatches(this.readRouteField(route, "parentId") ?? null, parentId)
|
|
951
964
|
);
|
|
952
965
|
}
|
|
953
|
-
async findFlowPageRoutesByParentIdAndTitle(parentId, title, transaction) {
|
|
966
|
+
async findFlowPageRoutesByParentIdAndTitle(parentId, title, transaction, layoutUid) {
|
|
954
967
|
const normalizedTitle = String(title || "").trim();
|
|
955
|
-
|
|
956
|
-
if (!normalizedTitle || !normalizedParentId) {
|
|
968
|
+
if (!normalizedTitle) {
|
|
957
969
|
return [];
|
|
958
970
|
}
|
|
959
|
-
|
|
971
|
+
const routes = import_lodash.default.castArray(
|
|
960
972
|
await this.db.getRepository("desktopRoutes").find({
|
|
961
|
-
filter: {
|
|
973
|
+
filter: (0, import_service_utils.buildDefinedPayload)({
|
|
962
974
|
type: "flowPage",
|
|
963
975
|
title: normalizedTitle,
|
|
964
|
-
parentId:
|
|
965
|
-
},
|
|
976
|
+
parentId: import_lodash.default.isNil(parentId) ? void 0 : String(parentId)
|
|
977
|
+
}),
|
|
966
978
|
transaction
|
|
967
979
|
})
|
|
968
980
|
);
|
|
981
|
+
const layoutUidFilter = await this.resolveDesktopRouteLayoutUidFilter(layoutUid, transaction);
|
|
982
|
+
const layoutMatchedRoutes = [];
|
|
983
|
+
if (!layoutUidFilter.length || !this.hasDesktopRouteUiLayoutsRelation()) {
|
|
984
|
+
layoutMatchedRoutes.push(...routes);
|
|
985
|
+
} else {
|
|
986
|
+
for (const route of routes) {
|
|
987
|
+
const routeLayoutUids = await this.readDesktopRouteUiLayoutUids(this.readRouteField(route, "id"), transaction);
|
|
988
|
+
if (import_lodash.default.intersection(routeLayoutUids, layoutUidFilter).length) {
|
|
989
|
+
layoutMatchedRoutes.push(route);
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
return layoutMatchedRoutes.filter(
|
|
994
|
+
(route) => this.routeParentIdMatches(this.readRouteField(route, "parentId") ?? null, parentId)
|
|
995
|
+
);
|
|
969
996
|
}
|
|
970
997
|
async assertMenuParentIsGroup(parentMenuRouteId, transaction) {
|
|
971
998
|
if (import_lodash.default.isNil(parentMenuRouteId)) {
|
|
@@ -1071,6 +1098,29 @@ class FlowSurfacesService {
|
|
|
1071
1098
|
});
|
|
1072
1099
|
return defaultLayout ? [DEFAULT_ADMIN_UI_LAYOUT_UID] : [];
|
|
1073
1100
|
}
|
|
1101
|
+
async findDesktopRouteUiLayoutByUid(layoutUid, transaction) {
|
|
1102
|
+
const normalizedLayoutUid = this.normalizeExplicitDesktopRouteLayoutUid(layoutUid);
|
|
1103
|
+
if (!normalizedLayoutUid || !this.hasDesktopRouteUiLayoutsRelation()) {
|
|
1104
|
+
return null;
|
|
1105
|
+
}
|
|
1106
|
+
return this.db.getRepository("uiLayouts").findOne({
|
|
1107
|
+
filter: {
|
|
1108
|
+
uid: normalizedLayoutUid
|
|
1109
|
+
},
|
|
1110
|
+
transaction
|
|
1111
|
+
});
|
|
1112
|
+
}
|
|
1113
|
+
async getDesktopRouteUiLayoutTypeByUid(layoutUid, transaction) {
|
|
1114
|
+
var _a;
|
|
1115
|
+
const uiLayout = await this.findDesktopRouteUiLayoutByUid(layoutUid, transaction);
|
|
1116
|
+
return String(((_a = uiLayout == null ? void 0 : uiLayout.get) == null ? void 0 : _a.call(uiLayout, "layoutType")) || (uiLayout == null ? void 0 : uiLayout.layoutType) || "").trim() || void 0;
|
|
1117
|
+
}
|
|
1118
|
+
async isMobileDesktopRouteUiLayoutUid(layoutUid, transaction) {
|
|
1119
|
+
if (!layoutUid) {
|
|
1120
|
+
return false;
|
|
1121
|
+
}
|
|
1122
|
+
return await this.getDesktopRouteUiLayoutTypeByUid(layoutUid, transaction) === MOBILE_UI_LAYOUT_TYPE;
|
|
1123
|
+
}
|
|
1074
1124
|
async resolveInheritedDesktopRouteUiLayoutUids(parentRoute, transaction) {
|
|
1075
1125
|
const parentRouteId = this.readRouteField(parentRoute, "id");
|
|
1076
1126
|
if (!import_lodash.default.isNil(parentRouteId)) {
|
|
@@ -1081,6 +1131,86 @@ class FlowSurfacesService {
|
|
|
1081
1131
|
}
|
|
1082
1132
|
return this.resolveDefaultDesktopRouteUiLayoutUids(transaction);
|
|
1083
1133
|
}
|
|
1134
|
+
normalizeExplicitDesktopRouteLayoutUid(value) {
|
|
1135
|
+
const normalized = String(value || "").trim();
|
|
1136
|
+
return normalized || void 0;
|
|
1137
|
+
}
|
|
1138
|
+
normalizeDesktopRouteLayoutUidFilter(value) {
|
|
1139
|
+
return import_lodash.default.uniq(
|
|
1140
|
+
import_lodash.default.castArray(value).map((item) => this.normalizeExplicitDesktopRouteLayoutUid(item)).filter(Boolean)
|
|
1141
|
+
);
|
|
1142
|
+
}
|
|
1143
|
+
async resolveDesktopRouteLayoutUidFilter(value, transaction) {
|
|
1144
|
+
const explicitLayoutUids = this.normalizeDesktopRouteLayoutUidFilter(value);
|
|
1145
|
+
if (explicitLayoutUids.length) {
|
|
1146
|
+
return explicitLayoutUids;
|
|
1147
|
+
}
|
|
1148
|
+
return this.resolveDefaultDesktopRouteUiLayoutUids(transaction);
|
|
1149
|
+
}
|
|
1150
|
+
async assertEnabledDesktopRouteUiLayoutUid(layoutUid, actionName, path, transaction) {
|
|
1151
|
+
if (!this.hasDesktopRouteUiLayoutsRelation()) {
|
|
1152
|
+
(0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path} requires plugin-ui-layout desktop route relation support`, {
|
|
1153
|
+
ruleId: "navigation-layout-unsupported",
|
|
1154
|
+
path,
|
|
1155
|
+
details: {
|
|
1156
|
+
layoutUid
|
|
1157
|
+
}
|
|
1158
|
+
});
|
|
1159
|
+
}
|
|
1160
|
+
const uiLayout = await this.db.getRepository("uiLayouts").findOne({
|
|
1161
|
+
filter: {
|
|
1162
|
+
uid: layoutUid,
|
|
1163
|
+
enabled: true
|
|
1164
|
+
},
|
|
1165
|
+
transaction
|
|
1166
|
+
});
|
|
1167
|
+
if (!uiLayout) {
|
|
1168
|
+
(0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path} must reference an enabled ui layout`, {
|
|
1169
|
+
ruleId: "navigation-layout-not-found",
|
|
1170
|
+
path,
|
|
1171
|
+
details: {
|
|
1172
|
+
layoutUid
|
|
1173
|
+
}
|
|
1174
|
+
});
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
async assertDesktopRouteBelongsToUiLayout(actionName, route, layoutUid, path, transaction) {
|
|
1178
|
+
const normalizedLayoutUid = this.normalizeExplicitDesktopRouteLayoutUid(layoutUid);
|
|
1179
|
+
if (!normalizedLayoutUid || !route) {
|
|
1180
|
+
return;
|
|
1181
|
+
}
|
|
1182
|
+
const routeId = this.readRouteField(route, "id");
|
|
1183
|
+
const routeLayoutUids = await this.readDesktopRouteUiLayoutUids(routeId, transaction);
|
|
1184
|
+
if (routeLayoutUids.includes(normalizedLayoutUid)) {
|
|
1185
|
+
return;
|
|
1186
|
+
}
|
|
1187
|
+
(0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path} does not belong to ui layout '${normalizedLayoutUid}'`, {
|
|
1188
|
+
ruleId: "navigation-route-layout-mismatch",
|
|
1189
|
+
path,
|
|
1190
|
+
details: {
|
|
1191
|
+
routeId,
|
|
1192
|
+
layoutUid: normalizedLayoutUid,
|
|
1193
|
+
routeLayoutUids
|
|
1194
|
+
}
|
|
1195
|
+
});
|
|
1196
|
+
}
|
|
1197
|
+
async resolveRequestedDesktopRouteUiLayoutUids(values, parentRoute, actionName, transaction) {
|
|
1198
|
+
const layoutUid = this.normalizeExplicitDesktopRouteLayoutUid(values.layoutUid);
|
|
1199
|
+
if (layoutUid) {
|
|
1200
|
+
await this.assertEnabledDesktopRouteUiLayoutUid(layoutUid, actionName, "values.layoutUid", transaction);
|
|
1201
|
+
if (parentRoute) {
|
|
1202
|
+
await this.assertDesktopRouteBelongsToUiLayout(
|
|
1203
|
+
actionName,
|
|
1204
|
+
parentRoute,
|
|
1205
|
+
layoutUid,
|
|
1206
|
+
"values.parentMenuRouteId",
|
|
1207
|
+
transaction
|
|
1208
|
+
);
|
|
1209
|
+
}
|
|
1210
|
+
return [layoutUid];
|
|
1211
|
+
}
|
|
1212
|
+
return this.resolveInheritedDesktopRouteUiLayoutUids(parentRoute, transaction);
|
|
1213
|
+
}
|
|
1084
1214
|
async setDesktopRouteUiLayouts(routeId, uiLayoutUids, transaction) {
|
|
1085
1215
|
const relationRouteId = this.normalizeDesktopRouteRelationId(routeId);
|
|
1086
1216
|
if (import_lodash.default.isUndefined(relationRouteId) || !uiLayoutUids.length || !this.hasDesktopRouteUiLayoutsRelation()) {
|
|
@@ -1181,8 +1311,19 @@ class FlowSurfacesService {
|
|
|
1181
1311
|
async createFlowMenuGroup(values, transaction) {
|
|
1182
1312
|
const parentRoute = await this.assertMenuParentIsGroup(values.parentMenuRouteId, transaction);
|
|
1183
1313
|
const parentId = this.readRouteField(parentRoute, "id") ?? null;
|
|
1314
|
+
const routeUiLayoutUids = await this.resolveRequestedDesktopRouteUiLayoutUids(
|
|
1315
|
+
values,
|
|
1316
|
+
parentRoute,
|
|
1317
|
+
"createMenu",
|
|
1318
|
+
transaction
|
|
1319
|
+
);
|
|
1184
1320
|
const title = String(values.title || "").trim();
|
|
1185
|
-
const existingGroups = await this.findMenuGroupRoutesByParentIdAndTitle(
|
|
1321
|
+
const existingGroups = await this.findMenuGroupRoutesByParentIdAndTitle(
|
|
1322
|
+
parentId,
|
|
1323
|
+
title,
|
|
1324
|
+
transaction,
|
|
1325
|
+
routeUiLayoutUids
|
|
1326
|
+
);
|
|
1186
1327
|
if (existingGroups.length === 1) {
|
|
1187
1328
|
return this.buildMenuResult(existingGroups[0]);
|
|
1188
1329
|
}
|
|
@@ -1222,7 +1363,7 @@ class FlowSurfacesService {
|
|
|
1222
1363
|
});
|
|
1223
1364
|
await this.attachDesktopRouteUiLayoutsToRouteAndChildren(
|
|
1224
1365
|
this.readRouteField(route, "id"),
|
|
1225
|
-
|
|
1366
|
+
routeUiLayoutUids,
|
|
1226
1367
|
transaction
|
|
1227
1368
|
);
|
|
1228
1369
|
return this.buildMenuResult(route);
|
|
@@ -1230,6 +1371,12 @@ class FlowSurfacesService {
|
|
|
1230
1371
|
async createFlowMenuItem(values, transaction) {
|
|
1231
1372
|
var _a;
|
|
1232
1373
|
const parentRoute = await this.assertMenuParentIsGroup(values.parentMenuRouteId, transaction);
|
|
1374
|
+
const routeUiLayoutUids = await this.resolveRequestedDesktopRouteUiLayoutUids(
|
|
1375
|
+
values,
|
|
1376
|
+
parentRoute,
|
|
1377
|
+
"createMenu",
|
|
1378
|
+
transaction
|
|
1379
|
+
);
|
|
1233
1380
|
this.assertVisibleNavigationIcon("createMenu", "values", values);
|
|
1234
1381
|
const pageSchemaUid = values.pageSchemaUid || (0, import_utils.uid)();
|
|
1235
1382
|
const menuSchemaUid = (0, import_utils.uid)();
|
|
@@ -1276,7 +1423,7 @@ class FlowSurfacesService {
|
|
|
1276
1423
|
});
|
|
1277
1424
|
await this.attachDesktopRouteUiLayoutsToRouteAndChildren(
|
|
1278
1425
|
this.readRouteField(createdRoute, "id"),
|
|
1279
|
-
|
|
1426
|
+
routeUiLayoutUids,
|
|
1280
1427
|
transaction
|
|
1281
1428
|
);
|
|
1282
1429
|
const route = await desktopRoutes.findOne({
|
|
@@ -1313,7 +1460,7 @@ class FlowSurfacesService {
|
|
|
1313
1460
|
});
|
|
1314
1461
|
}
|
|
1315
1462
|
sanitizePublicCreateMenuValues(values) {
|
|
1316
|
-
return import_lodash.default.pick(values, ["title", "type", "icon", "tooltip", "hideInMenu", "parentMenuRouteId"]);
|
|
1463
|
+
return import_lodash.default.pick(values, ["title", "type", "layoutUid", "icon", "tooltip", "hideInMenu", "parentMenuRouteId"]);
|
|
1317
1464
|
}
|
|
1318
1465
|
async loadRouteBackedPageStructure(route, transaction) {
|
|
1319
1466
|
const routeId = this.readRouteField(route, "id");
|
|
@@ -3223,7 +3370,13 @@ class FlowSurfacesService {
|
|
|
3223
3370
|
if (!groupTitle) {
|
|
3224
3371
|
return document;
|
|
3225
3372
|
}
|
|
3226
|
-
const
|
|
3373
|
+
const layoutUid = this.normalizeExplicitDesktopRouteLayoutUid(document.navigation.layoutUid);
|
|
3374
|
+
const matchedRoutes = await this.findMenuGroupRoutesByParentIdAndTitle(
|
|
3375
|
+
null,
|
|
3376
|
+
groupTitle,
|
|
3377
|
+
transaction,
|
|
3378
|
+
layoutUid || await this.resolveDefaultDesktopRouteUiLayoutUids(transaction)
|
|
3379
|
+
);
|
|
3227
3380
|
if (!matchedRoutes.length) {
|
|
3228
3381
|
return document;
|
|
3229
3382
|
}
|
|
@@ -3248,29 +3401,89 @@ class FlowSurfacesService {
|
|
|
3248
3401
|
}
|
|
3249
3402
|
};
|
|
3250
3403
|
}
|
|
3404
|
+
async normalizeApplyBlueprintCreateMobileNavigation(document, transaction) {
|
|
3405
|
+
var _a;
|
|
3406
|
+
if (document.mode !== "create") {
|
|
3407
|
+
return document;
|
|
3408
|
+
}
|
|
3409
|
+
const layoutUid = this.normalizeExplicitDesktopRouteLayoutUid((_a = document.navigation) == null ? void 0 : _a.layoutUid);
|
|
3410
|
+
if (!await this.isMobileDesktopRouteUiLayoutUid(layoutUid, transaction)) {
|
|
3411
|
+
return document;
|
|
3412
|
+
}
|
|
3413
|
+
return {
|
|
3414
|
+
...document,
|
|
3415
|
+
navigation: (0, import_service_utils.buildDefinedPayload)({
|
|
3416
|
+
...document.navigation,
|
|
3417
|
+
layoutUid,
|
|
3418
|
+
group: void 0
|
|
3419
|
+
})
|
|
3420
|
+
};
|
|
3421
|
+
}
|
|
3422
|
+
async assertApplyBlueprintCreateNavigationLayout(document, transaction) {
|
|
3423
|
+
var _a, _b, _c;
|
|
3424
|
+
if (document.mode !== "create") {
|
|
3425
|
+
return;
|
|
3426
|
+
}
|
|
3427
|
+
const layoutUid = this.normalizeExplicitDesktopRouteLayoutUid((_a = document.navigation) == null ? void 0 : _a.layoutUid);
|
|
3428
|
+
if (!layoutUid) {
|
|
3429
|
+
return;
|
|
3430
|
+
}
|
|
3431
|
+
await this.assertEnabledDesktopRouteUiLayoutUid(
|
|
3432
|
+
layoutUid,
|
|
3433
|
+
"applyBlueprint",
|
|
3434
|
+
"values.navigation.layoutUid",
|
|
3435
|
+
transaction
|
|
3436
|
+
);
|
|
3437
|
+
if (await this.isMobileDesktopRouteUiLayoutUid(layoutUid, transaction)) {
|
|
3438
|
+
return;
|
|
3439
|
+
}
|
|
3440
|
+
const groupRouteId = (_c = (_b = document.navigation) == null ? void 0 : _b.group) == null ? void 0 : _c.routeId;
|
|
3441
|
+
if (import_lodash.default.isNil(groupRouteId) || groupRouteId === "") {
|
|
3442
|
+
return;
|
|
3443
|
+
}
|
|
3444
|
+
const groupRoute = await this.assertMenuParentIsGroup(groupRouteId, transaction);
|
|
3445
|
+
await this.assertDesktopRouteBelongsToUiLayout(
|
|
3446
|
+
"applyBlueprint",
|
|
3447
|
+
groupRoute,
|
|
3448
|
+
layoutUid,
|
|
3449
|
+
"values.navigation.group.routeId",
|
|
3450
|
+
transaction
|
|
3451
|
+
);
|
|
3452
|
+
}
|
|
3251
3453
|
async resolveApplyBlueprintCreatePageIdentity(document, transaction) {
|
|
3252
|
-
var _a, _b, _c, _d, _e;
|
|
3454
|
+
var _a, _b, _c, _d, _e, _f;
|
|
3253
3455
|
if (document.mode !== "create") {
|
|
3254
3456
|
return document;
|
|
3255
3457
|
}
|
|
3256
3458
|
const groupRouteId = (_b = (_a = document.navigation) == null ? void 0 : _a.group) == null ? void 0 : _b.routeId;
|
|
3257
|
-
const
|
|
3258
|
-
|
|
3459
|
+
const layoutUid = this.normalizeExplicitDesktopRouteLayoutUid((_c = document.navigation) == null ? void 0 : _c.layoutUid);
|
|
3460
|
+
const pageTitle = String(((_d = document.page) == null ? void 0 : _d.title) || ((_f = (_e = document.navigation) == null ? void 0 : _e.item) == null ? void 0 : _f.title) || "").trim();
|
|
3461
|
+
const hasGroupRouteId = !import_lodash.default.isNil(groupRouteId) && groupRouteId !== "";
|
|
3462
|
+
if (!pageTitle || !hasGroupRouteId && !layoutUid) {
|
|
3259
3463
|
return document;
|
|
3260
3464
|
}
|
|
3261
|
-
const
|
|
3465
|
+
const groupRoute = hasGroupRouteId ? await this.findMenuRouteById(groupRouteId, transaction) : null;
|
|
3466
|
+
const layoutUidFilter = layoutUid || (groupRoute ? await this.resolveInheritedDesktopRouteUiLayoutUids(groupRoute, transaction) : void 0);
|
|
3467
|
+
const matchedPages = await this.findFlowPageRoutesByParentIdAndTitle(
|
|
3468
|
+
hasGroupRouteId ? groupRouteId : null,
|
|
3469
|
+
pageTitle,
|
|
3470
|
+
transaction,
|
|
3471
|
+
layoutUidFilter
|
|
3472
|
+
);
|
|
3262
3473
|
if (!matchedPages.length) {
|
|
3263
3474
|
return document;
|
|
3264
3475
|
}
|
|
3265
3476
|
if (matchedPages.length > 1) {
|
|
3477
|
+
const locationLabel = hasGroupRouteId ? `under navigation.group.routeId '${groupRouteId}'` : `at the root of ui layout '${layoutUid}'`;
|
|
3266
3478
|
(0, import_errors.throwBadRequest)(
|
|
3267
|
-
`flowSurfaces applyBlueprint
|
|
3479
|
+
`flowSurfaces applyBlueprint ${locationLabel} already has ${matchedPages.length} flow pages titled '${pageTitle}'; pass target.pageSchemaUid explicitly before applyBlueprint`
|
|
3268
3480
|
);
|
|
3269
3481
|
}
|
|
3270
3482
|
const pageSchemaUid = String(this.readRouteField(matchedPages[0], "schemaUid") || "").trim();
|
|
3271
3483
|
if (!pageSchemaUid) {
|
|
3484
|
+
const locationLabel = hasGroupRouteId ? `under navigation.group.routeId '${groupRouteId}'` : `at the root of ui layout '${layoutUid}'`;
|
|
3272
3485
|
(0, import_errors.throwBadRequest)(
|
|
3273
|
-
`flowSurfaces applyBlueprint existing flow page '${pageTitle}'
|
|
3486
|
+
`flowSurfaces applyBlueprint existing flow page '${pageTitle}' ${locationLabel} is missing schemaUid; pass target.pageSchemaUid explicitly before applyBlueprint`
|
|
3274
3487
|
);
|
|
3275
3488
|
}
|
|
3276
3489
|
return {
|
|
@@ -3285,7 +3498,15 @@ class FlowSurfacesService {
|
|
|
3285
3498
|
async prepareApplyBlueprintRequest(values, transaction, createdKanbanSortFields) {
|
|
3286
3499
|
var _a;
|
|
3287
3500
|
const initialDocument = (0, import_blueprint.prepareFlowSurfaceApplyBlueprintDocument)(values);
|
|
3288
|
-
|
|
3501
|
+
await this.assertApplyBlueprintCreateNavigationLayout(initialDocument, transaction);
|
|
3502
|
+
const mobileNormalizedDocument = await this.normalizeApplyBlueprintCreateMobileNavigation(
|
|
3503
|
+
initialDocument,
|
|
3504
|
+
transaction
|
|
3505
|
+
);
|
|
3506
|
+
const groupResolvedDocument = await this.resolveApplyBlueprintCreateNavigationGroup(
|
|
3507
|
+
mobileNormalizedDocument,
|
|
3508
|
+
transaction
|
|
3509
|
+
);
|
|
3289
3510
|
const document = await this.resolveApplyBlueprintCreatePageIdentity(groupResolvedDocument, transaction);
|
|
3290
3511
|
await this.prepareApplyBlueprintKanbanBlocks(document, transaction, createdKanbanSortFields);
|
|
3291
3512
|
const replaceTarget = document.mode === "replace" && document.target ? await this.resolveApplyBlueprintReplaceTargetInfo(document.target.pageSchemaUid, transaction) : void 0;
|
|
@@ -3942,7 +4163,8 @@ class FlowSurfacesService {
|
|
|
3942
4163
|
await (0, import_authoring_validation.assertFlowSurfaceAuthoringPayload)("applyBlueprint", values, {
|
|
3943
4164
|
transaction: options.transaction,
|
|
3944
4165
|
enabledPackages,
|
|
3945
|
-
findMenuGroupRoutesByTitle: (title, transaction) => this.findMenuGroupRoutesByTitle(title, transaction),
|
|
4166
|
+
findMenuGroupRoutesByTitle: (title, transaction, layoutUid) => this.findMenuGroupRoutesByTitle(title, transaction, layoutUid),
|
|
4167
|
+
getUiLayoutTypeByUid: (layoutUid, transaction) => this.getDesktopRouteUiLayoutTypeByUid(layoutUid, transaction),
|
|
3946
4168
|
getCollection: (dataSourceKey, collectionName) => this.getCollection(dataSourceKey || "main", collectionName || "")
|
|
3947
4169
|
});
|
|
3948
4170
|
}
|
|
@@ -6026,6 +6248,11 @@ class FlowSurfacesService {
|
|
|
6026
6248
|
const pageSchemaUid = this.readRouteField(route, "schemaUid");
|
|
6027
6249
|
const structure = await this.loadRouteBackedPageStructure(route, transaction);
|
|
6028
6250
|
let tabRoute = structure.tabRoutes[0];
|
|
6251
|
+
const layoutUid = this.normalizeExplicitDesktopRouteLayoutUid(values.layoutUid);
|
|
6252
|
+
if (layoutUid) {
|
|
6253
|
+
await this.assertEnabledDesktopRouteUiLayoutUid(layoutUid, "createPage", "values.layoutUid", transaction);
|
|
6254
|
+
await this.assertDesktopRouteBelongsToUiLayout("createPage", route, layoutUid, "values.menuRouteId", transaction);
|
|
6255
|
+
}
|
|
6029
6256
|
const routeUiLayoutUids = await this.ensureDesktopRouteUiLayouts(route, transaction);
|
|
6030
6257
|
const routeOptions = this.readRouteOptions(route);
|
|
6031
6258
|
if (!routeOptions[FLOW_SURFACE_MENU_BINDABLE_OPTION_KEY]) {
|
|
@@ -17244,13 +17471,20 @@ class FlowSurfacesService {
|
|
|
17244
17471
|
description: changes.description,
|
|
17245
17472
|
className: changes.className
|
|
17246
17473
|
}),
|
|
17247
|
-
stepParams: (0, import_service_utils.hasDefinedValue)(changes, ["code", "version"]) ? {
|
|
17248
|
-
jsSettings: {
|
|
17249
|
-
|
|
17250
|
-
|
|
17251
|
-
|
|
17252
|
-
|
|
17253
|
-
|
|
17474
|
+
stepParams: (0, import_service_utils.hasDefinedValue)(changes, ["code", "version", "showBlockCard"]) ? {
|
|
17475
|
+
jsSettings: (0, import_service_utils.buildDefinedPayload)({
|
|
17476
|
+
...(0, import_service_utils.hasDefinedValue)(changes, ["code", "version"]) ? {
|
|
17477
|
+
runJs: (0, import_service_utils.buildDefinedPayload)({
|
|
17478
|
+
code: changes.code,
|
|
17479
|
+
version: changes.version
|
|
17480
|
+
})
|
|
17481
|
+
} : {},
|
|
17482
|
+
...(0, import_service_utils.hasOwnDefined)(changes, "showBlockCard") ? {
|
|
17483
|
+
showBlockCard: {
|
|
17484
|
+
showBlockCard: changes.showBlockCard
|
|
17485
|
+
}
|
|
17486
|
+
} : {}
|
|
17487
|
+
})
|
|
17254
17488
|
} : void 0
|
|
17255
17489
|
},
|
|
17256
17490
|
options
|
|
@@ -45,7 +45,8 @@ export type FlowSurfaceConfigureOption = {
|
|
|
45
45
|
type: FlowSurfaceConfigureOptionValueType;
|
|
46
46
|
description?: string;
|
|
47
47
|
enum?: Array<string | number | boolean>;
|
|
48
|
-
example?:
|
|
48
|
+
example?: unknown;
|
|
49
|
+
default?: unknown;
|
|
49
50
|
supportsFlowContext?: boolean;
|
|
50
51
|
};
|
|
51
52
|
export type FlowSurfaceConfigureOptions = Record<string, FlowSurfaceConfigureOption>;
|
|
@@ -2635,6 +2635,10 @@ declare const _default: {
|
|
|
2635
2635
|
FlowSurfaceApplyBlueprintNavigation: {
|
|
2636
2636
|
type: string;
|
|
2637
2637
|
properties: {
|
|
2638
|
+
layoutUid: {
|
|
2639
|
+
type: string;
|
|
2640
|
+
description: string;
|
|
2641
|
+
};
|
|
2638
2642
|
group: {
|
|
2639
2643
|
$ref: string;
|
|
2640
2644
|
};
|
|
@@ -3148,6 +3152,10 @@ declare const _default: {
|
|
|
3148
3152
|
type: string;
|
|
3149
3153
|
required: string[];
|
|
3150
3154
|
properties: {
|
|
3155
|
+
layoutUid: {
|
|
3156
|
+
type: string;
|
|
3157
|
+
description: string;
|
|
3158
|
+
};
|
|
3151
3159
|
title: {
|
|
3152
3160
|
type: string;
|
|
3153
3161
|
};
|
|
@@ -3270,6 +3278,10 @@ declare const _default: {
|
|
|
3270
3278
|
FlowSurfaceCreatePageRequest: {
|
|
3271
3279
|
type: string;
|
|
3272
3280
|
properties: {
|
|
3281
|
+
layoutUid: {
|
|
3282
|
+
type: string;
|
|
3283
|
+
description: string;
|
|
3284
|
+
};
|
|
3273
3285
|
menuRouteId: {
|
|
3274
3286
|
oneOf: {
|
|
3275
3287
|
type: string;
|
|
@@ -6102,6 +6114,7 @@ declare const _default: {
|
|
|
6102
6114
|
};
|
|
6103
6115
|
};
|
|
6104
6116
|
example: {};
|
|
6117
|
+
default: {};
|
|
6105
6118
|
supportsFlowContext: {
|
|
6106
6119
|
type: string;
|
|
6107
6120
|
};
|
|
@@ -668,6 +668,7 @@ export declare const flowSurfaceExamples: {
|
|
|
668
668
|
title: string;
|
|
669
669
|
description: string;
|
|
670
670
|
className: string;
|
|
671
|
+
showBlockCard: boolean;
|
|
671
672
|
version: string;
|
|
672
673
|
code: string;
|
|
673
674
|
};
|
|
@@ -764,6 +765,7 @@ export declare const flowSurfaceExamples: {
|
|
|
764
765
|
title: string;
|
|
765
766
|
description: string;
|
|
766
767
|
className: string;
|
|
768
|
+
showBlockCard: boolean;
|
|
767
769
|
version: string;
|
|
768
770
|
code: string;
|
|
769
771
|
};
|
|
@@ -1068,6 +1070,7 @@ export declare const flowSurfaceExamples: {
|
|
|
1068
1070
|
settings: {
|
|
1069
1071
|
title: string;
|
|
1070
1072
|
description: string;
|
|
1073
|
+
showBlockCard: boolean;
|
|
1071
1074
|
version: string;
|
|
1072
1075
|
code: string;
|
|
1073
1076
|
};
|
|
@@ -893,6 +893,7 @@ const flowSurfaceExamples = {
|
|
|
893
893
|
title: "Custom hero",
|
|
894
894
|
description: "Rendered by JS block runtime",
|
|
895
895
|
className: "hero-shell",
|
|
896
|
+
showBlockCard: true,
|
|
896
897
|
version: "1.0.0",
|
|
897
898
|
code: "ctx.render('<div>Hello from JS block</div>');"
|
|
898
899
|
}
|
|
@@ -996,6 +997,7 @@ const flowSurfaceExamples = {
|
|
|
996
997
|
title: "Users hero",
|
|
997
998
|
description: "Rendered from FlowSurfaces configure",
|
|
998
999
|
className: "users-hero",
|
|
1000
|
+
showBlockCard: true,
|
|
999
1001
|
version: "1.0.1",
|
|
1000
1002
|
code: "ctx.render('<div>Users hero</div>');"
|
|
1001
1003
|
}
|
|
@@ -1341,6 +1343,7 @@ const flowSurfaceExamples = {
|
|
|
1341
1343
|
settings: {
|
|
1342
1344
|
title: "Users banner",
|
|
1343
1345
|
description: "Custom JS rendered banner",
|
|
1346
|
+
showBlockCard: true,
|
|
1344
1347
|
version: "1.0.0",
|
|
1345
1348
|
code: "ctx.render('<div>Users banner</div>');"
|
|
1346
1349
|
}
|
|
@@ -623,7 +623,7 @@ const actionDocs = {
|
|
|
623
623
|
tags: [FLOW_SURFACES_TAG],
|
|
624
624
|
summary: "Apply a page blueprint to create or replace one Modern page",
|
|
625
625
|
description: valuesCompatibilityNote(
|
|
626
|
-
`Accepts one simplified JSON page blueprint and compiles it to internal flow-surface operations. The public blueprint describes page structure (\`create\` or \`replace\`, page metadata, ordered tabs, blocks, fields, actions, inline popups, optional reusable assets) and optional top-level \`reaction.items[]\` for whole-page interaction authoring. Each reaction item targets an explicit local key / bind key produced by the same blueprint run. Only explicitly listed reaction items are written. \`rules: []\` clears the targeted slot. Repeating the same \`(type, target)\` reaction slot in one blueprint is invalid. In \`replace\`, reaction targets always bind to the newly produced blueprint result, not historical nodes from the previous page version; if a slot must exist in the resulting surface, include it explicitly instead of relying on omission. Localized reaction edits on an existing surface should use \`getReactionMeta\` + \`set*Rules\` instead of applying a whole page blueprint again. The request body is that page-document JSON object itself and must not be JSON-stringified. Wrong: \`{ "requestBody": "{\\"version\\":\\"1\\"}" }\`. Internal planning details stay hidden. In \`create\`, \`navigation.group.routeId\` has the highest priority when targeting an existing menu group. If \`routeId\` is present, applyBlueprint ignores \`title\`, \`icon\`, \`tooltip\`, and \`hideInMenu\` on \`navigation.group\`; applyBlueprint create mode does not mutate existing group metadata, so callers should use \`updateMenu\` separately when that is required. When \`routeId\` is omitted and \`navigation.group.title\` is provided, applyBlueprint reuses one existing same-title group when it is unique, creates a new group when none exists, and rejects ambiguous multi-match cases. Metadata such as \`icon\`, \`tooltip\`, and \`hideInMenu\` is used only when a new group is created and is ignored when an existing group is reused. \`replace\` uses \`target.pageSchemaUid\`, updates only the explicit page-level fields provided in \`page\`, maps blueprint tabs to existing route-backed tab slots by index, rewrites each slot in order, removes trailing old tabs, and appends extra new tabs when needed. Tab and block keys are optional in the public blueprint; omit them unless custom layout or cross-block targeting needs a stable in-document identifier. \`layout\` is only allowed on tabs and inline popup documents; blocks themselves do not accept a \`layout\` property. Public applyBlueprint blocks do not support generic \`form\`; use \`editForm\` or \`createForm\`. AI employee actions use \`type: "aiEmployee"\` plus public \`settings.username\`, \`workContext\`, \`tasks\`, \`auto\`, and \`style\`; work context may target \`self\` or a same-blueprint block key and is persisted as real Flow Model \`uid\` values. For JS blocks/fields/actions, \`script\` is a non-empty string asset key into \`assets.scripts\`; put inline JS in \`settings.code\` and \`settings.version\`. Direct \`table\` / \`list\` / \`gridCard\` / \`calendar\` / \`kanban\` blocks may omit \`defaultFilter\`; the backend generates one from live metadata with up to 4 scalar/filterable fields. Explicit values must contain at least the smaller of 3 and the collection eligible-field count, and values with more than 4 fields are truncated before persistence. A valid explicit or generated block-level value backfills the default \`filter\` action \`settings.defaultFilter\`; explicit filter-action \`settings.defaultFilter\` still wins. ${TREE_TABLE_RECORD_ACTION_DEFAULTS_NOTE} ${APPLY_BLUEPRINT_TREE_TABLE_TITLE_FIELD_NOTE} Inline popup documents may set \`popup.tryTemplate=true\` to ask the backend for the best compatible popup template before falling back to local popup content. Inline popup documents may also combine \`popup.tryTemplate\` with \`popup.saveAsTemplate={ name, description, local? }\`: a hit binds the matched template immediately and lets later inline popups in the same blueprint reuse that final bound template through \`popup.template={ local, mode }\`, while a miss requires explicit local \`popup.blocks\` so the fallback popup can be saved and reused. Custom \`edit\` popups that provide \`popup.blocks\` must include exactly one \`editForm\` block; that \`editForm\` may omit \`resource\` and then inherits the opener's current-record context. When layout is omitted, applyBlueprint auto-generates a simple top-to-bottom layout. When a \`replace\` run expands a page to multiple tabs while the current page still has \`enableTabs=false\`, callers must set \`page.enableTabs=true\` explicitly. The response hides execution internals and returns only the resolved page target and final surface readback.`
|
|
626
|
+
`Accepts one simplified JSON page blueprint and compiles it to internal flow-surface operations. The public blueprint describes page structure (\`create\` or \`replace\`, page metadata, ordered tabs, blocks, fields, actions, inline popups, optional reusable assets) and optional top-level \`reaction.items[]\` for whole-page interaction authoring. Each reaction item targets an explicit local key / bind key produced by the same blueprint run. Only explicitly listed reaction items are written. \`rules: []\` clears the targeted slot. Repeating the same \`(type, target)\` reaction slot in one blueprint is invalid. In \`replace\`, reaction targets always bind to the newly produced blueprint result, not historical nodes from the previous page version; if a slot must exist in the resulting surface, include it explicitly instead of relying on omission. Localized reaction edits on an existing surface should use \`getReactionMeta\` + \`set*Rules\` instead of applying a whole page blueprint again. The request body is that page-document JSON object itself and must not be JSON-stringified. Wrong: \`{ "requestBody": "{\\"version\\":\\"1\\"}" }\`. Internal planning details stay hidden. In \`create\`, \`navigation.layoutUid\` optionally scopes menu group reuse, duplicate page identity checks, and newly created routes to an enabled UI layout such as \`admin-layout-model\` or \`mobile-layout-model\`; when the target layout type is mobile, applyBlueprint ignores \`navigation.group\` and creates a root-level mobile tab page. When \`layoutUid\` is omitted, routes keep the existing admin/default inheritance behavior. In non-mobile \`create\`, \`navigation.group.routeId\` has the highest priority when targeting an existing menu group. If \`routeId\` is present, applyBlueprint ignores \`title\`, \`icon\`, \`tooltip\`, and \`hideInMenu\` on \`navigation.group\`; applyBlueprint create mode does not mutate existing group metadata, so callers should use \`updateMenu\` separately when that is required. When \`routeId\` is omitted and \`navigation.group.title\` is provided, applyBlueprint reuses one existing same-title group in the target layout when it is unique, creates a new group when none exists, and rejects ambiguous multi-match cases. Metadata such as \`icon\`, \`tooltip\`, and \`hideInMenu\` is used only when a new group is created and is ignored when an existing group is reused. \`replace\` uses \`target.pageSchemaUid\`, updates only the explicit page-level fields provided in \`page\`, maps blueprint tabs to existing route-backed tab slots by index, rewrites each slot in order, removes trailing old tabs, and appends extra new tabs when needed. Tab and block keys are optional in the public blueprint; omit them unless custom layout or cross-block targeting needs a stable in-document identifier. \`layout\` is only allowed on tabs and inline popup documents; blocks themselves do not accept a \`layout\` property. Public applyBlueprint blocks do not support generic \`form\`; use \`editForm\` or \`createForm\`. AI employee actions use \`type: "aiEmployee"\` plus public \`settings.username\`, \`workContext\`, \`tasks\`, \`auto\`, and \`style\`; work context may target \`self\` or a same-blueprint block key and is persisted as real Flow Model \`uid\` values. For JS blocks/fields/actions, \`script\` is a non-empty string asset key into \`assets.scripts\`; put inline JS in \`settings.code\` and \`settings.version\`. Direct \`table\` / \`list\` / \`gridCard\` / \`calendar\` / \`kanban\` blocks may omit \`defaultFilter\`; the backend generates one from live metadata with up to 4 scalar/filterable fields. Explicit values must contain at least the smaller of 3 and the collection eligible-field count, and values with more than 4 fields are truncated before persistence. A valid explicit or generated block-level value backfills the default \`filter\` action \`settings.defaultFilter\`; explicit filter-action \`settings.defaultFilter\` still wins. ${TREE_TABLE_RECORD_ACTION_DEFAULTS_NOTE} ${APPLY_BLUEPRINT_TREE_TABLE_TITLE_FIELD_NOTE} Inline popup documents may set \`popup.tryTemplate=true\` to ask the backend for the best compatible popup template before falling back to local popup content. Inline popup documents may also combine \`popup.tryTemplate\` with \`popup.saveAsTemplate={ name, description, local? }\`: a hit binds the matched template immediately and lets later inline popups in the same blueprint reuse that final bound template through \`popup.template={ local, mode }\`, while a miss requires explicit local \`popup.blocks\` so the fallback popup can be saved and reused. Custom \`edit\` popups that provide \`popup.blocks\` must include exactly one \`editForm\` block; that \`editForm\` may omit \`resource\` and then inherits the opener's current-record context. When layout is omitted, applyBlueprint auto-generates a simple top-to-bottom layout. When a \`replace\` run expands a page to multiple tabs while the current page still has \`enableTabs=false\`, callers must set \`page.enableTabs=true\` explicitly. The response hides execution internals and returns only the resolved page target and final surface readback.`
|
|
627
627
|
),
|
|
628
628
|
requestBody: {
|
|
629
629
|
required: true,
|
|
@@ -809,7 +809,7 @@ const actionDocs = {
|
|
|
809
809
|
tags: [FLOW_SURFACES_TAG],
|
|
810
810
|
summary: "Create a group menu or a bindable V2 menu item",
|
|
811
811
|
description: valuesCompatibilityNote(
|
|
812
|
-
'Creates a FlowSurfaces menu node. `type="group"` creates a menu group. `type="item"` creates a menu item that can be bound to a modern page (v2), and automatically fills in the flowPage route, the default hidden tab route, and the RootPageModel anchor.'
|
|
812
|
+
'Creates a FlowSurfaces menu node. `type="group"` creates a menu group. `type="item"` creates a menu item that can be bound to a modern page (v2), and automatically fills in the flowPage route, the default hidden tab route, and the RootPageModel anchor. Optional `layoutUid` scopes the route to an enabled UI layout; omitted values keep the existing parent/default admin layout inheritance.'
|
|
813
813
|
),
|
|
814
814
|
requestBody: requestBody("FlowSurfaceCreateMenuRequest", import_flow_surfaces.flowSurfaceExamples.createMenu),
|
|
815
815
|
responses: responses("FlowSurfaceCreateMenuResult")
|
|
@@ -827,7 +827,7 @@ const actionDocs = {
|
|
|
827
827
|
tags: [FLOW_SURFACES_TAG],
|
|
828
828
|
summary: "Initialize a modern page for an existing bindable menu item",
|
|
829
829
|
description: valuesCompatibilityNote(
|
|
830
|
-
"Initializes a modern page (v2) for an existing bindable menu item through `menuRouteId` first, and fills in the default BlockGridModel. In compatibility mode, if `menuRouteId` is omitted, the old behavior still applies and a top-level menu plus page will be created automatically. Before initialization, do not call page/tab lifecycle actions such as `addTab`, `updateTab`, `moveTab`, `removeTab`, or `destroyPage`."
|
|
830
|
+
"Initializes a modern page (v2) for an existing bindable menu item through `menuRouteId` first, and fills in the default BlockGridModel. Optional `layoutUid` asserts that the existing menu route belongs to the target UI layout; omitted values keep the existing parent/default admin layout inheritance. In compatibility mode, if `menuRouteId` is omitted, the old behavior still applies and a top-level menu plus page will be created automatically. Before initialization, do not call page/tab lifecycle actions such as `addTab`, `updateTab`, `moveTab`, `removeTab`, or `destroyPage`."
|
|
831
831
|
),
|
|
832
832
|
requestBody: requestBody("FlowSurfaceCreatePageRequest", import_flow_surfaces.flowSurfaceExamples.createPage),
|
|
833
833
|
responses: responses("FlowSurfaceCreatePageResult")
|
|
@@ -1642,6 +1642,7 @@ const schemas = {
|
|
|
1642
1642
|
}
|
|
1643
1643
|
},
|
|
1644
1644
|
example: {},
|
|
1645
|
+
default: {},
|
|
1645
1646
|
supportsFlowContext: {
|
|
1646
1647
|
type: "boolean"
|
|
1647
1648
|
}
|
|
@@ -4166,11 +4167,11 @@ const schemas = {
|
|
|
4166
4167
|
properties: {
|
|
4167
4168
|
routeId: {
|
|
4168
4169
|
...STRING_OR_INTEGER_SCHEMA,
|
|
4169
|
-
description: "Preferred existing menu-group route id. When present, routeId has the highest priority and title/icon/tooltip/hideInMenu are ignored. applyBlueprint create mode does not mutate existing group metadata; use low-level updateMenu separately when needed."
|
|
4170
|
+
description: "Preferred existing menu-group route id for non-mobile create mode. When present, routeId has the highest priority and title/icon/tooltip/hideInMenu are ignored. Ignored when navigation.layoutUid targets a mobile layout because mobile pages are created as root tabs. applyBlueprint create mode does not mutate existing group metadata; use low-level updateMenu separately when needed."
|
|
4170
4171
|
},
|
|
4171
4172
|
title: {
|
|
4172
4173
|
type: "string",
|
|
4173
|
-
description: "Group title for create mode. When `routeId` is omitted, applyBlueprint reuses a same-title group if the match is unique, creates one when no group exists, and rejects ambiguous multi-match cases. If an existing group is reused, group metadata is ignored; use low-level updateMenu to change existing group metadata."
|
|
4174
|
+
description: "Group title for non-mobile create mode. When `routeId` is omitted, applyBlueprint reuses a same-title group if the match is unique, creates one when no group exists, and rejects ambiguous multi-match cases. Ignored when navigation.layoutUid targets a mobile layout because mobile pages are created as root tabs. If an existing group is reused, group metadata is ignored; use low-level updateMenu to change existing group metadata."
|
|
4174
4175
|
},
|
|
4175
4176
|
icon: {
|
|
4176
4177
|
type: "string",
|
|
@@ -4190,6 +4191,10 @@ const schemas = {
|
|
|
4190
4191
|
FlowSurfaceApplyBlueprintNavigation: {
|
|
4191
4192
|
type: "object",
|
|
4192
4193
|
properties: {
|
|
4194
|
+
layoutUid: {
|
|
4195
|
+
type: "string",
|
|
4196
|
+
description: "Optional enabled UI layout uid that scopes create-mode route lookup and newly created routes. Use `mobile-layout-model` for mobile pages; mobile layouts ignore navigation.group and create a root-level tab page. When omitted, the server preserves the existing parent/default admin layout behavior."
|
|
4197
|
+
},
|
|
4193
4198
|
group: ref("FlowSurfaceApplyBlueprintNavigationGroup"),
|
|
4194
4199
|
item: {
|
|
4195
4200
|
type: "object",
|
|
@@ -4405,7 +4410,7 @@ const schemas = {
|
|
|
4405
4410
|
FlowSurfaceApplyBlueprintRequest: {
|
|
4406
4411
|
type: "object",
|
|
4407
4412
|
required: ["mode", "tabs"],
|
|
4408
|
-
description: `Simplified page-structure request object for applyBlueprint. \`version\` may be omitted and defaults to '1'. Runtime validation enforces mode-specific rules: create does not accept target, while replace requires target.pageSchemaUid and does not use navigation. For JS blocks/fields/actions, \`script\` is a non-empty string asset key into \`assets.scripts\`, and referenced script assets must provide non-empty \`code\`; put inline JS in \`settings.code\` and \`settings.version\`. ${TREE_TABLE_RECORD_ACTION_DEFAULTS_NOTE} ${APPLY_BLUEPRINT_TREE_TABLE_TITLE_FIELD_NOTE} \`defaults.collections\` may provide main data-source collection-level fieldGroups, popup metadata with required \`name\` and \`description\`, and formBehavior for generated default add/edit popup forms; use \`defaults.dataSources.<dataSourceKey>.collections\` for external data sources. v1 does not support \`defaults.blocks\`.`,
|
|
4413
|
+
description: `Simplified page-structure request object for applyBlueprint. \`version\` may be omitted and defaults to '1'. Runtime validation enforces mode-specific rules: create does not accept target, while replace requires target.pageSchemaUid and does not use navigation. In create mode, \`navigation.layoutUid\` scopes menu group reuse, duplicate page identity, and newly created routes to the target layout; use \`mobile-layout-model\` for mobile pages, where \`navigation.group\` is ignored and the page is created as a root tab, and omit it for default admin behavior. For JS blocks/fields/actions, \`script\` is a non-empty string asset key into \`assets.scripts\`, and referenced script assets must provide non-empty \`code\`; put inline JS in \`settings.code\` and \`settings.version\`. ${TREE_TABLE_RECORD_ACTION_DEFAULTS_NOTE} ${APPLY_BLUEPRINT_TREE_TABLE_TITLE_FIELD_NOTE} \`defaults.collections\` may provide main data-source collection-level fieldGroups, popup metadata with required \`name\` and \`description\`, and formBehavior for generated default add/edit popup forms; use \`defaults.dataSources.<dataSourceKey>.collections\` for external data sources. v1 does not support \`defaults.blocks\`.`,
|
|
4409
4414
|
properties: {
|
|
4410
4415
|
version: {
|
|
4411
4416
|
type: "string",
|
|
@@ -4577,6 +4582,10 @@ const schemas = {
|
|
|
4577
4582
|
type: "object",
|
|
4578
4583
|
required: ["title"],
|
|
4579
4584
|
properties: {
|
|
4585
|
+
layoutUid: {
|
|
4586
|
+
type: "string",
|
|
4587
|
+
description: "Optional enabled UI layout uid for the created menu route, for example `mobile-layout-model`. When omitted, the route inherits its parent layout or the default admin layout."
|
|
4588
|
+
},
|
|
4580
4589
|
title: {
|
|
4581
4590
|
type: "string"
|
|
4582
4591
|
},
|
|
@@ -4673,6 +4682,10 @@ const schemas = {
|
|
|
4673
4682
|
FlowSurfaceCreatePageRequest: {
|
|
4674
4683
|
type: "object",
|
|
4675
4684
|
properties: {
|
|
4685
|
+
layoutUid: {
|
|
4686
|
+
type: "string",
|
|
4687
|
+
description: "Optional enabled UI layout uid. With `menuRouteId`, the existing route must already belong to this layout. Without `menuRouteId`, the compatibility create-menu fallback creates the route in this layout."
|
|
4688
|
+
},
|
|
4676
4689
|
menuRouteId: STRING_OR_INTEGER_SCHEMA,
|
|
4677
4690
|
pageSchemaUid: {
|
|
4678
4691
|
type: "string"
|