@webiny/app-headless-cms 6.5.0-beta.5 → 6.5.0-beta.6
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/features/formModel/CmsFormModelBuilder.d.ts +1 -1
- package/features/formModel/CmsFormModelBuilder.js +1 -13
- package/features/formModel/CmsFormModelBuilder.js.map +1 -1
- package/features/formModel/CmsFormModelBuilder.test.js +141 -0
- package/features/formModel/CmsFormModelBuilder.test.js.map +1 -1
- package/features/formModel/CmsLayoutMapper.d.ts +8 -1
- package/features/formModel/CmsLayoutMapper.js +23 -1
- package/features/formModel/CmsLayoutMapper.js.map +1 -1
- package/features/formModel/mappers/DynamicZoneFieldMapper.js +3 -0
- package/features/formModel/mappers/DynamicZoneFieldMapper.js.map +1 -1
- package/features/formModel/mappers/ObjectFieldMapper.js +11 -6
- package/features/formModel/mappers/ObjectFieldMapper.js.map +1 -1
- package/package.json +20 -20
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { IFormModelConfig } from "@webiny/app-admin/features/formModel/abstractions.js";
|
|
2
|
-
import {
|
|
2
|
+
import type { CmsModel } from "../../types.js";
|
|
3
3
|
import type { ICmsFieldTypeMapper, ICmsFormModelBuilder } from "./abstractions.js";
|
|
4
4
|
import type { ICmsFieldRenderer } from "../../presentation/fieldRenderers/abstractions.js";
|
|
5
5
|
declare class CmsFormModelBuilderImpl implements ICmsFormModelBuilder {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { isLayoutField } from "../../types.js";
|
|
2
1
|
import { CmsFieldTypeMapper, CmsFormModelBuilder } from "./abstractions.js";
|
|
3
2
|
import { CmsFieldRenderer } from "../../presentation/fieldRenderers/abstractions.js";
|
|
4
|
-
import { mapCmsLayout } from "./CmsLayoutMapper.js";
|
|
3
|
+
import { collectFieldIds, mapCmsLayout } from "./CmsLayoutMapper.js";
|
|
5
4
|
import { createBuiltInMappers } from "./mappers/index.js";
|
|
6
5
|
import { applyFieldProps } from "./mappers/applyFieldProps.js";
|
|
7
6
|
class CmsFormModelBuilderImpl {
|
|
@@ -82,17 +81,6 @@ const CmsFormModelBuilder_CmsFormModelBuilder = CmsFormModelBuilder.createImplem
|
|
|
82
81
|
]
|
|
83
82
|
]
|
|
84
83
|
});
|
|
85
|
-
function collectFieldIds(layout, idToFieldId) {
|
|
86
|
-
const fieldIds = new Set();
|
|
87
|
-
for (const row of layout)for (const cell of row)if ("string" == typeof cell) {
|
|
88
|
-
const fieldId = idToFieldId.get(cell);
|
|
89
|
-
if (fieldId) fieldIds.add(fieldId);
|
|
90
|
-
} else if (isLayoutField(cell) && "tabs" === cell.type) {
|
|
91
|
-
const tabsField = cell;
|
|
92
|
-
for (const tab of tabsField.tabs)for (const id of collectFieldIds(tab.layout, idToFieldId))fieldIds.add(id);
|
|
93
|
-
}
|
|
94
|
-
return fieldIds;
|
|
95
|
-
}
|
|
96
84
|
export { CmsFormModelBuilder_CmsFormModelBuilder as CmsFormModelBuilder };
|
|
97
85
|
|
|
98
86
|
//# sourceMappingURL=CmsFormModelBuilder.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/formModel/CmsFormModelBuilder.js","sources":["../../../src/features/formModel/CmsFormModelBuilder.ts"],"sourcesContent":["import type {\n IFieldBuilder,\n IFieldBuilderRegistry,\n IFormModelConfig\n} from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport
|
|
1
|
+
{"version":3,"file":"features/formModel/CmsFormModelBuilder.js","sources":["../../../src/features/formModel/CmsFormModelBuilder.ts"],"sourcesContent":["import type {\n IFieldBuilder,\n IFieldBuilderRegistry,\n IFormModelConfig\n} from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport type { CmsModel, CmsModelField } from \"~/types.js\";\nimport type {\n ICmsFieldTypeMapper,\n ICmsFieldMapperContext,\n ICmsFormModelBuilder\n} from \"./abstractions.js\";\nimport { CmsFormModelBuilder as BuilderAbstraction } from \"./abstractions.js\";\nimport { CmsFieldTypeMapper } from \"./abstractions.js\";\nimport { CmsFieldRenderer } from \"~/presentation/fieldRenderers/abstractions.js\";\nimport type { ICmsFieldRenderer } from \"~/presentation/fieldRenderers/abstractions.js\";\nimport { collectFieldIds, mapCmsLayout } from \"./CmsLayoutMapper.js\";\nimport { createBuiltInMappers } from \"./mappers/index.js\";\nimport { applyFieldProps } from \"./mappers/applyFieldProps.js\";\n\nclass CmsFormModelBuilderImpl implements ICmsFormModelBuilder {\n private mappers: Map<string, ICmsFieldTypeMapper>;\n private rendererMap: Map<string, string>;\n private renderers: Map<string, ICmsFieldRenderer>;\n\n constructor(\n customMappers: ICmsFieldTypeMapper[] | undefined,\n fieldRenderers: ICmsFieldRenderer[] | undefined\n ) {\n this.mappers = new Map();\n for (const mapper of createBuiltInMappers()) {\n this.mappers.set(mapper.type, mapper);\n }\n for (const mapper of customMappers || []) {\n this.mappers.set(mapper.type, mapper);\n }\n\n this.rendererMap = new Map();\n this.renderers = new Map();\n for (const renderer of fieldRenderers || []) {\n this.rendererMap.set(renderer.rendererName, renderer.formRenderer);\n this.renderers.set(renderer.rendererName, renderer);\n }\n }\n\n build(model: CmsModel): IFormModelConfig {\n const context: ICmsFieldMapperContext = {\n model,\n rendererMap: this.rendererMap,\n mapField: (field, registry) => this.mapField(field, registry, context)\n };\n\n const idToFieldId = new Map<string, string>();\n for (const field of model.fields) {\n idToFieldId.set(field.id, field.fieldId);\n }\n\n const fieldIdsInLayout = model.layout ? collectFieldIds(model.layout, idToFieldId) : null;\n\n return {\n fields: registry => {\n const result: Record<string, IFieldBuilder> = {};\n for (const field of model.fields) {\n const builder = this.mapField(field, registry, context);\n if (fieldIdsInLayout && !fieldIdsInLayout.has(field.fieldId)) {\n builder.hidden();\n }\n result[field.fieldId] = builder;\n }\n return result;\n },\n layout: model.layout\n ? layout => mapCmsLayout(model.layout!, layout, idToFieldId)\n : undefined\n };\n }\n\n private mapField(\n modelField: CmsModelField,\n registry: IFieldBuilderRegistry,\n context: ICmsFieldMapperContext\n ): IFieldBuilder {\n const field = this.withCompatibleRenderer(modelField, context.model);\n const mapper = this.mappers.get(field.type);\n if (mapper) {\n return mapper.map(field, registry, context);\n }\n\n return applyFieldProps(registry.text(), field, context.rendererMap);\n }\n\n /**\n * A list renderer can't render a single value: `dateTimeInputs` calls `.map()` on a\n * stored date string and crashes the form. When a single-value field is configured with\n * a renderer that only accepts list fields, drop it so the field type's default\n * single-value renderer is used instead.\n */\n private withCompatibleRenderer(field: CmsModelField, model: CmsModel): CmsModelField {\n if (field.list || !field.renderer || typeof field.renderer !== \"object\") {\n return field;\n }\n const renderer = this.renderers.get(field.renderer.name);\n if (!renderer || renderer.canUse({ field, model })) {\n return field;\n }\n if (!renderer.canUse({ field: { ...field, list: true }, model })) {\n return field;\n }\n if (process.env.NODE_ENV === \"development\") {\n console.warn(\n `[CmsFormModelBuilder] Renderer \"${field.renderer.name}\" is for list fields; ` +\n `field \"${field.fieldId}\" is not a list and uses its default renderer instead.`\n );\n }\n // Mappers treat a missing renderer as \"use the field type's default\".\n const { renderer: _renderer, ...rest } = field;\n return rest as CmsModelField;\n }\n}\n\nexport const CmsFormModelBuilder = BuilderAbstraction.createImplementation({\n implementation: CmsFormModelBuilderImpl,\n dependencies: [\n [CmsFieldTypeMapper, { multiple: true, optional: true }],\n [CmsFieldRenderer, { multiple: true, optional: true }]\n ]\n});\n"],"names":["CmsFormModelBuilderImpl","customMappers","fieldRenderers","Map","mapper","createBuiltInMappers","renderer","model","context","field","registry","idToFieldId","fieldIdsInLayout","collectFieldIds","result","builder","layout","mapCmsLayout","undefined","modelField","applyFieldProps","process","console","_renderer","rest","CmsFormModelBuilder","BuilderAbstraction","CmsFieldTypeMapper","CmsFieldRenderer"],"mappings":"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"}
|
|
@@ -107,5 +107,146 @@ describe("CmsFormModelBuilder renderer cardinality", ()=>{
|
|
|
107
107
|
expect(item.children.get("openTime").vm.renderer).toBe("dateTimeInput");
|
|
108
108
|
});
|
|
109
109
|
});
|
|
110
|
+
const rowNames = (layout)=>layout.map((row)=>row.fields.map((f)=>f.name));
|
|
111
|
+
describe("CmsFormModelBuilder nested layouts", ()=>{
|
|
112
|
+
it("lays out a single object with the layout stored on the field", ()=>{
|
|
113
|
+
const form = createCmsForm([
|
|
114
|
+
field("address", "object", false, "object-accordion", {
|
|
115
|
+
settings: {
|
|
116
|
+
fields: [
|
|
117
|
+
field("street", "text", false, "text-input"),
|
|
118
|
+
field("city", "text", false, "text-input", {
|
|
119
|
+
id: "c1ty"
|
|
120
|
+
}),
|
|
121
|
+
field("zipCode", "text", false, "text-input")
|
|
122
|
+
],
|
|
123
|
+
layout: [
|
|
124
|
+
[
|
|
125
|
+
"street"
|
|
126
|
+
],
|
|
127
|
+
[
|
|
128
|
+
"c1ty",
|
|
129
|
+
"zipCode"
|
|
130
|
+
]
|
|
131
|
+
]
|
|
132
|
+
}
|
|
133
|
+
})
|
|
134
|
+
]);
|
|
135
|
+
expect(rowNames(form.field("address").vm.layout)).toEqual([
|
|
136
|
+
[
|
|
137
|
+
"street"
|
|
138
|
+
],
|
|
139
|
+
[
|
|
140
|
+
"city",
|
|
141
|
+
"zipCode"
|
|
142
|
+
]
|
|
143
|
+
]);
|
|
144
|
+
});
|
|
145
|
+
it("lays out every item of an object list", ()=>{
|
|
146
|
+
const form = createCmsForm([
|
|
147
|
+
field("facilityStats", "object", true, "objects-accordion", {
|
|
148
|
+
settings: {
|
|
149
|
+
fields: [
|
|
150
|
+
field("statValue", "text", false, "text-input"),
|
|
151
|
+
field("statLabel", "text", false, "text-input")
|
|
152
|
+
],
|
|
153
|
+
layout: [
|
|
154
|
+
[
|
|
155
|
+
"statValue",
|
|
156
|
+
"statLabel"
|
|
157
|
+
]
|
|
158
|
+
]
|
|
159
|
+
}
|
|
160
|
+
})
|
|
161
|
+
]);
|
|
162
|
+
form.setData({
|
|
163
|
+
facilityStats: [
|
|
164
|
+
{
|
|
165
|
+
statValue: "1",
|
|
166
|
+
statLabel: "a"
|
|
167
|
+
}
|
|
168
|
+
]
|
|
169
|
+
});
|
|
170
|
+
const vm = form.field("facilityStats").vm;
|
|
171
|
+
expect(rowNames(vm.items[0].layout)).toEqual([
|
|
172
|
+
[
|
|
173
|
+
"statValue",
|
|
174
|
+
"statLabel"
|
|
175
|
+
]
|
|
176
|
+
]);
|
|
177
|
+
});
|
|
178
|
+
it("gives children missing from the stored layout a row of their own", ()=>{
|
|
179
|
+
const form = createCmsForm([
|
|
180
|
+
field("address", "object", false, "object-accordion", {
|
|
181
|
+
settings: {
|
|
182
|
+
fields: [
|
|
183
|
+
field("street", "text", false, "text-input"),
|
|
184
|
+
field("city", "text", false, "text-input"),
|
|
185
|
+
field("state", "text", false, "text-input")
|
|
186
|
+
],
|
|
187
|
+
layout: [
|
|
188
|
+
[
|
|
189
|
+
"street",
|
|
190
|
+
"city"
|
|
191
|
+
]
|
|
192
|
+
]
|
|
193
|
+
}
|
|
194
|
+
})
|
|
195
|
+
]);
|
|
196
|
+
expect(rowNames(form.field("address").vm.layout)).toEqual([
|
|
197
|
+
[
|
|
198
|
+
"street",
|
|
199
|
+
"city"
|
|
200
|
+
],
|
|
201
|
+
[
|
|
202
|
+
"state"
|
|
203
|
+
]
|
|
204
|
+
]);
|
|
205
|
+
});
|
|
206
|
+
it("lays out a dynamic zone template with the template's layout", ()=>{
|
|
207
|
+
const form = createCmsForm([
|
|
208
|
+
field("blocks", "dynamicZone", true, "dynamicZone", {
|
|
209
|
+
settings: {
|
|
210
|
+
templates: [
|
|
211
|
+
{
|
|
212
|
+
id: "hero",
|
|
213
|
+
name: "Hero",
|
|
214
|
+
gqlTypeName: "Hero",
|
|
215
|
+
description: "",
|
|
216
|
+
icon: null,
|
|
217
|
+
fields: [
|
|
218
|
+
field("title", "text", false, "text-input"),
|
|
219
|
+
field("subtitle", "text", false, "text-input")
|
|
220
|
+
],
|
|
221
|
+
layout: [
|
|
222
|
+
[
|
|
223
|
+
"title",
|
|
224
|
+
"subtitle"
|
|
225
|
+
]
|
|
226
|
+
],
|
|
227
|
+
validation: []
|
|
228
|
+
}
|
|
229
|
+
]
|
|
230
|
+
}
|
|
231
|
+
})
|
|
232
|
+
]);
|
|
233
|
+
form.setData({
|
|
234
|
+
blocks: [
|
|
235
|
+
{
|
|
236
|
+
_templateId: "hero",
|
|
237
|
+
title: "T",
|
|
238
|
+
subtitle: "S"
|
|
239
|
+
}
|
|
240
|
+
]
|
|
241
|
+
});
|
|
242
|
+
const vm = form.field("blocks").vm;
|
|
243
|
+
expect(rowNames(vm.items[0].layout)).toEqual([
|
|
244
|
+
[
|
|
245
|
+
"title",
|
|
246
|
+
"subtitle"
|
|
247
|
+
]
|
|
248
|
+
]);
|
|
249
|
+
});
|
|
250
|
+
});
|
|
110
251
|
|
|
111
252
|
//# sourceMappingURL=CmsFormModelBuilder.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/formModel/CmsFormModelBuilder.test.js","sources":["../../../src/features/formModel/CmsFormModelBuilder.test.ts"],"sourcesContent":["import { describe, it, expect } from \"vitest\";\nimport { Container } from \"@webiny/di\";\nimport { FormModelFeature } from \"@webiny/app-admin/features/formModel/feature.js\";\nimport { IdentityContextFeature } from \"@webiny/app-admin/features/security/IdentityContext/feature.js\";\nimport { FormModelFactory } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport { CmsFormModelBuilder } from \"~/features/formModel/abstractions.js\";\nimport { CmsFormModelFeature } from \"~/features/formModel/feature.js\";\nimport { DateTimeInputRenderer } from \"~/presentation/fieldTypes/renderers/dateTime/DateTimeInputRenderer.js\";\nimport { DateTimeInputsRenderer } from \"~/presentation/fieldTypes/renderers/dateTime/DateTimeInputsRenderer.js\";\nimport { TextInputRenderer } from \"~/presentation/fieldTypes/renderers/text/TextInputRenderer.js\";\nimport { TextInputsRenderer } from \"~/presentation/fieldTypes/renderers/text/TextInputsRenderer.js\";\n\nconst field = (fieldId: string, type: string, list: boolean, renderer: string, extra = {}) => ({\n id: fieldId,\n fieldId,\n type,\n label: fieldId,\n tags: [],\n list,\n renderer: { name: renderer, settings: {} },\n validation: [],\n listValidation: [],\n settings: {},\n predefinedValues: { enabled: false, values: [] },\n ...extra\n});\n\nfunction createCmsForm(fields: any[]) {\n const container = new Container();\n IdentityContextFeature.register(container);\n FormModelFeature.register(container);\n CmsFormModelFeature.register(container);\n container.register(DateTimeInputRenderer);\n container.register(DateTimeInputsRenderer);\n container.register(TextInputRenderer);\n container.register(TextInputsRenderer);\n\n const model = {\n modelId: \"test\",\n fields,\n layout: fields.map(f => [f.fieldId])\n } as any;\n const config = container.resolve(CmsFormModelBuilder).build(model);\n return container.resolve(FormModelFactory).create(config);\n}\n\ndescribe(\"CmsFormModelBuilder renderer cardinality\", () => {\n it(\"keeps renderers that match the field's cardinality\", () => {\n const form = createCmsForm([\n field(\"single\", \"datetime\", false, \"date-time-input\"),\n field(\"many\", \"datetime\", true, \"date-time-inputs\")\n ]);\n\n expect(form.field(\"single\").vm.renderer).toBe(\"dateTimeInput\");\n expect(form.field(\"many\").vm.renderer).toBe(\"dateTimeInputs\");\n });\n\n it(\"falls back to the single-value renderer when a list renderer is set on a non-list field\", () => {\n const form = createCmsForm([\n field(\"openTime\", \"datetime\", false, \"date-time-inputs\"),\n field(\"name\", \"text\", false, \"text-inputs\")\n ]);\n\n expect(form.field(\"openTime\").vm.renderer).toBe(\"dateTimeInput\");\n expect(form.field(\"name\").vm.renderer).toBe(\"textInput\");\n });\n\n it(\"keeps the list renderer for list datetime fields with a subtype\", () => {\n const form = createCmsForm(\n [\"date\", \"time\", \"dateTimeWithTimezone\", \"dateTimeWithoutTimezone\"].map(type =>\n field(type, \"datetime\", true, \"date-time-inputs\", { settings: { type } })\n )\n );\n\n expect(form.field(\"date\").vm.renderer).toBe(\"dateTimeInputs\");\n expect(form.field(\"time\").vm.renderer).toBe(\"dateTimeInputs\");\n expect(form.field(\"dateTimeWithTimezone\").vm.renderer).toBe(\"dateTimeInputs\");\n expect(form.field(\"dateTimeWithoutTimezone\").vm.renderer).toBe(\"dateTimeInputs\");\n });\n\n it(\"applies the fallback to fields nested in object lists\", () => {\n const form = createCmsForm([\n field(\"holidayHours\", \"object\", true, \"objects-accordion\", {\n settings: {\n fields: [field(\"openTime\", \"datetime\", false, \"date-time-inputs\")],\n layout: [[\"openTime\"]]\n }\n })\n ]);\n\n form.setData({ holidayHours: [{ openTime: \"2026-12-24T09:00:00.000Z\" }] });\n const item = (form.field(\"holidayHours\") as any).items[0];\n\n expect(item.children.get(\"openTime\").vm.renderer).toBe(\"dateTimeInput\");\n });\n});\n"],"names":["field","fieldId","type","list","renderer","extra","createCmsForm","fields","container","Container","IdentityContextFeature","FormModelFeature","CmsFormModelFeature","DateTimeInputRenderer","DateTimeInputsRenderer","TextInputRenderer","TextInputsRenderer","model","f","config","CmsFormModelBuilder","FormModelFactory","describe","it","form","expect","item"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"features/formModel/CmsFormModelBuilder.test.js","sources":["../../../src/features/formModel/CmsFormModelBuilder.test.ts"],"sourcesContent":["import { describe, it, expect } from \"vitest\";\nimport { Container } from \"@webiny/di\";\nimport { FormModelFeature } from \"@webiny/app-admin/features/formModel/feature.js\";\nimport { IdentityContextFeature } from \"@webiny/app-admin/features/security/IdentityContext/feature.js\";\nimport { FormModelFactory } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport { CmsFormModelBuilder } from \"~/features/formModel/abstractions.js\";\nimport { CmsFormModelFeature } from \"~/features/formModel/feature.js\";\nimport { DateTimeInputRenderer } from \"~/presentation/fieldTypes/renderers/dateTime/DateTimeInputRenderer.js\";\nimport { DateTimeInputsRenderer } from \"~/presentation/fieldTypes/renderers/dateTime/DateTimeInputsRenderer.js\";\nimport { TextInputRenderer } from \"~/presentation/fieldTypes/renderers/text/TextInputRenderer.js\";\nimport { TextInputsRenderer } from \"~/presentation/fieldTypes/renderers/text/TextInputsRenderer.js\";\n\nconst field = (fieldId: string, type: string, list: boolean, renderer: string, extra = {}) => ({\n id: fieldId,\n fieldId,\n type,\n label: fieldId,\n tags: [],\n list,\n renderer: { name: renderer, settings: {} },\n validation: [],\n listValidation: [],\n settings: {},\n predefinedValues: { enabled: false, values: [] },\n ...extra\n});\n\nfunction createCmsForm(fields: any[]) {\n const container = new Container();\n IdentityContextFeature.register(container);\n FormModelFeature.register(container);\n CmsFormModelFeature.register(container);\n container.register(DateTimeInputRenderer);\n container.register(DateTimeInputsRenderer);\n container.register(TextInputRenderer);\n container.register(TextInputsRenderer);\n\n const model = {\n modelId: \"test\",\n fields,\n layout: fields.map(f => [f.fieldId])\n } as any;\n const config = container.resolve(CmsFormModelBuilder).build(model);\n return container.resolve(FormModelFactory).create(config);\n}\n\ndescribe(\"CmsFormModelBuilder renderer cardinality\", () => {\n it(\"keeps renderers that match the field's cardinality\", () => {\n const form = createCmsForm([\n field(\"single\", \"datetime\", false, \"date-time-input\"),\n field(\"many\", \"datetime\", true, \"date-time-inputs\")\n ]);\n\n expect(form.field(\"single\").vm.renderer).toBe(\"dateTimeInput\");\n expect(form.field(\"many\").vm.renderer).toBe(\"dateTimeInputs\");\n });\n\n it(\"falls back to the single-value renderer when a list renderer is set on a non-list field\", () => {\n const form = createCmsForm([\n field(\"openTime\", \"datetime\", false, \"date-time-inputs\"),\n field(\"name\", \"text\", false, \"text-inputs\")\n ]);\n\n expect(form.field(\"openTime\").vm.renderer).toBe(\"dateTimeInput\");\n expect(form.field(\"name\").vm.renderer).toBe(\"textInput\");\n });\n\n it(\"keeps the list renderer for list datetime fields with a subtype\", () => {\n const form = createCmsForm(\n [\"date\", \"time\", \"dateTimeWithTimezone\", \"dateTimeWithoutTimezone\"].map(type =>\n field(type, \"datetime\", true, \"date-time-inputs\", { settings: { type } })\n )\n );\n\n expect(form.field(\"date\").vm.renderer).toBe(\"dateTimeInputs\");\n expect(form.field(\"time\").vm.renderer).toBe(\"dateTimeInputs\");\n expect(form.field(\"dateTimeWithTimezone\").vm.renderer).toBe(\"dateTimeInputs\");\n expect(form.field(\"dateTimeWithoutTimezone\").vm.renderer).toBe(\"dateTimeInputs\");\n });\n\n it(\"applies the fallback to fields nested in object lists\", () => {\n const form = createCmsForm([\n field(\"holidayHours\", \"object\", true, \"objects-accordion\", {\n settings: {\n fields: [field(\"openTime\", \"datetime\", false, \"date-time-inputs\")],\n layout: [[\"openTime\"]]\n }\n })\n ]);\n\n form.setData({ holidayHours: [{ openTime: \"2026-12-24T09:00:00.000Z\" }] });\n const item = (form.field(\"holidayHours\") as any).items[0];\n\n expect(item.children.get(\"openTime\").vm.renderer).toBe(\"dateTimeInput\");\n });\n});\n\nconst rowNames = (layout: any[]) => layout.map(row => row.fields.map((f: any) => f.name));\n\ndescribe(\"CmsFormModelBuilder nested layouts\", () => {\n it(\"lays out a single object with the layout stored on the field\", () => {\n const form = createCmsForm([\n field(\"address\", \"object\", false, \"object-accordion\", {\n settings: {\n fields: [\n field(\"street\", \"text\", false, \"text-input\"),\n // Fields created in the model editor have an `id` that differs from `fieldId`.\n field(\"city\", \"text\", false, \"text-input\", { id: \"c1ty\" }),\n field(\"zipCode\", \"text\", false, \"text-input\")\n ],\n layout: [[\"street\"], [\"c1ty\", \"zipCode\"]]\n }\n })\n ]);\n\n expect(rowNames((form.field(\"address\").vm as any).layout)).toEqual([\n [\"street\"],\n [\"city\", \"zipCode\"]\n ]);\n });\n\n it(\"lays out every item of an object list\", () => {\n const form = createCmsForm([\n field(\"facilityStats\", \"object\", true, \"objects-accordion\", {\n settings: {\n fields: [\n field(\"statValue\", \"text\", false, \"text-input\"),\n field(\"statLabel\", \"text\", false, \"text-input\")\n ],\n layout: [[\"statValue\", \"statLabel\"]]\n }\n })\n ]);\n\n form.setData({ facilityStats: [{ statValue: \"1\", statLabel: \"a\" }] });\n const vm = form.field(\"facilityStats\").vm as any;\n\n expect(rowNames(vm.items[0].layout)).toEqual([[\"statValue\", \"statLabel\"]]);\n });\n\n it(\"gives children missing from the stored layout a row of their own\", () => {\n const form = createCmsForm([\n field(\"address\", \"object\", false, \"object-accordion\", {\n settings: {\n fields: [\n field(\"street\", \"text\", false, \"text-input\"),\n field(\"city\", \"text\", false, \"text-input\"),\n field(\"state\", \"text\", false, \"text-input\")\n ],\n layout: [[\"street\", \"city\"]]\n }\n })\n ]);\n\n expect(rowNames((form.field(\"address\").vm as any).layout)).toEqual([\n [\"street\", \"city\"],\n [\"state\"]\n ]);\n });\n\n it(\"lays out a dynamic zone template with the template's layout\", () => {\n const form = createCmsForm([\n field(\"blocks\", \"dynamicZone\", true, \"dynamicZone\", {\n settings: {\n templates: [\n {\n id: \"hero\",\n name: \"Hero\",\n gqlTypeName: \"Hero\",\n description: \"\",\n icon: null,\n fields: [\n field(\"title\", \"text\", false, \"text-input\"),\n field(\"subtitle\", \"text\", false, \"text-input\")\n ],\n layout: [[\"title\", \"subtitle\"]],\n validation: []\n }\n ]\n }\n })\n ]);\n\n form.setData({ blocks: [{ _templateId: \"hero\", title: \"T\", subtitle: \"S\" }] });\n const vm = form.field(\"blocks\").vm as any;\n\n expect(rowNames(vm.items[0].layout)).toEqual([[\"title\", \"subtitle\"]]);\n });\n});\n"],"names":["field","fieldId","type","list","renderer","extra","createCmsForm","fields","container","Container","IdentityContextFeature","FormModelFeature","CmsFormModelFeature","DateTimeInputRenderer","DateTimeInputsRenderer","TextInputRenderer","TextInputsRenderer","model","f","config","CmsFormModelBuilder","FormModelFactory","describe","it","form","expect","item","rowNames","layout","row","vm"],"mappings":"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"}
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
import { type CmsEditorFieldsLayout } from "../../types.js";
|
|
1
|
+
import { type CmsEditorFieldsLayout, type CmsModelField } from "../../types.js";
|
|
2
2
|
import type { ILayoutBuilder, ILayoutNodeBuilder } from "@webiny/app-admin/features/formModel/abstractions.js";
|
|
3
3
|
export declare function mapCmsLayout(cmsLayout: CmsEditorFieldsLayout, layoutBuilder: ILayoutBuilder, idToFieldId: Map<string, string>): ILayoutNodeBuilder[];
|
|
4
|
+
export declare function collectFieldIds(layout: CmsEditorFieldsLayout, idToFieldId: Map<string, string>): Set<string>;
|
|
5
|
+
/**
|
|
6
|
+
* Maps the layout stored on an object field or a dynamic zone template. Returns `undefined`
|
|
7
|
+
* when there is no layout, so the form falls back to one row per child. Children missing
|
|
8
|
+
* from the layout get a row of their own at the end, so a stale layout can't hide them.
|
|
9
|
+
*/
|
|
10
|
+
export declare function mapCmsNestedLayout(cmsLayout: CmsEditorFieldsLayout | undefined, fields: CmsModelField[]): ((layoutBuilder: ILayoutBuilder) => ILayoutNodeBuilder[]) | undefined;
|
|
@@ -19,6 +19,28 @@ function mapCmsLayout(cmsLayout, layoutBuilder, idToFieldId) {
|
|
|
19
19
|
}
|
|
20
20
|
return nodes;
|
|
21
21
|
}
|
|
22
|
+
function collectFieldIds(layout, idToFieldId) {
|
|
23
|
+
const fieldIds = new Set();
|
|
24
|
+
for (const row of layout)for (const cell of row)if ("string" == typeof cell) {
|
|
25
|
+
const fieldId = idToFieldId.get(cell);
|
|
26
|
+
if (fieldId) fieldIds.add(fieldId);
|
|
27
|
+
} else if (isLayoutField(cell) && "tabs" === cell.type) {
|
|
28
|
+
const tabsField = cell;
|
|
29
|
+
for (const tab of tabsField.tabs)for (const id of collectFieldIds(tab.layout, idToFieldId))fieldIds.add(id);
|
|
30
|
+
}
|
|
31
|
+
return fieldIds;
|
|
32
|
+
}
|
|
33
|
+
function mapCmsNestedLayout(cmsLayout, fields) {
|
|
34
|
+
if (!cmsLayout || 0 === cmsLayout.length) return;
|
|
35
|
+
const idToFieldId = new Map();
|
|
36
|
+
for (const field of fields)idToFieldId.set(field.id, field.fieldId);
|
|
37
|
+
const fieldIdsInLayout = collectFieldIds(cmsLayout, idToFieldId);
|
|
38
|
+
return (layoutBuilder)=>{
|
|
39
|
+
const nodes = mapCmsLayout(cmsLayout, layoutBuilder, idToFieldId);
|
|
40
|
+
for (const field of fields)if (!fieldIdsInLayout.has(field.fieldId)) nodes.push(layoutBuilder.row(field.fieldId));
|
|
41
|
+
return nodes;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
22
44
|
function mapLayoutField(field, layoutBuilder, idToFieldId) {
|
|
23
45
|
switch(field.type){
|
|
24
46
|
case "separator":
|
|
@@ -83,6 +105,6 @@ function mapAlert(field, layoutBuilder) {
|
|
|
83
105
|
})));
|
|
84
106
|
return builder;
|
|
85
107
|
}
|
|
86
|
-
export { mapCmsLayout };
|
|
108
|
+
export { collectFieldIds, mapCmsLayout, mapCmsNestedLayout };
|
|
87
109
|
|
|
88
110
|
//# sourceMappingURL=CmsLayoutMapper.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/formModel/CmsLayoutMapper.js","sources":["../../../src/features/formModel/CmsLayoutMapper.ts"],"sourcesContent":["import {\n isLayoutField,\n type CmsEditorFieldsLayout,\n type CmsLayoutField,\n type CmsSeparatorLayoutField,\n type CmsTabLayoutField,\n type CmsAlertLayoutField\n} from \"~/types.js\";\nimport type {\n ILayoutBuilder,\n ILayoutNodeBuilder\n} from \"@webiny/app-admin/features/formModel/abstractions.js\";\n\nexport function mapCmsLayout(\n cmsLayout: CmsEditorFieldsLayout,\n layoutBuilder: ILayoutBuilder,\n idToFieldId: Map<string, string>\n): ILayoutNodeBuilder[] {\n const nodes: ILayoutNodeBuilder[] = [];\n\n for (const row of cmsLayout) {\n if (row.length === 0) {\n continue;\n }\n\n const firstCell = row[0];\n\n if (row.length === 1 && isLayoutField(firstCell)) {\n const layoutField = firstCell as CmsLayoutField;\n const node = mapLayoutField(layoutField, layoutBuilder, idToFieldId);\n if (node) {\n nodes.push(node);\n }\n continue;\n }\n\n const fieldIds: string[] = [];\n for (const cell of row) {\n if (typeof cell === \"string\") {\n const fieldId = idToFieldId.get(cell);\n if (fieldId) {\n fieldIds.push(fieldId);\n }\n }\n }\n\n if (fieldIds.length > 0) {\n nodes.push(layoutBuilder.row(...fieldIds));\n }\n }\n\n return nodes;\n}\n\nfunction mapLayoutField(\n field: CmsLayoutField,\n layoutBuilder: ILayoutBuilder,\n idToFieldId: Map<string, string>\n): ILayoutNodeBuilder | null {\n switch (field.type) {\n case \"separator\":\n return mapSeparator(field as CmsSeparatorLayoutField, layoutBuilder);\n\n case \"tabs\":\n return mapTabs(field as CmsTabLayoutField, layoutBuilder, idToFieldId);\n\n case \"alert\":\n return mapAlert(field as CmsAlertLayoutField, layoutBuilder);\n\n default:\n return null;\n }\n}\n\nfunction mapSeparator(\n field: CmsSeparatorLayoutField,\n layoutBuilder: ILayoutBuilder\n): ILayoutNodeBuilder {\n const builder = layoutBuilder.separator();\n if (field.label) {\n builder.title(field.label);\n }\n if (field.description) {\n builder.description(field.description);\n }\n if (field.rules) {\n builder.rules(\n field.rules.map(r => ({\n type: r.type,\n target: r.target,\n operator: r.operator,\n value: r.value ?? null,\n action: r.action as \"hide\" | \"disable\"\n }))\n );\n }\n return builder;\n}\n\nfunction mapTabs(\n field: CmsTabLayoutField,\n layoutBuilder: ILayoutBuilder,\n idToFieldId: Map<string, string>\n): ILayoutNodeBuilder {\n const tabsBuilder = layoutBuilder.tabs(field.id);\n\n for (const tab of field.tabs) {\n tabsBuilder.tab(tab.id, t => {\n t.label(tab.label);\n if (tab.icon) {\n t.icon({ type: \"icon\", name: tab.icon });\n }\n t.layout(l => mapCmsLayout(tab.layout, l, idToFieldId));\n if (tab.rules) {\n t.rules(\n tab.rules.map(r => ({\n type: r.type,\n target: r.target,\n operator: r.operator,\n value: r.value ?? null,\n action: r.action as \"hide\" | \"disable\"\n }))\n );\n }\n });\n }\n\n if (field.rules) {\n tabsBuilder.rules(\n field.rules.map(r => ({\n type: r.type,\n target: r.target,\n operator: r.operator,\n value: r.value ?? null,\n action: r.action as \"hide\" | \"disable\"\n }))\n );\n }\n\n return tabsBuilder;\n}\n\nfunction mapAlert(field: CmsAlertLayoutField, layoutBuilder: ILayoutBuilder): ILayoutNodeBuilder {\n const builder = layoutBuilder.alert();\n if (field.label) {\n builder.message(field.label);\n }\n if (field.alertType) {\n builder.alertType(field.alertType);\n }\n if (field.rules) {\n builder.rules(\n field.rules.map(r => ({\n type: r.type,\n target: r.target,\n operator: r.operator,\n value: r.value ?? null,\n action: r.action as \"hide\" | \"disable\"\n }))\n );\n }\n return builder;\n}\n"],"names":["mapCmsLayout","cmsLayout","layoutBuilder","idToFieldId","nodes","row","firstCell","isLayoutField","layoutField","node","mapLayoutField","fieldIds","cell","fieldId","field","mapSeparator","mapTabs","mapAlert","builder","r","tabsBuilder","tab","t","l"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"features/formModel/CmsLayoutMapper.js","sources":["../../../src/features/formModel/CmsLayoutMapper.ts"],"sourcesContent":["import {\n isLayoutField,\n type CmsEditorFieldsLayout,\n type CmsLayoutField,\n type CmsModelField,\n type CmsSeparatorLayoutField,\n type CmsTabLayoutField,\n type CmsAlertLayoutField\n} from \"~/types.js\";\nimport type {\n ILayoutBuilder,\n ILayoutNodeBuilder\n} from \"@webiny/app-admin/features/formModel/abstractions.js\";\n\nexport function mapCmsLayout(\n cmsLayout: CmsEditorFieldsLayout,\n layoutBuilder: ILayoutBuilder,\n idToFieldId: Map<string, string>\n): ILayoutNodeBuilder[] {\n const nodes: ILayoutNodeBuilder[] = [];\n\n for (const row of cmsLayout) {\n if (row.length === 0) {\n continue;\n }\n\n const firstCell = row[0];\n\n if (row.length === 1 && isLayoutField(firstCell)) {\n const layoutField = firstCell as CmsLayoutField;\n const node = mapLayoutField(layoutField, layoutBuilder, idToFieldId);\n if (node) {\n nodes.push(node);\n }\n continue;\n }\n\n const fieldIds: string[] = [];\n for (const cell of row) {\n if (typeof cell === \"string\") {\n const fieldId = idToFieldId.get(cell);\n if (fieldId) {\n fieldIds.push(fieldId);\n }\n }\n }\n\n if (fieldIds.length > 0) {\n nodes.push(layoutBuilder.row(...fieldIds));\n }\n }\n\n return nodes;\n}\n\nexport function collectFieldIds(\n layout: CmsEditorFieldsLayout,\n idToFieldId: Map<string, string>\n): Set<string> {\n const fieldIds = new Set<string>();\n\n for (const row of layout) {\n for (const cell of row) {\n if (typeof cell === \"string\") {\n const fieldId = idToFieldId.get(cell);\n if (fieldId) {\n fieldIds.add(fieldId);\n }\n } else if (isLayoutField(cell) && cell.type === \"tabs\") {\n const tabsField = cell as { tabs: Array<{ layout: CmsEditorFieldsLayout }> };\n for (const tab of tabsField.tabs) {\n for (const id of collectFieldIds(tab.layout, idToFieldId)) {\n fieldIds.add(id);\n }\n }\n }\n }\n }\n\n return fieldIds;\n}\n\n/**\n * Maps the layout stored on an object field or a dynamic zone template. Returns `undefined`\n * when there is no layout, so the form falls back to one row per child. Children missing\n * from the layout get a row of their own at the end, so a stale layout can't hide them.\n */\nexport function mapCmsNestedLayout(\n cmsLayout: CmsEditorFieldsLayout | undefined,\n fields: CmsModelField[]\n): ((layoutBuilder: ILayoutBuilder) => ILayoutNodeBuilder[]) | undefined {\n if (!cmsLayout || cmsLayout.length === 0) {\n return undefined;\n }\n\n const idToFieldId = new Map<string, string>();\n for (const field of fields) {\n idToFieldId.set(field.id, field.fieldId);\n }\n\n const fieldIdsInLayout = collectFieldIds(cmsLayout, idToFieldId);\n\n return layoutBuilder => {\n const nodes = mapCmsLayout(cmsLayout, layoutBuilder, idToFieldId);\n for (const field of fields) {\n if (!fieldIdsInLayout.has(field.fieldId)) {\n nodes.push(layoutBuilder.row(field.fieldId));\n }\n }\n return nodes;\n };\n}\n\nfunction mapLayoutField(\n field: CmsLayoutField,\n layoutBuilder: ILayoutBuilder,\n idToFieldId: Map<string, string>\n): ILayoutNodeBuilder | null {\n switch (field.type) {\n case \"separator\":\n return mapSeparator(field as CmsSeparatorLayoutField, layoutBuilder);\n\n case \"tabs\":\n return mapTabs(field as CmsTabLayoutField, layoutBuilder, idToFieldId);\n\n case \"alert\":\n return mapAlert(field as CmsAlertLayoutField, layoutBuilder);\n\n default:\n return null;\n }\n}\n\nfunction mapSeparator(\n field: CmsSeparatorLayoutField,\n layoutBuilder: ILayoutBuilder\n): ILayoutNodeBuilder {\n const builder = layoutBuilder.separator();\n if (field.label) {\n builder.title(field.label);\n }\n if (field.description) {\n builder.description(field.description);\n }\n if (field.rules) {\n builder.rules(\n field.rules.map(r => ({\n type: r.type,\n target: r.target,\n operator: r.operator,\n value: r.value ?? null,\n action: r.action as \"hide\" | \"disable\"\n }))\n );\n }\n return builder;\n}\n\nfunction mapTabs(\n field: CmsTabLayoutField,\n layoutBuilder: ILayoutBuilder,\n idToFieldId: Map<string, string>\n): ILayoutNodeBuilder {\n const tabsBuilder = layoutBuilder.tabs(field.id);\n\n for (const tab of field.tabs) {\n tabsBuilder.tab(tab.id, t => {\n t.label(tab.label);\n if (tab.icon) {\n t.icon({ type: \"icon\", name: tab.icon });\n }\n t.layout(l => mapCmsLayout(tab.layout, l, idToFieldId));\n if (tab.rules) {\n t.rules(\n tab.rules.map(r => ({\n type: r.type,\n target: r.target,\n operator: r.operator,\n value: r.value ?? null,\n action: r.action as \"hide\" | \"disable\"\n }))\n );\n }\n });\n }\n\n if (field.rules) {\n tabsBuilder.rules(\n field.rules.map(r => ({\n type: r.type,\n target: r.target,\n operator: r.operator,\n value: r.value ?? null,\n action: r.action as \"hide\" | \"disable\"\n }))\n );\n }\n\n return tabsBuilder;\n}\n\nfunction mapAlert(field: CmsAlertLayoutField, layoutBuilder: ILayoutBuilder): ILayoutNodeBuilder {\n const builder = layoutBuilder.alert();\n if (field.label) {\n builder.message(field.label);\n }\n if (field.alertType) {\n builder.alertType(field.alertType);\n }\n if (field.rules) {\n builder.rules(\n field.rules.map(r => ({\n type: r.type,\n target: r.target,\n operator: r.operator,\n value: r.value ?? null,\n action: r.action as \"hide\" | \"disable\"\n }))\n );\n }\n return builder;\n}\n"],"names":["mapCmsLayout","cmsLayout","layoutBuilder","idToFieldId","nodes","row","firstCell","isLayoutField","layoutField","node","mapLayoutField","fieldIds","cell","fieldId","collectFieldIds","layout","Set","tabsField","tab","id","mapCmsNestedLayout","fields","Map","field","fieldIdsInLayout","mapSeparator","mapTabs","mapAlert","builder","r","tabsBuilder","t","l"],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { applyFieldProps } from "./applyFieldProps.js";
|
|
2
|
+
import { mapCmsNestedLayout } from "../CmsLayoutMapper.js";
|
|
2
3
|
import { generateAlphaNumericLowerCaseId } from "@webiny/utils/generateId";
|
|
3
4
|
class DynamicZoneFieldMapper {
|
|
4
5
|
map(field, registry, context) {
|
|
@@ -21,6 +22,8 @@ class DynamicZoneFieldMapper {
|
|
|
21
22
|
if (template.fields && template.fields.length > 0) for (const child of template.fields)result[child.fieldId] = context.mapField(child, childRegistry);
|
|
22
23
|
return result;
|
|
23
24
|
});
|
|
25
|
+
const layout = mapCmsNestedLayout(template.layout, template.fields ?? []);
|
|
26
|
+
if (layout) t.layout(layout);
|
|
24
27
|
});
|
|
25
28
|
return applyFieldProps(builder, field, context.rendererMap);
|
|
26
29
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/formModel/mappers/DynamicZoneFieldMapper.js","sources":["../../../../src/features/formModel/mappers/DynamicZoneFieldMapper.ts"],"sourcesContent":["import type { ICmsFieldTypeMapper, ICmsFieldMapperContext } from \"../abstractions.js\";\nimport type {\n IFieldBuilder,\n IFieldBuilderRegistry,\n IObjectFieldBuilder\n} from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport type { CmsModelField, CmsDynamicZoneTemplate } from \"~/types.js\";\nimport { applyFieldProps } from \"./applyFieldProps.js\";\nimport type { ITemplateIcon } from \"@webiny/app-admin/features/formModel/index.js\";\nimport { generateAlphaNumericLowerCaseId } from \"@webiny/utils/generateId\";\n\nexport class DynamicZoneFieldMapper implements ICmsFieldTypeMapper {\n readonly type = \"dynamicZone\";\n\n map(\n field: CmsModelField,\n registry: IFieldBuilderRegistry,\n context: ICmsFieldMapperContext\n ): IFieldBuilder {\n const builder = registry.object() as IObjectFieldBuilder;\n\n const templates = field.settings?.templates as CmsDynamicZoneTemplate[] | undefined;\n if (templates) {\n for (const template of templates) {\n builder.template(template.id, t => {\n t.label(template.name);\n if (template.description) {\n t.description(template.description);\n }\n if (template.icon) {\n const icon = template.icon;\n if (typeof icon === \"object\" && \"name\" in icon) {\n t.icon(icon as ITemplateIcon);\n } else if (typeof icon === \"string\") {\n t.icon({ type: \"icon\", name: icon });\n }\n }\n t.fields(childRegistry => {\n const result: Record<string, IFieldBuilder> = {};\n result[\"_id\"] = childRegistry\n .text()\n .hidden()\n .defaultValue(() => generateAlphaNumericLowerCaseId(12))\n .cloneValue(() => generateAlphaNumericLowerCaseId(12));\n if (template.fields && template.fields.length > 0) {\n for (const child of template.fields) {\n result[child.fieldId] = context.mapField(child, childRegistry);\n }\n }\n return result;\n });\n });\n }\n }\n\n return applyFieldProps(builder, field, context.rendererMap);\n }\n}\n"],"names":["DynamicZoneFieldMapper","field","registry","context","builder","templates","template","t","icon","childRegistry","result","generateAlphaNumericLowerCaseId","child","applyFieldProps"],"mappings":"
|
|
1
|
+
{"version":3,"file":"features/formModel/mappers/DynamicZoneFieldMapper.js","sources":["../../../../src/features/formModel/mappers/DynamicZoneFieldMapper.ts"],"sourcesContent":["import type { ICmsFieldTypeMapper, ICmsFieldMapperContext } from \"../abstractions.js\";\nimport type {\n IFieldBuilder,\n IFieldBuilderRegistry,\n IObjectFieldBuilder\n} from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport type { CmsModelField, CmsDynamicZoneTemplate } from \"~/types.js\";\nimport { applyFieldProps } from \"./applyFieldProps.js\";\nimport { mapCmsNestedLayout } from \"../CmsLayoutMapper.js\";\nimport type { ITemplateIcon } from \"@webiny/app-admin/features/formModel/index.js\";\nimport { generateAlphaNumericLowerCaseId } from \"@webiny/utils/generateId\";\n\nexport class DynamicZoneFieldMapper implements ICmsFieldTypeMapper {\n readonly type = \"dynamicZone\";\n\n map(\n field: CmsModelField,\n registry: IFieldBuilderRegistry,\n context: ICmsFieldMapperContext\n ): IFieldBuilder {\n const builder = registry.object() as IObjectFieldBuilder;\n\n const templates = field.settings?.templates as CmsDynamicZoneTemplate[] | undefined;\n if (templates) {\n for (const template of templates) {\n builder.template(template.id, t => {\n t.label(template.name);\n if (template.description) {\n t.description(template.description);\n }\n if (template.icon) {\n const icon = template.icon;\n if (typeof icon === \"object\" && \"name\" in icon) {\n t.icon(icon as ITemplateIcon);\n } else if (typeof icon === \"string\") {\n t.icon({ type: \"icon\", name: icon });\n }\n }\n t.fields(childRegistry => {\n const result: Record<string, IFieldBuilder> = {};\n result[\"_id\"] = childRegistry\n .text()\n .hidden()\n .defaultValue(() => generateAlphaNumericLowerCaseId(12))\n .cloneValue(() => generateAlphaNumericLowerCaseId(12));\n if (template.fields && template.fields.length > 0) {\n for (const child of template.fields) {\n result[child.fieldId] = context.mapField(child, childRegistry);\n }\n }\n return result;\n });\n const layout = mapCmsNestedLayout(template.layout, template.fields ?? []);\n if (layout) {\n t.layout(layout);\n }\n });\n }\n }\n\n return applyFieldProps(builder, field, context.rendererMap);\n }\n}\n"],"names":["DynamicZoneFieldMapper","field","registry","context","builder","templates","template","t","icon","childRegistry","result","generateAlphaNumericLowerCaseId","child","layout","mapCmsNestedLayout","applyFieldProps"],"mappings":";;;AAYO,MAAMA;IAGT,IACIC,KAAoB,EACpBC,QAA+B,EAC/BC,OAA+B,EAClB;QACb,MAAMC,UAAUF,SAAS,MAAM;QAE/B,MAAMG,YAAYJ,MAAM,QAAQ,EAAE;QAClC,IAAII,WACA,KAAK,MAAMC,YAAYD,UACnBD,QAAQ,QAAQ,CAACE,SAAS,EAAE,EAAEC,CAAAA;YAC1BA,EAAE,KAAK,CAACD,SAAS,IAAI;YACrB,IAAIA,SAAS,WAAW,EACpBC,EAAE,WAAW,CAACD,SAAS,WAAW;YAEtC,IAAIA,SAAS,IAAI,EAAE;gBACf,MAAME,OAAOF,SAAS,IAAI;gBAC1B,IAAI,AAAgB,YAAhB,OAAOE,QAAqB,UAAUA,MACtCD,EAAE,IAAI,CAACC;qBACJ,IAAI,AAAgB,YAAhB,OAAOA,MACdD,EAAE,IAAI,CAAC;oBAAE,MAAM;oBAAQ,MAAMC;gBAAK;YAE1C;YACAD,EAAE,MAAM,CAACE,CAAAA;gBACL,MAAMC,SAAwC,CAAC;gBAC/CA,MAAM,CAAC,MAAM,GAAGD,cACX,IAAI,GACJ,MAAM,GACN,YAAY,CAAC,IAAME,gCAAgC,KACnD,UAAU,CAAC,IAAMA,gCAAgC;gBACtD,IAAIL,SAAS,MAAM,IAAIA,SAAS,MAAM,CAAC,MAAM,GAAG,GAC5C,KAAK,MAAMM,SAASN,SAAS,MAAM,CAC/BI,MAAM,CAACE,MAAM,OAAO,CAAC,GAAGT,QAAQ,QAAQ,CAACS,OAAOH;gBAGxD,OAAOC;YACX;YACA,MAAMG,SAASC,mBAAmBR,SAAS,MAAM,EAAEA,SAAS,MAAM,IAAI,EAAE;YACxE,IAAIO,QACAN,EAAE,MAAM,CAACM;QAEjB;QAIR,OAAOE,gBAAgBX,SAASH,OAAOE,QAAQ,WAAW;IAC9D;;aAhDS,IAAI,GAAG;;AAiDpB"}
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import { applyFieldProps } from "./applyFieldProps.js";
|
|
2
|
+
import { mapCmsNestedLayout } from "../CmsLayoutMapper.js";
|
|
2
3
|
import { generateAlphaNumericLowerCaseId } from "@webiny/utils/generateId";
|
|
3
4
|
class ObjectFieldMapper {
|
|
4
5
|
map(field, registry, context) {
|
|
5
6
|
const builder = registry.object();
|
|
6
7
|
const childFields = field.settings?.fields;
|
|
7
|
-
if (childFields && childFields.length > 0)
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
if (childFields && childFields.length > 0) {
|
|
9
|
+
builder.fields((childRegistry)=>{
|
|
10
|
+
const result = {};
|
|
11
|
+
result["_id"] = childRegistry.text().hidden().defaultValue(()=>generateAlphaNumericLowerCaseId(12)).cloneValue(()=>generateAlphaNumericLowerCaseId(12));
|
|
12
|
+
for (const child of childFields)result[child.fieldId] = context.mapField(child, childRegistry);
|
|
13
|
+
return result;
|
|
14
|
+
});
|
|
15
|
+
const layout = mapCmsNestedLayout(field.settings?.layout, childFields);
|
|
16
|
+
if (layout) builder.layout(layout);
|
|
17
|
+
}
|
|
13
18
|
return applyFieldProps(builder, field, context.rendererMap);
|
|
14
19
|
}
|
|
15
20
|
constructor(){
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/formModel/mappers/ObjectFieldMapper.js","sources":["../../../../src/features/formModel/mappers/ObjectFieldMapper.ts"],"sourcesContent":["import type { ICmsFieldTypeMapper, ICmsFieldMapperContext } from \"../abstractions.js\";\nimport type {\n IFieldBuilder,\n IFieldBuilderRegistry,\n IObjectFieldBuilder\n} from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport type { CmsModelField } from \"~/types.js\";\nimport { applyFieldProps } from \"./applyFieldProps.js\";\nimport { generateAlphaNumericLowerCaseId } from \"@webiny/utils/generateId\";\n\nexport class ObjectFieldMapper implements ICmsFieldTypeMapper {\n readonly type = \"object\";\n\n map(\n field: CmsModelField,\n registry: IFieldBuilderRegistry,\n context: ICmsFieldMapperContext\n ): IFieldBuilder {\n const builder = registry.object() as IObjectFieldBuilder;\n\n const childFields = field.settings?.fields;\n if (childFields && childFields.length > 0) {\n builder.fields(childRegistry => {\n const result: Record<string, IFieldBuilder> = {};\n result[\"_id\"] = childRegistry\n .text()\n .hidden()\n .defaultValue(() => generateAlphaNumericLowerCaseId(12))\n .cloneValue(() => generateAlphaNumericLowerCaseId(12));\n for (const child of childFields) {\n result[child.fieldId] = context.mapField(child, childRegistry);\n }\n return result;\n });\n }\n\n return applyFieldProps(builder, field, context.rendererMap);\n }\n}\n"],"names":["ObjectFieldMapper","field","registry","context","builder","childFields","childRegistry","result","generateAlphaNumericLowerCaseId","child","applyFieldProps"],"mappings":"
|
|
1
|
+
{"version":3,"file":"features/formModel/mappers/ObjectFieldMapper.js","sources":["../../../../src/features/formModel/mappers/ObjectFieldMapper.ts"],"sourcesContent":["import type { ICmsFieldTypeMapper, ICmsFieldMapperContext } from \"../abstractions.js\";\nimport type {\n IFieldBuilder,\n IFieldBuilderRegistry,\n IObjectFieldBuilder\n} from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport type { CmsModelField } from \"~/types.js\";\nimport { applyFieldProps } from \"./applyFieldProps.js\";\nimport { mapCmsNestedLayout } from \"../CmsLayoutMapper.js\";\nimport { generateAlphaNumericLowerCaseId } from \"@webiny/utils/generateId\";\n\nexport class ObjectFieldMapper implements ICmsFieldTypeMapper {\n readonly type = \"object\";\n\n map(\n field: CmsModelField,\n registry: IFieldBuilderRegistry,\n context: ICmsFieldMapperContext\n ): IFieldBuilder {\n const builder = registry.object() as IObjectFieldBuilder;\n\n const childFields = field.settings?.fields;\n if (childFields && childFields.length > 0) {\n builder.fields(childRegistry => {\n const result: Record<string, IFieldBuilder> = {};\n result[\"_id\"] = childRegistry\n .text()\n .hidden()\n .defaultValue(() => generateAlphaNumericLowerCaseId(12))\n .cloneValue(() => generateAlphaNumericLowerCaseId(12));\n for (const child of childFields) {\n result[child.fieldId] = context.mapField(child, childRegistry);\n }\n return result;\n });\n\n const layout = mapCmsNestedLayout(field.settings?.layout, childFields);\n if (layout) {\n builder.layout(layout);\n }\n }\n\n return applyFieldProps(builder, field, context.rendererMap);\n }\n}\n"],"names":["ObjectFieldMapper","field","registry","context","builder","childFields","childRegistry","result","generateAlphaNumericLowerCaseId","child","layout","mapCmsNestedLayout","applyFieldProps"],"mappings":";;;AAWO,MAAMA;IAGT,IACIC,KAAoB,EACpBC,QAA+B,EAC/BC,OAA+B,EAClB;QACb,MAAMC,UAAUF,SAAS,MAAM;QAE/B,MAAMG,cAAcJ,MAAM,QAAQ,EAAE;QACpC,IAAII,eAAeA,YAAY,MAAM,GAAG,GAAG;YACvCD,QAAQ,MAAM,CAACE,CAAAA;gBACX,MAAMC,SAAwC,CAAC;gBAC/CA,MAAM,CAAC,MAAM,GAAGD,cACX,IAAI,GACJ,MAAM,GACN,YAAY,CAAC,IAAME,gCAAgC,KACnD,UAAU,CAAC,IAAMA,gCAAgC;gBACtD,KAAK,MAAMC,SAASJ,YAChBE,MAAM,CAACE,MAAM,OAAO,CAAC,GAAGN,QAAQ,QAAQ,CAACM,OAAOH;gBAEpD,OAAOC;YACX;YAEA,MAAMG,SAASC,mBAAmBV,MAAM,QAAQ,EAAE,QAAQI;YAC1D,IAAIK,QACAN,QAAQ,MAAM,CAACM;QAEvB;QAEA,OAAOE,gBAAgBR,SAASH,OAAOE,QAAQ,WAAW;IAC9D;;aA/BS,IAAI,GAAG;;AAgCpB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webiny/app-headless-cms",
|
|
3
|
-
"version": "6.5.0-beta.
|
|
3
|
+
"version": "6.5.0-beta.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./index.js",
|
|
@@ -28,25 +28,25 @@
|
|
|
28
28
|
"@fortawesome/react-fontawesome": "3.5.0",
|
|
29
29
|
"@lexical/utils": "0.51.0",
|
|
30
30
|
"@types/react": "18.3.31",
|
|
31
|
-
"@webiny/admin-ui": "6.5.0-beta.
|
|
32
|
-
"@webiny/app": "6.5.0-beta.
|
|
33
|
-
"@webiny/app-aco": "6.5.0-beta.
|
|
34
|
-
"@webiny/app-admin": "6.5.0-beta.
|
|
35
|
-
"@webiny/app-graphql-playground": "6.5.0-beta.
|
|
36
|
-
"@webiny/app-headless-cms-common": "6.5.0-beta.
|
|
37
|
-
"@webiny/cms-sdk": "6.5.0-beta.
|
|
31
|
+
"@webiny/admin-ui": "6.5.0-beta.6",
|
|
32
|
+
"@webiny/app": "6.5.0-beta.6",
|
|
33
|
+
"@webiny/app-aco": "6.5.0-beta.6",
|
|
34
|
+
"@webiny/app-admin": "6.5.0-beta.6",
|
|
35
|
+
"@webiny/app-graphql-playground": "6.5.0-beta.6",
|
|
36
|
+
"@webiny/app-headless-cms-common": "6.5.0-beta.6",
|
|
37
|
+
"@webiny/cms-sdk": "6.5.0-beta.6",
|
|
38
38
|
"@webiny/di": "1.1.0",
|
|
39
|
-
"@webiny/feature": "6.5.0-beta.
|
|
40
|
-
"@webiny/form": "6.5.0-beta.
|
|
41
|
-
"@webiny/frontend-settings": "6.5.0-beta.
|
|
42
|
-
"@webiny/icons": "6.5.0-beta.
|
|
43
|
-
"@webiny/lexical-editor": "6.5.0-beta.
|
|
44
|
-
"@webiny/lexical-nodes": "6.5.0-beta.
|
|
45
|
-
"@webiny/plugins": "6.5.0-beta.
|
|
46
|
-
"@webiny/react-composition": "6.5.0-beta.
|
|
47
|
-
"@webiny/react-properties": "6.5.0-beta.
|
|
48
|
-
"@webiny/utils": "6.5.0-beta.
|
|
49
|
-
"@webiny/validation": "6.5.0-beta.
|
|
39
|
+
"@webiny/feature": "6.5.0-beta.6",
|
|
40
|
+
"@webiny/form": "6.5.0-beta.6",
|
|
41
|
+
"@webiny/frontend-settings": "6.5.0-beta.6",
|
|
42
|
+
"@webiny/icons": "6.5.0-beta.6",
|
|
43
|
+
"@webiny/lexical-editor": "6.5.0-beta.6",
|
|
44
|
+
"@webiny/lexical-nodes": "6.5.0-beta.6",
|
|
45
|
+
"@webiny/plugins": "6.5.0-beta.6",
|
|
46
|
+
"@webiny/react-composition": "6.5.0-beta.6",
|
|
47
|
+
"@webiny/react-properties": "6.5.0-beta.6",
|
|
48
|
+
"@webiny/utils": "6.5.0-beta.6",
|
|
49
|
+
"@webiny/validation": "6.5.0-beta.6",
|
|
50
50
|
"dot-prop-immutable": "2.1.1",
|
|
51
51
|
"graphql": "16.14.2",
|
|
52
52
|
"graphql-tag": "2.12.7",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"zod": "4.6.5"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
-
"@webiny/build-tools": "6.5.0-beta.
|
|
66
|
+
"@webiny/build-tools": "6.5.0-beta.6",
|
|
67
67
|
"rimraf": "6.1.3",
|
|
68
68
|
"typescript": "7.0.2",
|
|
69
69
|
"vitest": "5.0.2"
|