@wertzui/ngx-restworld-client 7.2.0 → 8.0.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 (96) hide show
  1. package/esm2020/lib/components/restworld-file/restworld-file.component.mjs +57 -0
  2. package/esm2020/lib/components/restworld-form/restworld-form.component.mjs +188 -0
  3. package/esm2020/lib/components/restworld-id-navigation/restworld-id-navigation.component.mjs +65 -0
  4. package/esm2020/lib/components/restworld-image/restworld-image.component.mjs +164 -0
  5. package/esm2020/lib/components/restworld-inputs/restworld-inputs.mjs +306 -0
  6. package/esm2020/lib/components/restworld-label/restworld-label.component.mjs +24 -0
  7. package/esm2020/lib/components/restworld-menu-button/restworld-menu-button.component.mjs +40 -0
  8. package/esm2020/lib/components/restworld-table/restworld-table.component.mjs +157 -0
  9. package/esm2020/lib/components/restworld-validation-errors/restworld-validation-errors.component.mjs +21 -0
  10. package/esm2020/lib/models/o-data.mjs +2 -0
  11. package/esm2020/lib/models/restworld-image.mjs +2 -0
  12. package/esm2020/lib/models/restworld-options.mjs +2 -2
  13. package/esm2020/lib/models/special-properties.mjs +6 -0
  14. package/esm2020/lib/models/templating.mjs +2 -0
  15. package/esm2020/lib/restworld-client.module.mjs +83 -25
  16. package/esm2020/lib/services/o-data.service.mjs +6 -3
  17. package/esm2020/lib/services/restworld-client-collection.mjs +7 -7
  18. package/esm2020/lib/services/restworld-client.mjs +40 -29
  19. package/esm2020/lib/services/settings.service.mjs +5 -5
  20. package/esm2020/lib/views/restworld-edit-view/restworld-edit-view.component.mjs +24 -255
  21. package/esm2020/lib/views/restworld-list-view/restworld-list-view.component.mjs +49 -101
  22. package/esm2020/public-api.mjs +17 -6
  23. package/fesm2015/wertzui-ngx-restworld-client.mjs +1373 -1017
  24. package/fesm2015/wertzui-ngx-restworld-client.mjs.map +1 -1
  25. package/fesm2020/wertzui-ngx-restworld-client.mjs +1322 -978
  26. package/fesm2020/wertzui-ngx-restworld-client.mjs.map +1 -1
  27. package/index.d.ts +1 -0
  28. package/lib/components/restworld-avatar/restworld-avatar.component.d.ts +1 -0
  29. package/lib/components/restworld-avatar/restworld-avatar.component.d.ts.map +1 -0
  30. package/lib/{views/restworld-file-view/restworld-file-view.component.d.ts → components/restworld-file/restworld-file.component.d.ts} +4 -3
  31. package/lib/components/restworld-file/restworld-file.component.d.ts.map +1 -0
  32. package/lib/components/restworld-form/restworld-form.component.d.ts +53 -0
  33. package/lib/components/restworld-form/restworld-form.component.d.ts.map +1 -0
  34. package/lib/components/restworld-id-navigation/restworld-id-navigation.component.d.ts +27 -0
  35. package/lib/components/restworld-id-navigation/restworld-id-navigation.component.d.ts.map +1 -0
  36. package/lib/components/restworld-image/restworld-image.component.d.ts +62 -0
  37. package/lib/components/restworld-image/restworld-image.component.d.ts.map +1 -0
  38. package/lib/components/restworld-inputs/restworld-inputs.d.ts +146 -0
  39. package/lib/components/restworld-inputs/restworld-inputs.d.ts.map +1 -0
  40. package/lib/components/restworld-label/restworld-label.component.d.ts +14 -0
  41. package/lib/components/restworld-label/restworld-label.component.d.ts.map +1 -0
  42. package/lib/components/restworld-menu-button/restworld-menu-button.component.d.ts +12 -0
  43. package/lib/components/restworld-menu-button/restworld-menu-button.component.d.ts.map +1 -0
  44. package/lib/components/restworld-table/restworld-table.component.d.ts +54 -0
  45. package/lib/components/restworld-table/restworld-table.component.d.ts.map +1 -0
  46. package/lib/components/restworld-validation-errors/restworld-validation-errors.component.d.ts +15 -0
  47. package/lib/components/restworld-validation-errors/restworld-validation-errors.component.d.ts.map +1 -0
  48. package/lib/constants/link-names.d.ts +1 -0
  49. package/lib/constants/link-names.d.ts.map +1 -0
  50. package/lib/models/api-url.d.ts +1 -0
  51. package/lib/models/api-url.d.ts.map +1 -0
  52. package/lib/models/client-settings.d.ts +1 -0
  53. package/lib/models/client-settings.d.ts.map +1 -0
  54. package/lib/models/o-data.d.ts +7 -0
  55. package/lib/models/o-data.d.ts.map +1 -0
  56. package/lib/models/problem-details.d.ts +1 -0
  57. package/lib/models/problem-details.d.ts.map +1 -0
  58. package/lib/models/restworld-image.d.ts +28 -0
  59. package/lib/models/restworld-image.d.ts.map +1 -0
  60. package/lib/models/restworld-options.d.ts +2 -1
  61. package/lib/models/restworld-options.d.ts.map +1 -0
  62. package/lib/models/special-properties.d.ts +9 -0
  63. package/lib/models/special-properties.d.ts.map +1 -0
  64. package/lib/models/templating.d.ts +8 -0
  65. package/lib/models/templating.d.ts.map +1 -0
  66. package/lib/pipes/as.pipe.d.ts +1 -0
  67. package/lib/pipes/as.pipe.d.ts.map +1 -0
  68. package/lib/pipes/safe-url.pipe.d.ts +1 -0
  69. package/lib/pipes/safe-url.pipe.d.ts.map +1 -0
  70. package/lib/restworld-client.module.d.ts +45 -37
  71. package/lib/restworld-client.module.d.ts.map +1 -0
  72. package/lib/services/avatar-generator.d.ts +1 -0
  73. package/lib/services/avatar-generator.d.ts.map +1 -0
  74. package/lib/services/form.service.d.ts +1 -0
  75. package/lib/services/form.service.d.ts.map +1 -0
  76. package/lib/services/o-data.service.d.ts +1 -0
  77. package/lib/services/o-data.service.d.ts.map +1 -0
  78. package/lib/services/restworld-client-collection.d.ts +9 -8
  79. package/lib/services/restworld-client-collection.d.ts.map +1 -0
  80. package/lib/services/restworld-client.d.ts +12 -4
  81. package/lib/services/restworld-client.d.ts.map +1 -0
  82. package/lib/services/settings.service.d.ts +3 -2
  83. package/lib/services/settings.service.d.ts.map +1 -0
  84. package/lib/views/restworld-edit-view/restworld-edit-view.component.d.ts +16 -68
  85. package/lib/views/restworld-edit-view/restworld-edit-view.component.d.ts.map +1 -0
  86. package/lib/views/restworld-list-view/restworld-list-view.component.d.ts +25 -41
  87. package/lib/views/restworld-list-view/restworld-list-view.component.d.ts.map +1 -0
  88. package/package.json +6 -6
  89. package/public-api.d.ts +17 -5
  90. package/public-api.d.ts.map +1 -0
  91. package/wertzui-ngx-restworld-client.d.ts.map +1 -0
  92. package/esm2020/lib/views/restworld-edit-form/restworld-edit-form.component.mjs +0 -233
  93. package/esm2020/lib/views/restworld-file-view/restworld-file-view.component.mjs +0 -57
  94. package/esm2020/lib/views/restworld-image-view/restworld-image-view.component.mjs +0 -139
  95. package/lib/views/restworld-edit-form/restworld-edit-form.component.d.ts +0 -74
  96. package/lib/views/restworld-image-view/restworld-image-view.component.d.ts +0 -57
@@ -1,68 +1,70 @@
1
1
  import { __awaiter } from 'tslib';
2
2
  import * as i0 from '@angular/core';
3
- import { Injectable, Component, Input, Pipe, forwardRef, ViewChildren, ContentChild, APP_INITIALIZER, NgModule } from '@angular/core';
3
+ import { Injectable, Component, Input, Pipe, forwardRef, ViewChildren, ContentChild, EventEmitter, Output, ViewChild, APP_INITIALIZER, NgModule } from '@angular/core';
4
4
  import * as i2 from 'primeng/tooltip';
5
5
  import { TooltipModule } from 'primeng/tooltip';
6
6
  import * as i3 from 'primeng/avatar';
7
7
  import { AvatarModule } from 'primeng/avatar';
8
+ import * as i5 from '@angular/forms';
9
+ import { NG_VALUE_ACCESSOR, UntypedFormGroup, UntypedFormArray, UntypedFormControl, Validators, ControlContainer, FormGroupDirective, FormGroup, FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
10
+ import * as i4 from 'primeng/fileupload';
11
+ import { FileUpload, FileUploadModule } from 'primeng/fileupload';
12
+ import * as i2$1 from '@angular/common';
13
+ import { CommonModule } from '@angular/common';
14
+ import * as i3$1 from 'primeng/button';
15
+ import { ButtonModule } from 'primeng/button';
8
16
  import * as _ from 'lodash';
9
- import * as i1$1 from '@wertzui/ngx-hal-client';
10
- import { Resource, PropertyType, FormsResource, Link, PagedListResource, PropertyPromptDisplayType, Template } from '@wertzui/ngx-hal-client';
11
17
  import * as i1 from '@angular/platform-browser';
12
- import * as i5 from '@angular/forms';
13
- import { UntypedFormGroup, UntypedFormArray, UntypedFormControl, Validators, NG_VALUE_ACCESSOR, FormGroup, FormArray, FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
14
- import * as i2$1 from 'primeng/api';
15
- import { FilterMatchMode, ConfirmationService, MessageService } from 'primeng/api';
18
+ import * as i1$1 from '@wertzui/ngx-hal-client';
19
+ import { Resource, FormsResource, Link, PagedListResource, PropertyType, Property, NumberTemplate } from '@wertzui/ngx-hal-client';
16
20
  import { HttpHeaders } from '@angular/common/http';
17
21
  import { lastValueFrom } from 'rxjs';
18
- import * as i4 from '@angular/common';
19
- import { CommonModule } from '@angular/common';
22
+ import * as i2$3 from 'primeng/api';
23
+ import { FilterMatchMode, ConfirmationService, MessageService } from 'primeng/api';
24
+ import * as i7 from 'primeng/progressspinner';
25
+ import { ProgressSpinnerModule } from 'primeng/progressspinner';
26
+ import * as i8 from 'primeng/ripple';
27
+ import { RippleModule } from 'primeng/ripple';
28
+ import * as i2$2 from 'ngx-valdemort';
29
+ import { ValdemortModule } from 'ngx-valdemort';
30
+ import * as i9$1 from '@angular/cdk/drag-drop';
31
+ import { DragDropModule } from '@angular/cdk/drag-drop';
32
+ import * as i13 from 'primeng/dropdown';
33
+ import { DropdownModule } from 'primeng/dropdown';
34
+ import * as i14 from 'primeng/multiselect';
35
+ import { MultiSelectModule } from 'primeng/multiselect';
20
36
  import * as i4$1 from 'primeng/inputtext';
21
37
  import { InputTextModule } from 'primeng/inputtext';
22
- import * as i8$1 from 'primeng/inputnumber';
38
+ import * as i16 from 'primeng/inputnumber';
23
39
  import { InputNumberModule } from 'primeng/inputnumber';
24
- import * as i9$1 from 'primeng/calendar';
40
+ import * as i17 from 'primeng/calendar';
25
41
  import { CalendarModule } from 'primeng/calendar';
26
- import * as i5$1 from 'primeng/button';
27
- import { ButtonModule } from 'primeng/button';
28
- import * as i11 from 'primeng/checkbox';
42
+ import * as i18 from 'primeng/checkbox';
29
43
  import { CheckboxModule } from 'primeng/checkbox';
30
- import * as i6 from 'primeng/ripple';
31
- import { RippleModule } from 'primeng/ripple';
32
- import * as i13 from 'primeng/tristatecheckbox';
44
+ import * as i19 from 'primeng/tristatecheckbox';
33
45
  import { TriStateCheckboxModule } from 'primeng/tristatecheckbox';
34
- import * as i14 from 'primeng/dropdown';
35
- import { DropdownModule } from 'primeng/dropdown';
36
- import * as i15 from 'primeng/multiselect';
37
- import { MultiSelectModule } from 'primeng/multiselect';
38
- import * as i16 from 'ngx-valdemort';
39
- import { ValdemortModule } from 'ngx-valdemort';
40
- import * as i17 from '@angular/cdk/drag-drop';
41
- import { DragDropModule } from '@angular/cdk/drag-drop';
42
- import * as i8 from 'ngx-image-cropper';
46
+ import * as i8$1 from 'ngx-image-cropper';
43
47
  import { ImageCropperComponent, ImageCropperModule } from 'ngx-image-cropper';
44
- import * as i7 from 'primeng/fileupload';
45
- import { FileUpload, FileUploadModule } from 'primeng/fileupload';
46
48
  import * as i9 from 'primeng/dialog';
47
49
  import { Dialog, DialogModule } from 'primeng/dialog';
48
50
  import * as i10 from 'primeng/colorpicker';
49
51
  import { ColorPickerModule } from 'primeng/colorpicker';
50
- import * as i4$2 from '@angular/router';
52
+ import * as i3$2 from '@angular/router';
51
53
  import { RouterModule } from '@angular/router';
52
- import * as i10$1 from 'primeng/confirmdialog';
54
+ import * as i5$1 from 'primeng/splitbutton';
55
+ import { SplitButtonModule } from 'primeng/splitbutton';
56
+ import * as i3$3 from 'primeng/table';
57
+ import { TableModule } from 'primeng/table';
58
+ import * as i7$1 from 'primeng/contextmenu';
59
+ import { ContextMenuModule } from 'primeng/contextmenu';
60
+ import * as i5$2 from 'primeng/confirmdialog';
53
61
  import { ConfirmDialogModule } from 'primeng/confirmdialog';
54
- import * as i11$1 from 'primeng/toast';
62
+ import * as i6 from 'primeng/toast';
55
63
  import { ToastModule } from 'primeng/toast';
56
- import * as i12 from 'primeng/tabview';
64
+ import * as i7$2 from 'primeng/tabview';
57
65
  import { TabViewModule } from 'primeng/tabview';
58
- import * as i13$1 from 'primeng/skeleton';
66
+ import * as i8$2 from 'primeng/skeleton';
59
67
  import { SkeletonModule } from 'primeng/skeleton';
60
- import * as i14$1 from 'primeng/progressspinner';
61
- import { ProgressSpinnerModule } from 'primeng/progressspinner';
62
- import * as i7$1 from 'primeng/table';
63
- import { TableModule } from 'primeng/table';
64
- import * as i13$2 from 'primeng/splitbutton';
65
- import { SplitButtonModule } from 'primeng/splitbutton';
66
68
  import { ScrollingModule } from '@angular/cdk/scrolling';
67
69
  import { MessagesModule } from 'primeng/messages';
68
70
  import { PanelModule } from 'primeng/panel';
@@ -206,29 +208,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImpor
206
208
  type: Input
207
209
  }] } });
208
210
 
209
- class ProblemDetails extends Resource {
210
- static isProblemDetails(resource) {
211
- return resource instanceof ProblemDetails;
212
- }
213
- static containsProblemDetailsInformation(resource) {
214
- return resource && (resource instanceof ProblemDetails || (resource instanceof Resource && 'status' in resource && _.isNumber(resource['status']) && resource['status'] >= 100 && resource['status'] < 600));
215
- }
216
- static fromResource(resource) {
217
- if (!ProblemDetails.containsProblemDetailsInformation(resource))
218
- throw new Error(`The resource ${resource} does not have problem details.`);
219
- return Object.assign(new ProblemDetails(), resource);
220
- }
221
- }
222
-
223
- class RESTworldOptions {
224
- constructor(BaseUrl, Version) {
225
- this.BaseUrl = BaseUrl;
226
- this.Version = Version;
227
- if (!BaseUrl.endsWith('/'))
228
- throw new Error(`The provided BaseUrl '${BaseUrl}' does not end with a slash '/'.`);
229
- }
230
- }
231
-
232
211
  class SafeUrlPipe {
233
212
  constructor(_domSanitizer) {
234
213
  this._domSanitizer = _domSanitizer;
@@ -248,255 +227,99 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImpor
248
227
  }]
249
228
  }], ctorParameters: function () { return [{ type: i1.DomSanitizer }]; } });
250
229
 
251
- /**
252
- * Cast super type into type using generics
253
- * Return Type obtained by optional @param type OR assignment type.
254
- */
255
- class AsPipe {
256
- /**
257
- * Cast (S: SuperType) into (T: Type) using @Generics.
258
- * @param value (S: SuperType) obtained from input type.
259
- * @optional @param type (T CastingType)
260
- * type?: { new (): T }
261
- * type?: new () => T
262
- */
263
- transform(value, type) {
264
- return value;
230
+ class RestWorldFileComponent {
231
+ constructor() {
232
+ this.disabled = false;
265
233
  }
266
- }
267
- AsPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: AsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
268
- AsPipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "15.0.3", ngImport: i0, type: AsPipe, name: "as" });
269
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: AsPipe, decorators: [{
270
- type: Pipe,
271
- args: [{ name: 'as' }]
272
- }] });
273
-
274
- class FormService {
275
- createFormGroupsFromTemplates(templates) {
276
- const tabs = Object.fromEntries(Object.entries(templates).map(([name, template]) => [
277
- name,
278
- this.createFormGroupFromTemplate(template)
279
- ]));
280
- return tabs;
234
+ writeValue(obj) {
235
+ this.uri = obj;
281
236
  }
282
- createFormGroupFromTemplates(templates, ignoredProperties) {
283
- const controls = Object.fromEntries(Object.entries(templates)
284
- .filter(([key,]) => !ignoredProperties.some(p => key === p))
285
- .map(([name, template]) => [
286
- name,
287
- this.createFormGroupFromTemplate(template)
288
- ]));
289
- const formGroup = new UntypedFormGroup(controls);
290
- return formGroup;
237
+ registerOnChange(fn) {
238
+ this.onChange = fn;
291
239
  }
292
- createFormArrayFromTemplates(templates, ignoredProperties) {
293
- const controls = Object.entries(templates)
294
- .filter(([key,]) => !ignoredProperties.some(p => key === p))
295
- .map(([, template]) => this.createFormGroupFromTemplate(template));
296
- const formArray = new UntypedFormArray(controls);
297
- return formArray;
240
+ registerOnTouched() {
241
+ // not needed for this component, but needed to implement the interface
298
242
  }
299
- createFormGroupFromTemplate(template) {
300
- const controls = Object.fromEntries(template.properties.map(p => [
301
- p.name,
302
- this.createFormControl(p)
303
- ]));
304
- const formGroup = new UntypedFormGroup(controls);
305
- return formGroup;
243
+ setDisabledState(isDisabled) {
244
+ this.disabled = isDisabled;
306
245
  }
307
- createFormControl(property) {
308
- if (property.type === PropertyType.Object)
309
- return this.createFormGroupFromTemplate(property._templates['default']);
310
- if (property.type === PropertyType.Collection)
311
- return this.createFormArrayFromTemplates(property._templates, ['default']);
312
- const control = new UntypedFormControl(property.value);
313
- if (property.max)
314
- control.addValidators(Validators.max(property.max));
315
- if (property.maxLength)
316
- control.addValidators(Validators.maxLength(property.maxLength));
317
- if (property.min)
318
- control.addValidators(Validators.min(property.min));
319
- if (property.minLength)
320
- control.addValidators(Validators.minLength(property.minLength));
321
- if (property.regex)
322
- control.addValidators(Validators.pattern(property.regex));
323
- if (property.required)
324
- control.addValidators(Validators.required);
325
- if (property.type === PropertyType.Email)
326
- control.addValidators(Validators.email);
327
- return control;
246
+ fileChanged(event) {
247
+ const file = event.files[0];
248
+ const reader = new FileReader();
249
+ reader.onload = () => {
250
+ var _a;
251
+ this.uri = reader.result;
252
+ (_a = this.onChange) === null || _a === void 0 ? void 0 : _a.call(this, this.uri);
253
+ };
254
+ reader.readAsDataURL(file);
328
255
  }
329
256
  }
330
- FormService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: FormService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
331
- FormServiceprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: FormService, providedIn: 'root' });
332
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: FormService, decorators: [{
333
- type: Injectable,
334
- args: [{
335
- providedIn: 'root'
336
- }]
337
- }] });
257
+ RestWorldFileComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldFileComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
258
+ RestWorldFileComponentcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.3", type: RestWorldFileComponent, selector: "rw-file", inputs: { accept: "accept", fileName: "fileName" }, providers: [{
259
+ provide: NG_VALUE_ACCESSOR,
260
+ useExisting: forwardRef(() => RestWorldFileComponent),
261
+ multi: true
262
+ }], viewQueries: [{ propertyName: "fileUploads", predicate: FileUpload, descendants: true }], ngImport: i0, template: "<div class=\"flex align-items-center\">\r\n <p-button *ngIf=\"!uri\" [disabled]=\"true\" icon=\"pi pi-download\" class=\"mr-1\" pTooltip=\"No file present\"></p-button>\r\n <a *ngIf=\"uri\" [href]=\"uri | safeUrl\" [download]=\"fileName || 'download'\" class=\"mr-1\" pButton pTooltip=\"Download file\" icon=\"pi pi-download\"></a>\r\n <p-fileUpload chooseIcon=\"pi-upload fas fa-upload\" pTooltip=\"Upload new file\" mode=\"basic\" [auto]=\"true\" [accept]=\"accept || ''\" [customUpload]=\"true\" (uploadHandler)=\"fileChanged($event)\"></p-fileUpload>\r\n</div>\r\n", styles: ["a{text-decoration:none}a.p-button-icon-only span.p-button-label{height:1rem!important}\n"], dependencies: [{ kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "fitContent", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "directive", type: i3$1.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading"] }, { kind: "component", type: i3$1.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "style", "styleClass", "badgeClass", "ariaLabel"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: i4.FileUpload, selector: "p-fileUpload", inputs: ["name", "url", "method", "multiple", "accept", "disabled", "auto", "withCredentials", "maxFileSize", "invalidFileSizeMessageSummary", "invalidFileSizeMessageDetail", "invalidFileTypeMessageSummary", "invalidFileTypeMessageDetail", "invalidFileLimitMessageDetail", "invalidFileLimitMessageSummary", "style", "styleClass", "previewWidth", "chooseLabel", "uploadLabel", "cancelLabel", "chooseIcon", "uploadIcon", "cancelIcon", "showUploadButton", "showCancelButton", "mode", "headers", "customUpload", "fileLimit", "uploadStyleClass", "cancelStyleClass", "removeStyleClass", "chooseStyleClass", "files"], outputs: ["onBeforeUpload", "onSend", "onUpload", "onError", "onClear", "onRemove", "onSelect", "onProgress", "uploadHandler", "onImageError"] }, { kind: "pipe", type: SafeUrlPipe, name: "safeUrl" }] });
263
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldFileComponent, decorators: [{
264
+ type: Component,
265
+ args: [{ selector: 'rw-file', providers: [{
266
+ provide: NG_VALUE_ACCESSOR,
267
+ useExisting: forwardRef(() => RestWorldFileComponent),
268
+ multi: true
269
+ }], template: "<div class=\"flex align-items-center\">\r\n <p-button *ngIf=\"!uri\" [disabled]=\"true\" icon=\"pi pi-download\" class=\"mr-1\" pTooltip=\"No file present\"></p-button>\r\n <a *ngIf=\"uri\" [href]=\"uri | safeUrl\" [download]=\"fileName || 'download'\" class=\"mr-1\" pButton pTooltip=\"Download file\" icon=\"pi pi-download\"></a>\r\n <p-fileUpload chooseIcon=\"pi-upload fas fa-upload\" pTooltip=\"Upload new file\" mode=\"basic\" [auto]=\"true\" [accept]=\"accept || ''\" [customUpload]=\"true\" (uploadHandler)=\"fileChanged($event)\"></p-fileUpload>\r\n</div>\r\n", styles: ["a{text-decoration:none}a.p-button-icon-only span.p-button-label{height:1rem!important}\n"] }]
270
+ }], propDecorators: { accept: [{
271
+ type: Input
272
+ }], fileName: [{
273
+ type: Input
274
+ }], fileUploads: [{
275
+ type: ViewChildren,
276
+ args: [FileUpload]
277
+ }] } });
338
278
 
339
- class ODataService {
340
- static createFilterForProperty(property, filter) {
341
- if (!filter.value)
342
- return undefined;
343
- const oDataOperator = ODataService.createODataOperator(filter.matchMode);
344
- const comparisonValue = ODataService.createComparisonValue(property, filter.value);
345
- switch (oDataOperator) {
346
- case 'contains':
347
- case 'not contains':
348
- case 'startswith':
349
- case 'endswith':
350
- return `${oDataOperator}(${property}, ${comparisonValue})`;
351
- default:
352
- return `${property} ${oDataOperator} ${comparisonValue}`;
353
- }
279
+ class ProblemDetails extends Resource {
280
+ static isProblemDetails(resource) {
281
+ return resource instanceof ProblemDetails;
354
282
  }
355
- static createFilterForPropertyArray(property, filters) {
356
- const filter = filters
357
- .map(f => ODataService.createFilterForProperty(property, f))
358
- .filter(f => !!f)
359
- .join(` ${filters[0].operator} `);
360
- if (filter === '')
361
- return undefined;
362
- return `(${filter})`;
283
+ static containsProblemDetailsInformation(resource) {
284
+ return resource && (resource instanceof ProblemDetails || (resource instanceof Resource && 'status' in resource && _.isNumber(resource['status']) && resource['status'] >= 100 && resource['status'] < 600));
363
285
  }
364
- static createFilterFromTableLoadEvent(event, properties) {
365
- if (!event.filters || properties === undefined)
366
- return undefined;
367
- const filter = Object.entries(event.filters)
368
- // The type definition is wrong, event.filters has values of type FilterMetadata[] and not FilterMetadata.
369
- .map(([propertyName, filter]) => ({ property: ODataService.findPropertyByName(properties, propertyName), filters: filter }))
370
- .map(f => ODataService.createFilterForPropertyArray(f.property, f.filters))
371
- .filter(f => !!f)
372
- .join(' and ');
373
- if (filter === '')
374
- return undefined;
375
- return `(${filter})`;
286
+ static fromResource(resource) {
287
+ if (!ProblemDetails.containsProblemDetailsInformation(resource))
288
+ throw new Error(`The resource ${resource} does not have problem details.`);
289
+ return Object.assign(new ProblemDetails(), resource);
376
290
  }
377
- static createOrderByFromTableLoadEvent(event) {
378
- if (event.sortField) {
379
- const order = !event.sortOrder || event.sortOrder > 0 ? 'asc' : 'desc';
380
- return `${event.sortField} ${order}`;
381
- }
382
- return undefined;
291
+ }
292
+
293
+ class RestWorldClient {
294
+ constructor(_halClient, _options) {
295
+ this._halClient = _halClient;
296
+ this._options = _options;
383
297
  }
384
- static createParametersFromTableLoadEvent(event, template) {
385
- const oDataParameters = {
386
- $filter: ODataService.createFilterFromTableLoadEvent(event, template === null || template === void 0 ? void 0 : template.properties),
387
- $orderby: ODataService.createOrderByFromTableLoadEvent(event),
388
- $top: ODataService.createTopFromTableLoadEvent(event),
389
- $skip: ODataService.createSkipFromTableLoadEvent(event)
390
- };
391
- return oDataParameters;
298
+ get halClient() {
299
+ return this._halClient;
392
300
  }
393
- static createSkipFromTableLoadEvent(event) {
394
- return event.first;
301
+ static combineHeaders(originalHeaders, headersToAdd, overwriteExisting) {
302
+ if (!headersToAdd)
303
+ return originalHeaders;
304
+ if (!originalHeaders)
305
+ return headersToAdd;
306
+ let combinedHeaders = originalHeaders;
307
+ for (const key in headersToAdd.keys) {
308
+ if (!combinedHeaders.has(key) || overwriteExisting) {
309
+ const headerValuesToAdd = headersToAdd.getAll(key);
310
+ if (headerValuesToAdd)
311
+ combinedHeaders = combinedHeaders.set(key, headerValuesToAdd);
312
+ }
313
+ }
314
+ return combinedHeaders;
395
315
  }
396
- static createTopFromTableLoadEvent(event) {
397
- return event.rows;
398
- }
399
- static createComparisonValue(property, value) {
400
- if (value === null || value === undefined)
401
- return 'null';
402
- const type = property.type;
403
- switch (type) {
404
- case PropertyType.Date:
405
- return `cast(${value.toISOString()}, Edm.DateOnly)`;
406
- case PropertyType.DatetimeLocal:
407
- return `cast(${value.toISOString()}, Edm.DateTime)`;
408
- case PropertyType.DatetimeOffset:
409
- return `cast(${value.toISOString()}, Edm.DateTimeOffset)`;
410
- case PropertyType.Time:
411
- return `cast(${value.toISOString()}, Edm.TimeOnly)`;
412
- case PropertyType.Duration:
413
- return `cast(${value.toISOString()}, Edm.TimeSpan)`;
414
- default:
415
- return `'${value}'`;
416
- }
417
- }
418
- static createODataOperator(matchMode) {
419
- switch (matchMode) {
420
- case FilterMatchMode.STARTS_WITH:
421
- return 'startswith';
422
- case FilterMatchMode.CONTAINS:
423
- return 'contains';
424
- case FilterMatchMode.NOT_CONTAINS:
425
- return 'not contains';
426
- case FilterMatchMode.ENDS_WITH:
427
- return 'endswith';
428
- case FilterMatchMode.EQUALS:
429
- return 'eq';
430
- case FilterMatchMode.NOT_EQUALS:
431
- return 'ne';
432
- case FilterMatchMode.IN:
433
- return 'in';
434
- case FilterMatchMode.LESS_THAN:
435
- return 'lt';
436
- case FilterMatchMode.LESS_THAN_OR_EQUAL_TO:
437
- return 'le';
438
- case FilterMatchMode.GREATER_THAN:
439
- return 'gt';
440
- case FilterMatchMode.GREATER_THAN_OR_EQUAL_TO:
441
- return 'ge';
442
- case FilterMatchMode.IS:
443
- return 'eq';
444
- case FilterMatchMode.IS_NOT:
445
- return 'ne';
446
- case FilterMatchMode.BEFORE:
447
- return 'lt';
448
- case FilterMatchMode.AFTER:
449
- return 'gt';
450
- case FilterMatchMode.DATE_AFTER:
451
- return 'ge';
452
- case FilterMatchMode.DATE_BEFORE:
453
- return 'lt';
454
- case FilterMatchMode.DATE_IS:
455
- return 'eq';
456
- case FilterMatchMode.DATE_IS_NOT:
457
- return 'ne';
458
- default:
459
- throw Error(`Unknown matchMode ${matchMode}`);
460
- }
461
- }
462
- static findPropertyByName(properties, propertyName) {
463
- const property = properties.find(p => p.name === propertyName);
464
- if (property === undefined)
465
- throw new Error(`Cannot find a property with the name ${propertyName} in the properties of the search form template.`);
466
- return property;
467
- }
468
- }
469
-
470
- class RESTworldClient {
471
- constructor(_halClient, _options) {
472
- this._halClient = _halClient;
473
- this._options = _options;
474
- }
475
- get halClient() {
476
- return this._halClient;
477
- }
478
- static combineHeaders(originalHeaders, headersToAdd, overwriteExisting) {
479
- if (!headersToAdd)
480
- return originalHeaders;
481
- if (!originalHeaders)
482
- return headersToAdd;
483
- let combinedHeaders = originalHeaders;
484
- for (const key in headersToAdd.keys) {
485
- if (!combinedHeaders.has(key) || overwriteExisting) {
486
- const headerValuesToAdd = headersToAdd.getAll(key);
487
- if (headerValuesToAdd)
488
- combinedHeaders = combinedHeaders.set(key, headerValuesToAdd);
489
- }
490
- }
491
- return combinedHeaders;
492
- }
493
- static createHeaders(mediaType, version) {
494
- if (version)
495
- return new HttpHeaders({
496
- 'Accept': `${mediaType || 'application/hal+json'}; v=${version}`,
497
- 'Content-Type': `${mediaType || 'application/hal+json'}; v=${version}`
498
- });
499
- return new HttpHeaders();
316
+ static createHeaders(mediaType, version) {
317
+ if (version)
318
+ return new HttpHeaders({
319
+ 'Accept': `${mediaType || 'application/hal+json'}; v=${version}`,
320
+ 'Content-Type': `${mediaType || 'application/hal+json'}; v=${version}`
321
+ });
322
+ return new HttpHeaders();
500
323
  }
501
324
  delete(resource) {
502
325
  return __awaiter(this, void 0, void 0, function* () {
@@ -504,7 +327,7 @@ class RESTworldClient {
504
327
  if (!deleteLink)
505
328
  throw new Error(`The resource ${resource} does not have a delete link.`);
506
329
  const uri = deleteLink.href;
507
- const header = RESTworldClient.createHeaders('application/hal+json', this._options.Version);
330
+ const header = RestWorldClient.createHeaders('application/hal+json', this._options.Version);
508
331
  const response = yield this.halClient.delete(uri, ProblemDetails, header);
509
332
  return response;
510
333
  });
@@ -526,12 +349,17 @@ class RESTworldClient {
526
349
  getAllForms(resource) {
527
350
  return __awaiter(this, void 0, void 0, function* () {
528
351
  const urls = resource.getFormLinkHrefs();
529
- const header = RESTworldClient.createHeaders('application/prs.hal-forms+json', this._options.Version);
530
- const formsPromises = urls.map(url => this._halClient.get(url, FormsResource, ProblemDetails, header));
352
+ const formsPromises = urls.map(url => this.getForm(url));
531
353
  const formsAndProblems = yield Promise.all(formsPromises);
532
354
  return formsAndProblems;
533
355
  });
534
356
  }
357
+ getForm(url) {
358
+ return __awaiter(this, void 0, void 0, function* () {
359
+ const header = RestWorldClient.createHeaders('application/prs.hal-forms+json', this._options.Version);
360
+ return this._halClient.get(url, FormsResource, ProblemDetails, header);
361
+ });
362
+ }
535
363
  getAllLinksFromHome() {
536
364
  if (!this._homeResource)
537
365
  throw new Error('Home resource is not set. Call ensureHomeResourceIsSet() first.');
@@ -624,8 +452,8 @@ class RESTworldClient {
624
452
  const link = new Link();
625
453
  link.href = uri;
626
454
  const filledUri = link.fillTemplate(parameters);
627
- const defaultHeaders = RESTworldClient.createHeaders('application/hal+json', this._options.Version);
628
- const combinedHeaders = RESTworldClient.combineHeaders(headers, defaultHeaders, false);
455
+ const defaultHeaders = RestWorldClient.createHeaders('application/hal+json', this._options.Version);
456
+ const combinedHeaders = RestWorldClient.combineHeaders(headers, defaultHeaders, false);
629
457
  const response = yield this.halClient.get(filledUri, PagedListResource, ProblemDetails, combinedHeaders);
630
458
  return response;
631
459
  });
@@ -635,30 +463,26 @@ class RESTworldClient {
635
463
  const link = new Link();
636
464
  link.href = uri;
637
465
  const filledUri = link.fillTemplate(parameters);
638
- const defaultHeaders = RESTworldClient.createHeaders('text/csv', this._options.Version);
639
- const combinedHeaders = RESTworldClient.combineHeaders(headers, defaultHeaders, false);
466
+ const defaultHeaders = RestWorldClient.createHeaders('text/csv', this._options.Version);
467
+ const combinedHeaders = RestWorldClient.combineHeaders(headers, defaultHeaders, false);
640
468
  const response = yield lastValueFrom(this.halClient.httpClient.get(filledUri, { headers: combinedHeaders, responseType: 'blob', observe: 'response' }));
641
469
  return response;
642
470
  });
643
471
  }
644
- getSingle(relOrUri, id, headers, curie) {
472
+ getSingle(rel, id, headers, curie) {
645
473
  return __awaiter(this, void 0, void 0, function* () {
646
- let uri;
647
- if (relOrUri.startsWith('http')) {
648
- if (id !== undefined)
649
- throw new Error('When supplying a URI, an ID cannot be supplied too.');
650
- if (curie)
651
- throw new Error('When supplying a URI, a curie cannot be supplied too.');
652
- uri = relOrUri;
653
- }
654
- else {
655
- if (!_.isNumber(id))
656
- throw new Error('When supplying a rel, an ID must be supplied too.');
657
- const link = this.getLinkFromHome(relOrUri, LinkNames.get, curie);
658
- uri = link.fillTemplate({ id: id.toString() });
659
- }
660
- const defaultHeaders = RESTworldClient.createHeaders('application/hal+json', this._options.Version);
661
- const combinedHeaders = RESTworldClient.combineHeaders(headers, defaultHeaders, false);
474
+ if (!_.isNumber(id))
475
+ throw new Error('When supplying a rel, an ID must be supplied too.');
476
+ const link = this.getLinkFromHome(rel, LinkNames.get, curie);
477
+ const uri = link.fillTemplate({ id: id.toString() });
478
+ const response = this.getSingleByUri(uri, headers);
479
+ return response;
480
+ });
481
+ }
482
+ getSingleByUri(uri, headers) {
483
+ return __awaiter(this, void 0, void 0, function* () {
484
+ const defaultHeaders = RestWorldClient.createHeaders('application/hal+json', this._options.Version);
485
+ const combinedHeaders = RestWorldClient.combineHeaders(headers, defaultHeaders, false);
662
486
  const response = yield this.halClient.get(uri, Resource, ProblemDetails, combinedHeaders);
663
487
  return response;
664
488
  });
@@ -672,7 +496,7 @@ class RESTworldClient {
672
496
  throw new Error(`The save link ${saveLink} does not have a save name.`);
673
497
  const uri = saveLink.href;
674
498
  const method = saveLink.name.toLowerCase();
675
- const header = RESTworldClient.createHeaders('application/hal+json', this._options.Version);
499
+ const header = RestWorldClient.createHeaders('application/hal+json', this._options.Version);
676
500
  let response;
677
501
  switch (method) {
678
502
  case 'put':
@@ -692,7 +516,7 @@ class RESTworldClient {
692
516
  return __awaiter(this, void 0, void 0, function* () {
693
517
  const uri = template.target || '';
694
518
  const method = (_a = template.method) === null || _a === void 0 ? void 0 : _a.toLowerCase();
695
- const header = RESTworldClient.createHeaders('application/prs.hal-forms+json', this._options.Version);
519
+ const header = RestWorldClient.createHeaders('application/prs.hal-forms+json', this._options.Version);
696
520
  let response;
697
521
  switch (method) {
698
522
  case 'put':
@@ -720,7 +544,7 @@ class RESTworldClient {
720
544
  }
721
545
  getHomeForced() {
722
546
  return __awaiter(this, void 0, void 0, function* () {
723
- const header = RESTworldClient.createHeaders('application/hal+json', this._options.Version);
547
+ const header = RestWorldClient.createHeaders('application/hal+json', this._options.Version);
724
548
  const response = yield this.halClient.get(this._options.BaseUrl, Resource, ProblemDetails, header);
725
549
  return response;
726
550
  });
@@ -768,9 +592,27 @@ class RESTworldClient {
768
592
  .map(([, template]) => this.setInitialSelectedOptionsElementsForTemplate(template)));
769
593
  });
770
594
  }
595
+ deleteByTemplateAndForm(template, formGroup) {
596
+ return __awaiter(this, void 0, void 0, function* () {
597
+ const url = template.target;
598
+ if (url === undefined)
599
+ throw new Error("The target of the given template cannot be undefined.");
600
+ const timestamp = formGroup.value.timestamp;
601
+ return this.deleteByUrl(url, timestamp);
602
+ });
603
+ }
604
+ deleteByUrl(url, timestamp) {
605
+ return __awaiter(this, void 0, void 0, function* () {
606
+ let header = RestWorldClient.createHeaders('application/hal+json', this._options.Version);
607
+ if (timestamp !== undefined)
608
+ header = header.append("ETag", timestamp);
609
+ const response = yield this.halClient.delete(url, ProblemDetails, header);
610
+ return response;
611
+ });
612
+ }
771
613
  }
772
614
 
773
- class RESTworldClientCollection {
615
+ class RestWorldClientCollection {
774
616
  constructor(_halClient) {
775
617
  this._halClient = _halClient;
776
618
  this._clients = {};
@@ -782,7 +624,7 @@ class RESTworldClientCollection {
782
624
  return __awaiter(this, void 0, void 0, function* () {
783
625
  if (Object.keys(this._clients).includes(name))
784
626
  return this.getClient(name);
785
- const client = new RESTworldClient(this._halClient, options);
627
+ const client = new RestWorldClient(this._halClient, options);
786
628
  yield client.ensureHomeResourceIsSet();
787
629
  this._clients[name] = client;
788
630
  return client;
@@ -798,115 +640,245 @@ class RESTworldClientCollection {
798
640
  return this._clients;
799
641
  }
800
642
  }
801
- RESTworldClientCollection.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RESTworldClientCollection, deps: [{ token: i1$1.HalClient }], target: i0.ɵɵFactoryTarget.Injectable });
802
- RESTworldClientCollection.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RESTworldClientCollection, providedIn: 'root' });
803
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RESTworldClientCollection, decorators: [{
643
+ RestWorldClientCollection.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldClientCollection, deps: [{ token: i1$1.HalClient }], target: i0.ɵɵFactoryTarget.Injectable });
644
+ RestWorldClientCollection.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldClientCollection, providedIn: 'root' });
645
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldClientCollection, decorators: [{
804
646
  type: Injectable,
805
647
  args: [{
806
648
  providedIn: 'root'
807
649
  }]
808
650
  }], ctorParameters: function () { return [{ type: i1$1.HalClient }]; } });
809
651
 
810
- class SettingsService {
811
- constructor(_clients) {
812
- this._clients = _clients;
813
- this.initializing = false;
814
- this.initialized = false;
652
+ class FormService {
653
+ createFormGroupsFromTemplates(templates) {
654
+ const tabs = Object.fromEntries(Object.entries(templates).map(([name, template]) => [
655
+ name,
656
+ this.createFormGroupFromTemplate(template)
657
+ ]));
658
+ return tabs;
815
659
  }
816
- get settings() {
817
- return SettingsService._settings;
660
+ createFormGroupFromTemplates(templates, ignoredProperties) {
661
+ const controls = Object.fromEntries(Object.entries(templates)
662
+ .filter(([key,]) => !ignoredProperties.some(p => key === p))
663
+ .map(([name, template]) => [
664
+ name,
665
+ this.createFormGroupFromTemplate(template)
666
+ ]));
667
+ const formGroup = new UntypedFormGroup(controls);
668
+ return formGroup;
818
669
  }
819
- ensureInitialized() {
820
- return __awaiter(this, void 0, void 0, function* () {
821
- if (this.initializing || this.initialized)
822
- return;
823
- this.initializing = true;
824
- yield SettingsService.ensureSettingsAreLoaded();
825
- yield this.populateRESTworldClientCollectionFromSettings();
826
- this.initialized = true;
827
- this.initializing = false;
828
- });
670
+ createFormArrayFromTemplates(templates, ignoredProperties) {
671
+ const controls = Object.entries(templates)
672
+ .filter(([key,]) => !ignoredProperties.some(p => key === p))
673
+ .map(([, template]) => this.createFormGroupFromTemplate(template));
674
+ const formArray = new UntypedFormArray(controls);
675
+ return formArray;
829
676
  }
830
- /**
831
- * Call this method in your main.ts before calling bootstrapModule(...)
832
- *
833
- * Example:
834
- * async function main() {
835
- * try {
836
- * await SettingsService.ensureSettingsAreLoaded();
837
- *
838
- * const providers : StaticProvider[] = [
839
- * { provide: 'BASE_URL', useFactory: getBaseUrl, deps: [] }
840
- * ];
841
- *
842
- * await platformBrowserDynamic(providers).bootstrapModule(AppModule);
843
- * }
844
- * catch (e) {
845
- * console.error(e);
846
- * }
847
- * }
848
- *
849
- * main();
850
- * */
851
- static ensureSettingsAreLoaded() {
852
- return __awaiter(this, void 0, void 0, function* () {
853
- if (SettingsService._settings === undefined) {
854
- const response = yield fetch('/settings');
855
- const settings = yield response.json();
856
- SettingsService._settings = settings;
857
- }
858
- });
677
+ createFormGroupFromTemplate(template) {
678
+ const controls = Object.fromEntries(template.properties.map(p => [
679
+ p.name,
680
+ this.createFormControl(p)
681
+ ]));
682
+ const formGroup = new UntypedFormGroup(controls);
683
+ return formGroup;
859
684
  }
860
- populateRESTworldClientCollectionFromSettings() {
861
- var _a;
862
- return __awaiter(this, void 0, void 0, function* () {
863
- if (!((_a = this.settings) === null || _a === void 0 ? void 0 : _a.apiUrls))
864
- return;
865
- yield Promise.all(this.settings.apiUrls
866
- .map(api => this._clients.addOrGetExistingClient(api.name, new RESTworldOptions(api.url, api.version))));
867
- });
685
+ createFormControl(property) {
686
+ if (property.type === PropertyType.Object)
687
+ return this.createFormGroupFromTemplate(property._templates['default']);
688
+ if (property.type === PropertyType.Collection)
689
+ return this.createFormArrayFromTemplates(property._templates, ['default']);
690
+ const control = new UntypedFormControl(property.value);
691
+ if (property.max)
692
+ control.addValidators(Validators.max(property.max));
693
+ if (property.maxLength)
694
+ control.addValidators(Validators.maxLength(property.maxLength));
695
+ if (property.min)
696
+ control.addValidators(Validators.min(property.min));
697
+ if (property.minLength)
698
+ control.addValidators(Validators.minLength(property.minLength));
699
+ if (property.regex)
700
+ control.addValidators(Validators.pattern(property.regex));
701
+ if (property.required)
702
+ control.addValidators(Validators.required);
703
+ if (property.type === PropertyType.Email)
704
+ control.addValidators(Validators.email);
705
+ return control;
868
706
  }
869
707
  }
870
- SettingsService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: SettingsService, deps: [{ token: RESTworldClientCollection }], target: i0.ɵɵFactoryTarget.Injectable });
871
- SettingsService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: SettingsService, providedIn: 'root' });
872
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: SettingsService, decorators: [{
708
+ FormService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: FormService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
709
+ FormService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: FormService, providedIn: 'root' });
710
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: FormService, decorators: [{
873
711
  type: Injectable,
874
712
  args: [{
875
713
  providedIn: 'root'
876
714
  }]
877
- }], ctorParameters: function () { return [{ type: RESTworldClientCollection }]; } });
715
+ }] });
878
716
 
879
- class RESTWorldImageViewComponent {
880
- constructor() {
881
- this.disabled = false;
882
- this.displayCropDialog = false;
883
- }
884
- writeValue(obj) {
885
- this.uri = obj;
886
- }
887
- registerOnChange(fn) {
888
- this.onChange = fn;
889
- }
890
- registerOnTouched() {
891
- // not needed for this component, but needed to implement the interface
892
- }
893
- setDisabledState(isDisabled) {
894
- this.disabled = isDisabled;
895
- }
896
- ngOnInit() {
897
- // If no background color is set, we set it to white.
898
- // Otherwise the color picker would show red, the input would be empty and the image cropper would show transparent.
899
- if (!this.backgroundColor)
900
- this.backgroundColor = '#ffffff';
901
- }
902
- ngOnDestroy() {
903
- var _a;
904
- (_a = this._subscriptions) === null || _a === void 0 ? void 0 : _a.forEach(s => s.unsubscribe());
717
+ class PropertyWithImage extends Property {
718
+ }
719
+ class PropertyWithOptions extends Property {
720
+ }
721
+
722
+ /**
723
+ * A label that is generated from the given property.
724
+ * If you also want an input element, you can either use RestWorldFormElement <rw-form-element> to have a label and an input rendered,
725
+ * or use RestWorldInput <rw-input> which will just render the input element, so you can freely place this label.
726
+ */
727
+ class RestWorldLabelComponent {
728
+ get PropertyType() {
729
+ return PropertyType;
905
730
  }
906
- ngAfterViewInit() {
907
- var _a;
908
- // We need to trigger imageLoadedInView each time, after the opening animation of the dialog has been completed.
909
- // Otherwise the image cropper initially (and after every window resize) thinks that the image size is 0x0,
731
+ }
732
+ RestWorldLabelComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldLabelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
733
+ RestWorldLabelComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.3", type: RestWorldLabelComponent, selector: "rw-label", inputs: { property: "property" }, ngImport: i0, template: "<label \r\n *ngIf=\"property.type !== PropertyType.Hidden\" \r\n [attr.for]=\"property.name\"\r\n [class.p-disabled]=\"property.readOnly\">\r\n {{property.prompt ?? property.name}}\r\n</label>", styles: [".label-hidden{visibility:hidden}.label-collapsed{display:none}\n"], dependencies: [{ kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }] });
734
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldLabelComponent, decorators: [{
735
+ type: Component,
736
+ args: [{ selector: 'rw-label', viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }], template: "<label \r\n *ngIf=\"property.type !== PropertyType.Hidden\" \r\n [attr.for]=\"property.name\"\r\n [class.p-disabled]=\"property.readOnly\">\r\n {{property.prompt ?? property.name}}\r\n</label>", styles: [".label-hidden{visibility:hidden}.label-collapsed{display:none}\n"] }]
737
+ }], propDecorators: { property: [{
738
+ type: Input
739
+ }] } });
740
+
741
+ /**
742
+ * Displays validation errors either for one property or for a whole form.
743
+ */
744
+ class RestWorldValidationErrorsComponent {
745
+ }
746
+ RestWorldValidationErrorsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldValidationErrorsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
747
+ RestWorldValidationErrorsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.3", type: RestWorldValidationErrorsComponent, selector: "rw-validation-errors", inputs: { property: "property", form: "form" }, ngImport: i0, template: "<val-errors *ngIf=\"property\" [controlName]=\"property.name ?? null\">\n <ng-template valError=\"required\">The field '{{property.prompt ?? property.name}}' is required.</ng-template>\n <ng-template valError=\"email\">The email must be a valid email address.</ng-template>\n <ng-template valError=\"min\" let-error=\"error\">'{{property.prompt ?? property.name}}' must be equal or greater than or equal to {{ error.min }}.</ng-template>\n <ng-template valError=\"max\" let-error=\"error\">'{{property.prompt ?? property.name}}' must be smaller than or equal to {{ error.max }}.</ng-template>\n <ng-template valError=\"minlength\" let-error=\"error\">The length of '{{property.prompt ?? property.name}}' must be equal or greater than or equal to {{ error.requiredLength }}.</ng-template>\n <ng-template valError=\"maxlength\" let-error=\"error\">The length of '{{property.prompt ?? property.name}}' must be shorter than or equal to {{ error.requiredLength }}.</ng-template>\n <ng-template valError=\"pattern\" let-error=\"error\">The value for '{{property.prompt ?? property.name}}' does not match the pattern {{ error }}.</ng-template>\n <ng-template valError=\"remote\" let-error=\"error\">{{ error }}</ng-template>\n</val-errors>\n\n<val-errors *ngIf=\"form\" [control]=\"form\">\n <ng-template valError=\"remote\" let-error=\"error\">{{ error }}</ng-template>\n</val-errors>", styles: [""], dependencies: [{ kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2$2.ValidationErrorsComponent, selector: "val-errors", inputs: ["control", "controlName", "label"] }, { kind: "directive", type: i2$2.ValidationErrorDirective, selector: "ng-template[valError]", inputs: ["valError"] }], viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }] });
748
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldValidationErrorsComponent, decorators: [{
749
+ type: Component,
750
+ args: [{ selector: 'rw-validation-errors', viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }], template: "<val-errors *ngIf=\"property\" [controlName]=\"property.name ?? null\">\n <ng-template valError=\"required\">The field '{{property.prompt ?? property.name}}' is required.</ng-template>\n <ng-template valError=\"email\">The email must be a valid email address.</ng-template>\n <ng-template valError=\"min\" let-error=\"error\">'{{property.prompt ?? property.name}}' must be equal or greater than or equal to {{ error.min }}.</ng-template>\n <ng-template valError=\"max\" let-error=\"error\">'{{property.prompt ?? property.name}}' must be smaller than or equal to {{ error.max }}.</ng-template>\n <ng-template valError=\"minlength\" let-error=\"error\">The length of '{{property.prompt ?? property.name}}' must be equal or greater than or equal to {{ error.requiredLength }}.</ng-template>\n <ng-template valError=\"maxlength\" let-error=\"error\">The length of '{{property.prompt ?? property.name}}' must be shorter than or equal to {{ error.requiredLength }}.</ng-template>\n <ng-template valError=\"pattern\" let-error=\"error\">The value for '{{property.prompt ?? property.name}}' does not match the pattern {{ error }}.</ng-template>\n <ng-template valError=\"remote\" let-error=\"error\">{{ error }}</ng-template>\n</val-errors>\n\n<val-errors *ngIf=\"form\" [control]=\"form\">\n <ng-template valError=\"remote\" let-error=\"error\">{{ error }}</ng-template>\n</val-errors>" }]
751
+ }], propDecorators: { property: [{
752
+ type: Input
753
+ }], form: [{
754
+ type: Input
755
+ }] } });
756
+
757
+ /**
758
+ * Cast super type into type using generics
759
+ * Return Type obtained by optional @param type OR assignment type.
760
+ */
761
+ class AsPipe {
762
+ /**
763
+ * Cast (S: SuperType) into (T: Type) using @Generics.
764
+ * @param value (S: SuperType) obtained from input type.
765
+ * @optional @param type (T CastingType)
766
+ * type?: { new (): T }
767
+ * type?: new () => T
768
+ */
769
+ transform(value, type) {
770
+ return value;
771
+ }
772
+ }
773
+ AsPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: AsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
774
+ AsPipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "15.0.3", ngImport: i0, type: AsPipe, name: "as" });
775
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: AsPipe, decorators: [{
776
+ type: Pipe,
777
+ args: [{ name: 'as' }]
778
+ }] });
779
+
780
+ class RestWorldImageComponent {
781
+ constructor() {
782
+ this.disabled = false;
783
+ this.displayCropDialog = false;
784
+ }
785
+ get alt() {
786
+ var _a;
787
+ return (_a = this.property.prompt) !== null && _a !== void 0 ? _a : this.property.name;
788
+ }
789
+ get accept() {
790
+ var _a, _b;
791
+ return (_b = (_a = this.property.restWorldImage.accept) !== null && _a !== void 0 ? _a : this.property.placeholder) !== null && _b !== void 0 ? _b : "image/*";
792
+ }
793
+ get fileName() {
794
+ var _a;
795
+ return this.property.name + "." + ((_a = this.property.restWorldImage.format) !== null && _a !== void 0 ? _a : ".png");
796
+ }
797
+ get alignImage() {
798
+ return this.property.restWorldImage.alignImage;
799
+ }
800
+ get aspectRatio() {
801
+ return this.property.restWorldImage.aspectRatio;
802
+ }
803
+ get backgroundColor() {
804
+ return this.property.restWorldImage.backgroundColor;
805
+ }
806
+ set backgroundColor(value) {
807
+ this.property.restWorldImage.backgroundColor = value;
808
+ }
809
+ get canvasRotation() {
810
+ return this.property.restWorldImage.canvasRotation;
811
+ }
812
+ get containWithinAspectRatio() {
813
+ return this.property.restWorldImage.containWithinAspectRatio;
814
+ }
815
+ get cropper() {
816
+ return this.property.restWorldImage.cropper;
817
+ }
818
+ get cropperMaxHeight() {
819
+ return this.property.restWorldImage.cropperMaxHeight;
820
+ }
821
+ get cropperMaxWidth() {
822
+ return this.property.restWorldImage.cropperMaxWidth;
823
+ }
824
+ get cropperMinHeight() {
825
+ return this.property.restWorldImage.cropperMinHeight;
826
+ }
827
+ get cropperMinWidth() {
828
+ return this.property.restWorldImage.cropperMinWidth;
829
+ }
830
+ get cropperStaticHeight() {
831
+ return this.property.restWorldImage.cropperStaticHeight;
832
+ }
833
+ get cropperStaticWidth() {
834
+ return this.property.restWorldImage.cropperStaticWidth;
835
+ }
836
+ get format() {
837
+ return this.property.restWorldImage.format;
838
+ }
839
+ get imageQuality() {
840
+ return this.property.restWorldImage.imageQuality;
841
+ }
842
+ get initialStepSize() {
843
+ return this.property.restWorldImage.initialStepSize;
844
+ }
845
+ get maintainAspectRatio() {
846
+ return this.property.restWorldImage.maintainAspectRatio;
847
+ }
848
+ get onlyScaleDown() {
849
+ return this.property.restWorldImage.onlyScaleDown;
850
+ }
851
+ get resizeToWidth() {
852
+ return this.property.restWorldImage.resizeToWidth;
853
+ }
854
+ get resizeToHeight() {
855
+ return this.property.restWorldImage.resizeToHeight;
856
+ }
857
+ get roundCropper() {
858
+ return this.property.restWorldImage.roundCropper;
859
+ }
860
+ writeValue(obj) {
861
+ this.uri = obj;
862
+ }
863
+ registerOnChange(fn) {
864
+ this.onChange = fn;
865
+ }
866
+ registerOnTouched() {
867
+ // not needed for this component, but needed to implement the interface
868
+ }
869
+ setDisabledState(isDisabled) {
870
+ this.disabled = isDisabled;
871
+ }
872
+ ngOnInit() {
873
+ // If no background color is set, we set it to white.
874
+ // Otherwise the color picker would show red, the input would be empty and the image cropper would show transparent.
875
+ if (!this.backgroundColor)
876
+ this.backgroundColor = '#ffffff';
877
+ }
878
+ ngAfterViewInit() {
879
+ var _a;
880
+ // We need to trigger imageLoadedInView each time, after the opening animation of the dialog has been completed.
881
+ // Otherwise the image cropper initially (and after every window resize) thinks that the image size is 0x0,
910
882
  // because the opening animation hast just begun when the image cropper is first shown.
911
883
  (_a = this.dialogs) === null || _a === void 0 ? void 0 : _a.map(d => d.onShow.subscribe(() => { var _a; return (_a = this.imageCroppers) === null || _a === void 0 ? void 0 : _a.forEach(i => { i.imageLoadedInView(); }); }));
912
884
  }
@@ -932,64 +904,20 @@ class RESTWorldImageViewComponent {
932
904
  this.displayCropDialog = false;
933
905
  }
934
906
  }
935
- RESTWorldImageViewComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RESTWorldImageViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
936
- RESTWorldImageViewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.3", type: RESTWorldImageViewComponent, selector: "rw-image", inputs: { alt: "alt", accept: "accept", fileName: "fileName", alignImage: "alignImage", aspectRatio: "aspectRatio", backgroundColor: "backgroundColor", canvasRotation: "canvasRotation", containWithinAspectRatio: "containWithinAspectRatio", cropper: "cropper", cropperMaxHeight: "cropperMaxHeight", cropperMaxWidth: "cropperMaxWidth", cropperMinHeight: "cropperMinHeight", cropperMinWidth: "cropperMinWidth", cropperStaticHeight: "cropperStaticHeight", cropperStaticWidth: "cropperStaticWidth", format: "format", imageQuality: "imageQuality", initialStepSize: "initialStepSize", maintainAspectRatio: "maintainAspectRatio", onlyScaleDown: "onlyScaleDown", resizeToWidth: "resizeToWidth", resizeToHeight: "resizeToHeight", roundCropper: "roundCropper" }, providers: [{
907
+ RestWorldImageComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldImageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
908
+ RestWorldImageComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.3", type: RestWorldImageComponent, selector: "rw-image", inputs: { property: "property" }, providers: [{
937
909
  provide: NG_VALUE_ACCESSOR,
938
- useExisting: forwardRef(() => RESTWorldImageViewComponent),
910
+ useExisting: forwardRef(() => RestWorldImageComponent),
939
911
  multi: true
940
- }], viewQueries: [{ propertyName: "fileUploads", predicate: FileUpload, descendants: true }, { propertyName: "imageCroppers", predicate: ImageCropperComponent, descendants: true }, { propertyName: "dialogs", predicate: Dialog, descendants: true }], ngImport: i0, template: "<div class=\"flex align-items-center\">\r\n <p-button *ngIf=\"!uri\" [disabled]=\"true\" icon=\"pi pi-download\" class=\"mr-1\" pTooltip=\"No image present\"></p-button>\r\n <a *ngIf=\"uri\" [href]=\"uri | safeUrl\" [download]=\"fileName || 'download'\" class=\"mr-1\" pButton pTooltip=\"Download image\" icon=\"pi pi-download\"></a>\r\n <p-fileUpload class=\"mr-1\" chooseIcon=\"pi-upload fas fa-upload\" mode=\"basic\" [auto]=\"true\" [accept]=\"accept || 'image/*'\" [customUpload]=\"true\" (uploadHandler)=\"imageChanged($event)\" pTooltip=\"Upload new image\"></p-fileUpload>\r\n <img *ngIf=\"uri\" class=\"thumbnail\" [src]=\"uri | safeUrl\" [alt]=\"alt\" (click)=\"showCropDialog()\" pTooltip=\"Zoom and crop\" />\r\n</div>\r\n\r\n<p-dialog [header]=\"alt ?? ''\" [(visible)]=\"displayCropDialog\">\r\n <image-cropper\r\n [autoCrop]=\"true\"\r\n (imageCropped)=\"croppedImageChanged($event)\"\r\n [alignImage]=\"alignImage ?? 'center'\"\r\n [aspectRatio]=\"aspectRatio ?? 1\"\r\n [backgroundColor]=\"backgroundColor ?? null\"\r\n [canvasRotation]=\"canvasRotation ?? 0\"\r\n [containWithinAspectRatio]=\"containWithinAspectRatio ?? false\"\r\n [cropper]=\"cropper ?? { x1: -100, y1: -100, x2: 10000, y2: 10000 }\"\r\n [cropperMaxHeight]=\"cropperMaxHeight ?? 0\"\r\n [cropperMaxWidth]=\"cropperMaxWidth ?? 0\"\r\n [cropperMinHeight]=\"cropperMinHeight ?? 0\"\r\n [cropperMinWidth]=\"cropperMinWidth ?? 0\"\r\n [cropperStaticHeight]=\"cropperStaticHeight ?? 0\"\r\n [cropperStaticWidth]=\"cropperStaticWidth ?? 0\"\r\n [format]=\"format ?? 'png'\"\r\n [imageQuality]=\"imageQuality ?? 92\"\r\n [initialStepSize]=\"initialStepSize ?? 3\"\r\n [maintainAspectRatio]=\"maintainAspectRatio ?? true\"\r\n [onlyScaleDown]=\"onlyScaleDown ?? false\"\r\n [resizeToWidth]=\"resizeToWidth ?? 0\"\r\n [resizeToHeight]=\"resizeToHeight ?? 0\"\r\n [roundCropper]=\"roundCropper ?? false\"\r\n [imageFile]=\"tempImageFile!\"\r\n [imageURL]=\"uri!\"\r\n ></image-cropper>\r\n <div class=\"flex justify-content-end\">\r\n <div class=\"flex-auto align-items-center\">\r\n <span>Background color:&nbsp;</span>\r\n <p-colorPicker [(ngModel)]=\"backgroundColor\" appendTo=\"body\" class=\"ml-1 mr-1\"></p-colorPicker>\r\n <input pInputText [(ngModel)]=\"backgroundColor\" />\r\n </div>\r\n <button type=\"button\" pButton pRipple (click)=\"acceptCroppedImage()\" class=\"mr-2\">Ok</button>\r\n <button type=\"button\" pButton pRipple (click)=\"closeCropDialog()\">Cancel</button>\r\n </div>\r\n</p-dialog>\r\n", styles: ["img.thumbnail{height:calc(1rem + 18px);cursor:zoom-in;border-radius:3px}a{text-decoration:none;height:calc(1rem + 18px)}a.p-button-icon-only span.p-button-label{height:1rem!important}\n"], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "fitContent", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]" }, { kind: "directive", type: i5$1.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading"] }, { kind: "component", type: i5$1.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "style", "styleClass", "badgeClass", "ariaLabel"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: i6.Ripple, selector: "[pRipple]" }, { kind: "component", type: i7.FileUpload, selector: "p-fileUpload", inputs: ["name", "url", "method", "multiple", "accept", "disabled", "auto", "withCredentials", "maxFileSize", "invalidFileSizeMessageSummary", "invalidFileSizeMessageDetail", "invalidFileTypeMessageSummary", "invalidFileTypeMessageDetail", "invalidFileLimitMessageDetail", "invalidFileLimitMessageSummary", "style", "styleClass", "previewWidth", "chooseLabel", "uploadLabel", "cancelLabel", "chooseIcon", "uploadIcon", "cancelIcon", "showUploadButton", "showCancelButton", "mode", "headers", "customUpload", "fileLimit", "uploadStyleClass", "cancelStyleClass", "removeStyleClass", "chooseStyleClass", "files"], outputs: ["onBeforeUpload", "onSend", "onUpload", "onError", "onClear", "onRemove", "onSelect", "onProgress", "uploadHandler", "onImageError"] }, { kind: "component", type: i8.ImageCropperComponent, selector: "image-cropper", inputs: ["imageChangedEvent", "imageURL", "imageBase64", "imageFile", "imageAltText", "format", "transform", "maintainAspectRatio", "aspectRatio", "resetCropOnAspectRatioChange", "resizeToWidth", "resizeToHeight", "cropperMinWidth", "cropperMinHeight", "cropperMaxHeight", "cropperMaxWidth", "cropperStaticWidth", "cropperStaticHeight", "canvasRotation", "initialStepSize", "roundCropper", "onlyScaleDown", "imageQuality", "autoCrop", "backgroundColor", "containWithinAspectRatio", "hideResizeSquares", "allowMoveImage", "cropper", "alignImage", "disabled", "hidden"], outputs: ["imageCropped", "startCropImage", "imageLoaded", "cropperReady", "loadImageFailed", "transformChange"] }, { kind: "component", type: i9.Dialog, selector: "p-dialog", inputs: ["header", "draggable", "resizable", "positionLeft", "positionTop", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "responsive", "appendTo", "breakpoints", "styleClass", "maskStyleClass", "showHeader", "breakpoint", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "visible", "style", "position"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "component", type: i10.ColorPicker, selector: "p-colorPicker", inputs: ["style", "styleClass", "inline", "format", "appendTo", "disabled", "tabindex", "inputId", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onChange", "onShow", "onHide"] }, { kind: "pipe", type: SafeUrlPipe, name: "safeUrl" }] });
941
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RESTWorldImageViewComponent, decorators: [{
912
+ }], viewQueries: [{ propertyName: "fileUploads", predicate: FileUpload, descendants: true }, { propertyName: "imageCroppers", predicate: ImageCropperComponent, descendants: true }, { propertyName: "dialogs", predicate: Dialog, descendants: true }], ngImport: i0, template: "<div class=\"flex align-items-center\">\r\n <p-button *ngIf=\"!uri\" [disabled]=\"true\" icon=\"pi pi-download\" class=\"mr-1\" pTooltip=\"No image present\"></p-button>\r\n <a *ngIf=\"uri\" [href]=\"uri | safeUrl\" [download]=\"fileName || 'download'\" class=\"mr-1\" pButton pTooltip=\"Download image\" icon=\"pi pi-download\"></a>\r\n <p-fileUpload class=\"mr-1\" chooseIcon=\"pi-upload fas fa-upload\" mode=\"basic\" [auto]=\"true\" [accept]=\"accept || 'image/*'\" [customUpload]=\"true\" (uploadHandler)=\"imageChanged($event)\" pTooltip=\"Upload new image\"></p-fileUpload>\r\n <img *ngIf=\"uri\" class=\"thumbnail\" [src]=\"uri | safeUrl\" [alt]=\"alt\" (click)=\"showCropDialog()\" pTooltip=\"Zoom and crop\" />\r\n</div>\r\n\r\n<p-dialog [header]=\"alt ?? ''\" [(visible)]=\"displayCropDialog\">\r\n <image-cropper\r\n [autoCrop]=\"true\"\r\n (imageCropped)=\"croppedImageChanged($event)\"\r\n [alignImage]=\"alignImage ?? 'center'\"\r\n [aspectRatio]=\"aspectRatio ?? 1\"\r\n [backgroundColor]=\"backgroundColor ?? null\"\r\n [canvasRotation]=\"canvasRotation ?? 0\"\r\n [containWithinAspectRatio]=\"containWithinAspectRatio ?? false\"\r\n [cropper]=\"cropper ?? { x1: -100, y1: -100, x2: 10000, y2: 10000 }\"\r\n [cropperMaxHeight]=\"cropperMaxHeight ?? 0\"\r\n [cropperMaxWidth]=\"cropperMaxWidth ?? 0\"\r\n [cropperMinHeight]=\"cropperMinHeight ?? 0\"\r\n [cropperMinWidth]=\"cropperMinWidth ?? 0\"\r\n [cropperStaticHeight]=\"cropperStaticHeight ?? 0\"\r\n [cropperStaticWidth]=\"cropperStaticWidth ?? 0\"\r\n [format]=\"format ?? 'png'\"\r\n [imageQuality]=\"imageQuality ?? 92\"\r\n [initialStepSize]=\"initialStepSize ?? 3\"\r\n [maintainAspectRatio]=\"maintainAspectRatio ?? true\"\r\n [onlyScaleDown]=\"onlyScaleDown ?? false\"\r\n [resizeToWidth]=\"resizeToWidth ?? 0\"\r\n [resizeToHeight]=\"resizeToHeight ?? 0\"\r\n [roundCropper]=\"roundCropper ?? false\"\r\n [imageFile]=\"tempImageFile!\"\r\n [imageURL]=\"uri!\"\r\n ></image-cropper>\r\n <div class=\"flex justify-content-end\">\r\n <div class=\"flex-auto align-items-center\">\r\n <span>Background color:&nbsp;</span>\r\n <p-colorPicker [(ngModel)]=\"backgroundColor\" appendTo=\"body\" class=\"ml-1 mr-1\"></p-colorPicker>\r\n <input pInputText [(ngModel)]=\"backgroundColor\" />\r\n </div>\r\n <button type=\"button\" pButton pRipple (click)=\"acceptCroppedImage()\" class=\"mr-2\">Ok</button>\r\n <button type=\"button\" pButton pRipple (click)=\"closeCropDialog()\">Cancel</button>\r\n </div>\r\n</p-dialog>\r\n", styles: ["img.thumbnail{height:calc(1rem + 18px);cursor:zoom-in;border-radius:3px}a{text-decoration:none}a.p-button-icon-only span.p-button-label{height:1rem!important}\n"], dependencies: [{ kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "fitContent", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]" }, { kind: "directive", type: i3$1.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading"] }, { kind: "component", type: i3$1.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "style", "styleClass", "badgeClass", "ariaLabel"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: i8.Ripple, selector: "[pRipple]" }, { kind: "component", type: i4.FileUpload, selector: "p-fileUpload", inputs: ["name", "url", "method", "multiple", "accept", "disabled", "auto", "withCredentials", "maxFileSize", "invalidFileSizeMessageSummary", "invalidFileSizeMessageDetail", "invalidFileTypeMessageSummary", "invalidFileTypeMessageDetail", "invalidFileLimitMessageDetail", "invalidFileLimitMessageSummary", "style", "styleClass", "previewWidth", "chooseLabel", "uploadLabel", "cancelLabel", "chooseIcon", "uploadIcon", "cancelIcon", "showUploadButton", "showCancelButton", "mode", "headers", "customUpload", "fileLimit", "uploadStyleClass", "cancelStyleClass", "removeStyleClass", "chooseStyleClass", "files"], outputs: ["onBeforeUpload", "onSend", "onUpload", "onError", "onClear", "onRemove", "onSelect", "onProgress", "uploadHandler", "onImageError"] }, { kind: "component", type: i8$1.ImageCropperComponent, selector: "image-cropper", inputs: ["imageChangedEvent", "imageURL", "imageBase64", "imageFile", "imageAltText", "format", "transform", "maintainAspectRatio", "aspectRatio", "resetCropOnAspectRatioChange", "resizeToWidth", "resizeToHeight", "cropperMinWidth", "cropperMinHeight", "cropperMaxHeight", "cropperMaxWidth", "cropperStaticWidth", "cropperStaticHeight", "canvasRotation", "initialStepSize", "roundCropper", "onlyScaleDown", "imageQuality", "autoCrop", "backgroundColor", "containWithinAspectRatio", "hideResizeSquares", "allowMoveImage", "cropper", "alignImage", "disabled", "hidden"], outputs: ["imageCropped", "startCropImage", "imageLoaded", "cropperReady", "loadImageFailed", "transformChange"] }, { kind: "component", type: i9.Dialog, selector: "p-dialog", inputs: ["header", "draggable", "resizable", "positionLeft", "positionTop", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "responsive", "appendTo", "breakpoints", "styleClass", "maskStyleClass", "showHeader", "breakpoint", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "visible", "style", "position"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "component", type: i10.ColorPicker, selector: "p-colorPicker", inputs: ["style", "styleClass", "inline", "format", "appendTo", "disabled", "tabindex", "inputId", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onChange", "onShow", "onHide"] }, { kind: "pipe", type: SafeUrlPipe, name: "safeUrl" }] });
913
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldImageComponent, decorators: [{
942
914
  type: Component,
943
915
  args: [{ selector: 'rw-image', providers: [{
944
916
  provide: NG_VALUE_ACCESSOR,
945
- useExisting: forwardRef(() => RESTWorldImageViewComponent),
917
+ useExisting: forwardRef(() => RestWorldImageComponent),
946
918
  multi: true
947
- }], template: "<div class=\"flex align-items-center\">\r\n <p-button *ngIf=\"!uri\" [disabled]=\"true\" icon=\"pi pi-download\" class=\"mr-1\" pTooltip=\"No image present\"></p-button>\r\n <a *ngIf=\"uri\" [href]=\"uri | safeUrl\" [download]=\"fileName || 'download'\" class=\"mr-1\" pButton pTooltip=\"Download image\" icon=\"pi pi-download\"></a>\r\n <p-fileUpload class=\"mr-1\" chooseIcon=\"pi-upload fas fa-upload\" mode=\"basic\" [auto]=\"true\" [accept]=\"accept || 'image/*'\" [customUpload]=\"true\" (uploadHandler)=\"imageChanged($event)\" pTooltip=\"Upload new image\"></p-fileUpload>\r\n <img *ngIf=\"uri\" class=\"thumbnail\" [src]=\"uri | safeUrl\" [alt]=\"alt\" (click)=\"showCropDialog()\" pTooltip=\"Zoom and crop\" />\r\n</div>\r\n\r\n<p-dialog [header]=\"alt ?? ''\" [(visible)]=\"displayCropDialog\">\r\n <image-cropper\r\n [autoCrop]=\"true\"\r\n (imageCropped)=\"croppedImageChanged($event)\"\r\n [alignImage]=\"alignImage ?? 'center'\"\r\n [aspectRatio]=\"aspectRatio ?? 1\"\r\n [backgroundColor]=\"backgroundColor ?? null\"\r\n [canvasRotation]=\"canvasRotation ?? 0\"\r\n [containWithinAspectRatio]=\"containWithinAspectRatio ?? false\"\r\n [cropper]=\"cropper ?? { x1: -100, y1: -100, x2: 10000, y2: 10000 }\"\r\n [cropperMaxHeight]=\"cropperMaxHeight ?? 0\"\r\n [cropperMaxWidth]=\"cropperMaxWidth ?? 0\"\r\n [cropperMinHeight]=\"cropperMinHeight ?? 0\"\r\n [cropperMinWidth]=\"cropperMinWidth ?? 0\"\r\n [cropperStaticHeight]=\"cropperStaticHeight ?? 0\"\r\n [cropperStaticWidth]=\"cropperStaticWidth ?? 0\"\r\n [format]=\"format ?? 'png'\"\r\n [imageQuality]=\"imageQuality ?? 92\"\r\n [initialStepSize]=\"initialStepSize ?? 3\"\r\n [maintainAspectRatio]=\"maintainAspectRatio ?? true\"\r\n [onlyScaleDown]=\"onlyScaleDown ?? false\"\r\n [resizeToWidth]=\"resizeToWidth ?? 0\"\r\n [resizeToHeight]=\"resizeToHeight ?? 0\"\r\n [roundCropper]=\"roundCropper ?? false\"\r\n [imageFile]=\"tempImageFile!\"\r\n [imageURL]=\"uri!\"\r\n ></image-cropper>\r\n <div class=\"flex justify-content-end\">\r\n <div class=\"flex-auto align-items-center\">\r\n <span>Background color:&nbsp;</span>\r\n <p-colorPicker [(ngModel)]=\"backgroundColor\" appendTo=\"body\" class=\"ml-1 mr-1\"></p-colorPicker>\r\n <input pInputText [(ngModel)]=\"backgroundColor\" />\r\n </div>\r\n <button type=\"button\" pButton pRipple (click)=\"acceptCroppedImage()\" class=\"mr-2\">Ok</button>\r\n <button type=\"button\" pButton pRipple (click)=\"closeCropDialog()\">Cancel</button>\r\n </div>\r\n</p-dialog>\r\n", styles: ["img.thumbnail{height:calc(1rem + 18px);cursor:zoom-in;border-radius:3px}a{text-decoration:none;height:calc(1rem + 18px)}a.p-button-icon-only span.p-button-label{height:1rem!important}\n"] }]
948
- }], propDecorators: { alt: [{
949
- type: Input
950
- }], accept: [{
951
- type: Input
952
- }], fileName: [{
953
- type: Input
954
- }], alignImage: [{
955
- type: Input
956
- }], aspectRatio: [{
957
- type: Input
958
- }], backgroundColor: [{
959
- type: Input
960
- }], canvasRotation: [{
961
- type: Input
962
- }], containWithinAspectRatio: [{
963
- type: Input
964
- }], cropper: [{
965
- type: Input
966
- }], cropperMaxHeight: [{
967
- type: Input
968
- }], cropperMaxWidth: [{
969
- type: Input
970
- }], cropperMinHeight: [{
971
- type: Input
972
- }], cropperMinWidth: [{
973
- type: Input
974
- }], cropperStaticHeight: [{
975
- type: Input
976
- }], cropperStaticWidth: [{
977
- type: Input
978
- }], format: [{
979
- type: Input
980
- }], imageQuality: [{
981
- type: Input
982
- }], initialStepSize: [{
983
- type: Input
984
- }], maintainAspectRatio: [{
985
- type: Input
986
- }], onlyScaleDown: [{
987
- type: Input
988
- }], resizeToWidth: [{
989
- type: Input
990
- }], resizeToHeight: [{
991
- type: Input
992
- }], roundCropper: [{
919
+ }], template: "<div class=\"flex align-items-center\">\r\n <p-button *ngIf=\"!uri\" [disabled]=\"true\" icon=\"pi pi-download\" class=\"mr-1\" pTooltip=\"No image present\"></p-button>\r\n <a *ngIf=\"uri\" [href]=\"uri | safeUrl\" [download]=\"fileName || 'download'\" class=\"mr-1\" pButton pTooltip=\"Download image\" icon=\"pi pi-download\"></a>\r\n <p-fileUpload class=\"mr-1\" chooseIcon=\"pi-upload fas fa-upload\" mode=\"basic\" [auto]=\"true\" [accept]=\"accept || 'image/*'\" [customUpload]=\"true\" (uploadHandler)=\"imageChanged($event)\" pTooltip=\"Upload new image\"></p-fileUpload>\r\n <img *ngIf=\"uri\" class=\"thumbnail\" [src]=\"uri | safeUrl\" [alt]=\"alt\" (click)=\"showCropDialog()\" pTooltip=\"Zoom and crop\" />\r\n</div>\r\n\r\n<p-dialog [header]=\"alt ?? ''\" [(visible)]=\"displayCropDialog\">\r\n <image-cropper\r\n [autoCrop]=\"true\"\r\n (imageCropped)=\"croppedImageChanged($event)\"\r\n [alignImage]=\"alignImage ?? 'center'\"\r\n [aspectRatio]=\"aspectRatio ?? 1\"\r\n [backgroundColor]=\"backgroundColor ?? null\"\r\n [canvasRotation]=\"canvasRotation ?? 0\"\r\n [containWithinAspectRatio]=\"containWithinAspectRatio ?? false\"\r\n [cropper]=\"cropper ?? { x1: -100, y1: -100, x2: 10000, y2: 10000 }\"\r\n [cropperMaxHeight]=\"cropperMaxHeight ?? 0\"\r\n [cropperMaxWidth]=\"cropperMaxWidth ?? 0\"\r\n [cropperMinHeight]=\"cropperMinHeight ?? 0\"\r\n [cropperMinWidth]=\"cropperMinWidth ?? 0\"\r\n [cropperStaticHeight]=\"cropperStaticHeight ?? 0\"\r\n [cropperStaticWidth]=\"cropperStaticWidth ?? 0\"\r\n [format]=\"format ?? 'png'\"\r\n [imageQuality]=\"imageQuality ?? 92\"\r\n [initialStepSize]=\"initialStepSize ?? 3\"\r\n [maintainAspectRatio]=\"maintainAspectRatio ?? true\"\r\n [onlyScaleDown]=\"onlyScaleDown ?? false\"\r\n [resizeToWidth]=\"resizeToWidth ?? 0\"\r\n [resizeToHeight]=\"resizeToHeight ?? 0\"\r\n [roundCropper]=\"roundCropper ?? false\"\r\n [imageFile]=\"tempImageFile!\"\r\n [imageURL]=\"uri!\"\r\n ></image-cropper>\r\n <div class=\"flex justify-content-end\">\r\n <div class=\"flex-auto align-items-center\">\r\n <span>Background color:&nbsp;</span>\r\n <p-colorPicker [(ngModel)]=\"backgroundColor\" appendTo=\"body\" class=\"ml-1 mr-1\"></p-colorPicker>\r\n <input pInputText [(ngModel)]=\"backgroundColor\" />\r\n </div>\r\n <button type=\"button\" pButton pRipple (click)=\"acceptCroppedImage()\" class=\"mr-2\">Ok</button>\r\n <button type=\"button\" pButton pRipple (click)=\"closeCropDialog()\">Cancel</button>\r\n </div>\r\n</p-dialog>\r\n", styles: ["img.thumbnail{height:calc(1rem + 18px);cursor:zoom-in;border-radius:3px}a{text-decoration:none}a.p-button-icon-only span.p-button-label{height:1rem!important}\n"] }]
920
+ }], propDecorators: { property: [{
993
921
  type: Input
994
922
  }], fileUploads: [{
995
923
  type: ViewChildren,
@@ -1002,145 +930,145 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImpor
1002
930
  args: [Dialog]
1003
931
  }] } });
1004
932
 
1005
- class RESTWorldFileViewComponent {
1006
- constructor() {
1007
- this.disabled = false;
1008
- }
1009
- writeValue(obj) {
1010
- this.uri = obj;
1011
- }
1012
- registerOnChange(fn) {
1013
- this.onChange = fn;
1014
- }
1015
- registerOnTouched() {
1016
- // not needed for this component, but needed to implement the interface
1017
- }
1018
- setDisabledState(isDisabled) {
1019
- this.disabled = isDisabled;
933
+ /**
934
+ * A form element with a label that is automatically created from a property in a form template.
935
+ * This may also be a complex object or a collection in which case multiple and nested input elements may be rendered.
936
+ * If you want a form element without a label, use RestWorldFormInput <rw-form-input>.
937
+ */
938
+ class RestWorldFormElementComponent {
939
+ }
940
+ RestWorldFormElementComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldFormElementComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
941
+ RestWorldFormElementComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.3", type: RestWorldFormElementComponent, selector: "rw-form-element", inputs: { property: "property", apiName: "apiName" }, ngImport: i0, template: "<div class=\"grid field\">\r\n <rw-label [property]=\"property\" class=\"col-12 md:col-2 flex align-items-center\"></rw-label>\r\n <rw-input [apiName]=\"apiName\" [property]=\"property\" class=\"col-12 md:col-10\"></rw-input>\r\n</div>\r\n", styles: [""], dependencies: [{ kind: "component", type: i0.forwardRef(function () { return RestWorldInputComponent; }), selector: "rw-input", inputs: ["property", "apiName"] }, { kind: "component", type: i0.forwardRef(function () { return RestWorldLabelComponent; }), selector: "rw-label", inputs: ["property"] }], viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }] });
942
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldFormElementComponent, decorators: [{
943
+ type: Component,
944
+ args: [{ selector: 'rw-form-element', viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }], template: "<div class=\"grid field\">\r\n <rw-label [property]=\"property\" class=\"col-12 md:col-2 flex align-items-center\"></rw-label>\r\n <rw-input [apiName]=\"apiName\" [property]=\"property\" class=\"col-12 md:col-10\"></rw-input>\r\n</div>\r\n" }]
945
+ }], propDecorators: { property: [{
946
+ type: Input
947
+ }], apiName: [{
948
+ type: Input
949
+ }] } });
950
+ /**
951
+ * A form input element that is automatically created from a property in a form template.
952
+ * This may also be a complex object or a collection in which case multiple and nested input elements may be rendered.
953
+ * If you also want a label, use RestWorldFormElement <rw-form-element>.
954
+ * You can also use one of the different RestWorldInput... <rw-input-...> elements to render a specific input,
955
+ * but it is advised to control the rendered input through the passed in property.
956
+ */
957
+ class RestWorldInputComponent {
958
+ get PropertyType() {
959
+ return PropertyType;
1020
960
  }
1021
- fileChanged(event) {
1022
- const file = event.files[0];
1023
- const reader = new FileReader();
1024
- reader.onload = () => {
1025
- var _a;
1026
- this.uri = reader.result;
1027
- (_a = this.onChange) === null || _a === void 0 ? void 0 : _a.call(this, this.uri);
1028
- };
1029
- reader.readAsDataURL(file);
961
+ get PropertyWithOptions() {
962
+ return PropertyWithOptions;
1030
963
  }
1031
964
  }
1032
- RESTWorldFileViewComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RESTWorldFileViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1033
- RESTWorldFileViewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.3", type: RESTWorldFileViewComponent, selector: "rw-file", inputs: { accept: "accept", fileName: "fileName" }, providers: [{
1034
- provide: NG_VALUE_ACCESSOR,
1035
- useExisting: forwardRef(() => RESTWorldFileViewComponent),
1036
- multi: true
1037
- }], viewQueries: [{ propertyName: "fileUploads", predicate: FileUpload, descendants: true }], ngImport: i0, template: "<div class=\"flex align-items-center\">\r\n <p-button *ngIf=\"!uri\" [disabled]=\"true\" icon=\"pi pi-download\" class=\"mr-1\" pTooltip=\"No file present\"></p-button>\r\n <a *ngIf=\"uri\" [href]=\"uri | safeUrl\" [download]=\"fileName || 'download'\" class=\"mr-1\" pButton pTooltip=\"Download file\" icon=\"pi pi-download\"></a>\r\n <p-fileUpload chooseIcon=\"pi-upload fas fa-upload\" pTooltip=\"Upload new file\" mode=\"basic\" [auto]=\"true\" [accept]=\"accept || ''\" [customUpload]=\"true\" (uploadHandler)=\"fileChanged($event)\"></p-fileUpload>\r\n</div>\r\n", styles: ["a{text-decoration:none;height:calc(1rem + 18px)}a.p-button-icon-only span.p-button-label{height:1rem!important}\n"], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "fitContent", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "directive", type: i5$1.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading"] }, { kind: "component", type: i5$1.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "style", "styleClass", "badgeClass", "ariaLabel"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: i7.FileUpload, selector: "p-fileUpload", inputs: ["name", "url", "method", "multiple", "accept", "disabled", "auto", "withCredentials", "maxFileSize", "invalidFileSizeMessageSummary", "invalidFileSizeMessageDetail", "invalidFileTypeMessageSummary", "invalidFileTypeMessageDetail", "invalidFileLimitMessageDetail", "invalidFileLimitMessageSummary", "style", "styleClass", "previewWidth", "chooseLabel", "uploadLabel", "cancelLabel", "chooseIcon", "uploadIcon", "cancelIcon", "showUploadButton", "showCancelButton", "mode", "headers", "customUpload", "fileLimit", "uploadStyleClass", "cancelStyleClass", "removeStyleClass", "chooseStyleClass", "files"], outputs: ["onBeforeUpload", "onSend", "onUpload", "onError", "onClear", "onRemove", "onSelect", "onProgress", "uploadHandler", "onImageError"] }, { kind: "pipe", type: SafeUrlPipe, name: "safeUrl" }] });
1038
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RESTWorldFileViewComponent, decorators: [{
965
+ RestWorldInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
966
+ RestWorldInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.3", type: RestWorldInputComponent, selector: "rw-input", inputs: { property: "property", apiName: "apiName" }, ngImport: i0, template: "<rw-input-dropdown *ngIf=\"property.options\" [apiName]=\"apiName\" [property]=\"property | as:PropertyWithOptions\"></rw-input-dropdown>\r\n\r\n<ng-container *ngIf=\"!property.options\">\r\n <ng-container [ngSwitch]=\"property.type\">\r\n <rw-input-object *ngSwitchCase=\"PropertyType.Object\" [apiName]=\"apiName\" [property]=\"property\"></rw-input-object>\r\n <rw-input-collection *ngSwitchCase=\"PropertyType.Collection\" [apiName]=\"apiName\" [property]=\"property\"></rw-input-collection>\r\n <rw-input-simple *ngSwitchDefault [property]=\"property\"></rw-input-simple>\r\n </ng-container>\r\n</ng-container>\r\n\r\n<rw-validation-errors [property]=\"property\"></rw-validation-errors>", styles: [""], dependencies: [{ kind: "directive", type: i0.forwardRef(function () { return i2$1.NgIf; }), selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i0.forwardRef(function () { return i2$1.NgSwitch; }), selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i0.forwardRef(function () { return i2$1.NgSwitchCase; }), selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i0.forwardRef(function () { return i2$1.NgSwitchDefault; }), selector: "[ngSwitchDefault]" }, { kind: "component", type: i0.forwardRef(function () { return RestWorldInputDropdownComponent; }), selector: "rw-input-dropdown", inputs: ["property", "apiName"] }, { kind: "component", type: i0.forwardRef(function () { return RestWorldInputCollectionComponent; }), selector: "rw-input-collection", inputs: ["property", "apiName"] }, { kind: "component", type: i0.forwardRef(function () { return RestWorldInputObjectComponent; }), selector: "rw-input-object", inputs: ["property", "apiName"] }, { kind: "component", type: i0.forwardRef(function () { return RestWorldInputSimpleComponent; }), selector: "rw-input-simple", inputs: ["property"] }, { kind: "component", type: i0.forwardRef(function () { return RestWorldValidationErrorsComponent; }), selector: "rw-validation-errors", inputs: ["property", "form"] }, { kind: "pipe", type: i0.forwardRef(function () { return AsPipe; }), name: "as" }], viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }] });
967
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldInputComponent, decorators: [{
1039
968
  type: Component,
1040
- args: [{ selector: 'rw-file', providers: [{
1041
- provide: NG_VALUE_ACCESSOR,
1042
- useExisting: forwardRef(() => RESTWorldFileViewComponent),
1043
- multi: true
1044
- }], template: "<div class=\"flex align-items-center\">\r\n <p-button *ngIf=\"!uri\" [disabled]=\"true\" icon=\"pi pi-download\" class=\"mr-1\" pTooltip=\"No file present\"></p-button>\r\n <a *ngIf=\"uri\" [href]=\"uri | safeUrl\" [download]=\"fileName || 'download'\" class=\"mr-1\" pButton pTooltip=\"Download file\" icon=\"pi pi-download\"></a>\r\n <p-fileUpload chooseIcon=\"pi-upload fas fa-upload\" pTooltip=\"Upload new file\" mode=\"basic\" [auto]=\"true\" [accept]=\"accept || ''\" [customUpload]=\"true\" (uploadHandler)=\"fileChanged($event)\"></p-fileUpload>\r\n</div>\r\n", styles: ["a{text-decoration:none;height:calc(1rem + 18px)}a.p-button-icon-only span.p-button-label{height:1rem!important}\n"] }]
1045
- }], propDecorators: { accept: [{
969
+ args: [{ selector: 'rw-input', viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }], template: "<rw-input-dropdown *ngIf=\"property.options\" [apiName]=\"apiName\" [property]=\"property | as:PropertyWithOptions\"></rw-input-dropdown>\r\n\r\n<ng-container *ngIf=\"!property.options\">\r\n <ng-container [ngSwitch]=\"property.type\">\r\n <rw-input-object *ngSwitchCase=\"PropertyType.Object\" [apiName]=\"apiName\" [property]=\"property\"></rw-input-object>\r\n <rw-input-collection *ngSwitchCase=\"PropertyType.Collection\" [apiName]=\"apiName\" [property]=\"property\"></rw-input-collection>\r\n <rw-input-simple *ngSwitchDefault [property]=\"property\"></rw-input-simple>\r\n </ng-container>\r\n</ng-container>\r\n\r\n<rw-validation-errors [property]=\"property\"></rw-validation-errors>" }]
970
+ }], propDecorators: { property: [{
1046
971
  type: Input
1047
- }], fileName: [{
972
+ }], apiName: [{
1048
973
  type: Input
1049
- }], fileUploads: [{
1050
- type: ViewChildren,
1051
- args: [FileUpload]
1052
- }] } });
1053
-
1054
- class RestworldEditFormComponent {
1055
- constructor(_formService, _changeDetectorRef, _messageService, _clients) {
974
+ }] } });
975
+ /**
976
+ * A collection that is automatically created from the given property.
977
+ * The collection supports drag & drop to re order the elements and can also be nested.
978
+ * It is advised to use RestWorldInputComponent <rw-input> and control the rendered inputs with the passed in property
979
+ * instead of using this component directly.
980
+ */
981
+ class RestWorldInputCollectionComponent {
982
+ constructor(_controlContainer, _formService, _changeDetectorRef) {
983
+ this._controlContainer = _controlContainer;
1056
984
  this._formService = _formService;
1057
985
  this._changeDetectorRef = _changeDetectorRef;
1058
- this._messageService = _messageService;
1059
- this._clients = _clients;
1060
- this.UntypedFormGroup = (FormGroup);
1061
- this.UntypedFormArray = (FormArray);
1062
- this.Number = Number;
986
+ this._templates = [];
1063
987
  }
1064
- get PropertyType() {
1065
- return PropertyType;
988
+ get templates() {
989
+ return this._templates;
1066
990
  }
1067
- get PropertyPromptDisplayType() {
1068
- return PropertyPromptDisplayType;
991
+ get defaultTemplate() {
992
+ if (this._defaultTemplate === undefined)
993
+ throw new Error("No default template found.");
994
+ return this._defaultTemplate;
1069
995
  }
1070
- get dateFormat() {
1071
- return new Date(3333, 11, 22)
1072
- .toLocaleDateString()
1073
- .replace("22", "dd")
1074
- .replace("11", "mm")
1075
- .replace("3333", "yy")
1076
- .replace("33", "y");
996
+ get innerFormArray() {
997
+ if (this._innerFormArray === undefined)
998
+ throw new Error("formGroup is not set.");
999
+ return this._innerFormArray;
1077
1000
  }
1078
1001
  ngOnInit() {
1079
- if (!this.formGroup)
1080
- throw new Error("[formGroup] is required on <rw-form>");
1081
- if (!this.template)
1082
- throw new Error("[template] is required on <rw-form>");
1083
- if (!this.apiName)
1084
- throw new Error("[apiName] is required on <rw-form>");
1085
- }
1086
- getTooltip(resource, keysToExclude) {
1087
- const tooltip = Object.entries(resource)
1088
- .filter(([key]) => !(key.startsWith('_') || ['createdAt', 'createdBy', 'lastChangedAt', 'lastChangedBy', 'timestamp'].includes(key) || (keysToExclude === null || keysToExclude === void 0 ? void 0 : keysToExclude.includes(key))))
1089
- .reduce((prev, [key, value], index) => `${prev}${index === 0 ? '' : '\n'}${key}: ${RestworldEditFormComponent.jsonStringifyWithElipsis(value)}`, '');
1090
- return tooltip;
1091
- }
1092
- static jsonStringifyWithElipsis(value) {
1093
- const maxLength = 200;
1094
- const end = 10;
1095
- const start = maxLength - end - 2;
1096
- const json = JSON.stringify(value);
1097
- const shortened = json.length > maxLength ? json.substring(0, start) + '…' + json.substring(json.length - end) : json;
1098
- return shortened;
1002
+ const formGroup = this._controlContainer.control;
1003
+ this._innerFormArray = formGroup.controls[this.property.name];
1004
+ this._templates = RestWorldInputCollectionComponent.getCollectionEntryTemplates(this.property);
1005
+ this._defaultTemplate = this.property._templates.default;
1099
1006
  }
1100
- getCollectionEntryTemplates(property) {
1007
+ static getCollectionEntryTemplates(property) {
1101
1008
  if (!property)
1102
1009
  return [];
1103
1010
  return Object.entries(property._templates)
1104
- .filter(([key,]) => Number.isInteger(Number.parseInt(key)))
1105
- .map(([, value]) => value);
1011
+ .filter(([key, value]) => { var _a; return Number.isInteger(Number.parseInt(key)) && Number.isInteger(Number.parseInt((_a = value.title) !== null && _a !== void 0 ? _a : "")); })
1012
+ .map(([, value]) => new NumberTemplate(value));
1106
1013
  }
1107
- addNewItemToCollection(property, formArray) {
1108
- if (!(formArray instanceof (FormArray)))
1109
- throw new Error('formArray is not an instance of FormArray.');
1110
- const maxIndex = Math.max(...Object.keys(property._templates)
1014
+ addNewItemToCollection() {
1015
+ const maxIndex = Math.max(...Object.keys(this.templates)
1111
1016
  .map(key => Number.parseInt(key))
1112
1017
  .filter(key => Number.isSafeInteger(key)));
1113
1018
  const nextIndex = maxIndex < 0 ? 0 : maxIndex + 1;
1114
- const defaultTemplate = property._templates['default'];
1115
- const copiedTemplateDto = JSON.parse(JSON.stringify(defaultTemplate));
1116
- const copiedTemplate = new Template(copiedTemplateDto);
1117
- copiedTemplate.title = nextIndex.toString();
1118
- property._templates[copiedTemplate.title] = copiedTemplate;
1119
- formArray.push(this._formService.createFormGroupFromTemplate(defaultTemplate));
1120
- }
1121
- deleteItemFromCollection(property, formArray, template) {
1122
- if (!template.title)
1123
- throw new Error(`Cannot delete the item, because the template '${template}' does not have a title.`);
1124
- if (!(formArray instanceof (FormArray)))
1125
- throw new Error('formArray is not an instance of FormArray.');
1126
- const templates = property._templates;
1127
- delete templates[template.title];
1128
- formArray.removeAt(Number.parseInt(template.title));
1019
+ const copiedTemplateDto = JSON.parse(JSON.stringify(this.defaultTemplate));
1020
+ const copiedTemplate = new NumberTemplate(copiedTemplateDto);
1021
+ copiedTemplate.title = nextIndex;
1022
+ this.templates[copiedTemplate.title] = copiedTemplate;
1023
+ this.innerFormArray.push(this._formService.createFormGroupFromTemplate(this.defaultTemplate));
1024
+ }
1025
+ deleteItemFromCollection(template) {
1026
+ delete this.templates[template.title];
1027
+ this.innerFormArray.removeAt(template.title);
1129
1028
  }
1130
1029
  collectionItemDropped($event) {
1131
- const formArray = $event.container.data.formArray;
1132
1030
  const previousIndex = $event.previousIndex;
1133
1031
  const currentIndex = $event.currentIndex;
1134
1032
  const movementDirection = currentIndex > previousIndex ? 1 : -1;
1135
1033
  // Move in FormArray
1136
1034
  // We do not need to move the item in the _templates object
1137
- const movedControl = formArray.at(previousIndex);
1035
+ const movedControl = this.innerFormArray.at(previousIndex);
1138
1036
  for (let i = previousIndex; i * movementDirection < currentIndex * movementDirection; i = i + movementDirection) {
1139
- formArray.setControl(i, formArray.at(i + movementDirection));
1037
+ this.innerFormArray.setControl(i, this.innerFormArray.at(i + movementDirection));
1140
1038
  }
1141
- formArray.setControl(currentIndex, movedControl);
1039
+ this.innerFormArray.setControl(currentIndex, movedControl);
1142
1040
  this._changeDetectorRef.markForCheck();
1143
- console.log($event);
1041
+ }
1042
+ }
1043
+ RestWorldInputCollectionComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldInputCollectionComponent, deps: [{ token: i5.ControlContainer }, { token: FormService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
1044
+ RestWorldInputCollectionComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.3", type: RestWorldInputCollectionComponent, selector: "rw-input-collection", inputs: { property: "property", apiName: "apiName" }, queries: [{ propertyName: "inputCollectionRef", first: true, predicate: ["inputCollection"], descendants: true }], ngImport: i0, template: "<div class=\"flex align-items-center\">\n <div class=\"brace\">\n </div>\n <div class=\"w-full\" cdkDropList (cdkDropListDropped)=\"collectionItemDropped($event)\">\n <div *ngFor=\"let template of templates\" class=\"flex align-items-center\" cdkDrag>\n <i class=\"fas fa-grip-lines\" cdkDragHandle></i>\n <div class=\"brace\">\n </div>\n <div class=\"w-full flex justify-content-end\">\n <rw-input-template [formGroup]=\"innerFormArray.controls[template.title]\" [template]=\"defaultTemplate\" [apiName]=\"apiName\" class=\"w-full\"></rw-input-template>\n <button pButton pRipple type=\"button\" icon=\"fas fa-trash\" class=\"p-button-outlined p-button-danger ml-2 mb-3\" (click)=\"deleteItemFromCollection(template)\"></button>\n </div>\n </div>\n <div class=\"flex justify-content-end w-full\">\n <button pButton pRipple type=\"button\" icon=\"fas fa-plus\" class=\"p-button-outlined p-button-info\" (click)=\"addNewItemToCollection()\"></button>\n </div>\n </div>\n</div>", styles: [".cdk-drag-handle{cursor:move}.cdk-drag-preview{background-color:#ffffffd0;border:2px dashed rgb(206,212,218);cursor:move}.cdk-drag-placeholder{border:2px dashed rgb(206,212,218);margin:-2px}.brace{align-self:stretch;margin:.2rem .5rem;border-left:1px solid rgb(206,212,218);border-top:1px solid rgb(206,212,218);border-bottom:1px solid rgb(206,212,218);width:1rem}\n"], dependencies: [{ kind: "directive", type: i0.forwardRef(function () { return i2$1.NgForOf; }), selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i0.forwardRef(function () { return i5.NgControlStatusGroup; }), selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i0.forwardRef(function () { return i5.FormGroupDirective; }), selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i0.forwardRef(function () { return i3$1.ButtonDirective; }), selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading"] }, { kind: "directive", type: i0.forwardRef(function () { return i8.Ripple; }), selector: "[pRipple]" }, { kind: "directive", type: i0.forwardRef(function () { return i9$1.CdkDropList; }), selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i0.forwardRef(function () { return i9$1.CdkDrag; }), selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i0.forwardRef(function () { return i9$1.CdkDragHandle; }), selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: i0.forwardRef(function () { return RestWorldInputTemplateComponent; }), selector: "rw-input-template", inputs: ["apiName", "template"] }], viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }] });
1045
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldInputCollectionComponent, decorators: [{
1046
+ type: Component,
1047
+ args: [{ selector: 'rw-input-collection', viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }], template: "<div class=\"flex align-items-center\">\n <div class=\"brace\">\n </div>\n <div class=\"w-full\" cdkDropList (cdkDropListDropped)=\"collectionItemDropped($event)\">\n <div *ngFor=\"let template of templates\" class=\"flex align-items-center\" cdkDrag>\n <i class=\"fas fa-grip-lines\" cdkDragHandle></i>\n <div class=\"brace\">\n </div>\n <div class=\"w-full flex justify-content-end\">\n <rw-input-template [formGroup]=\"innerFormArray.controls[template.title]\" [template]=\"defaultTemplate\" [apiName]=\"apiName\" class=\"w-full\"></rw-input-template>\n <button pButton pRipple type=\"button\" icon=\"fas fa-trash\" class=\"p-button-outlined p-button-danger ml-2 mb-3\" (click)=\"deleteItemFromCollection(template)\"></button>\n </div>\n </div>\n <div class=\"flex justify-content-end w-full\">\n <button pButton pRipple type=\"button\" icon=\"fas fa-plus\" class=\"p-button-outlined p-button-info\" (click)=\"addNewItemToCollection()\"></button>\n </div>\n </div>\n</div>", styles: [".cdk-drag-handle{cursor:move}.cdk-drag-preview{background-color:#ffffffd0;border:2px dashed rgb(206,212,218);cursor:move}.cdk-drag-placeholder{border:2px dashed rgb(206,212,218);margin:-2px}.brace{align-self:stretch;margin:.2rem .5rem;border-left:1px solid rgb(206,212,218);border-top:1px solid rgb(206,212,218);border-bottom:1px solid rgb(206,212,218);width:1rem}\n"] }]
1048
+ }], ctorParameters: function () { return [{ type: i5.ControlContainer }, { type: FormService }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { property: [{
1049
+ type: Input
1050
+ }], apiName: [{
1051
+ type: Input
1052
+ }], inputCollectionRef: [{
1053
+ type: ContentChild,
1054
+ args: ['inputCollection', { static: false }]
1055
+ }] } });
1056
+ /**
1057
+ * A dropdown that is automatically created from the given property.
1058
+ * The dropdown supports searching through a RESTWorld list endpoint on the backend.
1059
+ * It is advised to use RestWorldInputComponent <rw-input> and control the rendered inputs with the passed in property
1060
+ * instead of using this component directly.
1061
+ */
1062
+ class RestWorldInputDropdownComponent {
1063
+ constructor(_messageService, _clients) {
1064
+ this._messageService = _messageService;
1065
+ this._clients = _clients;
1066
+ }
1067
+ getDropdownElementTooltip(resource, keysToExclude) {
1068
+ const tooltip = Object.entries(resource)
1069
+ .filter(([key]) => !(key.startsWith('_') || ['createdAt', 'createdBy', 'lastChangedAt', 'lastChangedBy', 'timestamp'].includes(key) || (keysToExclude === null || keysToExclude === void 0 ? void 0 : keysToExclude.includes(key))))
1070
+ .reduce((prev, [key, value], index) => `${prev}${index === 0 ? '' : '\n'}${key}: ${RestWorldInputDropdownComponent.jsonStringifyWithElipsis(value)}`, '');
1071
+ return tooltip;
1144
1072
  }
1145
1073
  onOptionsFiltered(property, event) {
1146
1074
  var _a, _b;
@@ -1155,7 +1083,7 @@ class RestworldEditFormComponent {
1155
1083
  const response = yield this.getClient().getListByUri(templatedUri, { $filter: filter, $top: 10 });
1156
1084
  if (!response.ok || ProblemDetails.isProblemDetails(response.body) || !response.body) {
1157
1085
  const message = `An error occurred while getting the filtered items.`;
1158
- this._messageService.add({ severity: 'error', summary: 'Error', detail: message, data: response });
1086
+ this._messageService.add({ severity: 'error', summary: 'Error', detail: message, data: response, sticky: true });
1159
1087
  return;
1160
1088
  }
1161
1089
  const items = response.body._embedded.items;
@@ -1167,15 +1095,21 @@ class RestworldEditFormComponent {
1167
1095
  throw new Error('Cannot get a client, because the apiName is not set.');
1168
1096
  return this._clients.getClient(this.apiName);
1169
1097
  }
1098
+ static jsonStringifyWithElipsis(value) {
1099
+ const maxLength = 200;
1100
+ const end = 10;
1101
+ const start = maxLength - end - 2;
1102
+ const json = JSON.stringify(value);
1103
+ const shortened = json.length > maxLength ? json.substring(0, start) + '…' + json.substring(json.length - end) : json;
1104
+ return shortened;
1105
+ }
1170
1106
  }
1171
- RestworldEditFormComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestworldEditFormComponent, deps: [{ token: FormService }, { token: i0.ChangeDetectorRef }, { token: i2$1.MessageService }, { token: RESTworldClientCollection }], target: i0.ɵɵFactoryTarget.Component });
1172
- RestworldEditFormComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.3", type: RestworldEditFormComponent, selector: "rw-form", inputs: { formGroup: "formGroup", template: "template", apiName: "apiName" }, queries: [{ propertyName: "inputOptionsSingleRef", first: true, predicate: ["inputOptionsSingle"], descendants: true }, { propertyName: "inputOptionsMultipleRef", first: true, predicate: ["inputOptionsMultiple"], descendants: true }, { propertyName: "inputOptionsRef", first: true, predicate: ["inputOptions"], descendants: true }, { propertyName: "inputHiddenRef", first: true, predicate: ["inputHidden"], descendants: true }, { propertyName: "inputTextRef", first: true, predicate: ["inputText"], descendants: true }, { propertyName: "inputTextareaRef", first: true, predicate: ["inputTextarea"], descendants: true }, { propertyName: "inputSearchRef", first: true, predicate: ["inputSearch"], descendants: true }, { propertyName: "inputTelRef", first: true, predicate: ["inputTel"], descendants: true }, { propertyName: "inputUrlRef", first: true, predicate: ["inputUrl"], descendants: true }, { propertyName: "inputEmailRef", first: true, predicate: ["inputEmail"], descendants: true }, { propertyName: "inputPasswordRef", first: true, predicate: ["inputPassword"], descendants: true }, { propertyName: "inputDateRef", first: true, predicate: ["inputDate"], descendants: true }, { propertyName: "inputMonthRef", first: true, predicate: ["inputMonth"], descendants: true }, { propertyName: "inputWeekRef", first: true, predicate: ["inputWeek"], descendants: true }, { propertyName: "inputTimeRef", first: true, predicate: ["inputTime"], descendants: true }, { propertyName: "inputDatetimeLocalRef", first: true, predicate: ["inputDatetimeLocal"], descendants: true }, { propertyName: "inputNumberRef", first: true, predicate: ["inputNumber"], descendants: true }, { propertyName: "inputRangeRef", first: true, predicate: ["inputRange"], descendants: true }, { propertyName: "inputColorRef", first: true, predicate: ["inputColor"], descendants: true }, { propertyName: "inputBoolRef", first: true, predicate: ["inputBool"], descendants: true }, { propertyName: "inputDatetimeOffsetRef", first: true, predicate: ["inputDatetimeOffset"], descendants: true }, { propertyName: "inputDurationRef", first: true, predicate: ["inputDuration"], descendants: true }, { propertyName: "inputImageRef", first: true, predicate: ["inputImage"], descendants: true }, { propertyName: "inputFileRef", first: true, predicate: ["inputFile"], descendants: true }, { propertyName: "inputObjectRef", first: true, predicate: ["inputObject"], descendants: true }, { propertyName: "inputCollectionRef", first: true, predicate: ["inputCollection"], descendants: true }, { propertyName: "inputDefaultRef", first: true, predicate: ["inputDefault"], descendants: true }], ngImport: i0, template: "\r\n<div class=\"grid field\">\r\n <div class=\"col-12 md:col-10 md:col-offset-2\">\r\n <val-errors [control]=\"formGroup\">\r\n <ng-template valError=\"remote\" let-error=\"error\">{{ error }}</ng-template>\r\n </val-errors>\r\n </div>\r\n</div>\r\n<div *ngFor=\"let property of template.properties\" class=\"grid field\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"property.type !== PropertyType.Hidden\" [attr.for]=\"property.name\" class=\"col-12 mb-2 md:col-2 md:mb-0\" [class.p-disabled]=\"property.readOnly\" [class.hasChildren]=\"property._templates\" [class.label-hidden]=\"property.promptDisplay === PropertyPromptDisplayType.Hidden\" [class.label-collapsed]=\"property.promptDisplay === PropertyPromptDisplayType.Collapsed\">{{property.prompt || property.name}}</label>\r\n <div class=\"col-12 md:col-10\">\r\n\r\n <ng-template #defaultInputOptions let-property=\"property\" let-template=\"template\">\r\n\r\n <ng-template #defaultInputOptionsSingle let-property=\"property\" let-template=\"template\">\r\n <p-dropdown [formControlName]=\"property.name\" [id]=\"property.name\" [options]=\"property.options.inline\" [filterBy]=\"(property.options.promptField || 'prompt') + ',' + (property.options.valueField || 'value')\" [optionValue]=\"property.options.valueField || 'value'\" [readonly]=\"property.readOnly\" [required]=\"property.required || property.options.minItems > 0\" [filter]=\"true\" [autoDisplayFirst]=\"false\" [showClear]=\"!property.required || property.options.minItems <= 0\" (onFilter)=\"onOptionsFiltered(property, $event)\" styleClass=\"w-full\" [filterPlaceholder]=\"property?.options?.link?.href ? 'search for more results' : ''\">\r\n <ng-template let-item pTemplate=\"selectedItem\">\r\n <span [pTooltip]=\"getTooltip(item, [property.options.promptField || 'prompt', property.options.valueField || 'value'])\">{{item[property.options.promptField || 'prompt']}} ({{item[property.options.valueField || 'value']}})</span>\r\n </ng-template>\r\n <ng-template let-item pTemplate=\"item\">\r\n <span [pTooltip]=\"getTooltip(item, [property.options.promptField || 'prompt', property.options.valueField || 'value'])\">{{item[property.options.promptField || 'prompt']}} ({{item[property.options.valueField || 'value']}})</span>\r\n </ng-template>\r\n </p-dropdown>\r\n </ng-template>\r\n <ng-container *ngIf=\"!property.options.maxItems || property.options.maxItems == 1\">\r\n <ng-container *ngTemplateOutlet=\"inputOptionsSingleRef || defaultInputOptionsSingle; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n <ng-template #defaultInputOptionsMultiple let-property=\"property\" let-template=\"template\">\r\n <p-multiSelect [formControlName]=\"property.name\" [id]=\"property.name\" [options]=\"property.options.inline\" [optionLabel]=\"property.options.promptField || 'prompt'\" [optionValue]=\"property.options.valueField || 'value'\" [readonly]=\"property.readOnly\" [selectionLimit]=\"property.options.maxItems\" [required]=\"property.required || property.options.minItems > 0\"></p-multiSelect>\r\n </ng-template>\r\n <ng-container *ngIf=\"property.options.maxItems > 1\">\r\n <ng-container *ngTemplateOutlet=\"inputOptionsMultipleRef || defaultInputOptionsMultiple; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n </ng-template>\r\n <ng-container *ngIf=\"property.options\">\r\n <ng-container *ngTemplateOutlet=\"inputOptionsRef || defaultInputOptions; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n <div *ngIf=\"!property.options\">\r\n <div [ngSwitch]=\"property.type\">\r\n\r\n <ng-template #defaultInputHidden let-property=\"property\" let-template=\"template\">\r\n <input [formControlName]=\"property.name\" [id]=\"property.name\" type=\"hidden\" [value]=\"property.value\" />\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Hidden\">\r\n <ng-container *ngTemplateOutlet=\"inputHiddenRef || defaultInputHidden; context:{ property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n <ng-template #defaultInputText let-property=\"property\" let-template=\"template\">\r\n <input [formControlName]=\"property.name\" [id]=\"property.name\" type=\"text\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Text\">\r\n <ng-container *ngTemplateOutlet=\"inputTextRef || defaultInputText; context:{ property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputTextarea let-property=\"property\" let-template=\"template\">\r\n <textarea [formControlName]=\"property.name\" [id]=\"property.name\" pInputTextarea class=\"w-full p-inputtextarea p-inputtext p-component p-element\" [class.p-disabled]=\"property.readOnly\" [cols]=\"property.cols\" [rows]=\"property.rows\"></textarea>\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Textarea\">\r\n <ng-container *ngTemplateOutlet=\"inputTextareaRef || defaultInputTextarea; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputSearch let-property=\"property\" let-template=\"template\">\r\n <input [formControlName]=\"property.name\" [id]=\"property.name\" type=\"search\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Search\">\r\n <ng-container *ngTemplateOutlet=\"inputSearchRef || defaultInputSearch; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputTel let-property=\"property\" let-template=\"template\">\r\n <input [formControlName]=\"property.name\" [id]=\"property.name\" type=\"tel\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Tel\">\r\n <ng-container *ngTemplateOutlet=\"inputTelRef || defaultInputTel; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputUrl let-property=\"property\" let-template=\"template\">\r\n <input [formControlName]=\"property.name\" [id]=\"property.name\" type=\"url\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Url\">\r\n <ng-container *ngTemplateOutlet=\"inputUrlRef || defaultInputUrl; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputEmail let-property=\"property\" let-template=\"template\">\r\n <input [formControlName]=\"property.name\" [id]=\"property.name\" type=\"email\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Email\">\r\n <ng-container *ngTemplateOutlet=\"inputEmailRef || defaultInputEmail; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputPassword let-property=\"property\" let-template=\"template\">\r\n <input [formControlName]=\"property.name\" [id]=\"property.name\" type=\"password\" pPassword class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Password\">\r\n <ng-container *ngTemplateOutlet=\"inputPasswordRef || defaultInputPassword; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputDate let-property=\"property\" let-template=\"template\">\r\n <p-calendar [formControlName]=\"property.name\" [id]=\"property.name\" [dateFormat]=\"dateFormat\" [showWeek]=\"true\" [showIcon]=\"true\" styleClass=\"w-full\" [class.p-disabled]=\"property.readOnly\"></p-calendar>\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Date\">\r\n <ng-container *ngTemplateOutlet=\"inputDateRef || defaultInputDate; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputMonth let-property=\"property\" let-template=\"template\">\r\n <p-calendar [formControlName]=\"property.name\" [id]=\"property.name\" [dateFormat]=\"dateFormat\" [showWeek]=\"false\" view=\"month\" [showIcon]=\"true\" styleClass=\"w-full\" [class.p-disabled]=\"property.readOnly\"></p-calendar>\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Month\">\r\n <ng-container *ngTemplateOutlet=\"inputMonthRef || defaultInputMonth; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputWeek let-property=\"property\" let-template=\"template\">\r\n <input [formControlName]=\"property.name\" [id]=\"property.name\" type=\"week\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Week\">\r\n <ng-container *ngTemplateOutlet=\"inputWeekRef || defaultInputWeek; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputTime let-property=\"property\" let-template=\"template\">\r\n <p-calendar [formControlName]=\"property.name\" [id]=\"property.name\" [dateFormat]=\"dateFormat\" [showTime]=\"true\" [timeOnly]=\"true\" [showWeek]=\"false\" [showIcon]=\"true\" styleClass=\"w-full\" [class.p-disabled]=\"property.readOnly\"></p-calendar>\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Time\">\r\n <ng-container *ngTemplateOutlet=\"inputTimeRef || defaultInputTime; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputDatetimeLocal let-property=\"property\" let-template=\"template\">\r\n <p-calendar [formControlName]=\"property.name\" [id]=\"property.name\" [dateFormat]=\"dateFormat\" [showTime]=\"true\" [showWeek]=\"false\" [showIcon]=\"true\" styleClass=\"w-full\" [class.p-disabled]=\"property.readOnly\"></p-calendar>\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.DatetimeLocal\">\r\n <ng-container *ngTemplateOutlet=\"inputDatetimeLocalRef || defaultInputDatetimeLocal; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputNumber let-property=\"property\" let-template=\"template\">\r\n <p-inputNumber [formControlName]=\"property.name\" [id]=\"property.name\" mode=\"decimal\" [showButtons]=\"!property.readOnly\" class=\"w-full\" styleClass=\"w-full\" [class.p-disabled]=\"property.readOnly\"></p-inputNumber>\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Number\">\r\n <ng-container *ngTemplateOutlet=\"inputNumberRef || defaultInputNumber; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputRange let-property=\"property\" let-template=\"template\">\r\n <input [formControlName]=\"property.name\" [id]=\"property.name\" type=\"range\" [min]=\"property.min\" [max]=\"property.max\" [step]=\"property.step\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Range\">\r\n <ng-container *ngTemplateOutlet=\"inputRangeRef || defaultInputRange; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputColor let-property=\"property\" let-template=\"template\">\r\n <input [formControlName]=\"property.name\" [id]=\"property.name\" type=\"color\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Color\">\r\n <ng-container *ngTemplateOutlet=\"inputColorRef || defaultInputColor; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputBool let-property=\"property\" let-template=\"template\" let-formGroup=\"formGroup\">\r\n <p-checkbox *ngIf=\"property.required\" [binary]=\"true\" [formControl]=\"formGroup.controls[property.name]\" [id]=\"property.name\" [readonly]=\"property.readOnly\"></p-checkbox>\r\n <p-triStateCheckbox *ngIf=\"!property.required\" [formControl]=\"formGroup.controls[property.name]\" [id]=\"property.name\" [readonly]=\"property.readOnly\"></p-triStateCheckbox>\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Bool\">\r\n <ng-container *ngTemplateOutlet=\"inputBoolRef || defaultInputBool; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputDatetimeOffset let-property=\"property\" let-template=\"template\">\r\n <p-calendar [formControlName]=\"property.name\" [id]=\"property.name\" [dateFormat]=\"dateFormat\" [showTime]=\"true\" [showWeek]=\"false\" [showIcon]=\"true\" styleClass=\"w-full\" [class.p-disabled]=\"property.readOnly\"></p-calendar>\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.DatetimeOffset\">\r\n <ng-container *ngTemplateOutlet=\"inputDatetimeOffsetRef || defaultInputDatetimeOffset; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputDuration let-property=\"property\" let-template=\"template\">\r\n <p-calendar *ngSwitchCase=\"PropertyType.Duration\" [formControlName]=\"property.name\" [id]=\"property.name\" [dateFormat]=\"dateFormat\" [showTime]=\"true\" [timeOnly]=\"true\" [showWeek]=\"false\" [showIcon]=\"true\" styleClass=\"w-full\" [class.p-disabled]=\"property.readOnly\"></p-calendar>\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Duration\">\r\n <ng-container *ngTemplateOutlet=\"inputDurationRef || defaultInputDuration; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputImage let-property=\"property\" let-template=\"template\">\r\n <rw-image [formControlName]=\"property.name\"\r\n [accept]=\"property.restWorldImage?.accept ?? property.placeholder ?? 'image/*'\"\r\n [alignImage]=\"property.restWorldImage?.alignImage\"\r\n [alt]=\"property.prompt ?? property.name\"\r\n [aspectRatio]=\"property.restWorldImage?.aspectRatio\"\r\n [backgroundColor]=\"property.restWorldImage?.backgroundColor\"\r\n [canvasRotation]=\"property.restWorldImage?.canvasRotation\"\r\n [containWithinAspectRatio]=\"property.restWorldImage?.containWithinAspectRatio\"\r\n [cropper]=\"property.restWorldImage?.cropper\"\r\n [cropperMaxHeight]=\"property.restWorldImage?.cropperMaxHeight\"\r\n [cropperMaxWidth]=\"property.restWorldImage?.cropperMaxWidth\"\r\n [cropperMinHeight]=\"property.restWorldImage?.cropperMinHeight\"\r\n [cropperMinWidth]=\"property.restWorldImage?.cropperMinWidth\"\r\n [cropperStaticHeight]=\"property.restWorldImage?.cropperStaticHeight\"\r\n [cropperStaticWidth]=\"property.restWorldImage?.cropperStaticWidth\"\r\n [fileName]=\"property.name + '.' + (property.restWorldImage?.format ?? 'png')\"\r\n [format]=\"property.restWorldImage?.format\"\r\n [imageQuality]=\"property.restWorldImage?.imageQuality\"\r\n [initialStepSize]=\"property.restWorldImage?.initialStepSize\"\r\n [maintainAspectRatio]=\"property.restWorldImage?.maintainAspectRatio\"\r\n [onlyScaleDown]=\"property.restWorldImage?.onlyScaleDown\"\r\n [resizeToWidth]=\"property.restWorldImage?.resizeToWidth\"\r\n [resizeToHeight]=\"property.restWorldImage?.resizeToHeight\"\r\n [roundCropper]=\"property.restWorldImage?.roundCropper\"></rw-image>\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Image\">\r\n <ng-container *ngTemplateOutlet=\"inputImageRef || defaultInputImage; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputFile let-property=\"property\" let-template=\"template\">\r\n <rw-file [formControlName]=\"property.name\" [fileName]=\"property.name\" [accept]=\"property.placeholder\"></rw-file>\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.File\">\r\n <ng-container *ngTemplateOutlet=\"inputFileRef || defaultInputFile; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputObject let-property=\"property\" let-template=\"template\">\r\n <div class=\"flex align-items-center\">\r\n <div class=\"brace\">\r\n </div>\r\n <div class=\"w-full\">\r\n <rw-form [formGroup]=\"(formGroup.controls[property.name] | as : UntypedFormGroup)\" [template]=\"property._templates.default\" [apiName]=\"apiName\"></rw-form>\r\n </div>\r\n </div>\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Object\">\r\n <ng-container *ngTemplateOutlet=\"inputObjectRef || defaultInputObject; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputCollection let-property=\"property\" let-template=\"template\">\r\n <div class=\"flex align-items-center\">\r\n <div class=\"brace\">\r\n </div>\r\n <div class=\"w-full\" cdkDropList [cdkDropListData]=\"{ property: property, formArray: (formGroup.controls[property.name] | as : UntypedFormArray)}\" (cdkDropListDropped)=\"collectionItemDropped($event)\">\r\n <div *ngFor=\"let template of getCollectionEntryTemplates(property)\" class=\"flex align-items-center\" cdkDrag>\r\n <i class=\"fas fa-grip-lines\" cdkDragHandle></i>\r\n <div class=\"brace\">\r\n </div>\r\n <div class=\"w-full flex justify-content-end\">\r\n <rw-form [formGroup]=\"((formGroup.controls[property.name] | as : UntypedFormArray).controls[Number.parseInt(template.title!)] | as : UntypedFormGroup)\" [template]=\"template\" [apiName]=\"apiName\" class=\"w-full\"></rw-form>\r\n <button pButton pRipple type=\"button\" icon=\"fas fa-trash\" class=\"p-button-outlined p-button-danger ml-2 mb-3\" (click)=\"deleteItemFromCollection(property, formGroup.controls[property.name], template)\"></button>\r\n </div>\r\n </div>\r\n <div class=\"flex justify-content-end w-full\">\r\n <button pButton pRipple type=\"button\" icon=\"fas fa-plus\" class=\"p-button-outlined p-button-info\" (click)=\"addNewItemToCollection(property, formGroup.controls[property.name])\"></button>\r\n </div>\r\n </div>\r\n </div>\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Collection\">\r\n <ng-container *ngTemplateOutlet=\"inputCollectionRef || defaultInputCollection; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputDefault let-property=\"property\" let-template=\"template\">\r\n <input [formControlName]=\"property.name\" [id]=\"property.name\" type=\"text\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\r\n </ng-template>\r\n <ng-container *ngSwitchDefault>\r\n <ng-container *ngTemplateOutlet=\"inputDefaultRef || defaultInputDefault; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n </div>\r\n </div>\r\n <val-errors [controlName]=\"property.name || null\">\r\n <ng-template valError=\"required\">The field '{{property.prompt || property.name}}' is required.</ng-template>\r\n <ng-template valError=\"email\">The email must be a valid email address.</ng-template>\r\n <ng-template valError=\"min\" let-error=\"error\">'{{property.prompt || property.name}}' must be equal or greater than or equal to {{ error.min }}.</ng-template>\r\n <ng-template valError=\"max\" let-error=\"error\">'{{property.prompt || property.name}}' must be smaller than or equal to {{ error.max }}.</ng-template>\r\n <ng-template valError=\"minlength\" let-error=\"error\">The length of '{{property.prompt || property.name}}' must be equal or greater than or equal to {{ error.requiredLength }}.</ng-template>\r\n <ng-template valError=\"maxlength\" let-error=\"error\">The length of '{{property.prompt || property.name}}' must be shorter than or equal to {{ error.requiredLength }}.</ng-template>\r\n <ng-template valError=\"pattern\" let-error=\"error\">The value for '{{property.prompt || property.name}}' does not match the pattern {{ error }}.</ng-template>\r\n <ng-template valError=\"remote\" let-error=\"error\">{{ error }}</ng-template>\r\n </val-errors>\r\n </div>\r\n</div>\r\n", styles: [".brace{align-self:stretch;margin:.2rem .5rem;border-left:1px solid rgb(206,212,218);border-top:1px solid rgb(206,212,218);border-bottom:1px solid rgb(206,212,218);width:1rem}.cdk-drag-handle{cursor:move}.cdk-drag-preview{background-color:#ffffffd0;border:2px dashed rgb(206,212,218);cursor:move}.cdk-drag-placeholder{border:2px dashed rgb(206,212,218);margin:-2px}.label-hidden{visibility:hidden}.label-collapsed{display:none}\n"], dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i4.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i4.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i4.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.RangeValueAccessor, selector: "input[type=range][formControlName],input[type=range][formControl],input[type=range][ngModel]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i5.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i5.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i5.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i2$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i2.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "fitContent", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]" }, { kind: "component", type: i8$1.InputNumber, selector: "p-inputNumber", inputs: ["showButtons", "format", "buttonLayout", "inputId", "styleClass", "style", "placeholder", "size", "maxlength", "tabindex", "title", "ariaLabel", "ariaRequired", "name", "required", "autocomplete", "min", "max", "incrementButtonClass", "decrementButtonClass", "incrementButtonIcon", "decrementButtonIcon", "readonly", "step", "allowEmpty", "locale", "localeMatcher", "mode", "currency", "currencyDisplay", "useGrouping", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "inputStyle", "inputStyleClass", "showClear", "disabled"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown", "onClear"] }, { kind: "component", type: i9$1.Calendar, selector: "p-calendar", inputs: ["style", "styleClass", "inputStyle", "inputId", "name", "inputStyleClass", "placeholder", "ariaLabelledBy", "iconAriaLabel", "disabled", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "icon", "appendTo", "readonlyInput", "shortYearCutoff", "monthNavigator", "yearNavigator", "hourFormat", "timeOnly", "stepHour", "stepMinute", "stepSecond", "showSeconds", "required", "showOnFocus", "showWeek", "showClear", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "touchUI", "timeSeparator", "focusTrap", "showTransitionOptions", "hideTransitionOptions", "tabindex", "view", "defaultDate", "minDate", "maxDate", "disabledDates", "disabledDays", "yearRange", "showTime", "responsiveOptions", "numberOfMonths", "firstDayOfWeek", "locale"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onClear", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }, { kind: "directive", type: i5$1.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading"] }, { kind: "component", type: i11.Checkbox, selector: "p-checkbox", inputs: ["value", "name", "disabled", "binary", "label", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "style", "styleClass", "labelStyleClass", "formControl", "checkboxIcon", "readonly", "required", "trueValue", "falseValue"], outputs: ["onChange"] }, { kind: "directive", type: i6.Ripple, selector: "[pRipple]" }, { kind: "component", type: i13.TriStateCheckbox, selector: "p-triStateCheckbox", inputs: ["disabled", "name", "ariaLabelledBy", "tabindex", "inputId", "style", "styleClass", "label", "readonly", "checkboxTrueIcon", "checkboxFalseIcon"], outputs: ["onChange"] }, { kind: "component", type: i14.Dropdown, selector: "p-dropdown", inputs: ["scrollHeight", "filter", "name", "style", "panelStyle", "styleClass", "panelStyleClass", "readonly", "required", "editable", "appendTo", "tabindex", "placeholder", "filterPlaceholder", "filterLocale", "inputId", "selectId", "dataKey", "filterBy", "autofocus", "resetFilterOnHide", "dropdownIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "autoDisplayFirst", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "maxlength", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "overlayDirection", "disabled", "itemSize", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "options", "filterValue"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: i15.MultiSelect, selector: "p-multiSelect", inputs: ["style", "styleClass", "panelStyle", "panelStyleClass", "inputId", "disabled", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "appendTo", "dataKey", "name", "label", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "defaultLabel", "placeholder", "options", "filterValue", "itemSize"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad"] }, { kind: "component", type: i16.ValidationErrorsComponent, selector: "val-errors", inputs: ["control", "controlName", "label"] }, { kind: "directive", type: i16.ValidationErrorDirective, selector: "ng-template[valError]", inputs: ["valError"] }, { kind: "directive", type: i17.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i17.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i17.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: RESTWorldImageViewComponent, selector: "rw-image", inputs: ["alt", "accept", "fileName", "alignImage", "aspectRatio", "backgroundColor", "canvasRotation", "containWithinAspectRatio", "cropper", "cropperMaxHeight", "cropperMaxWidth", "cropperMinHeight", "cropperMinWidth", "cropperStaticHeight", "cropperStaticWidth", "format", "imageQuality", "initialStepSize", "maintainAspectRatio", "onlyScaleDown", "resizeToWidth", "resizeToHeight", "roundCropper"] }, { kind: "component", type: RESTWorldFileViewComponent, selector: "rw-file", inputs: ["accept", "fileName"] }, { kind: "component", type: RestworldEditFormComponent, selector: "rw-form", inputs: ["formGroup", "template", "apiName"] }, { kind: "pipe", type: AsPipe, name: "as" }] });
1173
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestworldEditFormComponent, decorators: [{
1107
+ RestWorldInputDropdownComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldInputDropdownComponent, deps: [{ token: i2$3.MessageService }, { token: RestWorldClientCollection }], target: i0.ɵɵFactoryTarget.Component });
1108
+ RestWorldInputDropdownComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.3", type: RestWorldInputDropdownComponent, selector: "rw-input-dropdown", inputs: { property: "property", apiName: "apiName" }, queries: [{ propertyName: "inputOptionsSingleRef", first: true, predicate: ["inputOptionsSingle"], descendants: true }, { propertyName: "inputOptionsMultipleRef", first: true, predicate: ["inputOptionsMultiple"], descendants: true }], ngImport: i0, template: "<ng-template #defaultInputOptionsSingle let-property=\"property\" let-template=\"template\">\n <p-dropdown \n [formControlName]=\"property.name\" \n [id]=\"property.name\" \n [options]=\"property.options.inline\" \n [filterBy]=\"(property.options.promptField ?? 'prompt') + ',' + (property.options.valueField ?? 'value')\" \n [optionValue]=\"property.options.valueField ?? 'value'\" \n [readonly]=\"property.readOnly\" \n [required]=\"property.required || property.options.minItems > 0\" \n [filter]=\"true\" \n [autoDisplayFirst]=\"false\" \n [showClear]=\"!property.required || property.options.minItems <= 0\" \n (onFilter)=\"onOptionsFiltered(property, $event)\" \n styleClass=\"w-full\" \n [filterPlaceholder]=\"property?.options?.link?.href ? 'search for more results' : ''\">\n <ng-template let-item pTemplate=\"selectedItem\">\n <span [pTooltip]=\"getDropdownElementTooltip(item, [property.options.promptField ?? 'prompt', property.options.valueField ?? 'value'])\">{{item[property.options.promptField ?? 'prompt']}} ({{item[property.options.valueField ?? 'value']}})</span>\n </ng-template>\n <ng-template let-item pTemplate=\"item\">\n <span [pTooltip]=\"getDropdownElementTooltip(item, [property.options.promptField ?? 'prompt', property.options.valueField ?? 'value'])\">{{item[property.options.promptField ?? 'prompt']}} ({{item[property.options.valueField ?? 'value']}})</span>\n </ng-template>\n </p-dropdown>\n</ng-template>\n<ng-container *ngIf=\"!property.options.maxItems || property.options.maxItems == 1\">\n <ng-container *ngTemplateOutlet=\"inputOptionsSingleRef ?? defaultInputOptionsSingle; context: { property: property, apiName: apiName }\"></ng-container>\n</ng-container>\n\n<ng-template #defaultInputOptionsMultiple let-property=\"property\" let-template=\"template\">\n <p-multiSelect \n [formControlName]=\"property.name\" \n [id]=\"property.name\" \n [options]=\"property.options.inline\" \n [optionLabel]=\"property.options.promptField ?? 'prompt'\" \n [optionValue]=\"property.options.valueField ?? 'value'\" \n [readonly]=\"property.readOnly\" \n [selectionLimit]=\"property.options.maxItems\" \n [required]=\"property.required || property.options.minItems > 0\"></p-multiSelect>\n</ng-template>\n<ng-container *ngIf=\"(property.options.maxItems ?? 0) > 1\">\n <ng-container *ngTemplateOutlet=\"inputOptionsMultipleRef ?? defaultInputOptionsMultiple; context: { property: property, apiName: apiName }\"></ng-container>\n</ng-container>", styles: [""], dependencies: [{ kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i5.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i2$3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i2.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "fitContent", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "component", type: i13.Dropdown, selector: "p-dropdown", inputs: ["scrollHeight", "filter", "name", "style", "panelStyle", "styleClass", "panelStyleClass", "readonly", "required", "editable", "appendTo", "tabindex", "placeholder", "filterPlaceholder", "filterLocale", "inputId", "selectId", "dataKey", "filterBy", "autofocus", "resetFilterOnHide", "dropdownIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "autoDisplayFirst", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "maxlength", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "overlayDirection", "disabled", "itemSize", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "options", "filterValue"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: i14.MultiSelect, selector: "p-multiSelect", inputs: ["style", "styleClass", "panelStyle", "panelStyleClass", "inputId", "disabled", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "appendTo", "dataKey", "name", "label", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "defaultLabel", "placeholder", "options", "filterValue", "itemSize"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad"] }], viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }] });
1109
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldInputDropdownComponent, decorators: [{
1174
1110
  type: Component,
1175
- args: [{ selector: 'rw-form', template: "\r\n<div class=\"grid field\">\r\n <div class=\"col-12 md:col-10 md:col-offset-2\">\r\n <val-errors [control]=\"formGroup\">\r\n <ng-template valError=\"remote\" let-error=\"error\">{{ error }}</ng-template>\r\n </val-errors>\r\n </div>\r\n</div>\r\n<div *ngFor=\"let property of template.properties\" class=\"grid field\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"property.type !== PropertyType.Hidden\" [attr.for]=\"property.name\" class=\"col-12 mb-2 md:col-2 md:mb-0\" [class.p-disabled]=\"property.readOnly\" [class.hasChildren]=\"property._templates\" [class.label-hidden]=\"property.promptDisplay === PropertyPromptDisplayType.Hidden\" [class.label-collapsed]=\"property.promptDisplay === PropertyPromptDisplayType.Collapsed\">{{property.prompt || property.name}}</label>\r\n <div class=\"col-12 md:col-10\">\r\n\r\n <ng-template #defaultInputOptions let-property=\"property\" let-template=\"template\">\r\n\r\n <ng-template #defaultInputOptionsSingle let-property=\"property\" let-template=\"template\">\r\n <p-dropdown [formControlName]=\"property.name\" [id]=\"property.name\" [options]=\"property.options.inline\" [filterBy]=\"(property.options.promptField || 'prompt') + ',' + (property.options.valueField || 'value')\" [optionValue]=\"property.options.valueField || 'value'\" [readonly]=\"property.readOnly\" [required]=\"property.required || property.options.minItems > 0\" [filter]=\"true\" [autoDisplayFirst]=\"false\" [showClear]=\"!property.required || property.options.minItems <= 0\" (onFilter)=\"onOptionsFiltered(property, $event)\" styleClass=\"w-full\" [filterPlaceholder]=\"property?.options?.link?.href ? 'search for more results' : ''\">\r\n <ng-template let-item pTemplate=\"selectedItem\">\r\n <span [pTooltip]=\"getTooltip(item, [property.options.promptField || 'prompt', property.options.valueField || 'value'])\">{{item[property.options.promptField || 'prompt']}} ({{item[property.options.valueField || 'value']}})</span>\r\n </ng-template>\r\n <ng-template let-item pTemplate=\"item\">\r\n <span [pTooltip]=\"getTooltip(item, [property.options.promptField || 'prompt', property.options.valueField || 'value'])\">{{item[property.options.promptField || 'prompt']}} ({{item[property.options.valueField || 'value']}})</span>\r\n </ng-template>\r\n </p-dropdown>\r\n </ng-template>\r\n <ng-container *ngIf=\"!property.options.maxItems || property.options.maxItems == 1\">\r\n <ng-container *ngTemplateOutlet=\"inputOptionsSingleRef || defaultInputOptionsSingle; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n <ng-template #defaultInputOptionsMultiple let-property=\"property\" let-template=\"template\">\r\n <p-multiSelect [formControlName]=\"property.name\" [id]=\"property.name\" [options]=\"property.options.inline\" [optionLabel]=\"property.options.promptField || 'prompt'\" [optionValue]=\"property.options.valueField || 'value'\" [readonly]=\"property.readOnly\" [selectionLimit]=\"property.options.maxItems\" [required]=\"property.required || property.options.minItems > 0\"></p-multiSelect>\r\n </ng-template>\r\n <ng-container *ngIf=\"property.options.maxItems > 1\">\r\n <ng-container *ngTemplateOutlet=\"inputOptionsMultipleRef || defaultInputOptionsMultiple; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n </ng-template>\r\n <ng-container *ngIf=\"property.options\">\r\n <ng-container *ngTemplateOutlet=\"inputOptionsRef || defaultInputOptions; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n <div *ngIf=\"!property.options\">\r\n <div [ngSwitch]=\"property.type\">\r\n\r\n <ng-template #defaultInputHidden let-property=\"property\" let-template=\"template\">\r\n <input [formControlName]=\"property.name\" [id]=\"property.name\" type=\"hidden\" [value]=\"property.value\" />\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Hidden\">\r\n <ng-container *ngTemplateOutlet=\"inputHiddenRef || defaultInputHidden; context:{ property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n <ng-template #defaultInputText let-property=\"property\" let-template=\"template\">\r\n <input [formControlName]=\"property.name\" [id]=\"property.name\" type=\"text\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Text\">\r\n <ng-container *ngTemplateOutlet=\"inputTextRef || defaultInputText; context:{ property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputTextarea let-property=\"property\" let-template=\"template\">\r\n <textarea [formControlName]=\"property.name\" [id]=\"property.name\" pInputTextarea class=\"w-full p-inputtextarea p-inputtext p-component p-element\" [class.p-disabled]=\"property.readOnly\" [cols]=\"property.cols\" [rows]=\"property.rows\"></textarea>\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Textarea\">\r\n <ng-container *ngTemplateOutlet=\"inputTextareaRef || defaultInputTextarea; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputSearch let-property=\"property\" let-template=\"template\">\r\n <input [formControlName]=\"property.name\" [id]=\"property.name\" type=\"search\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Search\">\r\n <ng-container *ngTemplateOutlet=\"inputSearchRef || defaultInputSearch; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputTel let-property=\"property\" let-template=\"template\">\r\n <input [formControlName]=\"property.name\" [id]=\"property.name\" type=\"tel\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Tel\">\r\n <ng-container *ngTemplateOutlet=\"inputTelRef || defaultInputTel; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputUrl let-property=\"property\" let-template=\"template\">\r\n <input [formControlName]=\"property.name\" [id]=\"property.name\" type=\"url\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Url\">\r\n <ng-container *ngTemplateOutlet=\"inputUrlRef || defaultInputUrl; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputEmail let-property=\"property\" let-template=\"template\">\r\n <input [formControlName]=\"property.name\" [id]=\"property.name\" type=\"email\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Email\">\r\n <ng-container *ngTemplateOutlet=\"inputEmailRef || defaultInputEmail; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputPassword let-property=\"property\" let-template=\"template\">\r\n <input [formControlName]=\"property.name\" [id]=\"property.name\" type=\"password\" pPassword class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Password\">\r\n <ng-container *ngTemplateOutlet=\"inputPasswordRef || defaultInputPassword; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputDate let-property=\"property\" let-template=\"template\">\r\n <p-calendar [formControlName]=\"property.name\" [id]=\"property.name\" [dateFormat]=\"dateFormat\" [showWeek]=\"true\" [showIcon]=\"true\" styleClass=\"w-full\" [class.p-disabled]=\"property.readOnly\"></p-calendar>\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Date\">\r\n <ng-container *ngTemplateOutlet=\"inputDateRef || defaultInputDate; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputMonth let-property=\"property\" let-template=\"template\">\r\n <p-calendar [formControlName]=\"property.name\" [id]=\"property.name\" [dateFormat]=\"dateFormat\" [showWeek]=\"false\" view=\"month\" [showIcon]=\"true\" styleClass=\"w-full\" [class.p-disabled]=\"property.readOnly\"></p-calendar>\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Month\">\r\n <ng-container *ngTemplateOutlet=\"inputMonthRef || defaultInputMonth; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputWeek let-property=\"property\" let-template=\"template\">\r\n <input [formControlName]=\"property.name\" [id]=\"property.name\" type=\"week\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Week\">\r\n <ng-container *ngTemplateOutlet=\"inputWeekRef || defaultInputWeek; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputTime let-property=\"property\" let-template=\"template\">\r\n <p-calendar [formControlName]=\"property.name\" [id]=\"property.name\" [dateFormat]=\"dateFormat\" [showTime]=\"true\" [timeOnly]=\"true\" [showWeek]=\"false\" [showIcon]=\"true\" styleClass=\"w-full\" [class.p-disabled]=\"property.readOnly\"></p-calendar>\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Time\">\r\n <ng-container *ngTemplateOutlet=\"inputTimeRef || defaultInputTime; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputDatetimeLocal let-property=\"property\" let-template=\"template\">\r\n <p-calendar [formControlName]=\"property.name\" [id]=\"property.name\" [dateFormat]=\"dateFormat\" [showTime]=\"true\" [showWeek]=\"false\" [showIcon]=\"true\" styleClass=\"w-full\" [class.p-disabled]=\"property.readOnly\"></p-calendar>\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.DatetimeLocal\">\r\n <ng-container *ngTemplateOutlet=\"inputDatetimeLocalRef || defaultInputDatetimeLocal; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputNumber let-property=\"property\" let-template=\"template\">\r\n <p-inputNumber [formControlName]=\"property.name\" [id]=\"property.name\" mode=\"decimal\" [showButtons]=\"!property.readOnly\" class=\"w-full\" styleClass=\"w-full\" [class.p-disabled]=\"property.readOnly\"></p-inputNumber>\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Number\">\r\n <ng-container *ngTemplateOutlet=\"inputNumberRef || defaultInputNumber; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputRange let-property=\"property\" let-template=\"template\">\r\n <input [formControlName]=\"property.name\" [id]=\"property.name\" type=\"range\" [min]=\"property.min\" [max]=\"property.max\" [step]=\"property.step\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Range\">\r\n <ng-container *ngTemplateOutlet=\"inputRangeRef || defaultInputRange; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputColor let-property=\"property\" let-template=\"template\">\r\n <input [formControlName]=\"property.name\" [id]=\"property.name\" type=\"color\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Color\">\r\n <ng-container *ngTemplateOutlet=\"inputColorRef || defaultInputColor; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputBool let-property=\"property\" let-template=\"template\" let-formGroup=\"formGroup\">\r\n <p-checkbox *ngIf=\"property.required\" [binary]=\"true\" [formControl]=\"formGroup.controls[property.name]\" [id]=\"property.name\" [readonly]=\"property.readOnly\"></p-checkbox>\r\n <p-triStateCheckbox *ngIf=\"!property.required\" [formControl]=\"formGroup.controls[property.name]\" [id]=\"property.name\" [readonly]=\"property.readOnly\"></p-triStateCheckbox>\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Bool\">\r\n <ng-container *ngTemplateOutlet=\"inputBoolRef || defaultInputBool; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputDatetimeOffset let-property=\"property\" let-template=\"template\">\r\n <p-calendar [formControlName]=\"property.name\" [id]=\"property.name\" [dateFormat]=\"dateFormat\" [showTime]=\"true\" [showWeek]=\"false\" [showIcon]=\"true\" styleClass=\"w-full\" [class.p-disabled]=\"property.readOnly\"></p-calendar>\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.DatetimeOffset\">\r\n <ng-container *ngTemplateOutlet=\"inputDatetimeOffsetRef || defaultInputDatetimeOffset; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputDuration let-property=\"property\" let-template=\"template\">\r\n <p-calendar *ngSwitchCase=\"PropertyType.Duration\" [formControlName]=\"property.name\" [id]=\"property.name\" [dateFormat]=\"dateFormat\" [showTime]=\"true\" [timeOnly]=\"true\" [showWeek]=\"false\" [showIcon]=\"true\" styleClass=\"w-full\" [class.p-disabled]=\"property.readOnly\"></p-calendar>\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Duration\">\r\n <ng-container *ngTemplateOutlet=\"inputDurationRef || defaultInputDuration; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputImage let-property=\"property\" let-template=\"template\">\r\n <rw-image [formControlName]=\"property.name\"\r\n [accept]=\"property.restWorldImage?.accept ?? property.placeholder ?? 'image/*'\"\r\n [alignImage]=\"property.restWorldImage?.alignImage\"\r\n [alt]=\"property.prompt ?? property.name\"\r\n [aspectRatio]=\"property.restWorldImage?.aspectRatio\"\r\n [backgroundColor]=\"property.restWorldImage?.backgroundColor\"\r\n [canvasRotation]=\"property.restWorldImage?.canvasRotation\"\r\n [containWithinAspectRatio]=\"property.restWorldImage?.containWithinAspectRatio\"\r\n [cropper]=\"property.restWorldImage?.cropper\"\r\n [cropperMaxHeight]=\"property.restWorldImage?.cropperMaxHeight\"\r\n [cropperMaxWidth]=\"property.restWorldImage?.cropperMaxWidth\"\r\n [cropperMinHeight]=\"property.restWorldImage?.cropperMinHeight\"\r\n [cropperMinWidth]=\"property.restWorldImage?.cropperMinWidth\"\r\n [cropperStaticHeight]=\"property.restWorldImage?.cropperStaticHeight\"\r\n [cropperStaticWidth]=\"property.restWorldImage?.cropperStaticWidth\"\r\n [fileName]=\"property.name + '.' + (property.restWorldImage?.format ?? 'png')\"\r\n [format]=\"property.restWorldImage?.format\"\r\n [imageQuality]=\"property.restWorldImage?.imageQuality\"\r\n [initialStepSize]=\"property.restWorldImage?.initialStepSize\"\r\n [maintainAspectRatio]=\"property.restWorldImage?.maintainAspectRatio\"\r\n [onlyScaleDown]=\"property.restWorldImage?.onlyScaleDown\"\r\n [resizeToWidth]=\"property.restWorldImage?.resizeToWidth\"\r\n [resizeToHeight]=\"property.restWorldImage?.resizeToHeight\"\r\n [roundCropper]=\"property.restWorldImage?.roundCropper\"></rw-image>\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Image\">\r\n <ng-container *ngTemplateOutlet=\"inputImageRef || defaultInputImage; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputFile let-property=\"property\" let-template=\"template\">\r\n <rw-file [formControlName]=\"property.name\" [fileName]=\"property.name\" [accept]=\"property.placeholder\"></rw-file>\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.File\">\r\n <ng-container *ngTemplateOutlet=\"inputFileRef || defaultInputFile; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputObject let-property=\"property\" let-template=\"template\">\r\n <div class=\"flex align-items-center\">\r\n <div class=\"brace\">\r\n </div>\r\n <div class=\"w-full\">\r\n <rw-form [formGroup]=\"(formGroup.controls[property.name] | as : UntypedFormGroup)\" [template]=\"property._templates.default\" [apiName]=\"apiName\"></rw-form>\r\n </div>\r\n </div>\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Object\">\r\n <ng-container *ngTemplateOutlet=\"inputObjectRef || defaultInputObject; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputCollection let-property=\"property\" let-template=\"template\">\r\n <div class=\"flex align-items-center\">\r\n <div class=\"brace\">\r\n </div>\r\n <div class=\"w-full\" cdkDropList [cdkDropListData]=\"{ property: property, formArray: (formGroup.controls[property.name] | as : UntypedFormArray)}\" (cdkDropListDropped)=\"collectionItemDropped($event)\">\r\n <div *ngFor=\"let template of getCollectionEntryTemplates(property)\" class=\"flex align-items-center\" cdkDrag>\r\n <i class=\"fas fa-grip-lines\" cdkDragHandle></i>\r\n <div class=\"brace\">\r\n </div>\r\n <div class=\"w-full flex justify-content-end\">\r\n <rw-form [formGroup]=\"((formGroup.controls[property.name] | as : UntypedFormArray).controls[Number.parseInt(template.title!)] | as : UntypedFormGroup)\" [template]=\"template\" [apiName]=\"apiName\" class=\"w-full\"></rw-form>\r\n <button pButton pRipple type=\"button\" icon=\"fas fa-trash\" class=\"p-button-outlined p-button-danger ml-2 mb-3\" (click)=\"deleteItemFromCollection(property, formGroup.controls[property.name], template)\"></button>\r\n </div>\r\n </div>\r\n <div class=\"flex justify-content-end w-full\">\r\n <button pButton pRipple type=\"button\" icon=\"fas fa-plus\" class=\"p-button-outlined p-button-info\" (click)=\"addNewItemToCollection(property, formGroup.controls[property.name])\"></button>\r\n </div>\r\n </div>\r\n </div>\r\n </ng-template>\r\n <ng-container *ngSwitchCase=\"PropertyType.Collection\">\r\n <ng-container *ngTemplateOutlet=\"inputCollectionRef || defaultInputCollection; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n\r\n <ng-template #defaultInputDefault let-property=\"property\" let-template=\"template\">\r\n <input [formControlName]=\"property.name\" [id]=\"property.name\" type=\"text\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\r\n </ng-template>\r\n <ng-container *ngSwitchDefault>\r\n <ng-container *ngTemplateOutlet=\"inputDefaultRef || defaultInputDefault; context: { property: property, template: template, formGroup: formGroup, apiName: apiName }\"></ng-container>\r\n </ng-container>\r\n\r\n </div>\r\n </div>\r\n <val-errors [controlName]=\"property.name || null\">\r\n <ng-template valError=\"required\">The field '{{property.prompt || property.name}}' is required.</ng-template>\r\n <ng-template valError=\"email\">The email must be a valid email address.</ng-template>\r\n <ng-template valError=\"min\" let-error=\"error\">'{{property.prompt || property.name}}' must be equal or greater than or equal to {{ error.min }}.</ng-template>\r\n <ng-template valError=\"max\" let-error=\"error\">'{{property.prompt || property.name}}' must be smaller than or equal to {{ error.max }}.</ng-template>\r\n <ng-template valError=\"minlength\" let-error=\"error\">The length of '{{property.prompt || property.name}}' must be equal or greater than or equal to {{ error.requiredLength }}.</ng-template>\r\n <ng-template valError=\"maxlength\" let-error=\"error\">The length of '{{property.prompt || property.name}}' must be shorter than or equal to {{ error.requiredLength }}.</ng-template>\r\n <ng-template valError=\"pattern\" let-error=\"error\">The value for '{{property.prompt || property.name}}' does not match the pattern {{ error }}.</ng-template>\r\n <ng-template valError=\"remote\" let-error=\"error\">{{ error }}</ng-template>\r\n </val-errors>\r\n </div>\r\n</div>\r\n", styles: [".brace{align-self:stretch;margin:.2rem .5rem;border-left:1px solid rgb(206,212,218);border-top:1px solid rgb(206,212,218);border-bottom:1px solid rgb(206,212,218);width:1rem}.cdk-drag-handle{cursor:move}.cdk-drag-preview{background-color:#ffffffd0;border:2px dashed rgb(206,212,218);cursor:move}.cdk-drag-placeholder{border:2px dashed rgb(206,212,218);margin:-2px}.label-hidden{visibility:hidden}.label-collapsed{display:none}\n"] }]
1176
- }], ctorParameters: function () { return [{ type: FormService }, { type: i0.ChangeDetectorRef }, { type: i2$1.MessageService }, { type: RESTworldClientCollection }]; }, propDecorators: { formGroup: [{
1177
- type: Input
1178
- }], template: [{
1111
+ args: [{ selector: 'rw-input-dropdown', viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }], template: "<ng-template #defaultInputOptionsSingle let-property=\"property\" let-template=\"template\">\n <p-dropdown \n [formControlName]=\"property.name\" \n [id]=\"property.name\" \n [options]=\"property.options.inline\" \n [filterBy]=\"(property.options.promptField ?? 'prompt') + ',' + (property.options.valueField ?? 'value')\" \n [optionValue]=\"property.options.valueField ?? 'value'\" \n [readonly]=\"property.readOnly\" \n [required]=\"property.required || property.options.minItems > 0\" \n [filter]=\"true\" \n [autoDisplayFirst]=\"false\" \n [showClear]=\"!property.required || property.options.minItems <= 0\" \n (onFilter)=\"onOptionsFiltered(property, $event)\" \n styleClass=\"w-full\" \n [filterPlaceholder]=\"property?.options?.link?.href ? 'search for more results' : ''\">\n <ng-template let-item pTemplate=\"selectedItem\">\n <span [pTooltip]=\"getDropdownElementTooltip(item, [property.options.promptField ?? 'prompt', property.options.valueField ?? 'value'])\">{{item[property.options.promptField ?? 'prompt']}} ({{item[property.options.valueField ?? 'value']}})</span>\n </ng-template>\n <ng-template let-item pTemplate=\"item\">\n <span [pTooltip]=\"getDropdownElementTooltip(item, [property.options.promptField ?? 'prompt', property.options.valueField ?? 'value'])\">{{item[property.options.promptField ?? 'prompt']}} ({{item[property.options.valueField ?? 'value']}})</span>\n </ng-template>\n </p-dropdown>\n</ng-template>\n<ng-container *ngIf=\"!property.options.maxItems || property.options.maxItems == 1\">\n <ng-container *ngTemplateOutlet=\"inputOptionsSingleRef ?? defaultInputOptionsSingle; context: { property: property, apiName: apiName }\"></ng-container>\n</ng-container>\n\n<ng-template #defaultInputOptionsMultiple let-property=\"property\" let-template=\"template\">\n <p-multiSelect \n [formControlName]=\"property.name\" \n [id]=\"property.name\" \n [options]=\"property.options.inline\" \n [optionLabel]=\"property.options.promptField ?? 'prompt'\" \n [optionValue]=\"property.options.valueField ?? 'value'\" \n [readonly]=\"property.readOnly\" \n [selectionLimit]=\"property.options.maxItems\" \n [required]=\"property.required || property.options.minItems > 0\"></p-multiSelect>\n</ng-template>\n<ng-container *ngIf=\"(property.options.maxItems ?? 0) > 1\">\n <ng-container *ngTemplateOutlet=\"inputOptionsMultipleRef ?? defaultInputOptionsMultiple; context: { property: property, apiName: apiName }\"></ng-container>\n</ng-container>" }]
1112
+ }], ctorParameters: function () { return [{ type: i2$3.MessageService }, { type: RestWorldClientCollection }]; }, propDecorators: { property: [{
1179
1113
  type: Input
1180
1114
  }], apiName: [{
1181
1115
  type: Input
@@ -1185,99 +1119,742 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImpor
1185
1119
  }], inputOptionsMultipleRef: [{
1186
1120
  type: ContentChild,
1187
1121
  args: ['inputOptionsMultiple', { static: false }]
1188
- }], inputOptionsRef: [{
1189
- type: ContentChild,
1190
- args: ['inputOptions', { static: false }]
1191
- }], inputHiddenRef: [{
1192
- type: ContentChild,
1193
- args: ['inputHidden', { static: false }]
1194
- }], inputTextRef: [{
1195
- type: ContentChild,
1196
- args: ['inputText', { static: false }]
1197
- }], inputTextareaRef: [{
1198
- type: ContentChild,
1199
- args: ['inputTextarea', { static: false }]
1200
- }], inputSearchRef: [{
1201
- type: ContentChild,
1202
- args: ['inputSearch', { static: false }]
1203
- }], inputTelRef: [{
1204
- type: ContentChild,
1205
- args: ['inputTel', { static: false }]
1206
- }], inputUrlRef: [{
1207
- type: ContentChild,
1208
- args: ['inputUrl', { static: false }]
1209
- }], inputEmailRef: [{
1210
- type: ContentChild,
1211
- args: ['inputEmail', { static: false }]
1212
- }], inputPasswordRef: [{
1213
- type: ContentChild,
1214
- args: ['inputPassword', { static: false }]
1215
- }], inputDateRef: [{
1216
- type: ContentChild,
1217
- args: ['inputDate', { static: false }]
1218
- }], inputMonthRef: [{
1219
- type: ContentChild,
1220
- args: ['inputMonth', { static: false }]
1221
- }], inputWeekRef: [{
1222
- type: ContentChild,
1223
- args: ['inputWeek', { static: false }]
1224
- }], inputTimeRef: [{
1225
- type: ContentChild,
1226
- args: ['inputTime', { static: false }]
1227
- }], inputDatetimeLocalRef: [{
1228
- type: ContentChild,
1229
- args: ['inputDatetimeLocal', { static: false }]
1230
- }], inputNumberRef: [{
1231
- type: ContentChild,
1232
- args: ['inputNumber', { static: false }]
1233
- }], inputRangeRef: [{
1234
- type: ContentChild,
1235
- args: ['inputRange', { static: false }]
1236
- }], inputColorRef: [{
1237
- type: ContentChild,
1238
- args: ['inputColor', { static: false }]
1239
- }], inputBoolRef: [{
1240
- type: ContentChild,
1241
- args: ['inputBool', { static: false }]
1242
- }], inputDatetimeOffsetRef: [{
1243
- type: ContentChild,
1244
- args: ['inputDatetimeOffset', { static: false }]
1245
- }], inputDurationRef: [{
1246
- type: ContentChild,
1247
- args: ['inputDuration', { static: false }]
1248
- }], inputImageRef: [{
1249
- type: ContentChild,
1250
- args: ['inputImage', { static: false }]
1251
- }], inputFileRef: [{
1252
- type: ContentChild,
1253
- args: ['inputFile', { static: false }]
1122
+ }] } });
1123
+ /**
1124
+ * A complex object with multiple properties that is automatically created from the given property.
1125
+ * The object can also be nested.
1126
+ * It is advised to use RestWorldInputComponent <rw-input> and control the rendered inputs with the passed in property
1127
+ * instead of using this component directly.
1128
+ */
1129
+ class RestWorldInputObjectComponent {
1130
+ constructor(_controlContainer) {
1131
+ this._controlContainer = _controlContainer;
1132
+ }
1133
+ get innerFormGroup() {
1134
+ if (this._innerFormGroup === undefined)
1135
+ throw new Error("formGroup is not set.");
1136
+ return this._innerFormGroup;
1137
+ }
1138
+ ngOnInit() {
1139
+ const formGroup = this._controlContainer.control;
1140
+ this._innerFormGroup = formGroup.controls[this.property.name];
1141
+ }
1142
+ }
1143
+ RestWorldInputObjectComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldInputObjectComponent, deps: [{ token: i5.ControlContainer }], target: i0.ɵɵFactoryTarget.Component });
1144
+ RestWorldInputObjectComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.3", type: RestWorldInputObjectComponent, selector: "rw-input-object", inputs: { property: "property", apiName: "apiName" }, queries: [{ propertyName: "inputObjectRef", first: true, predicate: ["inputObject"], descendants: true }], ngImport: i0, template: "<ng-template #defaultInputObject let-property=\"property\" let-template=\"template\">\n <div class=\"flex align-items-center\">\n <div class=\"brace\">\n </div>\n <div class=\"w-full\">\n <rw-input-template [formGroup]=\"innerFormGroup\" [template]=\"property._templates.default\" [apiName]=\"apiName\"></rw-input-template>\n </div>\n </div>\n</ng-template>\n<ng-container>\n <ng-container *ngTemplateOutlet=\"inputObjectRef || defaultInputObject; context: { property: property, innerFormGroup: innerFormGroup, apiName: apiName }\"></ng-container>\n</ng-container>", styles: [".brace{align-self:stretch;margin:.2rem .5rem;border-left:1px solid rgb(206,212,218);border-top:1px solid rgb(206,212,218);border-bottom:1px solid rgb(206,212,218);width:1rem}\n"], dependencies: [{ kind: "directive", type: i0.forwardRef(function () { return i2$1.NgTemplateOutlet; }), selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i0.forwardRef(function () { return i5.NgControlStatusGroup; }), selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i0.forwardRef(function () { return i5.FormGroupDirective; }), selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i0.forwardRef(function () { return RestWorldInputTemplateComponent; }), selector: "rw-input-template", inputs: ["apiName", "template"] }], viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }] });
1145
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldInputObjectComponent, decorators: [{
1146
+ type: Component,
1147
+ args: [{ selector: 'rw-input-object', viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }], template: "<ng-template #defaultInputObject let-property=\"property\" let-template=\"template\">\n <div class=\"flex align-items-center\">\n <div class=\"brace\">\n </div>\n <div class=\"w-full\">\n <rw-input-template [formGroup]=\"innerFormGroup\" [template]=\"property._templates.default\" [apiName]=\"apiName\"></rw-input-template>\n </div>\n </div>\n</ng-template>\n<ng-container>\n <ng-container *ngTemplateOutlet=\"inputObjectRef || defaultInputObject; context: { property: property, innerFormGroup: innerFormGroup, apiName: apiName }\"></ng-container>\n</ng-container>", styles: [".brace{align-self:stretch;margin:.2rem .5rem;border-left:1px solid rgb(206,212,218);border-top:1px solid rgb(206,212,218);border-bottom:1px solid rgb(206,212,218);width:1rem}\n"] }]
1148
+ }], ctorParameters: function () { return [{ type: i5.ControlContainer }]; }, propDecorators: { property: [{
1149
+ type: Input
1150
+ }], apiName: [{
1151
+ type: Input
1254
1152
  }], inputObjectRef: [{
1255
1153
  type: ContentChild,
1256
1154
  args: ['inputObject', { static: false }]
1257
- }], inputCollectionRef: [{
1258
- type: ContentChild,
1259
- args: ['inputCollection', { static: false }]
1260
- }], inputDefaultRef: [{
1261
- type: ContentChild,
1262
- args: ['inputDefault', { static: false }]
1263
- }] } });
1155
+ }] } });
1156
+ /**
1157
+ * A simple input element, like a text, or a number that is automatically created from the given property.
1158
+ * It is advised to use RestWorldInputComponent <rw-input> and control the rendered inputs with the passed in property
1159
+ * instead of using this component directly.
1160
+ */
1161
+ class RestWorldInputSimpleComponent {
1162
+ constructor(_controlContainer) {
1163
+ this._controlContainer = _controlContainer;
1164
+ }
1165
+ get PropertyType() {
1166
+ return PropertyType;
1167
+ }
1168
+ get dateFormat() {
1169
+ return new Date(3333, 11, 22)
1170
+ .toLocaleDateString()
1171
+ .replace("22", "dd")
1172
+ .replace("11", "mm")
1173
+ .replace("3333", "yy")
1174
+ .replace("33", "y");
1175
+ }
1176
+ get formControl() {
1177
+ if (this._formControl === undefined)
1178
+ throw new Error("formGroup is not set.");
1179
+ return this._formControl;
1180
+ }
1181
+ get PropertyWithImage() {
1182
+ return PropertyWithImage;
1183
+ }
1184
+ ngOnInit() {
1185
+ const formGroup = this._controlContainer.control;
1186
+ this._formControl = formGroup.controls[this.property.name];
1187
+ }
1188
+ }
1189
+ RestWorldInputSimpleComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldInputSimpleComponent, deps: [{ token: i5.ControlContainer }], target: i0.ɵɵFactoryTarget.Component });
1190
+ RestWorldInputSimpleComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.3", type: RestWorldInputSimpleComponent, selector: "rw-input-simple", inputs: { property: "property" }, ngImport: i0, template: "<div [ngSwitch]=\"property.type\">\n\n <input *ngSwitchCase=\"PropertyType.Hidden\" [formControlName]=\"property.name\" [id]=\"property.name\" type=\"hidden\" [value]=\"property.value\" />\n \n <input *ngSwitchCase=\"PropertyType.Text\" [formControlName]=\"property.name\" [id]=\"property.name\" type=\"text\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\n \n <textarea *ngSwitchCase=\"PropertyType.Textarea\" [formControlName]=\"property.name\" [id]=\"property.name\" pInputTextarea class=\"w-full p-inputtextarea p-inputtext p-component p-element\" [class.p-disabled]=\"property.readOnly\" [cols]=\"property.cols\" [rows]=\"property.rows\"></textarea>\n \n <input *ngSwitchCase=\"PropertyType.Search\" [formControlName]=\"property.name\" [id]=\"property.name\" type=\"search\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\n \n <input *ngSwitchCase=\"PropertyType.Tel\" [formControlName]=\"property.name\" [id]=\"property.name\" type=\"tel\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\n \n <input *ngSwitchCase=\"PropertyType.Url\" [formControlName]=\"property.name\" [id]=\"property.name\" type=\"url\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\n \n <input *ngSwitchCase=\"PropertyType.Email\" [formControlName]=\"property.name\" [id]=\"property.name\" type=\"email\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\n \n <input *ngSwitchCase=\"PropertyType.Password\" [formControlName]=\"property.name\" [id]=\"property.name\" type=\"password\" pPassword class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\n \n <p-calendar *ngSwitchCase=\"PropertyType.Date\" [formControlName]=\"property.name\" [id]=\"property.name\" [dateFormat]=\"dateFormat\" [showWeek]=\"true\" [showIcon]=\"true\" styleClass=\"w-full\" [class.p-disabled]=\"property.readOnly\"></p-calendar>\n \n <p-calendar *ngSwitchCase=\"PropertyType.Month\" [formControlName]=\"property.name\" [id]=\"property.name\" [dateFormat]=\"dateFormat\" [showWeek]=\"false\" view=\"month\" [showIcon]=\"true\" styleClass=\"w-full\" [class.p-disabled]=\"property.readOnly\"></p-calendar>\n \n <input *ngSwitchCase=\"PropertyType.Week\" [formControlName]=\"property.name\" [id]=\"property.name\" type=\"week\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\n \n <p-calendar *ngSwitchCase=\"PropertyType.Time\" [formControlName]=\"property.name\" [id]=\"property.name\" [dateFormat]=\"dateFormat\" [showTime]=\"true\" [timeOnly]=\"true\" [showWeek]=\"false\" [showIcon]=\"true\" styleClass=\"w-full\" [class.p-disabled]=\"property.readOnly\"></p-calendar>\n \n <p-calendar *ngSwitchCase=\"PropertyType.DatetimeLocal\" [formControlName]=\"property.name\" [id]=\"property.name\" [dateFormat]=\"dateFormat\" [showTime]=\"true\" [showWeek]=\"false\" [showIcon]=\"true\" styleClass=\"w-full\" [class.p-disabled]=\"property.readOnly\"></p-calendar>\n \n <p-inputNumber *ngSwitchCase=\"PropertyType.Number\" [formControlName]=\"property.name\" [id]=\"property.name\" mode=\"decimal\" [showButtons]=\"!property.readOnly\" class=\"w-full\" styleClass=\"w-full\" [class.p-disabled]=\"property.readOnly\"></p-inputNumber>\n \n <input *ngSwitchCase=\"PropertyType.Range\" [formControlName]=\"property.name\" [id]=\"property.name\" type=\"range\" [min]=\"property.min\" [max]=\"property.max\" [step]=\"property.step\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\n \n <input *ngSwitchCase=\"PropertyType.Color\" [formControlName]=\"property.name\" [id]=\"property.name\" type=\"color\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\n \n <ng-container *ngSwitchCase=\"PropertyType.Bool\">\n <p-checkbox *ngIf=\"property.required\" [binary]=\"true\" [formControl]=\"formControl\" [id]=\"property.name\" [readonly]=\"property.readOnly!\"></p-checkbox>\n <p-triStateCheckbox *ngIf=\"!property.required\" [formControl]=\"formControl\" [id]=\"property.name\" [readonly]=\"property.readOnly!\"></p-triStateCheckbox>\n </ng-container>\n \n <p-calendar *ngSwitchCase=\"PropertyType.DatetimeOffset\" [formControlName]=\"property.name\" [id]=\"property.name\" [dateFormat]=\"dateFormat\" [showTime]=\"true\" [showWeek]=\"false\" [showIcon]=\"true\" styleClass=\"w-full\" [class.p-disabled]=\"property.readOnly\"></p-calendar>\n \n <p-calendar *ngSwitchCase=\"PropertyType.Duration\" [formControlName]=\"property.name\" [id]=\"property.name\" [dateFormat]=\"dateFormat\" [showTime]=\"true\" [timeOnly]=\"true\" [showWeek]=\"false\" [showIcon]=\"true\" styleClass=\"w-full\" [class.p-disabled]=\"property.readOnly\"></p-calendar>\n\n <rw-image *ngSwitchCase=\"PropertyType.Image\" [formControlName]=\"property.name\" [property]=\"property | as:PropertyWithImage\"></rw-image>\n\n <rw-file *ngSwitchCase=\"PropertyType.File\" [formControlName]=\"property.name\" [fileName]=\"property.name\" [accept]=\"property.placeholder\"></rw-file>\n\n <input *ngSwitchDefault [formControlName]=\"property.name\" [id]=\"property.name\" type=\"text\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\n</div>", styles: [""], dependencies: [{ kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i2$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i2$1.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.RangeValueAccessor, selector: "input[type=range][formControlName],input[type=range][formControl],input[type=range][ngModel]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i5.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]" }, { kind: "component", type: i16.InputNumber, selector: "p-inputNumber", inputs: ["showButtons", "format", "buttonLayout", "inputId", "styleClass", "style", "placeholder", "size", "maxlength", "tabindex", "title", "ariaLabel", "ariaRequired", "name", "required", "autocomplete", "min", "max", "incrementButtonClass", "decrementButtonClass", "incrementButtonIcon", "decrementButtonIcon", "readonly", "step", "allowEmpty", "locale", "localeMatcher", "mode", "currency", "currencyDisplay", "useGrouping", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "inputStyle", "inputStyleClass", "showClear", "disabled"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown", "onClear"] }, { kind: "component", type: i17.Calendar, selector: "p-calendar", inputs: ["style", "styleClass", "inputStyle", "inputId", "name", "inputStyleClass", "placeholder", "ariaLabelledBy", "iconAriaLabel", "disabled", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "icon", "appendTo", "readonlyInput", "shortYearCutoff", "monthNavigator", "yearNavigator", "hourFormat", "timeOnly", "stepHour", "stepMinute", "stepSecond", "showSeconds", "required", "showOnFocus", "showWeek", "showClear", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "touchUI", "timeSeparator", "focusTrap", "showTransitionOptions", "hideTransitionOptions", "tabindex", "view", "defaultDate", "minDate", "maxDate", "disabledDates", "disabledDays", "yearRange", "showTime", "responsiveOptions", "numberOfMonths", "firstDayOfWeek", "locale"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onClear", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }, { kind: "component", type: i18.Checkbox, selector: "p-checkbox", inputs: ["value", "name", "disabled", "binary", "label", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "style", "styleClass", "labelStyleClass", "formControl", "checkboxIcon", "readonly", "required", "trueValue", "falseValue"], outputs: ["onChange"] }, { kind: "component", type: i19.TriStateCheckbox, selector: "p-triStateCheckbox", inputs: ["disabled", "name", "ariaLabelledBy", "tabindex", "inputId", "style", "styleClass", "label", "readonly", "checkboxTrueIcon", "checkboxFalseIcon"], outputs: ["onChange"] }, { kind: "component", type: RestWorldImageComponent, selector: "rw-image", inputs: ["property"] }, { kind: "component", type: RestWorldFileComponent, selector: "rw-file", inputs: ["accept", "fileName"] }, { kind: "pipe", type: AsPipe, name: "as" }], viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }] });
1191
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldInputSimpleComponent, decorators: [{
1192
+ type: Component,
1193
+ args: [{ selector: 'rw-input-simple', viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }], template: "<div [ngSwitch]=\"property.type\">\n\n <input *ngSwitchCase=\"PropertyType.Hidden\" [formControlName]=\"property.name\" [id]=\"property.name\" type=\"hidden\" [value]=\"property.value\" />\n \n <input *ngSwitchCase=\"PropertyType.Text\" [formControlName]=\"property.name\" [id]=\"property.name\" type=\"text\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\n \n <textarea *ngSwitchCase=\"PropertyType.Textarea\" [formControlName]=\"property.name\" [id]=\"property.name\" pInputTextarea class=\"w-full p-inputtextarea p-inputtext p-component p-element\" [class.p-disabled]=\"property.readOnly\" [cols]=\"property.cols\" [rows]=\"property.rows\"></textarea>\n \n <input *ngSwitchCase=\"PropertyType.Search\" [formControlName]=\"property.name\" [id]=\"property.name\" type=\"search\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\n \n <input *ngSwitchCase=\"PropertyType.Tel\" [formControlName]=\"property.name\" [id]=\"property.name\" type=\"tel\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\n \n <input *ngSwitchCase=\"PropertyType.Url\" [formControlName]=\"property.name\" [id]=\"property.name\" type=\"url\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\n \n <input *ngSwitchCase=\"PropertyType.Email\" [formControlName]=\"property.name\" [id]=\"property.name\" type=\"email\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\n \n <input *ngSwitchCase=\"PropertyType.Password\" [formControlName]=\"property.name\" [id]=\"property.name\" type=\"password\" pPassword class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\n \n <p-calendar *ngSwitchCase=\"PropertyType.Date\" [formControlName]=\"property.name\" [id]=\"property.name\" [dateFormat]=\"dateFormat\" [showWeek]=\"true\" [showIcon]=\"true\" styleClass=\"w-full\" [class.p-disabled]=\"property.readOnly\"></p-calendar>\n \n <p-calendar *ngSwitchCase=\"PropertyType.Month\" [formControlName]=\"property.name\" [id]=\"property.name\" [dateFormat]=\"dateFormat\" [showWeek]=\"false\" view=\"month\" [showIcon]=\"true\" styleClass=\"w-full\" [class.p-disabled]=\"property.readOnly\"></p-calendar>\n \n <input *ngSwitchCase=\"PropertyType.Week\" [formControlName]=\"property.name\" [id]=\"property.name\" type=\"week\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\n \n <p-calendar *ngSwitchCase=\"PropertyType.Time\" [formControlName]=\"property.name\" [id]=\"property.name\" [dateFormat]=\"dateFormat\" [showTime]=\"true\" [timeOnly]=\"true\" [showWeek]=\"false\" [showIcon]=\"true\" styleClass=\"w-full\" [class.p-disabled]=\"property.readOnly\"></p-calendar>\n \n <p-calendar *ngSwitchCase=\"PropertyType.DatetimeLocal\" [formControlName]=\"property.name\" [id]=\"property.name\" [dateFormat]=\"dateFormat\" [showTime]=\"true\" [showWeek]=\"false\" [showIcon]=\"true\" styleClass=\"w-full\" [class.p-disabled]=\"property.readOnly\"></p-calendar>\n \n <p-inputNumber *ngSwitchCase=\"PropertyType.Number\" [formControlName]=\"property.name\" [id]=\"property.name\" mode=\"decimal\" [showButtons]=\"!property.readOnly\" class=\"w-full\" styleClass=\"w-full\" [class.p-disabled]=\"property.readOnly\"></p-inputNumber>\n \n <input *ngSwitchCase=\"PropertyType.Range\" [formControlName]=\"property.name\" [id]=\"property.name\" type=\"range\" [min]=\"property.min\" [max]=\"property.max\" [step]=\"property.step\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\n \n <input *ngSwitchCase=\"PropertyType.Color\" [formControlName]=\"property.name\" [id]=\"property.name\" type=\"color\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\n \n <ng-container *ngSwitchCase=\"PropertyType.Bool\">\n <p-checkbox *ngIf=\"property.required\" [binary]=\"true\" [formControl]=\"formControl\" [id]=\"property.name\" [readonly]=\"property.readOnly!\"></p-checkbox>\n <p-triStateCheckbox *ngIf=\"!property.required\" [formControl]=\"formControl\" [id]=\"property.name\" [readonly]=\"property.readOnly!\"></p-triStateCheckbox>\n </ng-container>\n \n <p-calendar *ngSwitchCase=\"PropertyType.DatetimeOffset\" [formControlName]=\"property.name\" [id]=\"property.name\" [dateFormat]=\"dateFormat\" [showTime]=\"true\" [showWeek]=\"false\" [showIcon]=\"true\" styleClass=\"w-full\" [class.p-disabled]=\"property.readOnly\"></p-calendar>\n \n <p-calendar *ngSwitchCase=\"PropertyType.Duration\" [formControlName]=\"property.name\" [id]=\"property.name\" [dateFormat]=\"dateFormat\" [showTime]=\"true\" [timeOnly]=\"true\" [showWeek]=\"false\" [showIcon]=\"true\" styleClass=\"w-full\" [class.p-disabled]=\"property.readOnly\"></p-calendar>\n\n <rw-image *ngSwitchCase=\"PropertyType.Image\" [formControlName]=\"property.name\" [property]=\"property | as:PropertyWithImage\"></rw-image>\n\n <rw-file *ngSwitchCase=\"PropertyType.File\" [formControlName]=\"property.name\" [fileName]=\"property.name\" [accept]=\"property.placeholder\"></rw-file>\n\n <input *ngSwitchDefault [formControlName]=\"property.name\" [id]=\"property.name\" type=\"text\" pInputText class=\"w-full\" [class.p-disabled]=\"property.readOnly\" />\n</div>" }]
1194
+ }], ctorParameters: function () { return [{ type: i5.ControlContainer }]; }, propDecorators: { property: [{
1195
+ type: Input
1196
+ }] } });
1197
+ /**
1198
+ * A collection of rw-form-elemtns automatically created from a template.
1199
+ * Does not have any buttons on its own.
1200
+ * If you want buttons, use RestWorldForm <rw-form>.
1201
+ */
1202
+ class RestWorldInputTemplateComponent {
1203
+ }
1204
+ RestWorldInputTemplateComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldInputTemplateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1205
+ RestWorldInputTemplateComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.3", type: RestWorldInputTemplateComponent, selector: "rw-input-template", inputs: { apiName: "apiName", template: "template" }, ngImport: i0, template: "<rw-form-element *ngFor=\"let property of template.properties\" [property]=\"property\" [apiName]=\"apiName\"></rw-form-element>", styles: [""], dependencies: [{ kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: RestWorldFormElementComponent, selector: "rw-form-element", inputs: ["property", "apiName"] }], viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }] });
1206
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldInputTemplateComponent, decorators: [{
1207
+ type: Component,
1208
+ args: [{ selector: 'rw-input-template', viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }], template: "<rw-form-element *ngFor=\"let property of template.properties\" [property]=\"property\" [apiName]=\"apiName\"></rw-form-element>" }]
1209
+ }], propDecorators: { apiName: [{
1210
+ type: Input
1211
+ }], template: [{
1212
+ type: Input
1213
+ }] } });
1214
+
1215
+ /**
1216
+ * A form with Save, Reload and Delete buttons.
1217
+ * If you do not want buttons, use RestWorldFormTemplateComponent <rw-form-template>.
1218
+ * You can also provide your own buttons by passing in a template.
1219
+ */
1220
+ class RestWorldFormComponent {
1221
+ constructor(_clients, _confirmationService, _messageService, _formService) {
1222
+ this._clients = _clients;
1223
+ this._confirmationService = _confirmationService;
1224
+ this._messageService = _messageService;
1225
+ this._formService = _formService;
1226
+ this.allowSubmit = true;
1227
+ this.allowDelete = true;
1228
+ this.allowReload = true;
1229
+ this.showSubmit = true;
1230
+ this.showDelete = true;
1231
+ this.showReload = true;
1232
+ this.afterDelete = new EventEmitter();
1233
+ this.afterSubmit = new EventEmitter();
1234
+ this._isLoading = false;
1235
+ }
1236
+ get isLoading() {
1237
+ return this._isLoading;
1238
+ }
1239
+ get formGroup() {
1240
+ return this._formGroup;
1241
+ }
1242
+ get canSubmit() {
1243
+ return this.allowSubmit &&
1244
+ this.template.target !== undefined &&
1245
+ !this.isLoading;
1246
+ }
1247
+ get canDelete() {
1248
+ return this.allowDelete &&
1249
+ this.template.target !== undefined &&
1250
+ this.template.method == "PUT" &&
1251
+ !this.isLoading;
1252
+ }
1253
+ get canReload() {
1254
+ return this.allowReload &&
1255
+ this.template.target !== undefined &&
1256
+ this.template.title !== undefined &&
1257
+ this.template.properties.some(p => p.name === "id" && p.value !== undefined && p.value !== null && p.value !== 0) &&
1258
+ !this.isLoading;
1259
+ }
1260
+ ngOnInit() {
1261
+ this._formGroup = this._formService.createFormGroupFromTemplate(this.template);
1262
+ }
1263
+ reload() {
1264
+ return __awaiter(this, void 0, void 0, function* () {
1265
+ if (!this.canReload)
1266
+ return;
1267
+ this._isLoading = true;
1268
+ try {
1269
+ const response = yield this.getClient().getForm(this.template.target);
1270
+ if (!response.ok || ProblemDetails.isProblemDetails(response.body) || !response.body) {
1271
+ this._messageService.add({ severity: 'error', summary: 'Error', detail: 'Error while loading the resource from the API.', data: response, sticky: true });
1272
+ }
1273
+ else {
1274
+ this.template = response.body.getTemplateByTitle(this.template.title);
1275
+ this._formGroup = this._formService.createFormGroupFromTemplate(this.template);
1276
+ }
1277
+ }
1278
+ catch (e) {
1279
+ this._messageService.add({ severity: 'error', summary: 'Error', detail: `An unknown error occurred. ${JSON.stringify(e)}`, sticky: true });
1280
+ console.log(e);
1281
+ }
1282
+ this._isLoading = false;
1283
+ });
1284
+ }
1285
+ showDeleteConfirmatioModal() {
1286
+ this._confirmationService.confirm({
1287
+ message: 'Do you really want to delete this resource?',
1288
+ header: 'Confirm delete',
1289
+ icon: 'far fa-trash-alt',
1290
+ accept: () => this.delete()
1291
+ });
1292
+ }
1293
+ submit() {
1294
+ return __awaiter(this, void 0, void 0, function* () {
1295
+ if (!this.canSubmit)
1296
+ return;
1297
+ this._isLoading = true;
1298
+ try {
1299
+ const response = yield this.getClient().submit(this.template, this.formGroup.value);
1300
+ if (!response.ok) {
1301
+ let summary = 'Error';
1302
+ let detail = 'Error while saving the resource.';
1303
+ if (ProblemDetails.isProblemDetails(response.body)) {
1304
+ const problemDetails = response.body;
1305
+ summary = problemDetails.title || summary;
1306
+ detail = problemDetails.detail || detail;
1307
+ // display validation errors
1308
+ if (problemDetails['errors']) {
1309
+ for (const [key, errorsForKey] of Object.entries(problemDetails['errors'])) {
1310
+ const path = key.split(/\.|\[/).map(e => e.replace("]", ""));
1311
+ // The path might start with a $, indicating the root.
1312
+ if (path.length > 0 && path[0] === '$')
1313
+ path.shift();
1314
+ const formControl = path.reduce(RestWorldFormComponent.getSubControl, this.formGroup);
1315
+ formControl.setErrors(Object.assign(Object.assign({}, formControl.errors), { remote: errorsForKey }));
1316
+ formControl.markAsTouched();
1317
+ }
1318
+ }
1319
+ }
1320
+ this._messageService.add({ severity: 'error', summary: summary, detail: detail, data: response, sticky: true });
1321
+ }
1322
+ else {
1323
+ const templateBeforeSubmit = this.template;
1324
+ const responseResource = response.body;
1325
+ const templateAfterSubmit = responseResource.getTemplateByTitle(this.template.title);
1326
+ this._messageService.add({ severity: 'success', summary: 'Saved', detail: 'The resource has been saved.' });
1327
+ this.afterSubmit.emit({ old: templateBeforeSubmit, new: templateAfterSubmit });
1328
+ }
1329
+ }
1330
+ catch (e) {
1331
+ this._messageService.add({ severity: 'error', summary: 'Error', detail: `An unknown error occurred. ${JSON.stringify(e)}`, sticky: true });
1332
+ console.log(e);
1333
+ }
1334
+ this._isLoading = false;
1335
+ });
1336
+ }
1337
+ delete() {
1338
+ return __awaiter(this, void 0, void 0, function* () {
1339
+ if (!this.canDelete)
1340
+ return;
1341
+ if (this.formGroup === undefined)
1342
+ throw new Error("formGroup cannot be undefined.");
1343
+ yield this.getClient().deleteByTemplateAndForm(this.template, this.formGroup);
1344
+ this._messageService.add({ severity: 'success', summary: 'Deleted', detail: 'The resource has been deleted.' });
1345
+ this.afterDelete.emit();
1346
+ });
1347
+ }
1348
+ static getSubControl(control, pathElement) {
1349
+ if (pathElement === "")
1350
+ return control;
1351
+ if (control instanceof UntypedFormGroup)
1352
+ return control.controls[pathElement];
1353
+ if (control instanceof UntypedFormArray) {
1354
+ const index = Number.parseInt(pathElement);
1355
+ if (Number.isInteger(index))
1356
+ return control.controls[index];
1357
+ }
1358
+ return control;
1359
+ }
1360
+ getClient() {
1361
+ return this._clients.getClient(this.apiName);
1362
+ }
1363
+ }
1364
+ RestWorldFormComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldFormComponent, deps: [{ token: RestWorldClientCollection }, { token: i2$3.ConfirmationService }, { token: i2$3.MessageService }, { token: FormService }], target: i0.ɵɵFactoryTarget.Component });
1365
+ RestWorldFormComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.3", type: RestWorldFormComponent, selector: "rw-form", inputs: { template: "template", apiName: "apiName", rel: "rel", allowSubmit: "allowSubmit", allowDelete: "allowDelete", allowReload: "allowReload", showSubmit: "showSubmit", showDelete: "showDelete", showReload: "showReload" }, outputs: { afterDelete: "afterDelete", afterSubmit: "afterSubmit" }, queries: [{ propertyName: "buttonsRef", first: true, predicate: ["buttons"], descendants: true }], ngImport: i0, template: "<form *ngIf=\"formGroup !== undefined && template !== undefined\" [formGroup]=\"formGroup\" (ngSubmit)=\"submit()\">\n <div class=\"blockable-container\">\n <div class=\"blockable-element\">\n <rw-input-template [template]=\"template\" [apiName]=\"apiName\"></rw-input-template>\n </div>\n <div class=\"blockable-overlay\" *ngIf=\"isLoading\">\n <p-progressSpinner></p-progressSpinner>\n </div>\n </div>\n\n <div class=\"grid\">\n <div class=\"col\">\n <div class=\"flex justify-content-end w-full\">\n <ng-template #defaultButtons>\n <button pButton pRipple type=\"submit\" label=\"Save\" icon=\"far fa-save\" class=\"mx-2 p-button-success\"\n [disabled]=\"!canSubmit\"></button>\n <button pButton pRipple type=\"button\" label=\"Reload\" icon=\"fas fa-redo\" class=\"mx-2 p-button-info\"\n (click)=\"reload()\" [disabled]=\"!canReload\"></button>\n <button pButton pRipple type=\"button\" label=\"Delete\" icon=\"far fa-trash-alt\"\n class=\"ml-2 p-button-danger\" (click)=\"showDeleteConfirmatioModal()\"\n [disabled]=\"!canDelete\"></button>\n </ng-template>\n <ng-container *ngTemplateOutlet=\"buttonsRef || defaultButtons\"></ng-container>\n </div>\n </div>\n </div>\n</form>\n", styles: [".blockable-container{display:grid;place-items:center;grid-template-areas:\"inner\"}.blockable-element{grid-area:inner;width:100%}.blockable-overlay{grid-area:inner;height:100%;width:100%;background-color:#0006;display:flex;align-items:center;justify-content:center;z-index:1}\n"], dependencies: [{ kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i5.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3$1.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading"] }, { kind: "component", type: i7.ProgressSpinner, selector: "p-progressSpinner", inputs: ["style", "styleClass", "strokeWidth", "fill", "animationDuration"] }, { kind: "directive", type: i8.Ripple, selector: "[pRipple]" }, { kind: "component", type: RestWorldInputTemplateComponent, selector: "rw-input-template", inputs: ["apiName", "template"] }] });
1366
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldFormComponent, decorators: [{
1367
+ type: Component,
1368
+ args: [{ selector: 'rw-form', template: "<form *ngIf=\"formGroup !== undefined && template !== undefined\" [formGroup]=\"formGroup\" (ngSubmit)=\"submit()\">\n <div class=\"blockable-container\">\n <div class=\"blockable-element\">\n <rw-input-template [template]=\"template\" [apiName]=\"apiName\"></rw-input-template>\n </div>\n <div class=\"blockable-overlay\" *ngIf=\"isLoading\">\n <p-progressSpinner></p-progressSpinner>\n </div>\n </div>\n\n <div class=\"grid\">\n <div class=\"col\">\n <div class=\"flex justify-content-end w-full\">\n <ng-template #defaultButtons>\n <button pButton pRipple type=\"submit\" label=\"Save\" icon=\"far fa-save\" class=\"mx-2 p-button-success\"\n [disabled]=\"!canSubmit\"></button>\n <button pButton pRipple type=\"button\" label=\"Reload\" icon=\"fas fa-redo\" class=\"mx-2 p-button-info\"\n (click)=\"reload()\" [disabled]=\"!canReload\"></button>\n <button pButton pRipple type=\"button\" label=\"Delete\" icon=\"far fa-trash-alt\"\n class=\"ml-2 p-button-danger\" (click)=\"showDeleteConfirmatioModal()\"\n [disabled]=\"!canDelete\"></button>\n </ng-template>\n <ng-container *ngTemplateOutlet=\"buttonsRef || defaultButtons\"></ng-container>\n </div>\n </div>\n </div>\n</form>\n", styles: [".blockable-container{display:grid;place-items:center;grid-template-areas:\"inner\"}.blockable-element{grid-area:inner;width:100%}.blockable-overlay{grid-area:inner;height:100%;width:100%;background-color:#0006;display:flex;align-items:center;justify-content:center;z-index:1}\n"] }]
1369
+ }], ctorParameters: function () { return [{ type: RestWorldClientCollection }, { type: i2$3.ConfirmationService }, { type: i2$3.MessageService }, { type: FormService }]; }, propDecorators: { template: [{
1370
+ type: Input
1371
+ }], apiName: [{
1372
+ type: Input
1373
+ }], rel: [{
1374
+ type: Input
1375
+ }], allowSubmit: [{
1376
+ type: Input
1377
+ }], allowDelete: [{
1378
+ type: Input
1379
+ }], allowReload: [{
1380
+ type: Input
1381
+ }], showSubmit: [{
1382
+ type: Input
1383
+ }], showDelete: [{
1384
+ type: Input
1385
+ }], showReload: [{
1386
+ type: Input
1387
+ }], afterDelete: [{
1388
+ type: Output
1389
+ }], afterSubmit: [{
1390
+ type: Output
1391
+ }], buttonsRef: [{
1392
+ type: ContentChild,
1393
+ args: ['buttons', { static: false }]
1394
+ }] } });
1395
+
1396
+ class RestWorldIdNavigationComponent {
1397
+ constructor(_clients, _messageService, _router, _route) {
1398
+ this._clients = _clients;
1399
+ this._messageService = _messageService;
1400
+ this._router = _router;
1401
+ this._route = _route;
1402
+ this.idNavigationForm = new FormGroup({
1403
+ id: new FormControl(null, Validators.compose([Validators.min(1), Validators.max(Number.MAX_SAFE_INTEGER)]))
1404
+ });
1405
+ }
1406
+ navigateById() {
1407
+ var _a, _b, _c;
1408
+ return __awaiter(this, void 0, void 0, function* () {
1409
+ if (!this.rel)
1410
+ throw new Error('The "rel" must be set through the uri of this page for the ID navigation to work.');
1411
+ if (!this.idNavigationForm.valid) {
1412
+ this._messageService.add({ detail: 'You must enter a valid ID to naviage to.', severity: 'error' });
1413
+ return;
1414
+ }
1415
+ var idToNavigateTo = this.idNavigationForm.controls.id.value;
1416
+ var client = this.getClient();
1417
+ var response = yield client.getList(this.rel, { $filter: `id eq ${idToNavigateTo}` });
1418
+ if (!response.ok || ProblemDetails.isProblemDetails(response.body) || !response.body) {
1419
+ this._messageService.add({ severity: 'error', summary: 'Error', detail: 'Error while loading the resources from the API.', data: response });
1420
+ return;
1421
+ }
1422
+ var resource = (_c = (_b = (_a = response.body) === null || _a === void 0 ? void 0 : _a._embedded) === null || _b === void 0 ? void 0 : _b.items) === null || _c === void 0 ? void 0 : _c[0];
1423
+ if (!resource) {
1424
+ this._messageService.add({ severity: 'error', summary: 'Error', detail: 'No resource found with the specified ID.' });
1425
+ return;
1426
+ }
1427
+ if (this.urlPrefix !== undefined)
1428
+ yield this._router.navigate([this.urlPrefix, resource._links.self[0].href]);
1429
+ else
1430
+ yield this._router.navigate(["..", resource._links.self[0].href], { relativeTo: this._route });
1431
+ this.idNavigationForm.reset();
1432
+ });
1433
+ }
1434
+ getClient() {
1435
+ if (!this.apiName)
1436
+ throw new Error('Cannot get a client, because the apiName is not set.');
1437
+ return this._clients.getClient(this.apiName);
1438
+ }
1439
+ }
1440
+ RestWorldIdNavigationComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldIdNavigationComponent, deps: [{ token: RestWorldClientCollection }, { token: i2$3.MessageService }, { token: i3$2.Router }, { token: i3$2.ActivatedRoute }], target: i0.ɵɵFactoryTarget.Component });
1441
+ RestWorldIdNavigationComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.3", type: RestWorldIdNavigationComponent, selector: "rw-id-navigation", inputs: { apiName: "apiName", rel: "rel", urlPrefix: "urlPrefix" }, ngImport: i0, template: "<form [formGroup]=\"idNavigationForm\" (ngSubmit)=\"navigateById()\" class=\"mr-3\">\n <div class=\"p-inputgroup\">\n <p-inputNumber formControlName=\"id\" placeholder=\"Navigate by ID\"></p-inputNumber>\n <button type=\"submit\" pButton pRipple icon=\"fa-solid fa-arrow-right\"></button>\n </div>\n</form>\n", styles: [""], dependencies: [{ kind: "directive", type: i5.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i5.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i16.InputNumber, selector: "p-inputNumber", inputs: ["showButtons", "format", "buttonLayout", "inputId", "styleClass", "style", "placeholder", "size", "maxlength", "tabindex", "title", "ariaLabel", "ariaRequired", "name", "required", "autocomplete", "min", "max", "incrementButtonClass", "decrementButtonClass", "incrementButtonIcon", "decrementButtonIcon", "readonly", "step", "allowEmpty", "locale", "localeMatcher", "mode", "currency", "currencyDisplay", "useGrouping", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "inputStyle", "inputStyleClass", "showClear", "disabled"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown", "onClear"] }, { kind: "directive", type: i3$1.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading"] }, { kind: "directive", type: i8.Ripple, selector: "[pRipple]" }] });
1442
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldIdNavigationComponent, decorators: [{
1443
+ type: Component,
1444
+ args: [{ selector: 'rw-id-navigation', template: "<form [formGroup]=\"idNavigationForm\" (ngSubmit)=\"navigateById()\" class=\"mr-3\">\n <div class=\"p-inputgroup\">\n <p-inputNumber formControlName=\"id\" placeholder=\"Navigate by ID\"></p-inputNumber>\n <button type=\"submit\" pButton pRipple icon=\"fa-solid fa-arrow-right\"></button>\n </div>\n</form>\n" }]
1445
+ }], ctorParameters: function () { return [{ type: RestWorldClientCollection }, { type: i2$3.MessageService }, { type: i3$2.Router }, { type: i3$2.ActivatedRoute }]; }, propDecorators: { apiName: [{
1446
+ type: Input
1447
+ }], rel: [{
1448
+ type: Input
1449
+ }], urlPrefix: [{
1450
+ type: Input
1451
+ }] } });
1452
+
1453
+ class RestWorldMenuButtonComponent {
1454
+ constructor(_router) {
1455
+ this._router = _router;
1456
+ this.items = [];
1457
+ }
1458
+ onClick(item) {
1459
+ if (item.url) {
1460
+ window.location.href = item.url;
1461
+ }
1462
+ else if (item.routerLink) {
1463
+ this._router.navigate(item.routerLink, {
1464
+ queryParams: item.queryParams,
1465
+ fragment: item.fragment,
1466
+ queryParamsHandling: item.queryParamsHandling,
1467
+ preserveFragment: item.preserveFragment,
1468
+ skipLocationChange: item.skipLocationChange,
1469
+ replaceUrl: item.replaceUrl
1470
+ });
1471
+ }
1472
+ else if (item.command) {
1473
+ item.command();
1474
+ }
1475
+ }
1476
+ }
1477
+ RestWorldMenuButtonComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldMenuButtonComponent, deps: [{ token: i3$2.Router }], target: i0.ɵɵFactoryTarget.Component });
1478
+ RestWorldMenuButtonComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.3", type: RestWorldMenuButtonComponent, selector: "rw-menu-button", inputs: { items: "items" }, ngImport: i0, template: "<ng-container *ngFor=\"let item of items; index as i\">\n <p-button\n *ngIf=\"!item.items\"\n [label]=\"item.label!\"\n [icon]=\"item.icon!\"\n [disabled]=\"item.disabled!\"\n [style]=\"item.style\"\n [styleClass]=\"item.styleClass!\"\n [pTooltip]=\"item.tooltip!\"\n [tooltipPosition]=\"item.tooltipPosition!\"\n (onClick)=\"onClick(item)\"\n [class.ml-2]=\"i > 0\">\n </p-button>\n\n <p-splitButton\n *ngIf=\"item.items\"\n [label]=\"item.label!\"\n [icon]=\"item.icon!\"\n [model]=\"item.items\"\n appendTo=\"body\"\n [disabled]=\"item.disabled!\"\n [style]=\"item.style\"\n [styleClass]=\"item.styleClass!\"\n [pTooltip]=\"item.tooltip!\"\n [tooltipPosition]=\"item.tooltipPosition!\"\n (onClick)=\"onClick(item)\"\n [class.ml-2]=\"i > 0\">\n </p-splitButton>\n</ng-container>\n", styles: [""], dependencies: [{ kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "fitContent", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "component", type: i3$1.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "style", "styleClass", "badgeClass", "ariaLabel"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: i5$1.SplitButton, selector: "p-splitButton", inputs: ["model", "icon", "iconPos", "label", "style", "styleClass", "menuStyle", "menuStyleClass", "disabled", "tabindex", "appendTo", "dir", "expandAriaLabel", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onClick", "onDropdownClick"] }] });
1479
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldMenuButtonComponent, decorators: [{
1480
+ type: Component,
1481
+ args: [{ selector: 'rw-menu-button', template: "<ng-container *ngFor=\"let item of items; index as i\">\n <p-button\n *ngIf=\"!item.items\"\n [label]=\"item.label!\"\n [icon]=\"item.icon!\"\n [disabled]=\"item.disabled!\"\n [style]=\"item.style\"\n [styleClass]=\"item.styleClass!\"\n [pTooltip]=\"item.tooltip!\"\n [tooltipPosition]=\"item.tooltipPosition!\"\n (onClick)=\"onClick(item)\"\n [class.ml-2]=\"i > 0\">\n </p-button>\n\n <p-splitButton\n *ngIf=\"item.items\"\n [label]=\"item.label!\"\n [icon]=\"item.icon!\"\n [model]=\"item.items\"\n appendTo=\"body\"\n [disabled]=\"item.disabled!\"\n [style]=\"item.style\"\n [styleClass]=\"item.styleClass!\"\n [pTooltip]=\"item.tooltip!\"\n [tooltipPosition]=\"item.tooltipPosition!\"\n (onClick)=\"onClick(item)\"\n [class.ml-2]=\"i > 0\">\n </p-splitButton>\n</ng-container>\n" }]
1482
+ }], ctorParameters: function () { return [{ type: i3$2.Router }]; }, propDecorators: { items: [{
1483
+ type: Input
1484
+ }] } });
1485
+
1486
+ class ODataService {
1487
+ static createFilterForProperty(property, filter) {
1488
+ if (!filter.value)
1489
+ return undefined;
1490
+ const oDataOperator = ODataService.createODataOperator(filter.matchMode);
1491
+ const comparisonValue = ODataService.createComparisonValue(property, filter.value);
1492
+ switch (oDataOperator) {
1493
+ case 'contains':
1494
+ case 'not contains':
1495
+ case 'startswith':
1496
+ case 'endswith':
1497
+ return `${oDataOperator}(${property.name}, ${comparisonValue})`;
1498
+ default:
1499
+ return `${property.name} ${oDataOperator} ${comparisonValue}`;
1500
+ }
1501
+ }
1502
+ static createFilterForPropertyArray(property, filters) {
1503
+ const filter = filters
1504
+ .map(f => ODataService.createFilterForProperty(property, f))
1505
+ .filter(f => !!f)
1506
+ .join(` ${filters[0].operator} `);
1507
+ if (filter === '')
1508
+ return undefined;
1509
+ return `(${filter})`;
1510
+ }
1511
+ static createFilterFromTableLoadEvent(event, properties) {
1512
+ if (!event.filters || properties === undefined)
1513
+ return undefined;
1514
+ const filter = Object.entries(event.filters)
1515
+ // The type definition is wrong, event.filters has values of type FilterMetadata[] and not FilterMetadata.
1516
+ .map(([propertyName, filter]) => ({ property: ODataService.findPropertyByName(properties, propertyName), filters: filter }))
1517
+ .map(f => ODataService.createFilterForPropertyArray(f.property, f.filters))
1518
+ .filter(f => !!f)
1519
+ .join(' and ');
1520
+ if (filter === '')
1521
+ return undefined;
1522
+ return `(${filter})`;
1523
+ }
1524
+ static createOrderByFromTableLoadEvent(event) {
1525
+ if (event.sortField) {
1526
+ const order = !event.sortOrder || event.sortOrder > 0 ? 'asc' : 'desc';
1527
+ return `${event.sortField} ${order}`;
1528
+ }
1529
+ return undefined;
1530
+ }
1531
+ static createParametersFromTableLoadEvent(event, template) {
1532
+ const oDataParameters = {
1533
+ $filter: ODataService.createFilterFromTableLoadEvent(event, template === null || template === void 0 ? void 0 : template.properties),
1534
+ $orderby: ODataService.createOrderByFromTableLoadEvent(event),
1535
+ $top: ODataService.createTopFromTableLoadEvent(event),
1536
+ $skip: ODataService.createSkipFromTableLoadEvent(event)
1537
+ };
1538
+ return oDataParameters;
1539
+ }
1540
+ static createSkipFromTableLoadEvent(event) {
1541
+ return event.first;
1542
+ }
1543
+ static createTopFromTableLoadEvent(event) {
1544
+ return event.rows;
1545
+ }
1546
+ static createComparisonValue(property, value) {
1547
+ if (value === null || value === undefined)
1548
+ return 'null';
1549
+ const type = property.type;
1550
+ switch (type) {
1551
+ case PropertyType.Date:
1552
+ return `cast(${value.toISOString()}, Edm.DateOnly)`;
1553
+ case PropertyType.DatetimeLocal:
1554
+ return `cast(${value.toISOString()}, Edm.DateTime)`;
1555
+ case PropertyType.DatetimeOffset:
1556
+ return `cast(${value.toISOString()}, Edm.DateTimeOffset)`;
1557
+ case PropertyType.Time:
1558
+ return `cast(${value.toISOString()}, Edm.TimeOnly)`;
1559
+ case PropertyType.Duration:
1560
+ return `cast(${value.toISOString()}, Edm.TimeSpan)`;
1561
+ case PropertyType.Bool:
1562
+ case PropertyType.Number:
1563
+ return '' + value;
1564
+ default:
1565
+ return `'${value}'`;
1566
+ }
1567
+ }
1568
+ static createODataOperator(matchMode) {
1569
+ switch (matchMode) {
1570
+ case FilterMatchMode.STARTS_WITH:
1571
+ return 'startswith';
1572
+ case FilterMatchMode.CONTAINS:
1573
+ return 'contains';
1574
+ case FilterMatchMode.NOT_CONTAINS:
1575
+ return 'not contains';
1576
+ case FilterMatchMode.ENDS_WITH:
1577
+ return 'endswith';
1578
+ case FilterMatchMode.EQUALS:
1579
+ return 'eq';
1580
+ case FilterMatchMode.NOT_EQUALS:
1581
+ return 'ne';
1582
+ case FilterMatchMode.IN:
1583
+ return 'in';
1584
+ case FilterMatchMode.LESS_THAN:
1585
+ return 'lt';
1586
+ case FilterMatchMode.LESS_THAN_OR_EQUAL_TO:
1587
+ return 'le';
1588
+ case FilterMatchMode.GREATER_THAN:
1589
+ return 'gt';
1590
+ case FilterMatchMode.GREATER_THAN_OR_EQUAL_TO:
1591
+ return 'ge';
1592
+ case FilterMatchMode.IS:
1593
+ return 'eq';
1594
+ case FilterMatchMode.IS_NOT:
1595
+ return 'ne';
1596
+ case FilterMatchMode.BEFORE:
1597
+ return 'lt';
1598
+ case FilterMatchMode.AFTER:
1599
+ return 'gt';
1600
+ case FilterMatchMode.DATE_AFTER:
1601
+ return 'ge';
1602
+ case FilterMatchMode.DATE_BEFORE:
1603
+ return 'lt';
1604
+ case FilterMatchMode.DATE_IS:
1605
+ return 'eq';
1606
+ case FilterMatchMode.DATE_IS_NOT:
1607
+ return 'ne';
1608
+ default:
1609
+ throw Error(`Unknown matchMode ${matchMode}`);
1610
+ }
1611
+ }
1612
+ static findPropertyByName(properties, propertyName) {
1613
+ const property = properties.find(p => p.name === propertyName);
1614
+ if (property === undefined)
1615
+ throw new Error(`Cannot find a property with the name ${propertyName} in the properties of the search form template.`);
1616
+ return property;
1617
+ }
1618
+ }
1619
+
1620
+ var ColumnFilterType;
1621
+ (function (ColumnFilterType) {
1622
+ ColumnFilterType["text"] = "text";
1623
+ ColumnFilterType["numeric"] = "numeric";
1624
+ ColumnFilterType["boolean"] = "boolean";
1625
+ ColumnFilterType["date"] = "date";
1626
+ })(ColumnFilterType || (ColumnFilterType = {}));
1627
+ class RestWorldTableComponent {
1628
+ constructor() {
1629
+ this._rows = [];
1630
+ this.rowsPerPageOptions = [10, 25, 50];
1631
+ this.headerMenu = [];
1632
+ this.rowMenu = () => [];
1633
+ this._rowMenus = [];
1634
+ this.showRowMenuAsColumn = true;
1635
+ this.showRowMenuOnRightClick = true;
1636
+ this.totalRecords = 0;
1637
+ this.styleClass = "";
1638
+ this.scrollable = true;
1639
+ this.scrollHeight = "flex";
1640
+ this.onFilterOrSortChanged = new EventEmitter();
1641
+ this._contextMenuItems = [];
1642
+ this.isLoading = false;
1643
+ this._columns = [];
1644
+ }
1645
+ set template(value) {
1646
+ var _a;
1647
+ this._template = value;
1648
+ this._columns = (_a = value === null || value === void 0 ? void 0 : value.properties.filter(p => p.type !== PropertyType.Hidden)) !== null && _a !== void 0 ? _a : [];
1649
+ this.setSortFieldAndSortOrder(value);
1650
+ }
1651
+ get template() {
1652
+ return this._template;
1653
+ }
1654
+ get rows() {
1655
+ return this._rows;
1656
+ }
1657
+ set rows(value) {
1658
+ this._rows = value;
1659
+ if (this.showRowMenuAsColumn)
1660
+ this._rowMenus = value.map(r => this.rowMenu(r, false));
1661
+ }
1662
+ get rowMenus() {
1663
+ return this._rowMenus;
1664
+ }
1665
+ get showMenuColumn() {
1666
+ return this.headerMenu.length > 0 || this.showRowMenuAsColumn;
1667
+ }
1668
+ setSortFieldAndSortOrder(template) {
1669
+ var _a, _b;
1670
+ const orderBy = (_b = (_a = template === null || template === void 0 ? void 0 : template.properties) === null || _a === void 0 ? void 0 : _a.find(p => (p === null || p === void 0 ? void 0 : p.name) === "$orderby")) === null || _b === void 0 ? void 0 : _b.value;
1671
+ if (orderBy === null || orderBy === undefined || typeof orderBy !== 'string')
1672
+ return;
1673
+ const [field, order] = orderBy.split(" ");
1674
+ const orderAsNumber = (order === null || order === void 0 ? void 0 : order.toLowerCase()) === "desc" ? -1 : 1;
1675
+ if (this.sortField !== field)
1676
+ this.sortField = field;
1677
+ if (this.sortOrder !== orderAsNumber)
1678
+ this.sortOrder = orderAsNumber;
1679
+ }
1680
+ get contextMenuItems() {
1681
+ return this._contextMenuItems;
1682
+ }
1683
+ get columns() {
1684
+ return this._columns;
1685
+ }
1686
+ get dateFormat() {
1687
+ return RestWorldTableComponent._dateFormat;
1688
+ }
1689
+ get PropertyType() {
1690
+ return PropertyType;
1691
+ }
1692
+ load(event) {
1693
+ this.sortField = event.sortField;
1694
+ this.sortOrder = event.sortOrder;
1695
+ const parameters = ODataService.createParametersFromTableLoadEvent(event, this.template);
1696
+ this.onFilterOrSortChanged.emit(parameters);
1697
+ }
1698
+ openContextMenu(event, row) {
1699
+ if (!this.showRowMenuOnRightClick || this.contextMenu === undefined)
1700
+ return;
1701
+ this._contextMenuItems = this.rowMenu(row, true);
1702
+ this.contextMenu.show(event);
1703
+ event.stopPropagation();
1704
+ }
1705
+ toColumnFilterType(propertyType) {
1706
+ switch (propertyType) {
1707
+ case PropertyType.Number:
1708
+ return ColumnFilterType.numeric;
1709
+ case PropertyType.Bool:
1710
+ return ColumnFilterType.boolean;
1711
+ case PropertyType.Date:
1712
+ case PropertyType.DatetimeLocal:
1713
+ case PropertyType.DatetimeOffset:
1714
+ return ColumnFilterType.date;
1715
+ default:
1716
+ return ColumnFilterType.text;
1717
+ }
1718
+ }
1719
+ }
1720
+ RestWorldTableComponent._dateFormat = new Date(3333, 10, 22)
1721
+ .toLocaleDateString()
1722
+ .replace("22", "dd")
1723
+ .replace("11", "MM")
1724
+ .replace("3333", "y")
1725
+ .replace("33", "yy");
1726
+ RestWorldTableComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1727
+ RestWorldTableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.3", type: RestWorldTableComponent, selector: "rw-table", inputs: { api: "api", template: "template", rows: "rows", rowsPerPageOptions: "rowsPerPageOptions", headerMenu: "headerMenu", rowMenu: "rowMenu", showRowMenuAsColumn: "showRowMenuAsColumn", showRowMenuOnRightClick: "showRowMenuOnRightClick", totalRecords: "totalRecords", styleClass: "styleClass", tableStyle: "tableStyle", scrollable: "scrollable", scrollHeight: "scrollHeight", isLoading: "isLoading" }, outputs: { onFilterOrSortChanged: "onFilterOrSortChanged" }, viewQueries: [{ propertyName: "contextMenu", first: true, predicate: ["contextMenu"], descendants: true }], ngImport: i0, template: "<p-table\n #table\n [value]=\"rows\"\n [columns]=\"columns\"\n [lazy]=\"true\"\n [lazyLoadOnInit]=\"false\"\n (onLazyLoad)=\"load($event)\"\n responsiveLayout=\"scroll\"\n [paginator]=\"true\"\n [rowsPerPageOptions]=\"rowsPerPageOptions\"\n [rows]=\"rows.length\"\n [totalRecords]=\"totalRecords\"\n [loading]=\"isLoading\"\n [sortField]=\"sortField!\"\n [sortOrder]=\"sortOrder!\"\n [styleClass]=\"styleClass\"\n [tableStyle]=\"tableStyle\"\n [scrollable]=\"scrollable\"\n [scrollHeight]=\"scrollHeight\">\n\n <ng-template pTemplate=\"header\" let-columns>\n <tr>\n <th *ngFor=\"let col of columns\" [pSortableColumn]=\"col.name\">\n <div class=\"p-d-flex p-jc-between p-ai-center\">\n {{col.prompt}}\n <ng-container *ngIf=\"!col.readOnly\">\n <p-sortIcon [field]=\"col.name\"></p-sortIcon>\n <p-columnFilter [type]=\"toColumnFilterType(col.type)\" [field]=\"col.name\" display=\"menu\"></p-columnFilter>\n </ng-container>\n </div>\n </th>\n <th *ngIf=\"showMenuColumn\" class=\"flex justify-content-end\">\n <rw-menu-button [items]=\"headerMenu\"></rw-menu-button>\n </th>\n </tr>\n </ng-template>\n\n <ng-template pTemplate=\"body\" let-entity let-columns=\"columns\" let-rowIndex=\"rowIndex\">\n <tr (contextmenu)=\"openContextMenu($event, entity)\">\n <td [ngSwitch]=\"col.type\" *ngFor=\"let col of columns\">\n <ng-container *ngSwitchCase=\"PropertyType.Text\">\n <rw-avatar *ngIf=\"col.name === 'createdBy' || col.name === 'lastChangedBy'\" [user]=\"entity[col.name]\"></rw-avatar>\n <span *ngIf=\"col.name !== 'createdBy' && col.name !== 'lastChangedBy'\">{{entity[col.name]}}</span>\n </ng-container>\n <span *ngSwitchCase=\"PropertyType.Number\" class=\"flex justify-content-end\">{{entity[col.name]}}</span>\n <span *ngSwitchCase=\"PropertyType.Bool\" class=\"flex justify-content-center\"><p-triStateCheckbox [(ngModel)]=\"entity[col.name]\" [readonly]=\"true\"></p-triStateCheckbox></span>\n <span *ngSwitchCase=\"PropertyType.Date\" [pTooltip]=\"entity[col.name]\">{{entity[col.name] | date:dateFormat}}</span>\n <span *ngSwitchCase=\"PropertyType.DatetimeLocal\" [pTooltip]=\"entity[col.name]\">{{entity[col.name] | date:dateFormat}}</span>\n <span *ngSwitchCase=\"PropertyType.DatetimeOffset\" [pTooltip]=\"entity[col.name]\">{{entity[col.name] | date:dateFormat}}</span>\n <span *ngSwitchCase=\"PropertyType.Collection\" class=\"flex justify-content-end\"><p *ngFor=\"let arrayElement of entity[col.name]\">{{arrayElement | json}}</p></span>\n <span *ngSwitchCase=\"PropertyType.Object\" class=\"flex justify-content-end\">{{entity[col.name] | json}}</span>\n </td>\n <td *ngIf=\"showMenuColumn\" class=\"flex justify-content-end\">\n <rw-menu-button *ngIf=\"showRowMenuAsColumn\" [items]=\"rowMenus[rowIndex - table.first]\"></rw-menu-button>\n </td>\n </tr>\n </ng-template>\n\n <p-contextMenu #contextMenu appendTo=\"body\" [model]=\"contextMenuItems\"></p-contextMenu>\n</p-table>\n", styles: [".p-tooltip{max-width:-moz-fit-content;max-width:fit-content}a.p-button{text-decoration:none}\n"], dependencies: [{ kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i2$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3$3.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "style", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "scrollDirection", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "responsive", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "autoLayout", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "groupRowsByOrder", "responsiveLayout", "breakpoint", "virtualRowHeight", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["selectAllChange", "selectionChange", "contextMenuSelectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i2$3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i3$3.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "component", type: i3$3.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "component", type: i3$3.ColumnFilter, selector: "p-columnFilter", inputs: ["field", "type", "display", "showMenu", "matchMode", "operator", "showOperator", "showClearButton", "showApplyButton", "showMatchModes", "showAddButton", "hideOnClear", "placeholder", "matchModeOptions", "maxConstraints", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "locale", "localeMatcher", "currency", "currencyDisplay", "useGrouping", "showButtons"] }, { kind: "directive", type: i2.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "fitContent", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "component", type: i19.TriStateCheckbox, selector: "p-triStateCheckbox", inputs: ["disabled", "name", "ariaLabelledBy", "tabindex", "inputId", "style", "styleClass", "label", "readonly", "checkboxTrueIcon", "checkboxFalseIcon"], outputs: ["onChange"] }, { kind: "component", type: i7$1.ContextMenu, selector: "p-contextMenu", inputs: ["model", "global", "target", "style", "styleClass", "appendTo", "autoZIndex", "baseZIndex", "triggerEvent"], outputs: ["onShow", "onHide"] }, { kind: "component", type: RestWorldAvatarComponent, selector: "rw-avatar", inputs: ["user"] }, { kind: "component", type: RestWorldMenuButtonComponent, selector: "rw-menu-button", inputs: ["items"] }, { kind: "pipe", type: i2$1.JsonPipe, name: "json" }, { kind: "pipe", type: i2$1.DatePipe, name: "date" }] });
1728
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestWorldTableComponent, decorators: [{
1729
+ type: Component,
1730
+ args: [{ selector: 'rw-table', template: "<p-table\n #table\n [value]=\"rows\"\n [columns]=\"columns\"\n [lazy]=\"true\"\n [lazyLoadOnInit]=\"false\"\n (onLazyLoad)=\"load($event)\"\n responsiveLayout=\"scroll\"\n [paginator]=\"true\"\n [rowsPerPageOptions]=\"rowsPerPageOptions\"\n [rows]=\"rows.length\"\n [totalRecords]=\"totalRecords\"\n [loading]=\"isLoading\"\n [sortField]=\"sortField!\"\n [sortOrder]=\"sortOrder!\"\n [styleClass]=\"styleClass\"\n [tableStyle]=\"tableStyle\"\n [scrollable]=\"scrollable\"\n [scrollHeight]=\"scrollHeight\">\n\n <ng-template pTemplate=\"header\" let-columns>\n <tr>\n <th *ngFor=\"let col of columns\" [pSortableColumn]=\"col.name\">\n <div class=\"p-d-flex p-jc-between p-ai-center\">\n {{col.prompt}}\n <ng-container *ngIf=\"!col.readOnly\">\n <p-sortIcon [field]=\"col.name\"></p-sortIcon>\n <p-columnFilter [type]=\"toColumnFilterType(col.type)\" [field]=\"col.name\" display=\"menu\"></p-columnFilter>\n </ng-container>\n </div>\n </th>\n <th *ngIf=\"showMenuColumn\" class=\"flex justify-content-end\">\n <rw-menu-button [items]=\"headerMenu\"></rw-menu-button>\n </th>\n </tr>\n </ng-template>\n\n <ng-template pTemplate=\"body\" let-entity let-columns=\"columns\" let-rowIndex=\"rowIndex\">\n <tr (contextmenu)=\"openContextMenu($event, entity)\">\n <td [ngSwitch]=\"col.type\" *ngFor=\"let col of columns\">\n <ng-container *ngSwitchCase=\"PropertyType.Text\">\n <rw-avatar *ngIf=\"col.name === 'createdBy' || col.name === 'lastChangedBy'\" [user]=\"entity[col.name]\"></rw-avatar>\n <span *ngIf=\"col.name !== 'createdBy' && col.name !== 'lastChangedBy'\">{{entity[col.name]}}</span>\n </ng-container>\n <span *ngSwitchCase=\"PropertyType.Number\" class=\"flex justify-content-end\">{{entity[col.name]}}</span>\n <span *ngSwitchCase=\"PropertyType.Bool\" class=\"flex justify-content-center\"><p-triStateCheckbox [(ngModel)]=\"entity[col.name]\" [readonly]=\"true\"></p-triStateCheckbox></span>\n <span *ngSwitchCase=\"PropertyType.Date\" [pTooltip]=\"entity[col.name]\">{{entity[col.name] | date:dateFormat}}</span>\n <span *ngSwitchCase=\"PropertyType.DatetimeLocal\" [pTooltip]=\"entity[col.name]\">{{entity[col.name] | date:dateFormat}}</span>\n <span *ngSwitchCase=\"PropertyType.DatetimeOffset\" [pTooltip]=\"entity[col.name]\">{{entity[col.name] | date:dateFormat}}</span>\n <span *ngSwitchCase=\"PropertyType.Collection\" class=\"flex justify-content-end\"><p *ngFor=\"let arrayElement of entity[col.name]\">{{arrayElement | json}}</p></span>\n <span *ngSwitchCase=\"PropertyType.Object\" class=\"flex justify-content-end\">{{entity[col.name] | json}}</span>\n </td>\n <td *ngIf=\"showMenuColumn\" class=\"flex justify-content-end\">\n <rw-menu-button *ngIf=\"showRowMenuAsColumn\" [items]=\"rowMenus[rowIndex - table.first]\"></rw-menu-button>\n </td>\n </tr>\n </ng-template>\n\n <p-contextMenu #contextMenu appendTo=\"body\" [model]=\"contextMenuItems\"></p-contextMenu>\n</p-table>\n", styles: [".p-tooltip{max-width:-moz-fit-content;max-width:fit-content}a.p-button{text-decoration:none}\n"] }]
1731
+ }], propDecorators: { api: [{
1732
+ type: Input
1733
+ }], template: [{
1734
+ type: Input
1735
+ }], rows: [{
1736
+ type: Input
1737
+ }], rowsPerPageOptions: [{
1738
+ type: Input
1739
+ }], headerMenu: [{
1740
+ type: Input
1741
+ }], rowMenu: [{
1742
+ type: Input
1743
+ }], showRowMenuAsColumn: [{
1744
+ type: Input
1745
+ }], showRowMenuOnRightClick: [{
1746
+ type: Input
1747
+ }], totalRecords: [{
1748
+ type: Input
1749
+ }], styleClass: [{
1750
+ type: Input
1751
+ }], tableStyle: [{
1752
+ type: Input
1753
+ }], scrollable: [{
1754
+ type: Input
1755
+ }], scrollHeight: [{
1756
+ type: Input
1757
+ }], onFilterOrSortChanged: [{
1758
+ type: Output
1759
+ }], contextMenu: [{
1760
+ type: ViewChild,
1761
+ args: ["contextMenu"]
1762
+ }], isLoading: [{
1763
+ type: Input
1764
+ }] } });
1765
+
1766
+ class RestWorldOptions {
1767
+ constructor(BaseUrl, Version) {
1768
+ this.BaseUrl = BaseUrl;
1769
+ this.Version = Version;
1770
+ if (!BaseUrl.endsWith('/'))
1771
+ throw new Error(`The provided BaseUrl '${BaseUrl}' does not end with a slash '/'.`);
1772
+ }
1773
+ }
1774
+
1775
+ class SettingsService {
1776
+ constructor(_clients) {
1777
+ this._clients = _clients;
1778
+ this.initializing = false;
1779
+ this.initialized = false;
1780
+ }
1781
+ get settings() {
1782
+ return SettingsService._settings;
1783
+ }
1784
+ ensureInitialized() {
1785
+ return __awaiter(this, void 0, void 0, function* () {
1786
+ if (this.initializing || this.initialized)
1787
+ return;
1788
+ this.initializing = true;
1789
+ yield SettingsService.ensureSettingsAreLoaded();
1790
+ yield this.populateRESTworldClientCollectionFromSettings();
1791
+ this.initialized = true;
1792
+ this.initializing = false;
1793
+ });
1794
+ }
1795
+ /**
1796
+ * Call this method in your main.ts before calling bootstrapModule(...)
1797
+ *
1798
+ * Example:
1799
+ * async function main() {
1800
+ * try {
1801
+ * await SettingsService.ensureSettingsAreLoaded();
1802
+ *
1803
+ * const providers : StaticProvider[] = [
1804
+ * { provide: 'BASE_URL', useFactory: getBaseUrl, deps: [] }
1805
+ * ];
1806
+ *
1807
+ * await platformBrowserDynamic(providers).bootstrapModule(AppModule);
1808
+ * }
1809
+ * catch (e) {
1810
+ * console.error(e);
1811
+ * }
1812
+ * }
1813
+ *
1814
+ * main();
1815
+ * */
1816
+ static ensureSettingsAreLoaded() {
1817
+ return __awaiter(this, void 0, void 0, function* () {
1818
+ if (SettingsService._settings === undefined) {
1819
+ const response = yield fetch('/settings');
1820
+ const settings = yield response.json();
1821
+ SettingsService._settings = settings;
1822
+ }
1823
+ });
1824
+ }
1825
+ populateRESTworldClientCollectionFromSettings() {
1826
+ var _a;
1827
+ return __awaiter(this, void 0, void 0, function* () {
1828
+ if (!((_a = this.settings) === null || _a === void 0 ? void 0 : _a.apiUrls))
1829
+ return;
1830
+ yield Promise.all(this.settings.apiUrls
1831
+ .map(api => this._clients.addOrGetExistingClient(api.name, new RestWorldOptions(api.url, api.version))));
1832
+ });
1833
+ }
1834
+ }
1835
+ SettingsService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: SettingsService, deps: [{ token: RestWorldClientCollection }], target: i0.ɵɵFactoryTarget.Injectable });
1836
+ SettingsService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: SettingsService, providedIn: 'root' });
1837
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: SettingsService, decorators: [{
1838
+ type: Injectable,
1839
+ args: [{
1840
+ providedIn: 'root'
1841
+ }]
1842
+ }], ctorParameters: function () { return [{ type: RestWorldClientCollection }]; } });
1264
1843
 
1265
1844
  class RESTworldEditViewComponent {
1266
- constructor(_clients, _confirmationService, _messageService, _location, _router, _formService, valdemortConfig) {
1845
+ constructor(_clients, _messageService, valdemortConfig) {
1267
1846
  this._clients = _clients;
1268
- this._confirmationService = _confirmationService;
1269
1847
  this._messageService = _messageService;
1270
- this._location = _location;
1271
- this._router = _router;
1272
- this._formService = _formService;
1273
1848
  this.idNavigationForm = new FormGroup({
1274
1849
  id: new FormControl(null, Validators.compose([Validators.min(1), Validators.max(Number.MAX_SAFE_INTEGER)]))
1275
1850
  });
1276
- this.isLoading = false;
1277
- this._formTabs = {};
1278
- this._templates = {};
1851
+ this.isLoading = true;
1852
+ this._templates = [];
1279
1853
  valdemortConfig.errorClasses = 'p-error text-sm';
1280
1854
  }
1855
+ get templates() {
1856
+ return this._templates;
1857
+ }
1281
1858
  get PropertyType() {
1282
1859
  return PropertyType;
1283
1860
  }
@@ -1288,34 +1865,9 @@ class RESTworldEditViewComponent {
1288
1865
  this._apiName = value;
1289
1866
  this.load();
1290
1867
  }
1291
- get canDelete() {
1292
- var _a, _b;
1293
- const length = (_b = (_a = this.resource) === null || _a === void 0 ? void 0 : _a._links["delete"]) === null || _b === void 0 ? void 0 : _b.length;
1294
- return length !== undefined && length > 0;
1295
- }
1296
- get canSave() {
1297
- var _a, _b;
1298
- const length = (_b = (_a = this.resource) === null || _a === void 0 ? void 0 : _a._links["save"]) === null || _b === void 0 ? void 0 : _b.length;
1299
- return length !== undefined && length > 0;
1300
- }
1301
- get formTabs() {
1302
- return this._formTabs;
1303
- }
1304
- get isLoadingForTheFirstTime() {
1305
- return Object.keys(this.templates).length === 0 && this.isLoading;
1306
- }
1307
- get rel() {
1308
- return this._rel;
1309
- }
1310
- set rel(value) {
1311
- this._rel = value;
1312
- }
1313
1868
  get resource() {
1314
1869
  return this._resource;
1315
1870
  }
1316
- get templates() {
1317
- return this._templates;
1318
- }
1319
1871
  get uri() {
1320
1872
  return this._uri;
1321
1873
  }
@@ -1323,148 +1875,19 @@ class RESTworldEditViewComponent {
1323
1875
  this._uri = value;
1324
1876
  this.load();
1325
1877
  }
1326
- static getSubControl(control, pathElement) {
1327
- if (pathElement === "")
1328
- return control;
1329
- if (control instanceof UntypedFormGroup)
1330
- return control.controls[pathElement];
1331
- if (control instanceof UntypedFormArray) {
1332
- const index = Number.parseInt(pathElement);
1333
- if (Number.isInteger(index))
1334
- return control.controls[index];
1335
- }
1336
- return control;
1337
- }
1338
- static jsonStringifyWithElipsis(value) {
1339
- const maxLength = 200;
1340
- const end = 10;
1341
- const start = maxLength - end - 2;
1342
- const json = JSON.stringify(value);
1343
- const shortened = json.length > maxLength ? json.substring(0, start) + '…' + json.substring(json.length - end) : json;
1344
- return shortened;
1345
- }
1346
- canSubmit(templateName) {
1347
- const form = this.formTabs[templateName];
1348
- return form && form.valid;
1349
- }
1350
- delete() {
1351
- return __awaiter(this, void 0, void 0, function* () {
1352
- if (!this.apiName || !this.uri || !this.resource)
1353
- return;
1354
- Object.assign(this.resource, this.formTabs.value);
1355
- yield this.getClient().delete(this.resource);
1356
- setTimeout(() => this._messageService.add({ severity: 'success', summary: 'Deleted', detail: 'The resource has been deleted.' }), 100);
1357
- this._location.back();
1358
- });
1359
- }
1360
- getTooltip(resource, keysToExclude) {
1361
- const tooltip = Object.entries(resource)
1362
- .filter(([key]) => !(key.startsWith('_') || ['createdAt', 'createdBy', 'lastChangedAt', 'lastChangedBy', 'timestamp'].includes(key) || (keysToExclude === null || keysToExclude === void 0 ? void 0 : keysToExclude.includes(key))))
1363
- .reduce((prev, [key, value], index) => `${prev}${index === 0 ? '' : '\n'}${key}: ${RESTworldEditViewComponent.jsonStringifyWithElipsis(value)}`, '');
1364
- return tooltip;
1365
- }
1366
- imageChanged(formControl, event) {
1367
- const file = event.files[0];
1368
- console.log(file);
1369
- const reader = new FileReader();
1370
- reader.onload = () => {
1371
- const uri = reader.result;
1372
- console.log(uri);
1373
- formControl.setValue(uri);
1374
- };
1375
- reader.readAsDataURL(file);
1376
- }
1377
1878
  load() {
1378
1879
  return __awaiter(this, void 0, void 0, function* () {
1379
1880
  if (!this.apiName || !this.uri)
1380
1881
  return;
1381
1882
  this.isLoading = true;
1382
- const response = yield this.getClient().getSingle(this.uri);
1883
+ const response = yield this.getClient().getSingleByUri(this.uri);
1383
1884
  if (!response.ok || ProblemDetails.isProblemDetails(response.body) || !response.body) {
1384
- this._messageService.add({ severity: 'error', summary: 'Error', detail: 'Error while loading the resource from the API.', data: response });
1885
+ this._messageService.add({ severity: 'error', summary: 'Error', detail: 'Error while loading the resource from the API.', data: response, sticky: true });
1385
1886
  }
1386
1887
  else {
1387
1888
  this._resource = response.body;
1388
- this._templates = yield this.getAllTemplates(this._resource);
1389
- this._formTabs = this._formService.createFormGroupsFromTemplates(this._templates);
1390
- }
1391
- this.isLoading = false;
1392
- });
1393
- }
1394
- navigateById() {
1395
- var _a, _b, _c;
1396
- return __awaiter(this, void 0, void 0, function* () {
1397
- if (!this.rel)
1398
- throw new Error('The "rel" must be set through the uri of this page for the ID navigation to work.');
1399
- if (!this.idNavigationForm.valid) {
1400
- this._messageService.add({ detail: 'You must enter a valid ID to naviage to.', severity: 'error' });
1401
- return;
1402
- }
1403
- var idToNavigateTo = this.idNavigationForm.controls.id.value;
1404
- var client = this.getClient();
1405
- var response = yield client.getList(this.rel, { $filter: `id eq ${idToNavigateTo}` });
1406
- if (!response.ok || ProblemDetails.isProblemDetails(response.body) || !response.body) {
1407
- this._messageService.add({ severity: 'error', summary: 'Error', detail: 'Error while loading the resources from the API.', data: response });
1408
- return;
1409
- }
1410
- var resource = (_c = (_b = (_a = response.body) === null || _a === void 0 ? void 0 : _a._embedded) === null || _b === void 0 ? void 0 : _b.items) === null || _c === void 0 ? void 0 : _c[0];
1411
- if (!resource) {
1412
- this._messageService.add({ severity: 'error', summary: 'Error', detail: 'No resource found with the specified ID.' });
1413
- return;
1414
- }
1415
- yield this._router.navigate(['/edit', this.apiName, this.rel, resource._links.self[0].href]);
1416
- this.idNavigationForm.reset();
1417
- });
1418
- }
1419
- showDeleteConfirmatioModal() {
1420
- this._confirmationService.confirm({
1421
- message: 'Do you really want to delete this resource?',
1422
- header: 'Confirm delete',
1423
- icon: 'far fa-trash-alt',
1424
- accept: () => this.delete()
1425
- });
1426
- }
1427
- submit(templateName, template, formValue) {
1428
- return __awaiter(this, void 0, void 0, function* () {
1429
- this.isLoading = true;
1430
- try {
1431
- const targetBeforeSave = template.target;
1432
- const response = yield this.getClient().submit(template, formValue);
1433
- if (!response.ok) {
1434
- let summary = 'Error';
1435
- let detail = 'Error while saving the resource.';
1436
- if (ProblemDetails.isProblemDetails(response.body)) {
1437
- const problemDetails = response.body;
1438
- summary = problemDetails.title || summary;
1439
- detail = problemDetails.detail || detail;
1440
- // display validation errors
1441
- if (problemDetails['errors']) {
1442
- const form = this.formTabs[templateName];
1443
- for (const [key, errorsForKey] of Object.entries(problemDetails['errors'])) {
1444
- const path = key.split(/\.|\[/).map(e => e.replace("]", ""));
1445
- // The path might start with a $, indicating the root.
1446
- if (path.length > 0 && path[0] === '$')
1447
- path.shift();
1448
- const formControl = path.reduce(RESTworldEditViewComponent.getSubControl, form);
1449
- formControl.setErrors(Object.assign(Object.assign({}, formControl.errors), { remote: errorsForKey }));
1450
- formControl.markAsTouched();
1451
- }
1452
- }
1453
- }
1454
- this._messageService.add({ severity: 'error', summary: summary, detail: detail, data: response, life: 10000 });
1455
- }
1456
- else {
1457
- const responseResource = response.body;
1458
- const targetAfterSave = responseResource._templates[templateName].target;
1459
- setTimeout(() => this._messageService.add({ severity: 'success', summary: 'Saved', detail: 'The resource has been saved.' }), 100);
1460
- if (targetBeforeSave !== targetAfterSave) {
1461
- this._router.navigate(['/edit', this.apiName, responseResource._links.self[0].href]);
1462
- }
1463
- }
1464
- }
1465
- catch (e) {
1466
- this._messageService.add({ severity: 'error', summary: 'Error', detail: `An unknown error occurred. ${JSON.stringify(e)}`, life: 10000 });
1467
- console.log(e);
1889
+ const templates = yield this.getAllTemplates(this._resource);
1890
+ this._templates = Object.values(templates);
1468
1891
  }
1469
1892
  this.isLoading = false;
1470
1893
  });
@@ -1486,92 +1909,14 @@ class RESTworldEditViewComponent {
1486
1909
  return this._clients.getClient(this.apiName);
1487
1910
  }
1488
1911
  }
1489
- RESTworldEditViewComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RESTworldEditViewComponent, deps: [{ token: RESTworldClientCollection }, { token: i2$1.ConfirmationService }, { token: i2$1.MessageService }, { token: i4.Location }, { token: i4$2.Router }, { token: FormService }, { token: i16.ValdemortConfig }], target: i0.ɵɵFactoryTarget.Component });
1490
- RESTworldEditViewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.3", type: RESTworldEditViewComponent, selector: "rw-edit", inputs: { apiName: "apiName", rel: "rel", uri: "uri" }, queries: [{ propertyName: "buttonsRef", first: true, predicate: ["buttons"], descendants: true }, { propertyName: "extraTabsRef", first: true, predicate: ["extraTabs"], descendants: true }, { propertyName: "inputBoolRef", first: true, predicate: ["inputBool"], descendants: true }, { propertyName: "inputColorRef", first: true, predicate: ["inputColor"], descendants: true }, { propertyName: "inputDateRef", first: true, predicate: ["inputDate"], descendants: true }, { propertyName: "inputDatetimeLocalRef", first: true, predicate: ["inputDatetimeLocal"], descendants: true }, { propertyName: "inputDatetimeOffsetRef", first: true, predicate: ["inputDatetimeOffset"], descendants: true }, { propertyName: "inputDefaultRef", first: true, predicate: ["inputDefault"], descendants: true }, { propertyName: "inputDurationRef", first: true, predicate: ["inputDuration"], descendants: true }, { propertyName: "inputEmailRef", first: true, predicate: ["inputEmail"], descendants: true }, { propertyName: "inputFileRef", first: true, predicate: ["inputFile"], descendants: true }, { propertyName: "inputHiddenRef", first: true, predicate: ["inputHidden"], descendants: true }, { propertyName: "inputImageRef", first: true, predicate: ["inputImage"], descendants: true }, { propertyName: "inputMonthRef", first: true, predicate: ["inputMonth"], descendants: true }, { propertyName: "inputNumberRef", first: true, predicate: ["inputNumber"], descendants: true }, { propertyName: "inputOptionsMultipleRef", first: true, predicate: ["inputOptionsMultiple"], descendants: true }, { propertyName: "inputOptionsRef", first: true, predicate: ["inputOptions"], descendants: true }, { propertyName: "inputOptionsSingleRef", first: true, predicate: ["inputOptionsSingle"], descendants: true }, { propertyName: "inputPasswordRef", first: true, predicate: ["inputPassword"], descendants: true }, { propertyName: "inputRangeRef", first: true, predicate: ["inputRange"], descendants: true }, { propertyName: "inputSearchRef", first: true, predicate: ["inputSearch"], descendants: true }, { propertyName: "inputTelRef", first: true, predicate: ["inputTel"], descendants: true }, { propertyName: "inputTextRef", first: true, predicate: ["inputText"], descendants: true }, { propertyName: "inputTextareaRef", first: true, predicate: ["inputTextarea"], descendants: true }, { propertyName: "inputTimeRef", first: true, predicate: ["inputTime"], descendants: true }, { propertyName: "inputUrlRef", first: true, predicate: ["inputUrl"], descendants: true }, { propertyName: "inputWeekRef", first: true, predicate: ["inputWeek"], descendants: true }], ngImport: i0, template: "<div class=\"grid\">\r\n <div class=\"col-12 md:col-10\">\r\n <h1>Edit resource</h1>\r\n </div>\r\n <div class=\"col-12 md:col-2 align-items-center justify-content-end flex\">\r\n <form [formGroup]=\"idNavigationForm\" (ngSubmit)=\"navigateById()\" class=\"mr-3\">\r\n <div class=\"p-inputgroup\">\r\n <p-inputNumber formControlName=\"id\" placeholder=\"Navigate by ID\"></p-inputNumber>\r\n <button type=\"submit\" pButton pRipple icon=\"fa-solid fa-arrow-right\"></button>\r\n </div>\r\n </form>\r\n </div>\r\n</div>\r\n\r\n<p-tabView>\r\n\r\n <p-tabPanel *ngIf=\"isLoadingForTheFirstTime\" header=\"Loading\">\r\n <div *ngFor=\"let i of [1, 2, 3, 4, 5]\" class=\"grid field\">\r\n <p-skeleton class=\"col-12 mb-2 md:col-2 md:mb-0\" height=\"39px\"></p-skeleton>\r\n <div class=\"col-12 md:col-10\">\r\n <p-skeleton class=\"w-full\" height=\"39px\"></p-skeleton>\r\n </div>\r\n </div>\r\n <div class=\"grid\">\r\n <div class=\"col\">\r\n <div class=\"flex justify-content-end w-full\">\r\n <p-skeleton width=\"120px\" height=\"39px\" class=\"mx-2\"></p-skeleton>\r\n <p-skeleton width=\"120px\" height=\"39px\" class=\"mx-2\"></p-skeleton>\r\n <p-skeleton width=\"120px\" height=\"39px\" class=\"mx-2\"></p-skeleton>\r\n </div>\r\n </div>\r\n </div>\r\n </p-tabPanel>\r\n\r\n <p-tabPanel *ngFor=\"let item of templates | keyvalue\" [header]=\"item.value.title || item.key\" [disabled]=\"isLoading\">\r\n <form [formGroup]=\"formTabs[item.key]\" (ngSubmit)=\"submit(item.key, item.value, formTabs[item.key].value)\">\r\n <div class=\"blockable-container\">\r\n <div class=\"blockable-element\">\r\n <rw-form [formGroup]=\"formTabs[item.key]\" [template]=\"item.value\" [apiName]=\"apiName\"></rw-form>\r\n </div>\r\n <div class=\"blockable-overlay\" *ngIf=\"isLoading\">\r\n <p-progressSpinner></p-progressSpinner>\r\n </div>\r\n </div>\r\n\r\n <div class=\"grid\">\r\n <div class=\"col\">\r\n <div class=\"flex justify-content-end w-full\">\r\n <ng-template #defaultButtons>\r\n <button pButton pRipple type=\"submit\" label=\"Save\" icon=\"far fa-save\" class=\"mx-2 p-button-success\" [disabled]=\"isLoading || !canSubmit(item.key)\"></button>\r\n <button pButton pRipple type=\"button\" label=\"Reload\" icon=\"fas fa-redo\" class=\"mx-2 p-button-info\" (click)=\"load()\" [disabled]=\"isLoading\"></button>\r\n <button pButton pRipple type=\"button\" label=\"Delete\" icon=\"far fa-trash-alt\" class=\"ml-2 p-button-danger\" (click)=\"showDeleteConfirmatioModal()\" [disabled]=\"!resource || isLoading || !canDelete\"></button>\r\n </ng-template>\r\n <ng-container *ngTemplateOutlet=\"buttonsRef || defaultButtons\"></ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n </form>\r\n </p-tabPanel>\r\n\r\n <ng-template #defaultExtraTabs>\r\n </ng-template>\r\n <ng-container *ngTemplateOutlet=\"extraTabsRef || defaultExtraTabs\"></ng-container>\r\n\r\n</p-tabView>\r\n\r\n<p-toast></p-toast>\r\n<p-confirmDialog></p-confirmDialog>\r\n", styles: ["::ng-deep .p-tooltip{max-width:-moz-fit-content!important;max-width:fit-content!important}.blockable-container{display:grid;place-items:center;grid-template-areas:\"inner\"}.blockable-element{grid-area:inner;width:100%}.blockable-overlay{grid-area:inner;height:100%;width:100%;background-color:#0006;display:flex;align-items:center;justify-content:center;z-index:1}.field.grid>label.hasChildren{border-right:1px solid rgba(0,0,0,.1)}\n"], dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i5.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i5.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i8$1.InputNumber, selector: "p-inputNumber", inputs: ["showButtons", "format", "buttonLayout", "inputId", "styleClass", "style", "placeholder", "size", "maxlength", "tabindex", "title", "ariaLabel", "ariaRequired", "name", "required", "autocomplete", "min", "max", "incrementButtonClass", "decrementButtonClass", "incrementButtonIcon", "decrementButtonIcon", "readonly", "step", "allowEmpty", "locale", "localeMatcher", "mode", "currency", "currencyDisplay", "useGrouping", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "inputStyle", "inputStyleClass", "showClear", "disabled"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown", "onClear"] }, { kind: "directive", type: i5$1.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading"] }, { kind: "component", type: i10$1.ConfirmDialog, selector: "p-confirmDialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "visible", "position"], outputs: ["onHide"] }, { kind: "component", type: i11$1.Toast, selector: "p-toast", inputs: ["key", "autoZIndex", "baseZIndex", "style", "styleClass", "position", "preventOpenDuplicates", "preventDuplicates", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions", "breakpoints"], outputs: ["onClose"] }, { kind: "component", type: i12.TabView, selector: "p-tabView", inputs: ["orientation", "style", "styleClass", "controlClose", "scrollable", "activeIndex"], outputs: ["onChange", "onClose", "activeIndexChange"] }, { kind: "component", type: i12.TabPanel, selector: "p-tabPanel", inputs: ["closable", "headerStyle", "headerStyleClass", "cache", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "selected", "disabled", "header", "leftIcon", "rightIcon"] }, { kind: "component", type: i13$1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "style", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "component", type: i14$1.ProgressSpinner, selector: "p-progressSpinner", inputs: ["style", "styleClass", "strokeWidth", "fill", "animationDuration"] }, { kind: "directive", type: i6.Ripple, selector: "[pRipple]" }, { kind: "component", type: RestworldEditFormComponent, selector: "rw-form", inputs: ["formGroup", "template", "apiName"] }, { kind: "pipe", type: i4.KeyValuePipe, name: "keyvalue" }] });
1912
+ RESTworldEditViewComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RESTworldEditViewComponent, deps: [{ token: RestWorldClientCollection }, { token: i2$3.MessageService }, { token: i2$2.ValdemortConfig }], target: i0.ɵɵFactoryTarget.Component });
1913
+ RESTworldEditViewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.3", type: RESTworldEditViewComponent, selector: "rw-edit", inputs: { apiName: "apiName", rel: "rel", uri: "uri" }, queries: [{ propertyName: "extraTabsRef", first: true, predicate: ["extraTabs"], descendants: true }], ngImport: i0, template: "<div class=\"grid\">\r\n <div class=\"col-12 md:col-10\">\r\n <h1>Edit resource</h1>\r\n </div>\r\n <div class=\"col-12 md:col-2 align-items-center justify-content-end flex\">\r\n <rw-id-navigation [apiName]=\"apiName\" [rel]=\"rel\"></rw-id-navigation>\r\n </div>\r\n</div>\r\n\r\n<p-tabView>\r\n\r\n <p-tabPanel *ngIf=\"isLoading; else tabs\" header=\"Loading\">\r\n <div *ngFor=\"let i of [1, 2, 3, 4, 5]\" class=\"grid field\">\r\n <p-skeleton class=\"col-12 mb-2 md:col-2 md:mb-0\" height=\"39px\"></p-skeleton>\r\n <div class=\"col-12 md:col-10\">\r\n <p-skeleton class=\"w-full\" height=\"39px\"></p-skeleton>\r\n </div>\r\n </div>\r\n <div class=\"grid\">\r\n <div class=\"col\">\r\n <div class=\"flex justify-content-end w-full\">\r\n <p-skeleton width=\"120px\" height=\"39px\" class=\"mx-2\"></p-skeleton>\r\n <p-skeleton width=\"120px\" height=\"39px\" class=\"mx-2\"></p-skeleton>\r\n <p-skeleton width=\"120px\" height=\"39px\" class=\"mx-2\"></p-skeleton>\r\n </div>\r\n </div>\r\n </div>\r\n </p-tabPanel>\r\n\r\n <ng-template #tabs>\r\n <p-tabPanel *ngFor=\"let template of templates\" [header]=\"template.title ?? ''\" [disabled]=\"isLoading\">\r\n <rw-form [template]=\"template\" [apiName]=\"apiName\"></rw-form>\r\n </p-tabPanel>\r\n</ng-template>\r\n\r\n <ng-template #defaultExtraTabs>\r\n </ng-template>\r\n <ng-container *ngTemplateOutlet=\"extraTabsRef || defaultExtraTabs\"></ng-container>\r\n\r\n</p-tabView>\r\n\r\n<p-toast></p-toast>\r\n<p-confirmDialog></p-confirmDialog>\r\n", styles: ["::ng-deep .p-tooltip{max-width:-moz-fit-content!important;max-width:fit-content!important}.field.grid>label.hasChildren{border-right:1px solid rgba(0,0,0,.1)}\n"], dependencies: [{ kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i5$2.ConfirmDialog, selector: "p-confirmDialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "visible", "position"], outputs: ["onHide"] }, { kind: "component", type: i6.Toast, selector: "p-toast", inputs: ["key", "autoZIndex", "baseZIndex", "style", "styleClass", "position", "preventOpenDuplicates", "preventDuplicates", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions", "breakpoints"], outputs: ["onClose"] }, { kind: "component", type: i7$2.TabView, selector: "p-tabView", inputs: ["orientation", "style", "styleClass", "controlClose", "scrollable", "activeIndex"], outputs: ["onChange", "onClose", "activeIndexChange"] }, { kind: "component", type: i7$2.TabPanel, selector: "p-tabPanel", inputs: ["closable", "headerStyle", "headerStyleClass", "cache", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "selected", "disabled", "header", "leftIcon", "rightIcon"] }, { kind: "component", type: i8$2.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "style", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "component", type: RestWorldFormComponent, selector: "rw-form", inputs: ["template", "apiName", "rel", "allowSubmit", "allowDelete", "allowReload", "showSubmit", "showDelete", "showReload"], outputs: ["afterDelete", "afterSubmit"] }, { kind: "component", type: RestWorldIdNavigationComponent, selector: "rw-id-navigation", inputs: ["apiName", "rel", "urlPrefix"] }] });
1491
1914
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RESTworldEditViewComponent, decorators: [{
1492
1915
  type: Component,
1493
- args: [{ selector: 'rw-edit', template: "<div class=\"grid\">\r\n <div class=\"col-12 md:col-10\">\r\n <h1>Edit resource</h1>\r\n </div>\r\n <div class=\"col-12 md:col-2 align-items-center justify-content-end flex\">\r\n <form [formGroup]=\"idNavigationForm\" (ngSubmit)=\"navigateById()\" class=\"mr-3\">\r\n <div class=\"p-inputgroup\">\r\n <p-inputNumber formControlName=\"id\" placeholder=\"Navigate by ID\"></p-inputNumber>\r\n <button type=\"submit\" pButton pRipple icon=\"fa-solid fa-arrow-right\"></button>\r\n </div>\r\n </form>\r\n </div>\r\n</div>\r\n\r\n<p-tabView>\r\n\r\n <p-tabPanel *ngIf=\"isLoadingForTheFirstTime\" header=\"Loading\">\r\n <div *ngFor=\"let i of [1, 2, 3, 4, 5]\" class=\"grid field\">\r\n <p-skeleton class=\"col-12 mb-2 md:col-2 md:mb-0\" height=\"39px\"></p-skeleton>\r\n <div class=\"col-12 md:col-10\">\r\n <p-skeleton class=\"w-full\" height=\"39px\"></p-skeleton>\r\n </div>\r\n </div>\r\n <div class=\"grid\">\r\n <div class=\"col\">\r\n <div class=\"flex justify-content-end w-full\">\r\n <p-skeleton width=\"120px\" height=\"39px\" class=\"mx-2\"></p-skeleton>\r\n <p-skeleton width=\"120px\" height=\"39px\" class=\"mx-2\"></p-skeleton>\r\n <p-skeleton width=\"120px\" height=\"39px\" class=\"mx-2\"></p-skeleton>\r\n </div>\r\n </div>\r\n </div>\r\n </p-tabPanel>\r\n\r\n <p-tabPanel *ngFor=\"let item of templates | keyvalue\" [header]=\"item.value.title || item.key\" [disabled]=\"isLoading\">\r\n <form [formGroup]=\"formTabs[item.key]\" (ngSubmit)=\"submit(item.key, item.value, formTabs[item.key].value)\">\r\n <div class=\"blockable-container\">\r\n <div class=\"blockable-element\">\r\n <rw-form [formGroup]=\"formTabs[item.key]\" [template]=\"item.value\" [apiName]=\"apiName\"></rw-form>\r\n </div>\r\n <div class=\"blockable-overlay\" *ngIf=\"isLoading\">\r\n <p-progressSpinner></p-progressSpinner>\r\n </div>\r\n </div>\r\n\r\n <div class=\"grid\">\r\n <div class=\"col\">\r\n <div class=\"flex justify-content-end w-full\">\r\n <ng-template #defaultButtons>\r\n <button pButton pRipple type=\"submit\" label=\"Save\" icon=\"far fa-save\" class=\"mx-2 p-button-success\" [disabled]=\"isLoading || !canSubmit(item.key)\"></button>\r\n <button pButton pRipple type=\"button\" label=\"Reload\" icon=\"fas fa-redo\" class=\"mx-2 p-button-info\" (click)=\"load()\" [disabled]=\"isLoading\"></button>\r\n <button pButton pRipple type=\"button\" label=\"Delete\" icon=\"far fa-trash-alt\" class=\"ml-2 p-button-danger\" (click)=\"showDeleteConfirmatioModal()\" [disabled]=\"!resource || isLoading || !canDelete\"></button>\r\n </ng-template>\r\n <ng-container *ngTemplateOutlet=\"buttonsRef || defaultButtons\"></ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n </form>\r\n </p-tabPanel>\r\n\r\n <ng-template #defaultExtraTabs>\r\n </ng-template>\r\n <ng-container *ngTemplateOutlet=\"extraTabsRef || defaultExtraTabs\"></ng-container>\r\n\r\n</p-tabView>\r\n\r\n<p-toast></p-toast>\r\n<p-confirmDialog></p-confirmDialog>\r\n", styles: ["::ng-deep .p-tooltip{max-width:-moz-fit-content!important;max-width:fit-content!important}.blockable-container{display:grid;place-items:center;grid-template-areas:\"inner\"}.blockable-element{grid-area:inner;width:100%}.blockable-overlay{grid-area:inner;height:100%;width:100%;background-color:#0006;display:flex;align-items:center;justify-content:center;z-index:1}.field.grid>label.hasChildren{border-right:1px solid rgba(0,0,0,.1)}\n"] }]
1494
- }], ctorParameters: function () { return [{ type: RESTworldClientCollection }, { type: i2$1.ConfirmationService }, { type: i2$1.MessageService }, { type: i4.Location }, { type: i4$2.Router }, { type: FormService }, { type: i16.ValdemortConfig }]; }, propDecorators: { buttonsRef: [{
1495
- type: ContentChild,
1496
- args: ['buttons', { static: false }]
1497
- }], extraTabsRef: [{
1916
+ args: [{ selector: 'rw-edit', template: "<div class=\"grid\">\r\n <div class=\"col-12 md:col-10\">\r\n <h1>Edit resource</h1>\r\n </div>\r\n <div class=\"col-12 md:col-2 align-items-center justify-content-end flex\">\r\n <rw-id-navigation [apiName]=\"apiName\" [rel]=\"rel\"></rw-id-navigation>\r\n </div>\r\n</div>\r\n\r\n<p-tabView>\r\n\r\n <p-tabPanel *ngIf=\"isLoading; else tabs\" header=\"Loading\">\r\n <div *ngFor=\"let i of [1, 2, 3, 4, 5]\" class=\"grid field\">\r\n <p-skeleton class=\"col-12 mb-2 md:col-2 md:mb-0\" height=\"39px\"></p-skeleton>\r\n <div class=\"col-12 md:col-10\">\r\n <p-skeleton class=\"w-full\" height=\"39px\"></p-skeleton>\r\n </div>\r\n </div>\r\n <div class=\"grid\">\r\n <div class=\"col\">\r\n <div class=\"flex justify-content-end w-full\">\r\n <p-skeleton width=\"120px\" height=\"39px\" class=\"mx-2\"></p-skeleton>\r\n <p-skeleton width=\"120px\" height=\"39px\" class=\"mx-2\"></p-skeleton>\r\n <p-skeleton width=\"120px\" height=\"39px\" class=\"mx-2\"></p-skeleton>\r\n </div>\r\n </div>\r\n </div>\r\n </p-tabPanel>\r\n\r\n <ng-template #tabs>\r\n <p-tabPanel *ngFor=\"let template of templates\" [header]=\"template.title ?? ''\" [disabled]=\"isLoading\">\r\n <rw-form [template]=\"template\" [apiName]=\"apiName\"></rw-form>\r\n </p-tabPanel>\r\n</ng-template>\r\n\r\n <ng-template #defaultExtraTabs>\r\n </ng-template>\r\n <ng-container *ngTemplateOutlet=\"extraTabsRef || defaultExtraTabs\"></ng-container>\r\n\r\n</p-tabView>\r\n\r\n<p-toast></p-toast>\r\n<p-confirmDialog></p-confirmDialog>\r\n", styles: ["::ng-deep .p-tooltip{max-width:-moz-fit-content!important;max-width:fit-content!important}.field.grid>label.hasChildren{border-right:1px solid rgba(0,0,0,.1)}\n"] }]
1917
+ }], ctorParameters: function () { return [{ type: RestWorldClientCollection }, { type: i2$3.MessageService }, { type: i2$2.ValdemortConfig }]; }, propDecorators: { extraTabsRef: [{
1498
1918
  type: ContentChild,
1499
1919
  args: ['extraTabs', { static: false }]
1500
- }], inputBoolRef: [{
1501
- type: ContentChild,
1502
- args: ['inputBool', { static: false }]
1503
- }], inputColorRef: [{
1504
- type: ContentChild,
1505
- args: ['inputColor', { static: false }]
1506
- }], inputDateRef: [{
1507
- type: ContentChild,
1508
- args: ['inputDate', { static: false }]
1509
- }], inputDatetimeLocalRef: [{
1510
- type: ContentChild,
1511
- args: ['inputDatetimeLocal', { static: false }]
1512
- }], inputDatetimeOffsetRef: [{
1513
- type: ContentChild,
1514
- args: ['inputDatetimeOffset', { static: false }]
1515
- }], inputDefaultRef: [{
1516
- type: ContentChild,
1517
- args: ['inputDefault', { static: false }]
1518
- }], inputDurationRef: [{
1519
- type: ContentChild,
1520
- args: ['inputDuration', { static: false }]
1521
- }], inputEmailRef: [{
1522
- type: ContentChild,
1523
- args: ['inputEmail', { static: false }]
1524
- }], inputFileRef: [{
1525
- type: ContentChild,
1526
- args: ['inputFile', { static: false }]
1527
- }], inputHiddenRef: [{
1528
- type: ContentChild,
1529
- args: ['inputHidden', { static: false }]
1530
- }], inputImageRef: [{
1531
- type: ContentChild,
1532
- args: ['inputImage', { static: false }]
1533
- }], inputMonthRef: [{
1534
- type: ContentChild,
1535
- args: ['inputMonth', { static: false }]
1536
- }], inputNumberRef: [{
1537
- type: ContentChild,
1538
- args: ['inputNumber', { static: false }]
1539
- }], inputOptionsMultipleRef: [{
1540
- type: ContentChild,
1541
- args: ['inputOptionsMultiple', { static: false }]
1542
- }], inputOptionsRef: [{
1543
- type: ContentChild,
1544
- args: ['inputOptions', { static: false }]
1545
- }], inputOptionsSingleRef: [{
1546
- type: ContentChild,
1547
- args: ['inputOptionsSingle', { static: false }]
1548
- }], inputPasswordRef: [{
1549
- type: ContentChild,
1550
- args: ['inputPassword', { static: false }]
1551
- }], inputRangeRef: [{
1552
- type: ContentChild,
1553
- args: ['inputRange', { static: false }]
1554
- }], inputSearchRef: [{
1555
- type: ContentChild,
1556
- args: ['inputSearch', { static: false }]
1557
- }], inputTelRef: [{
1558
- type: ContentChild,
1559
- args: ['inputTel', { static: false }]
1560
- }], inputTextRef: [{
1561
- type: ContentChild,
1562
- args: ['inputText', { static: false }]
1563
- }], inputTextareaRef: [{
1564
- type: ContentChild,
1565
- args: ['inputTextarea', { static: false }]
1566
- }], inputTimeRef: [{
1567
- type: ContentChild,
1568
- args: ['inputTime', { static: false }]
1569
- }], inputUrlRef: [{
1570
- type: ContentChild,
1571
- args: ['inputUrl', { static: false }]
1572
- }], inputWeekRef: [{
1573
- type: ContentChild,
1574
- args: ['inputWeek', { static: false }]
1575
1920
  }], apiName: [{
1576
1921
  type: Input
1577
1922
  }], rel: [{
@@ -1580,13 +1925,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImpor
1580
1925
  type: Input
1581
1926
  }] } });
1582
1927
 
1583
- var ColumnFilterType;
1584
- (function (ColumnFilterType) {
1585
- ColumnFilterType["text"] = "text";
1586
- ColumnFilterType["numeric"] = "numeric";
1587
- ColumnFilterType["boolean"] = "boolean";
1588
- ColumnFilterType["date"] = "date";
1589
- })(ColumnFilterType || (ColumnFilterType = {}));
1590
1928
  class RESTworldListViewComponent {
1591
1929
  constructor(_clients, _confirmationService, _messageService, avatarGenerator, _router) {
1592
1930
  this._clients = _clients;
@@ -1595,33 +1933,31 @@ class RESTworldListViewComponent {
1595
1933
  this.avatarGenerator = avatarGenerator;
1596
1934
  this._router = _router;
1597
1935
  this.isLoading = false;
1598
- this.load = _.debounce(this.load2, 100);
1936
+ this.load = _.debounce(this.loadInternal, 100);
1599
1937
  this._editLink = '/edit';
1600
- this._sortField = '';
1601
- this._sortOrder = 1;
1938
+ this._lastParameters = {};
1602
1939
  this._totalRecords = 0;
1603
- this.rowsPerPage = [10, 25, 50];
1604
- this._lastEvent = {
1605
- rows: this.rowsPerPage[0]
1940
+ this.headerMenu = [];
1941
+ this.rowMenu = (row, openedByRightClick) => {
1942
+ var _a;
1943
+ return [
1944
+ {
1945
+ icon: "fas fa-edit",
1946
+ label: openedByRightClick ? "View / Edit" : undefined,
1947
+ tooltip: !openedByRightClick ? "View / Edit" : undefined,
1948
+ tooltipPosition: "left",
1949
+ routerLink: [this.editLink, this.apiName, this.rel, (_a = row._links) === null || _a === void 0 ? void 0 : _a.self[0].href]
1950
+ }, {
1951
+ icon: "fas fa-trash-alt",
1952
+ label: openedByRightClick ? "Delete" : undefined,
1953
+ tooltip: !openedByRightClick ? "Delete" : undefined,
1954
+ tooltipPosition: "left",
1955
+ styleClass: "p-button-danger",
1956
+ command: () => this.showDeleteConfirmatioModal(row)
1957
+ }
1958
+ ];
1606
1959
  };
1607
1960
  }
1608
- get PropertyType() {
1609
- return PropertyType;
1610
- }
1611
- get apiName() {
1612
- return this._apiName;
1613
- }
1614
- set apiName(value) {
1615
- this._apiName = value;
1616
- this.load(this._lastEvent);
1617
- }
1618
- get columns() {
1619
- var _a, _b;
1620
- return (_b = (_a = this.template) === null || _a === void 0 ? void 0 : _a.properties.filter(p => p.type !== PropertyType.Hidden)) !== null && _b !== void 0 ? _b : [];
1621
- }
1622
- get dateFormat() {
1623
- return RESTworldListViewComponent._dateFormat;
1624
- }
1625
1961
  get editLink() {
1626
1962
  return this._editLink;
1627
1963
  }
@@ -1629,6 +1965,14 @@ class RESTworldListViewComponent {
1629
1965
  if (value)
1630
1966
  this._editLink = value;
1631
1967
  }
1968
+ set apiName(value) {
1969
+ this._apiName = value;
1970
+ this.load(this._lastParameters);
1971
+ }
1972
+ ;
1973
+ get apiName() {
1974
+ return this._apiName;
1975
+ }
1632
1976
  get newHref() {
1633
1977
  var _a, _b;
1634
1978
  return (_b = (_a = this.resource) === null || _a === void 0 ? void 0 : _a.findLink('new')) === null || _b === void 0 ? void 0 : _b.href;
@@ -1638,27 +1982,7 @@ class RESTworldListViewComponent {
1638
1982
  }
1639
1983
  set rel(value) {
1640
1984
  this._rel = value;
1641
- this.load(this._lastEvent);
1642
- }
1643
- get rows() {
1644
- var _a;
1645
- return ((_a = this._lastEvent) === null || _a === void 0 ? void 0 : _a.rows) || 0;
1646
- }
1647
- get sortField() {
1648
- return this._sortField;
1649
- }
1650
- set sortField(value) {
1651
- this._sortField = value !== null && value !== void 0 ? value : '';
1652
- this._lastEvent.sortField = value;
1653
- this.load(this._lastEvent);
1654
- }
1655
- get sortOrder() {
1656
- return this._sortOrder;
1657
- }
1658
- set sortOrder(value) {
1659
- this._sortOrder = value !== null && value !== void 0 ? value : 1;
1660
- this._lastEvent.sortOrder = value;
1661
- this.load(this._lastEvent);
1985
+ this.load(this._lastParameters);
1662
1986
  }
1663
1987
  get template() {
1664
1988
  return this._template;
@@ -1670,9 +1994,6 @@ class RESTworldListViewComponent {
1670
1994
  var _a, _b;
1671
1995
  return ((_b = (_a = this.resource) === null || _a === void 0 ? void 0 : _a._embedded) === null || _b === void 0 ? void 0 : _b.items) || [];
1672
1996
  }
1673
- set totalRecords(value) {
1674
- this._totalRecords = value || 0;
1675
- }
1676
1997
  createNew() {
1677
1998
  return this._router.navigate([this.editLink, this.apiName, this.rel, this.newHref]);
1678
1999
  }
@@ -1682,16 +2003,15 @@ class RESTworldListViewComponent {
1682
2003
  return;
1683
2004
  yield this.getClient().delete(resource);
1684
2005
  this._messageService.add({ severity: 'success', summary: 'Deleted', detail: 'The resource has been deleted.' });
1685
- this.load(this._lastEvent);
2006
+ this.loadInternal(this._lastParameters);
1686
2007
  });
1687
2008
  }
1688
- load2(event) {
2009
+ loadInternal(parameters) {
2010
+ var _a, _b;
1689
2011
  return __awaiter(this, void 0, void 0, function* () {
1690
2012
  if (!this.apiName || !this.rel)
1691
2013
  return;
1692
2014
  this.isLoading = true;
1693
- this._lastEvent = event;
1694
- const parameters = ODataService.createParametersFromTableLoadEvent(event, this.template);
1695
2015
  const response = yield this.getClient().getList(this.rel, parameters);
1696
2016
  if (!response.ok || ProblemDetails.isProblemDetails(response.body) || !response.body) {
1697
2017
  this._messageService.add({ severity: 'error', summary: 'Error', detail: 'Error while loading the resources from the API.', data: response });
@@ -1707,7 +2027,17 @@ class RESTworldListViewComponent {
1707
2027
  this._messageService.add({ severity: 'error', summary: 'Error', detail: 'Error while loading the resources from the API. ' + e, data: e });
1708
2028
  }
1709
2029
  this.resource = response.body;
1710
- this.totalRecords = this.resource.totalPages && parameters.$top ? this.resource.totalPages * parameters.$top : undefined;
2030
+ const rowsPerPage = (_a = parameters.$top) !== null && _a !== void 0 ? _a : response.body._embedded.items.length;
2031
+ const totalPages = (_b = response.body.totalPages) !== null && _b !== void 0 ? _b : 1;
2032
+ this._totalRecords = totalPages * rowsPerPage;
2033
+ this.headerMenu = [
2034
+ {
2035
+ icon: "fas fa-plus",
2036
+ styleClass: "p-button-success",
2037
+ routerLink: [this.editLink, this.apiName, this.rel, this.newHref],
2038
+ items: this.createButtonMenu
2039
+ }
2040
+ ];
1711
2041
  }
1712
2042
  this.isLoading = false;
1713
2043
  });
@@ -1720,51 +2050,25 @@ class RESTworldListViewComponent {
1720
2050
  accept: () => this.delete(resource)
1721
2051
  });
1722
2052
  }
1723
- toColumnFilterType(propertyType) {
1724
- switch (propertyType) {
1725
- case PropertyType.Number:
1726
- return ColumnFilterType.numeric;
1727
- case PropertyType.Bool:
1728
- return ColumnFilterType.boolean;
1729
- case PropertyType.Date:
1730
- case PropertyType.DatetimeLocal:
1731
- case PropertyType.DatetimeOffset:
1732
- return ColumnFilterType.date;
1733
- default:
1734
- return ColumnFilterType.text;
1735
- }
1736
- }
1737
2053
  getClient() {
1738
2054
  if (!this.apiName)
1739
2055
  throw new Error('Cannot get a client, because the apiName is not set.');
1740
2056
  return this._clients.getClient(this.apiName);
1741
2057
  }
1742
2058
  }
1743
- RESTworldListViewComponent._dateFormat = new Date(3333, 10, 22)
1744
- .toLocaleDateString()
1745
- .replace("22", "dd")
1746
- .replace("11", "MM")
1747
- .replace("3333", "y")
1748
- .replace("33", "yy");
1749
- RESTworldListViewComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RESTworldListViewComponent, deps: [{ token: RESTworldClientCollection }, { token: i2$1.ConfirmationService }, { token: i2$1.MessageService }, { token: AvatarGenerator }, { token: i4$2.Router }], target: i0.ɵɵFactoryTarget.Component });
1750
- RESTworldListViewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.3", type: RESTworldListViewComponent, selector: "rw-list", inputs: { createButtonMenu: "createButtonMenu", rowsPerPage: "rowsPerPage", apiName: "apiName", editLink: "editLink", rel: "rel", sortField: "sortField", sortOrder: "sortOrder" }, ngImport: i0, template: "<p-table [value]=\"value\"\r\n [lazy]=\"true\"\r\n [lazyLoadOnInit]=\"false\"\r\n (onLazyLoad)=\"load($event)\"\r\n responsiveLayout=\"scroll\"\r\n [paginator]=\"true\"\r\n [rows]=\"rows\"\r\n [rowsPerPageOptions]=\"rowsPerPage\"\r\n [totalRecords]=\"totalRecords\"\r\n [loading]=\"isLoading\"\r\n [showInitialSortBadge]=\"true\"\r\n [columns]=\"columns\"\r\n [sortField]=\"sortField\"\r\n [sortOrder]=\"sortOrder\">\r\n\r\n <ng-template pTemplate=\"header\" let-columns>\r\n <tr>\r\n <th *ngFor=\"let col of columns\" [pSortableColumn]=\"col.name\">\r\n <div class=\"p-d-flex p-jc-between p-ai-center\">\r\n {{col.prompt}}\r\n <p-sortIcon [field]=\"col.name\"></p-sortIcon>\r\n <p-columnFilter [type]=\"toColumnFilterType(col.type)\" [field]=\"col.name\" display=\"menu\"></p-columnFilter>\r\n </div>\r\n </th>\r\n <th>\r\n <div class=\"flex justify-content-end\">\r\n <div class=\"mx-2\">\r\n <a *ngIf=\"!createButtonMenu\" class=\"p-button-success\" icon=\"fas fa-plus\" pButton [routerLink]=\"[editLink, apiName, rel, newHref]\" pTooltip=\"Create new\" tooltipPosition=\"left\"></a>\r\n <p-splitButton *ngIf=\"createButtonMenu\" styleClass=\"p-button-success\" icon=\"fas fa-plus\" pTooltip=\"Create new\" tooltipPosition=\"left\" (onClick)=\"createNew()\" [model]=\"createButtonMenu\" appendTo=\"body\"></p-splitButton>\r\n </div>\r\n </div>\r\n </th>\r\n </tr>\r\n </ng-template>\r\n\r\n <ng-template pTemplate=\"body\" let-entity let-columns=\"columns\">\r\n <tr>\r\n <td [ngSwitch]=\"col.type\" *ngFor=\"let col of columns\">\r\n <ng-container *ngSwitchCase=\"PropertyType.Text\">\r\n <rw-avatar *ngIf=\"col.name === 'createdBy' || col.name === 'lastChangedBy'\" [user]=\"entity[col.name]\"></rw-avatar>\r\n <span *ngIf=\"col.name !== 'createdBy' && col.name !== 'lastChangedBy'\">{{entity[col.name]}}</span>\r\n </ng-container>\r\n <span *ngSwitchCase=\"PropertyType.Number\" class=\"flex justify-content-end\">{{entity[col.name]}}</span>\r\n <span *ngSwitchCase=\"PropertyType.Bool\" class=\"flex justify-content-center\"><p-triStateCheckbox [(ngModel)]=\"entity[col.name]\" [readonly]=\"true\"></p-triStateCheckbox></span>\r\n <span *ngSwitchCase=\"PropertyType.Date\" [pTooltip]=\"entity[col.name]\">{{entity[col.name] | date:dateFormat}}</span>\r\n <span *ngSwitchCase=\"PropertyType.DatetimeLocal\" [pTooltip]=\"entity[col.name]\">{{entity[col.name] | date:dateFormat}}</span>\r\n <span *ngSwitchCase=\"PropertyType.DatetimeOffset\" [pTooltip]=\"entity[col.name]\">{{entity[col.name] | date:dateFormat}}</span>\r\n <span *ngSwitchCase=\"PropertyType.Collection\" class=\"flex justify-content-end\"><p *ngFor=\"let arrayElement of entity[col.name]\">{{arrayElement | json}}</p></span>\r\n <span *ngSwitchCase=\"PropertyType.Object\" class=\"flex justify-content-end\">{{entity[col.name] | json}}</span>\r\n </td>\r\n <td>\r\n <div class=\"flex justify-content-end\">\r\n <a pButton pTooltip=\"View/Edit\" tooltipPosition=\"left\" [routerLink]=\"[editLink, apiName, rel, entity._links?.self[0].href]\" icon=\"fas fa-edit\"></a>\r\n <button pTooltip=\"Delete\" tooltipPosition=\"left\" pButton *ngIf=\"entity._links.delete\" (click)=\"showDeleteConfirmatioModal(entity)\" icon=\"fas fa-trash-alt\" type=\"button\" class=\"mx-2 p-button-danger\"></button>\r\n </div>\r\n </td>\r\n </tr>\r\n </ng-template>\r\n\r\n <ng-template pTemplate=\"emptymessage\">\r\n <tr>\r\n <td colspan=\"8\">No entries found.</td>\r\n </tr>\r\n </ng-template>\r\n\r\n</p-table>\r\n\r\n<p-toast></p-toast>\r\n<p-confirmDialog></p-confirmDialog>\r\n", styles: [".p-tooltip{max-width:-moz-fit-content;max-width:fit-content}a.p-button{text-decoration:none}\n"], dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i4.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i4$2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i7$1.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "style", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "scrollDirection", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "responsive", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "autoLayout", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "groupRowsByOrder", "responsiveLayout", "breakpoint", "virtualRowHeight", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["selectAllChange", "selectionChange", "contextMenuSelectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i2$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i7$1.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "component", type: i7$1.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "component", type: i7$1.ColumnFilter, selector: "p-columnFilter", inputs: ["field", "type", "display", "showMenu", "matchMode", "operator", "showOperator", "showClearButton", "showApplyButton", "showMatchModes", "showAddButton", "hideOnClear", "placeholder", "matchModeOptions", "maxConstraints", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "locale", "localeMatcher", "currency", "currencyDisplay", "useGrouping", "showButtons"] }, { kind: "directive", type: i2.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "fitContent", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "directive", type: i5$1.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading"] }, { kind: "component", type: i10$1.ConfirmDialog, selector: "p-confirmDialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "visible", "position"], outputs: ["onHide"] }, { kind: "component", type: i11$1.Toast, selector: "p-toast", inputs: ["key", "autoZIndex", "baseZIndex", "style", "styleClass", "position", "preventOpenDuplicates", "preventDuplicates", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions", "breakpoints"], outputs: ["onClose"] }, { kind: "component", type: i13.TriStateCheckbox, selector: "p-triStateCheckbox", inputs: ["disabled", "name", "ariaLabelledBy", "tabindex", "inputId", "style", "styleClass", "label", "readonly", "checkboxTrueIcon", "checkboxFalseIcon"], outputs: ["onChange"] }, { kind: "component", type: i13$2.SplitButton, selector: "p-splitButton", inputs: ["model", "icon", "iconPos", "label", "style", "styleClass", "menuStyle", "menuStyleClass", "disabled", "tabindex", "appendTo", "dir", "expandAriaLabel", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onClick", "onDropdownClick"] }, { kind: "component", type: RestWorldAvatarComponent, selector: "rw-avatar", inputs: ["user"] }, { kind: "pipe", type: i4.JsonPipe, name: "json" }, { kind: "pipe", type: i4.DatePipe, name: "date" }] });
2059
+ RESTworldListViewComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RESTworldListViewComponent, deps: [{ token: RestWorldClientCollection }, { token: i2$3.ConfirmationService }, { token: i2$3.MessageService }, { token: AvatarGenerator }, { token: i3$2.Router }], target: i0.ɵɵFactoryTarget.Component });
2060
+ RESTworldListViewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.3", type: RESTworldListViewComponent, selector: "rw-list", inputs: { createButtonMenu: "createButtonMenu", editLink: "editLink", apiName: "apiName", rel: "rel" }, ngImport: i0, template: "<rw-table\r\n [api]=\"apiName\"\r\n [template]=\"template\"\r\n [rows]=\"value\"\r\n [headerMenu]=\"headerMenu\"\r\n [rowMenu]=\"rowMenu\"\r\n [totalRecords]=\"totalRecords\"\r\n [isLoading]=\"isLoading\"\r\n (onFilterOrSortChanged)=\"load($event)\">\r\n</rw-table>\r\n", styles: [".p-tooltip{max-width:-moz-fit-content;max-width:fit-content}a.p-button{text-decoration:none}\n"], dependencies: [{ kind: "component", type: RestWorldTableComponent, selector: "rw-table", inputs: ["api", "template", "rows", "rowsPerPageOptions", "headerMenu", "rowMenu", "showRowMenuAsColumn", "showRowMenuOnRightClick", "totalRecords", "styleClass", "tableStyle", "scrollable", "scrollHeight", "isLoading"], outputs: ["onFilterOrSortChanged"] }] });
1751
2061
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RESTworldListViewComponent, decorators: [{
1752
2062
  type: Component,
1753
- args: [{ selector: 'rw-list', template: "<p-table [value]=\"value\"\r\n [lazy]=\"true\"\r\n [lazyLoadOnInit]=\"false\"\r\n (onLazyLoad)=\"load($event)\"\r\n responsiveLayout=\"scroll\"\r\n [paginator]=\"true\"\r\n [rows]=\"rows\"\r\n [rowsPerPageOptions]=\"rowsPerPage\"\r\n [totalRecords]=\"totalRecords\"\r\n [loading]=\"isLoading\"\r\n [showInitialSortBadge]=\"true\"\r\n [columns]=\"columns\"\r\n [sortField]=\"sortField\"\r\n [sortOrder]=\"sortOrder\">\r\n\r\n <ng-template pTemplate=\"header\" let-columns>\r\n <tr>\r\n <th *ngFor=\"let col of columns\" [pSortableColumn]=\"col.name\">\r\n <div class=\"p-d-flex p-jc-between p-ai-center\">\r\n {{col.prompt}}\r\n <p-sortIcon [field]=\"col.name\"></p-sortIcon>\r\n <p-columnFilter [type]=\"toColumnFilterType(col.type)\" [field]=\"col.name\" display=\"menu\"></p-columnFilter>\r\n </div>\r\n </th>\r\n <th>\r\n <div class=\"flex justify-content-end\">\r\n <div class=\"mx-2\">\r\n <a *ngIf=\"!createButtonMenu\" class=\"p-button-success\" icon=\"fas fa-plus\" pButton [routerLink]=\"[editLink, apiName, rel, newHref]\" pTooltip=\"Create new\" tooltipPosition=\"left\"></a>\r\n <p-splitButton *ngIf=\"createButtonMenu\" styleClass=\"p-button-success\" icon=\"fas fa-plus\" pTooltip=\"Create new\" tooltipPosition=\"left\" (onClick)=\"createNew()\" [model]=\"createButtonMenu\" appendTo=\"body\"></p-splitButton>\r\n </div>\r\n </div>\r\n </th>\r\n </tr>\r\n </ng-template>\r\n\r\n <ng-template pTemplate=\"body\" let-entity let-columns=\"columns\">\r\n <tr>\r\n <td [ngSwitch]=\"col.type\" *ngFor=\"let col of columns\">\r\n <ng-container *ngSwitchCase=\"PropertyType.Text\">\r\n <rw-avatar *ngIf=\"col.name === 'createdBy' || col.name === 'lastChangedBy'\" [user]=\"entity[col.name]\"></rw-avatar>\r\n <span *ngIf=\"col.name !== 'createdBy' && col.name !== 'lastChangedBy'\">{{entity[col.name]}}</span>\r\n </ng-container>\r\n <span *ngSwitchCase=\"PropertyType.Number\" class=\"flex justify-content-end\">{{entity[col.name]}}</span>\r\n <span *ngSwitchCase=\"PropertyType.Bool\" class=\"flex justify-content-center\"><p-triStateCheckbox [(ngModel)]=\"entity[col.name]\" [readonly]=\"true\"></p-triStateCheckbox></span>\r\n <span *ngSwitchCase=\"PropertyType.Date\" [pTooltip]=\"entity[col.name]\">{{entity[col.name] | date:dateFormat}}</span>\r\n <span *ngSwitchCase=\"PropertyType.DatetimeLocal\" [pTooltip]=\"entity[col.name]\">{{entity[col.name] | date:dateFormat}}</span>\r\n <span *ngSwitchCase=\"PropertyType.DatetimeOffset\" [pTooltip]=\"entity[col.name]\">{{entity[col.name] | date:dateFormat}}</span>\r\n <span *ngSwitchCase=\"PropertyType.Collection\" class=\"flex justify-content-end\"><p *ngFor=\"let arrayElement of entity[col.name]\">{{arrayElement | json}}</p></span>\r\n <span *ngSwitchCase=\"PropertyType.Object\" class=\"flex justify-content-end\">{{entity[col.name] | json}}</span>\r\n </td>\r\n <td>\r\n <div class=\"flex justify-content-end\">\r\n <a pButton pTooltip=\"View/Edit\" tooltipPosition=\"left\" [routerLink]=\"[editLink, apiName, rel, entity._links?.self[0].href]\" icon=\"fas fa-edit\"></a>\r\n <button pTooltip=\"Delete\" tooltipPosition=\"left\" pButton *ngIf=\"entity._links.delete\" (click)=\"showDeleteConfirmatioModal(entity)\" icon=\"fas fa-trash-alt\" type=\"button\" class=\"mx-2 p-button-danger\"></button>\r\n </div>\r\n </td>\r\n </tr>\r\n </ng-template>\r\n\r\n <ng-template pTemplate=\"emptymessage\">\r\n <tr>\r\n <td colspan=\"8\">No entries found.</td>\r\n </tr>\r\n </ng-template>\r\n\r\n</p-table>\r\n\r\n<p-toast></p-toast>\r\n<p-confirmDialog></p-confirmDialog>\r\n", styles: [".p-tooltip{max-width:-moz-fit-content;max-width:fit-content}a.p-button{text-decoration:none}\n"] }]
1754
- }], ctorParameters: function () { return [{ type: RESTworldClientCollection }, { type: i2$1.ConfirmationService }, { type: i2$1.MessageService }, { type: AvatarGenerator }, { type: i4$2.Router }]; }, propDecorators: { createButtonMenu: [{
2063
+ args: [{ selector: 'rw-list', template: "<rw-table\r\n [api]=\"apiName\"\r\n [template]=\"template\"\r\n [rows]=\"value\"\r\n [headerMenu]=\"headerMenu\"\r\n [rowMenu]=\"rowMenu\"\r\n [totalRecords]=\"totalRecords\"\r\n [isLoading]=\"isLoading\"\r\n (onFilterOrSortChanged)=\"load($event)\">\r\n</rw-table>\r\n", styles: [".p-tooltip{max-width:-moz-fit-content;max-width:fit-content}a.p-button{text-decoration:none}\n"] }]
2064
+ }], ctorParameters: function () { return [{ type: RestWorldClientCollection }, { type: i2$3.ConfirmationService }, { type: i2$3.MessageService }, { type: AvatarGenerator }, { type: i3$2.Router }]; }, propDecorators: { createButtonMenu: [{
1755
2065
  type: Input
1756
- }], rowsPerPage: [{
2066
+ }], editLink: [{
1757
2067
  type: Input
1758
2068
  }], apiName: [{
1759
2069
  type: Input
1760
- }], editLink: [{
1761
- type: Input
1762
2070
  }], rel: [{
1763
2071
  type: Input
1764
- }], sortField: [{
1765
- type: Input
1766
- }], sortOrder: [{
1767
- type: Input
1768
2072
  }] } });
1769
2073
 
1770
2074
  function initializeSettings(settingsService) {
@@ -1775,13 +2079,25 @@ class RestworldClientModule {
1775
2079
  RestworldClientModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestworldClientModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1776
2080
  RestworldClientModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.0.3", ngImport: i0, type: RestworldClientModule, declarations: [RESTworldListViewComponent,
1777
2081
  RESTworldEditViewComponent,
1778
- RESTWorldImageViewComponent,
1779
- RESTWorldFileViewComponent,
1780
- RestworldEditFormComponent,
2082
+ RestWorldImageComponent,
2083
+ RestWorldFileComponent,
1781
2084
  RestWorldAvatarComponent,
1782
2085
  SafeUrlPipe,
1783
2086
  AsPipe,
1784
- RestWorldAvatarComponent], imports: [CommonModule,
2087
+ RestWorldAvatarComponent,
2088
+ RestWorldInputComponent,
2089
+ RestWorldLabelComponent,
2090
+ RestWorldFormElementComponent,
2091
+ RestWorldInputDropdownComponent,
2092
+ RestWorldInputCollectionComponent,
2093
+ RestWorldInputObjectComponent,
2094
+ RestWorldInputSimpleComponent,
2095
+ RestWorldValidationErrorsComponent,
2096
+ RestWorldInputTemplateComponent,
2097
+ RestWorldFormComponent,
2098
+ RestWorldTableComponent,
2099
+ RestWorldMenuButtonComponent,
2100
+ RestWorldIdNavigationComponent], imports: [CommonModule,
1785
2101
  RouterModule,
1786
2102
  FormsModule,
1787
2103
  ReactiveFormsModule,
@@ -1812,16 +2128,29 @@ RestworldClientModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", v
1812
2128
  ColorPickerModule,
1813
2129
  DragDropModule,
1814
2130
  SplitButtonModule,
1815
- AvatarModule], exports: [RESTworldListViewComponent,
2131
+ AvatarModule,
2132
+ ContextMenuModule], exports: [RESTworldListViewComponent,
1816
2133
  RESTworldEditViewComponent,
1817
- RESTWorldImageViewComponent,
1818
- RESTWorldFileViewComponent,
1819
- RestworldEditFormComponent,
2134
+ RestWorldImageComponent,
2135
+ RestWorldFileComponent,
1820
2136
  RestWorldAvatarComponent,
1821
2137
  SafeUrlPipe,
1822
- AsPipe] });
2138
+ AsPipe,
2139
+ RestWorldInputComponent,
2140
+ RestWorldLabelComponent,
2141
+ RestWorldFormElementComponent,
2142
+ RestWorldInputDropdownComponent,
2143
+ RestWorldInputCollectionComponent,
2144
+ RestWorldInputObjectComponent,
2145
+ RestWorldInputSimpleComponent,
2146
+ RestWorldValidationErrorsComponent,
2147
+ RestWorldInputTemplateComponent,
2148
+ RestWorldFormComponent,
2149
+ RestWorldTableComponent,
2150
+ RestWorldMenuButtonComponent,
2151
+ RestWorldIdNavigationComponent] });
1823
2152
  RestworldClientModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestworldClientModule, providers: [
1824
- RESTworldClientCollection,
2153
+ RestWorldClientCollection,
1825
2154
  AvatarGenerator,
1826
2155
  ConfirmationService,
1827
2156
  FormService,
@@ -1863,20 +2192,33 @@ RestworldClientModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", v
1863
2192
  ColorPickerModule,
1864
2193
  DragDropModule,
1865
2194
  SplitButtonModule,
1866
- AvatarModule] });
2195
+ AvatarModule,
2196
+ ContextMenuModule] });
1867
2197
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: RestworldClientModule, decorators: [{
1868
2198
  type: NgModule,
1869
2199
  args: [{
1870
2200
  declarations: [
1871
2201
  RESTworldListViewComponent,
1872
2202
  RESTworldEditViewComponent,
1873
- RESTWorldImageViewComponent,
1874
- RESTWorldFileViewComponent,
1875
- RestworldEditFormComponent,
2203
+ RestWorldImageComponent,
2204
+ RestWorldFileComponent,
1876
2205
  RestWorldAvatarComponent,
1877
2206
  SafeUrlPipe,
1878
2207
  AsPipe,
1879
2208
  RestWorldAvatarComponent,
2209
+ RestWorldInputComponent,
2210
+ RestWorldLabelComponent,
2211
+ RestWorldFormElementComponent,
2212
+ RestWorldInputDropdownComponent,
2213
+ RestWorldInputCollectionComponent,
2214
+ RestWorldInputObjectComponent,
2215
+ RestWorldInputSimpleComponent,
2216
+ RestWorldValidationErrorsComponent,
2217
+ RestWorldInputTemplateComponent,
2218
+ RestWorldFormComponent,
2219
+ RestWorldTableComponent,
2220
+ RestWorldMenuButtonComponent,
2221
+ RestWorldIdNavigationComponent,
1880
2222
  ],
1881
2223
  imports: [
1882
2224
  CommonModule,
@@ -1910,20 +2252,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImpor
1910
2252
  ColorPickerModule,
1911
2253
  DragDropModule,
1912
2254
  SplitButtonModule,
1913
- AvatarModule
2255
+ AvatarModule,
2256
+ ContextMenuModule,
1914
2257
  ],
1915
2258
  exports: [
1916
2259
  RESTworldListViewComponent,
1917
2260
  RESTworldEditViewComponent,
1918
- RESTWorldImageViewComponent,
1919
- RESTWorldFileViewComponent,
1920
- RestworldEditFormComponent,
2261
+ RestWorldImageComponent,
2262
+ RestWorldFileComponent,
1921
2263
  RestWorldAvatarComponent,
1922
2264
  SafeUrlPipe,
1923
- AsPipe
2265
+ AsPipe,
2266
+ RestWorldInputComponent,
2267
+ RestWorldLabelComponent,
2268
+ RestWorldFormElementComponent,
2269
+ RestWorldInputDropdownComponent,
2270
+ RestWorldInputCollectionComponent,
2271
+ RestWorldInputObjectComponent,
2272
+ RestWorldInputSimpleComponent,
2273
+ RestWorldValidationErrorsComponent,
2274
+ RestWorldInputTemplateComponent,
2275
+ RestWorldFormComponent,
2276
+ RestWorldTableComponent,
2277
+ RestWorldMenuButtonComponent,
2278
+ RestWorldIdNavigationComponent
1924
2279
  ],
1925
2280
  providers: [
1926
- RESTworldClientCollection,
2281
+ RestWorldClientCollection,
1927
2282
  AvatarGenerator,
1928
2283
  ConfirmationService,
1929
2284
  FormService,
@@ -1946,5 +2301,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImpor
1946
2301
  * Generated bundle index. Do not edit.
1947
2302
  */
1948
2303
 
1949
- export { AsPipe, AvatarGenerator, ColumnFilterType, FormService, LinkNames, ODataService, ProblemDetails, RESTWorldFileViewComponent, RESTWorldImageViewComponent, RESTworldClient, RESTworldClientCollection, RESTworldEditViewComponent, RESTworldListViewComponent, RESTworldOptions, RestWorldAvatarComponent, RestworldClientModule, RestworldEditFormComponent, SafeUrlPipe, SettingsService, initializeSettings };
2304
+ export { AsPipe, AvatarGenerator, FormService, LinkNames, ODataService, ProblemDetails, PropertyWithImage, PropertyWithOptions, RESTworldEditViewComponent, RESTworldListViewComponent, RestWorldAvatarComponent, RestWorldClient, RestWorldClientCollection, RestWorldFileComponent, RestWorldFormComponent, RestWorldFormElementComponent, RestWorldIdNavigationComponent, RestWorldImageComponent, RestWorldInputCollectionComponent, RestWorldInputComponent, RestWorldInputDropdownComponent, RestWorldInputObjectComponent, RestWorldInputSimpleComponent, RestWorldInputTemplateComponent, RestWorldLabelComponent, RestWorldMenuButtonComponent, RestWorldOptions, RestWorldTableComponent, RestWorldValidationErrorsComponent, RestworldClientModule, SafeUrlPipe, SettingsService, initializeSettings };
2305
+ //# sourceMappingURL=wertzui-ngx-restworld-client.mjs.map
1950
2306
  //# sourceMappingURL=wertzui-ngx-restworld-client.mjs.map