@wertzui/ngx-restworld-client 1.0.2 → 2.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 (31) hide show
  1. package/bundles/wertzui-ngx-restworld-client.umd.js +1101 -301
  2. package/bundles/wertzui-ngx-restworld-client.umd.js.map +1 -1
  3. package/esm2015/lib/models/problem-details.js +2 -2
  4. package/esm2015/lib/pipes/as.pipe.js +25 -0
  5. package/esm2015/lib/pipes/safe-url.pipe.js +23 -0
  6. package/esm2015/lib/restworld-client.module.js +68 -8
  7. package/esm2015/lib/services/avatar-generator.js +2 -2
  8. package/esm2015/lib/services/form.service.js +69 -0
  9. package/esm2015/lib/services/restworld-client-collection.js +1 -1
  10. package/esm2015/lib/services/restworld-client.js +46 -8
  11. package/esm2015/lib/views/restworld-edit-form/restworld-edit-form.component.js +238 -0
  12. package/esm2015/lib/views/restworld-edit-view/restworld-edit-view.component.js +209 -143
  13. package/esm2015/lib/views/restworld-file-view/restworld-file-view.component.js +63 -0
  14. package/esm2015/lib/views/restworld-image-view/restworld-image-view.component.js +107 -0
  15. package/esm2015/lib/views/restworld-list-view/restworld-list-view.component.js +64 -37
  16. package/esm2015/public-api.js +7 -1
  17. package/fesm2015/wertzui-ngx-restworld-client.js +880 -220
  18. package/fesm2015/wertzui-ngx-restworld-client.js.map +1 -1
  19. package/lib/models/problem-details.d.ts +4 -8
  20. package/lib/pipes/as.pipe.d.ts +18 -0
  21. package/lib/pipes/safe-url.pipe.d.ts +10 -0
  22. package/lib/restworld-client.module.d.ts +35 -21
  23. package/lib/services/form.service.d.ts +14 -0
  24. package/lib/services/restworld-client.d.ts +4 -1
  25. package/lib/views/restworld-edit-form/restworld-edit-form.component.d.ts +69 -0
  26. package/lib/views/restworld-edit-view/restworld-edit-view.component.d.ts +53 -32
  27. package/lib/views/restworld-file-view/restworld-file-view.component.d.ts +21 -0
  28. package/lib/views/restworld-image-view/restworld-image-view.component.d.ts +38 -0
  29. package/lib/views/restworld-list-view/restworld-list-view.component.d.ts +20 -8
  30. package/package.json +29 -8
  31. package/public-api.d.ts +6 -0
@@ -1,48 +1,66 @@
1
1
  import * as _ from 'lodash';
2
- import * as i1 from '@wertzui/ngx-hal-client';
3
- import { Resource, PagedListResource } from '@wertzui/ngx-hal-client';
2
+ import * as i1$1 from '@wertzui/ngx-hal-client';
3
+ import { Resource, PropertyType, PagedListResource, Link, FormsResource, Template } from '@wertzui/ngx-hal-client';
4
4
  import * as i0 from '@angular/core';
5
- import { Injectable, Input, Component, ContentChild, APP_INITIALIZER, NgModule } from '@angular/core';
5
+ import { Pipe, Injectable, Input, forwardRef, Component, ViewChildren, ContentChild, APP_INITIALIZER, NgModule } from '@angular/core';
6
+ import * as i1 from '@angular/platform-browser';
7
+ import * as i14 from '@angular/forms';
8
+ import { FormGroup, FormArray, FormControl, Validators, NG_VALUE_ACCESSOR, FormsModule, ReactiveFormsModule } from '@angular/forms';
6
9
  import { __awaiter } from 'tslib';
7
- import * as i1$1 from '@angular/common/http';
10
+ import * as i1$2 from '@angular/common/http';
8
11
  import { HttpHeaders, HttpClient } from '@angular/common/http';
9
- import * as i13 from '@angular/forms';
10
- import { FormGroup, FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
11
- import * as i2 from 'primeng/api';
12
+ import * as i2$1 from 'primeng/api';
12
13
  import { FilterMatchMode, ConfirmationService, MessageService } from 'primeng/api';
13
- import * as i3 from '@angular/common';
14
+ import * as i4$1 from 'primeng/dropdown';
15
+ import { DropdownModule } from 'primeng/dropdown';
16
+ import * as i5$1 from 'primeng/multiselect';
17
+ import { MultiSelectModule } from 'primeng/multiselect';
18
+ import * as i6 from 'primeng/calendar';
19
+ import { CalendarModule } from 'primeng/calendar';
20
+ import * as i7$1 from 'primeng/inputnumber';
21
+ import { InputNumberModule } from 'primeng/inputnumber';
22
+ import * as i8 from 'primeng/checkbox';
23
+ import { CheckboxModule } from 'primeng/checkbox';
24
+ import * as i9$1 from 'primeng/tristatecheckbox';
25
+ import { TriStateCheckboxModule } from 'primeng/tristatecheckbox';
26
+ import * as i2 from 'primeng/fileupload';
27
+ import { FileUpload, FileUploadModule } from 'primeng/fileupload';
28
+ import * as i1$3 from 'primeng/button';
29
+ import { ButtonModule } from 'primeng/button';
30
+ import * as i3 from 'primeng/dialog';
31
+ import { DialogModule } from 'primeng/dialog';
32
+ import * as i4 from 'ngx-image-cropper';
33
+ import { ImageCropperModule } from 'ngx-image-cropper';
34
+ import * as i5 from 'primeng/colorpicker';
35
+ import { ColorPickerModule } from 'primeng/colorpicker';
36
+ import * as i3$1 from '@angular/common';
14
37
  import { CommonModule } from '@angular/common';
15
- import * as i4 from '@angular/router';
38
+ import * as i7 from 'primeng/tooltip';
39
+ import { TooltipModule } from 'primeng/tooltip';
40
+ import * as i9 from 'primeng/inputtext';
41
+ import { InputTextModule } from 'primeng/inputtext';
42
+ import * as i10 from 'primeng/ripple';
43
+ import { RippleModule } from 'primeng/ripple';
44
+ import * as i12 from 'ngx-valdemort';
45
+ import { ValdemortModule } from 'ngx-valdemort';
46
+ import * as i17 from '@angular/cdk/drag-drop';
47
+ import { DragDropModule } from '@angular/cdk/drag-drop';
48
+ import * as i4$2 from '@angular/router';
16
49
  import { RouterModule } from '@angular/router';
17
- import * as i5 from 'primeng/tabview';
50
+ import * as i7$2 from 'primeng/tabview';
18
51
  import { TabViewModule } from 'primeng/tabview';
19
- import * as i6 from 'primeng/skeleton';
52
+ import * as i8$1 from 'primeng/skeleton';
20
53
  import { SkeletonModule } from 'primeng/skeleton';
21
- import * as i7 from 'primeng/calendar';
22
- import { CalendarModule } from 'primeng/calendar';
23
- import * as i8 from 'primeng/inputnumber';
24
- import { InputNumberModule } from 'primeng/inputnumber';
25
- import * as i9 from 'primeng/checkbox';
26
- import { CheckboxModule } from 'primeng/checkbox';
27
- import * as i10 from 'primeng/progressspinner';
54
+ import * as i10$1 from 'primeng/progressspinner';
28
55
  import { ProgressSpinnerModule } from 'primeng/progressspinner';
29
56
  import * as i11 from 'primeng/toast';
30
57
  import { ToastModule } from 'primeng/toast';
31
- import * as i12 from 'primeng/confirmdialog';
58
+ import * as i12$1 from 'primeng/confirmdialog';
32
59
  import { ConfirmDialogModule } from 'primeng/confirmdialog';
33
- import * as i14 from 'primeng/inputtext';
34
- import { InputTextModule } from 'primeng/inputtext';
35
- import * as i15 from 'primeng/button';
36
- import * as i16 from 'primeng/ripple';
37
- import { RippleModule } from 'primeng/ripple';
38
- import * as i4$1 from 'primeng/table';
60
+ import * as i4$3 from 'primeng/table';
39
61
  import { TableModule } from 'primeng/table';
40
- import * as i5$1 from 'primeng/avatar';
62
+ import * as i5$2 from 'primeng/avatar';
41
63
  import { AvatarModule } from 'primeng/avatar';
42
- import * as i6$1 from 'primeng/tristatecheckbox';
43
- import { TriStateCheckboxModule } from 'primeng/tristatecheckbox';
44
- import * as i10$1 from 'primeng/tooltip';
45
- import { TooltipModule } from 'primeng/tooltip';
46
64
  import { ScrollingModule } from '@angular/cdk/scrolling';
47
65
  import { MessagesModule } from 'primeng/messages';
48
66
  import { PanelModule } from 'primeng/panel';
@@ -62,7 +80,7 @@ class ProblemDetails extends Resource {
62
80
  return resource instanceof ProblemDetails;
63
81
  }
64
82
  static containsProblemDetailsInformation(resource) {
65
- return resource && (resource instanceof ProblemDetails || (resource instanceof Resource && resource.hasOwnProperty('status') && _.isNumber(resource.status) && resource.status >= 100 && resource.status < 600));
83
+ return resource && (resource instanceof ProblemDetails || (resource instanceof Resource && 'status' in resource && _.isNumber(resource['status']) && resource['status'] >= 100 && resource['status'] < 600));
66
84
  }
67
85
  static fromResource(resource) {
68
86
  if (!ProblemDetails.containsProblemDetailsInformation(resource))
@@ -80,9 +98,51 @@ class RESTworldOptions {
80
98
  }
81
99
  }
82
100
 
101
+ class SafeUrlPipe {
102
+ constructor(_domSanitizer) {
103
+ this._domSanitizer = _domSanitizer;
104
+ }
105
+ transform(url) {
106
+ if (_.isString(url))
107
+ throw new Error(`The given url '${url}' is not a string.`);
108
+ return this._domSanitizer.bypassSecurityTrustResourceUrl(url);
109
+ }
110
+ }
111
+ SafeUrlPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: SafeUrlPipe, deps: [{ token: i1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Pipe });
112
+ SafeUrlPipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: SafeUrlPipe, name: "safeUrl" });
113
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: SafeUrlPipe, decorators: [{
114
+ type: Pipe,
115
+ args: [{
116
+ name: 'safeUrl'
117
+ }]
118
+ }], ctorParameters: function () { return [{ type: i1.DomSanitizer }]; } });
119
+
120
+ /**
121
+ * Cast super type into type using generics
122
+ * Return Type obtained by optional @param type OR assignment type.
123
+ */
124
+ class AsPipe {
125
+ /**
126
+ * Cast (S: SuperType) into (T: Type) using @Generics.
127
+ * @param value (S: SuperType) obtained from input type.
128
+ * @optional @param type (T CastingType)
129
+ * type?: { new (): T }
130
+ * type?: new () => T
131
+ */
132
+ transform(value, type) {
133
+ return value;
134
+ }
135
+ }
136
+ AsPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: AsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
137
+ AsPipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: AsPipe, name: "as" });
138
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: AsPipe, decorators: [{
139
+ type: Pipe,
140
+ args: [{ name: 'as' }]
141
+ }] });
142
+
83
143
  class AvatarGenerator {
84
144
  constructor() {
85
- this.getImageOverride = (nameOrEmail) => '';
145
+ this.getImageOverride = () => '';
86
146
  }
87
147
  getImage(nameOrEmail) {
88
148
  let uri = AvatarGenerator._imageCache.get(nameOrEmail);
@@ -175,6 +235,71 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.11", ngImpo
175
235
  type: Input
176
236
  }] } });
177
237
 
238
+ class FormService {
239
+ createFormGroupsFromTemplates(templates) {
240
+ const tabs = Object.fromEntries(Object.entries(templates).map(([name, template]) => [
241
+ name,
242
+ this.createFormGroupFromTemplate(template)
243
+ ]));
244
+ return tabs;
245
+ }
246
+ createFormGroupFromTemplates(templates, ignoredProperties) {
247
+ const controls = Object.fromEntries(Object.entries(templates)
248
+ .filter(([key,]) => !ignoredProperties.some(p => key === p))
249
+ .map(([name, template]) => [
250
+ name,
251
+ this.createFormGroupFromTemplate(template)
252
+ ]));
253
+ const formGroup = new FormGroup(controls);
254
+ return formGroup;
255
+ }
256
+ createFormArrayFromTemplates(templates, ignoredProperties) {
257
+ const controls = Object.entries(templates)
258
+ .filter(([key,]) => !ignoredProperties.some(p => key === p))
259
+ .map(([, template]) => this.createFormGroupFromTemplate(template));
260
+ const formArray = new FormArray(controls);
261
+ return formArray;
262
+ }
263
+ createFormGroupFromTemplate(template) {
264
+ const controls = Object.fromEntries(template.properties.map(p => [
265
+ p.name,
266
+ this.createFormControl(p)
267
+ ]));
268
+ const formGroup = new FormGroup(controls);
269
+ return formGroup;
270
+ }
271
+ createFormControl(property) {
272
+ if (property.type === PropertyType.Object)
273
+ return this.createFormGroupFromTemplate(property._templates['default']);
274
+ if (property.type === PropertyType.Collection)
275
+ return this.createFormArrayFromTemplates(property._templates, ['default']);
276
+ const control = new FormControl(property.value);
277
+ if (property.max)
278
+ control.addValidators(Validators.max(property.max));
279
+ if (property.maxLength)
280
+ control.addValidators(Validators.maxLength(property.maxLength));
281
+ if (property.min)
282
+ control.addValidators(Validators.min(property.min));
283
+ if (property.minLength)
284
+ control.addValidators(Validators.minLength(property.minLength));
285
+ if (property.regex)
286
+ control.addValidators(Validators.pattern(property.regex));
287
+ if (property.required)
288
+ control.addValidators(Validators.required);
289
+ if (property.type === PropertyType.Email)
290
+ control.addValidators(Validators.email);
291
+ return control;
292
+ }
293
+ }
294
+ FormService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: FormService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
295
+ FormService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: FormService, providedIn: 'root' });
296
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: FormService, decorators: [{
297
+ type: Injectable,
298
+ args: [{
299
+ providedIn: 'root'
300
+ }]
301
+ }] });
302
+
178
303
  class RESTworldClient {
179
304
  constructor(_halClient, _options) {
180
305
  this._halClient = _halClient;
@@ -199,7 +324,7 @@ class RESTworldClient {
199
324
  }
200
325
  getHomeForced() {
201
326
  return __awaiter(this, void 0, void 0, function* () {
202
- const header = RESTworldClient.createHeaders(this._options.Version);
327
+ const header = RESTworldClient.createHeaders('application/hal+json', this._options.Version);
203
328
  const response = yield this.halClient.get(this._options.BaseUrl, Resource, ProblemDetails, header);
204
329
  return response;
205
330
  });
@@ -220,6 +345,15 @@ class RESTworldClient {
220
345
  return response;
221
346
  });
222
347
  }
348
+ getListByUri(uri, parameters, headers) {
349
+ return __awaiter(this, void 0, void 0, function* () {
350
+ const link = new Link();
351
+ link.href = uri;
352
+ const filledUri = link.fillTemplate(parameters);
353
+ const response = yield this.halClient.get(filledUri, PagedListResource, ProblemDetails, headers);
354
+ return response;
355
+ });
356
+ }
223
357
  getSingle(relOrUri, id, headers, curie) {
224
358
  return __awaiter(this, void 0, void 0, function* () {
225
359
  let uri;
@@ -249,7 +383,7 @@ class RESTworldClient {
249
383
  throw new Error(`The save link ${saveLink} does not have a save name.`);
250
384
  const uri = saveLink.href;
251
385
  const method = saveLink.name.toLowerCase();
252
- const header = RESTworldClient.createHeaders(this._options.Version);
386
+ const header = RESTworldClient.createHeaders('application/hal+json', this._options.Version);
253
387
  let response;
254
388
  switch (method) {
255
389
  case 'put':
@@ -264,13 +398,42 @@ class RESTworldClient {
264
398
  return response;
265
399
  });
266
400
  }
401
+ getAllForms(resource) {
402
+ return __awaiter(this, void 0, void 0, function* () {
403
+ const urls = resource.getFormLinkHrefs();
404
+ const header = RESTworldClient.createHeaders('application/prs.hal-forms+json', this._options.Version);
405
+ const formsPromises = urls.map(url => this._halClient.get(url, FormsResource, ProblemDetails, header));
406
+ const formsAndProblems = yield Promise.all(formsPromises);
407
+ return formsAndProblems;
408
+ });
409
+ }
410
+ submit(template, formValues) {
411
+ var _a;
412
+ return __awaiter(this, void 0, void 0, function* () {
413
+ const uri = template.target || '';
414
+ const method = (_a = template.method) === null || _a === void 0 ? void 0 : _a.toLowerCase();
415
+ const header = RESTworldClient.createHeaders('application/prs.hal-forms+json', this._options.Version);
416
+ let response;
417
+ switch (method) {
418
+ case 'put':
419
+ response = yield this.halClient.put(uri, formValues, FormsResource, ProblemDetails, header);
420
+ break;
421
+ case 'post':
422
+ response = yield this.halClient.post(uri, formValues, FormsResource, ProblemDetails, header);
423
+ break;
424
+ default:
425
+ response = yield this.halClient.get(uri, FormsResource, ProblemDetails, header);
426
+ }
427
+ return response;
428
+ });
429
+ }
267
430
  delete(resource) {
268
431
  return __awaiter(this, void 0, void 0, function* () {
269
432
  const deleteLink = resource.findLink('delete');
270
433
  if (!deleteLink)
271
434
  throw new Error(`The resource ${resource} does not have a delete link.`);
272
435
  const uri = deleteLink.href;
273
- const header = RESTworldClient.createHeaders(this._options.Version);
436
+ const header = RESTworldClient.createHeaders('application/hal+json', this._options.Version);
274
437
  const response = yield this.halClient.delete(uri, ProblemDetails, header);
275
438
  return response;
276
439
  });
@@ -282,7 +445,7 @@ class RESTworldClient {
282
445
  }
283
446
  getLinkFromHome(rel, name, curie) {
284
447
  const links = this.getLinksFromHome(rel, curie);
285
- const link = !!name ? links.find(l => l.name == name) : links[0];
448
+ const link = name ? links.find(l => l.name === name) : links[0];
286
449
  if (!link)
287
450
  throw new Error(`The home resource does not have a link with the rel '${this.getFullRel(rel, curie)}' and the name '${name}'.`);
288
451
  return link;
@@ -307,9 +470,9 @@ class RESTworldClient {
307
470
  const fullRel = `${curie}:${rel}`;
308
471
  return fullRel;
309
472
  }
310
- static createHeaders(version) {
473
+ static createHeaders(mediaType, version) {
311
474
  if (version)
312
- return new HttpHeaders({ 'Accept': `v=${version}` });
475
+ return new HttpHeaders({ 'Accept': `${mediaType || 'application/hal+json'}; v=${version}` });
313
476
  return new HttpHeaders();
314
477
  }
315
478
  }
@@ -342,14 +505,14 @@ class RESTworldClientCollection {
342
505
  return this._clients;
343
506
  }
344
507
  }
345
- RESTworldClientCollection.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: RESTworldClientCollection, deps: [{ token: i1.HalClient }], target: i0.ɵɵFactoryTarget.Injectable });
508
+ RESTworldClientCollection.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: RESTworldClientCollection, deps: [{ token: i1$1.HalClient }], target: i0.ɵɵFactoryTarget.Injectable });
346
509
  RESTworldClientCollection.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: RESTworldClientCollection, providedIn: 'root' });
347
510
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: RESTworldClientCollection, decorators: [{
348
511
  type: Injectable,
349
512
  args: [{
350
513
  providedIn: 'root'
351
514
  }]
352
- }], ctorParameters: function () { return [{ type: i1.HalClient }]; } });
515
+ }], ctorParameters: function () { return [{ type: i1$1.HalClient }]; } });
353
516
 
354
517
  class SettingsService {
355
518
  constructor(backend, _clients) {
@@ -382,31 +545,397 @@ class SettingsService {
382
545
  });
383
546
  }
384
547
  }
385
- SettingsService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: SettingsService, deps: [{ token: i1$1.HttpBackend }, { token: RESTworldClientCollection }], target: i0.ɵɵFactoryTarget.Injectable });
548
+ SettingsService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: SettingsService, deps: [{ token: i1$2.HttpBackend }, { token: RESTworldClientCollection }], target: i0.ɵɵFactoryTarget.Injectable });
386
549
  SettingsService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: SettingsService, providedIn: 'root' });
387
550
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: SettingsService, decorators: [{
388
551
  type: Injectable,
389
552
  args: [{
390
553
  providedIn: 'root'
391
554
  }]
392
- }], ctorParameters: function () { return [{ type: i1$1.HttpBackend }, { type: RESTworldClientCollection }]; } });
555
+ }], ctorParameters: function () { return [{ type: i1$2.HttpBackend }, { type: RESTworldClientCollection }]; } });
556
+
557
+ class RESTWorldImageViewComponent {
558
+ constructor() {
559
+ this.maintainAspectRatio = true;
560
+ this.aspectRatio = 1;
561
+ this.resizeToWidth = 0;
562
+ this.resizeToHeight = 0;
563
+ this.onlyScaleDown = false;
564
+ this.containWithinAspectRatio = false;
565
+ this.backgroundColor = "#ffffff";
566
+ this.format = 'png';
567
+ this.disabled = false;
568
+ this.displayCropDialog = false;
569
+ }
570
+ writeValue(obj) {
571
+ this.uri = obj;
572
+ }
573
+ registerOnChange(fn) {
574
+ this.onChange = fn;
575
+ }
576
+ registerOnTouched() {
577
+ // not needed for this component, but needed to implement the interface
578
+ }
579
+ setDisabledState(isDisabled) {
580
+ this.disabled = isDisabled;
581
+ }
582
+ showCropDialog() {
583
+ this.displayCropDialog = true;
584
+ }
585
+ imageChanged(event) {
586
+ this.tempImageFile = event.files[0];
587
+ this.showCropDialog();
588
+ }
589
+ croppedImageChanged(event) {
590
+ this.tempCroppedUri = event.base64;
591
+ }
592
+ acceptCroppedImage() {
593
+ var _a;
594
+ this.uri = this.tempCroppedUri;
595
+ (_a = this.onChange) === null || _a === void 0 ? void 0 : _a.call(this, this.uri);
596
+ this.closeCropDialog();
597
+ }
598
+ closeCropDialog() {
599
+ var _a;
600
+ (_a = this.fileUploads) === null || _a === void 0 ? void 0 : _a.forEach(f => f.clear());
601
+ this.displayCropDialog = false;
602
+ }
603
+ }
604
+ RESTWorldImageViewComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: RESTWorldImageViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
605
+ RESTWorldImageViewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.11", type: RESTWorldImageViewComponent, selector: "rw-image", inputs: { alt: "alt", accept: "accept", fileName: "fileName", maintainAspectRatio: "maintainAspectRatio", aspectRatio: "aspectRatio", resizeToWidth: "resizeToWidth", resizeToHeight: "resizeToHeight", onlyScaleDown: "onlyScaleDown", containWithinAspectRatio: "containWithinAspectRatio", backgroundColor: "backgroundColor", format: "format" }, providers: [{
606
+ provide: NG_VALUE_ACCESSOR,
607
+ useExisting: forwardRef(() => RESTWorldImageViewComponent),
608
+ multi: true
609
+ }], 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 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 || 'false'\" [customUpload]=\"true\" (uploadHandler)=\"imageChanged($event)\" pTooltip=\"Upload new image\"></p-fileUpload>\r\n <img *ngIf=\"uri\" [src]=\"uri\" [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 #cropper\r\n [imageFile]=\"tempImageFile!\"\r\n [imageURL]=\"uri!\"\r\n [maintainAspectRatio]=\"maintainAspectRatio\"\r\n [aspectRatio]=\"aspectRatio\"\r\n [resizeToWidth]=\"resizeToWidth\"\r\n [resizeToHeight]=\"resizeToHeight\"\r\n [onlyScaleDown]=\"onlyScaleDown\"\r\n [autoCrop]=\"true\"\r\n [containWithinAspectRatio]=\"containWithinAspectRatio\"\r\n [backgroundColor]=\"backgroundColor\"\r\n [format]=\"format\"\r\n (imageCropped)=\"croppedImageChanged($event)\"></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)]=\"cropper.backgroundColor\" appendTo=\"body\" class=\"ml-1 mr-1\"></p-colorPicker>\r\n <input pInputText [(ngModel)]=\"cropper.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{height:calc(1rem + 2*8px + 2*1px);cursor:zoom-in;border-radius:3px}a{text-decoration:none;height:calc(1rem + 2*8px + 2px)}a.p-button-icon-only span.p-button-label{height:1rem!important}\n"], components: [{ type: i1$3.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "style", "styleClass", "badgeClass"], outputs: ["onClick", "onFocus", "onBlur"] }, { type: i2.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", "files"], outputs: ["onBeforeUpload", "onSend", "onUpload", "onError", "onClear", "onRemove", "onSelect", "onProgress", "uploadHandler"] }, { type: i3.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"] }, { type: i4.ImageCropperComponent, selector: "image-cropper", inputs: ["format", "transform", "maintainAspectRatio", "aspectRatio", "resizeToWidth", "resizeToHeight", "cropperMinWidth", "cropperMinHeight", "cropperMaxHeight", "cropperMaxWidth", "cropperStaticWidth", "cropperStaticHeight", "canvasRotation", "initialStepSize", "roundCropper", "onlyScaleDown", "imageQuality", "autoCrop", "backgroundColor", "containWithinAspectRatio", "hideResizeSquares", "cropper", "alignImage", "disabled", "imageChangedEvent", "imageURL", "imageBase64", "imageFile"], outputs: ["imageCropped", "startCropImage", "imageLoaded", "cropperReady", "loadImageFailed"] }, { type: i5.ColorPicker, selector: "p-colorPicker", inputs: ["style", "styleClass", "inline", "format", "appendTo", "disabled", "tabindex", "inputId", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onChange", "onShow", "onHide"] }], directives: [{ type: i3$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i7.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { type: i1$3.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading"] }, { type: i14.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i14.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i14.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i9.InputText, selector: "[pInputText]" }, { type: i10.Ripple, selector: "[pRipple]" }], pipes: { "safeUrl": SafeUrlPipe } });
610
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: RESTWorldImageViewComponent, decorators: [{
611
+ type: Component,
612
+ args: [{
613
+ selector: 'rw-image',
614
+ templateUrl: './restworld-image-view.component.html',
615
+ styleUrls: ['./restworld-image-view.component.css'],
616
+ providers: [{
617
+ provide: NG_VALUE_ACCESSOR,
618
+ useExisting: forwardRef(() => RESTWorldImageViewComponent),
619
+ multi: true
620
+ }]
621
+ }]
622
+ }], propDecorators: { alt: [{
623
+ type: Input
624
+ }], accept: [{
625
+ type: Input
626
+ }], fileName: [{
627
+ type: Input
628
+ }], maintainAspectRatio: [{
629
+ type: Input
630
+ }], aspectRatio: [{
631
+ type: Input
632
+ }], resizeToWidth: [{
633
+ type: Input
634
+ }], resizeToHeight: [{
635
+ type: Input
636
+ }], onlyScaleDown: [{
637
+ type: Input
638
+ }], containWithinAspectRatio: [{
639
+ type: Input
640
+ }], backgroundColor: [{
641
+ type: Input
642
+ }], format: [{
643
+ type: Input
644
+ }], fileUploads: [{
645
+ type: ViewChildren,
646
+ args: [FileUpload]
647
+ }] } });
648
+
649
+ class RESTWorldFileViewComponent {
650
+ constructor() {
651
+ this.disabled = false;
652
+ }
653
+ writeValue(obj) {
654
+ this.uri = obj;
655
+ }
656
+ registerOnChange(fn) {
657
+ this.onChange = fn;
658
+ }
659
+ registerOnTouched() {
660
+ // not needed for this component, but needed to implement the interface
661
+ }
662
+ setDisabledState(isDisabled) {
663
+ this.disabled = isDisabled;
664
+ }
665
+ fileChanged(event) {
666
+ const file = event.files[0];
667
+ const reader = new FileReader();
668
+ reader.onload = () => {
669
+ var _a;
670
+ this.uri = reader.result;
671
+ (_a = this.onChange) === null || _a === void 0 ? void 0 : _a.call(this, this.uri);
672
+ };
673
+ reader.readAsDataURL(file);
674
+ }
675
+ }
676
+ RESTWorldFileViewComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: RESTWorldFileViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
677
+ RESTWorldFileViewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.11", type: RESTWorldFileViewComponent, selector: "rw-file", inputs: { accept: "accept", fileName: "fileName" }, providers: [{
678
+ provide: NG_VALUE_ACCESSOR,
679
+ useExisting: forwardRef(() => RESTWorldFileViewComponent),
680
+ multi: true
681
+ }], 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 || 'false'\" [customUpload]=\"true\" (uploadHandler)=\"fileChanged($event)\"></p-fileUpload>\r\n</div>\r\n", styles: ["a{text-decoration:none;height:calc(1rem + 2*8px + 2px)}a.p-button-icon-only span.p-button-label{height:1rem!important}\n"], components: [{ type: i1$3.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "style", "styleClass", "badgeClass"], outputs: ["onClick", "onFocus", "onBlur"] }, { type: i2.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", "files"], outputs: ["onBeforeUpload", "onSend", "onUpload", "onError", "onClear", "onRemove", "onSelect", "onProgress", "uploadHandler"] }], directives: [{ type: i3$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i7.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { type: i1$3.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading"] }], pipes: { "safeUrl": SafeUrlPipe } });
682
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: RESTWorldFileViewComponent, decorators: [{
683
+ type: Component,
684
+ args: [{
685
+ selector: 'rw-file',
686
+ templateUrl: './restworld-file-view.component.html',
687
+ styleUrls: ['./restworld-file-view.component.css'],
688
+ providers: [{
689
+ provide: NG_VALUE_ACCESSOR,
690
+ useExisting: forwardRef(() => RESTWorldFileViewComponent),
691
+ multi: true
692
+ }]
693
+ }]
694
+ }], propDecorators: { accept: [{
695
+ type: Input
696
+ }], fileName: [{
697
+ type: Input
698
+ }], fileUploads: [{
699
+ type: ViewChildren,
700
+ args: [FileUpload]
701
+ }] } });
702
+
703
+ class RestworldEditFormComponent {
704
+ constructor(_formService, _changeDetectorRef, _messageService, _clients) {
705
+ this._formService = _formService;
706
+ this._changeDetectorRef = _changeDetectorRef;
707
+ this._messageService = _messageService;
708
+ this._clients = _clients;
709
+ this.FormGroup = FormGroup;
710
+ this.FormArray = FormArray;
711
+ this.Number = Number;
712
+ }
713
+ get PropertyType() {
714
+ return PropertyType;
715
+ }
716
+ get dateFormat() {
717
+ return new Date(3333, 10, 22)
718
+ .toLocaleDateString()
719
+ .replace("22", "dd")
720
+ .replace("11", "mm")
721
+ .replace("3333", "yy")
722
+ .replace("33", "y");
723
+ }
724
+ ngOnInit() {
725
+ if (!this.formGroup)
726
+ throw new Error("[formGroup] is required on <rw-form>");
727
+ if (!this.template)
728
+ throw new Error("[template] is required on <rw-form>");
729
+ if (!this.apiName)
730
+ throw new Error("[apiName] is required on <rw-form>");
731
+ }
732
+ getTooltip(resource, keysToExclude) {
733
+ const tooltip = Object.entries(resource)
734
+ .filter(([key]) => !(key.startsWith('_') || ['createdAt', 'createdBy', 'lastChangedAt', 'lastChangedBy', 'timestamp'].includes(key) || (keysToExclude === null || keysToExclude === void 0 ? void 0 : keysToExclude.includes(key))))
735
+ .reduce((prev, [key, value], index) => `${prev}${index === 0 ? '' : '\n'}${key}: ${RestworldEditFormComponent.jsonStringifyWithElipsis(value)}`, '');
736
+ return tooltip;
737
+ }
738
+ static jsonStringifyWithElipsis(value) {
739
+ const maxLength = 200;
740
+ const end = 10;
741
+ const start = maxLength - end - 2;
742
+ const json = JSON.stringify(value);
743
+ const shortened = json.length > maxLength ? json.substring(0, start) + '…' + json.substring(json.length - end) : json;
744
+ return shortened;
745
+ }
746
+ getCollectionEntryTemplates(property) {
747
+ if (!property)
748
+ return [];
749
+ return Object.entries(property._templates)
750
+ .filter(([key,]) => Number.isInteger(Number.parseInt(key)))
751
+ .map(([, value]) => value);
752
+ }
753
+ addNewItemToCollection(property, formArray) {
754
+ if (!(formArray instanceof FormArray))
755
+ throw new Error('formArray is not an instance of FormArray.');
756
+ const maxIndex = Math.max(...Object.keys(property._templates)
757
+ .map(key => Number.parseInt(key))
758
+ .filter(key => Number.isSafeInteger(key)));
759
+ const nextIndex = maxIndex + 1;
760
+ const defaultTemplate = property._templates['default'];
761
+ const copiedTemplateDto = JSON.parse(JSON.stringify(defaultTemplate));
762
+ const copiedTemplate = new Template(copiedTemplateDto);
763
+ copiedTemplate.title = nextIndex.toString();
764
+ property._templates[copiedTemplate.title] = copiedTemplate;
765
+ formArray.push(this._formService.createFormGroupFromTemplate(defaultTemplate));
766
+ }
767
+ deleteItemFromCollection(property, formArray, template) {
768
+ if (!template.title)
769
+ throw new Error(`Cannot delete the item, because the template '${template}' does not have a title.`);
770
+ if (!(formArray instanceof FormArray))
771
+ throw new Error('formArray is not an instance of FormArray.');
772
+ const templates = property._templates;
773
+ delete templates[template.title];
774
+ formArray.removeAt(Number.parseInt(template.title));
775
+ }
776
+ collectionItemDropped($event) {
777
+ const formArray = $event.container.data.formArray;
778
+ const previousIndex = $event.previousIndex;
779
+ const currentIndex = $event.currentIndex;
780
+ const movementDirection = currentIndex > previousIndex ? 1 : -1;
781
+ // Move in FormArray
782
+ // We do not need to move the item in the _templates object
783
+ const movedControl = formArray.at(previousIndex);
784
+ for (let i = previousIndex; i * movementDirection < currentIndex * movementDirection; i = i + movementDirection) {
785
+ formArray.setControl(i, formArray.at(i + movementDirection));
786
+ }
787
+ formArray.setControl(currentIndex, movedControl);
788
+ this._changeDetectorRef.markForCheck();
789
+ console.log($event);
790
+ }
791
+ onOptionsFiltered(property, event) {
792
+ var _a, _b;
793
+ return __awaiter(this, void 0, void 0, function* () {
794
+ const options = property === null || property === void 0 ? void 0 : property.options;
795
+ if (!((_a = options === null || options === void 0 ? void 0 : options.link) === null || _a === void 0 ? void 0 : _a.href) || !event.filter || event.filter === '')
796
+ return;
797
+ const templatedUri = options.link.href;
798
+ let filter = `contains(${options.promptField}, '${event.filter}')`;
799
+ if (((_b = options.valueField) === null || _b === void 0 ? void 0 : _b.toLowerCase()) === 'id' && !Number.isNaN(Number.parseInt(event.filter)))
800
+ filter = `(${options.valueField} eq ${event.filter}) or (${filter})`;
801
+ const response = yield this.getClient().getListByUri(templatedUri, { $filter: filter, $top: 10 });
802
+ if (!response.ok || ProblemDetails.isProblemDetails(response.body) || !response.body) {
803
+ const message = `An error occurred while getting the filtered items.`;
804
+ this._messageService.add({ severity: 'error', summary: 'Error', detail: message, data: response });
805
+ return;
806
+ }
807
+ const items = response.body._embedded.items;
808
+ options.inline = items;
809
+ });
810
+ }
811
+ getClient() {
812
+ if (!this.apiName)
813
+ throw new Error('Cannot get a client, because the apiName is not set.');
814
+ return this._clients.getClient(this.apiName);
815
+ }
816
+ }
817
+ RestworldEditFormComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: RestworldEditFormComponent, deps: [{ token: FormService }, { token: i0.ChangeDetectorRef }, { token: i2$1.MessageService }, { token: RESTworldClientCollection }], target: i0.ɵɵFactoryTarget.Component });
818
+ RestworldEditFormComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.11", 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: "<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\">{{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\" [accept]=\"property.placeholder\"></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 : FormGroup)\" [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 : FormArray)}\" (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 : FormArray).controls[Number.parseInt(template.title!)] | as : FormGroup)\" [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}\n"], components: [{ type: i4$1.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", "virtualScroll", "itemSize", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "ariaFilterLabel", "ariaLabelledBy", "filterMatchMode", "maxlength", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "disabled", "options", "filterValue"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear"] }, { type: i5$1.MultiSelect, selector: "p-multiSelect", inputs: ["style", "styleClass", "panelStyle", "panelStyleClass", "inputId", "disabled", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "appendTo", "dataKey", "name", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "autoZIndex", "baseZIndex", "filterBy", "virtualScroll", "itemSize", "showTransitionOptions", "hideTransitionOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "scrollHeight", "defaultLabel", "placeholder", "options", "filterValue"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onPanelShow", "onPanelHide"] }, { type: i6.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", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "numberOfMonths", "view", "touchUI", "timeSeparator", "focusTrap", "firstDayOfWeek", "showTransitionOptions", "hideTransitionOptions", "tabindex", "defaultDate", "minDate", "maxDate", "disabledDates", "disabledDays", "yearRange", "showTime", "locale"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }, { type: i7$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", "disabled"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown"] }, { type: i8.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"] }, { type: i9$1.TriStateCheckbox, selector: "p-triStateCheckbox", inputs: ["disabled", "name", "ariaLabelledBy", "tabindex", "inputId", "style", "styleClass", "label", "readonly", "checkboxTrueIcon", "checkboxFalseIcon"], outputs: ["onChange"] }, { type: RESTWorldImageViewComponent, selector: "rw-image", inputs: ["alt", "accept", "fileName", "maintainAspectRatio", "aspectRatio", "resizeToWidth", "resizeToHeight", "onlyScaleDown", "containWithinAspectRatio", "backgroundColor", "format"] }, { type: RESTWorldFileViewComponent, selector: "rw-file", inputs: ["accept", "fileName"] }, { type: RestworldEditFormComponent, selector: "rw-form", inputs: ["formGroup", "template", "apiName"] }, { type: i12.ValidationErrorsComponent, selector: "val-errors", inputs: ["control", "controlName", "label"] }], directives: [{ type: i3$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i14.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i14.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i3$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i14.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i14.FormControlName, selector: "[formControlName]", inputs: ["disabled", "formControlName", "ngModel"], outputs: ["ngModelChange"] }, { type: i14.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i2$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { type: i7.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { type: i3$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i3$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { type: i14.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i3$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { type: i9.InputText, selector: "[pInputText]" }, { type: i14.RangeValueAccessor, selector: "input[type=range][formControlName],input[type=range][formControl],input[type=range][ngModel]" }, { type: i14.FormControlDirective, selector: "[formControl]", inputs: ["disabled", "formControl", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { type: i17.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "id", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListAutoScrollDisabled", "cdkDropListOrientation", "cdkDropListLockAxis", "cdkDropListData", "cdkDropListAutoScrollStep"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { type: i17.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragDisabled", "cdkDragStartDelay", "cdkDragLockAxis", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragBoundary", "cdkDragRootElement", "cdkDragPreviewContainer", "cdkDragData", "cdkDragFreeDragPosition"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { type: i17.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { type: i1$3.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading"] }, { type: i10.Ripple, selector: "[pRipple]" }, { type: i3$1.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { type: i12.ValidationErrorDirective, selector: "ng-template[valError]", inputs: ["valError"] }], pipes: { "as": AsPipe } });
819
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: RestworldEditFormComponent, decorators: [{
820
+ type: Component,
821
+ args: [{
822
+ selector: 'rw-form',
823
+ templateUrl: './restworld-edit-form.component.html',
824
+ styleUrls: ['./restworld-edit-form.component.css']
825
+ }]
826
+ }], ctorParameters: function () { return [{ type: FormService }, { type: i0.ChangeDetectorRef }, { type: i2$1.MessageService }, { type: RESTworldClientCollection }]; }, propDecorators: { formGroup: [{
827
+ type: Input
828
+ }], template: [{
829
+ type: Input
830
+ }], apiName: [{
831
+ type: Input
832
+ }], inputOptionsSingleRef: [{
833
+ type: ContentChild,
834
+ args: ['inputOptionsSingle', { static: false }]
835
+ }], inputOptionsMultipleRef: [{
836
+ type: ContentChild,
837
+ args: ['inputOptionsMultiple', { static: false }]
838
+ }], inputOptionsRef: [{
839
+ type: ContentChild,
840
+ args: ['inputOptions', { static: false }]
841
+ }], inputHiddenRef: [{
842
+ type: ContentChild,
843
+ args: ['inputHidden', { static: false }]
844
+ }], inputTextRef: [{
845
+ type: ContentChild,
846
+ args: ['inputText', { static: false }]
847
+ }], inputTextareaRef: [{
848
+ type: ContentChild,
849
+ args: ['inputTextarea', { static: false }]
850
+ }], inputSearchRef: [{
851
+ type: ContentChild,
852
+ args: ['inputSearch', { static: false }]
853
+ }], inputTelRef: [{
854
+ type: ContentChild,
855
+ args: ['inputTel', { static: false }]
856
+ }], inputUrlRef: [{
857
+ type: ContentChild,
858
+ args: ['inputUrl', { static: false }]
859
+ }], inputEmailRef: [{
860
+ type: ContentChild,
861
+ args: ['inputEmail', { static: false }]
862
+ }], inputPasswordRef: [{
863
+ type: ContentChild,
864
+ args: ['inputPassword', { static: false }]
865
+ }], inputDateRef: [{
866
+ type: ContentChild,
867
+ args: ['inputDate', { static: false }]
868
+ }], inputMonthRef: [{
869
+ type: ContentChild,
870
+ args: ['inputMonth', { static: false }]
871
+ }], inputWeekRef: [{
872
+ type: ContentChild,
873
+ args: ['inputWeek', { static: false }]
874
+ }], inputTimeRef: [{
875
+ type: ContentChild,
876
+ args: ['inputTime', { static: false }]
877
+ }], inputDatetimeLocalRef: [{
878
+ type: ContentChild,
879
+ args: ['inputDatetimeLocal', { static: false }]
880
+ }], inputNumberRef: [{
881
+ type: ContentChild,
882
+ args: ['inputNumber', { static: false }]
883
+ }], inputRangeRef: [{
884
+ type: ContentChild,
885
+ args: ['inputRange', { static: false }]
886
+ }], inputColorRef: [{
887
+ type: ContentChild,
888
+ args: ['inputColor', { static: false }]
889
+ }], inputBoolRef: [{
890
+ type: ContentChild,
891
+ args: ['inputBool', { static: false }]
892
+ }], inputDatetimeOffsetRef: [{
893
+ type: ContentChild,
894
+ args: ['inputDatetimeOffset', { static: false }]
895
+ }], inputDurationRef: [{
896
+ type: ContentChild,
897
+ args: ['inputDuration', { static: false }]
898
+ }], inputImageRef: [{
899
+ type: ContentChild,
900
+ args: ['inputImage', { static: false }]
901
+ }], inputFileRef: [{
902
+ type: ContentChild,
903
+ args: ['inputFile', { static: false }]
904
+ }], inputObjectRef: [{
905
+ type: ContentChild,
906
+ args: ['inputObject', { static: false }]
907
+ }], inputCollectionRef: [{
908
+ type: ContentChild,
909
+ args: ['inputCollection', { static: false }]
910
+ }], inputDefaultRef: [{
911
+ type: ContentChild,
912
+ args: ['inputDefault', { static: false }]
913
+ }] } });
393
914
 
394
915
  class RESTworldEditViewComponent {
395
- constructor(_clients, _confirmationService, _messageService, _location, _router) {
916
+ constructor(_clients, _confirmationService, _messageService, _location, _router, _formService, valdemortConfig) {
396
917
  this._clients = _clients;
397
918
  this._confirmationService = _confirmationService;
398
919
  this._messageService = _messageService;
399
920
  this._location = _location;
400
921
  this._router = _router;
401
- this._properties = [];
402
- this._formGroup = new FormGroup({});
922
+ this._formService = _formService;
923
+ this._templates = {};
924
+ this._formTabs = {};
403
925
  this.isLoading = false;
926
+ valdemortConfig.errorClasses = 'p-error text-sm';
927
+ }
928
+ get PropertyType() {
929
+ return PropertyType;
404
930
  }
405
- get properties() {
406
- return this._properties;
931
+ get templates() {
932
+ return this._templates;
407
933
  }
408
- get formGroup() {
409
- return this._formGroup;
934
+ get isLoadingForTheFirstTime() {
935
+ return Object.keys(this.templates).length === 0 && this.isLoading;
936
+ }
937
+ get formTabs() {
938
+ return this._formTabs;
410
939
  }
411
940
  set apiName(value) {
412
941
  this._apiName = value;
@@ -443,39 +972,68 @@ class RESTworldEditViewComponent {
443
972
  const length = (_b = (_a = this.resource) === null || _a === void 0 ? void 0 : _a._links["delete"]) === null || _b === void 0 ? void 0 : _b.length;
444
973
  return length !== undefined && length > 0;
445
974
  }
446
- get dateFormat() {
447
- return new Date(3333, 10, 22)
448
- .toLocaleDateString()
449
- .replace("22", "dd")
450
- .replace("11", "mm")
451
- .replace("3333", "yy")
452
- .replace("33", "y");
975
+ canSubmit(templateName) {
976
+ const form = this.formTabs[templateName];
977
+ return form && form.valid;
978
+ }
979
+ getTooltip(resource, keysToExclude) {
980
+ const tooltip = Object.entries(resource)
981
+ .filter(([key]) => !(key.startsWith('_') || ['createdAt', 'createdBy', 'lastChangedAt', 'lastChangedBy', 'timestamp'].includes(key) || (keysToExclude === null || keysToExclude === void 0 ? void 0 : keysToExclude.includes(key))))
982
+ .reduce((prev, [key, value], index) => `${prev}${index === 0 ? '' : '\n'}${key}: ${RESTworldEditViewComponent.jsonStringifyWithElipsis(value)}`, '');
983
+ return tooltip;
984
+ }
985
+ static jsonStringifyWithElipsis(value) {
986
+ const maxLength = 200;
987
+ const end = 10;
988
+ const start = maxLength - end - 2;
989
+ const json = JSON.stringify(value);
990
+ const shortened = json.length > maxLength ? json.substring(0, start) + '…' + json.substring(json.length - end) : json;
991
+ return shortened;
453
992
  }
454
993
  getClient() {
455
994
  if (!this.apiName)
456
995
  throw new Error('Cannot get a client, because the apiName is not set.');
457
996
  return this._clients.getClient(this.apiName);
458
997
  }
459
- save() {
998
+ submit(templateName, template, formValue) {
460
999
  return __awaiter(this, void 0, void 0, function* () {
461
- if (!this.apiName || !this.uri || !this.resource)
462
- return;
463
- Object.assign(this.resource, this.formGroup.value);
464
- const selfHrefBeforeSave = this.resource._links.self[0].href;
465
1000
  this.isLoading = true;
466
- const response = yield this.getClient().save(this.resource);
467
- this.isLoading = false;
468
- if (!response.ok || ProblemDetails.isProblemDetails(response.body)) {
469
- const message = response.status === 409 /* Conflict */ ? 'Someone else modified the resource. Try reloading it and apply your changes again.' : 'Error while saving the resource.';
470
- this._messageService.add({ severity: 'error', summary: 'Error', detail: message, data: response });
471
- }
472
- else {
473
- const selfHrefAfterSave = this.resource._links.self[0].href;
474
- setTimeout(() => this._messageService.add({ severity: 'success', summary: 'Saved', detail: 'The resource has been saved.' }), 100);
475
- if (selfHrefBeforeSave !== selfHrefAfterSave) {
476
- this._router.navigate(['/edit', this.apiName, selfHrefAfterSave]);
1001
+ try {
1002
+ const targetBeforeSave = template.target;
1003
+ const response = yield this.getClient().submit(template, formValue);
1004
+ if (!response.ok) {
1005
+ let summary = 'Error';
1006
+ let detail = 'Error while saving the resource.';
1007
+ if (ProblemDetails.isProblemDetails(response.body)) {
1008
+ const problemDetails = response.body;
1009
+ summary = problemDetails.title || summary;
1010
+ detail = problemDetails.detail || detail;
1011
+ // display validation errors
1012
+ if (problemDetails['errors']) {
1013
+ const form = this.formTabs[templateName];
1014
+ for (const [key, errorsForKey] of Object.entries(problemDetails['errors'])) {
1015
+ const path = key.split(/\.|\[/).map(e => e.replace("]", ""));
1016
+ const formControl = path.reduce((control, pathElement) => (control instanceof FormGroup ? control.controls[pathElement] : control) || control, form);
1017
+ formControl.setErrors({ remote: errorsForKey });
1018
+ }
1019
+ }
1020
+ }
1021
+ this._messageService.add({ severity: 'error', summary: summary, detail: detail, data: response, life: 10000 });
1022
+ }
1023
+ else {
1024
+ const responseResource = response.body;
1025
+ const targetAfterSave = responseResource._templates[templateName].target;
1026
+ setTimeout(() => this._messageService.add({ severity: 'success', summary: 'Saved', detail: 'The resource has been saved.' }), 100);
1027
+ if (targetBeforeSave !== targetAfterSave) {
1028
+ this._router.navigate(['/edit', this.apiName, responseResource._links.self[0].href]);
1029
+ }
477
1030
  }
478
1031
  }
1032
+ catch (e) {
1033
+ this._messageService.add({ severity: 'error', summary: 'Error', detail: `An unknown error occurred. ${JSON.stringify(e)}`, life: 10000 });
1034
+ console.log(e);
1035
+ }
1036
+ this.isLoading = false;
479
1037
  });
480
1038
  }
481
1039
  showDeleteConfirmatioModal() {
@@ -490,7 +1048,7 @@ class RESTworldEditViewComponent {
490
1048
  return __awaiter(this, void 0, void 0, function* () {
491
1049
  if (!this.apiName || !this.uri || !this.resource)
492
1050
  return;
493
- Object.assign(this.resource, this.formGroup.value);
1051
+ Object.assign(this.resource, this.formTabs.value);
494
1052
  yield this.getClient().delete(this.resource);
495
1053
  setTimeout(() => this._messageService.add({ severity: 'success', summary: 'Deleted', detail: 'The resource has been deleted.' }), 100);
496
1054
  this._location.back();
@@ -507,136 +1065,173 @@ class RESTworldEditViewComponent {
507
1065
  }
508
1066
  else {
509
1067
  this._resource = response.body;
510
- this._properties = RESTworldEditViewComponent.createProperyInfos(this._resource);
511
- this._formGroup = RESTworldEditViewComponent.createFormGroup(this._properties);
1068
+ this._templates = yield this.getAllTemplates(this._resource);
1069
+ this._formTabs = this._formService.createFormGroupsFromTemplates(this._templates);
512
1070
  }
513
1071
  this.isLoading = false;
514
1072
  });
515
1073
  }
516
- static createFormGroup(properties) {
517
- const controls = Object.fromEntries(properties.map(p => [
518
- p.field,
519
- p.type === 'object' && p.children ? RESTworldEditViewComponent.createFormGroup(p.children) : new FormControl(p.value)
520
- ]));
521
- const formGroup = new FormGroup(controls);
522
- return formGroup;
1074
+ setInitialSelectedOptionsElementsForTemplates(templates) {
1075
+ return __awaiter(this, void 0, void 0, function* () {
1076
+ return Promise.all(Object.values(templates)
1077
+ .map(template => this.setInitialSelectedOptionsElementsForTemplate(template)));
1078
+ });
523
1079
  }
524
- static createProperyInfos(resource) {
525
- if (!resource)
526
- return [];
527
- // Get all distinct properties from all rows
528
- // We look at all rows to eliminate possible undefined values
529
- const properties = Object.entries(resource)
530
- .filter(p => p[0] !== '_links' &&
531
- p[0] !== '_embedded' &&
532
- p[0] !== 'id' &&
533
- p[0] !== 'timestamp');
534
- // Check if the rows are entities with change tracking
535
- const withoutChangeTrackingProperties = properties.filter(p => p[0] !== 'createdAt' &&
536
- p[0] !== 'createdBy' &&
537
- p[0] !== 'lastChangedAt' &&
538
- p[0] !== 'lastChangedBy');
539
- const hasChangeTrackingProperties = withoutChangeTrackingProperties.length < properties.length;
540
- // First the id, then all other properties
541
- const sortedProperties = [];
542
- if (Object.hasOwnProperty('id'))
543
- sortedProperties.push(['id', resource['id']]);
544
- sortedProperties.push(...withoutChangeTrackingProperties);
545
- // And change tracking properties at the end
546
- if (hasChangeTrackingProperties) {
547
- sortedProperties.push(['createdAt', resource['createdAt']]);
548
- sortedProperties.push(['createdBy', resource['createdBy']]);
549
- sortedProperties.push(['lastChangedAt', resource['lastChangedAt']]);
550
- sortedProperties.push(['lastChangedBy', resource['lastChangedBy']]);
551
- }
552
- const propertyDescriptions = sortedProperties
553
- .map(p => ({
554
- field: p[0],
555
- value: p[1],
556
- label: RESTworldEditViewComponent.toTitleCase(p[0]),
557
- type: RESTworldEditViewComponent.getColumnType(p[0], p[1]),
558
- isReadOnly: RESTworldEditViewComponent.getIsReadOnly(p[0])
559
- }));
560
- for (var description of propertyDescriptions) {
561
- if (description.type === 'object') {
562
- const children = RESTworldEditViewComponent.createProperyInfos(description.value);
563
- children.forEach(d => description.field + '.' + d.field);
564
- description.children = children;
565
- }
566
- }
567
- return propertyDescriptions;
1080
+ imageChanged(formControl, event) {
1081
+ const file = event.files[0];
1082
+ console.log(file);
1083
+ const reader = new FileReader();
1084
+ reader.onload = () => {
1085
+ const uri = reader.result;
1086
+ console.log(uri);
1087
+ formControl.setValue(uri);
1088
+ };
1089
+ reader.readAsDataURL(file);
568
1090
  }
569
- static getIsReadOnly(field) {
570
- return field === 'id' || field === 'createdAt' || field === 'createdBy' || field === 'lastChangedAt' || field === 'lastChangedBy';
1091
+ setInitialSelectedOptionsElementsForTemplate(template) {
1092
+ return __awaiter(this, void 0, void 0, function* () {
1093
+ return Promise.all(template.properties
1094
+ .filter(property => { var _a, _b; return (_b = (_a = property === null || property === void 0 ? void 0 : property.options) === null || _a === void 0 ? void 0 : _a.link) === null || _b === void 0 ? void 0 : _b.href; })
1095
+ .map(property => this.setInitialSelectedOptionsElementForProperty(property)));
1096
+ });
571
1097
  }
572
- static getColumnType(field, value) {
573
- if (value === null || value === undefined)
574
- return 'text';
575
- if (_.isNumber(value))
576
- return 'numeric';
577
- if (_.isDate(value))
578
- return 'date';
579
- if (_.isString(value)) {
580
- return 'text';
581
- }
582
- if (_.isBoolean(value))
583
- return 'boolean';
584
- if (_.isObject(value))
585
- return 'object';
586
- if (_.isArray(value))
587
- return 'array';
588
- return 'text';
1098
+ setInitialSelectedOptionsElementForProperty(property) {
1099
+ var _a;
1100
+ return __awaiter(this, void 0, void 0, function* () {
1101
+ const options = property === null || property === void 0 ? void 0 : property.options;
1102
+ if (!((_a = options === null || options === void 0 ? void 0 : options.link) === null || _a === void 0 ? void 0 : _a.href))
1103
+ return;
1104
+ const templatedUri = options.link.href;
1105
+ const filter = `${options.valueField} eq ${property.value}`;
1106
+ const response = yield this.getClient().getListByUri(templatedUri, { $filter: filter, $top: 10 });
1107
+ if (!response.ok || ProblemDetails.isProblemDetails(response.body) || !response.body) {
1108
+ const message = `An error occurred while getting the filtered items.`;
1109
+ this._messageService.add({ severity: 'error', summary: 'Error', detail: message, data: response });
1110
+ return;
1111
+ }
1112
+ const items = response.body._embedded.items;
1113
+ options.inline = items;
1114
+ });
589
1115
  }
590
- static toTitleCase(anyCase) {
591
- return anyCase
592
- .replace(/(_)+/g, ' ') // underscore to whitespace
593
- .replace(/([a-z])([A-Z][a-z])/g, "$1 $2") // insert space before each new word if there is none
594
- .replace(/([A-Z][a-z])([A-Z])/g, "$1 $2") // insert space after each word if there is none
595
- .replace(/([a-z])([A-Z]+[a-z])/g, "$1 $2") // insert space after single letter word if there is none
596
- .replace(/([A-Z]+)([A-Z][a-z][a-z])/g, "$1 $2") // insert space before single letter word if there is none
597
- .replace(/([a-z]+)([A-Z0-9]+)/g, "$1 $2") // insert space after numbers
598
- .replace(/^./, (match) => match.toUpperCase()); // change first letter to be upper case
1116
+ getAllTemplates(resource) {
1117
+ return __awaiter(this, void 0, void 0, function* () {
1118
+ const formResponses = yield this.getClient().getAllForms(resource);
1119
+ const failedResponses = formResponses.filter(response => !response.ok || ProblemDetails.isProblemDetails(response.body) || !response.body);
1120
+ if (failedResponses.length !== 0) {
1121
+ for (const response of failedResponses) {
1122
+ this._messageService.add({ severity: 'error', summary: 'Error', detail: 'Error while loading the resource from the API.', data: response });
1123
+ }
1124
+ return Promise.resolve({});
1125
+ }
1126
+ const formTemplates = Object.assign({}, ...formResponses.map(response => response.body._templates));
1127
+ yield this.setInitialSelectedOptionsElementsForTemplates(formTemplates);
1128
+ return formTemplates;
1129
+ });
599
1130
  }
600
1131
  }
601
- RESTworldEditViewComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: RESTworldEditViewComponent, deps: [{ token: RESTworldClientCollection }, { token: i2.ConfirmationService }, { token: i2.MessageService }, { token: i3.Location }, { token: i4.Router }], target: i0.ɵɵFactoryTarget.Component });
602
- RESTworldEditViewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.11", type: RESTworldEditViewComponent, selector: "restworld-edit-view", inputs: { apiName: "apiName", uri: "uri" }, queries: [{ propertyName: "visualTabRef", first: true, predicate: ["visualTab"], descendants: true }, { propertyName: "formRef", first: true, predicate: ["form"], descendants: true }, { propertyName: "formRowRef", first: true, predicate: ["formRow"], descendants: true }, { propertyName: "formLabelRef", first: true, predicate: ["formLabel"], descendants: true }, { propertyName: "formInputRef", first: true, predicate: ["formInput"], descendants: true }, { propertyName: "visualTabAdditionalRef", first: true, predicate: ["visualTabAdditional"], descendants: true }, { propertyName: "rawTabRef", first: true, predicate: ["rawTab"], descendants: true }, { propertyName: "buttonsRef", first: true, predicate: ["buttonsRef"], descendants: true }], ngImport: i0, template: "<div class=\"grid\">\r\n <div class=\"col\">\r\n <h1>Edit resource</h1>\r\n </div>\r\n</div>\r\n\r\n<form [formGroup]=\"formGroup\" (ngSubmit)=\"save()\">\r\n <p-tabView>\r\n <p-tabPanel header=\"Visual\" [disabled]=\"!resource || isLoading\">\r\n <ng-template #defaultVisualTab>\r\n <ng-container *ngIf=\"!resource && isLoading\">\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 </ng-container>\r\n\r\n <div *ngIf=\"resource\" class=\"blockable-container\">\r\n <div class=\"blockable-element\">\r\n <ng-template #defaultForm let-properties=\"properties\" let-formGroup=\"formGroup\">\r\n <div [formGroup]=\"formGroup\">\r\n <div *ngFor=\"let property of properties\" class=\"grid field\">\r\n <ng-template #defaultFormRow>\r\n <ng-template #defaultFormLabel>\r\n <label [attr.for]=\"property.field\" class=\"col-12 mb-2 md:col-2 md:mb-0\" [class.p-disabled]=\"property.isReadOnly\" [class.hasChildren]=\"property.children?.length > 0\">{{property.label}}</label>\r\n </ng-template>\r\n <ng-container *ngTemplateOutlet=\"formLabelRef || defaultFormLabel; context:{ $implicit: property }\"></ng-container>\r\n <ng-template #defaultFormInput let-property let-formGroup=\"formGroup\">\r\n <div [ngSwitch]=\"property.type\" class=\"col-12 md:col-10\">\r\n <input *ngSwitchCase=\"'text'\" [formControlName]=\"property.field\" [id]=\"property.field\" type=\"text\" pInputText class=\"w-full\" [class.p-disabled]=\"property.isReadOnly\">\r\n <p-calendar *ngSwitchCase=\"'date'\" [formControlName]=\"property.field\" [id]=\"property.field\" [dateFormat]=\"dateFormat\" [showTime]=\"true\" [showIcon]=\"true\" styleClass=\"w-full\" [class.p-disabled]=\"property.isReadOnly\"></p-calendar>\r\n <p-inputNumber *ngSwitchCase=\"'numeric'\" [formControlName]=\"property.field\" [id]=\"property.field\" mode=\"decimal\" [showButtons]=\"!property.isReadOnly\" class=\"w-full\" styleClass=\"w-full\" [class.p-disabled]=\"property.isReadOnly\"></p-inputNumber>\r\n <p-checkbox *ngSwitchCase=\"'boolean'\" [formControl]=\"formGroup.controls[property.field]\" [id]=\"property.field\" [readonly]=\"property.isReadOnly\"></p-checkbox>\r\n <div *ngSwitchCase=\"'object'\">\r\n <ng-container *ngTemplateOutlet=\"formRef || defaultForm; context:{ properties: property.children, formGroup: formGroup.controls[property.field] }\"></ng-container>\r\n </div>\r\n </div>\r\n </ng-template>\r\n <ng-container *ngTemplateOutlet=\"formInputRef || defaultFormInput; context:{ $implicit: property, formGroup: formGroup }\"></ng-container>\r\n </ng-template>\r\n <ng-container *ngTemplateOutlet=\"formRowRef || defaultFormRow; context:{ $implicit: property }\"></ng-container>\r\n </div>\r\n </div>\r\n </ng-template>\r\n <ng-container *ngTemplateOutlet=\"formRef || defaultForm; context: { properties: properties, formGroup: formGroup }\"></ng-container>\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 </ng-template>\r\n <ng-container *ngTemplateOutlet=\"visualTabRef || defaultVisualTab\"></ng-container>\r\n <ng-container *ngTemplateOutlet=\"visualTabAdditionalRef || null; context:{ $implicit: resource, properties: properties, isLoading: isLoading }\"></ng-container>\r\n </p-tabPanel>\r\n\r\n <p-tabPanel header=\"Raw\" [disabled]=\"!resource || isLoading\">\r\n <ng-template #defaultRawTab>\r\n <pre>{{resource | json}}</pre>\r\n </ng-template>\r\n <ng-container *ngTemplateOutlet=\"rawTabRef || defaultRawTab\"></ng-container>\r\n </p-tabPanel>\r\n </p-tabView>\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]=\"!resource || isLoading || !canSave\"></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=\"mx-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\r\n</form>\r\n\r\n<p-toast></p-toast>\r\n<p-confirmDialog></p-confirmDialog>\r\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}.field.grid>label.hasChildren{border-right:1px solid rgba(0,0,0,.1)}\n"], components: [{ type: i5.TabView, selector: "p-tabView", inputs: ["orientation", "style", "styleClass", "controlClose", "scrollable", "activeIndex"], outputs: ["onChange", "onClose", "activeIndexChange"] }, { type: i5.TabPanel, selector: "p-tabPanel", inputs: ["closable", "headerStyle", "headerStyleClass", "cache", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "selected", "disabled", "header", "leftIcon", "rightIcon"] }, { type: i6.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "style", "shape", "animation", "borderRadius", "size", "width", "height"] }, { type: i7.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", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "numberOfMonths", "view", "touchUI", "timeSeparator", "focusTrap", "firstDayOfWeek", "showTransitionOptions", "hideTransitionOptions", "tabindex", "defaultDate", "minDate", "maxDate", "disabledDates", "disabledDays", "yearRange", "showTime", "locale"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }, { type: i8.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", "disabled"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown"] }, { type: i9.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"] }, { type: i10.ProgressSpinner, selector: "p-progressSpinner", inputs: ["style", "styleClass", "strokeWidth", "fill", "animationDuration"] }, { type: i11.Toast, selector: "p-toast", inputs: ["key", "autoZIndex", "baseZIndex", "style", "styleClass", "position", "preventOpenDuplicates", "preventDuplicates", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions", "breakpoints"], outputs: ["onClose"] }, { type: i12.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"] }], directives: [{ type: i13.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i13.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i13.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i3.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { type: i3.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { type: i13.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i14.InputText, selector: "[pInputText]" }, { type: i13.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i13.FormControlName, selector: "[formControlName]", inputs: ["disabled", "formControlName", "ngModel"], outputs: ["ngModelChange"] }, { type: i13.FormControlDirective, selector: "[formControl]", inputs: ["disabled", "formControl", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { type: i15.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading"] }, { type: i16.Ripple, selector: "[pRipple]" }], pipes: { "json": i3.JsonPipe } });
1132
+ RESTworldEditViewComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: RESTworldEditViewComponent, deps: [{ token: RESTworldClientCollection }, { token: i2$1.ConfirmationService }, { token: i2$1.MessageService }, { token: i3$1.Location }, { token: i4$2.Router }, { token: FormService }, { token: i12.ValdemortConfig }], target: i0.ɵɵFactoryTarget.Component });
1133
+ RESTworldEditViewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.11", type: RESTworldEditViewComponent, selector: "rw-edit", inputs: { apiName: "apiName", uri: "uri" }, queries: [{ propertyName: "extraTabsRef", first: true, predicate: ["extraTabs"], descendants: true }, { propertyName: "buttonsRef", first: true, predicate: ["buttons"], descendants: true }, { 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: "inputDefaultRef", first: true, predicate: ["inputDefault"], descendants: true }], ngImport: i0, template: "<div class=\"grid\">\r\n <div class=\"col\">\r\n <h1>Edit resource</h1>\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:-webkit-fit-content!important;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"], components: [{ type: i7$2.TabView, selector: "p-tabView", inputs: ["orientation", "style", "styleClass", "controlClose", "scrollable", "activeIndex"], outputs: ["onChange", "onClose", "activeIndexChange"] }, { type: i7$2.TabPanel, selector: "p-tabPanel", inputs: ["closable", "headerStyle", "headerStyleClass", "cache", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "selected", "disabled", "header", "leftIcon", "rightIcon"] }, { type: i8$1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "style", "shape", "animation", "borderRadius", "size", "width", "height"] }, { type: RestworldEditFormComponent, selector: "rw-form", inputs: ["formGroup", "template", "apiName"] }, { type: i10$1.ProgressSpinner, selector: "p-progressSpinner", inputs: ["style", "styleClass", "strokeWidth", "fill", "animationDuration"] }, { type: i11.Toast, selector: "p-toast", inputs: ["key", "autoZIndex", "baseZIndex", "style", "styleClass", "position", "preventOpenDuplicates", "preventDuplicates", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions", "breakpoints"], outputs: ["onClose"] }, { type: i12$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"] }], directives: [{ type: i3$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i14.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i14.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i14.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i1$3.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading"] }, { type: i10.Ripple, selector: "[pRipple]" }, { type: i3$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "keyvalue": i3$1.KeyValuePipe } });
603
1134
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: RESTworldEditViewComponent, decorators: [{
604
1135
  type: Component,
605
1136
  args: [{
606
- selector: 'restworld-edit-view',
1137
+ selector: 'rw-edit',
607
1138
  templateUrl: './restworld-edit-view.component.html',
608
1139
  styleUrls: ['./restworld-edit-view.component.css']
609
1140
  }]
610
- }], ctorParameters: function () { return [{ type: RESTworldClientCollection }, { type: i2.ConfirmationService }, { type: i2.MessageService }, { type: i3.Location }, { type: i4.Router }]; }, propDecorators: { apiName: [{
1141
+ }], ctorParameters: function () { return [{ type: RESTworldClientCollection }, { type: i2$1.ConfirmationService }, { type: i2$1.MessageService }, { type: i3$1.Location }, { type: i4$2.Router }, { type: FormService }, { type: i12.ValdemortConfig }]; }, propDecorators: { apiName: [{
611
1142
  type: Input
612
1143
  }], uri: [{
613
1144
  type: Input
614
- }], visualTabRef: [{
1145
+ }], extraTabsRef: [{
615
1146
  type: ContentChild,
616
- args: ['visualTab', { static: false }]
617
- }], formRef: [{
1147
+ args: ['extraTabs', { static: false }]
1148
+ }], buttonsRef: [{
618
1149
  type: ContentChild,
619
- args: ['form', { static: false }]
620
- }], formRowRef: [{
1150
+ args: ['buttons', { static: false }]
1151
+ }], inputOptionsSingleRef: [{
621
1152
  type: ContentChild,
622
- args: ['formRow', { static: false }]
623
- }], formLabelRef: [{
1153
+ args: ['inputOptionsSingle', { static: false }]
1154
+ }], inputOptionsMultipleRef: [{
624
1155
  type: ContentChild,
625
- args: ['formLabel', { static: false }]
626
- }], formInputRef: [{
1156
+ args: ['inputOptionsMultiple', { static: false }]
1157
+ }], inputOptionsRef: [{
627
1158
  type: ContentChild,
628
- args: ['formInput', { static: false }]
629
- }], visualTabAdditionalRef: [{
1159
+ args: ['inputOptions', { static: false }]
1160
+ }], inputHiddenRef: [{
630
1161
  type: ContentChild,
631
- args: ['visualTabAdditional', { static: false }]
632
- }], rawTabRef: [{
1162
+ args: ['inputHidden', { static: false }]
1163
+ }], inputTextRef: [{
633
1164
  type: ContentChild,
634
- args: ['rawTab', { static: false }]
635
- }], buttonsRef: [{
1165
+ args: ['inputText', { static: false }]
1166
+ }], inputTextareaRef: [{
1167
+ type: ContentChild,
1168
+ args: ['inputTextarea', { static: false }]
1169
+ }], inputSearchRef: [{
1170
+ type: ContentChild,
1171
+ args: ['inputSearch', { static: false }]
1172
+ }], inputTelRef: [{
1173
+ type: ContentChild,
1174
+ args: ['inputTel', { static: false }]
1175
+ }], inputUrlRef: [{
1176
+ type: ContentChild,
1177
+ args: ['inputUrl', { static: false }]
1178
+ }], inputEmailRef: [{
1179
+ type: ContentChild,
1180
+ args: ['inputEmail', { static: false }]
1181
+ }], inputPasswordRef: [{
1182
+ type: ContentChild,
1183
+ args: ['inputPassword', { static: false }]
1184
+ }], inputDateRef: [{
1185
+ type: ContentChild,
1186
+ args: ['inputDate', { static: false }]
1187
+ }], inputMonthRef: [{
1188
+ type: ContentChild,
1189
+ args: ['inputMonth', { static: false }]
1190
+ }], inputWeekRef: [{
1191
+ type: ContentChild,
1192
+ args: ['inputWeek', { static: false }]
1193
+ }], inputTimeRef: [{
1194
+ type: ContentChild,
1195
+ args: ['inputTime', { static: false }]
1196
+ }], inputDatetimeLocalRef: [{
1197
+ type: ContentChild,
1198
+ args: ['inputDatetimeLocal', { static: false }]
1199
+ }], inputNumberRef: [{
1200
+ type: ContentChild,
1201
+ args: ['inputNumber', { static: false }]
1202
+ }], inputRangeRef: [{
1203
+ type: ContentChild,
1204
+ args: ['inputRange', { static: false }]
1205
+ }], inputColorRef: [{
1206
+ type: ContentChild,
1207
+ args: ['inputColor', { static: false }]
1208
+ }], inputBoolRef: [{
1209
+ type: ContentChild,
1210
+ args: ['inputBool', { static: false }]
1211
+ }], inputDatetimeOffsetRef: [{
636
1212
  type: ContentChild,
637
- args: ['buttonsRef', { static: false }]
1213
+ args: ['inputDatetimeOffset', { static: false }]
1214
+ }], inputDurationRef: [{
1215
+ type: ContentChild,
1216
+ args: ['inputDuration', { static: false }]
1217
+ }], inputImageRef: [{
1218
+ type: ContentChild,
1219
+ args: ['inputImage', { static: false }]
1220
+ }], inputFileRef: [{
1221
+ type: ContentChild,
1222
+ args: ['inputFile', { static: false }]
1223
+ }], inputDefaultRef: [{
1224
+ type: ContentChild,
1225
+ args: ['inputDefault', { static: false }]
638
1226
  }] } });
639
1227
 
1228
+ var ColumnType;
1229
+ (function (ColumnType) {
1230
+ ColumnType["text"] = "text";
1231
+ ColumnType["numeric"] = "numeric";
1232
+ ColumnType["boolean"] = "boolean";
1233
+ ColumnType["date"] = "date";
1234
+ })(ColumnType || (ColumnType = {}));
640
1235
  class RESTworldListViewComponent {
641
1236
  constructor(_clients, _confirmationService, _messageService, avatarGenerator) {
642
1237
  this._clients = _clients;
@@ -713,12 +1308,12 @@ class RESTworldListViewComponent {
713
1308
  return;
714
1309
  this.isLoading = true;
715
1310
  this._lastEvent = event;
716
- const parameters = RESTworldListViewComponent.createParametersFromEvent(event);
1311
+ const parameters = this.createParametersFromEvent(event);
717
1312
  const response = yield this.getClient().getList(this.rel, parameters);
718
1313
  if (!response.ok || ProblemDetails.isProblemDetails(response.body) || !response.body) {
719
1314
  this._messageService.add({ severity: 'error', summary: 'Error', detail: 'Error while loading the resources from the API.', data: response });
720
1315
  }
721
- else {
1316
+ else if (response.body) {
722
1317
  this.resource = response.body;
723
1318
  this.totalRecords = this.resource.totalPages && parameters.$top ? this.resource.totalPages * parameters.$top : undefined;
724
1319
  this._columns = this.createColumns();
@@ -745,7 +1340,7 @@ class RESTworldListViewComponent {
745
1340
  }
746
1341
  createColumns() {
747
1342
  if (this.value.length === 0)
748
- return [];
1343
+ return this.columns;
749
1344
  // Get all distinct properties from all rows
750
1345
  // We look at all rows to eliminate possible undefined values
751
1346
  const rowsWithProperties = this.value
@@ -754,9 +1349,9 @@ class RESTworldListViewComponent {
754
1349
  p[0] !== '_embedded' &&
755
1350
  p[0] !== 'id' &&
756
1351
  p[0] !== 'timestamp'));
757
- let distinctProperties = rowsWithProperties[0];
758
- for (let propertiesOfRow of rowsWithProperties) {
759
- for (var property of propertiesOfRow) {
1352
+ const distinctProperties = rowsWithProperties[0];
1353
+ for (const propertiesOfRow of rowsWithProperties) {
1354
+ for (const property of propertiesOfRow) {
760
1355
  const propertyName = property[0];
761
1356
  const propertyValue = property[1];
762
1357
  const alreadyFoundPropertyWithSameName = distinctProperties.find(p => p[0] === propertyName);
@@ -794,16 +1389,16 @@ class RESTworldListViewComponent {
794
1389
  }
795
1390
  static getColumnType(value) {
796
1391
  if (value === null || value === undefined)
797
- return 'text';
1392
+ return ColumnType.text;
798
1393
  if (_.isNumber(value))
799
- return 'numeric';
1394
+ return ColumnType.numeric;
800
1395
  if (_.isDate(value))
801
- return 'date';
1396
+ return ColumnType.date;
802
1397
  if (_.isString(value))
803
- return 'text';
1398
+ return ColumnType.text;
804
1399
  if (_.isBoolean(value))
805
- return 'boolean';
806
- return 'text';
1400
+ return ColumnType.boolean;
1401
+ return ColumnType.text;
807
1402
  }
808
1403
  static toTitleCase(anyCase) {
809
1404
  return anyCase
@@ -815,9 +1410,9 @@ class RESTworldListViewComponent {
815
1410
  .replace(/([a-z]+)([A-Z0-9]+)/g, "$1 $2") // insert space after numbers
816
1411
  .replace(/^./, (match) => match.toUpperCase()); // change first letter to be upper case
817
1412
  }
818
- static createParametersFromEvent(event) {
1413
+ createParametersFromEvent(event) {
819
1414
  const oDataParameters = {
820
- $filter: RESTworldListViewComponent.createFilterFromEvent(event),
1415
+ $filter: this.createFilterFromEvent(event),
821
1416
  $orderby: RESTworldListViewComponent.createOrderByFromEvent(event),
822
1417
  $top: RESTworldListViewComponent.createTopFromEvent(event),
823
1418
  $skip: RESTworldListViewComponent.createSkipFromEvent(event)
@@ -837,22 +1432,33 @@ class RESTworldListViewComponent {
837
1432
  }
838
1433
  return undefined;
839
1434
  }
840
- static createFilterFromEvent(event) {
1435
+ createFilterFromEvent(event) {
841
1436
  if (!event.filters)
842
1437
  return undefined;
843
1438
  const filter = Object.entries(event.filters)
844
- .map(([property, filter]) => RESTworldListViewComponent.createFilterForProperty(property, filter))
845
- .filter(filter => !!filter)
1439
+ // The type definition is wrong, event.filters has values of type FilterMetadata[] and not FilterMetadata.
1440
+ .map(([property, filter]) => ({ property: property, filters: filter }))
1441
+ .map(f => this.createFilterForPropertyArray(f.property, f.filters))
1442
+ .filter(f => !!f)
846
1443
  .join(' and ');
847
1444
  if (filter === '')
848
1445
  return undefined;
849
1446
  return `(${filter})`;
850
1447
  }
851
- static createFilterForProperty(property, filter) {
1448
+ createFilterForPropertyArray(property, filters) {
1449
+ const filter = filters
1450
+ .map(f => this.createFilterForProperty(property, f))
1451
+ .filter(f => !!f)
1452
+ .join(` ${filters[0].operator} `);
1453
+ if (filter === '')
1454
+ return undefined;
1455
+ return `(${filter})`;
1456
+ }
1457
+ createFilterForProperty(property, filter) {
852
1458
  if (!filter.value)
853
1459
  return undefined;
854
1460
  const oDataOperator = RESTworldListViewComponent.createODataOperator(filter.matchMode);
855
- const comparisonValue = RESTworldListViewComponent.createComparisonValue(filter.value);
1461
+ const comparisonValue = this.createComparisonValue(property, filter.value);
856
1462
  switch (oDataOperator) {
857
1463
  case 'contains':
858
1464
  case 'not contains':
@@ -895,28 +1501,37 @@ class RESTworldListViewComponent {
895
1501
  return 'lt';
896
1502
  case FilterMatchMode.AFTER:
897
1503
  return 'gt';
1504
+ case FilterMatchMode.DATE_AFTER:
1505
+ return 'ge';
1506
+ case FilterMatchMode.DATE_BEFORE:
1507
+ return 'lt';
1508
+ case FilterMatchMode.DATE_IS:
1509
+ return 'eq';
1510
+ case FilterMatchMode.DATE_IS_NOT:
1511
+ return 'ne';
898
1512
  default:
899
1513
  throw Error(`Unknown matchMode ${matchMode}`);
900
1514
  }
901
1515
  }
902
- static createComparisonValue(value) {
1516
+ createComparisonValue(property, value) {
903
1517
  if (value === null || value === undefined)
904
1518
  return 'null';
905
- if (_.isNumber(value))
906
- return `${value}`;
907
- if (_.isDate(value))
908
- return `cast(${value.toISOString()}, Edm.DateTimeOffset)`;
909
- if (_.isString(value)) {
910
- const date = new Date(value);
911
- if (!isNaN(date.valueOf()))
912
- return `cast(${date.toISOString()}, Edm.DateTimeOffset)`;
913
- return `'${value}'`;
1519
+ const columns = this.columns.filter(c => c.field === property);
1520
+ if (columns.length !== 1)
1521
+ throw new Error(`Cannot find the column for the property ${property} which is specified in the filter.`);
1522
+ const type = columns[0].type;
1523
+ switch (type) {
1524
+ case ColumnType.boolean:
1525
+ return `${value}`;
1526
+ case ColumnType.date:
1527
+ return `cast(${value.toISOString()}, Edm.DateTimeOffset)`;
1528
+ case ColumnType.numeric:
1529
+ return `${value}`;
1530
+ case ColumnType.text:
1531
+ return `'${value}'`;
1532
+ default:
1533
+ throw new Error(`Unknown column type '${type}'`);
914
1534
  }
915
- if (_.isArray(value))
916
- return `(${value
917
- .map((v) => this.createComparisonValue(v))
918
- .join(',')})`;
919
- throw new Error(`Unknown type of value: ${value}.`);
920
1535
  }
921
1536
  }
922
1537
  RESTworldListViewComponent._dateFormat = new Date(3333, 10, 22)
@@ -925,16 +1540,16 @@ RESTworldListViewComponent._dateFormat = new Date(3333, 10, 22)
925
1540
  .replace("11", "MM")
926
1541
  .replace("3333", "y")
927
1542
  .replace("33", "yy");
928
- RESTworldListViewComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: RESTworldListViewComponent, deps: [{ token: RESTworldClientCollection }, { token: i2.ConfirmationService }, { token: i2.MessageService }, { token: AvatarGenerator }], target: i0.ɵɵFactoryTarget.Component });
929
- RESTworldListViewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.11", type: RESTworldListViewComponent, selector: "restworld-list-view", inputs: { editLink: "editLink", apiName: "apiName", rel: "rel", rowsPerPage: "rowsPerPage" }, 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\r\n <ng-template pTemplate=\"header\" let-columns>\r\n <tr>\r\n <th *ngFor=\"let col of columns\" [pSortableColumn]=\"col.field\">\r\n <div class=\"p-d-flex p-jc-between p-ai-center\">\r\n {{col.header}}\r\n <p-sortIcon [field]=\"col.field\"></p-sortIcon>\r\n <p-columnFilter [type]=\"col.type\" [field]=\"col.field\" 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\" pTooltip=\"Create new\" tooltipPosition=\"left\">\r\n <a class=\"p-button-success\" icon=\"fas fa-plus\" pButton [routerLink]=\"['/edit', apiName, newHref]\"></a>\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=\"'text'\">\r\n <p-avatar *ngIf=\"col.field === 'createdBy' || col.field === 'lastChangedBy'\" [pTooltip]=\"entity[col.field]\" tooltipPosition=\"top\" [image]=\"avatarGenerator.getImage(entity[col.field])\" [label]=\"avatarGenerator.getLabel(entity[col.field])\" [style]=\"avatarGenerator.getStyle(entity[col.field])\" shape=\"circle\"></p-avatar>\r\n <span *ngIf=\"col.field !== 'createdBy' && col.field !== 'lastChangedBy'\">{{entity[col.field]}}</span>\r\n </ng-container>\r\n <span *ngSwitchCase=\"'numeric'\" class=\"flex justify-content-end\">{{entity[col.field]}}</span>\r\n <span *ngSwitchCase=\"'boolean'\" class=\"flex justify-content-center\"><p-triStateCheckbox [(ngModel)]=\"entity[col.field]\" [readonly]=\"true\"></p-triStateCheckbox></span>\r\n <span *ngSwitchCase=\"'date'\" [pTooltip]=\"entity[col.field]\">{{entity[col.field] | date:dateFormat}}</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, 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:-webkit-fit-content;max-width:-moz-fit-content;max-width:fit-content}a.p-button{text-decoration:none}\n"], components: [{ type: i4$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", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "scrollDirection", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollDelay", "virtualRowHeight", "frozenWidth", "responsive", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "autoLayout", "exportFunction", "stateKey", "stateStorage", "editMode", "groupRowsBy", "groupRowsByOrder", "minBufferPx", "maxBufferPx", "responsiveLayout", "breakpoint", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection"], outputs: ["selectionChange", "contextMenuSelectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { type: i4$1.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { type: i4$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"] }, { type: i5$1.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "style", "styleClass"] }, { type: i6$1.TriStateCheckbox, selector: "p-triStateCheckbox", inputs: ["disabled", "name", "ariaLabelledBy", "tabindex", "inputId", "style", "styleClass", "label", "readonly", "checkboxTrueIcon", "checkboxFalseIcon"], outputs: ["onChange"] }, { type: i11.Toast, selector: "p-toast", inputs: ["key", "autoZIndex", "baseZIndex", "style", "styleClass", "position", "preventOpenDuplicates", "preventDuplicates", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions", "breakpoints"], outputs: ["onClose"] }, { type: i12.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"] }], directives: [{ type: i2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i4$1.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { type: i10$1.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { type: i4.RouterLinkWithHref, selector: "a[routerLink],area[routerLink]", inputs: ["routerLink", "target", "queryParams", "fragment", "queryParamsHandling", "preserveFragment", "skipLocationChange", "replaceUrl", "state", "relativeTo"] }, { type: i15.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading"] }, { type: i3.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { type: i3.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i13.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i13.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], pipes: { "date": i3.DatePipe } });
1543
+ RESTworldListViewComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: RESTworldListViewComponent, deps: [{ token: RESTworldClientCollection }, { token: i2$1.ConfirmationService }, { token: i2$1.MessageService }, { token: AvatarGenerator }], target: i0.ɵɵFactoryTarget.Component });
1544
+ RESTworldListViewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.11", type: RESTworldListViewComponent, selector: "rw-list", inputs: { editLink: "editLink", apiName: "apiName", rel: "rel", rowsPerPage: "rowsPerPage" }, 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\r\n <ng-template pTemplate=\"header\" let-columns>\r\n <tr>\r\n <th *ngFor=\"let col of columns\" [pSortableColumn]=\"col.field\">\r\n <div class=\"p-d-flex p-jc-between p-ai-center\">\r\n {{col.header}}\r\n <p-sortIcon [field]=\"col.field\"></p-sortIcon>\r\n <p-columnFilter [type]=\"col.type\" [field]=\"col.field\" 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\" pTooltip=\"Create new\" tooltipPosition=\"left\">\r\n <a class=\"p-button-success\" icon=\"fas fa-plus\" pButton [routerLink]=\"['/edit', apiName, newHref]\"></a>\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=\"'text'\">\r\n <p-avatar *ngIf=\"col.field === 'createdBy' || col.field === 'lastChangedBy'\" [pTooltip]=\"entity[col.field]\" tooltipPosition=\"top\" [image]=\"avatarGenerator.getImage(entity[col.field])\" [label]=\"avatarGenerator.getLabel(entity[col.field])\" [style]=\"avatarGenerator.getStyle(entity[col.field])\" shape=\"circle\"></p-avatar>\r\n <span *ngIf=\"col.field !== 'createdBy' && col.field !== 'lastChangedBy'\">{{entity[col.field]}}</span>\r\n </ng-container>\r\n <span *ngSwitchCase=\"'numeric'\" class=\"flex justify-content-end\">{{entity[col.field]}}</span>\r\n <span *ngSwitchCase=\"'boolean'\" class=\"flex justify-content-center\"><p-triStateCheckbox [(ngModel)]=\"entity[col.field]\" [readonly]=\"true\"></p-triStateCheckbox></span>\r\n <span *ngSwitchCase=\"'date'\" [pTooltip]=\"entity[col.field]\">{{entity[col.field] | date:dateFormat}}</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, 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:-webkit-fit-content;max-width:-moz-fit-content;max-width:fit-content}a.p-button{text-decoration:none}\n"], components: [{ type: i4$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", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "scrollDirection", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollDelay", "virtualRowHeight", "frozenWidth", "responsive", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "autoLayout", "exportFunction", "stateKey", "stateStorage", "editMode", "groupRowsBy", "groupRowsByOrder", "minBufferPx", "maxBufferPx", "responsiveLayout", "breakpoint", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection"], outputs: ["selectionChange", "contextMenuSelectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { type: i4$3.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { type: i4$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"] }, { type: i5$2.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "style", "styleClass"] }, { type: i9$1.TriStateCheckbox, selector: "p-triStateCheckbox", inputs: ["disabled", "name", "ariaLabelledBy", "tabindex", "inputId", "style", "styleClass", "label", "readonly", "checkboxTrueIcon", "checkboxFalseIcon"], outputs: ["onChange"] }, { type: i11.Toast, selector: "p-toast", inputs: ["key", "autoZIndex", "baseZIndex", "style", "styleClass", "position", "preventOpenDuplicates", "preventDuplicates", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions", "breakpoints"], outputs: ["onClose"] }, { type: i12$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"] }], directives: [{ type: i2$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { type: i3$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i4$3.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { type: i7.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { type: i4$2.RouterLinkWithHref, selector: "a[routerLink],area[routerLink]", inputs: ["routerLink", "target", "queryParams", "fragment", "queryParamsHandling", "preserveFragment", "skipLocationChange", "replaceUrl", "state", "relativeTo"] }, { type: i1$3.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading"] }, { type: i3$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { type: i3$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { type: i3$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i14.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i14.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], pipes: { "date": i3$1.DatePipe } });
930
1545
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: RESTworldListViewComponent, decorators: [{
931
1546
  type: Component,
932
1547
  args: [{
933
- selector: 'restworld-list-view',
1548
+ selector: 'rw-list',
934
1549
  templateUrl: './restworld-list-view.component.html',
935
1550
  styleUrls: ['./restworld-list-view.component.css']
936
1551
  }]
937
- }], ctorParameters: function () { return [{ type: RESTworldClientCollection }, { type: i2.ConfirmationService }, { type: i2.MessageService }, { type: AvatarGenerator }]; }, propDecorators: { editLink: [{
1552
+ }], ctorParameters: function () { return [{ type: RESTworldClientCollection }, { type: i2$1.ConfirmationService }, { type: i2$1.MessageService }, { type: AvatarGenerator }]; }, propDecorators: { editLink: [{
938
1553
  type: Input
939
1554
  }], apiName: [{
940
1555
  type: Input
@@ -951,7 +1566,12 @@ class RestworldClientModule {
951
1566
  }
952
1567
  RestworldClientModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: RestworldClientModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
953
1568
  RestworldClientModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: RestworldClientModule, declarations: [RESTworldListViewComponent,
954
- RESTworldEditViewComponent], imports: [CommonModule,
1569
+ RESTworldEditViewComponent,
1570
+ RESTWorldImageViewComponent,
1571
+ RESTWorldFileViewComponent,
1572
+ SafeUrlPipe,
1573
+ AsPipe,
1574
+ RestworldEditFormComponent], imports: [CommonModule,
955
1575
  RouterModule,
956
1576
  FormsModule,
957
1577
  ReactiveFormsModule,
@@ -971,12 +1591,25 @@ RestworldClientModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", v
971
1591
  ProgressSpinnerModule,
972
1592
  RippleModule,
973
1593
  TriStateCheckboxModule,
974
- AvatarModule], exports: [RESTworldListViewComponent,
975
- RESTworldEditViewComponent] });
1594
+ AvatarModule,
1595
+ DropdownModule,
1596
+ MultiSelectModule,
1597
+ FileUploadModule,
1598
+ ValdemortModule,
1599
+ ImageCropperModule,
1600
+ DialogModule,
1601
+ ButtonModule,
1602
+ ColorPickerModule,
1603
+ DragDropModule], exports: [RESTworldListViewComponent,
1604
+ RESTworldEditViewComponent,
1605
+ RESTWorldImageViewComponent,
1606
+ RESTWorldFileViewComponent,
1607
+ SafeUrlPipe] });
976
1608
  RestworldClientModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: RestworldClientModule, providers: [
977
1609
  RESTworldClientCollection,
978
1610
  AvatarGenerator,
979
1611
  ConfirmationService,
1612
+ FormService,
980
1613
  MessageService,
981
1614
  {
982
1615
  provide: APP_INITIALIZER,
@@ -1005,14 +1638,28 @@ RestworldClientModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", v
1005
1638
  ProgressSpinnerModule,
1006
1639
  RippleModule,
1007
1640
  TriStateCheckboxModule,
1008
- AvatarModule
1641
+ AvatarModule,
1642
+ DropdownModule,
1643
+ MultiSelectModule,
1644
+ FileUploadModule,
1645
+ ValdemortModule,
1646
+ ImageCropperModule,
1647
+ DialogModule,
1648
+ ButtonModule,
1649
+ ColorPickerModule,
1650
+ DragDropModule
1009
1651
  ]] });
1010
1652
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: RestworldClientModule, decorators: [{
1011
1653
  type: NgModule,
1012
1654
  args: [{
1013
1655
  declarations: [
1014
1656
  RESTworldListViewComponent,
1015
- RESTworldEditViewComponent
1657
+ RESTworldEditViewComponent,
1658
+ RESTWorldImageViewComponent,
1659
+ RESTWorldFileViewComponent,
1660
+ SafeUrlPipe,
1661
+ AsPipe,
1662
+ RestworldEditFormComponent
1016
1663
  ],
1017
1664
  imports: [
1018
1665
  CommonModule,
@@ -1035,16 +1682,29 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.11", ngImpo
1035
1682
  ProgressSpinnerModule,
1036
1683
  RippleModule,
1037
1684
  TriStateCheckboxModule,
1038
- AvatarModule
1685
+ AvatarModule,
1686
+ DropdownModule,
1687
+ MultiSelectModule,
1688
+ FileUploadModule,
1689
+ ValdemortModule,
1690
+ ImageCropperModule,
1691
+ DialogModule,
1692
+ ButtonModule,
1693
+ ColorPickerModule,
1694
+ DragDropModule
1039
1695
  ],
1040
1696
  exports: [
1041
1697
  RESTworldListViewComponent,
1042
- RESTworldEditViewComponent
1698
+ RESTworldEditViewComponent,
1699
+ RESTWorldImageViewComponent,
1700
+ RESTWorldFileViewComponent,
1701
+ SafeUrlPipe
1043
1702
  ],
1044
1703
  providers: [
1045
1704
  RESTworldClientCollection,
1046
1705
  AvatarGenerator,
1047
1706
  ConfirmationService,
1707
+ FormService,
1048
1708
  MessageService,
1049
1709
  {
1050
1710
  provide: APP_INITIALIZER,
@@ -1064,5 +1724,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.11", ngImpo
1064
1724
  * Generated bundle index. Do not edit.
1065
1725
  */
1066
1726
 
1067
- export { AvatarGenerator, LinkNames, ProblemDetails, RESTworldClient, RESTworldClientCollection, RESTworldEditViewComponent, RESTworldListViewComponent, RESTworldOptions, RestworldClientModule, SettingsService, initializeSettings };
1727
+ export { AsPipe, AvatarGenerator, ColumnType, FormService, LinkNames, ProblemDetails, RESTWorldFileViewComponent, RESTWorldImageViewComponent, RESTworldClient, RESTworldClientCollection, RESTworldEditViewComponent, RESTworldListViewComponent, RESTworldOptions, RestworldClientModule, RestworldEditFormComponent, SafeUrlPipe, SettingsService, initializeSettings };
1068
1728
  //# sourceMappingURL=wertzui-ngx-restworld-client.js.map