@sapui5/sap.fe.macros 1.139.0 → 1.141.0

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.
Files changed (254) hide show
  1. package/package.json +1 -1
  2. package/src/sap/fe/macros/.library +1 -1
  3. package/src/sap/fe/macros/Chart.js +53 -2
  4. package/src/sap/fe/macros/Chart.tsx +55 -0
  5. package/src/sap/fe/macros/CollaborativeDraftHandler.js +230 -0
  6. package/src/sap/fe/macros/CollaborativeDraftHandler.tsx +218 -0
  7. package/src/sap/fe/macros/CommonHelper.js +59 -15
  8. package/src/sap/fe/macros/CommonHelper.ts +65 -14
  9. package/src/sap/fe/macros/ConditionalSwitch.js +174 -0
  10. package/src/sap/fe/macros/ConditionalSwitch.tsx +141 -0
  11. package/src/sap/fe/macros/ConditionalSwitchProperty.js +78 -0
  12. package/src/sap/fe/macros/ConditionalSwitchProperty.tsx +62 -0
  13. package/src/sap/fe/macros/Field.js +78 -64
  14. package/src/sap/fe/macros/Field.ts +97 -68
  15. package/src/sap/fe/macros/FooterContent.js +5 -2
  16. package/src/sap/fe/macros/FooterContent.tsx +4 -1
  17. package/src/sap/fe/macros/MacroAPI.js +9 -4
  18. package/src/sap/fe/macros/MacroAPI.ts +9 -4
  19. package/src/sap/fe/macros/MessageButton.js +1 -2
  20. package/src/sap/fe/macros/MessageButton.tsx +0 -1
  21. package/src/sap/fe/macros/MultiValueField.js +10 -7
  22. package/src/sap/fe/macros/MultiValueField.tsx +7 -3
  23. package/src/sap/fe/macros/Page.js +5 -7
  24. package/src/sap/fe/macros/Page.tsx +4 -6
  25. package/src/sap/fe/macros/Paginator.js +9 -4
  26. package/src/sap/fe/macros/Paginator.tsx +12 -3
  27. package/src/sap/fe/macros/RichTextEditor.js +3 -2
  28. package/src/sap/fe/macros/RichTextEditor.tsx +2 -1
  29. package/src/sap/fe/macros/Share.js +14 -2
  30. package/src/sap/fe/macros/Share.tsx +13 -0
  31. package/src/sap/fe/macros/Status.js +251 -0
  32. package/src/sap/fe/macros/Status.tsx +212 -0
  33. package/src/sap/fe/macros/ValueHelp.js +4 -28
  34. package/src/sap/fe/macros/ValueHelp.tsx +2 -42
  35. package/src/sap/fe/macros/ai/EasyFillDialog.js +11 -17
  36. package/src/sap/fe/macros/ai/EasyFillDialog.tsx +11 -16
  37. package/src/sap/fe/macros/ai/EasyFilterBar.js +246 -97
  38. package/src/sap/fe/macros/ai/EasyFilterBar.tsx +302 -106
  39. package/src/sap/fe/macros/ai/EasyFilterDataFetcher.js +76 -33
  40. package/src/sap/fe/macros/ai/EasyFilterDataFetcher.ts +89 -40
  41. package/src/sap/fe/macros/ai/SummarizationButton.js +2 -2
  42. package/src/sap/fe/macros/ai/SummarizationButton.tsx +1 -1
  43. package/src/sap/fe/macros/chart/Chart.js +2 -2
  44. package/src/sap/fe/macros/chart/Chart.tsx +1 -1
  45. package/src/sap/fe/macros/chart/ChartHelper.js +1 -2
  46. package/src/sap/fe/macros/chart/ChartHelper.ts +0 -1
  47. package/src/sap/fe/macros/chart/ChartRuntime.js +1 -2
  48. package/src/sap/fe/macros/chart/ChartRuntime.ts +0 -1
  49. package/src/sap/fe/macros/chart/MdcChartTemplate.js +5 -5
  50. package/src/sap/fe/macros/chart/MdcChartTemplate.tsx +5 -5
  51. package/src/sap/fe/macros/contentSwitcher/ContentSwitcher.js +9 -2
  52. package/src/sap/fe/macros/contentSwitcher/ContentSwitcher.tsx +8 -0
  53. package/src/sap/fe/macros/controls/BuildingBlockObjectProperty.js +5 -1
  54. package/src/sap/fe/macros/controls/BuildingBlockObjectProperty.ts +4 -0
  55. package/src/sap/fe/macros/controls/BuildingBlockWithTemplating.js +4 -2
  56. package/src/sap/fe/macros/controls/BuildingBlockWithTemplating.ts +3 -1
  57. package/src/sap/fe/macros/controls/FilterBar.js +14 -5
  58. package/src/sap/fe/macros/controls/FilterBar.ts +3 -0
  59. package/src/sap/fe/macros/controls/NumberWithUnitOrCurrency.js +2 -2
  60. package/src/sap/fe/macros/controls/NumberWithUnitOrCurrency.tsx +2 -2
  61. package/src/sap/fe/macros/controls/RadioButtons.js +61 -38
  62. package/src/sap/fe/macros/controls/RadioButtons.tsx +39 -18
  63. package/src/sap/fe/macros/controls/Section.js +4 -3
  64. package/src/sap/fe/macros/controls/Section.ts +3 -2
  65. package/src/sap/fe/macros/controls/section/SubSection.js +63 -8
  66. package/src/sap/fe/macros/controls/section/SubSection.ts +67 -1
  67. package/src/sap/fe/macros/coreUI/OperationParameterDialog.js +43 -4
  68. package/src/sap/fe/macros/coreUI/OperationParameterDialog.tsx +48 -1
  69. package/src/sap/fe/macros/designtime/Designtime.helper.js +28 -1
  70. package/src/sap/fe/macros/designtime/Designtime.helper.ts +27 -0
  71. package/src/sap/fe/macros/field/Field.js +2 -2
  72. package/src/sap/fe/macros/field/Field.tsx +1 -1
  73. package/src/sap/fe/macros/field/FieldBaseDelegate.js +13 -7
  74. package/src/sap/fe/macros/field/FieldBaseDelegate.ts +12 -8
  75. package/src/sap/fe/macros/field/FieldFormatOptions.js +25 -2
  76. package/src/sap/fe/macros/field/FieldFormatOptions.ts +13 -0
  77. package/src/sap/fe/macros/field/FieldHelper.js +2 -2
  78. package/src/sap/fe/macros/field/FieldHelper.ts +1 -4
  79. package/src/sap/fe/macros/field/FieldRuntime.js +1 -2
  80. package/src/sap/fe/macros/field/FieldRuntime.ts +0 -1
  81. package/src/sap/fe/macros/field/FieldTemplating.js +3 -3
  82. package/src/sap/fe/macros/field/FieldTemplating.ts +4 -2
  83. package/src/sap/fe/macros/filter/FilterUtils.js +233 -5
  84. package/src/sap/fe/macros/filter/FilterUtils.ts +291 -7
  85. package/src/sap/fe/macros/filterBar/FilterBar.block.js +5 -3
  86. package/src/sap/fe/macros/filterBar/FilterBar.block.tsx +4 -2
  87. package/src/sap/fe/macros/filterBar/FilterBar.js +2 -2
  88. package/src/sap/fe/macros/filterBar/FilterBar.tsx +1 -1
  89. package/src/sap/fe/macros/filterBar/FilterBarAPI.js +63 -27
  90. package/src/sap/fe/macros/filterBar/FilterBarAPI.ts +49 -3
  91. package/src/sap/fe/macros/filterBar/FilterBarDelegate.js +5 -3
  92. package/src/sap/fe/macros/filterBar/FilterBarDelegate.ts +5 -2
  93. package/src/sap/fe/macros/filterBar/mixin/FilterBarAPIStateHandler.js +7 -2
  94. package/src/sap/fe/macros/filterBar/mixin/FilterBarAPIStateHandler.ts +6 -1
  95. package/src/sap/fe/macros/form/Form.block.js +7 -8
  96. package/src/sap/fe/macros/form/Form.block.ts +4 -6
  97. package/src/sap/fe/macros/form/Form.js +1 -4
  98. package/src/sap/fe/macros/form/Form.tsx +0 -3
  99. package/src/sap/fe/macros/form/FormContainer.block.js +555 -5
  100. package/src/sap/fe/macros/form/FormContainer.block.ts +665 -7
  101. package/src/sap/fe/macros/form/FormContainer.fragment.xml +1 -0
  102. package/src/sap/fe/macros/form/FormDelegate.js +24 -8
  103. package/src/sap/fe/macros/form/FormDelegate.ts +29 -7
  104. package/src/sap/fe/macros/form/FormHelper.js +1 -2
  105. package/src/sap/fe/macros/form/FormHelper.ts +0 -1
  106. package/src/sap/fe/macros/fpm/CustomFragment.block.js +1 -2
  107. package/src/sap/fe/macros/fpm/CustomFragment.block.ts +0 -1
  108. package/src/sap/fe/macros/internal/ActionCommand.block.js +1 -2
  109. package/src/sap/fe/macros/internal/ActionCommand.block.ts +0 -1
  110. package/src/sap/fe/macros/internal/DataPoint.js +3 -2
  111. package/src/sap/fe/macros/internal/DataPoint.tsx +10 -1
  112. package/src/sap/fe/macros/internal/FilterField.block.js +19 -5
  113. package/src/sap/fe/macros/internal/FilterField.block.ts +16 -4
  114. package/src/sap/fe/macros/internal/field/DisplayStyle.js +9 -3
  115. package/src/sap/fe/macros/internal/field/DisplayStyle.tsx +10 -2
  116. package/src/sap/fe/macros/internal/field/EditStyle.js +21 -4
  117. package/src/sap/fe/macros/internal/field/EditStyle.tsx +18 -4
  118. package/src/sap/fe/macros/internal/field/FieldStructureHelper.js +3 -2
  119. package/src/sap/fe/macros/internal/field/FieldStructureHelper.ts +5 -1
  120. package/src/sap/fe/macros/internal/filterField/FilterFieldTemplate.fragment.xml +1 -0
  121. package/src/sap/fe/macros/internal/helpers/ActionHelper.js +36 -5
  122. package/src/sap/fe/macros/internal/helpers/ActionHelper.ts +34 -4
  123. package/src/sap/fe/macros/internal/valuehelp/AdditionalValueHelper.js +46 -8
  124. package/src/sap/fe/macros/internal/valuehelp/AdditionalValueHelper.ts +60 -6
  125. package/src/sap/fe/macros/internal/valuehelp/TableDelegate.js +38 -2
  126. package/src/sap/fe/macros/internal/valuehelp/TableDelegate.ts +37 -2
  127. package/src/sap/fe/macros/internal/valuehelp/ValueListDialogTable.fragment.xml +1 -1
  128. package/src/sap/fe/macros/internal/valuehelp/ValueListHelper.js +10 -3
  129. package/src/sap/fe/macros/internal/valuehelp/ValueListHelper.ts +13 -2
  130. package/src/sap/fe/macros/library.js +1 -1
  131. package/src/sap/fe/macros/mdc/adapter/StateFilterToSelectionVariant.js +2 -1
  132. package/src/sap/fe/macros/mdc/adapter/StateFilterToSelectionVariant.ts +1 -0
  133. package/src/sap/fe/macros/messagebundle.properties +24 -4
  134. package/src/sap/fe/macros/messagebundle_ar.properties +8 -2
  135. package/src/sap/fe/macros/messagebundle_bg.properties +8 -2
  136. package/src/sap/fe/macros/messagebundle_ca.properties +11 -5
  137. package/src/sap/fe/macros/messagebundle_cnr.properties +8 -2
  138. package/src/sap/fe/macros/messagebundle_cs.properties +7 -1
  139. package/src/sap/fe/macros/messagebundle_cy.properties +9 -3
  140. package/src/sap/fe/macros/messagebundle_da.properties +8 -2
  141. package/src/sap/fe/macros/messagebundle_de.properties +13 -7
  142. package/src/sap/fe/macros/messagebundle_el.properties +7 -1
  143. package/src/sap/fe/macros/messagebundle_en.properties +11 -5
  144. package/src/sap/fe/macros/messagebundle_en_GB.properties +9 -3
  145. package/src/sap/fe/macros/messagebundle_en_US_saprigi.properties +11 -5
  146. package/src/sap/fe/macros/messagebundle_es.properties +10 -4
  147. package/src/sap/fe/macros/messagebundle_es_MX.properties +11 -5
  148. package/src/sap/fe/macros/messagebundle_et.properties +9 -3
  149. package/src/sap/fe/macros/messagebundle_fi.properties +7 -1
  150. package/src/sap/fe/macros/messagebundle_fr.properties +9 -3
  151. package/src/sap/fe/macros/messagebundle_fr_CA.properties +8 -2
  152. package/src/sap/fe/macros/messagebundle_hi.properties +8 -2
  153. package/src/sap/fe/macros/messagebundle_hr.properties +8 -2
  154. package/src/sap/fe/macros/messagebundle_hu.properties +7 -1
  155. package/src/sap/fe/macros/messagebundle_id.properties +15 -9
  156. package/src/sap/fe/macros/messagebundle_it.properties +7 -1
  157. package/src/sap/fe/macros/messagebundle_iw.properties +8 -2
  158. package/src/sap/fe/macros/messagebundle_ja.properties +13 -7
  159. package/src/sap/fe/macros/messagebundle_kk.properties +11 -5
  160. package/src/sap/fe/macros/messagebundle_ko.properties +8 -2
  161. package/src/sap/fe/macros/messagebundle_lt.properties +9 -3
  162. package/src/sap/fe/macros/messagebundle_lv.properties +8 -2
  163. package/src/sap/fe/macros/messagebundle_mk.properties +8 -2
  164. package/src/sap/fe/macros/messagebundle_ms.properties +7 -1
  165. package/src/sap/fe/macros/messagebundle_nl.properties +7 -1
  166. package/src/sap/fe/macros/messagebundle_no.properties +7 -1
  167. package/src/sap/fe/macros/messagebundle_pl.properties +8 -2
  168. package/src/sap/fe/macros/messagebundle_pt.properties +7 -1
  169. package/src/sap/fe/macros/messagebundle_pt_PT.properties +7 -1
  170. package/src/sap/fe/macros/messagebundle_ro.properties +8 -2
  171. package/src/sap/fe/macros/messagebundle_ru.properties +10 -4
  172. package/src/sap/fe/macros/messagebundle_sh.properties +8 -2
  173. package/src/sap/fe/macros/messagebundle_sk.properties +7 -1
  174. package/src/sap/fe/macros/messagebundle_sl.properties +7 -1
  175. package/src/sap/fe/macros/messagebundle_sr.properties +8 -2
  176. package/src/sap/fe/macros/messagebundle_sv.properties +7 -1
  177. package/src/sap/fe/macros/messagebundle_th.properties +8 -2
  178. package/src/sap/fe/macros/messagebundle_tr.properties +7 -1
  179. package/src/sap/fe/macros/messagebundle_uk.properties +10 -4
  180. package/src/sap/fe/macros/messagebundle_vi.properties +10 -4
  181. package/src/sap/fe/macros/messagebundle_zh_CN.properties +7 -1
  182. package/src/sap/fe/macros/messagebundle_zh_TW.properties +8 -2
  183. package/src/sap/fe/macros/messages/MessageButton.js +39 -18
  184. package/src/sap/fe/macros/messages/MessageButton.ts +42 -19
  185. package/src/sap/fe/macros/messages/MessagePopover.js +4 -2
  186. package/src/sap/fe/macros/messages/MessagePopover.ts +6 -4
  187. package/src/sap/fe/macros/microchart/MicroChart.js +2 -2
  188. package/src/sap/fe/macros/microchart/MicroChart.tsx +1 -1
  189. package/src/sap/fe/macros/microchart/MicroChartContainer.js +1 -2
  190. package/src/sap/fe/macros/microchart/MicroChartContainer.ts +1 -2
  191. package/src/sap/fe/macros/microchart/MicroChartHelper.js +2 -3
  192. package/src/sap/fe/macros/microchart/MicroChartHelper.tsx +1 -2
  193. package/src/sap/fe/macros/share/ShareAPI.js +4 -29
  194. package/src/sap/fe/macros/share/ShareAPI.ts +1 -32
  195. package/src/sap/fe/macros/situations/SituationsPopover.js +3 -1
  196. package/src/sap/fe/macros/situations/SituationsPopover.ts +2 -0
  197. package/src/sap/fe/macros/table/ActionsTemplating.js +4 -8
  198. package/src/sap/fe/macros/table/ActionsTemplating.tsx +5 -8
  199. package/src/sap/fe/macros/table/BasicSearch.js +1 -1
  200. package/src/sap/fe/macros/table/BasicSearch.ts +2 -1
  201. package/src/sap/fe/macros/table/Column.js +14 -2
  202. package/src/sap/fe/macros/table/Column.ts +7 -0
  203. package/src/sap/fe/macros/table/ColumnExportSettings.js +83 -15
  204. package/src/sap/fe/macros/table/ColumnExportSettings.ts +44 -0
  205. package/src/sap/fe/macros/table/ColumnOverride.js +14 -2
  206. package/src/sap/fe/macros/table/ColumnOverride.ts +7 -0
  207. package/src/sap/fe/macros/table/MdcTableTemplate.js +7 -5
  208. package/src/sap/fe/macros/table/MdcTableTemplate.tsx +21 -11
  209. package/src/sap/fe/macros/table/QuickFilterSelector.js +12 -3
  210. package/src/sap/fe/macros/table/QuickFilterSelector.tsx +15 -2
  211. package/src/sap/fe/macros/table/Table.block.js +188 -147
  212. package/src/sap/fe/macros/table/Table.block.tsx +41 -11
  213. package/src/sap/fe/macros/table/Table.js +16 -10
  214. package/src/sap/fe/macros/table/Table.tsx +16 -10
  215. package/src/sap/fe/macros/table/TableAPI.js +224 -184
  216. package/src/sap/fe/macros/table/TableAPI.ts +63 -19
  217. package/src/sap/fe/macros/table/TableEventHandlerProvider.js +6 -6
  218. package/src/sap/fe/macros/table/TableEventHandlerProvider.ts +5 -4
  219. package/src/sap/fe/macros/table/TableHelper.js +2 -3
  220. package/src/sap/fe/macros/table/TableHelper.ts +1 -2
  221. package/src/sap/fe/macros/table/TableRuntime.js +24 -5
  222. package/src/sap/fe/macros/table/TableRuntime.ts +31 -3
  223. package/src/sap/fe/macros/table/TreeTable.js +16 -10
  224. package/src/sap/fe/macros/table/TreeTable.tsx +16 -10
  225. package/src/sap/fe/macros/table/Utils.js +8 -3
  226. package/src/sap/fe/macros/table/Utils.ts +12 -3
  227. package/src/sap/fe/macros/table/delegates/ALPTableDelegate.js +1 -2
  228. package/src/sap/fe/macros/table/delegates/ALPTableDelegate.ts +0 -1
  229. package/src/sap/fe/macros/table/delegates/TableDelegate.js +69 -34
  230. package/src/sap/fe/macros/table/delegates/TableDelegate.ts +75 -33
  231. package/src/sap/fe/macros/table/delegates/TreeTableDelegate.js +1 -2
  232. package/src/sap/fe/macros/table/delegates/TreeTableDelegate.ts +0 -1
  233. package/src/sap/fe/macros/table/massEdit/MassEditDialog.js +10 -10
  234. package/src/sap/fe/macros/table/massEdit/MassEditDialog.tsx +11 -9
  235. package/src/sap/fe/macros/table/massEdit/MassEditDialogHelper.js +14 -12
  236. package/src/sap/fe/macros/table/massEdit/MassEditDialogHelper.tsx +11 -10
  237. package/src/sap/fe/macros/table/mixin/ContextMenuHandler.js +34 -4
  238. package/src/sap/fe/macros/table/mixin/ContextMenuHandler.ts +45 -2
  239. package/src/sap/fe/macros/table/mixin/EmptyRowsHandler.js +55 -12
  240. package/src/sap/fe/macros/table/mixin/EmptyRowsHandler.ts +71 -9
  241. package/src/sap/fe/macros/table/mixin/TableAPIStateHandler.js +53 -2
  242. package/src/sap/fe/macros/table/mixin/TableAPIStateHandler.ts +55 -0
  243. package/src/sap/fe/macros/table/mixin/TableExport.js +22 -3
  244. package/src/sap/fe/macros/table/mixin/TableExport.ts +25 -4
  245. package/src/sap/fe/macros/table/mixin/TableHierarchy.js +5 -1
  246. package/src/sap/fe/macros/table/mixin/TableHierarchy.ts +7 -0
  247. package/src/sap/fe/macros/table/mixin/TableSharing.js +4 -2
  248. package/src/sap/fe/macros/table/mixin/TableSharing.ts +10 -1
  249. package/src/sap/fe/macros/valuehelp/ValueHelpDelegate.js +36 -10
  250. package/src/sap/fe/macros/valuehelp/ValueHelpDelegate.ts +44 -9
  251. package/src/sap/fe/macros/visualfilters/VisualFilter.js +5 -4
  252. package/src/sap/fe/macros/visualfilters/VisualFilter.tsx +3 -2
  253. package/src/sap/fe/macros/visualfilters/VisualFilterRuntime.js +2 -3
  254. package/src/sap/fe/macros/visualfilters/VisualFilterRuntime.ts +1 -2
@@ -1,7 +1,11 @@
1
+ import type { ComplexType, EntitySet, EntityType, NavigationProperty, Property, TypeDefinition } from "@sap-ux/vocabularies-types";
1
2
  import Log from "sap/base/Log";
3
+ import Localization from "sap/base/i18n/Localization";
4
+ import { isConstant } from "sap/fe/base/BindingToolkit";
2
5
  import type { EnhanceWithUI5 } from "sap/fe/base/ClassSupport";
3
6
  import { aggregation, association, defineUI5Class, implementInterface, property, type PropertiesOf } from "sap/fe/base/ClassSupport";
4
7
  import type {
8
+ CodeListType,
5
9
  EasyFilterBarContainer$ShowValueHelpEvent,
6
10
  EasyFilterPropertyMetadata,
7
11
  TokenDefinition,
@@ -14,10 +18,11 @@ import BuildingBlock from "sap/fe/core/buildingBlocks/BuildingBlock";
14
18
  import BusyLocker from "sap/fe/core/controllerextensions/BusyLocker";
15
19
  import type { ControlState, NavigationParameter } from "sap/fe/core/controllerextensions/ViewState";
16
20
  import type IViewStateContributor from "sap/fe/core/controllerextensions/viewState/IViewStateContributor";
17
- import type { FilterField } from "sap/fe/core/definition/FEDefinition";
21
+ import { type FilterField } from "sap/fe/core/definition/FEDefinition";
18
22
  import type MetaPath from "sap/fe/core/helpers/MetaPath";
19
23
  import ModelHelper from "sap/fe/core/helpers/ModelHelper";
20
- import { isPathAnnotationExpression } from "sap/fe/core/helpers/TypeGuards";
24
+ import { isComplexType, isEntityType, isNavigationProperty, isPathAnnotationExpression, isProperty } from "sap/fe/core/helpers/TypeGuards";
25
+ import { isPathFilterable } from "sap/fe/core/templating/DataModelPathHelper";
21
26
  import { hasValueHelpWithFixedValues } from "sap/fe/core/templating/PropertyHelper";
22
27
  import {
23
28
  generateSelectParameter,
@@ -42,14 +47,13 @@ import DateTimeOffset from "sap/ui/model/odata/type/DateTimeOffset";
42
47
  import type ODataType from "sap/ui/model/odata/type/ODataType";
43
48
  import TimeOfDay from "sap/ui/model/odata/type/TimeOfDay";
44
49
  import type ODataMetaModel from "sap/ui/model/odata/v4/ODataMetaModel";
45
- import type { CodeList, MayBeLazy } from "ux/eng/fioriai/reuse/easyfilter/EasyFilter";
50
+ import type { CodeList } from "ux/eng/fioriai/reuse/easyfilter/EasyFilter";
46
51
 
47
52
  type EasyFilterBarState = {};
48
- type FieldMetadata = EasyFilterPropertyMetadata & { filterFieldName: string };
53
+ type FieldMetadata = EasyFilterPropertyMetadata & { maxLength?: number };
49
54
 
50
55
  /**
51
56
  * Delivery for beta release for the easy filter feature.
52
- * @experimental
53
57
  */
54
58
  @defineUI5Class("sap.fe.macros.EasyFilterBar")
55
59
  export default class EasyFilterBar extends BuildingBlock implements IViewStateContributor<EasyFilterBarState> {
@@ -71,8 +75,6 @@ export default class EasyFilterBar extends BuildingBlock implements IViewStateCo
71
75
  @aggregation({ type: "sap.fe.controls.easyFilter.EasyFilterBarContainer" })
72
76
  content?: EnhanceWithUI5<EasyFilterBarContainer>;
73
77
 
74
- _fetchedCodeList!: Record<string, CodeList | undefined>;
75
-
76
78
  private filterBarMetadata!: FieldMetadata[];
77
79
 
78
80
  private easyFilterPath?: string;
@@ -142,116 +144,272 @@ export default class EasyFilterBar extends BuildingBlock implements IViewStateCo
142
144
  }
143
145
 
144
146
  onMetadataAvailable(): void {
145
- this._fetchedCodeList ??= {};
146
147
  this.filterBarMetadata = this.prepareFilterBarMetadata();
147
148
  this.recommendedQueries = this.getAppComponent()?.getManifestEntry("sap.fe")?.macros?.easyFilter?.recommendedQueries ?? [];
148
149
  this.content = this.createContent() as EnhanceWithUI5<EasyFilterBarContainer>;
149
150
  this.content.filterBarMetadata = this.filterBarMetadata;
150
151
  }
151
152
 
153
+ private getUnitForProperty(prop: Property, basePath: string): string | undefined {
154
+ const unitAnnotation = prop.annotations.Measures?.ISOCurrency ?? prop.annotations.Measures?.Unit;
155
+ return isPathAnnotationExpression(unitAnnotation) ? `${basePath}/${unitAnnotation.path}` : undefined;
156
+ }
157
+
158
+ private getDefaultValueForFilterField(
159
+ field: FilterField,
160
+ startupParameters: Record<string, unknown>
161
+ ): TokenSelectedValuesDefinition[] | undefined {
162
+ let defaultValue: TokenSelectedValuesDefinition[] | undefined;
163
+ if (startupParameters.hasOwnProperty(field.name)) {
164
+ defaultValue = [
165
+ {
166
+ operator: FilterOperator.EQ,
167
+ selectedValues: startupParameters[field.name] as TokenSelectedValuesDefinition["selectedValues"]
168
+ }
169
+ ];
170
+ } else if (field.isParameter && startupParameters.hasOwnProperty(field.name.substring(2))) {
171
+ defaultValue = [
172
+ {
173
+ operator: FilterOperator.EQ,
174
+ selectedValues: startupParameters[field.name.substring(2)] as TokenSelectedValuesDefinition["selectedValues"]
175
+ }
176
+ ];
177
+ }
178
+ return defaultValue;
179
+ }
180
+
181
+ private getEditStateFilterMetadata(metaModel: ODataMetaModel): FieldMetadata {
182
+ // Assemble the code list for the editing status filter values:
183
+ const props = new JSONModel({
184
+ isDraftCollaborative: ModelHelper.isCollaborationDraftSupported(metaModel)
185
+ }).createBindingContext("/");
186
+
187
+ const editingStatusCodeList = DraftEditState.getEditStatesContext(props)
188
+ .getObject("/")
189
+ .map((state: { id: string; display: string }) => ({ value: state.id, description: state.display }));
190
+
191
+ return {
192
+ name: "$editState",
193
+ label: this.getTranslatedText("FILTERBAR_EDITING_STATUS"),
194
+ dataType: "Edm.String",
195
+ filterable: true,
196
+ codeList: editingStatusCodeList,
197
+ type: "MenuWithSingleSelect"
198
+ };
199
+ }
200
+
201
+ private getTokenType(prop: Property, filterRestriction: string): TokenType {
202
+ if (hasValueHelpWithFixedValues(prop)) {
203
+ return filterRestriction === "SingleValue" ? "MenuWithSingleSelect" : "MenuWithCheckBox";
204
+ }
205
+ switch (prop.type) {
206
+ case "Edm.Date":
207
+ return "Calendar";
208
+ case "Edm.TimeOfDay":
209
+ return "Time";
210
+ default:
211
+ return "ValueHelp";
212
+ }
213
+ }
214
+
215
+ private getLabel(element: Property | NavigationProperty | EntityType | ComplexType): string | undefined {
216
+ const label = element.annotations.Common?.Label?.toString();
217
+ const headerInfoTypeName = isEntityType(element) ? (element.annotations.UI?.HeaderInfo?.TypeName?.valueOf() as string) : undefined;
218
+ const result = headerInfoTypeName || label;
219
+
220
+ if (this.isComplexProperty(element) || isNavigationProperty(element)) {
221
+ return result || this.getLabel(element.targetType);
222
+ }
223
+
224
+ return result;
225
+ }
226
+
227
+ private isScalarProperty(element: unknown): element is Property & { targetType?: TypeDefinition } {
228
+ return isProperty(element) && !isComplexType(element.targetType);
229
+ }
230
+
231
+ private isComplexProperty(element: unknown): element is Property & { targetType: ComplexType } {
232
+ return isProperty(element) && isComplexType(element.targetType);
233
+ }
234
+
152
235
  prepareFilterBarMetadata(): FieldMetadata[] {
236
+ /*
237
+ * 1. INITIALIZATION:
238
+ * - Queue all root entity properties and navigation properties for traversal
239
+ * - Initialize result array and elimination set for Common.Text targets
240
+ *
241
+ * 2. BREADTH-FIRST TRAVERSAL:
242
+ * For each path in queue:
243
+ * - Skip UI.Hidden properties
244
+ * - Scalar properties: Generate metadata, track Common.Text targets for elimination
245
+ * - Complex properties: Add child properties to queue
246
+ * - Navigation properties: Add target EntityType properties to queue
247
+ * (Collections only if explicit filter fields exist, respect depth limits)
248
+ *
249
+ * 3. POST-PROCESSING:
250
+ * - Add $editState filter for draft-enabled entities
251
+ * - Remove properties marked for elimination (except explicit filter fields)
252
+ */
153
253
  const owner = this._getOwner()!;
154
254
  const definitionForPage = owner.preprocessorContext?.getDefinitionForPage();
155
- let filterBarDef;
156
- if (definitionForPage) {
157
- filterBarDef = definitionForPage.getFilterBarDefinition({});
158
255
 
159
- const metaModel = owner.preprocessorContext?.models.metaModel as ODataMetaModel;
256
+ if (!definitionForPage) {
257
+ return [];
258
+ }
160
259
 
161
- const getType = (edmType: string, codeList: MayBeLazy<CodeList> | undefined): TokenType => {
162
- if (codeList) {
163
- return "MenuWithCheckBox";
164
- }
165
- switch (edmType) {
166
- case "Edm.Date":
167
- return "Calendar";
168
- case "Edm.TimeOfDay":
169
- return "Time";
170
- default:
171
- return "ValueHelp";
172
- }
173
- };
174
- const startupParameters = owner.getAppComponent().getComponentData()?.startupParameters ?? {};
260
+ const filterBarDef = definitionForPage.getFilterBarDefinition({});
261
+ const metaPath = definitionForPage.getMetaPath();
262
+ const entitySet = metaPath.getClosestEntitySet() as EntitySet;
263
+
264
+ let filterExpressionRestrictions = entitySet.annotations.Capabilities?.FilterRestrictions?.FilterExpressionRestrictions ?? [];
265
+
266
+ // TODO: Maybe we can simplify this by using restrictions on the main entity set only
267
+ for (const navigationProperty in entitySet.navigationPropertyBinding) {
268
+ if (entitySet.navigationPropertyBinding[navigationProperty]?._type === "EntitySet") {
269
+ // FIXME: optional chaining should not be needed here -> root cause fix pending
270
+ const navigationPropertyEntitySet = entitySet.navigationPropertyBinding[navigationProperty] as EntitySet;
271
+ const navPropertyFilterExpressionRestrictions =
272
+ navigationPropertyEntitySet.annotations.Capabilities?.FilterRestrictions?.FilterExpressionRestrictions ?? [];
273
+
274
+ const currentFilterRestrictions = [...filterExpressionRestrictions];
275
+ filterExpressionRestrictions = [
276
+ ...filterExpressionRestrictions,
277
+ ...navPropertyFilterExpressionRestrictions.filter((restriction) => !currentFilterRestrictions.includes(restriction))
278
+ ];
279
+ }
280
+ }
175
281
 
176
- const filterFields = filterBarDef.getFilterFields();
177
- const nonHiddenFilterFields = filterFields.filter((field: FilterField) => {
178
- return !field.getTarget()?.annotations?.UI?.HiddenFilter?.valueOf();
179
- });
180
- const result = nonHiddenFilterFields.map((field: FilterField): FieldMetadata => {
181
- const propertyObject = field.getTarget();
182
- let codeList: MayBeLazy<CodeList> | undefined;
183
- const hasCodeList = hasValueHelpWithFixedValues(propertyObject);
184
- if (hasCodeList) {
185
- codeList = this._fetchedCodeList[field.name];
186
- if (!codeList) {
187
- codeList = async (): Promise<CodeList> => this.getCodeListForProperty(field.name, field.annotationPath!);
188
- }
189
- }
282
+ const metaModel = owner.preprocessorContext?.models.metaModel as ODataMetaModel;
190
283
 
191
- // Check if the filter field's target property has a currency or a unit. If so, look for the corresponding filter field (the
192
- // annotation has to be a path for that) and set the 'unit' property.
193
- const unitAnnotation = propertyObject.annotations.Measures?.ISOCurrency ?? propertyObject.annotations.Measures?.Unit;
194
- const unitProperty = isPathAnnotationExpression(unitAnnotation) ? unitAnnotation.$target : undefined;
195
- const unit = unitProperty ? filterFields.find((f) => f.getTarget() === unitProperty)?.name : undefined;
196
- let defaultValue: TokenSelectedValuesDefinition[] | undefined;
197
- if (startupParameters.hasOwnProperty(field.name)) {
198
- defaultValue = [
199
- {
200
- operator: FilterOperator.EQ,
201
- selectedValues: startupParameters[field.name] as TokenSelectedValuesDefinition["selectedValues"]
202
- }
203
- ];
204
- } else if (field.isParameter && startupParameters.hasOwnProperty(field.name.substring(2))) {
205
- defaultValue = [
206
- {
207
- operator: FilterOperator.EQ,
208
- selectedValues: startupParameters[field.name.substring(2)] as TokenSelectedValuesDefinition["selectedValues"]
209
- }
210
- ];
284
+ const getCodeList = (lastPathSegment: Property, propertyPath: string): CodeList | (() => Promise<CodeList>) | undefined =>
285
+ hasValueHelpWithFixedValues(lastPathSegment)
286
+ ? async (): Promise<CodeList> => this.getCodeListForProperty(propertyPath)
287
+ : undefined;
288
+
289
+ const filterFields = filterBarDef
290
+ .getFilterFields()
291
+ .filter((field: FilterField) => !field.getTarget()?.annotations?.UI?.HiddenFilter?.valueOf());
292
+
293
+ const startupParameters = owner.getAppComponent().getComponentData()?.startupParameters ?? {};
294
+
295
+ const maxDepth = 1; // Maximum depth for navigation properties
296
+
297
+ // Initialize traversal queue with all entity properties and navigation properties.
298
+ // Each path to traverse is a list of segments (e.g. [navProp1, complexProp1, complexProp2, scalarProp])
299
+ const pathsToExplore: (Property | NavigationProperty)[][] = [
300
+ ...entitySet.entityType.entityProperties,
301
+ ...entitySet.entityType.navigationProperties
302
+ ].map((element) => [element]);
303
+
304
+ // Resulting metadata array
305
+ const result: EasyFilterPropertyMetadata[] = [];
306
+
307
+ // Set of property paths to be eliminated from the filter bar metadata
308
+ const pathsToEliminate = new Set<string>();
309
+
310
+ const getPathLabel = (path: (Property | NavigationProperty)[]): string => {
311
+ const pathLabels = path.map((e) => this.getLabel(e) || `[${e.name}]`);
312
+ return Localization.getRTL() ? pathLabels.slice().reverse().join(" - ") : pathLabels.join(" - ");
313
+ };
314
+
315
+ while (pathsToExplore.length > 0) {
316
+ const currentPath = pathsToExplore.shift()!;
317
+
318
+ const navigationDepth = currentPath.filter(isNavigationProperty).length;
319
+
320
+ const lastPathSegment = currentPath[currentPath.length - 1];
321
+
322
+ if (lastPathSegment.annotations.UI?.Hidden?.valueOf() === true) {
323
+ continue;
324
+ }
325
+
326
+ const pathString = [`/${entitySet.name}`, ...currentPath.slice(0, -1).map((e) => e.name)].reduce(
327
+ (acc, curr) => `${acc}/${curr}`
328
+ );
329
+ const propertyPath = `${pathString}/${lastPathSegment.name}`;
330
+
331
+ if (this.isScalarProperty(lastPathSegment)) {
332
+ // Check for Common.Text annotation and record the annotation target path for elimination
333
+ const textAnnotation = lastPathSegment.annotations.Common?.Text;
334
+ if (isPathAnnotationExpression(textAnnotation)) {
335
+ // Construct the full path to the target property
336
+ pathsToEliminate.add(`${pathString}/${textAnnotation.path}`);
211
337
  }
212
- return {
213
- name: field.annotationPath!,
214
- filterFieldName: field.name,
215
- label: field.label,
216
- dataType: propertyObject.type,
217
- required: field.required ?? false,
218
- defaultValue: defaultValue,
219
- filterable: true,
220
- codeList: codeList,
221
- type: getType(propertyObject.type, codeList) as Exclude<TokenType, "ValueHelp">,
222
- unit: unit
338
+
339
+ // Scalar property: create metadata for the property
340
+ const filterField = filterFields.find((field) => field.getTarget() === lastPathSegment);
341
+ const filterRestriction = filterExpressionRestrictions.find(
342
+ (expression) => expression.Property?.$target === lastPathSegment
343
+ );
344
+ const filterable = isPathFilterable(this.getDataModelObjectPath(propertyPath));
345
+ const filterableExpression = isConstant(filterable) ? filterable.value : true;
346
+ const filterRestrictionExpression = filterRestriction?.AllowedExpressions as
347
+ | EasyFilterPropertyMetadata["filterRestriction"]
348
+ | undefined;
349
+ const codeList = getCodeList(lastPathSegment, propertyPath);
350
+ const metadata: EasyFilterPropertyMetadata = {
351
+ name: propertyPath,
352
+ label: getPathLabel(currentPath),
353
+ dataType: lastPathSegment.type,
354
+ required: filterField?.required,
355
+ defaultValue: filterField ? this.getDefaultValueForFilterField(filterField, startupParameters) : undefined,
356
+ filterable: filterField ? filterableExpression : undefined,
357
+ hiddenFilter: !filterField,
358
+ filterRestriction: filterField ? filterRestrictionExpression : undefined,
359
+ codeList,
360
+ type: this.getTokenType(
361
+ lastPathSegment,
362
+ filterRestriction?.AllowedExpressions?.toString() || "MultiRangeOrSearchExpression"
363
+ ) as Exclude<TokenType, "ValueHelp">,
364
+ unit: this.getUnitForProperty(lastPathSegment, pathString)
223
365
  };
224
- });
366
+ result.push(metadata);
367
+ } else if (this.isComplexProperty(lastPathSegment)) {
368
+ // Complex property: add all properties and navigation properties of the complex type
369
+ lastPathSegment.targetType.properties.forEach((child) => {
370
+ pathsToExplore.push([...currentPath, child]);
371
+ });
225
372
 
226
- // [Editing Status]
227
-
228
- if (ModelHelper.isMetaPathDraftSupported(definitionForPage.getMetaPath() as unknown as MetaPath<unknown>)) {
229
- // Assemble the code list for the editing status filter values:
230
- const props = new JSONModel({
231
- isDraftCollaborative: ModelHelper.isCollaborationDraftSupported(metaModel)
232
- }).createBindingContext("/");
233
-
234
- const editingStatusCodeList = DraftEditState.getEditStatesContext(props)
235
- .getObject("/")
236
- .map((state: { id: string; display: string }) => ({ value: state.id, description: state.display }));
237
-
238
- result.push({
239
- name: "$editState",
240
- filterFieldName: "$editState",
241
- label: this.getTranslatedText("FILTERBAR_EDITING_STATUS"),
242
- dataType: "Edm.String",
243
- required: false,
244
- filterable: true,
245
- codeList: editingStatusCodeList,
246
- type: "MenuWithCheckBox"
373
+ // only traverse navigation properties if we are not at the maximum depth
374
+ if (navigationDepth < maxDepth) {
375
+ lastPathSegment.targetType.navigationProperties.forEach((child) => {
376
+ pathsToExplore.push([...currentPath, child]);
377
+ });
378
+ }
379
+ } else if (isNavigationProperty(lastPathSegment)) {
380
+ // add 1:n navigation properties only if there are filter fields for at least one of the target properties
381
+ if (lastPathSegment.isCollection && !filterFields.some((field) => field.annotationPath?.startsWith(propertyPath))) {
382
+ continue;
383
+ }
384
+
385
+ lastPathSegment.targetType.entityProperties.forEach((child) => {
386
+ pathsToExplore.push([...currentPath, child]);
247
387
  });
388
+
389
+ // only traverse navigation properties if we are not at the maximum depth
390
+ if (navigationDepth < maxDepth) {
391
+ lastPathSegment.targetType.navigationProperties.forEach((child) => {
392
+ pathsToExplore.push([...currentPath, child]);
393
+ });
394
+ }
248
395
  }
249
- return result;
250
396
  }
251
- return [];
397
+
398
+ // [Editing Status]
399
+ if (ModelHelper.isMetaPathDraftSupported(definitionForPage.getMetaPath() as unknown as MetaPath<unknown>)) {
400
+ result.push(this.getEditStateFilterMetadata(metaModel));
401
+ }
402
+
403
+ // Remove properties marked for elimination (unless they are filter fields)
404
+ return result.filter((metadata) => {
405
+ return (
406
+ !metadata.hiddenFilter || // Keep if explicit filter field
407
+ !pathsToEliminate.has(metadata.name) // Keep if path not marked for elimination
408
+ );
409
+ });
252
410
  }
253
411
 
254
- async getCodeListForProperty(key: string, propertyPath: string): Promise<CodeList> {
412
+ async getCodeListForProperty(propertyPath: string): Promise<CodeList> {
255
413
  const defaultValueList = await this.getValueList(propertyPath);
256
414
 
257
415
  if (!defaultValueList) {
@@ -266,8 +424,7 @@ export default class EasyFilterBar extends BuildingBlock implements IViewStateCo
266
424
  const data = await listBinding.requestContexts();
267
425
 
268
426
  const filterGroupValues = data.map(mapValueListToCodeList(defaultValueList));
269
- this._fetchedCodeList[key] = filterGroupValues;
270
- const codeListProperty = this.filterBarMetadata.find((field) => field.name === key);
427
+ const codeListProperty = this.filterBarMetadata.find((field) => field.name === propertyPath);
271
428
  if (codeListProperty) {
272
429
  codeListProperty.codeList = filterGroupValues;
273
430
  }
@@ -279,17 +436,56 @@ export default class EasyFilterBar extends BuildingBlock implements IViewStateCo
279
436
  values: TokenSelectedValuesDefinition[]
280
437
  ): Promise<ValueHelpSelectedValuesDefinition[]> {
281
438
  const field = this.filterBarMetadata.find(({ name }) => name === fieldName);
282
- if (field) {
283
- const valueList = await this.getValueList(field.name);
439
+ let result: ValueHelpSelectedValuesDefinition[];
284
440
 
285
- if (valueList && ValueListHelper.isValueListSearchable(field.name, valueList)) {
286
- const resolvedTokenValues = await Promise.all(values.map(async (value) => resolveTokenValue(valueList, value)));
287
- return resolvedTokenValues.flat();
288
- }
441
+ if (!field) {
442
+ // return original values converted to the expected format if no field is defined
443
+ return unresolvedResult(values);
444
+ }
445
+ const valueList = await this.getValueList(field.name);
446
+
447
+ if (valueList && ValueListHelper.isValueListSearchable(field.name, valueList)) {
448
+ const resolvedTokenValues = await Promise.all(values.map(async (value) => resolveTokenValue(valueList, value)));
449
+ result = resolvedTokenValues.flat();
450
+ } else {
451
+ result = unresolvedResult(values);
452
+ }
453
+
454
+ // Apply maxLength filtering if defined
455
+ if (field.maxLength !== undefined) {
456
+ const filteredTokens = result
457
+ .map((token) => {
458
+ if (token.operator === FilterOperator.BT || token.operator === FilterOperator.NB) {
459
+ // Handle between operators - selectedValues is ValueHelpBetweenSelectedValues
460
+ const [a, b] = token.selectedValues;
461
+
462
+ // Check if both values exceed maxLength
463
+ if (String(a.value).length <= field.maxLength! && String(b.value).length <= field.maxLength!) {
464
+ return token; // Keep the token if both values are within limit
465
+ } else {
466
+ return null; // Remove the token if either value exceeds limit
467
+ }
468
+ } else {
469
+ // Handle other operators - selectedValues is CodeListType[]
470
+ const filtered: CodeListType[] = token.selectedValues.filter(
471
+ (selectedValue) => String(selectedValue.value).length <= field.maxLength!
472
+ );
473
+
474
+ // Only return the token if there are remaining values after filtering
475
+ if (filtered.length > 0) {
476
+ return { ...token, selectedValues: filtered };
477
+ } else {
478
+ return null; // Remove the token if no values remain
479
+ }
480
+ }
481
+ })
482
+ .filter((token): token is ValueHelpSelectedValuesDefinition => token !== null);
483
+
484
+ return filteredTokens;
289
485
  }
290
486
 
291
- // return original values converted to the expected format
292
- return unresolvedResult(values);
487
+ // if no maxLength is defined, return unfiltered result
488
+ return result;
293
489
  }
294
490
 
295
491
  async getValueList(fieldName: string): Promise<ValueListInfo | undefined> {