@smartbit4all/ng-client 7.3.50 → 7.3.52

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/MIGRATION-7.0.md CHANGED
@@ -2265,6 +2265,12 @@ font in parallel with the application, and a production build inlines the styles
2265
2265
  in p009) has its pair in the `material-symbols` package: `@import
2266
2266
  'material-symbols/outlined.css';`. Set `iconFont: false` next to it: a stylesheet that loads
2267
2267
  after the application started is not seen, and the library would reach for Google.
2268
+ - **The small self-hosted font** is `@fontsource/material-symbols-outlined/400.css` (≈320 KB,
2269
+ where `material-symbols` brings the full 4 MB range). It declares the font face only, so the
2270
+ `.material-symbols-outlined` class has to stand next to the import. The playground's
2271
+ `offline` configuration (`npm run startPlaygroundOffline`,
2272
+ `projects/app-playground/src/css/offline-fonts.css`) is the working example: with it no
2273
+ request leaves for Google Fonts.
2268
2274
  - **A Content Security Policy** has to allow the stylesheet and the font
2269
2275
  (`style-src https://fonts.googleapis.com`, `font-src https://fonts.gstatic.com`) whichever
2270
2276
  side links them.
package/README.md CHANGED
@@ -137,6 +137,15 @@ this.viewContext.setActionDescriptors(ACTION_DESCRIPTORS);
137
137
  this.viewContext.commonFeedbackText = 'Done.';
138
138
  ```
139
139
 
140
+ When the validation of a submitting action (`submit`) fails, a snackbar names the problem. Its text
141
+ is `descriptor.invalidFieldsText` of the action (set by the backend), else
142
+ `viewContext.commonInvalidFieldsText`, else "Hiányos vagy hibás adatok!". `{fields}` in the text is
143
+ replaced by the names of the invalid fields, comma separated:
144
+
145
+ ```ts
146
+ this.viewContext.commonInvalidFieldsText = 'Hiányos vagy hibás adatok: {fields}';
147
+ ```
148
+
140
149
  A toolbar renders the actions **addressed to its `id`** (`uiAction.toolbar == id`), pulling
141
150
  them from the screen component above it; an explicit `[uiActionModels]` binding wins. Without
142
151
  an `id` and without a binding it shows nothing.
@@ -5267,6 +5267,9 @@ class UiActionDescriptorService {
5267
5267
  if (server.feedbackText) {
5268
5268
  client.feedbackText = server.feedbackText;
5269
5269
  }
5270
+ if (server.invalidFieldsText) {
5271
+ client.invalidFieldsText = server.invalidFieldsText;
5272
+ }
5270
5273
  }
5271
5274
  // TODO use prop name to handle all dialogs
5272
5275
  // private mergeActionDescriptorDialog(
@@ -5449,18 +5452,46 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
5449
5452
  args: [{ selector: "app-success-snack-bar", template: "<span class=\"successSnakBarContainer\" matSnackBarLabel> {{ text }} </span>\n", styles: ["::ng-deep .mat-mdc-snack-bar-container{text-align:center;border-radius:2rem}.successSnakBarContainer{color:#fff}\n"] }]
5450
5453
  }], ctorParameters: () => [] });
5451
5454
 
5455
+ /** Shown when neither the action's descriptor nor the view context gives a text. */
5456
+ const DEFAULT_INVALID_FIELDS_TEXT = 'Hiányos vagy hibás adatok!';
5457
+ /** Replaced by the names of the invalid fields in the text the backend sends. */
5458
+ const INVALID_FIELDS_PLACEHOLDER = '{fields}';
5459
+ /**
5460
+ * The text of the invalid fields snackbar.
5461
+ *
5462
+ * `{fields}` in the template becomes the names of the invalid fields (each once, comma
5463
+ * separated). When there is no name to put in, the placeholder goes away together with the
5464
+ * separator before it, so "Hibás adatok: {fields}" turns into "Hibás adatok". A template without
5465
+ * the placeholder is shown as it is; no template gives the default text.
5466
+ */
5467
+ function resolveInvalidFieldsText(template, invalidFieldNames) {
5468
+ if (!template?.trim()) {
5469
+ return DEFAULT_INVALID_FIELDS_TEXT;
5470
+ }
5471
+ const names = [...new Set((invalidFieldNames ?? []).map((name) => name?.trim()).filter(Boolean))];
5472
+ const text = names.length
5473
+ ? template.split(INVALID_FIELDS_PLACEHOLDER).join(names.join(', '))
5474
+ : template.replace(/[\s:;,\-–]*\{fields\}/g, '');
5475
+ return text.trim() || DEFAULT_INVALID_FIELDS_TEXT;
5476
+ }
5477
+
5452
5478
  class InvalidFieldsSnackBarComponent {
5453
5479
  constructor() {
5454
5480
  this.data = inject(MAT_SNACK_BAR_DATA);
5481
+ this.viewContext = inject(SmartViewContextService);
5482
+ this.manager = inject(UiActionDescriptorService);
5483
+ const descriptorText = this.data.uiAction
5484
+ ? this.manager.getActionDescriptor(this.data.uiAction).invalidFieldsText
5485
+ : undefined;
5486
+ this.text = resolveInvalidFieldsText(descriptorText ?? this.viewContext.commonInvalidFieldsText, this.data.invalidFieldNames);
5455
5487
  }
5456
- ngOnInit() { }
5457
5488
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: InvalidFieldsSnackBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5458
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.8", type: InvalidFieldsSnackBarComponent, isStandalone: true, selector: "app-invalid-fields-snack-bar", ngImport: i0, template: "<div class=\"invalidFieldsSnackBar\">\n <!-- <div class=\"invalidFieldsSnackBarContainer\" *ngIf=\"data.message\">\n <span class=\"successSnakBarContainer\" matSnackBarLabel>\n {{ data.message }}\n </span>\n </div> -->\n <div class=\"invalidFieldsSnackBarContainer\">\n <span class=\"invalidFieldsMessage\" matSnackBarLabel> Hi\u00E1nyos vagy hib\u00E1s adatok! </span>\n </div>\n</div>\n", styles: [".invalidFieldsSnackBar ::ng-deep .mat-mdc-snack-bar-container{text-align:center;border-radius:2rem}.invalidFieldsMessage{color:#fff}\n"], dependencies: [{ kind: "directive", type: MatSnackBarLabel, selector: "[matSnackBarLabel]" }] }); }
5489
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.8", type: InvalidFieldsSnackBarComponent, isStandalone: true, selector: "app-invalid-fields-snack-bar", ngImport: i0, template: "<div class=\"invalidFieldsSnackBar\">\n <div class=\"invalidFieldsSnackBarContainer\">\n <span class=\"invalidFieldsMessage\" matSnackBarLabel> {{ text }} </span>\n </div>\n</div>\n", styles: [".invalidFieldsSnackBar ::ng-deep .mat-mdc-snack-bar-container{text-align:center;border-radius:2rem}.invalidFieldsMessage{color:#fff}\n"], dependencies: [{ kind: "directive", type: MatSnackBarLabel, selector: "[matSnackBarLabel]" }] }); }
5459
5490
  }
5460
5491
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: InvalidFieldsSnackBarComponent, decorators: [{
5461
5492
  type: Component,
5462
- args: [{ selector: 'app-invalid-fields-snack-bar', imports: [MatSnackBarLabel], template: "<div class=\"invalidFieldsSnackBar\">\n <!-- <div class=\"invalidFieldsSnackBarContainer\" *ngIf=\"data.message\">\n <span class=\"successSnakBarContainer\" matSnackBarLabel>\n {{ data.message }}\n </span>\n </div> -->\n <div class=\"invalidFieldsSnackBarContainer\">\n <span class=\"invalidFieldsMessage\" matSnackBarLabel> Hi\u00E1nyos vagy hib\u00E1s adatok! </span>\n </div>\n</div>\n", styles: [".invalidFieldsSnackBar ::ng-deep .mat-mdc-snack-bar-container{text-align:center;border-radius:2rem}.invalidFieldsMessage{color:#fff}\n"] }]
5463
- }] });
5493
+ args: [{ selector: 'app-invalid-fields-snack-bar', imports: [MatSnackBarLabel], template: "<div class=\"invalidFieldsSnackBar\">\n <div class=\"invalidFieldsSnackBarContainer\">\n <span class=\"invalidFieldsMessage\" matSnackBarLabel> {{ text }} </span>\n </div>\n</div>\n", styles: [".invalidFieldsSnackBar ::ng-deep .mat-mdc-snack-bar-container{text-align:center;border-radius:2rem}.invalidFieldsMessage{color:#fff}\n"] }]
5494
+ }], ctorParameters: () => [] });
5464
5495
 
5465
5496
  /**
5466
5497
  * Tokens for the three ui-action dialog services.
@@ -5535,7 +5566,7 @@ class UiActionService {
5535
5566
  };
5536
5567
  }
5537
5568
  if (invalidFields.invalidFieldKeys.length) {
5538
- this.showInvalidFieldsSnackbar(invalidFields);
5569
+ this.showInvalidFieldsSnackbar(invalidFields, uiAction);
5539
5570
  return;
5540
5571
  }
5541
5572
  }
@@ -5673,11 +5704,16 @@ class UiActionService {
5673
5704
  data: uiAction,
5674
5705
  });
5675
5706
  }
5676
- showInvalidFieldsSnackbar(invalidFields) {
5707
+ /**
5708
+ * @param uiAction the submitting action: its descriptor may carry the text of the snackbar
5709
+ * (`invalidFieldsText`). Without it the default text is shown.
5710
+ */
5711
+ showInvalidFieldsSnackbar(invalidFields, uiAction) {
5712
+ const data = { ...invalidFields, uiAction };
5677
5713
  this._snackBar.openFromComponent(InvalidFieldsSnackBarComponent, {
5678
5714
  duration: 5 * 1000,
5679
5715
  panelClass: ['backgroundColor-warn'],
5680
- data: invalidFields,
5716
+ data,
5681
5717
  });
5682
5718
  }
5683
5719
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: UiActionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
@@ -13272,7 +13308,9 @@ class SmartformwidgetComponent {
13272
13308
  }
13273
13309
  executeUiAction(uiAction) {
13274
13310
  let type = this.widgetInstance.type;
13275
- if (type !== SmartFormWidgetType.MULTI_FILE_UPLOADER && type !== SmartFormWidgetType.DIV) {
13311
+ if (type !== SmartFormWidgetType.FILE_UPLOADER &&
13312
+ type !== SmartFormWidgetType.MULTI_FILE_UPLOADER &&
13313
+ type !== SmartFormWidgetType.DIV) {
13276
13314
  return;
13277
13315
  }
13278
13316
  this.smartComponent.executeUiAction(uiAction);