@acorex/platform 20.6.0-next.20 → 20.6.0-next.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.
@@ -725,9 +725,11 @@ class PropertyFilter {
725
725
  const entityProps = (entity.properties ?? []).slice();
726
726
  const nameToViewLayout = buildViewLayoutMap(iface.properties ?? []);
727
727
  const allowedNames = this.computeAllowedNames(entityProps.map((p) => p.name));
728
+ // Calculate recommended dialog size based on form complexity
729
+ const calculatedSize = this.calculateRecommendedDialogSize(sections, entityProps, nameToViewLayout, allowedNames);
728
730
  const dialog = this.layoutBuilder.create().dialog((d) => {
729
731
  d.setTitle(title);
730
- d.setSize(this.externalSize ?? (this.deviceService.isMobileDevice() ? 'full' : 'md'));
732
+ d.setSize(this.externalSize ?? calculatedSize);
731
733
  d.setCloseButton(true);
732
734
  d.content((layout) => {
733
735
  // Default mode: 'view' for single, 'edit' for create/update
@@ -759,7 +761,7 @@ class PropertyFilter {
759
761
  fs.formField(prop.title, (field) => {
760
762
  // Path & field-level visibility/readonly
761
763
  field.path(fieldPath);
762
- if (prop.schema?.visible) {
764
+ if (prop.schema?.visible !== undefined) {
763
765
  field.visible(prop.schema?.visible);
764
766
  }
765
767
  if (prop.schema?.readonly !== undefined) {
@@ -840,6 +842,78 @@ class PropertyFilter {
840
842
  }
841
843
  return new Set(allNames);
842
844
  }
845
+ /**
846
+ * Calculates the recommended dialog size based on form complexity.
847
+ * Considers number of sections, properties, and average field width.
848
+ *
849
+ * @param sections - Interface sections to display
850
+ * @param entityProps - All entity properties
851
+ * @param nameToViewLayout - Map of property names to their view layout configurations
852
+ * @param allowedNames - Set of property names that should be displayed (after filtering)
853
+ * @returns Recommended dialog size ('full' | 'lg' | 'md')
854
+ */
855
+ calculateRecommendedDialogSize(sections, entityProps, nameToViewLayout, allowedNames) {
856
+ // Mobile devices always use full screen
857
+ if (this.deviceService.isMobileDevice()) {
858
+ return 'full';
859
+ }
860
+ // Calculate number of visible properties
861
+ const visibleProperties = entityProps.filter((p) => allowedNames.has(p.name) && nameToViewLayout.has(p.name));
862
+ const visiblePropertyCount = visibleProperties.length;
863
+ // Calculate average colSpan to determine field width
864
+ // colSpan determines how many columns a field occupies in a 12-column grid
865
+ // Examples:
866
+ // - colSpan = 12 → 1 field per row (full width)
867
+ // - colSpan = 6 → 2 fields per row (half width each)
868
+ // - colSpan = 4 → 3 fields per row (one-third width each)
869
+ // - colSpan = 3 → 4 fields per row (one-quarter width each)
870
+ let totalColSpan = 0;
871
+ let propertiesWithLayout = 0;
872
+ let hasColSpan3 = false; // Track if any field has colSpan = 3
873
+ for (const prop of visibleProperties) {
874
+ const viewLayout = nameToViewLayout.get(prop.name);
875
+ const positions = viewLayout?.layout?.positions;
876
+ if (positions) {
877
+ // Get colSpan from the largest available breakpoint
878
+ const colSpan = positions.lg?.colSpan ?? positions.xl?.colSpan ?? positions.md?.colSpan ?? positions.sm?.colSpan ?? 12; // default: full width
879
+ totalColSpan += colSpan;
880
+ propertiesWithLayout++;
881
+ // Check if this field has colSpan = 3
882
+ if (colSpan <= 3) {
883
+ hasColSpan3 = true;
884
+ }
885
+ }
886
+ else {
887
+ // If no layout defined, assume full width (12 columns)
888
+ totalColSpan += 12;
889
+ propertiesWithLayout++;
890
+ }
891
+ }
892
+ // Average colSpan: lower value = more fields per row, higher value = fewer fields per row
893
+ const avgColSpan = propertiesWithLayout > 0 ? totalColSpan / propertiesWithLayout : 12;
894
+ // Decision logic:
895
+ // - 10+ properties → complex form → needs 'lg'
896
+ // - avgColSpan <= 4 → 3+ fields per row → needs 'lg' (more horizontal space needed)
897
+ // - hasColSpan3 && avgColSpan <= 6 → row can sum to 12 with colSpan=3 (e.g., 9+3, 5+4+3, etc.) → needs 'lg'
898
+ // - Otherwise → 'md' is sufficient
899
+ if (visiblePropertyCount >= 10) {
900
+ return 'lg';
901
+ }
902
+ // If average colSpan <= 4, it means we can fit 3+ fields per row (12/4 = 3)
903
+ // This requires more horizontal space, so use 'lg'
904
+ if (avgColSpan <= 4) {
905
+ return 'lg';
906
+ }
907
+ // If there's a field with colSpan = 3 and avgColSpan <= 6,
908
+ // it means rows can sum to 12 with multiple fields including the colSpan=3 field
909
+ // (e.g., 9+3=12, 5+4+3=12, 4+3+3+2=12, etc.)
910
+ // This needs 'lg' for better horizontal space to accommodate the layout
911
+ if (hasColSpan3 && avgColSpan <= 6) {
912
+ return 'lg';
913
+ }
914
+ // For other cases (including full-width fields), 'md' is sufficient
915
+ return 'md';
916
+ }
843
917
  }
844
918
  //#endregion
845
919
  //#region ---- Helpers ----
@@ -946,6 +1020,7 @@ class AXPCreateEntityCommand {
946
1020
  }
947
1021
  async execute(input) {
948
1022
  const excludeProperties = input['excludeProperties'];
1023
+ const dialogSize = input['dialogSize'];
949
1024
  const { entity, entityInfo, data } = input.__context__;
950
1025
  const [moduleName, entityName] = (entity || '').split('.');
951
1026
  if (!moduleName || !entityName) {
@@ -972,6 +1047,9 @@ class AXPCreateEntityCommand {
972
1047
  const translatedTitle = await this.translationService.translateAsync(entityInfo.title);
973
1048
  chain = chain.title(`${createText} ${translatedTitle}`);
974
1049
  }
1050
+ if (dialogSize) {
1051
+ chain.size(dialogSize);
1052
+ }
975
1053
  dialogRef = await chain.show();
976
1054
  if (dialogRef.action() == 'cancel') {
977
1055
  dialogRef.close();
@@ -1063,6 +1141,7 @@ class AXPUpdateEntityCommand {
1063
1141
  //#region ---- Command Execution ----
1064
1142
  async execute(input) {
1065
1143
  const excludeProperties = input['excludeProperties'];
1144
+ const dialogSize = input['dialogSize'];
1066
1145
  const { entity, entityInfo, data } = input.__context__;
1067
1146
  const [moduleName, entityName] = (entity || '').split('.');
1068
1147
  if (!moduleName || !entityName) {
@@ -1099,6 +1178,9 @@ class AXPUpdateEntityCommand {
1099
1178
  const translatedTitle = await this.translationService.translateAsync(entityInfo.title);
1100
1179
  chain = chain.title(`${editText} ${translatedTitle}`);
1101
1180
  }
1181
+ if (dialogSize) {
1182
+ chain.size(dialogSize);
1183
+ }
1102
1184
  dialogRef = await chain.show();
1103
1185
  if (dialogRef.action() === 'cancel') {
1104
1186
  dialogRef.close();