ichec-angular-core 0.1.4 → 0.1.6

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.
@@ -1,51 +1,55 @@
1
1
  import { map, catchError, tap, mergeMap, throwError, BehaviorSubject, mergeAll, of, merge, debounceTime, distinctUntilChanged, Subscription, finalize } from 'rxjs';
2
2
  import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
3
3
  import * as i0 from '@angular/core';
4
- import { InjectionToken, inject, Injectable, input, signal, Component, viewChild, computed, output } from '@angular/core';
5
- import * as i1$3 from '@angular/forms';
4
+ import { InjectionToken, inject, Injectable, signal, input, Component, viewChild, computed, output } from '@angular/core';
5
+ import * as i1$2 from '@angular/forms';
6
6
  import { FormControl, Validators, FormGroup, FormsModule, ReactiveFormsModule, FormBuilder } from '@angular/forms';
7
7
  import * as i1 from '@angular/router';
8
8
  import { RouterModule, RouterOutlet, Router, ActivatedRoute } from '@angular/router';
9
9
  import * as i2 from '@angular/material/toolbar';
10
10
  import { MatToolbarModule } from '@angular/material/toolbar';
11
- import * as i1$1 from '@angular/material/icon';
11
+ import * as i5 from '@angular/material/icon';
12
12
  import { MatIconModule } from '@angular/material/icon';
13
13
  import * as i2$1 from '@angular/material/button';
14
14
  import { MatButtonModule } from '@angular/material/button';
15
- import * as i5 from '@angular/material/menu';
15
+ import * as i5$1 from '@angular/material/menu';
16
16
  import { MatMenuModule } from '@angular/material/menu';
17
- import * as i1$2 from '@angular/material/sidenav';
17
+ import * as i1$1 from '@angular/material/sidenav';
18
18
  import { MatSidenavContent, MatSidenavModule } from '@angular/material/sidenav';
19
19
  import * as i2$2 from '@angular/material/list';
20
20
  import { MatListModule } from '@angular/material/list';
21
- import { NgIf, Location, NgTemplateOutlet, TitleCasePipe } from '@angular/common';
21
+ import { NgIf, Location, TitleCasePipe, NgTemplateOutlet } from '@angular/common';
22
22
  import * as i3 from '@angular/material/input';
23
23
  import { MatInputModule } from '@angular/material/input';
24
- import * as i2$3 from '@angular/material/form-field';
24
+ import * as i4 from '@angular/material/form-field';
25
25
  import { MatFormFieldModule } from '@angular/material/form-field';
26
- import * as i1$4 from '@angular/material/card';
26
+ import * as i1$3 from '@angular/material/card';
27
27
  import { MatCardModule } from '@angular/material/card';
28
- import * as i4 from '@angular/material/checkbox';
28
+ import * as i4$1 from '@angular/material/checkbox';
29
29
  import { MatCheckboxModule } from '@angular/material/checkbox';
30
- import * as i1$5 from '@angular/material/table';
31
- import { MatTableModule, MatTable } from '@angular/material/table';
32
30
  import * as i6 from '@angular/material/select';
33
31
  import { MatSelectModule } from '@angular/material/select';
34
- import * as i4$1 from '@angular/material/tooltip';
32
+ import * as i1$5 from '@angular/material/table';
33
+ import { MatTableModule, MatTable } from '@angular/material/table';
34
+ import * as i4$2 from '@angular/material/tooltip';
35
35
  import { MatTooltipModule } from '@angular/material/tooltip';
36
+ import * as i1$4 from '@angular/material/expansion';
37
+ import { MatExpansionModule } from '@angular/material/expansion';
36
38
  import * as i6$1 from '@angular/material/autocomplete';
37
39
  import { MatAutocompleteModule } from '@angular/material/autocomplete';
38
40
  import * as i3$1 from '@angular/material/sort';
39
41
  import { MatSort, MatSortModule } from '@angular/material/sort';
40
42
  import * as i1$6 from '@angular/material/button-toggle';
41
43
  import { MatButtonToggleModule } from '@angular/material/button-toggle';
42
- import * as i2$6 from '@angular/material/progress-spinner';
44
+ import * as i2$5 from '@angular/material/progress-spinner';
43
45
  import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
44
- import * as i2$4 from '@angular/material/paginator';
46
+ import * as i2$3 from '@angular/material/paginator';
45
47
  import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator';
46
- import * as i2$5 from '@angular/cdk/scrolling';
48
+ import * as i2$4 from '@angular/cdk/scrolling';
47
49
  import { ScrollingModule } from '@angular/cdk/scrolling';
48
50
  import { DataSource } from '@angular/cdk/collections';
51
+ import * as i7 from '@angular/material/tabs';
52
+ import { MatTabsModule } from '@angular/material/tabs';
49
53
 
50
54
  class Paginated {
51
55
  count = 0;
@@ -114,6 +118,16 @@ class ApiError {
114
118
  text = "";
115
119
  }
116
120
 
121
+ var FieldType;
122
+ (function (FieldType) {
123
+ FieldType[FieldType["Boolean"] = 0] = "Boolean";
124
+ FieldType[FieldType["Char"] = 1] = "Char";
125
+ FieldType[FieldType["Text"] = 2] = "Text";
126
+ FieldType[FieldType["RichText"] = 3] = "RichText";
127
+ FieldType[FieldType["Selection"] = 4] = "Selection";
128
+ FieldType[FieldType["Integer"] = 5] = "Integer";
129
+ FieldType[FieldType["File"] = 6] = "File";
130
+ })(FieldType || (FieldType = {}));
117
131
  const FORM_FIELD_CHOICES = [{ value: "BOOLEAN", display_name: "Boolean" },
118
132
  { value: "CHAR", display_name: "Short Text" },
119
133
  { value: "TEXT", display_name: "Long Text" },
@@ -122,6 +136,23 @@ const FORM_FIELD_CHOICES = [{ value: "BOOLEAN", display_name: "Boolean" },
122
136
  { value: "INTEGER", display_name: "Integer" },
123
137
  { value: "FILE", display_name: "File" }
124
138
  ];
139
+ function getFieldTypeFromKey(key) {
140
+ switch (key) {
141
+ case "CHAR":
142
+ return FieldType.Char;
143
+ case "TEXT":
144
+ return FieldType.Text;
145
+ case "RICH_TEXT":
146
+ return FieldType.RichText;
147
+ case "SELECTION":
148
+ return FieldType.Selection;
149
+ case "INTEGER":
150
+ return FieldType.Integer;
151
+ case "FILE":
152
+ return FieldType.File;
153
+ }
154
+ return FieldType.Char;
155
+ }
125
156
 
126
157
  const ENDPOINT_URL = new InjectionToken("Default endpoint url");
127
158
  class RestService {
@@ -193,7 +224,16 @@ class RestService {
193
224
  });
194
225
  const form = new FormData();
195
226
  form.append("file", file);
196
- return this._http.post(this.getBaseUrl() + id + "/" + field, form, { headers: headers }).pipe(mergeMap(_ => this.getItem(id)), catchError(this.handleError));
227
+ return this._http.post(this.getBaseUrl() + id + "/" + field + "/upload", form, { headers: headers }).pipe(mergeMap(_ => this.getItem(id)), catchError(this.handleError));
228
+ }
229
+ putFile(id, field, file) {
230
+ const token = "Token " + localStorage.getItem("api_token");
231
+ const headers = new HttpHeaders({
232
+ 'Authorization': token,
233
+ 'Accept': 'application/json',
234
+ 'Content-Disposition': 'attachment; filename=' + file.name
235
+ });
236
+ return this._http.put(this.getBaseUrl() + id + "/" + field + "/upload", file, { headers: headers }).pipe(mergeMap(_ => this.getItem(id)), catchError(this.handleError));
197
237
  }
198
238
  patchItem(item, include_keys, exclude_keys) {
199
239
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -409,6 +449,26 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImpor
409
449
  class AddressService extends ItemWithUserService {
410
450
  _url = Address.plural;
411
451
  typename = Address.typename;
452
+ countryOptions = signal([], ...(ngDevMode ? [{ debugName: "countryOptions" }] : []));
453
+ refreshCountryOptions() {
454
+ this.getOptions().subscribe(options => this.onOptions(options));
455
+ }
456
+ onOptions(options) {
457
+ if (!options.actions) {
458
+ return;
459
+ }
460
+ if ('POST' in options.actions) {
461
+ this.onPostActions(options.actions['POST']);
462
+ }
463
+ }
464
+ onPostActions(actions) {
465
+ if ('country' in actions && actions['country'].choices) {
466
+ this.onCountryChoices(actions['country'].choices);
467
+ }
468
+ }
469
+ onCountryChoices(choices) {
470
+ this.countryOptions.update(() => choices.map(c => { return { name: c.display_name, code: c.value, flag: "" }; }));
471
+ }
412
472
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: AddressService, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
413
473
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: AddressService, providedIn: 'root' });
414
474
  }
@@ -460,6 +520,38 @@ class FormService {
460
520
  }));
461
521
  return new FormGroup(controls);
462
522
  }
523
+ createFieldValue(key, control) {
524
+ return { field: parseInt(key),
525
+ asset: null,
526
+ value: control.value
527
+ };
528
+ }
529
+ createItem(form) {
530
+ const values = Object.keys(form.controls).map(key => this.createFieldValue(key, form.controls[key]));
531
+ return { values: Array.from(values) };
532
+ }
533
+ updateFieldValue(control, item) {
534
+ item.value = control.value.value;
535
+ return item;
536
+ }
537
+ getValue(key, form) {
538
+ const field = parseInt(key);
539
+ for (const value of form.values) {
540
+ if (value.field.id == field) {
541
+ return value;
542
+ }
543
+ }
544
+ return null;
545
+ }
546
+ updateItem(form, item) {
547
+ Object.keys(form.controls).forEach(key => {
548
+ const value = this.getValue(key, item);
549
+ if (value) {
550
+ this.updateFieldValue(form.controls[key], value);
551
+ }
552
+ });
553
+ return item;
554
+ }
463
555
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: FormService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
464
556
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: FormService, providedIn: 'root' });
465
557
  }
@@ -543,7 +635,7 @@ class TopBarComponent {
543
635
  return "";
544
636
  }
545
637
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: TopBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
546
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: TopBarComponent, isStandalone: true, selector: "lib-top-bar", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "\n@if(user(); as user){\n<mat-toolbar style=\"height:60px\">\n <a mat-icon-button aria-label=\"Home\" [routerLink]=\"['home']\">\n <mat-icon>home</mat-icon>\n </a>\n <span>{{title()}}</span>\n <span class=\"topbar-spacer\"></span>\n <span>{{user.username}}</span>\n \n <button mat-icon-button style=\"margin: 5px\" aria-label=\"User Profile\" [matMenuTriggerFor]=\"profile_menu\">\n <mat-icon>person</mat-icon>\n </button>\n\n <mat-menu #profile_menu=\"matMenu\">\n <a mat-menu-item aria-label=\"My Profile\" [routerLink]=\"['/members/detail', user.id]\">\n <mat-icon>manage_accounts</mat-icon>\n <span>My Profile</span>\n </a> \n <a mat-menu-item aria-label=\"Get Support\" [routerLink]=\"['/feedback']\">\n <mat-icon>contact_support</mat-icon>\n <span>Get Support</span>\n </a> \n <button mat-menu-item (click)=\"onLogout()\">\n <mat-icon>logout</mat-icon>\n <span>Log Out</span>\n </button>\n\n </mat-menu>\n</mat-toolbar>\n}\n", styles: [".topbar-spacer{flex:1 1 auto}\n"], dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: MatToolbarModule }, { kind: "component", type: i2.MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i5.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i5.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i5.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }] });
638
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: TopBarComponent, isStandalone: true, selector: "lib-top-bar", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "\n@if(user(); as user){\n<mat-toolbar style=\"height:60px\">\n <a mat-icon-button aria-label=\"Home\" [routerLink]=\"['home']\">\n <mat-icon>home</mat-icon>\n </a>\n <span>{{title()}}</span>\n <span class=\"topbar-spacer\"></span>\n <span>{{user.username}}</span>\n \n <button mat-icon-button style=\"margin: 5px\" aria-label=\"User Profile\" [matMenuTriggerFor]=\"profile_menu\">\n <mat-icon>person</mat-icon>\n </button>\n\n <mat-menu #profile_menu=\"matMenu\">\n <a mat-menu-item aria-label=\"My Profile\" [routerLink]=\"['/members/detail', user.id]\">\n <mat-icon>manage_accounts</mat-icon>\n <span>My Profile</span>\n </a> \n <a mat-menu-item aria-label=\"Get Support\" [routerLink]=\"['/feedback']\">\n <mat-icon>contact_support</mat-icon>\n <span>Get Support</span>\n </a> \n <button mat-menu-item (click)=\"onLogout()\">\n <mat-icon>logout</mat-icon>\n <span>Log Out</span>\n </button>\n\n </mat-menu>\n</mat-toolbar>\n}\n", styles: [".topbar-spacer{flex:1 1 auto}\n"], dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: MatToolbarModule }, { kind: "component", type: i2.MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i5$1.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i5$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i5$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }] });
547
639
  }
548
640
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: TopBarComponent, decorators: [{
549
641
  type: Component,
@@ -561,11 +653,11 @@ class LeftNavComponent {
561
653
  return this._leftNavService.activeOptions;
562
654
  }
563
655
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: LeftNavComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
564
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: LeftNavComponent, isStandalone: true, selector: "lib-left-nav", viewQueries: [{ propertyName: "sideNavContent", first: true, predicate: MatSidenavContent, descendants: true, isSignal: true }], ngImport: i0, template: "<mat-sidenav-container class=\"leftnav-container\">\n <mat-sidenav mode=\"side\" class=\"leftnav-side\" opened>\n <mat-nav-list>\n @for (option of getOptions(); track option) {\n <a mat-list-item [routerLink]=\"option.route\" [routerLinkActive]=\"['is-active']\">{{ option.name }}</a>\n }\n </mat-nav-list>\n </mat-sidenav>\n <mat-sidenav-content class=\"leftnav-content\"> \n <router-outlet />\n </mat-sidenav-content>\n</mat-sidenav-container>\n", styles: [":host{display:flex;flex-direction:column}.leftnav-container{flex-grow:1;display:flex}.leftnav-content{display:flex;flex-grow:1;height:90vh}.leftnav-side{padding:5px;width:160px}.is-active{background-color:#d3d3d3}\n"], dependencies: [{ kind: "ngmodule", type: MatSidenavModule }, { kind: "component", type: i1$2.MatSidenav, selector: "mat-sidenav", inputs: ["fixedInViewport", "fixedTopGap", "fixedBottomGap"], exportAs: ["matSidenav"] }, { kind: "component", type: i1$2.MatSidenavContainer, selector: "mat-sidenav-container", exportAs: ["matSidenavContainer"] }, { kind: "component", type: i1$2.MatSidenavContent, selector: "mat-sidenav-content" }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i2$2.MatNavList, selector: "mat-nav-list", exportAs: ["matNavList"] }, { kind: "component", type: i2$2.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i1.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }] });
656
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: LeftNavComponent, isStandalone: true, selector: "lib-left-nav", viewQueries: [{ propertyName: "sideNavContent", first: true, predicate: MatSidenavContent, descendants: true, isSignal: true }], ngImport: i0, template: "<mat-sidenav-container class=\"leftnav-container\">\n <mat-sidenav mode=\"side\" class=\"leftnav-side\" opened>\n <mat-nav-list>\n @for (option of getOptions(); track option) {\n <a mat-list-item [routerLink]=\"option.route\" [routerLinkActive]=\"['is-active']\">{{ option.name }}</a>\n }\n </mat-nav-list>\n </mat-sidenav>\n <mat-sidenav-content class=\"leftnav-content\"> \n <router-outlet />\n </mat-sidenav-content>\n</mat-sidenav-container>\n", styles: [":host{display:flex;flex-direction:column}.leftnav-container{flex-grow:1;display:flex}.leftnav-content{display:flex;flex-grow:1;height:90vh}.leftnav-side{padding:5px;width:200px}.is-active{background-color:#d3d3d3}\n"], dependencies: [{ kind: "ngmodule", type: MatSidenavModule }, { kind: "component", type: i1$1.MatSidenav, selector: "mat-sidenav", inputs: ["fixedInViewport", "fixedTopGap", "fixedBottomGap"], exportAs: ["matSidenav"] }, { kind: "component", type: i1$1.MatSidenavContainer, selector: "mat-sidenav-container", exportAs: ["matSidenavContainer"] }, { kind: "component", type: i1$1.MatSidenavContent, selector: "mat-sidenav-content" }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i2$2.MatNavList, selector: "mat-nav-list", exportAs: ["matNavList"] }, { kind: "component", type: i2$2.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i1.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }] });
565
657
  }
566
658
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: LeftNavComponent, decorators: [{
567
659
  type: Component,
568
- args: [{ selector: 'lib-left-nav', imports: [MatSidenavModule, MatListModule, RouterOutlet, RouterModule], template: "<mat-sidenav-container class=\"leftnav-container\">\n <mat-sidenav mode=\"side\" class=\"leftnav-side\" opened>\n <mat-nav-list>\n @for (option of getOptions(); track option) {\n <a mat-list-item [routerLink]=\"option.route\" [routerLinkActive]=\"['is-active']\">{{ option.name }}</a>\n }\n </mat-nav-list>\n </mat-sidenav>\n <mat-sidenav-content class=\"leftnav-content\"> \n <router-outlet />\n </mat-sidenav-content>\n</mat-sidenav-container>\n", styles: [":host{display:flex;flex-direction:column}.leftnav-container{flex-grow:1;display:flex}.leftnav-content{display:flex;flex-grow:1;height:90vh}.leftnav-side{padding:5px;width:160px}.is-active{background-color:#d3d3d3}\n"] }]
660
+ args: [{ selector: 'lib-left-nav', imports: [MatSidenavModule, MatListModule, RouterOutlet, RouterModule], template: "<mat-sidenav-container class=\"leftnav-container\">\n <mat-sidenav mode=\"side\" class=\"leftnav-side\" opened>\n <mat-nav-list>\n @for (option of getOptions(); track option) {\n <a mat-list-item [routerLink]=\"option.route\" [routerLinkActive]=\"['is-active']\">{{ option.name }}</a>\n }\n </mat-nav-list>\n </mat-sidenav>\n <mat-sidenav-content class=\"leftnav-content\"> \n <router-outlet />\n </mat-sidenav-content>\n</mat-sidenav-container>\n", styles: [":host{display:flex;flex-direction:column}.leftnav-container{flex-grow:1;display:flex}.leftnav-content{display:flex;flex-grow:1;height:90vh}.leftnav-side{padding:5px;width:200px}.is-active{background-color:#d3d3d3}\n"] }]
569
661
  }] });
570
662
 
571
663
  const LOGIN_USER = new InjectionToken("Default login user - used for testing");
@@ -604,7 +696,7 @@ class LandingComponent {
604
696
  this.router.navigateByUrl("/home");
605
697
  }
606
698
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: LandingComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
607
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: LandingComponent, isStandalone: true, selector: "lib-landing", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "\n @if(message(); as message){\n <p>{{message}}</p>\n }\n \n <mat-card style=\"text-align:center;\">\n <form class=\"base-form\" #loginForm=\"ngForm\" (ngSubmit)=\"login()\">\n <mat-card-content>\n <mat-form-field class=\"form-field\">\n <input matInput\n placeholder=\"Username\"\n type=\"text\"\n [(ngModel)]=\"loginUser.name\"\n name=\"username\"\n required>\n </mat-form-field>\n <mat-form-field class=\"form-field\">\n <input matInput\n placeholder=\"Password\"\n type=\"password\"\n [(ngModel)]=\"loginUser.password\"\n name=\"password\"\n required>\n </mat-form-field>\n </mat-card-content>\n <div *ngIf=\"loginError\" class=\"error\">\n <mat-icon>error</mat-icon><p>{{loginError()}}</p>\n </div>\n <button mat-flat-button\n type=\"submit\"\n [disabled]=\"!loginForm.form.valid\">Log In</button>\n </form>\n </mat-card>\n\n\n \n", styles: [":host{display:flex;align-items:center;flex-grow:1;background-color:#a5b3c9;flex-direction:column}.base-form{padding:10px}.form-field{display:flex}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$3.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i1$4.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i1$4.MatCardContent, selector: "mat-card-content" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
699
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: LandingComponent, isStandalone: true, selector: "lib-landing", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "\n @if(message(); as message){\n <p>{{message}}</p>\n }\n \n <mat-card style=\"text-align:center;\">\n <form class=\"base-form\" #loginForm=\"ngForm\" (ngSubmit)=\"login()\">\n <mat-card-content>\n <mat-form-field class=\"form-field\">\n <input matInput\n placeholder=\"Username\"\n type=\"text\"\n [(ngModel)]=\"loginUser.name\"\n name=\"username\"\n required>\n </mat-form-field>\n <mat-form-field class=\"form-field\">\n <input matInput\n placeholder=\"Password\"\n type=\"password\"\n [(ngModel)]=\"loginUser.password\"\n name=\"password\"\n required>\n </mat-form-field>\n </mat-card-content>\n <div *ngIf=\"loginError\" class=\"error\">\n <mat-icon>error</mat-icon><p>{{loginError()}}</p>\n </div>\n <button mat-flat-button\n type=\"submit\"\n [disabled]=\"!loginForm.form.valid\">Log In</button>\n </form>\n </mat-card>\n\n\n \n", styles: [":host{display:flex;align-items:center;flex-grow:1;background-color:#a5b3c9;flex-direction:column}.base-form{padding:10px}.form-field{display:flex}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i1$3.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i1$3.MatCardContent, selector: "mat-card-content" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
608
700
  }
609
701
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: LandingComponent, decorators: [{
610
702
  type: Component,
@@ -678,11 +770,13 @@ class EditView {
678
770
  createMode = signal(false, ...(ngDevMode ? [{ debugName: "createMode" }] : []));
679
771
  heading = computed(() => { const prefix = this.createMode() ? "New " : "Edit "; return prefix + this.getTitle(); }, ...(ngDevMode ? [{ debugName: "heading" }] : []));
680
772
  item = signal(null, ...(ngDevMode ? [{ debugName: "item" }] : []));
773
+ fileKeys = [];
681
774
  _route = inject(ActivatedRoute);
682
775
  _location = inject(Location);
683
776
  _userService = inject(UserService);
684
777
  form;
685
778
  itemService;
779
+ uploadedFiles = [];
686
780
  constructor(itemService, form) {
687
781
  this.itemService = itemService;
688
782
  this.form = form;
@@ -691,6 +785,7 @@ class EditView {
691
785
  this.getItem();
692
786
  }
693
787
  onItemAvailable(item) {
788
+ this.form.setValue(item);
694
789
  this._userService.loggedInUser.subscribe(user => { if (user) {
695
790
  this.onItemAndUserAvailable(item, user);
696
791
  } });
@@ -745,7 +840,32 @@ class EditView {
745
840
  this.itemService.putItem(this.updateItem(item)).subscribe(item => this.saveFiles(item));
746
841
  }
747
842
  saveFiles(item) {
748
- this.onItemUpdated(item);
843
+ console.log("Saving files");
844
+ const next_file = this.getNextFileForUpload();
845
+ console.log("next is:", next_file);
846
+ if (next_file) {
847
+ this.saveFile(item, next_file);
848
+ }
849
+ else {
850
+ this.onItemUpdated(item);
851
+ }
852
+ }
853
+ saveFile(item, record) {
854
+ this.uploadedFiles.push(record.name);
855
+ if (record.file) {
856
+ this.itemService.putFile(item.id, record.name, record.file).subscribe(item => this.saveFiles(item));
857
+ }
858
+ else {
859
+ this.saveFiles(item);
860
+ }
861
+ }
862
+ getNextFileForUpload() {
863
+ for (const key of this.fileKeys) {
864
+ if (!this.uploadedFiles.includes(key)) {
865
+ return this.form.form.get(key)?.value;
866
+ }
867
+ }
868
+ return null;
749
869
  }
750
870
  isCreateRoute() {
751
871
  const urls = this._route.snapshot.url;
@@ -773,6 +893,7 @@ class EditView {
773
893
  }
774
894
  }
775
895
  onItemUpdated(item) {
896
+ this.uploadedFiles = [];
776
897
  this.item.set(item);
777
898
  this.goBack();
778
899
  }
@@ -798,7 +919,7 @@ class FormFieldDetailComponent {
798
919
  return this.field().id.toString();
799
920
  }
800
921
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: FormFieldDetailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
801
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: FormFieldDetailComponent, isStandalone: true, selector: "lib-form-field-detail", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div [formGroup]=\"form()\">\n <label [attr.for]=\"key\">{{ field().label }}</label>\n <div>\n @switch (field().field_type) {\n @case ('TEXT') {\n <mat-form-field class=\"form-field-wide\">\n <mat-label [attr.for]=\"key\">{{ field().label }}</mat-label>\n <textarea matInput\n [placeholder]=\"field().default\"\n type=\"text\"\n style=\"min-height:150px\"\n [formControlName]=\"key\"\n [name]=\"key\"></textarea>\n </mat-form-field>\n }\n @case('BOOLEAN')\n {\n <mat-checkbox\n class=\"form-field\"\n [name]=\"key\"\n [formControlName]=\"key\">\n {{ field().label }}\n </mat-checkbox>\n }\n @case ('INTEGER') {\n <mat-form-field class=\"form-field\">\n <mat-label>{{ field().label }}</mat-label>\n <input matInput\n [placeholder]=\"field().default\"\n type=\"number\"\n max=\"10\" min=\"1\"\n [formControlName]=\"key\"\n name=\"trl_stage\">\n </mat-form-field>\n }\n }\n </div>\n @if (!isValid) {\n <div class=\"errorMessage\">{{ field().label }} is required</div>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$3.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$3.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i4.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }] });
922
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: FormFieldDetailComponent, isStandalone: true, selector: "lib-form-field-detail", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div [formGroup]=\"form()\">\n <label [attr.for]=\"key\">{{ field().label }}</label>\n <div>\n @switch (field().field_type) {\n @case ('TEXT') {\n <mat-form-field class=\"form-field-wide\">\n <mat-label [attr.for]=\"key\">{{ field().label }}</mat-label>\n <textarea matInput\n [placeholder]=\"field().default\"\n type=\"text\"\n style=\"min-height:150px\"\n [formControlName]=\"key\"\n [name]=\"key\"></textarea>\n </mat-form-field>\n }\n @case('BOOLEAN')\n {\n <mat-checkbox\n class=\"form-field\"\n [name]=\"key\"\n [formControlName]=\"key\">\n {{ field().label }}\n </mat-checkbox>\n }\n @case ('INTEGER') {\n <mat-form-field class=\"form-field\">\n <mat-label>{{ field().label }}</mat-label>\n <input matInput\n [placeholder]=\"field().default\"\n type=\"number\"\n max=\"10\" min=\"1\"\n [formControlName]=\"key\"\n name=\"trl_stage\">\n </mat-form-field>\n }\n }\n </div>\n @if (!isValid) {\n <div class=\"errorMessage\">{{ field().label }} is required</div>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$2.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i4$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }] });
802
923
  }
803
924
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: FormFieldDetailComponent, decorators: [{
804
925
  type: Component,
@@ -808,102 +929,59 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImpor
808
929
  MatCheckboxModule], template: "<div [formGroup]=\"form()\">\n <label [attr.for]=\"key\">{{ field().label }}</label>\n <div>\n @switch (field().field_type) {\n @case ('TEXT') {\n <mat-form-field class=\"form-field-wide\">\n <mat-label [attr.for]=\"key\">{{ field().label }}</mat-label>\n <textarea matInput\n [placeholder]=\"field().default\"\n type=\"text\"\n style=\"min-height:150px\"\n [formControlName]=\"key\"\n [name]=\"key\"></textarea>\n </mat-form-field>\n }\n @case('BOOLEAN')\n {\n <mat-checkbox\n class=\"form-field\"\n [name]=\"key\"\n [formControlName]=\"key\">\n {{ field().label }}\n </mat-checkbox>\n }\n @case ('INTEGER') {\n <mat-form-field class=\"form-field\">\n <mat-label>{{ field().label }}</mat-label>\n <input matInput\n [placeholder]=\"field().default\"\n type=\"number\"\n max=\"10\" min=\"1\"\n [formControlName]=\"key\"\n name=\"trl_stage\">\n </mat-form-field>\n }\n }\n </div>\n @if (!isValid) {\n <div class=\"errorMessage\">{{ field().label }} is required</div>\n }\n</div>\n" }]
809
930
  }] });
810
931
 
811
- const FORM_FIELD_TABLE_FULL = [
812
- { name: 'label', title: 'Label', element_type: 'string' },
813
- { name: 'field_type', title: 'Type', element_type: 'string' }
814
- ];
815
- const FORM_GROUP_TABLE_FULL = [
816
- { name: 'label', title: 'Label', element_type: 'string' }
817
- ];
818
-
819
- class FormFieldListComponent {
820
- form = input.required(...(ngDevMode ? [{ debugName: "form" }] : []));
821
- edit = output();
822
- columns = FORM_FIELD_TABLE_FULL;
823
- columnNames = computed(() => { const names = this.columns.map(c => c.name); names.push("edit"); return names; }, ...(ngDevMode ? [{ debugName: "columnNames" }] : []));
824
- onEdit(id) {
825
- this.edit.emit(id);
826
- }
827
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: FormFieldListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
828
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: FormFieldListComponent, isStandalone: true, selector: "lib-form-field-list", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { edit: "edit" }, ngImport: i0, template: "<table mat-table [dataSource]=\"form().controls\" class=\"mat-elevation-z8\">\n @for (column of columns; track column.name) {\n <ng-container matColumnDef=\"{{ column.name }}\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>\n {{ column.title }}\n </th>\n <td mat-cell *matCellDef=\"let element\">{{ element.value[column.name] }}</td>\n </ng-container>\n }\n\n <ng-container matColumnDef=\"edit\">\n <th mat-header-cell *matHeaderCellDef>Edit\n </th>\n <td mat-cell *matCellDef=\"let idx = index\">\n <button mat-icon-button\n type=\"button\"\n color=\"primary\"\n aria-label=\"Edit an item\"\n (click)=\"onEdit(idx)\">\n <mat-icon>edit\n </mat-icon>\n </button>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"columnNames()\">\n </tr>\n <tr mat-row *matRowDef=\"let row; columns: columnNames();\">\n </tr>\n</table>\n\n\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i1$5.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i1$5.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1$5.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i1$5.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1$5.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1$5.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i1$5.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1$5.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i1$5.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i1$5.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
829
- }
830
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: FormFieldListComponent, decorators: [{
831
- type: Component,
832
- args: [{ selector: 'lib-form-field-list', imports: [MatTableModule, MatButtonModule, MatIconModule], template: "<table mat-table [dataSource]=\"form().controls\" class=\"mat-elevation-z8\">\n @for (column of columns; track column.name) {\n <ng-container matColumnDef=\"{{ column.name }}\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>\n {{ column.title }}\n </th>\n <td mat-cell *matCellDef=\"let element\">{{ element.value[column.name] }}</td>\n </ng-container>\n }\n\n <ng-container matColumnDef=\"edit\">\n <th mat-header-cell *matHeaderCellDef>Edit\n </th>\n <td mat-cell *matCellDef=\"let idx = index\">\n <button mat-icon-button\n type=\"button\"\n color=\"primary\"\n aria-label=\"Edit an item\"\n (click)=\"onEdit(idx)\">\n <mat-icon>edit\n </mat-icon>\n </button>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"columnNames()\">\n </tr>\n <tr mat-row *matRowDef=\"let row; columns: columnNames();\">\n </tr>\n</table>\n\n\n" }]
833
- }] });
834
-
835
932
  class FileUploadComponent {
836
- files = input([], ...(ngDevMode ? [{ debugName: "files" }] : []));
837
- previewLoaded = output();
838
- fileUploaded = output();
839
- clearLocal = output();
840
- onPreviewRead(name, content) {
841
- this.previewLoaded.emit({ name: name, content: content });
842
- }
843
- onFileUpload(name, event) {
933
+ control = input.required(...(ngDevMode ? [{ debugName: "control" }] : []));
934
+ onFileUpload(event) {
844
935
  if (!event.target) {
845
936
  return;
846
937
  }
847
938
  const input_element = event.target;
848
939
  if (input_element.files && input_element.files.length > 0) {
849
- const file = input_element.files[0];
850
- this.fileUploaded.emit({ name: name, file: file });
851
- const record = this.files().find(f => f.name == name);
852
- if (record && record.file_type == "image") {
853
- this.readFile(name, file);
854
- }
940
+ this.onFileUploaded(input_element.files[0]);
855
941
  }
856
942
  }
857
- readFile(name, file) {
858
- const reader = new FileReader();
859
- reader.readAsDataURL(file);
860
- reader.onload = () => {
861
- if (reader.result) {
862
- this.previewLoaded.emit({ name: name, content: reader.result });
863
- }
864
- ;
865
- };
943
+ onFileUploaded(file) {
944
+ const record = this.control().value;
945
+ record.file = file;
946
+ this.control().setValue(record);
947
+ if (record.file_type == "image") {
948
+ const reader = new FileReader();
949
+ reader.readAsDataURL(file);
950
+ reader.onload = () => { if (reader.result) {
951
+ this.onPreviewLoaded(reader.result);
952
+ } ; };
953
+ }
954
+ }
955
+ onPreviewLoaded(preview) {
956
+ const record = this.control().value;
957
+ record.local = preview;
958
+ this.control().setValue(record);
866
959
  }
867
960
  onClearLocal() {
868
- this.clearLocal.emit();
961
+ const record = this.control().value;
962
+ record.local = "";
963
+ this.control().setValue(record);
869
964
  }
870
965
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: FileUploadComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
871
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: FileUploadComponent, isStandalone: true, selector: "lib-file-upload", inputs: { files: { classPropertyName: "files", publicName: "files", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { previewLoaded: "previewLoaded", fileUploaded: "fileUploaded", clearLocal: "clearLocal" }, ngImport: i0, template: "<div class=\"container\">\n @for( file of files(); track file.name)\n {\n @if (file.local)\n {\n <div class=\"image_holder\">\n <p>Update {{file.display_name}}</p>\n <img alt=\"{{file.display_name}}\" src=\"{{file.local}}\" style=\"height:120px;\">\n <button mat-mini-fab (click)=\"onClearLocal()\" type=\"button\">\n <mat-icon>clear</mat-icon>\n </button>\n </div> \n }\n @else\n {\n @if (file.remote){\n <div class=\"image_holder\">\n <p>Update {{file.display_name}}</p>\n <img alt=\"{{file.display_name}}\" src=\"{{file.remote}}\" style=\"height:120px;\">\n </div>\n }\n @else {\n <div>\n <span>Upload a {{file.display_name}}</span>\n </div> \n }\n \n }\n\n <div class=\"button-row\">\n <button mat-mini-fab (click)=\"fileInput.click()\" type=\"button\">\n <mat-icon>attachment</mat-icon>\n </button>\n <input hidden type=\"file\" #fileInput (change)=\"onFileUpload(file.name, $event)\"/>\n </div> \n } \n</div>\n", styles: [".container{padding:10px;display:flex;justify-content:center;text-align:center;flex-direction:column;max-width:300px}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }] });
966
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: FileUploadComponent, isStandalone: true, selector: "lib-file-upload", inputs: { control: { classPropertyName: "control", publicName: "control", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"container\">\n @if (control().value.local)\n {\n <div class=\"image_holder\">\n <p>Update {{control().value.display_name | titlecase}}</p>\n <div style=\"display:flex; flex-direction:row; justify-content: center; align-content: center;\">\n <img alt=\"{{control().value.display_name}}\" src=\"{{control().value.local}}\" style=\"height:120px;\">\n\n <button mat-mini-fab (click)=\"onClearLocal()\" matTooltip=\"Clear\" type=\"button\" style=\"margin:10px\">\n <mat-icon>clear</mat-icon>\n </button>\n </div>\n </div>\n }\n @else\n {\n @if (control().value.remote){\n <div class=\"image_holder\">\n <p>Update {{control().value.display_name | titlecase}}</p>\n <img alt=\"{{control().value.display_name}}\" src=\"{{control().value.remote}}\" style=\"height:120px;\">\n </div>\n }\n @else {\n <div>\n <span>Upload a {{control().value.display_name}}</span>\n </div>\n }\n <div class=\"button-row\">\n <button mat-mini-fab (click)=\"fileInput.click()\" matTooltip=\"Attach\" type=\"button\" style=\"margin:10px\">\n <mat-icon>attachment</mat-icon>\n </button>\n <input hidden type=\"file\" #fileInput (change)=\"onFileUpload($event)\" />\n </div>\n }\n</div>", styles: [".container{padding:10px;display:flex;justify-content:center;text-align:center;flex-direction:column;max-width:300px}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "pipe", type: TitleCasePipe, name: "titlecase" }] });
872
967
  }
873
968
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: FileUploadComponent, decorators: [{
874
969
  type: Component,
875
- args: [{ selector: 'lib-file-upload', imports: [MatIconModule, MatButtonModule], template: "<div class=\"container\">\n @for( file of files(); track file.name)\n {\n @if (file.local)\n {\n <div class=\"image_holder\">\n <p>Update {{file.display_name}}</p>\n <img alt=\"{{file.display_name}}\" src=\"{{file.local}}\" style=\"height:120px;\">\n <button mat-mini-fab (click)=\"onClearLocal()\" type=\"button\">\n <mat-icon>clear</mat-icon>\n </button>\n </div> \n }\n @else\n {\n @if (file.remote){\n <div class=\"image_holder\">\n <p>Update {{file.display_name}}</p>\n <img alt=\"{{file.display_name}}\" src=\"{{file.remote}}\" style=\"height:120px;\">\n </div>\n }\n @else {\n <div>\n <span>Upload a {{file.display_name}}</span>\n </div> \n }\n \n }\n\n <div class=\"button-row\">\n <button mat-mini-fab (click)=\"fileInput.click()\" type=\"button\">\n <mat-icon>attachment</mat-icon>\n </button>\n <input hidden type=\"file\" #fileInput (change)=\"onFileUpload(file.name, $event)\"/>\n </div> \n } \n</div>\n", styles: [".container{padding:10px;display:flex;justify-content:center;text-align:center;flex-direction:column;max-width:300px}\n"] }]
970
+ args: [{ selector: 'lib-file-upload', imports: [MatIconModule, MatButtonModule, MatTooltipModule, TitleCasePipe], template: "<div class=\"container\">\n @if (control().value.local)\n {\n <div class=\"image_holder\">\n <p>Update {{control().value.display_name | titlecase}}</p>\n <div style=\"display:flex; flex-direction:row; justify-content: center; align-content: center;\">\n <img alt=\"{{control().value.display_name}}\" src=\"{{control().value.local}}\" style=\"height:120px;\">\n\n <button mat-mini-fab (click)=\"onClearLocal()\" matTooltip=\"Clear\" type=\"button\" style=\"margin:10px\">\n <mat-icon>clear</mat-icon>\n </button>\n </div>\n </div>\n }\n @else\n {\n @if (control().value.remote){\n <div class=\"image_holder\">\n <p>Update {{control().value.display_name | titlecase}}</p>\n <img alt=\"{{control().value.display_name}}\" src=\"{{control().value.remote}}\" style=\"height:120px;\">\n </div>\n }\n @else {\n <div>\n <span>Upload a {{control().value.display_name}}</span>\n </div>\n }\n <div class=\"button-row\">\n <button mat-mini-fab (click)=\"fileInput.click()\" matTooltip=\"Attach\" type=\"button\" style=\"margin:10px\">\n <mat-icon>attachment</mat-icon>\n </button>\n <input hidden type=\"file\" #fileInput (change)=\"onFileUpload($event)\" />\n </div>\n }\n</div>", styles: [".container{padding:10px;display:flex;justify-content:center;text-align:center;flex-direction:column;max-width:300px}\n"] }]
876
971
  }] });
877
972
 
878
973
  class FormFieldEditComponent {
879
974
  availableTypes = FORM_FIELD_CHOICES;
975
+ FieldType = FieldType;
880
976
  form = input.required(...(ngDevMode ? [{ debugName: "form" }] : []));
881
977
  editMode = input(false, ...(ngDevMode ? [{ debugName: "editMode" }] : []));
882
978
  submitted = output();
883
979
  cancelled = output();
884
- get isBoolean() {
885
- return this.fieldType === "BOOLEAN";
886
- }
887
- get isShortText() {
888
- return this.fieldType === "CHAR";
889
- }
890
- get isLongText() {
891
- return this.fieldType === "TEXT";
892
- }
893
- get isRichText() {
894
- return this.fieldType === "RICH_TEXT";
895
- }
896
- get isSelection() {
897
- return this.fieldType === "SELECTION";
898
- }
899
- get isInteger() {
900
- return this.fieldType === "INTEGER";
901
- }
902
- get isFile() {
903
- return this.fieldType === "FILE";
980
+ get templateControl() {
981
+ return this.form().get('template');
904
982
  }
905
983
  get fieldType() {
906
- return this.form().value.field_type;
984
+ return getFieldTypeFromKey(this.form().value.field_type);
907
985
  }
908
986
  submit() {
909
987
  this.submitted.emit();
@@ -912,7 +990,7 @@ class FormFieldEditComponent {
912
990
  this.cancelled.emit();
913
991
  }
914
992
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: FormFieldEditComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
915
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: FormFieldEditComponent, isStandalone: true, selector: "lib-form-field-edit", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null }, editMode: { classPropertyName: "editMode", publicName: "editMode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { submitted: "submitted", cancelled: "cancelled" }, ngImport: i0, template: "<form class=\"form-card\" id=\"app-field-form\" [formGroup]=\"form()\" (ngSubmit)=\"submit()\">\n <mat-form-field class=\"form-field\">\n <mat-label>Label</mat-label>\n <input matInput \n placeholder=\"Label\" \n type=\"text\" \n formControlName=\"label\" \n required \n name=\"label\">\n </mat-form-field>\n\n<mat-form-field class=\"form-field-wide\">\n<mat-label>Description</mat-label>\n<textarea matInput placeholder=\"Description\" style=\"min-height:150px\" type=\"text\" formControlName=\"description\"\n required name=\"description\"></textarea>\n</mat-form-field>\n\n <mat-checkbox class=\"example-margin\" formControlName=\"required\">Required?</mat-checkbox>\n\n<mat-form-field class=\"form-field\">\n <mat-label>Type</mat-label>\n <mat-select formControlName=\"field_type\" name=\"field_type\" required>\n @for(type of availableTypes; track type.value){\n <mat-option [value]=\"type.value\">{{type.display_name}}\n </mat-option>\n }\n </mat-select>\n</mat-form-field>\n \n @if(isBoolean)\n {\n <mat-form-field class=\"form-field\">\n <mat-label>Default</mat-label>\n <mat-select formControlName=\"default\" name=\"default\" required>\n <mat-option [value]=\"'true'\">True</mat-option>\n <mat-option [value]=\"'false'\">False</mat-option>\n </mat-select>\n </mat-form-field>\n }\n @else if(isShortText)\n {\n <mat-form-field class=\"form-field\">\n <mat-label>Default</mat-label>\n <input matInput \n placeholder=\"Default\" \n type=\"text\" \n formControlName=\"default\" \n name=\"default\">\n </mat-form-field>\n }\n @else if(isLongText || isRichText)\n {\n <mat-form-field class=\"form-field-wide\">\n <mat-label>Default</mat-label>\n <textarea matInput placeholder=\"Default\" style=\"min-height:150px\" type=\"text\" \n formControlName=\"default\"\n name=\"default\"></textarea>\n </mat-form-field>\n }\n @else if(isFile)\n {\n <lib-file-upload></lib-file-upload>\n }\n\n <div>\n\n @if(editMode())\n {\n <button mat-fab class=\"form_action_button\" \n type=\"submit\" form=\"app-field-form\" matTooltip=\"Save Field\"\n [disabled]=\"!form().valid\">\n <mat-icon>save</mat-icon>\n </button>\n\n <button mat-fab class=\"form_action_button\" \n matTooltip=\"Cancel Editing Field\" (click)=\"cancel()\">\n <mat-icon>cancel</mat-icon>\n </button> \n }\n @else {\n <button mat-fab class=\"form_action_button\" \n type=\"submit\" form=\"app-field-form\" matTooltip=\"Add Field\"\n [disabled]=\"!form().valid\">\n <mat-icon>add</mat-icon>\n </button>\n <button mat-fab class=\"form_action_button\" \n matTooltip=\"Cancel Adding Field\" (click)=\"cancel()\">\n <mat-icon>cancel</mat-icon>\n </button> \n }\n </div> \n</form>", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatCardModule }, { kind: "ngmodule", type: MatTableModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i2$3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$3.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i4.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: FileUploadComponent, selector: "lib-file-upload", inputs: ["files"], outputs: ["previewLoaded", "fileUploaded", "clearLocal"] }] });
993
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: FormFieldEditComponent, isStandalone: true, selector: "lib-form-field-edit", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null }, editMode: { classPropertyName: "editMode", publicName: "editMode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { submitted: "submitted", cancelled: "cancelled" }, ngImport: i0, template: "<form class=\"form-card\" id=\"app-field-form\" [formGroup]=\"form()\" (ngSubmit)=\"submit()\">\n <mat-form-field class=\"form-field\">\n <mat-label>Label</mat-label>\n <input matInput placeholder=\"Label\" type=\"text\" formControlName=\"label\" required name=\"label\">\n </mat-form-field>\n\n <mat-form-field class=\"form-field\">\n <mat-label>Key</mat-label>\n <input matInput placeholder=\"Key\" type=\"text\" formControlName=\"key\" required name=\"key\">\n </mat-form-field>\n\n <mat-form-field class=\"form-field-wide\">\n <mat-label>Description</mat-label>\n <textarea matInput placeholder=\"Description\" style=\"min-height:150px\" type=\"text\" formControlName=\"description\"\n required name=\"description\"></textarea>\n </mat-form-field>\n\n <mat-checkbox class=\"example-margin\" formControlName=\"required\">Required?</mat-checkbox>\n\n <mat-form-field class=\"form-field\">\n <mat-label>Type</mat-label>\n <mat-select formControlName=\"field_type\" name=\"field_type\" required>\n @for(type of availableTypes; track type.value){\n <mat-option [value]=\"type.value\">{{type.display_name}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n\n @switch (fieldType) {\n @case(FieldType.Boolean)\n {\n <mat-form-field class=\"form-field\">\n <mat-label>Default</mat-label>\n <mat-select formControlName=\"default\" name=\"default\" required>\n <mat-option [value]=\"'true'\">True</mat-option>\n <mat-option [value]=\"'false'\">False</mat-option>\n </mat-select>\n </mat-form-field>\n }\n @case(FieldType.Char)\n {\n <mat-form-field class=\"form-field\">\n <mat-label>Default</mat-label>\n <input matInput placeholder=\"Default\" type=\"text\" formControlName=\"default\" name=\"default\">\n </mat-form-field>\n }\n @case(FieldType.Text || FieldType.RichText)\n {\n <mat-form-field class=\"form-field-wide\">\n <mat-label>Default</mat-label>\n <textarea matInput placeholder=\"Default\" style=\"min-height:150px\" type=\"text\" formControlName=\"default\"\n name=\"default\"></textarea>\n </mat-form-field>\n }\n @case(FieldType.File)\n {\n <lib-file-upload [control]=\"templateControl\"></lib-file-upload>\n }\n}\n\n <div>\n @if(!editMode()) {\n <button mat-fab class=\"form-action-button\" type=\"submit\" matTooltip=\"Add Field\"\n [disabled]=\"!form().valid\">\n <mat-icon>add</mat-icon>\n </button>\n <button mat-fab class=\"form-action-button\" (click)=\"cancel()\" type=\"button\" matTooltip=\"Cancel\">\n <mat-icon>cancel</mat-icon>\n </button>\n }\n </div>\n</form>", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatCardModule }, { kind: "ngmodule", type: MatTableModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i4$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: FileUploadComponent, selector: "lib-file-upload", inputs: ["control"] }] });
916
994
  }
917
995
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: FormFieldEditComponent, decorators: [{
918
996
  type: Component,
@@ -927,7 +1005,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImpor
927
1005
  MatSelectModule,
928
1006
  MatTooltipModule,
929
1007
  MatCheckboxModule,
930
- FileUploadComponent], template: "<form class=\"form-card\" id=\"app-field-form\" [formGroup]=\"form()\" (ngSubmit)=\"submit()\">\n <mat-form-field class=\"form-field\">\n <mat-label>Label</mat-label>\n <input matInput \n placeholder=\"Label\" \n type=\"text\" \n formControlName=\"label\" \n required \n name=\"label\">\n </mat-form-field>\n\n<mat-form-field class=\"form-field-wide\">\n<mat-label>Description</mat-label>\n<textarea matInput placeholder=\"Description\" style=\"min-height:150px\" type=\"text\" formControlName=\"description\"\n required name=\"description\"></textarea>\n</mat-form-field>\n\n <mat-checkbox class=\"example-margin\" formControlName=\"required\">Required?</mat-checkbox>\n\n<mat-form-field class=\"form-field\">\n <mat-label>Type</mat-label>\n <mat-select formControlName=\"field_type\" name=\"field_type\" required>\n @for(type of availableTypes; track type.value){\n <mat-option [value]=\"type.value\">{{type.display_name}}\n </mat-option>\n }\n </mat-select>\n</mat-form-field>\n \n @if(isBoolean)\n {\n <mat-form-field class=\"form-field\">\n <mat-label>Default</mat-label>\n <mat-select formControlName=\"default\" name=\"default\" required>\n <mat-option [value]=\"'true'\">True</mat-option>\n <mat-option [value]=\"'false'\">False</mat-option>\n </mat-select>\n </mat-form-field>\n }\n @else if(isShortText)\n {\n <mat-form-field class=\"form-field\">\n <mat-label>Default</mat-label>\n <input matInput \n placeholder=\"Default\" \n type=\"text\" \n formControlName=\"default\" \n name=\"default\">\n </mat-form-field>\n }\n @else if(isLongText || isRichText)\n {\n <mat-form-field class=\"form-field-wide\">\n <mat-label>Default</mat-label>\n <textarea matInput placeholder=\"Default\" style=\"min-height:150px\" type=\"text\" \n formControlName=\"default\"\n name=\"default\"></textarea>\n </mat-form-field>\n }\n @else if(isFile)\n {\n <lib-file-upload></lib-file-upload>\n }\n\n <div>\n\n @if(editMode())\n {\n <button mat-fab class=\"form_action_button\" \n type=\"submit\" form=\"app-field-form\" matTooltip=\"Save Field\"\n [disabled]=\"!form().valid\">\n <mat-icon>save</mat-icon>\n </button>\n\n <button mat-fab class=\"form_action_button\" \n matTooltip=\"Cancel Editing Field\" (click)=\"cancel()\">\n <mat-icon>cancel</mat-icon>\n </button> \n }\n @else {\n <button mat-fab class=\"form_action_button\" \n type=\"submit\" form=\"app-field-form\" matTooltip=\"Add Field\"\n [disabled]=\"!form().valid\">\n <mat-icon>add</mat-icon>\n </button>\n <button mat-fab class=\"form_action_button\" \n matTooltip=\"Cancel Adding Field\" (click)=\"cancel()\">\n <mat-icon>cancel</mat-icon>\n </button> \n }\n </div> \n</form>" }]
1008
+ FileUploadComponent], template: "<form class=\"form-card\" id=\"app-field-form\" [formGroup]=\"form()\" (ngSubmit)=\"submit()\">\n <mat-form-field class=\"form-field\">\n <mat-label>Label</mat-label>\n <input matInput placeholder=\"Label\" type=\"text\" formControlName=\"label\" required name=\"label\">\n </mat-form-field>\n\n <mat-form-field class=\"form-field\">\n <mat-label>Key</mat-label>\n <input matInput placeholder=\"Key\" type=\"text\" formControlName=\"key\" required name=\"key\">\n </mat-form-field>\n\n <mat-form-field class=\"form-field-wide\">\n <mat-label>Description</mat-label>\n <textarea matInput placeholder=\"Description\" style=\"min-height:150px\" type=\"text\" formControlName=\"description\"\n required name=\"description\"></textarea>\n </mat-form-field>\n\n <mat-checkbox class=\"example-margin\" formControlName=\"required\">Required?</mat-checkbox>\n\n <mat-form-field class=\"form-field\">\n <mat-label>Type</mat-label>\n <mat-select formControlName=\"field_type\" name=\"field_type\" required>\n @for(type of availableTypes; track type.value){\n <mat-option [value]=\"type.value\">{{type.display_name}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n\n @switch (fieldType) {\n @case(FieldType.Boolean)\n {\n <mat-form-field class=\"form-field\">\n <mat-label>Default</mat-label>\n <mat-select formControlName=\"default\" name=\"default\" required>\n <mat-option [value]=\"'true'\">True</mat-option>\n <mat-option [value]=\"'false'\">False</mat-option>\n </mat-select>\n </mat-form-field>\n }\n @case(FieldType.Char)\n {\n <mat-form-field class=\"form-field\">\n <mat-label>Default</mat-label>\n <input matInput placeholder=\"Default\" type=\"text\" formControlName=\"default\" name=\"default\">\n </mat-form-field>\n }\n @case(FieldType.Text || FieldType.RichText)\n {\n <mat-form-field class=\"form-field-wide\">\n <mat-label>Default</mat-label>\n <textarea matInput placeholder=\"Default\" style=\"min-height:150px\" type=\"text\" formControlName=\"default\"\n name=\"default\"></textarea>\n </mat-form-field>\n }\n @case(FieldType.File)\n {\n <lib-file-upload [control]=\"templateControl\"></lib-file-upload>\n }\n}\n\n <div>\n @if(!editMode()) {\n <button mat-fab class=\"form-action-button\" type=\"submit\" matTooltip=\"Add Field\"\n [disabled]=\"!form().valid\">\n <mat-icon>add</mat-icon>\n </button>\n <button mat-fab class=\"form-action-button\" (click)=\"cancel()\" type=\"button\" matTooltip=\"Cancel\">\n <mat-icon>cancel</mat-icon>\n </button>\n }\n </div>\n</form>" }]
931
1009
  }] });
932
1010
 
933
1011
  class DynamicFormComponent {
@@ -939,20 +1017,24 @@ class DynamicFormComponent {
939
1017
  this.payLoad = JSON.stringify(this.form().getRawValue());
940
1018
  }
941
1019
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: DynamicFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
942
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: DynamicFormComponent, isStandalone: true, selector: "lib-dynamic-form", inputs: { inputForm: { classPropertyName: "inputForm", publicName: "inputForm", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div>\n <form (ngSubmit)=\"onSubmit()\" [formGroup]=\"form()\">\n\n @for (group of inputForm().groups; track group.id) {\n @for (field of group.fields; track field.id) {\n <div class=\"form-row\">\n <lib-form-field-detail [field]=\"field\" [form]=\"form()\" />\n </div>\n }\n }\n </form>\n @if (payLoad) {\n <div class=\"form-row\"><strong>Saved the following values</strong><br />{{ payLoad }}</div>\n }\n</div>", styles: [""], dependencies: [{ kind: "component", type: FormFieldDetailComponent, selector: "lib-form-field-detail", inputs: ["field", "form"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }] });
1020
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: DynamicFormComponent, isStandalone: true, selector: "lib-dynamic-form", inputs: { inputForm: { classPropertyName: "inputForm", publicName: "inputForm", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div>\n <form (ngSubmit)=\"onSubmit()\" [formGroup]=\"form()\">\n\n @for (group of inputForm().groups; track group.order) {\n\n @if(group.label)\n {\n <h3>{{group.label}}</h3>\n }\n\n @if(group.description){\n <p>{{group.description}}</p>\n }\n\n @for (field of group.fields; track field.order) {\n <div class=\"form-row\">\n <lib-form-field-detail [field]=\"field\" [form]=\"form()\" />\n </div>\n }\n }\n </form>\n</div>", styles: [""], dependencies: [{ kind: "component", type: FormFieldDetailComponent, selector: "lib-form-field-detail", inputs: ["field", "form"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }] });
943
1021
  }
944
1022
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: DynamicFormComponent, decorators: [{
945
1023
  type: Component,
946
- args: [{ selector: 'lib-dynamic-form', imports: [FormFieldDetailComponent, ReactiveFormsModule, FormFieldDetailComponent], template: "<div>\n <form (ngSubmit)=\"onSubmit()\" [formGroup]=\"form()\">\n\n @for (group of inputForm().groups; track group.id) {\n @for (field of group.fields; track field.id) {\n <div class=\"form-row\">\n <lib-form-field-detail [field]=\"field\" [form]=\"form()\" />\n </div>\n }\n }\n </form>\n @if (payLoad) {\n <div class=\"form-row\"><strong>Saved the following values</strong><br />{{ payLoad }}</div>\n }\n</div>" }]
1024
+ args: [{ selector: 'lib-dynamic-form', imports: [FormFieldDetailComponent, ReactiveFormsModule, FormFieldDetailComponent], template: "<div>\n <form (ngSubmit)=\"onSubmit()\" [formGroup]=\"form()\">\n\n @for (group of inputForm().groups; track group.order) {\n\n @if(group.label)\n {\n <h3>{{group.label}}</h3>\n }\n\n @if(group.description){\n <p>{{group.description}}</p>\n }\n\n @for (field of group.fields; track field.order) {\n <div class=\"form-row\">\n <lib-form-field-detail [field]=\"field\" [form]=\"form()\" />\n </div>\n }\n }\n </form>\n</div>" }]
947
1025
  }] });
948
1026
 
949
1027
  class FormFieldForm {
1028
+ static getBaseTemplate() {
1029
+ return { name: "template", display_name: "template", file_type: "", remote: "", local: "", file: null };
1030
+ }
950
1031
  static createForm(fb) {
951
1032
  return fb.group({
952
1033
  label: fb.control('', Validators.required),
1034
+ key: fb.control('', Validators.required),
953
1035
  required: fb.control(false, Validators.required),
954
1036
  description: fb.control('', Validators.required),
955
- template: fb.control(null),
1037
+ template: fb.control(this.getBaseTemplate()),
956
1038
  options: fb.control(null),
957
1039
  default: fb.control(''),
958
1040
  field_type: fb.control("BOOLEAN", Validators.required),
@@ -970,11 +1052,16 @@ class FormFieldForm {
970
1052
  if ('id' in item) {
971
1053
  id = item.id;
972
1054
  }
1055
+ const template = this.getBaseTemplate();
1056
+ if (item.template) {
1057
+ template.remote = item.template;
1058
+ }
973
1059
  form.setValue({
974
1060
  label: item.label,
1061
+ key: item.key,
975
1062
  required: item.required,
976
1063
  description: item.description,
977
- template: item.template,
1064
+ template: template,
978
1065
  options: "",
979
1066
  default: item.default,
980
1067
  field_type: item.field_type,
@@ -986,9 +1073,9 @@ class FormFieldForm {
986
1073
  const value = form.value;
987
1074
  return {
988
1075
  label: value.label || "",
1076
+ key: value.key || "",
989
1077
  required: value.required || false,
990
1078
  description: value.description || "",
991
- template: value.template || null,
992
1079
  options: null,
993
1080
  default: value.default || "",
994
1081
  field_type: value.field_type || "BOOLEAN",
@@ -998,9 +1085,9 @@ class FormFieldForm {
998
1085
  static updateItem(form, item) {
999
1086
  const value = form.value;
1000
1087
  item.label = value.label || "";
1088
+ item.key = value.key || "";
1001
1089
  item.required = value.required || false;
1002
1090
  item.description = value.description || "";
1003
- item.template = value.template || null;
1004
1091
  item.options = null;
1005
1092
  item.default = value.default || "";
1006
1093
  item.field_type = value.field_type || "BOOLEAN";
@@ -1027,6 +1114,14 @@ class FormGroupForm {
1027
1114
  static deleteField(form, id) {
1028
1115
  this.getFields(form).removeAt(id);
1029
1116
  }
1117
+ static reorderField(group, id, newIndex) {
1118
+ const current_field = this.getFields(group).at(id);
1119
+ current_field.patchValue({ "order": newIndex });
1120
+ const swap_field = this.getFields(group).at(newIndex);
1121
+ swap_field.patchValue({ "order": id });
1122
+ this.getFields(group).removeAt(id);
1123
+ this.getFields(group).insert(newIndex, current_field);
1124
+ }
1030
1125
  static fromItem(item, fb) {
1031
1126
  const form = this.createForm(fb);
1032
1127
  this.setValue(form, item, fb);
@@ -1088,161 +1183,116 @@ class FormGroupForm {
1088
1183
  }
1089
1184
 
1090
1185
  class FormGroupEditComponent {
1091
- create = input(false, ...(ngDevMode ? [{ debugName: "create" }] : []));
1092
1186
  form = input.required(...(ngDevMode ? [{ debugName: "form" }] : []));
1093
- cancelled = output();
1187
+ editMode = input(false, ...(ngDevMode ? [{ debugName: "editMode" }] : []));
1094
1188
  submitted = output();
1095
- editingField = signal(-1, ...(ngDevMode ? [{ debugName: "editingField" }] : []));
1096
- creatingField = signal(false, ...(ngDevMode ? [{ debugName: "creatingField" }] : []));
1189
+ cancelled = output();
1190
+ fb = inject(FormBuilder);
1097
1191
  fieldForm = null;
1098
- builder = inject(FormBuilder);
1099
1192
  get fields() {
1100
1193
  return this.form().get('fields');
1101
1194
  }
1102
- submit() {
1103
- this.submitted.emit();
1195
+ onFieldDelete(id) {
1196
+ FormGroupForm.deleteField(this.form(), id);
1104
1197
  }
1105
- cancel() {
1106
- this.cancelled.emit();
1198
+ onFieldOrderUp(id) {
1199
+ FormGroupForm.reorderField(this.form(), id, id + 1);
1107
1200
  }
1108
- addField() {
1109
- this.creatingField.set(true);
1110
- this.fieldForm = FormFieldForm.createForm(this.builder);
1201
+ onFieldOrderDown(id) {
1202
+ FormGroupForm.reorderField(this.form(), id, id - 1);
1111
1203
  }
1112
- editField(id) {
1113
- this.editingField.set(id);
1114
- this.fieldForm = this.fields.controls[this.editingField()];
1204
+ addField() {
1205
+ this.fieldForm = FormFieldForm.createForm(this.fb);
1115
1206
  }
1116
1207
  cancelField() {
1117
- this.resetField();
1118
- }
1119
- resetField() {
1120
- this.creatingField.set(false);
1121
1208
  this.fieldForm = null;
1122
- this.editingField.set(-1);
1123
1209
  }
1124
1210
  submitField() {
1125
- if (this.creatingField() && this.fieldForm && this.form) {
1211
+ if (this.fieldForm) {
1126
1212
  FormGroupForm.createField(this.form(), this.fieldForm);
1127
1213
  }
1128
- this.resetField();
1214
+ this.fieldForm = null;
1215
+ }
1216
+ cancel() {
1217
+ this.cancelled.emit();
1218
+ }
1219
+ submit() {
1220
+ this.submitted.emit();
1129
1221
  }
1130
1222
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: FormGroupEditComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1131
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: FormGroupEditComponent, isStandalone: true, selector: "lib-form-group-edit", inputs: { create: { classPropertyName: "create", publicName: "create", isSignal: true, isRequired: false, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { cancelled: "cancelled", submitted: "submitted" }, ngImport: i0, template: "<div [formGroup]=\"form()\">\n\n @if(fieldForm && fields)\n {\n @if(creatingField())\n {\n <h3>Creating Field</h3>\n }\n @else {\n <h3>Editing Field</h3>\n }\n <lib-form-field-edit [form]=\"fieldForm\" (submitted)=\"submitField()\"\n (cancelled)=\"cancelField()\"></lib-form-field-edit>\n }\n @else{\n\n @if(create())\n {\n <h3>Creating Group</h3>\n }\n @else {\n <h3>Editing Group</h3>\n }\n\n <mat-form-field class=\"form-field-wide\">\n <mat-label for=\"description\">Description</mat-label>\n <textarea matInput placeholder=\"\" type=\"text\" style=\"min-height:150px\" formControlName=\"description\"\n name=\"description\"></textarea>\n </mat-form-field>\n\n <h3>Fields</h3>\n <div>\n <button mat-fab class=\"form_action_button\" (click)=\"addField()\" matTooltip=\"Add a Field\" type=\"button\">\n <mat-icon>add</mat-icon>\n </button>\n\n @if(fields && fields.length > 0){\n <lib-form-field-list [form]=\"fields\" (edit)=\"editField($event)\">\n </lib-form-field-list>\n }\n </div>\n\n <button mat-fab class=\"form-action-button\" (click)=\"submit()\" matTooltip=\"Save Group\" type=\"button\">\n <mat-icon>save</mat-icon>\n </button>\n\n <button mat-fab class=\"form-action-button\" (click)=\"cancel()\" matTooltip=\"Cancel adding Group\" type=\"button\">\n <mat-icon>cancel</mat-icon>\n </button>\n }\n\n\n</div>", styles: [""], dependencies: [{ kind: "component", type: FormFieldEditComponent, selector: "lib-form-field-edit", inputs: ["form", "editMode"], outputs: ["submitted", "cancelled"] }, { kind: "component", type: FormFieldListComponent, selector: "lib-form-field-list", inputs: ["form"], outputs: ["edit"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$3.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
1223
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: FormGroupEditComponent, isStandalone: true, selector: "lib-form-group-edit", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null }, editMode: { classPropertyName: "editMode", publicName: "editMode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { submitted: "submitted", cancelled: "cancelled" }, ngImport: i0, template: "<form class=\"form-card\" style=\"width:100%\" [formGroup]=\"form()\" (ngSubmit)=\"submit()\">\n\n <mat-form-field class=\"form-field\">\n <mat-label for=\"label\">Label</mat-label>\n <input matInput placeholder=\"\" type=\"text\" formControlName=\"label\"\n name=\"label\"/>\n </mat-form-field> \n\n <mat-form-field class=\"form-field-wide\">\n <mat-label for=\"description\">Description</mat-label>\n <textarea matInput placeholder=\"\" type=\"text\" style=\"min-height:150px\" formControlName=\"description\"\n name=\"description\"></textarea>\n </mat-form-field>\n\n <h3>Fields</h3>\n @if(fieldForm){\n <lib-form-field-edit [form]=\"fieldForm\" (submitted)=\"submitField()\" (cancelled)=\"cancelField()\"></lib-form-field-edit>\n }\n @else {\n\n <button mat-fab class=\"form-action-button\" (click)=\"addField()\" matTooltip=\"Add a Field\" type=\"button\">\n <mat-icon>add</mat-icon>\n </button>\n\n <mat-accordion style=\"width:100%\">\n @for(field of fields.controls; track field; let idx=$index)\n {\n <mat-expansion-panel style=\"width:100%\">\n <mat-expansion-panel-header>\n <mat-panel-title>{{field.value.label}}</mat-panel-title>\n <div class=\"control\">\n <button mat-icon-button type=\"button\" color=\"primary\" matTooltip=\"Delete the Field\" aria-label=\"Delete an item\"\n (click)=\"onFieldDelete(idx)\">\n <mat-icon>delete\n </mat-icon>\n </button>\n @if(idx>0){\n <button mat-icon-button type=\"button\" color=\"primary\" matTooltip=\"Move Order Up\" aria-label=\"Move Order Up\"\n (click)=\"onFieldOrderUp(idx)\">\n <mat-icon>arrow_upward\n </mat-icon>\n </button>\n }\n @if(idx<fields.controls.length -1){\n <button mat-icon-button type=\"button\" color=\"primary\" matTooltip=\"Move Order Down\" aria-label=\"Move Order Down\"\n (click)=\"onFieldOrderDown(idx)\">\n <mat-icon>arrow_downward\n </mat-icon>\n </button>\n }\n </div>\n </mat-expansion-panel-header>\n <lib-form-field-edit [form]=\"field\" [editMode]=\"true\"></lib-form-field-edit>\n </mat-expansion-panel>\n }\n </mat-accordion>\n }\n\n @if(!editMode()){\n <div>\n <button mat-fab class=\"form-action-button\" \n type=\"submit\" matTooltip=\"Save Group\" [disabled]=\"!form().valid\">\n <mat-icon>save</mat-icon>\n </button>\n <button mat-fab class=\"form-action-button\" \n type=\"button\" matTooltip=\"Cancel\" (click)=\"cancel()\">\n <mat-icon>cancel</mat-icon>\n </button> \n </div>\n}\n<form>", styles: [""], dependencies: [{ kind: "ngmodule", type: MatExpansionModule }, { kind: "directive", type: i1$4.MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: i1$4.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i1$4.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i1$4.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2$1.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: FormFieldEditComponent, selector: "lib-form-field-edit", inputs: ["form", "editMode"], outputs: ["submitted", "cancelled"] }] });
1132
1224
  }
1133
1225
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: FormGroupEditComponent, decorators: [{
1134
1226
  type: Component,
1135
- args: [{ selector: 'lib-form-group-edit', imports: [FormFieldEditComponent,
1136
- FormFieldListComponent,
1227
+ args: [{ selector: 'lib-form-group-edit', imports: [MatExpansionModule,
1137
1228
  MatIconModule,
1138
- MatFormFieldModule,
1139
- ReactiveFormsModule,
1140
1229
  MatButtonModule,
1141
- MatInputModule, MatTooltipModule], template: "<div [formGroup]=\"form()\">\n\n @if(fieldForm && fields)\n {\n @if(creatingField())\n {\n <h3>Creating Field</h3>\n }\n @else {\n <h3>Editing Field</h3>\n }\n <lib-form-field-edit [form]=\"fieldForm\" (submitted)=\"submitField()\"\n (cancelled)=\"cancelField()\"></lib-form-field-edit>\n }\n @else{\n\n @if(create())\n {\n <h3>Creating Group</h3>\n }\n @else {\n <h3>Editing Group</h3>\n }\n\n <mat-form-field class=\"form-field-wide\">\n <mat-label for=\"description\">Description</mat-label>\n <textarea matInput placeholder=\"\" type=\"text\" style=\"min-height:150px\" formControlName=\"description\"\n name=\"description\"></textarea>\n </mat-form-field>\n\n <h3>Fields</h3>\n <div>\n <button mat-fab class=\"form_action_button\" (click)=\"addField()\" matTooltip=\"Add a Field\" type=\"button\">\n <mat-icon>add</mat-icon>\n </button>\n\n @if(fields && fields.length > 0){\n <lib-form-field-list [form]=\"fields\" (edit)=\"editField($event)\">\n </lib-form-field-list>\n }\n </div>\n\n <button mat-fab class=\"form-action-button\" (click)=\"submit()\" matTooltip=\"Save Group\" type=\"button\">\n <mat-icon>save</mat-icon>\n </button>\n\n <button mat-fab class=\"form-action-button\" (click)=\"cancel()\" matTooltip=\"Cancel adding Group\" type=\"button\">\n <mat-icon>cancel</mat-icon>\n </button>\n }\n\n\n</div>" }]
1142
- }] });
1143
-
1144
- class FormGroupListComponent {
1145
- form = input(...(ngDevMode ? [undefined, { debugName: "form" }] : []));
1146
- edit = output();
1147
- delete = output();
1148
- orderUp = output();
1149
- orderDown = output();
1150
- add = output();
1151
- table = viewChild(MatTable, ...(ngDevMode ? [{ debugName: "table" }] : []));
1152
- columns = FORM_GROUP_TABLE_FULL;
1153
- columnNames = computed(() => {
1154
- const names = this.columns.map(c => c.name);
1155
- names.push("edit");
1156
- return names;
1157
- }, ...(ngDevMode ? [{ debugName: "columnNames" }] : []));
1158
- onEdit(form) {
1159
- this.edit.emit(form.value.order);
1160
- }
1161
- onDelete(form) {
1162
- this.delete.emit(form.value.order);
1163
- this.table()?.renderRows();
1164
- }
1165
- onOrderUp(form) {
1166
- this.orderUp.emit(form.value.order);
1167
- this.table()?.renderRows();
1168
- }
1169
- onOrderDown(form) {
1170
- this.orderDown.emit(form.value.order);
1171
- this.table()?.renderRows();
1172
- }
1173
- onAdd() {
1174
- this.add.emit();
1175
- }
1176
- getLabel(form) {
1177
- if (form.value.label) {
1178
- return form.value.label;
1179
- }
1180
- else {
1181
- return "Group " + form.value.order.toString();
1182
- }
1183
- }
1184
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: FormGroupListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1185
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: FormGroupListComponent, isStandalone: true, selector: "lib-form-group-list", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { edit: "edit", delete: "delete", orderUp: "orderUp", orderDown: "orderDown", add: "add" }, viewQueries: [{ propertyName: "table", first: true, predicate: MatTable, descendants: true, isSignal: true }], ngImport: i0, template: "@if(form(); as form){\n\n@if (form.controls.length > 0){\n<table mat-table [dataSource]=\"form.controls\" class=\"mat-elevation-z8\">\n @for (column of columns; track column.name) {\n <ng-container matColumnDef=\"{{ column.name }}\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>\n {{ column.title }}\n </th>\n <td mat-cell *matCellDef=\"let element;\">\n {{ getLabel(element) }}\n </td>\n </ng-container>\n }\n <ng-container matColumnDef=\"edit\">\n <th mat-header-cell *matHeaderCellDef>Edit\n </th>\n <td mat-cell *matCellDef=\"let element\">\n <div class=\"control\">\n <button mat-icon-button\n type=\"button\"\n color=\"primary\"\n aria-label=\"Edit an item\"\n (click)=\"onEdit(element)\">\n <mat-icon>edit\n </mat-icon>\n </button>\n <button mat-icon-button\n type=\"button\"\n color=\"primary\"\n aria-label=\"Delete an item\"\n (click)=\"onDelete(element)\">\n <mat-icon>delete\n </mat-icon>\n </button>\n <button mat-icon-button\n type=\"button\"\n color=\"primary\"\n aria-label=\"Move Order Up\"\n (click)=\"onOrderUp(element)\">\n <mat-icon>arrow_upward\n </mat-icon>\n </button> \n <button mat-icon-button\n type=\"button\"\n color=\"primary\"\n aria-label=\"Move Order Down\"\n (click)=\"onOrderDown(element)\">\n <mat-icon>arrow_downward\n </mat-icon>\n </button>\n </div>\n </td>\n </ng-container>\n \n <tr mat-header-row *matHeaderRowDef=\"columnNames()\">\n </tr>\n <tr mat-row *matRowDef=\"let row; columns: columnNames();\">\n </tr>\n</table>\n}\n}\n\n<button mat-fab class=\"form-action-button\" \n (click)=\"onAdd()\" matTooltip=\"Add a Group\" type=\"button\">\n<mat-icon>add</mat-icon>\n</button>\n\n", styles: [".control,.mat-row:hover .control{display:block}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2$1.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i1$5.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i1$5.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1$5.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i1$5.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1$5.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1$5.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i1$5.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1$5.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i1$5.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i1$5.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
1186
- }
1187
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: FormGroupListComponent, decorators: [{
1188
- type: Component,
1189
- args: [{ selector: 'lib-form-group-list', imports: [MatIconModule, MatButtonModule, MatTableModule, MatTooltipModule], template: "@if(form(); as form){\n\n@if (form.controls.length > 0){\n<table mat-table [dataSource]=\"form.controls\" class=\"mat-elevation-z8\">\n @for (column of columns; track column.name) {\n <ng-container matColumnDef=\"{{ column.name }}\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>\n {{ column.title }}\n </th>\n <td mat-cell *matCellDef=\"let element;\">\n {{ getLabel(element) }}\n </td>\n </ng-container>\n }\n <ng-container matColumnDef=\"edit\">\n <th mat-header-cell *matHeaderCellDef>Edit\n </th>\n <td mat-cell *matCellDef=\"let element\">\n <div class=\"control\">\n <button mat-icon-button\n type=\"button\"\n color=\"primary\"\n aria-label=\"Edit an item\"\n (click)=\"onEdit(element)\">\n <mat-icon>edit\n </mat-icon>\n </button>\n <button mat-icon-button\n type=\"button\"\n color=\"primary\"\n aria-label=\"Delete an item\"\n (click)=\"onDelete(element)\">\n <mat-icon>delete\n </mat-icon>\n </button>\n <button mat-icon-button\n type=\"button\"\n color=\"primary\"\n aria-label=\"Move Order Up\"\n (click)=\"onOrderUp(element)\">\n <mat-icon>arrow_upward\n </mat-icon>\n </button> \n <button mat-icon-button\n type=\"button\"\n color=\"primary\"\n aria-label=\"Move Order Down\"\n (click)=\"onOrderDown(element)\">\n <mat-icon>arrow_downward\n </mat-icon>\n </button>\n </div>\n </td>\n </ng-container>\n \n <tr mat-header-row *matHeaderRowDef=\"columnNames()\">\n </tr>\n <tr mat-row *matRowDef=\"let row; columns: columnNames();\">\n </tr>\n</table>\n}\n}\n\n<button mat-fab class=\"form-action-button\" \n (click)=\"onAdd()\" matTooltip=\"Add a Group\" type=\"button\">\n<mat-icon>add</mat-icon>\n</button>\n\n", styles: [".control,.mat-row:hover .control{display:block}\n"] }]
1230
+ MatTooltipModule,
1231
+ ReactiveFormsModule,
1232
+ MatFormFieldModule,
1233
+ MatInputModule,
1234
+ FormFieldEditComponent], template: "<form class=\"form-card\" style=\"width:100%\" [formGroup]=\"form()\" (ngSubmit)=\"submit()\">\n\n <mat-form-field class=\"form-field\">\n <mat-label for=\"label\">Label</mat-label>\n <input matInput placeholder=\"\" type=\"text\" formControlName=\"label\"\n name=\"label\"/>\n </mat-form-field> \n\n <mat-form-field class=\"form-field-wide\">\n <mat-label for=\"description\">Description</mat-label>\n <textarea matInput placeholder=\"\" type=\"text\" style=\"min-height:150px\" formControlName=\"description\"\n name=\"description\"></textarea>\n </mat-form-field>\n\n <h3>Fields</h3>\n @if(fieldForm){\n <lib-form-field-edit [form]=\"fieldForm\" (submitted)=\"submitField()\" (cancelled)=\"cancelField()\"></lib-form-field-edit>\n }\n @else {\n\n <button mat-fab class=\"form-action-button\" (click)=\"addField()\" matTooltip=\"Add a Field\" type=\"button\">\n <mat-icon>add</mat-icon>\n </button>\n\n <mat-accordion style=\"width:100%\">\n @for(field of fields.controls; track field; let idx=$index)\n {\n <mat-expansion-panel style=\"width:100%\">\n <mat-expansion-panel-header>\n <mat-panel-title>{{field.value.label}}</mat-panel-title>\n <div class=\"control\">\n <button mat-icon-button type=\"button\" color=\"primary\" matTooltip=\"Delete the Field\" aria-label=\"Delete an item\"\n (click)=\"onFieldDelete(idx)\">\n <mat-icon>delete\n </mat-icon>\n </button>\n @if(idx>0){\n <button mat-icon-button type=\"button\" color=\"primary\" matTooltip=\"Move Order Up\" aria-label=\"Move Order Up\"\n (click)=\"onFieldOrderUp(idx)\">\n <mat-icon>arrow_upward\n </mat-icon>\n </button>\n }\n @if(idx<fields.controls.length -1){\n <button mat-icon-button type=\"button\" color=\"primary\" matTooltip=\"Move Order Down\" aria-label=\"Move Order Down\"\n (click)=\"onFieldOrderDown(idx)\">\n <mat-icon>arrow_downward\n </mat-icon>\n </button>\n }\n </div>\n </mat-expansion-panel-header>\n <lib-form-field-edit [form]=\"field\" [editMode]=\"true\"></lib-form-field-edit>\n </mat-expansion-panel>\n }\n </mat-accordion>\n }\n\n @if(!editMode()){\n <div>\n <button mat-fab class=\"form-action-button\" \n type=\"submit\" matTooltip=\"Save Group\" [disabled]=\"!form().valid\">\n <mat-icon>save</mat-icon>\n </button>\n <button mat-fab class=\"form-action-button\" \n type=\"button\" matTooltip=\"Cancel\" (click)=\"cancel()\">\n <mat-icon>cancel</mat-icon>\n </button> \n </div>\n}\n<form>" }]
1190
1235
  }] });
1191
1236
 
1192
1237
  class DynamicFormBuilderComponent {
1193
1238
  form = input.required(...(ngDevMode ? [{ debugName: "form" }] : []));
1194
1239
  handleSubmit = input(false, ...(ngDevMode ? [{ debugName: "handleSubmit" }] : []));
1195
1240
  submitted = output();
1196
- editingField = signal(-1, ...(ngDevMode ? [{ debugName: "editingField" }] : []));
1197
- creatingField = signal(false, ...(ngDevMode ? [{ debugName: "creatingField" }] : []));
1198
- editingGroup = signal(-1, ...(ngDevMode ? [{ debugName: "editingGroup" }] : []));
1199
- creatingGroup = signal(false, ...(ngDevMode ? [{ debugName: "creatingGroup" }] : []));
1200
1241
  dirty = signal(false, ...(ngDevMode ? [{ debugName: "dirty" }] : []));
1201
- formBuilder = inject(FormBuilder);
1242
+ fb = inject(FormBuilder);
1202
1243
  groupForm = null;
1203
1244
  addGroup() {
1204
- this.creatingGroup.set(true);
1205
- this.groupForm = FormGroupForm.createForm(this.formBuilder);
1206
- }
1207
- editGroup(id) {
1208
- this.editingGroup.set(id);
1209
- this.groupForm = this.form().groups.controls[id];
1210
- }
1211
- deleteGroup(id) {
1212
- this.form().deleteGroup(id);
1213
- this.dirty.set(true);
1214
- this.reset();
1245
+ this.groupForm = FormGroupForm.createForm(this.fb);
1215
1246
  }
1216
- submitGroup() {
1217
- if (this.creatingGroup() && this.groupForm) {
1247
+ createGroup() {
1248
+ if (this.groupForm) {
1218
1249
  this.form().createGroup(this.groupForm);
1219
1250
  }
1220
- this.dirty.set(true);
1221
- this.reset();
1222
- }
1223
- cancel() {
1224
- this.reset();
1251
+ this.groupForm = null;
1225
1252
  }
1226
- reset() {
1253
+ cancelGroup() {
1227
1254
  this.groupForm = null;
1228
- this.creatingGroup.set(false);
1229
- this.editingGroup.set(-1);
1230
1255
  }
1231
1256
  onSubmit() {
1232
1257
  this.submitted.emit();
1233
1258
  this.dirty.set(false);
1234
1259
  }
1260
+ deleteGroup(id) {
1261
+ this.form().deleteGroup(id);
1262
+ this.dirty.set(true);
1263
+ }
1264
+ onOrderUp(id) {
1265
+ this.form().orderUp(id);
1266
+ this.dirty.set(true);
1267
+ }
1268
+ onOrderDown(id) {
1269
+ this.form().orderDown(id);
1270
+ this.dirty.set(true);
1271
+ }
1272
+ getLabel(control) {
1273
+ const form = control;
1274
+ if (form.value.label) {
1275
+ return form.value.label;
1276
+ }
1277
+ else {
1278
+ return "Group " + form.value.order.toString();
1279
+ }
1280
+ }
1235
1281
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: DynamicFormBuilderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1236
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: DynamicFormBuilderComponent, isStandalone: true, selector: "lib-dynamic-form-builder", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null }, handleSubmit: { classPropertyName: "handleSubmit", publicName: "handleSubmit", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { submitted: "submitted" }, ngImport: i0, template: "<h2>Groups</h2>\n\n@if(groupForm)\n{\n<lib-form-group-edit [form]=\"groupForm\" [create]=\"creatingGroup()\" (cancelled)=\"cancel()\" (submitted)=\"submitGroup()\">\n</lib-form-group-edit>\n}\n@else {\n<lib-form-group-list [form]=\"form().groups\" (edit)=\"editGroup($event)\" (add)=\"addGroup()\"\n (delete)=\"deleteGroup($event)\"></lib-form-group-list>\n}\n\n@if(handleSubmit() && dirty())\n{\n <div>\n <button mat-fab class=\"form-action-button\" \n type=\"button\" matTooltip=\"Save Changes\" (click)=\"onSubmit()\">\n <mat-icon>save</mat-icon>\n </button>\n </div>\n}", styles: [""], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: FormGroupEditComponent, selector: "lib-form-group-edit", inputs: ["create", "form"], outputs: ["cancelled", "submitted"] }, { kind: "component", type: FormGroupListComponent, selector: "lib-form-group-list", inputs: ["form"], outputs: ["edit", "delete", "orderUp", "orderDown", "add"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
1282
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: DynamicFormBuilderComponent, isStandalone: true, selector: "lib-dynamic-form-builder", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null }, handleSubmit: { classPropertyName: "handleSubmit", publicName: "handleSubmit", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { submitted: "submitted" }, ngImport: i0, template: "<h2>Groups</h2>\n\n\n@if(groupForm)\n{\n<lib-form-group-edit [form]=\"groupForm\" (cancelled)=\"cancelGroup()\" (submitted)=\"createGroup()\"></lib-form-group-edit>\n}\n@else{\n\n<button mat-fab class=\"form-action-button\" (click)=\"addGroup()\" matTooltip=\"Add a Group\" type=\"button\">\n <mat-icon>add</mat-icon>\n</button>\n\n@if (form().groups.length > 0){\n\n<mat-accordion style=\"width:100%\">\n\n @for(group of form().groups.controls; track group; let group_idx=$index)\n {\n <mat-expansion-panel style=\"width:100%\">\n <mat-expansion-panel-header class=\"expansion-panel\">\n <mat-panel-title>{{getLabel(group)}}</mat-panel-title>\n <div class=\"expansion-panel-controls\">\n <button mat-icon-button type=\"button\" class=\"control-button\" color=\"primary\" matTooltip=\"Delete the Group\" aria-label=\"Delete an item\"\n (click)=\"deleteGroup(group_idx)\">\n <mat-icon>delete\n </mat-icon>\n </button>\n @if(group_idx>0){\n <button mat-icon-button class=\"control-button\" type=\"button\" color=\"primary\" matTooltip=\"Move Order Up\" aria-label=\"Move Order Up\"\n (click)=\"onOrderUp(group_idx)\">\n <mat-icon>arrow_upward\n </mat-icon>\n </button>\n }\n @if(group_idx < form().groups.controls.length - 1){\n <button mat-icon-button class=\"control-button\" type=\"button\" color=\"primary\" matTooltip=\"Move Order Down\" aria-label=\"Move Order Down\"\n (click)=\"onOrderDown(group_idx)\">\n <mat-icon>arrow_downward\n </mat-icon>\n </button>\n }\n </div>\n </mat-expansion-panel-header>\n <lib-form-group-edit [form]=\"group\" [editMode]=\"true\"></lib-form-group-edit>\n </mat-expansion-panel>\n }\n</mat-accordion>\n\n}\n\n@if(handleSubmit() && dirty())\n{\n <div>\n <button mat-fab class=\"form-action-button\" \n type=\"button\" matTooltip=\"Save Changes\" (click)=\"onSubmit()\">\n <mat-icon>save</mat-icon>\n </button>\n </div>\n}\n}", styles: [".expansion-panel-controls{display:none}.expansion-panel:hover .expansion-panel-controls{display:block}.control-button{margin-right:10px}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2$1.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "directive", type: i1$4.MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: i1$4.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i1$4.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i1$4.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "component", type: FormGroupEditComponent, selector: "lib-form-group-edit", inputs: ["form", "editMode"], outputs: ["submitted", "cancelled"] }] });
1237
1283
  }
1238
1284
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: DynamicFormBuilderComponent, decorators: [{
1239
1285
  type: Component,
1240
1286
  args: [{ selector: 'lib-dynamic-form-builder', imports: [
1241
1287
  MatIconModule,
1242
1288
  MatFormFieldModule,
1289
+ MatInputModule,
1243
1290
  ReactiveFormsModule,
1244
- MatButtonModule, FormGroupEditComponent, FormGroupListComponent, MatTooltipModule
1245
- ], template: "<h2>Groups</h2>\n\n@if(groupForm)\n{\n<lib-form-group-edit [form]=\"groupForm\" [create]=\"creatingGroup()\" (cancelled)=\"cancel()\" (submitted)=\"submitGroup()\">\n</lib-form-group-edit>\n}\n@else {\n<lib-form-group-list [form]=\"form().groups\" (edit)=\"editGroup($event)\" (add)=\"addGroup()\"\n (delete)=\"deleteGroup($event)\"></lib-form-group-list>\n}\n\n@if(handleSubmit() && dirty())\n{\n <div>\n <button mat-fab class=\"form-action-button\" \n type=\"button\" matTooltip=\"Save Changes\" (click)=\"onSubmit()\">\n <mat-icon>save</mat-icon>\n </button>\n </div>\n}" }]
1291
+ MatButtonModule,
1292
+ MatTooltipModule,
1293
+ MatExpansionModule,
1294
+ FormGroupEditComponent
1295
+ ], template: "<h2>Groups</h2>\n\n\n@if(groupForm)\n{\n<lib-form-group-edit [form]=\"groupForm\" (cancelled)=\"cancelGroup()\" (submitted)=\"createGroup()\"></lib-form-group-edit>\n}\n@else{\n\n<button mat-fab class=\"form-action-button\" (click)=\"addGroup()\" matTooltip=\"Add a Group\" type=\"button\">\n <mat-icon>add</mat-icon>\n</button>\n\n@if (form().groups.length > 0){\n\n<mat-accordion style=\"width:100%\">\n\n @for(group of form().groups.controls; track group; let group_idx=$index)\n {\n <mat-expansion-panel style=\"width:100%\">\n <mat-expansion-panel-header class=\"expansion-panel\">\n <mat-panel-title>{{getLabel(group)}}</mat-panel-title>\n <div class=\"expansion-panel-controls\">\n <button mat-icon-button type=\"button\" class=\"control-button\" color=\"primary\" matTooltip=\"Delete the Group\" aria-label=\"Delete an item\"\n (click)=\"deleteGroup(group_idx)\">\n <mat-icon>delete\n </mat-icon>\n </button>\n @if(group_idx>0){\n <button mat-icon-button class=\"control-button\" type=\"button\" color=\"primary\" matTooltip=\"Move Order Up\" aria-label=\"Move Order Up\"\n (click)=\"onOrderUp(group_idx)\">\n <mat-icon>arrow_upward\n </mat-icon>\n </button>\n }\n @if(group_idx < form().groups.controls.length - 1){\n <button mat-icon-button class=\"control-button\" type=\"button\" color=\"primary\" matTooltip=\"Move Order Down\" aria-label=\"Move Order Down\"\n (click)=\"onOrderDown(group_idx)\">\n <mat-icon>arrow_downward\n </mat-icon>\n </button>\n }\n </div>\n </mat-expansion-panel-header>\n <lib-form-group-edit [form]=\"group\" [editMode]=\"true\"></lib-form-group-edit>\n </mat-expansion-panel>\n }\n</mat-accordion>\n\n}\n\n@if(handleSubmit() && dirty())\n{\n <div>\n <button mat-fab class=\"form-action-button\" \n type=\"button\" matTooltip=\"Save Changes\" (click)=\"onSubmit()\">\n <mat-icon>save</mat-icon>\n </button>\n </div>\n}\n}", styles: [".expansion-panel-controls{display:none}.expansion-panel:hover .expansion-panel-controls{display:block}.control-button{margin-right:10px}\n"] }]
1246
1296
  }] });
1247
1297
 
1248
1298
  class DynamicFormForm {
@@ -1256,6 +1306,29 @@ class DynamicFormForm {
1256
1306
  get groups() {
1257
1307
  return this.form.get('groups');
1258
1308
  }
1309
+ orderUp(id) {
1310
+ this.reorder(id, id - 1);
1311
+ }
1312
+ orderDown(id) {
1313
+ this.reorder(id, id + 1);
1314
+ }
1315
+ reorder(id, newIndex) {
1316
+ const current_group = this.groups.at(id);
1317
+ current_group.patchValue({ "order": newIndex });
1318
+ const swap_group = this.groups.at(newIndex);
1319
+ swap_group.patchValue({ "order": id });
1320
+ this.groups.removeAt(id);
1321
+ this.groups.insert(newIndex, current_group);
1322
+ }
1323
+ fieldOrderUp(group_id, id) {
1324
+ this.reorderField(group_id, id, id - 1);
1325
+ }
1326
+ fieldOrderDown(group_id, id) {
1327
+ this.reorderField(group_id, id, id + 1);
1328
+ }
1329
+ reorderField(group_id, id, newIndex) {
1330
+ FormGroupForm.reorderField(this.groups.at(group_id), id, newIndex);
1331
+ }
1259
1332
  createGroup(group) {
1260
1333
  group.patchValue({ order: this.groups.controls.length });
1261
1334
  this.groups.push(group);
@@ -1263,6 +1336,9 @@ class DynamicFormForm {
1263
1336
  deleteGroup(id) {
1264
1337
  this.groups.removeAt(id);
1265
1338
  }
1339
+ deleteField(group_id, field_id) {
1340
+ FormGroupForm.deleteField(this.groups.at(group_id), field_id);
1341
+ }
1266
1342
  reset() {
1267
1343
  this.form = this.fb.group({
1268
1344
  groups: this.fb.array([])
@@ -1291,6 +1367,80 @@ class DynamicFormForm {
1291
1367
  }
1292
1368
  }
1293
1369
 
1370
+ class FormFieldValueForm {
1371
+ static createForm(fb) {
1372
+ return fb.group({
1373
+ value: fb.control('', Validators.required),
1374
+ id: fb.control(-1),
1375
+ field: fb.control(-1)
1376
+ });
1377
+ }
1378
+ static fromItem(item, builder) {
1379
+ const form = this.createForm(builder);
1380
+ this.setValue(form, item);
1381
+ return form;
1382
+ }
1383
+ static setValue(form, item) {
1384
+ let id = -1;
1385
+ if ('id' in item) {
1386
+ id = item.id;
1387
+ }
1388
+ form.setValue({
1389
+ value: item.value,
1390
+ field: item.field.id,
1391
+ id: id
1392
+ });
1393
+ }
1394
+ static createItem(form) {
1395
+ const value = form.value;
1396
+ return {
1397
+ value: value.value || "",
1398
+ field: value.field || -1,
1399
+ asset: null
1400
+ };
1401
+ }
1402
+ static updateItem(form, item) {
1403
+ const value = form.value;
1404
+ item.value = value.value || "";
1405
+ return item;
1406
+ }
1407
+ }
1408
+
1409
+ class PopulatedFormForm {
1410
+ fb = inject(FormBuilder);
1411
+ form;
1412
+ constructor() {
1413
+ this.form = this.fb.group({
1414
+ values: this.fb.array([])
1415
+ });
1416
+ }
1417
+ get values() {
1418
+ return this.form.get('values');
1419
+ }
1420
+ reset() {
1421
+ this.form = this.fb.group({
1422
+ groups: this.fb.array([])
1423
+ });
1424
+ }
1425
+ setValue(item) {
1426
+ this.values.clear();
1427
+ item.values.map(v => this.values.push(FormFieldValueForm.fromItem(v, this.fb)));
1428
+ }
1429
+ createItem() {
1430
+ return {
1431
+ values: Array.from(this.values.controls.map(v => FormFieldValueForm.createItem(v)))
1432
+ };
1433
+ }
1434
+ updateValue(form, items) {
1435
+ const matching_item = items.find(item => "id" in item && item.id == form.value.id);
1436
+ return FormFieldValueForm.updateItem(form, matching_item);
1437
+ }
1438
+ updateItem(item) {
1439
+ item.values = Array.from(this.values.controls.map(f => this.updateValue(f, item.values)));
1440
+ return item;
1441
+ }
1442
+ }
1443
+
1294
1444
  class SelectTableComponent {
1295
1445
  itemType = input("", ...(ngDevMode ? [{ debugName: "itemType" }] : []));
1296
1446
  selected = input([], ...(ngDevMode ? [{ debugName: "selected" }] : []));
@@ -1317,7 +1467,7 @@ class SelectTableComponent {
1317
1467
  this.table()?.renderRows();
1318
1468
  }
1319
1469
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: SelectTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1320
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: SelectTableComponent, isStandalone: true, selector: "lib-select-table", inputs: { itemType: { classPropertyName: "itemType", publicName: "itemType", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemAdded: "itemAdded", itemRemoved: "itemRemoved", searchChanged: "searchChanged" }, viewQueries: [{ propertyName: "table", first: true, predicate: MatTable, descendants: true, isSignal: true }], ngImport: i0, template: "<div class='select-container'>\n <div>\n <mat-form-field>\n <mat-label>Add {{itemType()}}</mat-label>\n <input \n type=\"text\"\n aria-label=\"Selected item\"\n matInput\n [formControl]=\"searchControl\" \n [matAutocomplete]=\"auto\">\n\n <mat-autocomplete #auto=\"matAutocomplete\">\n @for(item of options(); track item.item.id){\n <mat-option [value]=\"item.title\">{{item.title}}\n </mat-option>\n }\n </mat-autocomplete>\n </mat-form-field>\n\n <button mat-mini-fab type=\"button\" class=\"form_action_button\" (click)=\"add()\">\n <mat-icon>add\n </mat-icon>\n </button>\n </div>\n\n @if(selected().length > 0){\n <table mat-table [dataSource]=\"selected()\" class=\"mat-elevation-z8\">\n @for (column of columns(); track column.name) {\n <ng-container matColumnDef=\"{{ column.name }}\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>\n {{ column.title }}\n </th>\n <td mat-cell *matCellDef=\"let element\">{{ element[column.name] }}</td>\n </ng-container>\n }\n\n <ng-container matColumnDef=\"remove\">\n <th mat-header-cell *matHeaderCellDef>Remove\n </th>\n <td mat-cell *matCellDef=\"let element\">\n <button mat-icon-button\n color=\"primary\"\n aria-label=\"Remove an item\"\n (click)=\"remove(element.id)\">\n <mat-icon>remove\n </mat-icon>\n </button>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"columnNames()\">\n </tr>\n <tr mat-row *matRowDef=\"let row; columns: columnNames();\">\n </tr>\n </table>\n }\n</div>", styles: [".select-container,.table_container{display:flex;text-align:center;justify-content:center;flex-direction:column}.form_action_button{padding:5px;margin:5px}\n"], dependencies: [{ kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i1$5.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i1$5.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1$5.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i1$5.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1$5.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1$5.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i1$5.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1$5.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i1$5.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i1$5.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$3.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatAutocompleteModule }, { kind: "component", type: i6$1.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "directive", type: i6$1.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }] });
1470
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: SelectTableComponent, isStandalone: true, selector: "lib-select-table", inputs: { itemType: { classPropertyName: "itemType", publicName: "itemType", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemAdded: "itemAdded", itemRemoved: "itemRemoved", searchChanged: "searchChanged" }, viewQueries: [{ propertyName: "table", first: true, predicate: MatTable, descendants: true, isSignal: true }], ngImport: i0, template: "<div class='select-container'>\n <div>\n <mat-form-field>\n <mat-label>Add {{itemType()}}</mat-label>\n <input \n type=\"text\"\n aria-label=\"Selected item\"\n matInput\n [formControl]=\"searchControl\" \n [matAutocomplete]=\"auto\">\n\n <mat-autocomplete #auto=\"matAutocomplete\">\n @for(item of options(); track item.item.id){\n <mat-option [value]=\"item.title\">{{item.title}}\n </mat-option>\n }\n </mat-autocomplete>\n </mat-form-field>\n\n <button mat-mini-fab type=\"button\" class=\"form_action_button\" (click)=\"add()\">\n <mat-icon>add\n </mat-icon>\n </button>\n </div>\n\n @if(selected().length > 0){\n <table mat-table [dataSource]=\"selected()\" class=\"mat-elevation-z8\">\n @for (column of columns(); track column.name) {\n <ng-container matColumnDef=\"{{ column.name }}\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>\n {{ column.title }}\n </th>\n <td mat-cell *matCellDef=\"let element\">{{ element[column.name] }}</td>\n </ng-container>\n }\n\n <ng-container matColumnDef=\"remove\">\n <th mat-header-cell *matHeaderCellDef>Remove\n </th>\n <td mat-cell *matCellDef=\"let element\">\n <button mat-icon-button\n color=\"primary\"\n aria-label=\"Remove an item\"\n (click)=\"remove(element.id)\">\n <mat-icon>remove\n </mat-icon>\n </button>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"columnNames()\">\n </tr>\n <tr mat-row *matRowDef=\"let row; columns: columnNames();\">\n </tr>\n </table>\n }\n</div>", styles: [".select-container,.table_container{display:flex;text-align:center;justify-content:center;flex-direction:column}.form_action_button{padding:5px;margin:5px}\n"], dependencies: [{ kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i1$5.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i1$5.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1$5.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i1$5.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1$5.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1$5.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i1$5.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1$5.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i1$5.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i1$5.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatAutocompleteModule }, { kind: "component", type: i6$1.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "directive", type: i6$1.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }] });
1321
1471
  }
1322
1472
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: SelectTableComponent, decorators: [{
1323
1473
  type: Component,
@@ -1420,7 +1570,7 @@ class ListTableViewComponent {
1420
1570
  }));
1421
1571
  }
1422
1572
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: ListTableViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1423
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: ListTableViewComponent, isStandalone: true, selector: "lib-list-table-view", inputs: { itemType: { classPropertyName: "itemType", publicName: "itemType", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: false, transformFunction: null }, searchFilter: { classPropertyName: "searchFilter", publicName: "searchFilter", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "sort", first: true, predicate: MatSort, descendants: true, isSignal: true }, { propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true, isSignal: true }], ngImport: i0, template: "@if (dataSource(); as dataSource) {\n <table\n mat-table\n [dataSource]=\"dataSource\"\n matSort\n matSortActive=\"name\"\n matSortDisableClear\n matSortDirection=\"desc\"\n class=\"mat-elevation-z8\"\n >\n @for (column of columns(); track column.name) {\n <ng-container matColumnDef=\"{{ column.name }}\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>\n {{ column.title }}\n </th>\n <td mat-cell *matCellDef=\"let element\">{{ element[column.name] }}</td>\n </ng-container>\n }\n\n <tr mat-header-row *matHeaderRowDef=\"columnNames()\"></tr>\n <tr\n mat-row\n *matRowDef=\"let row; columns: columnNames()\"\n [routerLink]=\"['/' + itemType() + '/detail/', row.id]\"\n [routerLinkActive]=\"['is-active']\"\n ></tr>\n </table>\n\n <mat-paginator\n [length]=\"dataSource.length()\"\n [pageSize]=\"20\"\n [pageSizeOptions]=\"pageSizeOptions\"\n aria-label=\"Select page\"\n >\n </mat-paginator>\n}\n", styles: [".mat-mdc-row .mat-mdc-cell{border-bottom:1px solid transparent;border-top:1px solid transparent;cursor:pointer}.mat-mdc-row:hover .mat-mdc-cell{border-color:currentColor}.is-active{font-weight:700}\n"], dependencies: [{ kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i1$5.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i1$5.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1$5.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i1$5.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1$5.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1$5.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i1$5.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1$5.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i1$5.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i1$5.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i2$4.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatSortModule }, { kind: "directive", type: i3$1.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i3$1.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i1.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }] });
1573
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: ListTableViewComponent, isStandalone: true, selector: "lib-list-table-view", inputs: { itemType: { classPropertyName: "itemType", publicName: "itemType", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: false, transformFunction: null }, searchFilter: { classPropertyName: "searchFilter", publicName: "searchFilter", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "sort", first: true, predicate: MatSort, descendants: true, isSignal: true }, { propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true, isSignal: true }], ngImport: i0, template: "@if (dataSource(); as dataSource) {\n <table\n mat-table\n [dataSource]=\"dataSource\"\n matSort\n matSortActive=\"name\"\n matSortDisableClear\n matSortDirection=\"desc\"\n class=\"mat-elevation-z8\"\n >\n @for (column of columns(); track column.name) {\n <ng-container matColumnDef=\"{{ column.name }}\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>\n {{ column.title }}\n </th>\n <td mat-cell *matCellDef=\"let element\">{{ element[column.name] }}</td>\n </ng-container>\n }\n\n <tr mat-header-row *matHeaderRowDef=\"columnNames()\"></tr>\n <tr\n mat-row\n *matRowDef=\"let row; columns: columnNames()\"\n [routerLink]=\"['/' + itemType() + '/detail/', row.id]\"\n [routerLinkActive]=\"['is-active']\"\n ></tr>\n </table>\n\n <mat-paginator\n [length]=\"dataSource.length()\"\n [pageSize]=\"20\"\n [pageSizeOptions]=\"pageSizeOptions\"\n aria-label=\"Select page\"\n >\n </mat-paginator>\n}\n", styles: [".mat-mdc-row .mat-mdc-cell{border-bottom:1px solid transparent;border-top:1px solid transparent;cursor:pointer}.mat-mdc-row:hover .mat-mdc-cell{border-color:currentColor}.is-active{font-weight:700}\n"], dependencies: [{ kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i1$5.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i1$5.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1$5.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i1$5.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1$5.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1$5.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i1$5.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1$5.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i1$5.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i1$5.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i2$3.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatSortModule }, { kind: "directive", type: i3$1.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i3$1.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i1.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }] });
1424
1574
  }
1425
1575
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: ListTableViewComponent, decorators: [{
1426
1576
  type: Component,
@@ -1452,7 +1602,7 @@ class ListScrollViewComponent {
1452
1602
  data_source.reset(this.searchTerm(), this.pageSize());
1453
1603
  }
1454
1604
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: ListScrollViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1455
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.1.1", type: ListScrollViewComponent, isStandalone: true, selector: "lib-list-scroll-view", inputs: { searchTerm: { classPropertyName: "searchTerm", publicName: "searchTerm", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: false, transformFunction: null }, listItemTemplate: { classPropertyName: "listItemTemplate", publicName: "listItemTemplate", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<mat-nav-list>\n <cdk-virtual-scroll-viewport\n itemSize=\"150\"\n class=\"scrollable-list\"\n style=\"height: 600px; width: 500px\"\n >\n <ng-container *cdkVirtualFor=\"let item of dataSource()\">\n <ng-container\n *ngTemplateOutlet=\"listItemTemplate(); context: { item: item }\"\n >\n </ng-container>\n </ng-container>\n </cdk-virtual-scroll-viewport>\n</mat-nav-list>\n", styles: [":host{flex-grow:1}.mat-mdc-row .mat-mdc-cell{border-bottom:1px solid transparent;border-top:1px solid transparent;cursor:pointer}.mat-mdc-row:hover .mat-mdc-cell{border-color:currentColor}.is-active{font-weight:700}\n"], dependencies: [{ kind: "ngmodule", type: MatListModule }, { kind: "component", type: i2$2.MatNavList, selector: "mat-nav-list", exportAs: ["matNavList"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i2$5.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i2$5.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i2$5.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }] });
1605
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.1.1", type: ListScrollViewComponent, isStandalone: true, selector: "lib-list-scroll-view", inputs: { searchTerm: { classPropertyName: "searchTerm", publicName: "searchTerm", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: false, transformFunction: null }, listItemTemplate: { classPropertyName: "listItemTemplate", publicName: "listItemTemplate", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<mat-nav-list>\n <cdk-virtual-scroll-viewport\n itemSize=\"150\"\n class=\"scrollable-list\"\n style=\"height: 600px; width: 500px\"\n >\n <ng-container *cdkVirtualFor=\"let item of dataSource()\">\n <ng-container\n *ngTemplateOutlet=\"listItemTemplate(); context: { item: item }\"\n >\n </ng-container>\n </ng-container>\n </cdk-virtual-scroll-viewport>\n</mat-nav-list>\n", styles: [":host{flex-grow:1}.mat-mdc-row .mat-mdc-cell{border-bottom:1px solid transparent;border-top:1px solid transparent;cursor:pointer}.mat-mdc-row:hover .mat-mdc-cell{border-color:currentColor}.is-active{font-weight:700}\n"], dependencies: [{ kind: "ngmodule", type: MatListModule }, { kind: "component", type: i2$2.MatNavList, selector: "mat-nav-list", exportAs: ["matNavList"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i2$4.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i2$4.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i2$4.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }] });
1456
1606
  }
1457
1607
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: ListScrollViewComponent, decorators: [{
1458
1608
  type: Component,
@@ -1467,7 +1617,7 @@ class BackButtonComponent {
1467
1617
  this.location.back();
1468
1618
  }
1469
1619
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: BackButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1470
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.1", type: BackButtonComponent, isStandalone: true, selector: "lib-back-button", ngImport: i0, template: "<a mat-icon-button class=\"padded-button\"\n (click)=\"goBack()\"\n (keydown)=\"goBack()\"\n tabindex=\"0\"\n role=\"button\">\n<mat-icon>arrow_back</mat-icon>\n</a>\n\n", styles: [".padded-button{margin:5px}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }] });
1620
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.1", type: BackButtonComponent, isStandalone: true, selector: "lib-back-button", ngImport: i0, template: "<a mat-icon-button class=\"padded-button\"\n (click)=\"goBack()\"\n (keydown)=\"goBack()\"\n tabindex=\"0\"\n role=\"button\">\n<mat-icon>arrow_back</mat-icon>\n</a>\n\n", styles: [".padded-button{margin:5px}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }] });
1471
1621
  }
1472
1622
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: BackButtonComponent, decorators: [{
1473
1623
  type: Component,
@@ -1492,7 +1642,7 @@ class SearchBarComponent {
1492
1642
  this.searchChanged.emit(this.searchFilter.value);
1493
1643
  }
1494
1644
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: SearchBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1495
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: SearchBarComponent, isStandalone: true, selector: "lib-search-bar", inputs: { itemType: { classPropertyName: "itemType", publicName: "itemType", isSignal: true, isRequired: false, transformFunction: null }, sortFields: { classPropertyName: "sortFields", publicName: "sortFields", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { searchChanged: "searchChanged" }, ngImport: i0, template: "<div class=\"container\">\n <mat-form-field class=\"search\" style=\"margin: 10px;\">\n <mat-label>Search</mat-label>\n <input matInput [formControl]=\"searchFilter\" placeholder=\"Search {{ itemType() | titlecase }}\" />\n\n @if(searchFilter.value){\n <button matSuffix mat-icon-button aria-label=\"Cancel\" (click)=\"clearSearch()\">\n <mat-icon>cancel</mat-icon>\n </button>\n }\n @else(){\n <button matSuffix mat-icon-button aria-label=\"Search\">\n <mat-icon>search</mat-icon>\n </button>\n }\n </mat-form-field>\n\n @if(sortFields().length > 0){\n <mat-form-field style=\"margin: 10px\">\n <mat-label>Sort By</mat-label>\n <mat-select>\n @for(field of sortFields(); track field)\n {\n <mat-option>{{field}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n\n <button mat-icon-button aria-label=\"Sort Order\" matTooltip=\"Toggle sort order\">\n <mat-icon>sort</mat-icon>\n </button>\n }\n</div>", styles: [".container{width:100%;display:flex;flex-wrap:wrap;flex-direction:row;align-items:center;justify-content:center}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i2$3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$3.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: TitleCasePipe, name: "titlecase" }] });
1645
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: SearchBarComponent, isStandalone: true, selector: "lib-search-bar", inputs: { itemType: { classPropertyName: "itemType", publicName: "itemType", isSignal: true, isRequired: false, transformFunction: null }, sortFields: { classPropertyName: "sortFields", publicName: "sortFields", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { searchChanged: "searchChanged" }, ngImport: i0, template: "<div class=\"container\">\n <mat-form-field class=\"search\" style=\"margin: 10px;\">\n <mat-label>Search</mat-label>\n <input matInput [formControl]=\"searchFilter\" placeholder=\"Search {{ itemType() | titlecase }}\" />\n\n @if(searchFilter.value){\n <button matSuffix mat-icon-button aria-label=\"Cancel\" (click)=\"clearSearch()\">\n <mat-icon>cancel</mat-icon>\n </button>\n }\n @else(){\n <button matSuffix mat-icon-button aria-label=\"Search\">\n <mat-icon>search</mat-icon>\n </button>\n }\n </mat-form-field>\n\n @if(sortFields().length > 0){\n <mat-form-field style=\"margin: 10px\">\n <mat-label>Sort By</mat-label>\n <mat-select>\n @for(field of sortFields(); track field)\n {\n <mat-option>{{field}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n\n <button mat-icon-button aria-label=\"Sort Order\" matTooltip=\"Toggle sort order\">\n <mat-icon>sort</mat-icon>\n </button>\n }\n</div>", styles: [".container{width:100%;display:flex;flex-wrap:wrap;flex-direction:row;align-items:center;justify-content:center}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: TitleCasePipe, name: "titlecase" }] });
1496
1646
  }
1497
1647
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: SearchBarComponent, decorators: [{
1498
1648
  type: Component,
@@ -1517,10 +1667,12 @@ class ListDataSource extends DataSource {
1517
1667
  itemService;
1518
1668
  subscription = new Subscription();
1519
1669
  fetchedPages = new Set();
1520
- constructor(itemService, consumerType = "table") {
1670
+ defaultQueries = [];
1671
+ constructor(itemService, consumerType = "table", defaultQueries = []) {
1521
1672
  super();
1522
1673
  this.itemService = itemService;
1523
1674
  this.consumerType = consumerType;
1675
+ this.defaultQueries = defaultQueries;
1524
1676
  }
1525
1677
  connect(collectionViewer) {
1526
1678
  if (!this.hasTableConsumer()) {
@@ -1552,8 +1704,11 @@ class ListDataSource extends DataSource {
1552
1704
  return;
1553
1705
  }
1554
1706
  this.fetchedPages.add(idx);
1707
+ const queries = new Map([]);
1708
+ this.defaultQueries.forEach(q => queries.set(q.key, q.value));
1555
1709
  this.fetch(new ItemQuery({ page: idx + 1,
1556
1710
  page_size: this.pageSize(),
1711
+ queries: queries,
1557
1712
  filter: this.searchTerm() }));
1558
1713
  }
1559
1714
  fetch(query) {
@@ -1587,6 +1742,7 @@ class ListViewComponent {
1587
1742
  noSelfItemsMessage = input(...(ngDevMode ? [undefined, { debugName: "noSelfItemsMessage" }] : []));
1588
1743
  noItemsCanCreateMessage = input(...(ngDevMode ? [undefined, { debugName: "noItemsCanCreateMessage" }] : []));
1589
1744
  noItemsMessage = input(...(ngDevMode ? [undefined, { debugName: "noItemsMessage" }] : []));
1745
+ defaultQueries = input([], ...(ngDevMode ? [{ debugName: "defaultQueries" }] : []));
1590
1746
  selectedViewType = signal("table", ...(ngDevMode ? [{ debugName: "selectedViewType" }] : []));
1591
1747
  pageSize = 20;
1592
1748
  pageSizeOptions = [20, 50, 100];
@@ -1632,7 +1788,7 @@ class ListViewComponent {
1632
1788
  resetDataSource() {
1633
1789
  const item_service = this.itemService();
1634
1790
  if (item_service) {
1635
- this.dataSource = new ListDataSource(item_service, this.selectedViewType());
1791
+ this.dataSource = new ListDataSource(item_service, this.selectedViewType(), this.defaultQueries());
1636
1792
  }
1637
1793
  this.reset();
1638
1794
  }
@@ -1643,7 +1799,6 @@ class ListViewComponent {
1643
1799
  }
1644
1800
  viewChanged(event) {
1645
1801
  this.selectedViewType.set(event.value);
1646
- console.log(this.selectedViewType());
1647
1802
  this.resetDataSource();
1648
1803
  }
1649
1804
  isSelfList() {
@@ -1651,7 +1806,7 @@ class ListViewComponent {
1651
1806
  return (url_segments.length == 2) && (url_segments[1].path == "self");
1652
1807
  }
1653
1808
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: ListViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1654
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: ListViewComponent, isStandalone: true, selector: "lib-list-view", inputs: { viewType: { classPropertyName: "viewType", publicName: "viewType", isSignal: true, isRequired: false, transformFunction: null }, itemService: { classPropertyName: "itemService", publicName: "itemService", isSignal: true, isRequired: false, transformFunction: null }, itemDetailTemplate: { classPropertyName: "itemDetailTemplate", publicName: "itemDetailTemplate", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, sortFields: { classPropertyName: "sortFields", publicName: "sortFields", isSignal: true, isRequired: false, transformFunction: null }, noSelfItemsMessage: { classPropertyName: "noSelfItemsMessage", publicName: "noSelfItemsMessage", isSignal: true, isRequired: false, transformFunction: null }, noItemsCanCreateMessage: { classPropertyName: "noItemsCanCreateMessage", publicName: "noItemsCanCreateMessage", isSignal: true, isRequired: false, transformFunction: null }, noItemsMessage: { classPropertyName: "noItemsMessage", publicName: "noItemsMessage", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "sort", first: true, predicate: MatSort, descendants: true, isSignal: true }], ngImport: i0, template: "<lib-back-button></lib-back-button>\n\n<div class=\"container\">\n <div class=\"header\">\n <h1 class=\"title\">{{ title() | titlecase }}</h1>\n\n @if (canCreate()) {\n <div class=\"button-container\">\n <a mat-fab class=\"padded-button\" aria-label=\"Add new item\" matTooltip=\"Add new item\" [routerLink]=\"['create']\">\n <mat-icon>add</mat-icon></a>\n </div>\n }\n </div>\n\n @if(dataSource)\n {\n <div class=\"controls\" [hidden]=\"dataSource.sourceIsEmpty()\">\n <lib-search-bar [itemType]=\"title()\" [sortFields]=\"sortFields()\"\n (searchChanged)=\"onSearchChange($event)\"></lib-search-bar>\n\n @if(itemDetailTemplate()){\n <div style=\"margin: 10px\">\n <mat-button-toggle-group name=\"viewType\" aria-label=\"View Type\" [value]=\"selectedViewType()\"\n (change)=\"viewChanged($event)\">\n\n <mat-button-toggle value=\"table\" matTooltip=\"Show as table\">\n <mat-icon>table_view</mat-icon>\n </mat-button-toggle>\n\n <mat-button-toggle value=\"scroll\" matTooltip=\"Show as list\">\n <mat-icon>list</mat-icon>\n </mat-button-toggle>\n\n </mat-button-toggle-group>\n </div>\n }\n </div>\n\n @if (dataSource.loading()) {\n <div class=\"spinner-container\">\n <mat-spinner></mat-spinner>\n </div>\n }\n\n <div [hidden]=\"!dataSource.sourceIsEmpty()\">\n @if(isSelfList())\n {\n @if(noSelfItemsMessage())\n {\n <p>{{noSelfItemsMessage()}}</p>\n }\n @else {\n <p>You do not have any {{itemType()}}.</p> \n }\n }\n @else{\n @if(canCreate()){\n @if(noItemsCanCreateMessage())\n {\n <p>{{noItemsCanCreateMessage()}}</p>\n }\n @else{\n <p>There are currently no {{itemType()}}, click above to add one.</p>\n }\n }\n @else{\n @if(noItemsMessage())\n {\n <p>{{noItemsMessage()}}</p>\n }\n @else\n {\n <p>There are currently no {{itemType()}}.</p>\n }\n }\n }\n </div>\n\n <div [hidden]=\"dataSource.sourceIsEmpty()\">\n @if(isTableView()) {\n <lib-list-table-view [itemType]=\"itemType()\" [columns]=\"columns()\" [dataSource]=\"dataSource\">\n </lib-list-table-view>\n } \n @else {\n <lib-list-scroll-view [listItemTemplate]=\"itemDetailTemplate()\" [dataSource]=\"dataSource\"></lib-list-scroll-view>\n }\n\n </div>\n }\n</div>", styles: [":host{flex-grow:1}.container{display:flex;padding:10px;flex-direction:column;justify-content:center;text-align:center;align-items:center}.header{display:flex;flex-direction:row;align-items:center;justify-content:center}.title{text-align:center;padding:10px}.controls{display:flex;align-items:center;justify-content:center;flex-wrap:wrap}.hide-element{display:none}\n"], dependencies: [{ kind: "component", type: ListTableViewComponent, selector: "lib-list-table-view", inputs: ["itemType", "columns", "dataSource", "searchFilter"] }, { kind: "component", type: ListScrollViewComponent, selector: "lib-list-scroll-view", inputs: ["searchTerm", "pageSize", "dataSource", "listItemTemplate"] }, { kind: "component", type: BackButtonComponent, selector: "lib-back-button" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i1$6.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i1$6.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i2$6.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: SearchBarComponent, selector: "lib-search-bar", inputs: ["itemType", "sortFields"], outputs: ["searchChanged"] }, { kind: "pipe", type: TitleCasePipe, name: "titlecase" }] });
1809
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: ListViewComponent, isStandalone: true, selector: "lib-list-view", inputs: { viewType: { classPropertyName: "viewType", publicName: "viewType", isSignal: true, isRequired: false, transformFunction: null }, itemService: { classPropertyName: "itemService", publicName: "itemService", isSignal: true, isRequired: false, transformFunction: null }, itemDetailTemplate: { classPropertyName: "itemDetailTemplate", publicName: "itemDetailTemplate", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, sortFields: { classPropertyName: "sortFields", publicName: "sortFields", isSignal: true, isRequired: false, transformFunction: null }, noSelfItemsMessage: { classPropertyName: "noSelfItemsMessage", publicName: "noSelfItemsMessage", isSignal: true, isRequired: false, transformFunction: null }, noItemsCanCreateMessage: { classPropertyName: "noItemsCanCreateMessage", publicName: "noItemsCanCreateMessage", isSignal: true, isRequired: false, transformFunction: null }, noItemsMessage: { classPropertyName: "noItemsMessage", publicName: "noItemsMessage", isSignal: true, isRequired: false, transformFunction: null }, defaultQueries: { classPropertyName: "defaultQueries", publicName: "defaultQueries", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "sort", first: true, predicate: MatSort, descendants: true, isSignal: true }], ngImport: i0, template: "<lib-back-button></lib-back-button>\n\n<div class=\"container\">\n <div class=\"header\">\n <h1 class=\"title\">{{ title() | titlecase }}</h1>\n\n @if (canCreate()) {\n <div class=\"button-container\">\n <a mat-fab class=\"padded-button\" aria-label=\"Add new item\" matTooltip=\"Add new item\" [routerLink]=\"['create']\">\n <mat-icon>add</mat-icon></a>\n </div>\n }\n </div>\n\n @if(dataSource)\n {\n <div class=\"controls\" [hidden]=\"dataSource.sourceIsEmpty()\">\n <lib-search-bar [itemType]=\"title()\" [sortFields]=\"sortFields()\"\n (searchChanged)=\"onSearchChange($event)\"></lib-search-bar>\n\n @if(itemDetailTemplate()){\n <div style=\"margin: 10px\">\n <mat-button-toggle-group name=\"viewType\" aria-label=\"View Type\" [value]=\"selectedViewType()\"\n (change)=\"viewChanged($event)\">\n\n <mat-button-toggle value=\"table\" matTooltip=\"Show as table\">\n <mat-icon>table_view</mat-icon>\n </mat-button-toggle>\n\n <mat-button-toggle value=\"scroll\" matTooltip=\"Show as list\">\n <mat-icon>list</mat-icon>\n </mat-button-toggle>\n\n </mat-button-toggle-group>\n </div>\n }\n </div>\n\n @if (dataSource.loading()) {\n <div class=\"spinner-container\">\n <mat-spinner></mat-spinner>\n </div>\n }\n\n <div [hidden]=\"!dataSource.sourceIsEmpty()\">\n @if(isSelfList())\n {\n @if(noSelfItemsMessage())\n {\n <p>{{noSelfItemsMessage()}}</p>\n }\n @else {\n <p>You do not have any {{itemType()}}.</p> \n }\n }\n @else{\n @if(canCreate()){\n @if(noItemsCanCreateMessage())\n {\n <p>{{noItemsCanCreateMessage()}}</p>\n }\n @else{\n <p>There are currently no {{itemType()}}, click above to add one.</p>\n }\n }\n @else{\n @if(noItemsMessage())\n {\n <p>{{noItemsMessage()}}</p>\n }\n @else\n {\n <p>There are currently no {{itemType()}}.</p>\n }\n }\n }\n </div>\n\n <div [hidden]=\"dataSource.sourceIsEmpty()\">\n @if(isTableView()) {\n <lib-list-table-view [itemType]=\"itemType()\" [columns]=\"columns()\" [dataSource]=\"dataSource\">\n </lib-list-table-view>\n } \n @else {\n <lib-list-scroll-view [listItemTemplate]=\"itemDetailTemplate()\" [dataSource]=\"dataSource\"></lib-list-scroll-view>\n }\n\n </div>\n }\n</div>", styles: [":host{flex-grow:1}.container{display:flex;padding:10px;flex-direction:column;justify-content:center;text-align:center;align-items:center}.header{display:flex;flex-direction:row;align-items:center;justify-content:center}.title{text-align:center;padding:10px}.controls{display:flex;align-items:center;justify-content:center;flex-wrap:wrap}.hide-element{display:none}\n"], dependencies: [{ kind: "component", type: ListTableViewComponent, selector: "lib-list-table-view", inputs: ["itemType", "columns", "dataSource", "searchFilter"] }, { kind: "component", type: ListScrollViewComponent, selector: "lib-list-scroll-view", inputs: ["searchTerm", "pageSize", "dataSource", "listItemTemplate"] }, { kind: "component", type: BackButtonComponent, selector: "lib-back-button" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i1$6.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i1$6.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i2$5.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: SearchBarComponent, selector: "lib-search-bar", inputs: ["itemType", "sortFields"], outputs: ["searchChanged"] }, { kind: "pipe", type: TitleCasePipe, name: "titlecase" }] });
1655
1810
  }
1656
1811
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: ListViewComponent, decorators: [{
1657
1812
  type: Component,
@@ -1683,7 +1838,7 @@ class DetailHeaderComponent {
1683
1838
  this.deleteClicked.emit();
1684
1839
  }
1685
1840
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: DetailHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1686
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: DetailHeaderComponent, isStandalone: true, selector: "lib-detail-header", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: false, transformFunction: null }, route: { classPropertyName: "route", publicName: "route", isSignal: true, isRequired: false, transformFunction: null }, canEdit: { classPropertyName: "canEdit", publicName: "canEdit", isSignal: true, isRequired: false, transformFunction: null }, canDelete: { classPropertyName: "canDelete", publicName: "canDelete", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { deleteClicked: "deleteClicked" }, ngImport: i0, template: "<div class=\"container\">\n\n <h1 class=\"header\">{{text()}}</h1>\n\n <div class=\"controls\">\n @if(canEdit()){\n <a mat-mini-fab class=\"control-button\" matTooltip=\"Edit the item\" title=\"Click to edit this item\" aria-label=\"Click to edit this item\"\n [routerLink]=\"[fullRoute(), id()]\">\n <mat-icon>edit</mat-icon>\n </a>\n }\n\n @if(canDelete()){\n <button mat-mini-fab class=\"control-button\" (click)=\"deleteClick()\" matTooltip=\"Delete the item\" title=\"Click to delete this item\"\n aria-label=\"Click to delete this item\">\n <mat-icon>delete</mat-icon></button>\n }\n </div>\n\n</div>", styles: [".container{width:100%;max-width:500px;padding:5px}.header{width:100%;padding:5px;margin:5px}.controls{display:flex;flex-direction:row;align-content:center;justify-content:center}.control-button{padding:5px;margin:5px}\n"], dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
1841
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: DetailHeaderComponent, isStandalone: true, selector: "lib-detail-header", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: false, transformFunction: null }, route: { classPropertyName: "route", publicName: "route", isSignal: true, isRequired: false, transformFunction: null }, canEdit: { classPropertyName: "canEdit", publicName: "canEdit", isSignal: true, isRequired: false, transformFunction: null }, canDelete: { classPropertyName: "canDelete", publicName: "canDelete", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { deleteClicked: "deleteClicked" }, ngImport: i0, template: "<div class=\"container\">\n\n <h1 class=\"header\">{{text()}}</h1>\n\n <div class=\"controls\">\n @if(canEdit()){\n <a mat-mini-fab class=\"control-button\" matTooltip=\"Edit the item\" title=\"Click to edit this item\" aria-label=\"Click to edit this item\"\n [routerLink]=\"[fullRoute(), id()]\">\n <mat-icon>edit</mat-icon>\n </a>\n }\n\n @if(canDelete()){\n <button mat-mini-fab class=\"control-button\" (click)=\"deleteClick()\" matTooltip=\"Delete the item\" title=\"Click to delete this item\"\n aria-label=\"Click to delete this item\">\n <mat-icon>delete</mat-icon></button>\n }\n </div>\n\n</div>", styles: [".container{width:100%;max-width:500px;padding:5px}.header{width:100%;padding:5px;margin:5px}.controls{display:flex;flex-direction:row;align-content:center;justify-content:center}.control-button{padding:5px;margin:5px}\n"], dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
1687
1842
  }
1688
1843
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: DetailHeaderComponent, decorators: [{
1689
1844
  type: Component,
@@ -1721,30 +1876,39 @@ class UserDetailComponent extends DetailView {
1721
1876
  return super.canEdit();
1722
1877
  }
1723
1878
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: UserDetailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1724
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: UserDetailComponent, isStandalone: true, selector: "lib-user-detail", usesInheritance: true, ngImport: i0, template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n @if(item(); as item){\n <div class=\"item-detail-container\">\n\n <lib-detail-header\n [text]=\"item.username\"\n [id]=\"item.id\"\n [route]=\"itemService.typePlural()\"\n [canEdit]=\"canEdit()\"\n [canDelete]=\"canDelete()\"\n (onDelete)=\"onDelete()\"></lib-detail-header>\n\n @if(item.profile_url){\n <div class=\"image-holder\">\n <img alt=\"User Profile Image\" src=\"{{item.url}}{{item.profile_url}}\" style=\"height:120px;\">\n </div> \n }\n \n <div class=\"item-field\">\n <span><b>Email: </b></span>\n {{item.email}}\n </div>\n \n <div class=\"item-field\">\n <span><b>First Name: </b></span>\n {{item.first_name}}\n </div>\n \n <div class=\"item-field\">\n <span><b>Last Name: </b></span>\n {{item.last_name}}\n </div>\n \n </div>\n }\n</div>\n", styles: [":host{flex-grow:1}\n"], dependencies: [{ kind: "component", type: BackButtonComponent, selector: "lib-back-button" }, { kind: "component", type: DetailHeaderComponent, selector: "lib-detail-header", inputs: ["id", "text", "route", "canEdit", "canDelete"], outputs: ["deleteClicked"] }] });
1879
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: UserDetailComponent, isStandalone: true, selector: "lib-user-detail", usesInheritance: true, ngImport: i0, template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n @if(item(); as item){\n <div class=\"item-detail-container\">\n\n <lib-detail-header\n [text]=\"item.username\"\n [id]=\"item.id\"\n [route]=\"itemService.typePlural()\"\n [canEdit]=\"canEdit()\"\n [canDelete]=\"canDelete()\"\n (onDelete)=\"onDelete()\"></lib-detail-header>\n\n @if(item.profile){\n <div class=\"image-holder\">\n <img alt=\"User Profile Image\" src=\"{{item.profile}}\" style=\"height:120px;\">\n </div> \n }\n \n <div class=\"item-field\">\n <span><b>Email: </b></span>\n {{item.email}}\n </div>\n \n <div class=\"item-field\">\n <span><b>First Name: </b></span>\n {{item.first_name}}\n </div>\n \n <div class=\"item-field\">\n <span><b>Last Name: </b></span>\n {{item.last_name}}\n </div>\n \n </div>\n }\n</div>\n", styles: [":host{flex-grow:1}\n"], dependencies: [{ kind: "component", type: BackButtonComponent, selector: "lib-back-button" }, { kind: "component", type: DetailHeaderComponent, selector: "lib-detail-header", inputs: ["id", "text", "route", "canEdit", "canDelete"], outputs: ["deleteClicked"] }] });
1725
1880
  }
1726
1881
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: UserDetailComponent, decorators: [{
1727
1882
  type: Component,
1728
1883
  args: [{ selector: 'lib-user-detail', imports: [BackButtonComponent,
1729
- DetailHeaderComponent], template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n @if(item(); as item){\n <div class=\"item-detail-container\">\n\n <lib-detail-header\n [text]=\"item.username\"\n [id]=\"item.id\"\n [route]=\"itemService.typePlural()\"\n [canEdit]=\"canEdit()\"\n [canDelete]=\"canDelete()\"\n (onDelete)=\"onDelete()\"></lib-detail-header>\n\n @if(item.profile_url){\n <div class=\"image-holder\">\n <img alt=\"User Profile Image\" src=\"{{item.url}}{{item.profile_url}}\" style=\"height:120px;\">\n </div> \n }\n \n <div class=\"item-field\">\n <span><b>Email: </b></span>\n {{item.email}}\n </div>\n \n <div class=\"item-field\">\n <span><b>First Name: </b></span>\n {{item.first_name}}\n </div>\n \n <div class=\"item-field\">\n <span><b>Last Name: </b></span>\n {{item.last_name}}\n </div>\n \n </div>\n }\n</div>\n", styles: [":host{flex-grow:1}\n"] }]
1884
+ DetailHeaderComponent], template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n @if(item(); as item){\n <div class=\"item-detail-container\">\n\n <lib-detail-header\n [text]=\"item.username\"\n [id]=\"item.id\"\n [route]=\"itemService.typePlural()\"\n [canEdit]=\"canEdit()\"\n [canDelete]=\"canDelete()\"\n (onDelete)=\"onDelete()\"></lib-detail-header>\n\n @if(item.profile){\n <div class=\"image-holder\">\n <img alt=\"User Profile Image\" src=\"{{item.profile}}\" style=\"height:120px;\">\n </div> \n }\n \n <div class=\"item-field\">\n <span><b>Email: </b></span>\n {{item.email}}\n </div>\n \n <div class=\"item-field\">\n <span><b>First Name: </b></span>\n {{item.first_name}}\n </div>\n \n <div class=\"item-field\">\n <span><b>Last Name: </b></span>\n {{item.last_name}}\n </div>\n \n </div>\n }\n</div>\n", styles: [":host{flex-grow:1}\n"] }]
1730
1885
  }], ctorParameters: () => [] });
1731
1886
 
1732
1887
  class UserForm {
1733
- formBuilder = inject(FormBuilder);
1734
- form = this.formBuilder.group({
1735
- username: [''],
1736
- email: [''],
1737
- first_name: [''],
1738
- last_name: [''],
1739
- phone: ['']
1888
+ fb = inject(FormBuilder);
1889
+ form = this.fb.group({
1890
+ username: this.fb.control('', Validators.required),
1891
+ email: this.fb.control('', Validators.required),
1892
+ first_name: this.fb.control(''),
1893
+ last_name: this.fb.control(''),
1894
+ phone: this.fb.control(''),
1895
+ profile: this.fb.control(UserForm.getDefaultProfile()),
1740
1896
  });
1897
+ static getDefaultProfile() {
1898
+ return { name: "profile", display_name: "Profile Image", file_type: "image", remote: "", local: "", file: null };
1899
+ }
1741
1900
  setValue(item) {
1901
+ const profile = UserForm.getDefaultProfile();
1902
+ if (item.profile) {
1903
+ profile.remote = item.profile;
1904
+ }
1742
1905
  this.form.setValue({
1743
1906
  username: item.username,
1744
1907
  email: item.email,
1745
1908
  first_name: item.first_name,
1746
1909
  last_name: item.last_name,
1747
- phone: item.phone
1910
+ phone: item.phone,
1911
+ profile: profile
1748
1912
  });
1749
1913
  }
1750
1914
  createItem() {
@@ -1769,49 +1933,18 @@ class UserForm {
1769
1933
  }
1770
1934
 
1771
1935
  class UserEditComponent extends EditView {
1772
- files = signal([new FileRecord({
1773
- name: "image",
1774
- display_name: "Profile Image",
1775
- file_type: "image"
1776
- })], ...(ngDevMode ? [{ debugName: "files" }] : []));
1936
+ fileKeys = ["profile"];
1777
1937
  constructor() {
1778
1938
  super(inject(UserService), new UserForm());
1779
1939
  }
1780
1940
  ngOnInit() {
1781
1941
  this.onInit();
1782
1942
  }
1783
- onItemAvailable(item) {
1784
- this.form.setValue(item);
1785
- if (item.profile_url) {
1786
- this.files.update(files => { const file = files.find(f => f.name === "image"); if (file) {
1787
- file.remote = item.url + item.profile_url;
1788
- } ; return files; });
1789
- }
1790
- super.onItemAvailable(item);
1791
- }
1792
- submit() {
1793
- this.item.update((item) => { if (item) {
1794
- item = this.form.updateItem(item);
1795
- } return item; });
1796
- super.submit();
1797
- }
1798
- onPreviewLoaded(preview) {
1799
- this.files.update(files => { const file = files.find(f => f.name === preview.name); if (file) {
1800
- file.local = preview.content;
1801
- } ; return files; });
1802
- }
1803
- onFileUploaded(upload) {
1804
- this.files.update(files => { const file = files.find(f => f.name === upload.name); if (file) {
1805
- file.file = upload.file;
1806
- } ; return files; });
1807
- }
1808
- saveFiles(item) {
1809
- this.files().forEach(record => { if (record.file) {
1810
- this.itemService.postFile(item.id, record.name, record.file).subscribe(item => this.onItemUpdated(item));
1811
- } ; });
1943
+ get profileControl() {
1944
+ return this.form.form.get('profile');
1812
1945
  }
1813
1946
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: UserEditComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1814
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.1", type: UserEditComponent, isStandalone: true, selector: "lib-user-edit", usesInheritance: true, ngImport: i0, template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n\n <div class=\"item-edit-container\">\n\n <h1 class=\"item-edit-header\">{{heading() | titlecase}}</h1>\n\n <form class=\"form-card\" [formGroup]=\"form.form\" (ngSubmit)=\"submit()\">\n <mat-form-field class=\"form-field-wide\">\n <mat-label>Username</mat-label>\n <input matInput\n placeholder=\"Username\"\n type=\"text\"\n formControlName=\"username\"\n name=\"username\">\n </mat-form-field>\n \n <mat-form-field class=\"form-field-wide\">\n <mat-label>Email</mat-label>\n <input matInput\n placeholder=\"Email\"\n type=\"text\"\n formControlName=\"email\"\n name=\"email\">\n </mat-form-field>\n\n <mat-form-field class=\"form-field\">\n <mat-label>First Name</mat-label>\n <input matInput\n placeholder=\"First Name\"\n type=\"text\"\n formControlName=\"first_name\"\n name=\"first_name\">\n </mat-form-field>\n \n <mat-form-field class=\"form-field\">\n <mat-label>Last Name</mat-label>\n <input matInput\n placeholder=\"Last Name\"\n type=\"text\"\n formControlName=\"last_name\"\n name=\"last_name\">\n </mat-form-field>\n\n <lib-file-upload [files]=\"files()\"\n (previewLoaded)=\"onPreviewLoaded($event)\"\n (fileUploaded)=\"onFileUploaded($event)\"></lib-file-upload>\n\n <div class=\"button_group\">\n <button mat-fab\n class=\"form_action_button\"\n type=\"submit\"\n [disabled]=\"!form.form.valid\">\n <mat-icon>save</mat-icon></button>\n \n <button mat-fab\n class=\"form_action_button\"\n type=\"button\"\n (click)=\"cancel()\">\n <mat-icon>cancel</mat-icon></button>\n </div> \n </form>\n </div>\n</div>\n", styles: [":host{flex-grow:1}.item_view{display:flex;justify-content:left;align-items:left;flex-direction:column}.checkbox_group{justify-content:left;display:flex;flex-direction:column}.button_group{margin:10px;display:flex;flex-direction:row;justify-content:center}.btn-block{padding:5px}.form_action_button{padding:5px;margin:5px}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: BackButtonComponent, selector: "lib-back-button" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i2$3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$3.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: FileUploadComponent, selector: "lib-file-upload", inputs: ["files"], outputs: ["previewLoaded", "fileUploaded", "clearLocal"] }, { kind: "pipe", type: TitleCasePipe, name: "titlecase" }] });
1947
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.1", type: UserEditComponent, isStandalone: true, selector: "lib-user-edit", usesInheritance: true, ngImport: i0, template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n\n <div class=\"item-edit-container\">\n\n <h1 class=\"item-edit-header\">{{heading() | titlecase}}</h1>\n\n <form class=\"form-card\" [formGroup]=\"form.form\" (ngSubmit)=\"submit()\">\n <mat-form-field class=\"form-field-wide\">\n <mat-label>Username</mat-label>\n <input matInput\n placeholder=\"Username\"\n type=\"text\"\n formControlName=\"username\"\n name=\"username\">\n </mat-form-field>\n \n <mat-form-field class=\"form-field-wide\">\n <mat-label>Email</mat-label>\n <input matInput\n placeholder=\"Email\"\n type=\"text\"\n formControlName=\"email\"\n name=\"email\">\n </mat-form-field>\n\n <mat-form-field class=\"form-field\">\n <mat-label>First Name</mat-label>\n <input matInput\n placeholder=\"First Name\"\n type=\"text\"\n formControlName=\"first_name\"\n name=\"first_name\">\n </mat-form-field>\n \n <mat-form-field class=\"form-field\">\n <mat-label>Last Name</mat-label>\n <input matInput\n placeholder=\"Last Name\"\n type=\"text\"\n formControlName=\"last_name\"\n name=\"last_name\">\n </mat-form-field>\n\n <lib-file-upload [control]=\"profileControl\"></lib-file-upload>\n\n <div class=\"button_group\">\n <button mat-fab\n class=\"form_action_button\"\n type=\"submit\"\n [disabled]=\"!form.form.valid\">\n <mat-icon>save</mat-icon></button>\n \n <button mat-fab\n class=\"form_action_button\"\n type=\"button\"\n (click)=\"cancel()\">\n <mat-icon>cancel</mat-icon></button>\n </div> \n </form>\n </div>\n</div>\n", styles: [":host{flex-grow:1}.item_view{display:flex;justify-content:left;align-items:left;flex-direction:column}.checkbox_group{justify-content:left;display:flex;flex-direction:column}.button_group{margin:10px;display:flex;flex-direction:row;justify-content:center}.btn-block{padding:5px}.form_action_button{padding:5px;margin:5px}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: BackButtonComponent, selector: "lib-back-button" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: FileUploadComponent, selector: "lib-file-upload", inputs: ["control"] }, { kind: "pipe", type: TitleCasePipe, name: "titlecase" }] });
1815
1948
  }
1816
1949
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: UserEditComponent, decorators: [{
1817
1950
  type: Component,
@@ -1824,18 +1957,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImpor
1824
1957
  MatIconModule,
1825
1958
  FileUploadComponent,
1826
1959
  TitleCasePipe
1827
- ], template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n\n <div class=\"item-edit-container\">\n\n <h1 class=\"item-edit-header\">{{heading() | titlecase}}</h1>\n\n <form class=\"form-card\" [formGroup]=\"form.form\" (ngSubmit)=\"submit()\">\n <mat-form-field class=\"form-field-wide\">\n <mat-label>Username</mat-label>\n <input matInput\n placeholder=\"Username\"\n type=\"text\"\n formControlName=\"username\"\n name=\"username\">\n </mat-form-field>\n \n <mat-form-field class=\"form-field-wide\">\n <mat-label>Email</mat-label>\n <input matInput\n placeholder=\"Email\"\n type=\"text\"\n formControlName=\"email\"\n name=\"email\">\n </mat-form-field>\n\n <mat-form-field class=\"form-field\">\n <mat-label>First Name</mat-label>\n <input matInput\n placeholder=\"First Name\"\n type=\"text\"\n formControlName=\"first_name\"\n name=\"first_name\">\n </mat-form-field>\n \n <mat-form-field class=\"form-field\">\n <mat-label>Last Name</mat-label>\n <input matInput\n placeholder=\"Last Name\"\n type=\"text\"\n formControlName=\"last_name\"\n name=\"last_name\">\n </mat-form-field>\n\n <lib-file-upload [files]=\"files()\"\n (previewLoaded)=\"onPreviewLoaded($event)\"\n (fileUploaded)=\"onFileUploaded($event)\"></lib-file-upload>\n\n <div class=\"button_group\">\n <button mat-fab\n class=\"form_action_button\"\n type=\"submit\"\n [disabled]=\"!form.form.valid\">\n <mat-icon>save</mat-icon></button>\n \n <button mat-fab\n class=\"form_action_button\"\n type=\"button\"\n (click)=\"cancel()\">\n <mat-icon>cancel</mat-icon></button>\n </div> \n </form>\n </div>\n</div>\n", styles: [":host{flex-grow:1}.item_view{display:flex;justify-content:left;align-items:left;flex-direction:column}.checkbox_group{justify-content:left;display:flex;flex-direction:column}.button_group{margin:10px;display:flex;flex-direction:row;justify-content:center}.btn-block{padding:5px}.form_action_button{padding:5px;margin:5px}\n"] }]
1960
+ ], template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n\n <div class=\"item-edit-container\">\n\n <h1 class=\"item-edit-header\">{{heading() | titlecase}}</h1>\n\n <form class=\"form-card\" [formGroup]=\"form.form\" (ngSubmit)=\"submit()\">\n <mat-form-field class=\"form-field-wide\">\n <mat-label>Username</mat-label>\n <input matInput\n placeholder=\"Username\"\n type=\"text\"\n formControlName=\"username\"\n name=\"username\">\n </mat-form-field>\n \n <mat-form-field class=\"form-field-wide\">\n <mat-label>Email</mat-label>\n <input matInput\n placeholder=\"Email\"\n type=\"text\"\n formControlName=\"email\"\n name=\"email\">\n </mat-form-field>\n\n <mat-form-field class=\"form-field\">\n <mat-label>First Name</mat-label>\n <input matInput\n placeholder=\"First Name\"\n type=\"text\"\n formControlName=\"first_name\"\n name=\"first_name\">\n </mat-form-field>\n \n <mat-form-field class=\"form-field\">\n <mat-label>Last Name</mat-label>\n <input matInput\n placeholder=\"Last Name\"\n type=\"text\"\n formControlName=\"last_name\"\n name=\"last_name\">\n </mat-form-field>\n\n <lib-file-upload [control]=\"profileControl\"></lib-file-upload>\n\n <div class=\"button_group\">\n <button mat-fab\n class=\"form_action_button\"\n type=\"submit\"\n [disabled]=\"!form.form.valid\">\n <mat-icon>save</mat-icon></button>\n \n <button mat-fab\n class=\"form_action_button\"\n type=\"button\"\n (click)=\"cancel()\">\n <mat-icon>cancel</mat-icon></button>\n </div> \n </form>\n </div>\n</div>\n", styles: [":host{flex-grow:1}.item_view{display:flex;justify-content:left;align-items:left;flex-direction:column}.checkbox_group{justify-content:left;display:flex;flex-direction:column}.button_group{margin:10px;display:flex;flex-direction:row;justify-content:center}.btn-block{padding:5px}.form_action_button{padding:5px;margin:5px}\n"] }]
1828
1961
  }], ctorParameters: () => [] });
1829
1962
 
1830
1963
  class UserListDetailComponent {
1831
- item = input(...(ngDevMode ? [undefined, { debugName: "item" }] : []));
1964
+ item = input.required(...(ngDevMode ? [{ debugName: "item" }] : []));
1965
+ ngOnInit() {
1966
+ console.log(this.item());
1967
+ }
1832
1968
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: UserListDetailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1833
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: UserListDetailComponent, isStandalone: true, selector: "lib-user-list-detail", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<mat-card mat-list-item class=\"item-card\">\n @if(item(); as item){\n <mat-card-header>\n <mat-card-title-group style=\"padding: 5px\">\n <mat-card-title\n >{{ item.first_name }} {{ item.last_name }}</mat-card-title\n >\n <mat-card-subtitle>{{ item.username }}</mat-card-subtitle>\n </mat-card-title-group>\n </mat-card-header>\n\n <mat-card-content>\n <p>Email: {{ item.email }}</p>\n </mat-card-content>\n }\n</mat-card>\n", styles: [":host{flex-grow:1}.mat-mdc-row .mat-mdc-cell{border-bottom:1px solid transparent;border-top:1px solid transparent;cursor:pointer}.mat-mdc-row:hover .mat-mdc-cell{border-color:currentColor}.is-active{font-weight:700}\n"], dependencies: [{ kind: "ngmodule", type: MatListModule }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i1$4.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i1$4.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i1$4.MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: i1$4.MatCardSubtitle, selector: "mat-card-subtitle, [mat-card-subtitle], [matCardSubtitle]" }, { kind: "directive", type: i1$4.MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { kind: "component", type: i1$4.MatCardTitleGroup, selector: "mat-card-title-group" }] });
1969
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: UserListDetailComponent, isStandalone: true, selector: "lib-user-list-detail", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<mat-card mat-list-item class=\"item-card\">\n <mat-card-header>\n @if(item().profile_thumbnail)\n {\n <img mat-card-avatar src=\"{{item().profile_thumbnail}}\" alt=\"User avatar\">\n }\n <mat-card-title-group style=\"padding: 5px\">\n <mat-card-title\n >{{ item().first_name }} {{ item().last_name }}</mat-card-title\n >\n <mat-card-subtitle>{{ item().username }}</mat-card-subtitle>\n </mat-card-title-group>\n </mat-card-header>\n\n <mat-card-content>\n <p>Email: {{ item().email }}</p>\n </mat-card-content>\n</mat-card>\n", styles: [":host{flex-grow:1}.mat-mdc-row .mat-mdc-cell{border-bottom:1px solid transparent;border-top:1px solid transparent;cursor:pointer}.mat-mdc-row:hover .mat-mdc-cell{border-color:currentColor}.is-active{font-weight:700}\n"], dependencies: [{ kind: "ngmodule", type: MatListModule }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i1$3.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i1$3.MatCardAvatar, selector: "[mat-card-avatar], [matCardAvatar]" }, { kind: "directive", type: i1$3.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i1$3.MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: i1$3.MatCardSubtitle, selector: "mat-card-subtitle, [mat-card-subtitle], [matCardSubtitle]" }, { kind: "directive", type: i1$3.MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { kind: "component", type: i1$3.MatCardTitleGroup, selector: "mat-card-title-group" }] });
1834
1970
  }
1835
1971
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: UserListDetailComponent, decorators: [{
1836
1972
  type: Component,
1837
1973
  args: [{ selector: 'lib-user-list-detail', imports: [MatListModule,
1838
- MatCardModule], template: "<mat-card mat-list-item class=\"item-card\">\n @if(item(); as item){\n <mat-card-header>\n <mat-card-title-group style=\"padding: 5px\">\n <mat-card-title\n >{{ item.first_name }} {{ item.last_name }}</mat-card-title\n >\n <mat-card-subtitle>{{ item.username }}</mat-card-subtitle>\n </mat-card-title-group>\n </mat-card-header>\n\n <mat-card-content>\n <p>Email: {{ item.email }}</p>\n </mat-card-content>\n }\n</mat-card>\n", styles: [":host{flex-grow:1}.mat-mdc-row .mat-mdc-cell{border-bottom:1px solid transparent;border-top:1px solid transparent;cursor:pointer}.mat-mdc-row:hover .mat-mdc-cell{border-color:currentColor}.is-active{font-weight:700}\n"] }]
1974
+ MatCardModule], template: "<mat-card mat-list-item class=\"item-card\">\n <mat-card-header>\n @if(item().profile_thumbnail)\n {\n <img mat-card-avatar src=\"{{item().profile_thumbnail}}\" alt=\"User avatar\">\n }\n <mat-card-title-group style=\"padding: 5px\">\n <mat-card-title\n >{{ item().first_name }} {{ item().last_name }}</mat-card-title\n >\n <mat-card-subtitle>{{ item().username }}</mat-card-subtitle>\n </mat-card-title-group>\n </mat-card-header>\n\n <mat-card-content>\n <p>Email: {{ item().email }}</p>\n </mat-card-content>\n</mat-card>\n", styles: [":host{flex-grow:1}.mat-mdc-row .mat-mdc-cell{border-bottom:1px solid transparent;border-top:1px solid transparent;cursor:pointer}.mat-mdc-row:hover .mat-mdc-cell{border-color:currentColor}.is-active{font-weight:700}\n"] }]
1839
1975
  }] });
1840
1976
 
1841
1977
  class UserComponent {
@@ -1843,7 +1979,7 @@ class UserComponent {
1843
1979
  itemService = inject(UserService);
1844
1980
  columns = USER_TABLE_FULL;
1845
1981
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: UserComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1846
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.1", type: UserComponent, isStandalone: true, selector: "lib-user", ngImport: i0, template: "<lib-list-view\n [itemService]=\"itemService\"\n [itemDetailTemplate]=\"listItemTemplate\"\n [columns]=\"columns\"\n [viewType]=\"viewType()\"\n >\n <ng-template #listItemTemplate let-item=\"item\">\n <lib-user-list-detail [item]=\"item\"\n [routerLink]=\"['/' + itemService.typePlural() + '/detail/', item.id]\"\n [routerLinkActive]=\"['is-active']\">\n </lib-user-list-detail>\n </ng-template>\n</lib-list-view>\n", styles: [":host{flex-grow:1}\n"], dependencies: [{ kind: "component", type: ListViewComponent, selector: "lib-list-view", inputs: ["viewType", "itemService", "itemDetailTemplate", "columns", "sortFields", "noSelfItemsMessage", "noItemsCanCreateMessage", "noItemsMessage"] }, { kind: "component", type: UserListDetailComponent, selector: "lib-user-list-detail", inputs: ["item"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i1.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }] });
1982
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.1", type: UserComponent, isStandalone: true, selector: "lib-user", ngImport: i0, template: "<lib-list-view\n [itemService]=\"itemService\"\n [itemDetailTemplate]=\"listItemTemplate\"\n [columns]=\"columns\"\n [viewType]=\"viewType()\"\n >\n <ng-template #listItemTemplate let-item=\"item\">\n <lib-user-list-detail [item]=\"item\"\n [routerLink]=\"['/' + itemService.typePlural() + '/detail/', item.id]\"\n [routerLinkActive]=\"['is-active']\">\n </lib-user-list-detail>\n </ng-template>\n</lib-list-view>\n", styles: [":host{flex-grow:1}\n"], dependencies: [{ kind: "component", type: ListViewComponent, selector: "lib-list-view", inputs: ["viewType", "itemService", "itemDetailTemplate", "columns", "sortFields", "noSelfItemsMessage", "noItemsCanCreateMessage", "noItemsMessage", "defaultQueries"] }, { kind: "component", type: UserListDetailComponent, selector: "lib-user-list-detail", inputs: ["item"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i1.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }] });
1847
1983
  }
1848
1984
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: UserComponent, decorators: [{
1849
1985
  type: Component,
@@ -1870,7 +2006,7 @@ class GroupComponent {
1870
2006
  itemService = inject(GroupService);
1871
2007
  columns = [{ name: 'name', title: 'Name', element_type: 'string' }];
1872
2008
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: GroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1873
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.1", type: GroupComponent, isStandalone: true, selector: "lib-group", ngImport: i0, template: "<lib-list-view\n [itemService]=\"itemService\"\n [columns]=\"columns\"\n >\n</lib-list-view>\n\n", styles: [":host{flex-grow:1}\n"], dependencies: [{ kind: "component", type: ListViewComponent, selector: "lib-list-view", inputs: ["viewType", "itemService", "itemDetailTemplate", "columns", "sortFields", "noSelfItemsMessage", "noItemsCanCreateMessage", "noItemsMessage"] }] });
2009
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.1", type: GroupComponent, isStandalone: true, selector: "lib-group", ngImport: i0, template: "<lib-list-view\n [itemService]=\"itemService\"\n [columns]=\"columns\"\n >\n</lib-list-view>\n\n", styles: [":host{flex-grow:1}\n"], dependencies: [{ kind: "component", type: ListViewComponent, selector: "lib-list-view", inputs: ["viewType", "itemService", "itemDetailTemplate", "columns", "sortFields", "noSelfItemsMessage", "noItemsCanCreateMessage", "noItemsMessage", "defaultQueries"] }] });
1874
2010
  }
1875
2011
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: GroupComponent, decorators: [{
1876
2012
  type: Component,
@@ -1881,7 +2017,7 @@ class AddressEditComponent {
1881
2017
  countryOptions = input([], ...(ngDevMode ? [{ debugName: "countryOptions" }] : []));
1882
2018
  form = input(...(ngDevMode ? [undefined, { debugName: "form" }] : []));
1883
2019
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: AddressEditComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1884
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: AddressEditComponent, isStandalone: true, selector: "lib-address-edit", inputs: { countryOptions: { classPropertyName: "countryOptions", publicName: "countryOptions", isSignal: true, isRequired: false, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if(form(); as form){\n<div [formGroup]=\"form\" style=\"display: flex; flex-direction: column; width:100%\">\n <mat-form-field class=\"form-field-wide\">\n <mat-label for=\"line1\">Line 1</mat-label>\n <input matInput placeholder=\"Address Line 1\" type=\"text\" id=\"line1\" formControlName=\"line1\" name=\"line1\"\n required>\n </mat-form-field>\n\n <mat-form-field class=\"form-field-wide\">\n <mat-label for=\"line2\">Line 2</mat-label>\n <input matInput placeholder=\"Address Line 2\" type=\"text\" id=\"line2\" formControlName=\"line2\" name=\"line1\">\n </mat-form-field>\n\n <mat-form-field class=\"form-field-wide\">\n <mat-label for=\"line3\">Line 3</mat-label>\n <input matInput placeholder=\"Address Line 3\" type=\"text\" id=\"line3\" formControlName=\"line3\" name=\"line3\">\n </mat-form-field>\n\n <mat-form-field class=\"form-field\">\n <mat-label for=\"city\">City</mat-label>\n <input matInput placeholder=\"City\" type=\"text\" id=\"city\" formControlName=\"city\" name=\"city\">\n </mat-form-field>\n\n <mat-form-field class=\"form-field\">\n <mat-label for=\"region\">Region</mat-label>\n <input matInput placeholder=\"Region\" type=\"text\" id=\"region\" formControlName=\"region\" name=\"region\" required>\n </mat-form-field>\n\n <mat-form-field class=\"form-field\">\n <mat-label for=\"line1\">Post Code</mat-label>\n <input matInput placeholder=\"Post Code\" type=\"text\" id=\"postcode\" formControlName=\"postcode\" name=\"postcode\">\n </mat-form-field>\n\n <mat-form-field class=\"form-field\">\n <mat-label for=\"country\">Country</mat-label>\n <mat-select formControlName=\"country\" name=\"country\" id=\"country\" required>\n @for(country of countryOptions(); track $index){\n <mat-option [value]=\"country.code\">{{country.name}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n</div>\n}", styles: [""], dependencies: [{ kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$3.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] });
2020
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: AddressEditComponent, isStandalone: true, selector: "lib-address-edit", inputs: { countryOptions: { classPropertyName: "countryOptions", publicName: "countryOptions", isSignal: true, isRequired: false, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if(form(); as form){\n<div [formGroup]=\"form\" style=\"display: flex; flex-direction: column; width:100%\">\n <mat-form-field class=\"form-field-wide\">\n <mat-label for=\"line1\">Line 1</mat-label>\n <input matInput placeholder=\"Address Line 1\" type=\"text\" id=\"line1\" formControlName=\"line1\" name=\"line1\"\n required>\n </mat-form-field>\n\n <mat-form-field class=\"form-field-wide\">\n <mat-label for=\"line2\">Line 2</mat-label>\n <input matInput placeholder=\"Address Line 2\" type=\"text\" id=\"line2\" formControlName=\"line2\" name=\"line1\">\n </mat-form-field>\n\n <mat-form-field class=\"form-field-wide\">\n <mat-label for=\"line3\">Line 3</mat-label>\n <input matInput placeholder=\"Address Line 3\" type=\"text\" id=\"line3\" formControlName=\"line3\" name=\"line3\">\n </mat-form-field>\n\n <mat-form-field class=\"form-field\">\n <mat-label for=\"city\">City</mat-label>\n <input matInput placeholder=\"City\" type=\"text\" id=\"city\" formControlName=\"city\" name=\"city\">\n </mat-form-field>\n\n <mat-form-field class=\"form-field\">\n <mat-label for=\"region\">Region</mat-label>\n <input matInput placeholder=\"Region\" type=\"text\" id=\"region\" formControlName=\"region\" name=\"region\" required>\n </mat-form-field>\n\n <mat-form-field class=\"form-field\">\n <mat-label for=\"line1\">Post Code</mat-label>\n <input matInput placeholder=\"Post Code\" type=\"text\" id=\"postcode\" formControlName=\"postcode\" name=\"postcode\">\n </mat-form-field>\n\n <mat-form-field class=\"form-field\">\n <mat-label for=\"country\">Country</mat-label>\n <mat-select formControlName=\"country\" name=\"country\" id=\"country\" required>\n @for(country of countryOptions(); track $index){\n <mat-option [value]=\"country.code\">{{country.name}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n</div>\n}", styles: [""], dependencies: [{ kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] });
1885
2021
  }
1886
2022
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: AddressEditComponent, decorators: [{
1887
2023
  type: Component,
@@ -1903,18 +2039,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImpor
1903
2039
  }] });
1904
2040
 
1905
2041
  class AddressForm {
1906
- formBuilder = inject(FormBuilder);
1907
- form = this.formBuilder.group({
1908
- line1: [''],
1909
- line2: [''],
1910
- line3: [''],
1911
- city: [''],
1912
- region: [''],
1913
- postcode: [''],
1914
- country: ['']
1915
- });
1916
- setValue(item) {
1917
- this.form.setValue({
2042
+ static createForm(fb) {
2043
+ return fb.group({
2044
+ line1: fb.control('', Validators.required),
2045
+ line2: fb.control(''),
2046
+ line3: fb.control(''),
2047
+ city: fb.control(''),
2048
+ region: fb.control('', Validators.required),
2049
+ postcode: fb.control(''),
2050
+ country: fb.control('', Validators.required)
2051
+ });
2052
+ }
2053
+ static fromItem(item, fb) {
2054
+ const form = this.createForm(fb);
2055
+ this.setValue(form, item);
2056
+ return form;
2057
+ }
2058
+ static setValue(form, item) {
2059
+ form.setValue({
1918
2060
  line1: item.line1,
1919
2061
  line2: item.line2 || "",
1920
2062
  line3: item.line3 || "",
@@ -1924,18 +2066,20 @@ class AddressForm {
1924
2066
  country: item.country
1925
2067
  });
1926
2068
  }
1927
- createItem() {
1928
- const value = this.form.value;
1929
- return { line1: value.line1 || "",
2069
+ static createItem(form) {
2070
+ const value = form.value;
2071
+ return {
2072
+ line1: value.line1 || "",
1930
2073
  line2: value.line2 || null,
1931
2074
  line3: value.line3 || null,
1932
2075
  city: value.city || null,
1933
2076
  region: value.region || "",
1934
2077
  postcode: value.postcode || null,
1935
- country: value.country || "" };
2078
+ country: value.country || ""
2079
+ };
1936
2080
  }
1937
- updateItem(item) {
1938
- const value = this.form.value;
2081
+ static updateItem(form, item) {
2082
+ const value = form.value;
1939
2083
  item.line1 = value.line1 || "";
1940
2084
  item.line2 = value.line2 || null;
1941
2085
  item.line3 = value.line3 || null;
@@ -1953,7 +2097,7 @@ class OrganizationComponent {
1953
2097
  { name: 'website', title: 'Website', element_type: 'url' },
1954
2098
  { name: 'is_partner', title: 'Is Partner', element_type: 'boolean' }];
1955
2099
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: OrganizationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1956
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.1", type: OrganizationComponent, isStandalone: true, selector: "lib-organization", ngImport: i0, template: "<lib-list-view\n [itemService]=\"itemService\"\n [columns]=\"columns\"\n >\n</lib-list-view>\n\n\n\n", styles: [":host{flex-grow:1}\n"], dependencies: [{ kind: "component", type: ListViewComponent, selector: "lib-list-view", inputs: ["viewType", "itemService", "itemDetailTemplate", "columns", "sortFields", "noSelfItemsMessage", "noItemsCanCreateMessage", "noItemsMessage"] }] });
2100
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.1", type: OrganizationComponent, isStandalone: true, selector: "lib-organization", ngImport: i0, template: "<lib-list-view\n [itemService]=\"itemService\"\n [columns]=\"columns\"\n >\n</lib-list-view>\n\n\n\n", styles: [":host{flex-grow:1}\n"], dependencies: [{ kind: "component", type: ListViewComponent, selector: "lib-list-view", inputs: ["viewType", "itemService", "itemDetailTemplate", "columns", "sortFields", "noSelfItemsMessage", "noItemsCanCreateMessage", "noItemsMessage", "defaultQueries"] }] });
1957
2101
  }
1958
2102
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: OrganizationComponent, decorators: [{
1959
2103
  type: Component,
@@ -1970,36 +2114,40 @@ class OrganizationDetailComponent extends DetailView {
1970
2114
  this.onInit();
1971
2115
  }
1972
2116
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: OrganizationDetailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1973
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: OrganizationDetailComponent, isStandalone: true, selector: "lib-organization-detail", usesInheritance: true, ngImport: i0, template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n\n @if(item(); as item){\n <div class=\"item-detail-container\">\n\n <lib-detail-header\n [text]=\"item.name\"\n [id]=\"item.id\"\n [canEdit]=\"itemService.canEdit()\"\n [canDelete]=\"itemService.canDelete()\"\n [route]=\"itemService.typePlural()\"></lib-detail-header>\n\n <div class=\"item-field\">\n {{item.description}}\n </div>\n \n <h3>Address</h3>\n <lib-address-detail [address]=\"item.address\"></lib-address-detail>\n\n <div class=\"item-field\">\n <h3>Website</h3>{{item.website}}\n </div>\n </div>\n }\n</div>\n", styles: [":host{flex-grow:1}.padded_button{padding:5px}\n"], dependencies: [{ kind: "component", type: BackButtonComponent, selector: "lib-back-button" }, { kind: "component", type: DetailHeaderComponent, selector: "lib-detail-header", inputs: ["id", "text", "route", "canEdit", "canDelete"], outputs: ["deleteClicked"] }, { kind: "component", type: AddressDetailComponent, selector: "lib-address-detail", inputs: ["address"] }] });
2117
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: OrganizationDetailComponent, isStandalone: true, selector: "lib-organization-detail", usesInheritance: true, ngImport: i0, template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n\n @if(item(); as item){\n <div class=\"item-detail-container\">\n\n <lib-detail-header\n [text]=\"item.name\"\n [id]=\"item.id\"\n [canEdit]=\"itemService.canEdit()\"\n [canDelete]=\"itemService.canDelete()\"\n [route]=\"itemService.typePlural()\"></lib-detail-header>\n\n <div class=\"item-field\">\n {{item.description}}\n </div>\n \n <h3>Address</h3>\n <lib-address-detail [address]=\"item.address\"></lib-address-detail>\n\n <div class=\"item-field\">\n <h3>Website</h3>{{item.website}}\n </div>\n </div>\n }\n</div>\n", styles: [":host{flex-grow:1}\n"], dependencies: [{ kind: "component", type: BackButtonComponent, selector: "lib-back-button" }, { kind: "component", type: DetailHeaderComponent, selector: "lib-detail-header", inputs: ["id", "text", "route", "canEdit", "canDelete"], outputs: ["deleteClicked"] }, { kind: "component", type: AddressDetailComponent, selector: "lib-address-detail", inputs: ["address"] }] });
1974
2118
  }
1975
2119
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: OrganizationDetailComponent, decorators: [{
1976
2120
  type: Component,
1977
2121
  args: [{ selector: 'lib-organization-detail', imports: [BackButtonComponent,
1978
- DetailHeaderComponent, AddressDetailComponent], template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n\n @if(item(); as item){\n <div class=\"item-detail-container\">\n\n <lib-detail-header\n [text]=\"item.name\"\n [id]=\"item.id\"\n [canEdit]=\"itemService.canEdit()\"\n [canDelete]=\"itemService.canDelete()\"\n [route]=\"itemService.typePlural()\"></lib-detail-header>\n\n <div class=\"item-field\">\n {{item.description}}\n </div>\n \n <h3>Address</h3>\n <lib-address-detail [address]=\"item.address\"></lib-address-detail>\n\n <div class=\"item-field\">\n <h3>Website</h3>{{item.website}}\n </div>\n </div>\n }\n</div>\n", styles: [":host{flex-grow:1}.padded_button{padding:5px}\n"] }]
2122
+ DetailHeaderComponent, AddressDetailComponent], template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n\n @if(item(); as item){\n <div class=\"item-detail-container\">\n\n <lib-detail-header\n [text]=\"item.name\"\n [id]=\"item.id\"\n [canEdit]=\"itemService.canEdit()\"\n [canDelete]=\"itemService.canDelete()\"\n [route]=\"itemService.typePlural()\"></lib-detail-header>\n\n <div class=\"item-field\">\n {{item.description}}\n </div>\n \n <h3>Address</h3>\n <lib-address-detail [address]=\"item.address\"></lib-address-detail>\n\n <div class=\"item-field\">\n <h3>Website</h3>{{item.website}}\n </div>\n </div>\n }\n</div>\n", styles: [":host{flex-grow:1}\n"] }]
1979
2123
  }], ctorParameters: () => [] });
1980
2124
 
1981
2125
  class OrganizationForm {
1982
- formBuilder = inject(FormBuilder);
2126
+ fb = inject(FormBuilder);
1983
2127
  form;
1984
- address = new AddressForm();
1985
2128
  constructor() {
1986
- this.form = this.formBuilder.group({
1987
- name: [''],
1988
- acronym: [''],
1989
- description: [''],
1990
- website: [''],
1991
- address: [this.address.form]
2129
+ this.form = OrganizationForm.createForm(this.fb);
2130
+ }
2131
+ static createForm(fb) {
2132
+ return fb.group({
2133
+ name: fb.control('', Validators.required),
2134
+ acronym: fb.control(''),
2135
+ description: fb.control(''),
2136
+ website: fb.control(''),
2137
+ address: AddressForm.createForm(fb)
1992
2138
  });
1993
2139
  }
2140
+ get address() {
2141
+ return this.form.get('address');
2142
+ }
1994
2143
  setValue(item) {
1995
- this.address.setValue(item.address);
1996
- this.form.setValue({
2144
+ this.form.patchValue({
1997
2145
  name: item.name,
1998
2146
  acronym: item.acronym,
1999
2147
  description: item.description,
2000
- website: item.website,
2001
- address: this.address.form
2148
+ website: item.website
2002
2149
  });
2150
+ AddressForm.setValue(this.address, item.address);
2003
2151
  }
2004
2152
  createItem() {
2005
2153
  const value = this.form.value;
@@ -2008,7 +2156,7 @@ class OrganizationForm {
2008
2156
  acronym: value.acronym || "",
2009
2157
  description: value.description || "",
2010
2158
  website: value.website || "",
2011
- address: this.address.createItem(),
2159
+ address: AddressForm.createItem(this.address),
2012
2160
  members: []
2013
2161
  };
2014
2162
  }
@@ -2017,24 +2165,23 @@ class OrganizationForm {
2017
2165
  item.acronym = this.form.value.acronym || "";
2018
2166
  item.description = this.form.value.description || "";
2019
2167
  item.website = this.form.value.website || "";
2020
- item.address = this.address.updateItem(item.address);
2168
+ item.address = AddressForm.updateItem(this.address, item.address);
2021
2169
  return item;
2022
2170
  }
2023
2171
  }
2024
2172
 
2025
2173
  class OrganizationEditComponent extends EditView {
2026
- countryOptions = signal([], ...(ngDevMode ? [{ debugName: "countryOptions" }] : []));
2027
2174
  addressService = inject(AddressService);
2028
2175
  selectionManager = new SelectionManager();
2029
2176
  constructor() {
2030
2177
  super(inject(OrganizationService), new OrganizationForm());
2178
+ this.addressService.refreshCountryOptions();
2031
2179
  }
2032
2180
  ngOnInit() {
2033
2181
  this.onInit();
2034
- this.addressService.getOptions().subscribe(options => this.onOptions(options));
2035
2182
  }
2036
2183
  addressForm() {
2037
- return this.form.address.form;
2184
+ return this.form.address;
2038
2185
  }
2039
2186
  createItem() {
2040
2187
  const item = this.form.createItem();
@@ -2047,19 +2194,10 @@ class OrganizationEditComponent extends EditView {
2047
2194
  return item;
2048
2195
  }
2049
2196
  onItemAndUserAvailable(item, _) {
2050
- this.form.setValue(item);
2051
2197
  this.selectionManager.fetchCandidates(this.itemService.typename, item.id);
2052
2198
  }
2053
- onPostActions(actions) {
2054
- if ('country' in actions && actions['country'].choices) {
2055
- this.onCountryChoices(actions['country'].choices);
2056
- }
2057
- }
2058
- onCountryChoices(choices) {
2059
- this.countryOptions.update(() => choices.map(c => { return { name: c.display_name, code: c.value, flag: "" }; }));
2060
- }
2061
2199
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: OrganizationEditComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2062
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.1", type: OrganizationEditComponent, isStandalone: true, selector: "lib-organization-edit", usesInheritance: true, ngImport: i0, template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n\n <div class=\"item-edit-container\">\n \n <h1 class=\"item-edit-header\">{{heading() | titlecase}}</h1>\n\n <form class=\"form-card\" [formGroup]=\"form.form\" (ngSubmit)=\"submit()\">\n\n <mat-form-field class=\"form-field-wide\">\n <mat-label for=\"name\">Name</mat-label>\n <input matInput placeholder=\"Name\"\n type=\"text\"\n id=\"name\"\n formControlName=\"name\"\n name=\"name\"\n required>\n </mat-form-field>\n \n <mat-form-field class=\"form-field\">\n <mat-label for=\"acronym\">Acronym</mat-label> \n <input matInput placeholder=\"Acronym\"\n type=\"text\"\n id=\"acronym\"\n formControlName=\"acronym\"\n name=\"acronym\">\n </mat-form-field>\n \n <mat-form-field class=\"form-field-wide\">\n <mat-label for=\"description\">Description</mat-label>\n <textarea matInput placeholder=\"Description\"\n type=\"text\"\n id=\"description\"\n formControlName=\"description\"\n name=\"description\"\n class=\"medium-textarea\"\n required></textarea>\n </mat-form-field>\n\n <h3>Address</h3>\n <lib-address-edit \n [countryOptions]=\"countryOptions()\"\n [form]=\"addressForm()\"\n ></lib-address-edit>\n\n <h3>Members</h3>\n <lib-select-table [selected]=\"selectionManager.selected()\"\n [itemType]=\"'Members'\"\n [columns]=\"selectionManager.columns\"\n [options]=\"selectionManager.candidates()\"\n (itemAdded)=\"selectionManager.onAdded($event)\"\n (itemRemoved)=\"selectionManager.onRemoved($event)\"\n (searchChanged)=\"selectionManager.onSearchChanged($event)\">\n </lib-select-table>\n\n <div class=\"button_group\">\n <button mat-fab\n class=\"form_action_button\"\n type=\"submit\"\n [disabled]=\"!form.form.valid\">\n <mat-icon>save</mat-icon>\n </button>\n \n <button mat-fab\n type=\"button\"\n class=\"form_action_button\"\n (click)=\"cancel()\">\n <mat-icon>cancel</mat-icon>\n </button>\n </div>\n </form>\n </div>\n</div>\n", styles: [":host{flex-grow:1}.medium-textarea{min-height:150px}.checkbox_group{justify-content:left;display:flex;flex-direction:column}.button_group{margin:10px;display:flex;flex-direction:row;justify-content:center}.btn-block{padding:5px}.form_action_button{padding:5px;margin:5px}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i2$3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$3.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatSelectModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: BackButtonComponent, selector: "lib-back-button" }, { kind: "component", type: AddressEditComponent, selector: "lib-address-edit", inputs: ["countryOptions", "form"] }, { kind: "component", type: SelectTableComponent, selector: "lib-select-table", inputs: ["itemType", "selected", "options", "columns"], outputs: ["itemAdded", "itemRemoved", "searchChanged"] }, { kind: "pipe", type: TitleCasePipe, name: "titlecase" }] });
2200
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.1", type: OrganizationEditComponent, isStandalone: true, selector: "lib-organization-edit", usesInheritance: true, ngImport: i0, template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n\n <div class=\"item-edit-container\" style=\"width:100%\">\n \n <h1 class=\"item-edit-header\">{{heading() | titlecase}}</h1>\n\n <form class=\"form-card\" [formGroup]=\"form.form\" (ngSubmit)=\"submit()\">\n\n <mat-tab-group mat-stretch-tabs=\"true\" mat-align-tabs=\"center\" style=\"width:100%;\">\n\n <mat-tab label=\"Overview\" style=\"width:100%;\">\n <div style=\"padding:10px;\">\n <mat-form-field class=\"form-field-wide\">\n <mat-label for=\"name\">Name</mat-label>\n <input matInput placeholder=\"Name\"\n type=\"text\"\n id=\"name\"\n formControlName=\"name\"\n name=\"name\"\n required>\n </mat-form-field>\n \n <mat-form-field class=\"form-field\">\n <mat-label for=\"acronym\">Acronym</mat-label> \n <input matInput placeholder=\"Acronym\"\n type=\"text\"\n id=\"acronym\"\n formControlName=\"acronym\"\n name=\"acronym\">\n </mat-form-field>\n \n <mat-form-field class=\"form-field-wide\">\n <mat-label for=\"description\">Description</mat-label>\n <textarea matInput placeholder=\"Description\"\n type=\"text\"\n id=\"description\"\n formControlName=\"description\"\n name=\"description\"\n class=\"medium-textarea\"\n required></textarea>\n </mat-form-field>\n\n <mat-accordion style=\"width:100%\">\n <mat-expansion-panel style=\"width:100%\">\n <mat-expansion-panel-header>\n <mat-panel-title>Address</mat-panel-title>\n </mat-expansion-panel-header>\n\n <lib-address-edit \n [countryOptions]=\"addressService.countryOptions()\"\n [form]=\"addressForm()\"\n ></lib-address-edit>\n </mat-expansion-panel>\n </mat-accordion>\n </div>\n </mat-tab>\n\n <mat-tab label=\"Members\" style=\"width:100%;\">\n <div style=\"padding:10px\">\n <lib-select-table [selected]=\"selectionManager.selected()\"\n [itemType]=\"'Members'\"\n [columns]=\"selectionManager.columns\"\n [options]=\"selectionManager.candidates()\"\n (itemAdded)=\"selectionManager.onAdded($event)\"\n (itemRemoved)=\"selectionManager.onRemoved($event)\"\n (searchChanged)=\"selectionManager.onSearchChanged($event)\">\n </lib-select-table>\n </div>\n </mat-tab>\n\n </mat-tab-group>\n\n <div class=\"button_group\">\n <button mat-fab\n class=\"form_action_button\"\n type=\"submit\"\n [disabled]=\"!form.form.valid\">\n <mat-icon>save</mat-icon>\n </button>\n \n <button mat-fab\n type=\"button\"\n class=\"form_action_button\"\n (click)=\"cancel()\">\n <mat-icon>cancel</mat-icon>\n </button>\n </div>\n </form>\n </div>\n</div>\n", styles: [":host{flex-grow:1}.medium-textarea{min-height:150px}.checkbox_group{justify-content:left;display:flex;flex-direction:column}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatSelectModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "directive", type: i1$4.MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: i1$4.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i1$4.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i1$4.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "component", type: BackButtonComponent, selector: "lib-back-button" }, { kind: "component", type: AddressEditComponent, selector: "lib-address-edit", inputs: ["countryOptions", "form"] }, { kind: "component", type: SelectTableComponent, selector: "lib-select-table", inputs: ["itemType", "selected", "options", "columns"], outputs: ["itemAdded", "itemRemoved", "searchChanged"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i7.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i7.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "pipe", type: TitleCasePipe, name: "titlecase" }] });
2063
2201
  }
2064
2202
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: OrganizationEditComponent, decorators: [{
2065
2203
  type: Component,
@@ -2071,11 +2209,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImpor
2071
2209
  MatFormFieldModule,
2072
2210
  MatIconModule,
2073
2211
  MatCheckboxModule,
2212
+ MatExpansionModule,
2074
2213
  BackButtonComponent,
2075
2214
  AddressEditComponent,
2076
2215
  SelectTableComponent,
2216
+ MatTabsModule,
2077
2217
  TitleCasePipe
2078
- ], template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n\n <div class=\"item-edit-container\">\n \n <h1 class=\"item-edit-header\">{{heading() | titlecase}}</h1>\n\n <form class=\"form-card\" [formGroup]=\"form.form\" (ngSubmit)=\"submit()\">\n\n <mat-form-field class=\"form-field-wide\">\n <mat-label for=\"name\">Name</mat-label>\n <input matInput placeholder=\"Name\"\n type=\"text\"\n id=\"name\"\n formControlName=\"name\"\n name=\"name\"\n required>\n </mat-form-field>\n \n <mat-form-field class=\"form-field\">\n <mat-label for=\"acronym\">Acronym</mat-label> \n <input matInput placeholder=\"Acronym\"\n type=\"text\"\n id=\"acronym\"\n formControlName=\"acronym\"\n name=\"acronym\">\n </mat-form-field>\n \n <mat-form-field class=\"form-field-wide\">\n <mat-label for=\"description\">Description</mat-label>\n <textarea matInput placeholder=\"Description\"\n type=\"text\"\n id=\"description\"\n formControlName=\"description\"\n name=\"description\"\n class=\"medium-textarea\"\n required></textarea>\n </mat-form-field>\n\n <h3>Address</h3>\n <lib-address-edit \n [countryOptions]=\"countryOptions()\"\n [form]=\"addressForm()\"\n ></lib-address-edit>\n\n <h3>Members</h3>\n <lib-select-table [selected]=\"selectionManager.selected()\"\n [itemType]=\"'Members'\"\n [columns]=\"selectionManager.columns\"\n [options]=\"selectionManager.candidates()\"\n (itemAdded)=\"selectionManager.onAdded($event)\"\n (itemRemoved)=\"selectionManager.onRemoved($event)\"\n (searchChanged)=\"selectionManager.onSearchChanged($event)\">\n </lib-select-table>\n\n <div class=\"button_group\">\n <button mat-fab\n class=\"form_action_button\"\n type=\"submit\"\n [disabled]=\"!form.form.valid\">\n <mat-icon>save</mat-icon>\n </button>\n \n <button mat-fab\n type=\"button\"\n class=\"form_action_button\"\n (click)=\"cancel()\">\n <mat-icon>cancel</mat-icon>\n </button>\n </div>\n </form>\n </div>\n</div>\n", styles: [":host{flex-grow:1}.medium-textarea{min-height:150px}.checkbox_group{justify-content:left;display:flex;flex-direction:column}.button_group{margin:10px;display:flex;flex-direction:row;justify-content:center}.btn-block{padding:5px}.form_action_button{padding:5px;margin:5px}\n"] }]
2218
+ ], template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n\n <div class=\"item-edit-container\" style=\"width:100%\">\n \n <h1 class=\"item-edit-header\">{{heading() | titlecase}}</h1>\n\n <form class=\"form-card\" [formGroup]=\"form.form\" (ngSubmit)=\"submit()\">\n\n <mat-tab-group mat-stretch-tabs=\"true\" mat-align-tabs=\"center\" style=\"width:100%;\">\n\n <mat-tab label=\"Overview\" style=\"width:100%;\">\n <div style=\"padding:10px;\">\n <mat-form-field class=\"form-field-wide\">\n <mat-label for=\"name\">Name</mat-label>\n <input matInput placeholder=\"Name\"\n type=\"text\"\n id=\"name\"\n formControlName=\"name\"\n name=\"name\"\n required>\n </mat-form-field>\n \n <mat-form-field class=\"form-field\">\n <mat-label for=\"acronym\">Acronym</mat-label> \n <input matInput placeholder=\"Acronym\"\n type=\"text\"\n id=\"acronym\"\n formControlName=\"acronym\"\n name=\"acronym\">\n </mat-form-field>\n \n <mat-form-field class=\"form-field-wide\">\n <mat-label for=\"description\">Description</mat-label>\n <textarea matInput placeholder=\"Description\"\n type=\"text\"\n id=\"description\"\n formControlName=\"description\"\n name=\"description\"\n class=\"medium-textarea\"\n required></textarea>\n </mat-form-field>\n\n <mat-accordion style=\"width:100%\">\n <mat-expansion-panel style=\"width:100%\">\n <mat-expansion-panel-header>\n <mat-panel-title>Address</mat-panel-title>\n </mat-expansion-panel-header>\n\n <lib-address-edit \n [countryOptions]=\"addressService.countryOptions()\"\n [form]=\"addressForm()\"\n ></lib-address-edit>\n </mat-expansion-panel>\n </mat-accordion>\n </div>\n </mat-tab>\n\n <mat-tab label=\"Members\" style=\"width:100%;\">\n <div style=\"padding:10px\">\n <lib-select-table [selected]=\"selectionManager.selected()\"\n [itemType]=\"'Members'\"\n [columns]=\"selectionManager.columns\"\n [options]=\"selectionManager.candidates()\"\n (itemAdded)=\"selectionManager.onAdded($event)\"\n (itemRemoved)=\"selectionManager.onRemoved($event)\"\n (searchChanged)=\"selectionManager.onSearchChanged($event)\">\n </lib-select-table>\n </div>\n </mat-tab>\n\n </mat-tab-group>\n\n <div class=\"button_group\">\n <button mat-fab\n class=\"form_action_button\"\n type=\"submit\"\n [disabled]=\"!form.form.valid\">\n <mat-icon>save</mat-icon>\n </button>\n \n <button mat-fab\n type=\"button\"\n class=\"form_action_button\"\n (click)=\"cancel()\">\n <mat-icon>cancel</mat-icon>\n </button>\n </div>\n </form>\n </div>\n</div>\n", styles: [":host{flex-grow:1}.medium-textarea{min-height:150px}.checkbox_group{justify-content:left;display:flex;flex-direction:column}\n"] }]
2079
2219
  }], ctorParameters: () => [] });
2080
2220
 
2081
2221
  /*
@@ -2086,5 +2226,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImpor
2086
2226
  * Generated bundle index. Do not edit.
2087
2227
  */
2088
2228
 
2089
- export { Address, AddressDetailComponent, AddressEditComponent, AddressForm, AddressService, ApiError, AvatarComponent, BackButtonComponent, DetailHeaderComponent, DetailView, DynamicFormBuilderComponent, DynamicFormComponent, DynamicFormForm, ENDPOINT_URL, EditView, ErrorCode, FORM_FIELD_CHOICES, FeedbackComponent, FileRecord, FileUploadComponent, FormFieldDetailComponent, FormFieldEditComponent, FormFieldListComponent, FormService, Group, GroupComponent, GroupDetailComponent, GroupService, ItemQuery, ItemService, ItemWithUserService, LOGIN_USER, LandingComponent, LeftNavComponent, LeftNavService, ListTableViewComponent, ListViewComponent, MockItemService, Organization, OrganizationComponent, OrganizationDetailComponent, OrganizationEditComponent, OrganizationService, Paginated, Permission, PortalMember, ResolvedPermission, RestService, SearchBarComponent, SelectTableComponent, SelectionManager, TopBarComponent, UserComponent, UserDetailComponent, UserEditComponent, UserService };
2229
+ export { Address, AddressDetailComponent, AddressEditComponent, AddressForm, AddressService, ApiError, AvatarComponent, BackButtonComponent, DetailHeaderComponent, DetailView, DynamicFormBuilderComponent, DynamicFormComponent, DynamicFormForm, ENDPOINT_URL, EditView, ErrorCode, FORM_FIELD_CHOICES, FeedbackComponent, FieldType, FileRecord, FileUploadComponent, FormFieldDetailComponent, FormFieldEditComponent, FormFieldValueForm, FormService, Group, GroupComponent, GroupDetailComponent, GroupService, ItemQuery, ItemService, ItemWithUserService, LOGIN_USER, LandingComponent, LeftNavComponent, LeftNavService, ListTableViewComponent, ListViewComponent, MockItemService, Organization, OrganizationComponent, OrganizationDetailComponent, OrganizationEditComponent, OrganizationService, Paginated, Permission, PopulatedFormForm, PortalMember, ResolvedPermission, RestService, SearchBarComponent, SelectTableComponent, SelectionManager, TopBarComponent, UserComponent, UserDetailComponent, UserEditComponent, UserService, getFieldTypeFromKey };
2090
2230
  //# sourceMappingURL=ichec-angular-core.mjs.map