@sap-ux/fe-fpm-writer 0.43.19 → 0.43.21

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.
@@ -217,8 +217,10 @@ function getTemplateContent(buildingBlockData, viewDocument, manifest, fs, usePl
217
217
  // or for equal or below UI5 v1.96.0 contextPath is applied
218
218
  const minUI5Version = manifest ? (0, semver_1.coerce)((0, project_access_1.getMinimumUI5Version)(manifest)) : undefined;
219
219
  let targetProperty;
220
- if (buildingBlockData.buildingBlockType === types_1.BuildingBlockType.RichTextEditor) {
221
- // Get target property for RichTextEditor building block
220
+ if ((buildingBlockData.buildingBlockType === types_1.BuildingBlockType.RichTextEditor ||
221
+ buildingBlockData.buildingBlockType === types_1.BuildingBlockType.CustomFormField) &&
222
+ 'targetProperty' in buildingBlockData &&
223
+ typeof buildingBlockData.targetProperty === 'string') {
222
224
  targetProperty = buildingBlockData.targetProperty;
223
225
  }
224
226
  const applyContextPath = buildingBlockData.buildingBlockType === types_1.BuildingBlockType.Chart ||
@@ -74,6 +74,12 @@ exports.BUILDING_BLOCK_CONFIG = {
74
74
  namespace: { uri: 'sap.fe.macros.filterBar', prefix: 'macros' },
75
75
  processor: processCustomFilterField
76
76
  },
77
+ [types_1.BuildingBlockType.CustomFormField]: {
78
+ aggregationConfig: { aggregationName: 'fields', elementName: 'FormElement' },
79
+ templateFile: 'common/Fragment.xml',
80
+ namespace: { uri: 'sap.fe.macros', prefix: 'macros' },
81
+ processor: processCustomFormField
82
+ },
77
83
  [types_1.BuildingBlockType.RichTextEditorButtonGroups]: {
78
84
  aggregationConfig: { aggregationName: 'buttonGroups', elementName: 'ButtonGroup' },
79
85
  namespace: { uri: 'sap.fe.macros', prefix: 'macros' },
@@ -179,6 +185,36 @@ function processCustomFilterField(buildingBlockData, context) {
179
185
  fs.copyTpl((0, templates_1.getTemplatePath)(config.templateFile), viewPath, filterConfig);
180
186
  }
181
187
  }
188
+ /**
189
+ * Processes custom form field building block.
190
+ *
191
+ * @param {BuildingBlock} buildingBlockData - The building block data
192
+ * @param {ProcessingContext} context - Processing context
193
+ */
194
+ function processCustomFormField(buildingBlockData, context) {
195
+ const { fs, viewPath } = context;
196
+ if (!isBuildingBlockType(buildingBlockData, types_1.BuildingBlockType.CustomFormField)) {
197
+ throw new Error('Expected CustomFormField building block data');
198
+ }
199
+ if (!buildingBlockData.embededFragment) {
200
+ throw new Error('EmbeddedFragment is required for CustomFormField');
201
+ }
202
+ const config = getBuildingBlockConfig(types_1.BuildingBlockType.CustomFormField);
203
+ const formFieldConfig = buildingBlockData.embededFragment;
204
+ let processedEventHandler;
205
+ // Apply event handler
206
+ if (formFieldConfig.eventHandler) {
207
+ processedEventHandler = (0, event_handler_1.applyEventHandlerConfiguration)(fs, formFieldConfig, formFieldConfig.eventHandler, {
208
+ controllerSuffix: false,
209
+ typescript: formFieldConfig.typescript
210
+ });
211
+ formFieldConfig.eventHandler = processedEventHandler;
212
+ }
213
+ formFieldConfig.content ??= (0, defaults_1.getDefaultFragmentContent)('Custom Form Field Content', buildingBlockData.generateId, processedEventHandler);
214
+ if (viewPath && !fs.exists(viewPath)) {
215
+ fs.copyTpl((0, templates_1.getTemplatePath)(config.templateFile), viewPath, formFieldConfig);
216
+ }
217
+ }
182
218
  /**
183
219
  * Extracts a ButtonGroupConfig from an XML element.
184
220
  *
@@ -437,7 +473,8 @@ function processBuildingBlock(buildingBlockData, xmlDocument, manifestPath, mani
437
473
  }
438
474
  // Process embedded fragment for types that support it
439
475
  if ((isBuildingBlockType(buildingBlockData, types_1.BuildingBlockType.CustomColumn) ||
440
- isBuildingBlockType(buildingBlockData, types_1.BuildingBlockType.CustomFilterField)) &&
476
+ isBuildingBlockType(buildingBlockData, types_1.BuildingBlockType.CustomFilterField) ||
477
+ isBuildingBlockType(buildingBlockData, types_1.BuildingBlockType.CustomFormField)) &&
441
478
  buildingBlockData.embededFragment) {
442
479
  embeddedFragment = (0, defaults_1.setCommonDefaults)(buildingBlockData.embededFragment, manifestPath, manifest);
443
480
  viewPath = (0, node_path_1.join)(embeddedFragment.path, `${embeddedFragment.fragmentFile ?? embeddedFragment.name}.fragment.xml`);
@@ -9,6 +9,7 @@ export declare enum BuildingBlockType {
9
9
  FilterBar = "filter-bar",
10
10
  Chart = "chart",
11
11
  CustomFilterField = "custom-filter-field",
12
+ CustomFormField = "custom-form-field",
12
13
  Field = "field",
13
14
  Form = "form",
14
15
  Page = "page",
@@ -419,6 +420,48 @@ export interface CustomFilterField extends BuildingBlock {
419
420
  */
420
421
  embededFragment?: EmbededFragment;
421
422
  }
423
+ /**
424
+ * Represents a custom form field building block.
425
+ * Custom form fields can be added to Form building blocks using the FormElement control.
426
+ *
427
+ * @see https://sapui5.hana.ondemand.com/#/api/sap.fe.macros.FormElement
428
+ * @example
429
+ * <macros:Form id="MyForm" metaPath="@com.sap.vocabularies.UI.v1.FieldGroup#General">
430
+ * <macros:fields>
431
+ * <macros:FormElement
432
+ * label="Custom Field"
433
+ * placement="After"
434
+ * anchor="DataField::ExistingProperty">
435
+ * <macros:fields>
436
+ * <core:Fragment fragmentName="myApp.ext.CustomField" type="XML" />
437
+ * </macros:fields>
438
+ * </macros:FormElement>
439
+ * </macros:fields>
440
+ * </macros:Form>
441
+ * @extends {BuildingBlock}
442
+ */
443
+ export interface CustomFormField extends BuildingBlock {
444
+ /**
445
+ * Optional key for the FormElement.
446
+ */
447
+ formElementKey?: string;
448
+ /**
449
+ * The text that will be displayed as label for this FormElement.
450
+ */
451
+ label: string;
452
+ /**
453
+ * Position of the custom form field relative to an anchor element.
454
+ */
455
+ position?: Position;
456
+ /**
457
+ * The fragment that contains the template for the custom form field.
458
+ */
459
+ embededFragment: EmbededFragment;
460
+ /**
461
+ * Property used to construct the metaPath for the custom form field, e.g. "EntitySet/targetProperty".
462
+ */
463
+ targetProperty?: string;
464
+ }
422
465
  export interface CustomColumn extends BuildingBlock {
423
466
  title: string;
424
467
  width?: string;
@@ -11,6 +11,7 @@ var BuildingBlockType;
11
11
  BuildingBlockType["FilterBar"] = "filter-bar";
12
12
  BuildingBlockType["Chart"] = "chart";
13
13
  BuildingBlockType["CustomFilterField"] = "custom-filter-field";
14
+ BuildingBlockType["CustomFormField"] = "custom-form-field";
14
15
  BuildingBlockType["Field"] = "field";
15
16
  BuildingBlockType["Form"] = "form";
16
17
  BuildingBlockType["Page"] = "page";
package/dist/index.d.ts CHANGED
@@ -15,7 +15,7 @@ export { generateCustomView } from './view';
15
15
  export { enableFPM, FPMConfig } from './app';
16
16
  export { validateBasePath, validateVersion } from './common/validate';
17
17
  export { createIdGenerator, type IdGeneratorFunction, getRelativeTemplateComponentPath } from './common/file';
18
- export { BuildingBlockType, FilterBar, Form, Chart, Field, FieldFormatOptions, Table, BuildingBlockConfig, Page, CustomColumn, CustomFilterField, RichTextEditor, ButtonGroupConfig, Action } from './building-block/types';
18
+ export { BuildingBlockType, FilterBar, Form, Chart, Field, FieldFormatOptions, Table, BuildingBlockConfig, Page, CustomColumn, CustomFilterField, CustomFormField, RichTextEditor, ButtonGroupConfig, Action } from './building-block/types';
19
19
  export { generateBuildingBlock, getSerializedFileContent } from './building-block';
20
20
  export { ChartPromptsAnswer, FilterBarPromptsAnswer, FormPromptsAnswer, TablePromptsAnswer, PagePromptsAnswer, RichTextEditorPromptsAnswer, RichTextEditorButtonGroupsPromptsAnswer, BuildingBlockTypePromptsAnswer } from './building-block/prompts/questions';
21
21
  export { PromptsType, SupportedGeneratorAnswers, PromptsAPI, PromptsGroup, Prompts, ValidationResults, Answers, Subset, CodeSnippet } from './prompts';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sap-ux/fe-fpm-writer",
3
3
  "description": "SAP Fiori elements flexible programming model writer",
4
- "version": "0.43.19",
4
+ "version": "0.43.21",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/SAP/open-ux-tools.git",
@@ -30,9 +30,9 @@
30
30
  "semver": "7.7.4",
31
31
  "xml-formatter": "3.7.0",
32
32
  "xpath": "0.0.34",
33
- "@sap-ux/fiori-annotation-api": "0.9.41",
33
+ "@sap-ux/fiori-annotation-api": "0.9.42",
34
34
  "@sap-ux/i18n": "0.3.10",
35
- "@sap-ux/project-access": "1.35.19",
35
+ "@sap-ux/project-access": "1.35.20",
36
36
  "@sap-ux/logger": "0.8.5"
37
37
  },
38
38
  "devDependencies": {
@@ -0,0 +1,14 @@
1
+ <% if (!config?.hasAggregation) { %><<%- macrosNamespace %>:fields><% } %>
2
+ <<%- config?.aggregationNamespace %>:FormElement
3
+ <% if (data.formElementKey) { %> key="<%- data.formElementKey %>"<% } %>
4
+ label="<%- data.label %>"
5
+ <% if (data.id) { %> id="<%- data.id %>"<% } %>
6
+ <% if (data.metaPath) { %> metaPath="<%- data.metaPath %>"<% } %>
7
+ <% if (data.contextPath) { %> contextPath="<%- data.contextPath %>"<% } %>
8
+ <% if (data.position?.anchor) { %> anchor="<%- data.position.anchor %>"<% } %>
9
+ <% if (data.position?.placement) { %> placement="<%- data.position.placement %>"<% } %>>
10
+ <<%- macrosNamespace %>:fields>
11
+ <core:Fragment fragmentName="<%- data.embededFragment.ns %>.<%- data.embededFragment.name %>" type="XML" />
12
+ </<%- macrosNamespace %>:fields>
13
+ </<%- config?.aggregationNamespace %>:FormElement>
14
+ <% if (!config?.hasAggregation) { %></<%- macrosNamespace %>:fields><% } %>