ichec-angular-core 0.1.0 → 0.1.1

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.
@@ -31,14 +31,14 @@ import * as i6 from '@angular/material/select';
31
31
  import { MatSelectModule } from '@angular/material/select';
32
32
  import * as i6$1 from '@angular/material/autocomplete';
33
33
  import { MatAutocompleteModule } from '@angular/material/autocomplete';
34
- import * as i4 from '@angular/material/tooltip';
35
- import { MatTooltipModule } from '@angular/material/tooltip';
36
34
  import * as i3$3 from '@angular/material/sort';
37
35
  import { MatSort, MatSortModule } from '@angular/material/sort';
38
36
  import * as i1$5 from '@angular/material/button-toggle';
39
37
  import { MatButtonToggleModule } from '@angular/material/button-toggle';
40
38
  import * as i2$5 from '@angular/material/progress-spinner';
41
39
  import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
40
+ import * as i4 from '@angular/material/tooltip';
41
+ import { MatTooltipModule } from '@angular/material/tooltip';
42
42
  import * as i2$3 from '@angular/material/paginator';
43
43
  import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator';
44
44
  import * as i2$4 from '@angular/cdk/scrolling';
@@ -90,6 +90,41 @@ class Group {
90
90
  }
91
91
  }
92
92
 
93
+ class Address {
94
+ static typename = "address";
95
+ static plural = "addresses";
96
+ id = 0;
97
+ url = "";
98
+ line1 = "";
99
+ line2 = "";
100
+ line3 = "";
101
+ city = "";
102
+ region = "";
103
+ postcode = "";
104
+ country = "";
105
+ country_name = "";
106
+ country_flag = "";
107
+ members = [];
108
+ constructor(params = {}) {
109
+ Object.assign(this, params);
110
+ }
111
+ }
112
+ class Organization {
113
+ static typename = "organization";
114
+ static plural = "organizations";
115
+ id = 0;
116
+ url = "";
117
+ name = "";
118
+ acronym = "";
119
+ description = "";
120
+ address = "";
121
+ website = "";
122
+ members = [];
123
+ constructor(params = {}) {
124
+ Object.assign(this, params);
125
+ }
126
+ }
127
+
93
128
  class ItemQuery {
94
129
  queries = new Map();
95
130
  page = 0;
@@ -357,6 +392,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImpor
357
392
  }]
358
393
  }] });
359
394
 
395
+ class AddressService extends ItemService {
396
+ _url = Address.plural;
397
+ itemType = Address.plural;
398
+ instantiateType(item) {
399
+ return new Address(item);
400
+ }
401
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: AddressService, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
402
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: AddressService, providedIn: 'root' });
403
+ }
404
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: AddressService, decorators: [{
405
+ type: Injectable,
406
+ args: [{
407
+ providedIn: 'root'
408
+ }]
409
+ }] });
410
+
360
411
  class GroupService extends ItemService {
361
412
  userService = inject(UserService);
362
413
  userItems = new BehaviorSubject([]);
@@ -387,41 +438,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImpor
387
438
  }]
388
439
  }], ctorParameters: () => [] });
389
440
 
390
- class Address {
391
- static typename = "address";
392
- static plural = "addresses";
393
- id = 0;
394
- url = "";
395
- line1 = "";
396
- line2 = "";
397
- line3 = "";
398
- city = "";
399
- region = "";
400
- postcode = "";
401
- country = "";
402
- country_name = "";
403
- country_flag = "";
404
- members = [];
405
- constructor(params = {}) {
406
- Object.assign(this, params);
407
- }
408
- }
409
- class Organization {
410
- static typename = "organization";
411
- static plural = "organizations";
412
- id = 0;
413
- url = "";
414
- name = "";
415
- acronym = "";
416
- description = "";
417
- address = "";
418
- website = "";
419
- members = [];
420
- constructor(params = {}) {
421
- Object.assign(this, params);
422
- }
423
- }
424
-
425
441
  class OrganizationService extends ItemService {
426
442
  _url = Organization.plural;
427
443
  itemType = Organization.plural;
@@ -711,43 +727,20 @@ class EditView {
711
727
  }
712
728
 
713
729
  class ListView {
714
- count = signal(0, ...(ngDevMode ? [{ debugName: "count" }] : []));
715
- items = signal([], ...(ngDevMode ? [{ debugName: "items" }] : []));
716
- next_url = null;
717
730
  _route = inject(ActivatedRoute);
718
- _location = inject(Location);
719
- _userService = inject(UserService);
720
- _itemService;
721
- constructor(_itemService) {
722
- this._itemService = _itemService;
723
- }
724
- getItems(query = new ItemQuery()) {
725
- if (this.isSelfList()) {
726
- this._userService.loggedInUser.subscribe(user => {
727
- if (user) {
728
- this.onUserAvailable(user, query);
729
- }
730
- });
731
- }
732
- else {
733
- this._itemService.get(query).subscribe(items => this.onItems(items));
734
- }
735
- }
736
- onItems(paginated) {
737
- this.count.set(paginated.count);
738
- this.items.set(paginated.results);
739
- this.next_url = paginated.next;
740
- }
741
- onUserAvailable(user, query) {
742
- this._itemService.getForUser(user, query).subscribe(items => this.onItems(items));
731
+ userService = inject(UserService);
732
+ user = signal(null, ...(ngDevMode ? [{ debugName: "user" }] : []));
733
+ getUser() {
734
+ this.userService.loggedInUser.subscribe(user => {
735
+ if (user) {
736
+ this.user.set(user);
737
+ }
738
+ });
743
739
  }
744
740
  isSelfList() {
745
741
  const url_segments = this._route.snapshot.url;
746
742
  return (url_segments.length == 2) && (url_segments[1].path == "self");
747
743
  }
748
- goBack() {
749
- this._location.back();
750
- }
751
744
  }
752
745
 
753
746
  class SelectTableComponent {
@@ -789,6 +782,101 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImpor
789
782
  MatInputModule], 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"] }]
790
783
  }] });
791
784
 
785
+ /* eslint-disable @typescript-eslint/no-explicit-any */
786
+ class ListTableViewComponent {
787
+ itemType = input("", ...(ngDevMode ? [{ debugName: "itemType" }] : []));
788
+ columns = input([], ...(ngDevMode ? [{ debugName: "columns" }] : []));
789
+ dataSource = input(...(ngDevMode ? [undefined, { debugName: "dataSource" }] : []));
790
+ searchFilter = input("", ...(ngDevMode ? [{ debugName: "searchFilter" }] : []));
791
+ pageSizeOptions = [20, 50, 100];
792
+ initialPageSize = 20;
793
+ columnNames = computed(() => this.columns().map(c => c.name), ...(ngDevMode ? [{ debugName: "columnNames" }] : []));
794
+ sort = viewChild(MatSort, ...(ngDevMode ? [{ debugName: "sort" }] : []));
795
+ paginator = viewChild(MatPaginator, ...(ngDevMode ? [{ debugName: "paginator" }] : []));
796
+ ngOnInit() {
797
+ const data_source = this.dataSource();
798
+ if (data_source) {
799
+ data_source.fetch(new ItemQuery({ page_size: this.initialPageSize }));
800
+ }
801
+ }
802
+ ngAfterViewInit() {
803
+ const paginator = this.paginator();
804
+ const sort = this.sort();
805
+ if (!paginator || !sort) {
806
+ return;
807
+ }
808
+ sort.sortChange.subscribe(() => this.reset());
809
+ merge(sort.sortChange, paginator.page)
810
+ .pipe(tap(() => this.fetch()))
811
+ .subscribe();
812
+ }
813
+ reset() {
814
+ const paginator = this.paginator();
815
+ if (!paginator) {
816
+ return;
817
+ }
818
+ paginator.pageIndex = 0;
819
+ }
820
+ fetch() {
821
+ const paginator = this.paginator();
822
+ const sort = this.sort();
823
+ const data_source = this.dataSource();
824
+ if (!paginator || !sort || !data_source) {
825
+ return;
826
+ }
827
+ data_source.fetch(new ItemQuery({
828
+ page: paginator.pageIndex + 1,
829
+ page_size: paginator.pageSize,
830
+ sort_order: sort.direction,
831
+ sort_field: sort.active,
832
+ filter: this.searchFilter()
833
+ }));
834
+ }
835
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: ListTableViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
836
+ 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$4.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i1$4.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1$4.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i1$4.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1$4.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1$4.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i1$4.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1$4.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i1$4.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i1$4.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$3.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i3$3.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"] }] });
837
+ }
838
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: ListTableViewComponent, decorators: [{
839
+ type: Component,
840
+ args: [{ selector: 'lib-list-table-view', imports: [MatTableModule,
841
+ ReactiveFormsModule,
842
+ MatButtonModule,
843
+ MatInputModule,
844
+ MatIconModule,
845
+ MatPaginatorModule,
846
+ MatSortModule,
847
+ RouterModule
848
+ ], 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"] }]
849
+ }] });
850
+
851
+ // Datasource needs any
852
+ /* eslint-disable @typescript-eslint/no-explicit-any */
853
+ class ListScrollViewComponent {
854
+ searchTerm = input("", ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
855
+ pageSize = input(20, ...(ngDevMode ? [{ debugName: "pageSize" }] : []));
856
+ dataSource = input(...(ngDevMode ? [undefined, { debugName: "dataSource" }] : []));
857
+ listItemTemplate = input(null, ...(ngDevMode ? [{ debugName: "listItemTemplate" }] : []));
858
+ ngOnInit() {
859
+ this.reset();
860
+ }
861
+ reset() {
862
+ const data_source = this.dataSource();
863
+ if (!data_source) {
864
+ return;
865
+ }
866
+ // sort_order: this.sort!.direction,
867
+ // sort_field: this.sort!.active,
868
+ data_source.reset(this.searchTerm(), this.pageSize());
869
+ }
870
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: ListScrollViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
871
+ 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"] }] });
872
+ }
873
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: ListScrollViewComponent, decorators: [{
874
+ type: Component,
875
+ args: [{ selector: 'lib-list-scroll-view', imports: [MatListModule,
876
+ NgTemplateOutlet,
877
+ ScrollingModule], 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"] }]
878
+ }] });
879
+
792
880
  class BackButtonComponent {
793
881
  location = inject(Location);
794
882
  goBack() {
@@ -802,42 +890,233 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImpor
802
890
  args: [{ selector: 'lib-back-button', imports: [MatIconModule, MatButtonModule], 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"] }]
803
891
  }] });
804
892
 
805
- class DetailHeaderComponent {
806
- id = input(0, ...(ngDevMode ? [{ debugName: "id" }] : []));
807
- text = input("", ...(ngDevMode ? [{ debugName: "text" }] : []));
808
- route = input("", ...(ngDevMode ? [{ debugName: "route" }] : []));
809
- canEdit = input(false, ...(ngDevMode ? [{ debugName: "canEdit" }] : []));
810
- canDelete = input(false, ...(ngDevMode ? [{ debugName: "canDelete" }] : []));
811
- deleteClicked = output();
812
- fullRoute = computed(() => "/" + this.route() + "s/edit/", ...(ngDevMode ? [{ debugName: "fullRoute" }] : []));
813
- deleteClick() {
814
- this.deleteClicked.emit();
893
+ class SearchBarComponent {
894
+ itemType = input("", ...(ngDevMode ? [{ debugName: "itemType" }] : []));
895
+ sortFields = input([], ...(ngDevMode ? [{ debugName: "sortFields" }] : []));
896
+ sortAscending = signal(true, ...(ngDevMode ? [{ debugName: "sortAscending" }] : []));
897
+ searchChanged = output();
898
+ searchFilter = new FormControl();
899
+ ngAfterViewInit() {
900
+ this.searchFilter.valueChanges.pipe(debounceTime(150), distinctUntilChanged(), tap(() => {
901
+ this.searchEntered();
902
+ })).subscribe();
815
903
  }
816
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: DetailHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
817
- 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: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
904
+ clearSearch() {
905
+ this.searchFilter.setValue("");
906
+ }
907
+ searchEntered() {
908
+ this.searchChanged.emit(this.searchFilter.value);
909
+ }
910
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: SearchBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
911
+ 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$2.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: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3$1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.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: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: TitleCasePipe, name: "titlecase" }] });
818
912
  }
819
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: DetailHeaderComponent, decorators: [{
913
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: SearchBarComponent, decorators: [{
820
914
  type: Component,
821
- args: [{ selector: 'lib-detail-header', imports: [RouterModule,
915
+ args: [{ selector: 'lib-search-bar', imports: [ReactiveFormsModule,
916
+ MatInputModule,
917
+ MatTooltipModule,
822
918
  MatButtonModule,
823
- MatIconModule, MatTooltipModule], 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"] }]
919
+ MatSelectModule,
920
+ MatIconModule,
921
+ TitleCasePipe], 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"] }]
824
922
  }] });
825
923
 
826
- class FileUploadComponent {
827
- files = input([], ...(ngDevMode ? [{ debugName: "files" }] : []));
828
- previewLoaded = output();
829
- fileUploaded = output();
830
- onPreviewRead(name, content) {
831
- this.previewLoaded.emit({ name: name, content: content });
832
- }
833
- onFileUpload(name, event) {
834
- if (!event.target) {
835
- return;
836
- }
837
- const input_element = event.target;
838
- if (input_element.files && input_element.files.length > 0) {
839
- const file = input_element.files[0];
840
- this.fileUploaded.emit({ name: name, file: file });
924
+ class ListDataSource extends DataSource {
925
+ length = signal(0, ...(ngDevMode ? [{ debugName: "length" }] : []));
926
+ loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : []));
927
+ searchTerm = signal("", ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
928
+ pageSize = signal(20, ...(ngDevMode ? [{ debugName: "pageSize" }] : []));
929
+ consumerType;
930
+ items = new BehaviorSubject([]);
931
+ itemService;
932
+ subscription = new Subscription();
933
+ fetchedPages = new Set();
934
+ constructor(itemService, consumerType = "table") {
935
+ super();
936
+ this.itemService = itemService;
937
+ this.consumerType = consumerType;
938
+ }
939
+ connect(collectionViewer) {
940
+ if (!this.hasTableConsumer()) {
941
+ this.subscription.add(collectionViewer.viewChange.subscribe((range) => this.onRange(range)));
942
+ }
943
+ return this.items.asObservable();
944
+ }
945
+ hasTableConsumer() {
946
+ return this.consumerType === "table";
947
+ }
948
+ onRange(range) {
949
+ const start_page = Math.floor(range.start / this.pageSize());
950
+ const end_page = Math.floor(range.end / this.pageSize());
951
+ for (let idx = start_page; idx <= end_page; idx++) {
952
+ this.fetchPage(idx);
953
+ }
954
+ }
955
+ reset(searchTerm = "", pageSize = 20) {
956
+ this.fetchedPages = new Set();
957
+ this.length.set(0);
958
+ this.searchTerm.set(searchTerm);
959
+ this.pageSize.set(pageSize);
960
+ this.loading.set(true);
961
+ this.items.next([]);
962
+ this.fetchPage(0);
963
+ }
964
+ fetchPage(idx) {
965
+ if (this.fetchedPages.has(idx)) {
966
+ return;
967
+ }
968
+ this.fetchedPages.add(idx);
969
+ this.fetch(new ItemQuery({ page: idx + 1,
970
+ page_size: this.pageSize(),
971
+ filter: this.searchTerm() }));
972
+ }
973
+ fetch(query) {
974
+ this.loading.set(true);
975
+ this.itemService.get(query).pipe(catchError(() => of(new Paginated())), finalize(() => this.loading.set(false))).subscribe(response => this.onResponse(response));
976
+ }
977
+ onResponse(response) {
978
+ this.length.set(response.count);
979
+ if (this.hasTableConsumer()) {
980
+ this.items.next(response.results);
981
+ }
982
+ else {
983
+ this.items.next([...this.items.value, ...response.results]);
984
+ }
985
+ }
986
+ disconnect() {
987
+ this.items.complete();
988
+ if (this.subscription) {
989
+ this.subscription.unsubscribe();
990
+ }
991
+ }
992
+ }
993
+
994
+ class ListViewComponent {
995
+ viewType = input("table", ...(ngDevMode ? [{ debugName: "viewType" }] : []));
996
+ itemService = input(...(ngDevMode ? [undefined, { debugName: "itemService" }] : []));
997
+ itemDetailTemplate = input(null, ...(ngDevMode ? [{ debugName: "itemDetailTemplate" }] : []));
998
+ columns = input([], ...(ngDevMode ? [{ debugName: "columns" }] : []));
999
+ sortFields = input([], ...(ngDevMode ? [{ debugName: "sortFields" }] : []));
1000
+ noSelfItemsMessage = input(...(ngDevMode ? [undefined, { debugName: "noSelfItemsMessage" }] : []));
1001
+ noItemsCanCreateMessage = input(...(ngDevMode ? [undefined, { debugName: "noItemsCanCreateMessage" }] : []));
1002
+ noItemsMessage = input(...(ngDevMode ? [undefined, { debugName: "noItemsMessage" }] : []));
1003
+ selectedViewType = signal("table", ...(ngDevMode ? [{ debugName: "selectedViewType" }] : []));
1004
+ pageSize = 20;
1005
+ pageSizeOptions = [20, 50, 100];
1006
+ route = inject(ActivatedRoute);
1007
+ dataSource = undefined;
1008
+ sort = viewChild(MatSort, ...(ngDevMode ? [{ debugName: "sort" }] : []));
1009
+ columnNames = computed(() => this.columns().map(c => c.name), ...(ngDevMode ? [{ debugName: "columnNames" }] : []));
1010
+ searchTerm = "";
1011
+ ngOnInit() {
1012
+ this.selectedViewType.set(this.viewType());
1013
+ this.resetDataSource();
1014
+ }
1015
+ ngAfterViewInit() {
1016
+ const sort = this.sort();
1017
+ if (sort) {
1018
+ sort.sortChange.pipe(tap(() => this.reset())).subscribe();
1019
+ }
1020
+ }
1021
+ onSearchChange(value) {
1022
+ this.searchTerm = value;
1023
+ this.reset();
1024
+ }
1025
+ canCreate() {
1026
+ const item_service = this.itemService();
1027
+ if (item_service) {
1028
+ return item_service.canCreate();
1029
+ }
1030
+ return false;
1031
+ }
1032
+ itemType() {
1033
+ const item_service = this.itemService();
1034
+ if (item_service) {
1035
+ return item_service.itemType;
1036
+ }
1037
+ return "";
1038
+ }
1039
+ isTableView() {
1040
+ return this.selectedViewType() === "table";
1041
+ }
1042
+ resetDataSource() {
1043
+ const item_service = this.itemService();
1044
+ if (item_service) {
1045
+ this.dataSource = new ListDataSource(item_service, this.selectedViewType());
1046
+ }
1047
+ this.reset();
1048
+ }
1049
+ reset() {
1050
+ if (this.dataSource) {
1051
+ this.dataSource.reset(this.searchTerm, this.pageSize);
1052
+ }
1053
+ }
1054
+ viewChanged(event) {
1055
+ this.selectedViewType.set(event.value);
1056
+ console.log(this.selectedViewType());
1057
+ this.resetDataSource();
1058
+ }
1059
+ isSelfList() {
1060
+ const url_segments = this.route.snapshot.url;
1061
+ return (url_segments.length == 2) && (url_segments[1].path == "self");
1062
+ }
1063
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: ListViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1064
+ 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\">{{ itemType() | 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 <div class=\"controls\">\n <lib-search-bar [itemType]=\"itemType()\" [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)\n {\n @if (dataSource.loading()) {\n <div class=\"spinner-container\">\n <mat-spinner></mat-spinner>\n </div>\n }\n @else{\n @if(dataSource.length() === 0)\n {\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 }\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 }\n @else{\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 }\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}\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$5.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$5.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: i3.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.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" }] });
1065
+ }
1066
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: ListViewComponent, decorators: [{
1067
+ type: Component,
1068
+ args: [{ selector: 'lib-list-view', imports: [ListTableViewComponent,
1069
+ ListScrollViewComponent,
1070
+ BackButtonComponent,
1071
+ MatFormFieldModule,
1072
+ MatButtonToggleModule,
1073
+ MatProgressSpinnerModule,
1074
+ MatIconModule,
1075
+ ReactiveFormsModule,
1076
+ RouterModule,
1077
+ TitleCasePipe,
1078
+ MatInputModule,
1079
+ MatTooltipModule,
1080
+ MatButtonModule,
1081
+ SearchBarComponent], template: "<lib-back-button></lib-back-button>\n\n<div class=\"container\">\n <div class=\"header\">\n <h1 class=\"title\">{{ itemType() | 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 <div class=\"controls\">\n <lib-search-bar [itemType]=\"itemType()\" [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)\n {\n @if (dataSource.loading()) {\n <div class=\"spinner-container\">\n <mat-spinner></mat-spinner>\n </div>\n }\n @else{\n @if(dataSource.length() === 0)\n {\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 }\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 }\n @else{\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 }\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}\n"] }]
1082
+ }] });
1083
+
1084
+ class DetailHeaderComponent {
1085
+ id = input(0, ...(ngDevMode ? [{ debugName: "id" }] : []));
1086
+ text = input("", ...(ngDevMode ? [{ debugName: "text" }] : []));
1087
+ route = input("", ...(ngDevMode ? [{ debugName: "route" }] : []));
1088
+ canEdit = input(false, ...(ngDevMode ? [{ debugName: "canEdit" }] : []));
1089
+ canDelete = input(false, ...(ngDevMode ? [{ debugName: "canDelete" }] : []));
1090
+ deleteClicked = output();
1091
+ fullRoute = computed(() => "/" + this.route() + "s/edit/", ...(ngDevMode ? [{ debugName: "fullRoute" }] : []));
1092
+ deleteClick() {
1093
+ this.deleteClicked.emit();
1094
+ }
1095
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: DetailHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1096
+ 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: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
1097
+ }
1098
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: DetailHeaderComponent, decorators: [{
1099
+ type: Component,
1100
+ args: [{ selector: 'lib-detail-header', imports: [RouterModule,
1101
+ MatButtonModule,
1102
+ MatIconModule, MatTooltipModule], 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"] }]
1103
+ }] });
1104
+
1105
+ class FileUploadComponent {
1106
+ files = input([], ...(ngDevMode ? [{ debugName: "files" }] : []));
1107
+ previewLoaded = output();
1108
+ fileUploaded = output();
1109
+ onPreviewRead(name, content) {
1110
+ this.previewLoaded.emit({ name: name, content: content });
1111
+ }
1112
+ onFileUpload(name, event) {
1113
+ if (!event.target) {
1114
+ return;
1115
+ }
1116
+ const input_element = event.target;
1117
+ if (input_element.files && input_element.files.length > 0) {
1118
+ const file = input_element.files[0];
1119
+ this.fileUploaded.emit({ name: name, file: file });
841
1120
  const record = this.files().find(f => f.name == name);
842
1121
  if (record && record.file_type == "image") {
843
1122
  this.readFile(name, file);
@@ -979,290 +1258,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImpor
979
1258
  ], template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n\n @if(item(); as item){\n <div class=\"item-edit-container\">\n\n <h1 class=\"item-edit-header\">{{heading()}}</h1>\n\n <form class=\"form-card\" [formGroup]=\"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.valid\">\n <mat-icon>save</mat-icon></button>\n \n <button mat-fab\n class=\"form_action_button\"\n (click)=\"cancel()\">\n <mat-icon>cancel</mat-icon></button>\n </div>\n \n </form>\n </div>\n }\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"] }]
980
1259
  }], ctorParameters: () => [] });
981
1260
 
982
- /* eslint-disable @typescript-eslint/no-explicit-any */
983
- class ListTableViewComponent {
984
- itemType = input("", ...(ngDevMode ? [{ debugName: "itemType" }] : []));
985
- columns = input([], ...(ngDevMode ? [{ debugName: "columns" }] : []));
986
- dataSource = input(...(ngDevMode ? [undefined, { debugName: "dataSource" }] : []));
987
- searchFilter = input("", ...(ngDevMode ? [{ debugName: "searchFilter" }] : []));
988
- pageSizeOptions = [20, 50, 100];
989
- initialPageSize = 20;
990
- columnNames = computed(() => this.columns().map(c => c.name), ...(ngDevMode ? [{ debugName: "columnNames" }] : []));
991
- sort = viewChild(MatSort, ...(ngDevMode ? [{ debugName: "sort" }] : []));
992
- paginator = viewChild(MatPaginator, ...(ngDevMode ? [{ debugName: "paginator" }] : []));
993
- ngOnInit() {
994
- const data_source = this.dataSource();
995
- if (data_source) {
996
- data_source.fetch(new ItemQuery({ page_size: this.initialPageSize }));
997
- }
998
- }
999
- ngAfterViewInit() {
1000
- const paginator = this.paginator();
1001
- const sort = this.sort();
1002
- if (!paginator || !sort) {
1003
- return;
1004
- }
1005
- sort.sortChange.subscribe(() => this.reset());
1006
- merge(sort.sortChange, paginator.page)
1007
- .pipe(tap(() => this.fetch()))
1008
- .subscribe();
1009
- }
1010
- reset() {
1011
- const paginator = this.paginator();
1012
- if (!paginator) {
1013
- return;
1014
- }
1015
- paginator.pageIndex = 0;
1016
- }
1017
- fetch() {
1018
- const paginator = this.paginator();
1019
- const sort = this.sort();
1020
- const data_source = this.dataSource();
1021
- if (!paginator || !sort || !data_source) {
1022
- return;
1023
- }
1024
- data_source.fetch(new ItemQuery({
1025
- page: paginator.pageIndex + 1,
1026
- page_size: paginator.pageSize,
1027
- sort_order: sort.direction,
1028
- sort_field: sort.active,
1029
- filter: this.searchFilter()
1030
- }));
1031
- }
1032
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: ListTableViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1033
- 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$4.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i1$4.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1$4.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i1$4.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1$4.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1$4.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i1$4.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1$4.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i1$4.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i1$4.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$3.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i3$3.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"] }] });
1261
+ class UserListDetailComponent {
1262
+ item = input(...(ngDevMode ? [undefined, { debugName: "item" }] : []));
1263
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: UserListDetailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1264
+ 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$3.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { 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" }] });
1034
1265
  }
1035
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: ListTableViewComponent, decorators: [{
1036
- type: Component,
1037
- args: [{ selector: 'lib-list-table-view', imports: [MatTableModule,
1038
- ReactiveFormsModule,
1039
- MatButtonModule,
1040
- MatInputModule,
1041
- MatIconModule,
1042
- MatPaginatorModule,
1043
- MatSortModule,
1044
- RouterModule
1045
- ], 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"] }]
1046
- }] });
1047
-
1048
- // Datasource needs any
1049
- /* eslint-disable @typescript-eslint/no-explicit-any */
1050
- class ListScrollViewComponent {
1051
- searchTerm = input("", ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
1052
- pageSize = input(20, ...(ngDevMode ? [{ debugName: "pageSize" }] : []));
1053
- dataSource = input(...(ngDevMode ? [undefined, { debugName: "dataSource" }] : []));
1054
- listItemTemplate = input(null, ...(ngDevMode ? [{ debugName: "listItemTemplate" }] : []));
1055
- ngOnInit() {
1056
- this.reset();
1057
- }
1058
- reset() {
1059
- const data_source = this.dataSource();
1060
- if (!data_source) {
1061
- return;
1062
- }
1063
- // sort_order: this.sort!.direction,
1064
- // sort_field: this.sort!.active,
1065
- data_source.reset(this.searchTerm(), this.pageSize());
1066
- }
1067
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: ListScrollViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1068
- 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"] }] });
1069
- }
1070
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: ListScrollViewComponent, decorators: [{
1071
- type: Component,
1072
- args: [{ selector: 'lib-list-scroll-view', imports: [MatListModule,
1073
- NgTemplateOutlet,
1074
- ScrollingModule], 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"] }]
1075
- }] });
1076
-
1077
- class SearchBarComponent {
1078
- itemType = input("", ...(ngDevMode ? [{ debugName: "itemType" }] : []));
1079
- sortFields = input([], ...(ngDevMode ? [{ debugName: "sortFields" }] : []));
1080
- sortAscending = signal(true, ...(ngDevMode ? [{ debugName: "sortAscending" }] : []));
1081
- searchChanged = output();
1082
- searchFilter = new FormControl();
1083
- ngAfterViewInit() {
1084
- this.searchFilter.valueChanges.pipe(debounceTime(150), distinctUntilChanged(), tap(() => {
1085
- this.searchEntered();
1086
- })).subscribe();
1087
- }
1088
- clearSearch() {
1089
- this.searchFilter.setValue("");
1090
- }
1091
- searchEntered() {
1092
- this.searchChanged.emit(this.searchFilter.value);
1093
- }
1094
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: SearchBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1095
- 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$2.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: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3$1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.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: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: TitleCasePipe, name: "titlecase" }] });
1096
- }
1097
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: SearchBarComponent, decorators: [{
1098
- type: Component,
1099
- args: [{ selector: 'lib-search-bar', imports: [ReactiveFormsModule,
1100
- MatInputModule,
1101
- MatTooltipModule,
1102
- MatButtonModule,
1103
- MatSelectModule,
1104
- MatIconModule,
1105
- TitleCasePipe], 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"] }]
1106
- }] });
1107
-
1108
- class ListDataSource extends DataSource {
1109
- length = signal(0, ...(ngDevMode ? [{ debugName: "length" }] : []));
1110
- loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : []));
1111
- searchTerm = signal("", ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
1112
- pageSize = signal(20, ...(ngDevMode ? [{ debugName: "pageSize" }] : []));
1113
- consumerType;
1114
- items = new BehaviorSubject([]);
1115
- itemService;
1116
- subscription = new Subscription();
1117
- fetchedPages = new Set();
1118
- constructor(itemService, consumerType = "table") {
1119
- super();
1120
- this.itemService = itemService;
1121
- this.consumerType = consumerType;
1122
- }
1123
- connect(collectionViewer) {
1124
- if (!this.hasTableConsumer()) {
1125
- this.subscription.add(collectionViewer.viewChange.subscribe((range) => this.onRange(range)));
1126
- }
1127
- return this.items.asObservable();
1128
- }
1129
- hasTableConsumer() {
1130
- return this.consumerType === "table";
1131
- }
1132
- onRange(range) {
1133
- const start_page = Math.floor(range.start / this.pageSize());
1134
- const end_page = Math.floor(range.end / this.pageSize());
1135
- for (let idx = start_page; idx <= end_page; idx++) {
1136
- this.fetchPage(idx);
1137
- }
1138
- }
1139
- reset(searchTerm = "", pageSize = 20) {
1140
- this.fetchedPages = new Set();
1141
- this.length.set(0);
1142
- this.searchTerm.set(searchTerm);
1143
- this.pageSize.set(pageSize);
1144
- this.loading.set(true);
1145
- this.items.next([]);
1146
- this.fetchPage(0);
1147
- }
1148
- fetchPage(idx) {
1149
- if (this.fetchedPages.has(idx)) {
1150
- return;
1151
- }
1152
- this.fetchedPages.add(idx);
1153
- this.fetch(new ItemQuery({ page: idx + 1,
1154
- page_size: this.pageSize(),
1155
- filter: this.searchTerm() }));
1156
- }
1157
- fetch(query) {
1158
- this.loading.set(true);
1159
- this.itemService.get(query).pipe(catchError(() => of(new Paginated())), finalize(() => this.loading.set(false))).subscribe(response => this.onResponse(response));
1160
- }
1161
- onResponse(response) {
1162
- this.length.set(response.count);
1163
- if (this.hasTableConsumer()) {
1164
- this.items.next(response.results);
1165
- }
1166
- else {
1167
- this.items.next([...this.items.value, ...response.results]);
1168
- }
1169
- }
1170
- disconnect() {
1171
- this.items.complete();
1172
- if (this.subscription) {
1173
- this.subscription.unsubscribe();
1174
- }
1175
- }
1176
- }
1177
-
1178
- class ListViewComponent {
1179
- viewType = input("table", ...(ngDevMode ? [{ debugName: "viewType" }] : []));
1180
- itemService = input(...(ngDevMode ? [undefined, { debugName: "itemService" }] : []));
1181
- itemDetailTemplate = input(null, ...(ngDevMode ? [{ debugName: "itemDetailTemplate" }] : []));
1182
- columns = input([], ...(ngDevMode ? [{ debugName: "columns" }] : []));
1183
- sortFields = input([], ...(ngDevMode ? [{ debugName: "sortFields" }] : []));
1184
- selectedViewType = signal("table", ...(ngDevMode ? [{ debugName: "selectedViewType" }] : []));
1185
- pageSize = 20;
1186
- pageSizeOptions = [20, 50, 100];
1187
- dataSource = undefined;
1188
- sort = viewChild(MatSort, ...(ngDevMode ? [{ debugName: "sort" }] : []));
1189
- columnNames = computed(() => this.columns().map(c => c.name), ...(ngDevMode ? [{ debugName: "columnNames" }] : []));
1190
- searchTerm = "";
1191
- ngOnInit() {
1192
- this.selectedViewType.set(this.viewType());
1193
- this.resetDataSource();
1194
- }
1195
- ngAfterViewInit() {
1196
- const sort = this.sort();
1197
- if (sort) {
1198
- sort.sortChange.pipe(tap(() => this.reset())).subscribe();
1199
- }
1200
- }
1201
- onSearchChange(value) {
1202
- this.searchTerm = value;
1203
- this.reset();
1204
- }
1205
- canCreate() {
1206
- const item_service = this.itemService();
1207
- if (item_service) {
1208
- return item_service.canCreate();
1209
- }
1210
- return false;
1211
- }
1212
- itemType() {
1213
- const item_service = this.itemService();
1214
- if (item_service) {
1215
- return item_service.itemType;
1216
- }
1217
- return "";
1218
- }
1219
- isTableView() {
1220
- return this.selectedViewType() === "table";
1221
- }
1222
- resetDataSource() {
1223
- const item_service = this.itemService();
1224
- if (item_service) {
1225
- this.dataSource = new ListDataSource(item_service, this.selectedViewType());
1226
- }
1227
- this.reset();
1228
- }
1229
- reset() {
1230
- if (this.dataSource) {
1231
- this.dataSource.reset(this.searchTerm, this.pageSize);
1232
- }
1233
- }
1234
- viewChanged(event) {
1235
- this.selectedViewType.set(event.value);
1236
- console.log(this.selectedViewType());
1237
- this.resetDataSource();
1238
- }
1239
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: ListViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1240
- 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 } }, 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\">{{ itemType() | titlecase }}</h1>\n\n @if (canCreate()) {\n <div class=\"button-container\">\n <a mat-fab class=\"padded-button\" \n aria-label=\"Add new item\" \n matTooltip=\"Add new item\" [routerLink]=\"['create']\">\n <mat-icon>add</mat-icon></a>\n </div>\n }\n </div>\n\n <div class=\"controls\">\n <lib-search-bar \n [itemType]=\"itemType()\"\n [sortFields]=\"sortFields()\"\n (searchChanged)=\"onSearchChange($event)\"\n ></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 <mat-button-toggle value=\"table\" matTooltip=\"Show as table\">\n <mat-icon>table_view</mat-icon>\n </mat-button-toggle>\n <mat-button-toggle value=\"scroll\" matTooltip=\"Show as list\">\n <mat-icon>list</mat-icon>\n </mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n }\n </div>\n\n @if (dataSource && dataSource.loading()) {\n <div class=\"spinner-container\">\n <mat-spinner></mat-spinner>\n </div>\n }\n\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</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}\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$5.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$5.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: i3.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.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" }] });
1241
- }
1242
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: ListViewComponent, decorators: [{
1243
- type: Component,
1244
- args: [{ selector: 'lib-list-view', imports: [ListTableViewComponent,
1245
- ListScrollViewComponent,
1246
- BackButtonComponent,
1247
- MatFormFieldModule,
1248
- MatButtonToggleModule,
1249
- MatProgressSpinnerModule,
1250
- MatIconModule,
1251
- ReactiveFormsModule,
1252
- RouterModule,
1253
- TitleCasePipe,
1254
- MatInputModule,
1255
- MatTooltipModule,
1256
- MatButtonModule,
1257
- SearchBarComponent], template: "<lib-back-button></lib-back-button>\n\n<div class=\"container\">\n <div class=\"header\">\n <h1 class=\"title\">{{ itemType() | titlecase }}</h1>\n\n @if (canCreate()) {\n <div class=\"button-container\">\n <a mat-fab class=\"padded-button\" \n aria-label=\"Add new item\" \n matTooltip=\"Add new item\" [routerLink]=\"['create']\">\n <mat-icon>add</mat-icon></a>\n </div>\n }\n </div>\n\n <div class=\"controls\">\n <lib-search-bar \n [itemType]=\"itemType()\"\n [sortFields]=\"sortFields()\"\n (searchChanged)=\"onSearchChange($event)\"\n ></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 <mat-button-toggle value=\"table\" matTooltip=\"Show as table\">\n <mat-icon>table_view</mat-icon>\n </mat-button-toggle>\n <mat-button-toggle value=\"scroll\" matTooltip=\"Show as list\">\n <mat-icon>list</mat-icon>\n </mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n }\n </div>\n\n @if (dataSource && dataSource.loading()) {\n <div class=\"spinner-container\">\n <mat-spinner></mat-spinner>\n </div>\n }\n\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</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}\n"] }]
1258
- }] });
1259
-
1260
- class UserListDetailComponent {
1261
- item = input(...(ngDevMode ? [undefined, { debugName: "item" }] : []));
1262
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: UserListDetailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1263
- 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$3.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { 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" }] });
1264
- }
1265
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: UserListDetailComponent, decorators: [{
1266
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: UserListDetailComponent, decorators: [{
1266
1267
  type: Component,
1267
1268
  args: [{ selector: 'lib-user-list-detail', imports: [MatListModule,
1268
1269
  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"] }]
@@ -1273,7 +1274,7 @@ class UserComponent {
1273
1274
  itemService = inject(UserService);
1274
1275
  columns = [{ name: 'username', title: 'Name', element_type: 'string' }];
1275
1276
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: UserComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1276
- 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.itemType + '/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"] }, { 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"] }] });
1277
+ 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.itemType + '/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"] }] });
1277
1278
  }
1278
1279
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: UserComponent, decorators: [{
1279
1280
  type: Component,
@@ -1302,76 +1303,13 @@ class GroupComponent {
1302
1303
  itemService = inject(GroupService);
1303
1304
  columns = [{ name: 'name', title: 'Name', element_type: 'string' }];
1304
1305
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: GroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1305
- 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"] }] });
1306
+ 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"] }] });
1306
1307
  }
1307
1308
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: GroupComponent, decorators: [{
1308
1309
  type: Component,
1309
1310
  args: [{ selector: 'lib-group', imports: [ListViewComponent], template: "<lib-list-view\n [itemService]=\"itemService\"\n [columns]=\"columns\"\n >\n</lib-list-view>\n\n", styles: [":host{flex-grow:1}\n"] }]
1310
1311
  }] });
1311
1312
 
1312
- class OrganizationComponent {
1313
- itemService = inject(OrganizationService);
1314
- columns = [{ name: 'name', title: 'Name', element_type: 'string' },
1315
- { name: 'website', title: 'Website', element_type: 'url' },
1316
- { name: 'is_partner', title: 'Is Partner', element_type: 'boolean' }];
1317
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: OrganizationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1318
- 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"] }] });
1319
- }
1320
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: OrganizationComponent, decorators: [{
1321
- type: Component,
1322
- args: [{ selector: 'lib-organization', imports: [
1323
- ListViewComponent
1324
- ], 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"] }]
1325
- }] });
1326
-
1327
- class AddressService extends ItemService {
1328
- _url = Address.plural;
1329
- itemType = Address.plural;
1330
- instantiateType(item) {
1331
- return new Address(item);
1332
- }
1333
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: AddressService, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
1334
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: AddressService, providedIn: 'root' });
1335
- }
1336
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: AddressService, decorators: [{
1337
- type: Injectable,
1338
- args: [{
1339
- providedIn: 'root'
1340
- }]
1341
- }] });
1342
-
1343
- class AddressDetailComponent {
1344
- address = input(...(ngDevMode ? [undefined, { debugName: "address" }] : []));
1345
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: AddressDetailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1346
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: AddressDetailComponent, isStandalone: true, selector: "lib-address-detail", inputs: { address: { classPropertyName: "address", publicName: "address", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if(address(); as address){\n<div class=\"item-field\" style=\"display:flex;flex-wrap: wrap;justify-content: center;align-content: center;\">\n <span style=\"margin-left: 3px;\">{{address.line1}}, </span>\n <span style=\"margin-left: 3px;\">{{address.line2}},</span>\n @if(address.line3){\n <span style=\"margin-left: 3px;\">{{address.line3}},</span>\n }\n @if(address.city){\n <span style=\"margin-left: 3px;\">{{address.city}},</span>\n }\n <span style=\"margin-left: 3px;\">{{address.region}},</span>\n @if(address.postcode){ \n <span style=\"margin-left: 3px;\">{{address.postcode}},</span>\n }\n <span style=\"margin-left: 3px;\">{{address.country_name}}</span>\n</div>\n}", styles: [""] });
1347
- }
1348
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: AddressDetailComponent, decorators: [{
1349
- type: Component,
1350
- args: [{ selector: 'lib-address-detail', imports: [], template: "@if(address(); as address){\n<div class=\"item-field\" style=\"display:flex;flex-wrap: wrap;justify-content: center;align-content: center;\">\n <span style=\"margin-left: 3px;\">{{address.line1}}, </span>\n <span style=\"margin-left: 3px;\">{{address.line2}},</span>\n @if(address.line3){\n <span style=\"margin-left: 3px;\">{{address.line3}},</span>\n }\n @if(address.city){\n <span style=\"margin-left: 3px;\">{{address.city}},</span>\n }\n <span style=\"margin-left: 3px;\">{{address.region}},</span>\n @if(address.postcode){ \n <span style=\"margin-left: 3px;\">{{address.postcode}},</span>\n }\n <span style=\"margin-left: 3px;\">{{address.country_name}}</span>\n</div>\n}" }]
1351
- }] });
1352
-
1353
- class OrganizationDetailComponent extends DetailView {
1354
- typename = "organization";
1355
- address = signal(null, ...(ngDevMode ? [{ debugName: "address" }] : []));
1356
- addressService = inject(AddressService);
1357
- constructor() {
1358
- super(inject(OrganizationService));
1359
- }
1360
- ngOnInit() {
1361
- this.onInit();
1362
- }
1363
- onItemAndUserAvailable(item, _user) {
1364
- this.addressService.getUrl(item.address).subscribe(address => this.address.set(address));
1365
- }
1366
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: OrganizationDetailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1367
- 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]=\"typename\"></lib-detail-header>\n\n <div class=\"item-field\">\n {{item.description}}\n </div>\n \n @if(address(); as address)\n {\n <h3>Address</h3>\n <lib-address-detail [address]=\"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"] }] });
1368
- }
1369
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: OrganizationDetailComponent, decorators: [{
1370
- type: Component,
1371
- args: [{ selector: 'lib-organization-detail', imports: [BackButtonComponent,
1372
- 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]=\"typename\"></lib-detail-header>\n\n <div class=\"item-field\">\n {{item.description}}\n </div>\n \n @if(address(); as address)\n {\n <h3>Address</h3>\n <lib-address-detail [address]=\"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"] }]
1373
- }], ctorParameters: () => [] });
1374
-
1375
1313
  class AddressEditComponent {
1376
1314
  countryOptions = input([], ...(ngDevMode ? [{ debugName: "countryOptions" }] : []));
1377
1315
  form = input(...(ngDevMode ? [undefined, { debugName: "form" }] : []));
@@ -1387,6 +1325,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImpor
1387
1325
  ], 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\" required>\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\" required>\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\" required>\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\" required>\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}" }]
1388
1326
  }] });
1389
1327
 
1328
+ class AddressDetailComponent {
1329
+ address = input(...(ngDevMode ? [undefined, { debugName: "address" }] : []));
1330
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: AddressDetailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1331
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: AddressDetailComponent, isStandalone: true, selector: "lib-address-detail", inputs: { address: { classPropertyName: "address", publicName: "address", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if(address(); as address){\n<div class=\"item-field\" style=\"display:flex;flex-wrap: wrap;justify-content: center;align-content: center;\">\n <span style=\"margin-left: 3px;\">{{address.line1}}, </span>\n <span style=\"margin-left: 3px;\">{{address.line2}},</span>\n @if(address.line3){\n <span style=\"margin-left: 3px;\">{{address.line3}},</span>\n }\n @if(address.city){\n <span style=\"margin-left: 3px;\">{{address.city}},</span>\n }\n <span style=\"margin-left: 3px;\">{{address.region}},</span>\n @if(address.postcode){ \n <span style=\"margin-left: 3px;\">{{address.postcode}},</span>\n }\n <span style=\"margin-left: 3px;\">{{address.country_name}}</span>\n</div>\n}", styles: [""] });
1332
+ }
1333
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: AddressDetailComponent, decorators: [{
1334
+ type: Component,
1335
+ args: [{ selector: 'lib-address-detail', imports: [], template: "@if(address(); as address){\n<div class=\"item-field\" style=\"display:flex;flex-wrap: wrap;justify-content: center;align-content: center;\">\n <span style=\"margin-left: 3px;\">{{address.line1}}, </span>\n <span style=\"margin-left: 3px;\">{{address.line2}},</span>\n @if(address.line3){\n <span style=\"margin-left: 3px;\">{{address.line3}},</span>\n }\n @if(address.city){\n <span style=\"margin-left: 3px;\">{{address.city}},</span>\n }\n <span style=\"margin-left: 3px;\">{{address.region}},</span>\n @if(address.postcode){ \n <span style=\"margin-left: 3px;\">{{address.postcode}},</span>\n }\n <span style=\"margin-left: 3px;\">{{address.country_name}}</span>\n</div>\n}" }]
1336
+ }] });
1337
+
1390
1338
  class AddressForm {
1391
1339
  formBuilder = inject(FormBuilder);
1392
1340
  form = this.formBuilder.group({
@@ -1422,6 +1370,43 @@ class AddressForm {
1422
1370
  }
1423
1371
  }
1424
1372
 
1373
+ class OrganizationComponent {
1374
+ itemService = inject(OrganizationService);
1375
+ columns = [{ name: 'name', title: 'Name', element_type: 'string' },
1376
+ { name: 'website', title: 'Website', element_type: 'url' },
1377
+ { name: 'is_partner', title: 'Is Partner', element_type: 'boolean' }];
1378
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: OrganizationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1379
+ 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"] }] });
1380
+ }
1381
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: OrganizationComponent, decorators: [{
1382
+ type: Component,
1383
+ args: [{ selector: 'lib-organization', imports: [
1384
+ ListViewComponent
1385
+ ], 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"] }]
1386
+ }] });
1387
+
1388
+ class OrganizationDetailComponent extends DetailView {
1389
+ typename = "organization";
1390
+ address = signal(null, ...(ngDevMode ? [{ debugName: "address" }] : []));
1391
+ addressService = inject(AddressService);
1392
+ constructor() {
1393
+ super(inject(OrganizationService));
1394
+ }
1395
+ ngOnInit() {
1396
+ this.onInit();
1397
+ }
1398
+ onItemAndUserAvailable(item, _user) {
1399
+ this.addressService.getUrl(item.address).subscribe(address => this.address.set(address));
1400
+ }
1401
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: OrganizationDetailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1402
+ 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]=\"typename\"></lib-detail-header>\n\n <div class=\"item-field\">\n {{item.description}}\n </div>\n \n @if(address(); as address)\n {\n <h3>Address</h3>\n <lib-address-detail [address]=\"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"] }] });
1403
+ }
1404
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: OrganizationDetailComponent, decorators: [{
1405
+ type: Component,
1406
+ args: [{ selector: 'lib-organization-detail', imports: [BackButtonComponent,
1407
+ 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]=\"typename\"></lib-detail-header>\n\n <div class=\"item-field\">\n {{item.description}}\n </div>\n \n @if(address(); as address)\n {\n <h3>Address</h3>\n <lib-address-detail [address]=\"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"] }]
1408
+ }], ctorParameters: () => [] });
1409
+
1425
1410
  class OrganizationForm {
1426
1411
  formBuilder = inject(FormBuilder);
1427
1412
  form;
@@ -1588,5 +1573,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImpor
1588
1573
  * Generated bundle index. Do not edit.
1589
1574
  */
1590
1575
 
1591
- export { ApiError, BackButtonComponent, DetailHeaderComponent, DetailView, ENDPOINT_URL, EditView, ErrorCode, FileRecord, FileUploadComponent, Group, GroupComponent, GroupDetailComponent, GroupService, ItemQuery, LOGIN_USER, LandingComponent, LeftNavComponent, LeftNavService, ListView, OrganizationComponent, OrganizationDetailComponent, OrganizationEditComponent, OrganizationService, Paginated, Permission, PortalMember, ResolvedPermission, RestService, SelectTableComponent, TopBarComponent, UserComponent, UserDetailComponent, UserEditComponent, UserService };
1576
+ export { Address, AddressDetailComponent, AddressEditComponent, AddressForm, AddressService, ApiError, BackButtonComponent, DetailHeaderComponent, DetailView, ENDPOINT_URL, EditView, ErrorCode, FileRecord, FileUploadComponent, Group, GroupComponent, GroupDetailComponent, GroupService, ItemQuery, ItemService, LOGIN_USER, LandingComponent, LeftNavComponent, LeftNavService, ListTableViewComponent, ListView, ListViewComponent, Organization, OrganizationComponent, OrganizationDetailComponent, OrganizationEditComponent, OrganizationService, Paginated, Permission, PortalMember, ResolvedPermission, RestService, SearchBarComponent, SelectTableComponent, TopBarComponent, UserComponent, UserDetailComponent, UserEditComponent, UserService };
1592
1577
  //# sourceMappingURL=ichec-angular-core.mjs.map