ichec-angular-core 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,11 @@
1
- import { map, catchError, mergeMap, throwError, BehaviorSubject, tap, of, debounceTime, distinctUntilChanged, merge, Subscription, finalize } from 'rxjs';
1
+ import { BehaviorSubject, map, catchError, mergeMap, throwError, tap, of, debounceTime, distinctUntilChanged, merge, Subscription, finalize } from 'rxjs';
2
2
  import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
3
3
  import * as i0 from '@angular/core';
4
4
  import { InjectionToken, inject, DOCUMENT, Injectable, signal, Component, computed, input, output, viewChild } from '@angular/core';
5
5
  import { CookieService } from 'ngx-cookie-service';
6
6
  import * as i1$2 from '@angular/forms';
7
7
  import { FormControl, Validators, FormGroup, ReactiveFormsModule, FormBuilder } from '@angular/forms';
8
- import { Location, NgTemplateOutlet, TitleCasePipe, DatePipe } from '@angular/common';
8
+ import { Location, NgTemplateOutlet, TitleCasePipe, DatePipe, NgStyle } from '@angular/common';
9
9
  import * as i1$3 from '@angular/router';
10
10
  import { ActivatedRoute, RouterModule, RouterOutlet } from '@angular/router';
11
11
  import { MatDialogRef, MAT_DIALOG_DATA, MatDialogTitle, MatDialogContent, MatDialogActions, MatDialogClose, MatDialog } from '@angular/material/dialog';
@@ -178,7 +178,7 @@ class FileRecord {
178
178
 
179
179
  const REST_SERVICE_CONFIG = new InjectionToken("Config for the rest service");
180
180
  class RestService {
181
- manifest = { login_url: "", logout_url: "", supports_cors: false };
181
+ manifest = new BehaviorSubject(null);
182
182
  _url = "";
183
183
  config = inject(REST_SERVICE_CONFIG);
184
184
  _http = inject(HttpClient);
@@ -190,7 +190,14 @@ class RestService {
190
190
  query.queries.set('user', user.id.toString());
191
191
  return this.get(query);
192
192
  }
193
+ _getServiceManifest() {
194
+ console.log("Fetching service manifest");
195
+ return this._http.get(this.config.endpoint_url + "/manifest");
196
+ }
193
197
  get(query = new ItemQuery()) {
198
+ if (!this.manifest.value) {
199
+ this._getServiceManifest().subscribe(m => { this.manifest.next(m); this.get(query); });
200
+ }
194
201
  const params = query.queries;
195
202
  if (query.page > 0) {
196
203
  params.set('page', query.page.toString());
@@ -283,8 +290,12 @@ class RestService {
283
290
  return this.config.endpoint_url + "/api/" + this._url.slice(0, -1) + "_media/";
284
291
  }
285
292
  getRequestBase(content_type = "json", params = new HttpParams(), file = "") {
293
+ let supports_cors = "same-origin";
294
+ if (this.manifest.value && this.manifest.value.supports_cors) {
295
+ supports_cors = 'include';
296
+ }
286
297
  return { headers: this.getHeaders(content_type, file),
287
- credentials: this.manifest.supports_cors ? 'include' : 'same-origin',
298
+ credentials: supports_cors ? 'include' : 'same-origin',
288
299
  params: params };
289
300
  }
290
301
  handleError(error) {
@@ -337,7 +348,12 @@ class UserService extends ItemService {
337
348
  permissions = new Map();
338
349
  login(next = "/") {
339
350
  console.log("Starting login flow");
340
- this._getServiceManifest().subscribe(m => { this.manifest = m; this._do_login(next); });
351
+ if (this.manifest.value) {
352
+ this._do_login(next);
353
+ }
354
+ else {
355
+ this._getServiceManifest().subscribe(m => { this.manifest.next(m); this._do_login(next); });
356
+ }
341
357
  }
342
358
  logout(next = "") {
343
359
  if (this.loggedInUser.value === null) {
@@ -352,13 +368,13 @@ class UserService extends ItemService {
352
368
  if (next) {
353
369
  suffix = "?next=" + next;
354
370
  }
355
- console.log("posting logout to: ", prefix + this.manifest.logout_url + "/" + suffix);
356
- this._http.post(prefix + this.manifest.logout_url + "/" + suffix, "", {
371
+ console.log("posting logout to: ", prefix + this.manifest.value.logout_url + "/" + suffix);
372
+ this._http.post(prefix + this.manifest.value.logout_url + "/" + suffix, "", {
357
373
  headers: new HttpHeaders({
358
374
  'X-CSRFToken': this.cookieService.get("csrftoken")
359
375
  }),
360
376
  responseType: 'text',
361
- credentials: this.manifest.supports_cors ? 'include' : 'same-origin'
377
+ credentials: this.manifest.value.supports_cors ? 'include' : 'same-origin'
362
378
  }).pipe(
363
379
  // The backend can return an error as it tries to redirect to a non-existing url.
364
380
  catchError(_ => this.document.location.href = prefix + "/" + suffix)).subscribe(_ => {
@@ -370,7 +386,7 @@ class UserService extends ItemService {
370
386
  }
371
387
  getSelf() {
372
388
  console.log("Attempting to fetch self profile");
373
- return this._getServiceManifest().pipe(mergeMap(m => { this.manifest = m; return this._getSelf(); }));
389
+ return this._getServiceManifest().pipe(mergeMap(m => { this.manifest.next(m); return this._getSelf(); }));
374
390
  }
375
391
  _getSelf() {
376
392
  return this.getUrl(this.config.endpoint_url + "/api/self/").pipe(tap(user => this.onSelf(user)), map(user => { return user; }), catchError(e => this._selfFetchFailed(e)));
@@ -385,16 +401,12 @@ class UserService extends ItemService {
385
401
  return throwError(() => error);
386
402
  }
387
403
  }
388
- _getServiceManifest() {
389
- console.log("Fetching service manifest");
390
- return this._http.get(this.config.endpoint_url + "/manifest");
391
- }
392
404
  _do_login(next) {
393
405
  let prefix = "";
394
406
  if (this.config.endpoint_url) {
395
407
  prefix = this.config.endpoint_url + "/";
396
408
  }
397
- this.document.location.href = prefix + this.manifest.login_url + "/?next=" + next;
409
+ this.document.location.href = prefix + this.manifest.value.login_url + "/?next=" + next;
398
410
  }
399
411
  hasAddPermission(feature) {
400
412
  const perm = this.permissions.get(feature);
@@ -649,30 +661,39 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
649
661
  }], ctorParameters: () => [] });
650
662
 
651
663
  class LeftNavService {
652
- activeOptions = signal(new Set(), ...(ngDevMode ? [{ debugName: "activeOptions" }] : []));
664
+ activeGroupings = signal(new Set(), ...(ngDevMode ? [{ debugName: "activeGroupings" }] : []));
665
+ wide = signal(true, ...(ngDevMode ? [{ debugName: "wide" }] : []));
666
+ _defaultGroupings = [];
653
667
  _groups = [];
654
- _defaultOptions = [];
655
668
  _groupService = inject(GroupService);
656
669
  constructor() {
657
670
  this._groupService.userItems.subscribe(groups => this.onGroupsUpdated(groups));
658
671
  }
659
672
  onGroupsUpdated(groups) {
660
- const options = new Set();
661
- this._defaultOptions.forEach(e => options.add(e));
673
+ const groupings = new Set();
674
+ this._defaultGroupings.forEach(e => groupings.add(e));
662
675
  groups.forEach(g => this._groups.forEach(n => {
663
676
  if (n.name == g.name) {
664
- n.options.forEach(o => options.add(o));
677
+ n.groupings.forEach(g => groupings.add(g));
665
678
  }
666
679
  ;
667
680
  }));
668
- this.activeOptions.set(options);
681
+ this.activeGroupings.set(groupings);
669
682
  }
670
- setDefaultOptions(options) {
671
- this._defaultOptions = options;
683
+ setDefaultGroupings(groupings) {
684
+ this._defaultGroupings = groupings;
672
685
  }
673
686
  setGroups(groups) {
674
687
  this._groups = groups;
675
688
  }
689
+ toggle() {
690
+ if (this.wide()) {
691
+ this.wide.set(false);
692
+ }
693
+ else {
694
+ this.wide.set(true);
695
+ }
696
+ }
676
697
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: LeftNavService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
677
698
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: LeftNavService, providedIn: 'root' });
678
699
  }
@@ -1082,11 +1103,11 @@ class BackButtonComponent {
1082
1103
  this.location.back();
1083
1104
  }
1084
1105
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: BackButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1085
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.3", type: BackButtonComponent, isStandalone: true, selector: "lib-back-button", ngImport: i0, template: "<a mat-icon-button class=\"padded-button\"\n (click)=\"goBack()\"\n (keydown)=\"goBack()\"\n tabindex=\"0\"\n role=\"button\">\n<mat-icon>arrow_back</mat-icon>\n</a>\n\n", styles: [".padded-button{margin-left:5px}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }] });
1106
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.3", type: BackButtonComponent, isStandalone: true, selector: "lib-back-button", ngImport: i0, template: "<a mat-icon-button class=\"padded-button\"\n (click)=\"goBack()\"\n (keydown)=\"goBack()\"\n tabindex=\"0\"\n role=\"button\">\n<mat-icon>arrow_back</mat-icon>\n</a>\n\n", styles: [":host{position:absolute}.padded-button{margin-left:5px;margin-top:5px}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }] });
1086
1107
  }
1087
1108
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: BackButtonComponent, decorators: [{
1088
1109
  type: Component,
1089
- 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-left:5px}\n"] }]
1110
+ 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: [":host{position:absolute}.padded-button{margin-left:5px;margin-top:5px}\n"] }]
1090
1111
  }] });
1091
1112
 
1092
1113
  class DetailHeaderComponent {
@@ -1787,8 +1808,10 @@ class ListScrollViewComponent {
1787
1808
  searchTerm = input("", ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
1788
1809
  pageSize = input(20, ...(ngDevMode ? [{ debugName: "pageSize" }] : []));
1789
1810
  itemHeight = input(100, ...(ngDevMode ? [{ debugName: "itemHeight" }] : []));
1811
+ itemWidth = input("200", ...(ngDevMode ? [{ debugName: "itemWidth" }] : []));
1790
1812
  dataSource = input(...(ngDevMode ? [undefined, { debugName: "dataSource" }] : []));
1791
1813
  listItemTemplate = input(null, ...(ngDevMode ? [{ debugName: "listItemTemplate" }] : []));
1814
+ routerMode = input(false, ...(ngDevMode ? [{ debugName: "routerMode" }] : []));
1792
1815
  selection = signal(null, ...(ngDevMode ? [{ debugName: "selection" }] : []));
1793
1816
  selected = output();
1794
1817
  reset() {
@@ -1805,14 +1828,14 @@ class ListScrollViewComponent {
1805
1828
  this.selected.emit(id);
1806
1829
  }
1807
1830
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: ListScrollViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1808
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.3", 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 }, itemHeight: { classPropertyName: "itemHeight", publicName: "itemHeight", 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 } }, outputs: { selected: "selected" }, ngImport: i0, template: "<mat-nav-list style=\"padding: 0px; display:flex; justify-content: center; \">\n <ul style=\"margin: 0px; padding: 0px\">\n <cdk-virtual-scroll-viewport\n itemSize=\"itemHeight()\"\n class=\"scrollable-list\"\n style=\"height: 600px; width: 300px; padding: 5px\"\n >\n <ng-container *cdkVirtualFor=\"let item of dataSource(); let even = even;\">\n <li style=\"margin: 0px; padding: 0px\" \n (click)=\"onSelected(item.id)\" \n (keydown)=\"onSelected(item.id)\"\n tabindex=\"0\"\n role=\"button\">\n <ng-container\n *ngTemplateOutlet=\"listItemTemplate(); context: { item: item, even: even, selected: item.id === selection()}\" \n >\n </ng-container>\n </li>\n </ng-container>\n </cdk-virtual-scroll-viewport>\n </ul>\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$3.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i2$3.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i2$3.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }] });
1831
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", 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 }, itemHeight: { classPropertyName: "itemHeight", publicName: "itemHeight", isSignal: true, isRequired: false, transformFunction: null }, itemWidth: { classPropertyName: "itemWidth", publicName: "itemWidth", 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 }, routerMode: { classPropertyName: "routerMode", publicName: "routerMode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selected: "selected" }, ngImport: i0, template: "<mat-nav-list style=\"padding: 0px; display:flex; justify-content: center; \">\n <cdk-virtual-scroll-viewport\n itemSize=\"itemHeight()\"\n class=\"scrollable-list\"\n style=\"width:100%\"\n >\n <ng-container *cdkVirtualFor=\"let item of dataSource(); let even = even;\">\n @if(routerMode())\n {\n <ng-container\n *ngTemplateOutlet=\"listItemTemplate(); context: { item: item, even: even, selected: item.id === selection()}\" \n >\n </ng-container>\n }\n @else \n {\n <li\n (click)=\"onSelected(item.id)\" \n (keydown)=\"onSelected(item.id)\"\n tabindex=\"0\"\n role=\"button\">\n <ng-container\n *ngTemplateOutlet=\"listItemTemplate(); context: { item: item, even: even, selected: item.id === selection()}\" \n >\n </ng-container> \n }\n </ng-container>\n </cdk-virtual-scroll-viewport>\n</mat-nav-list>\n", styles: [":host{flex-grow:1}.scrollable-list{height:600px;padding:5px}.tight{width:200px}.medium{width:300px}.wide{width:400px}ul,li{margin:0;padding:0;list-style-type:none;padding-inline-start:0;list-style:none}\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$3.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i2$3.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i2$3.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }] });
1809
1832
  }
1810
1833
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: ListScrollViewComponent, decorators: [{
1811
1834
  type: Component,
1812
1835
  args: [{ selector: 'lib-list-scroll-view', imports: [MatListModule,
1813
1836
  NgTemplateOutlet,
1814
- ScrollingModule], template: "<mat-nav-list style=\"padding: 0px; display:flex; justify-content: center; \">\n <ul style=\"margin: 0px; padding: 0px\">\n <cdk-virtual-scroll-viewport\n itemSize=\"itemHeight()\"\n class=\"scrollable-list\"\n style=\"height: 600px; width: 300px; padding: 5px\"\n >\n <ng-container *cdkVirtualFor=\"let item of dataSource(); let even = even;\">\n <li style=\"margin: 0px; padding: 0px\" \n (click)=\"onSelected(item.id)\" \n (keydown)=\"onSelected(item.id)\"\n tabindex=\"0\"\n role=\"button\">\n <ng-container\n *ngTemplateOutlet=\"listItemTemplate(); context: { item: item, even: even, selected: item.id === selection()}\" \n >\n </ng-container>\n </li>\n </ng-container>\n </cdk-virtual-scroll-viewport>\n </ul>\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"] }]
1815
- }], propDecorators: { searchTerm: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchTerm", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], itemHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemHeight", required: false }] }], dataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataSource", required: false }] }], listItemTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "listItemTemplate", required: false }] }], selected: [{ type: i0.Output, args: ["selected"] }] } });
1837
+ ScrollingModule], template: "<mat-nav-list style=\"padding: 0px; display:flex; justify-content: center; \">\n <cdk-virtual-scroll-viewport\n itemSize=\"itemHeight()\"\n class=\"scrollable-list\"\n style=\"width:100%\"\n >\n <ng-container *cdkVirtualFor=\"let item of dataSource(); let even = even;\">\n @if(routerMode())\n {\n <ng-container\n *ngTemplateOutlet=\"listItemTemplate(); context: { item: item, even: even, selected: item.id === selection()}\" \n >\n </ng-container>\n }\n @else \n {\n <li\n (click)=\"onSelected(item.id)\" \n (keydown)=\"onSelected(item.id)\"\n tabindex=\"0\"\n role=\"button\">\n <ng-container\n *ngTemplateOutlet=\"listItemTemplate(); context: { item: item, even: even, selected: item.id === selection()}\" \n >\n </ng-container> \n }\n </ng-container>\n </cdk-virtual-scroll-viewport>\n</mat-nav-list>\n", styles: [":host{flex-grow:1}.scrollable-list{height:600px;padding:5px}.tight{width:200px}.medium{width:300px}.wide{width:400px}ul,li{margin:0;padding:0;list-style-type:none;padding-inline-start:0;list-style:none}\n"] }]
1838
+ }], propDecorators: { searchTerm: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchTerm", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], itemHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemHeight", required: false }] }], itemWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemWidth", required: false }] }], dataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataSource", required: false }] }], listItemTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "listItemTemplate", required: false }] }], routerMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "routerMode", required: false }] }], selected: [{ type: i0.Output, args: ["selected"] }] } });
1816
1839
 
1817
1840
  class ListDataSource extends DataSource {
1818
1841
  length = signal(0, ...(ngDevMode ? [{ debugName: "length" }] : []));
@@ -1922,6 +1945,7 @@ class ListViewComponent {
1922
1945
  listItemTemplate = input(null, ...(ngDevMode ? [{ debugName: "listItemTemplate" }] : []));
1923
1946
  itemDetailTemplate = input(null, ...(ngDevMode ? [{ debugName: "itemDetailTemplate" }] : []));
1924
1947
  itemHeight = input(100, ...(ngDevMode ? [{ debugName: "itemHeight" }] : []));
1948
+ itemWidth = input(300, ...(ngDevMode ? [{ debugName: "itemWidth" }] : []));
1925
1949
  columns = input([], ...(ngDevMode ? [{ debugName: "columns" }] : []));
1926
1950
  sortFields = input([], ...(ngDevMode ? [{ debugName: "sortFields" }] : []));
1927
1951
  noSelfItemsMessage = input(...(ngDevMode ? [undefined, { debugName: "noSelfItemsMessage" }] : []));
@@ -1938,6 +1962,14 @@ class ListViewComponent {
1938
1962
  sort = viewChild(MatSort, ...(ngDevMode ? [{ debugName: "sort" }] : []));
1939
1963
  columnNames = computed(() => this.columns().map(c => c.name), ...(ngDevMode ? [{ debugName: "columnNames" }] : []));
1940
1964
  searchTerm = "";
1965
+ get resolvedItemWidth() {
1966
+ if (this.itemDetailTemplate()) {
1967
+ return (this.itemWidth() + 50).toString() + "px";
1968
+ }
1969
+ else {
1970
+ return "100%";
1971
+ }
1972
+ }
1941
1973
  ngOnInit() {
1942
1974
  this.selectedViewType.set(this.viewType());
1943
1975
  this.resetDataSource();
@@ -2002,7 +2034,7 @@ class ListViewComponent {
2002
2034
  return (url_segments.length == 2) && (url_segments[1].path == "self");
2003
2035
  }
2004
2036
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: ListViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2005
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", 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 }, listItemTemplate: { classPropertyName: "listItemTemplate", publicName: "listItemTemplate", isSignal: true, isRequired: false, transformFunction: null }, itemDetailTemplate: { classPropertyName: "itemDetailTemplate", publicName: "itemDetailTemplate", isSignal: true, isRequired: false, transformFunction: null }, itemHeight: { classPropertyName: "itemHeight", publicName: "itemHeight", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, sortFields: { classPropertyName: "sortFields", publicName: "sortFields", isSignal: true, isRequired: false, transformFunction: null }, noSelfItemsMessage: { classPropertyName: "noSelfItemsMessage", publicName: "noSelfItemsMessage", isSignal: true, isRequired: false, transformFunction: null }, noItemsCanCreateMessage: { classPropertyName: "noItemsCanCreateMessage", publicName: "noItemsCanCreateMessage", isSignal: true, isRequired: false, transformFunction: null }, noItemsMessage: { classPropertyName: "noItemsMessage", publicName: "noItemsMessage", isSignal: true, isRequired: false, transformFunction: null }, defaultQueries: { classPropertyName: "defaultQueries", publicName: "defaultQueries", isSignal: true, isRequired: false, transformFunction: null }, embeddedMode: { classPropertyName: "embeddedMode", publicName: "embeddedMode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selected: "selected" }, viewQueries: [{ propertyName: "sort", first: true, predicate: MatSort, descendants: true, isSignal: true }], ngImport: i0, template: "@if(!embeddedMode()){\n<lib-back-button style=\"position: absolute;\"></lib-back-button>\n}\n\n<div class=\"container\">\n <lib-list-header style=\"width:100%\"\n [itemType]=\"itemType()\" \n [canCreate]=\"canCreate()\" \n [showControls]=\"showControls()\"\n [sortFields]=\"sortFields()\"\n (searchChanged)=\"onSearchChange($event)\"></lib-list-header>\n\n <div class=\"content_container\" style=\"width:100%\">\n @if(dataSource)\n {\n <div class=\"search_result_container\" style=\"width:350px\">\n\n @if (dataSource.loading()) {\n <div class=\"spinner-container\">\n <mat-spinner></mat-spinner>\n </div>\n }\n\n @if(!embeddedMode()){\n <div [hidden]=\"!dataSource.sourceIsEmpty()\">\n @if(isSelfList())\n {\n @if(noSelfItemsMessage())\n {\n <p>{{noSelfItemsMessage()}}</p>\n }\n @else {\n <p>You do not have any {{itemType()}}.</p>\n }\n }\n @else{\n @if(canCreate()){\n @if(noItemsCanCreateMessage())\n {\n <p>{{noItemsCanCreateMessage()}}</p>\n }\n @else{\n <p>There are currently no {{itemType()}}, click above to add one.</p>\n }\n }\n @else{\n @if(noItemsMessage())\n {\n <p>{{noItemsMessage()}}</p>\n }\n @else\n {\n <p>There are currently no {{itemType()}}.</p>\n }\n }\n }\n </div>\n }\n\n <div style=\"width: 100%\" [hidden]=\"dataSource.sourceIsEmpty()\">\n @if(isTableView()) {\n <lib-list-table-view [itemType]=\"itemType()\" [columns]=\"columns()\" [dataSource]=\"dataSource\">\n </lib-list-table-view>\n }\n @else {\n <h2 style=\"margin-bottom:5px; margin-top: 0px; padding: 0px;\">Results: {{dataSource.length()}}</h2>\n <lib-list-scroll-view [listItemTemplate]=\"listItemTemplate()\" [itemHeight]=\"itemHeight()\" [dataSource]=\"dataSource\" (selected)=\"onSelection($event)\"></lib-list-scroll-view>\n }\n </div>\n </div>\n <div class=\"detail-container\" style=\"width:100%; min-width: 400px;\">\n <ng-container *ngTemplateOutlet=\"itemDetailTemplate()\">\n </ng-container>\n </div>\n }\n </div>\n</div>", styles: [":host{flex-grow:1}.container{display:flex;padding-left:10px;padding-right:10px;flex-direction:column;justify-content:center;text-align:center;align-items:center}.content_container{display:flex;flex-direction:row;justify-content:left;text-align:left;align-items:left}.hide-element{display:none}\n"], dependencies: [{ kind: "component", type: ListTableViewComponent, selector: "lib-list-table-view", inputs: ["itemType", "columns", "dataSource", "searchFilter"] }, { kind: "component", type: ListScrollViewComponent, selector: "lib-list-scroll-view", inputs: ["searchTerm", "pageSize", "itemHeight", "dataSource", "listItemTemplate"], outputs: ["selected"] }, { kind: "component", type: BackButtonComponent, selector: "lib-back-button" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i1$5.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: ListHeaderComponent, selector: "lib-list-header", inputs: ["itemType", "canCreate", "showControls", "sortFields"], outputs: ["searchChanged"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
2037
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", 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 }, listItemTemplate: { classPropertyName: "listItemTemplate", publicName: "listItemTemplate", isSignal: true, isRequired: false, transformFunction: null }, itemDetailTemplate: { classPropertyName: "itemDetailTemplate", publicName: "itemDetailTemplate", isSignal: true, isRequired: false, transformFunction: null }, itemHeight: { classPropertyName: "itemHeight", publicName: "itemHeight", isSignal: true, isRequired: false, transformFunction: null }, itemWidth: { classPropertyName: "itemWidth", publicName: "itemWidth", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, sortFields: { classPropertyName: "sortFields", publicName: "sortFields", isSignal: true, isRequired: false, transformFunction: null }, noSelfItemsMessage: { classPropertyName: "noSelfItemsMessage", publicName: "noSelfItemsMessage", isSignal: true, isRequired: false, transformFunction: null }, noItemsCanCreateMessage: { classPropertyName: "noItemsCanCreateMessage", publicName: "noItemsCanCreateMessage", isSignal: true, isRequired: false, transformFunction: null }, noItemsMessage: { classPropertyName: "noItemsMessage", publicName: "noItemsMessage", isSignal: true, isRequired: false, transformFunction: null }, defaultQueries: { classPropertyName: "defaultQueries", publicName: "defaultQueries", isSignal: true, isRequired: false, transformFunction: null }, embeddedMode: { classPropertyName: "embeddedMode", publicName: "embeddedMode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selected: "selected" }, viewQueries: [{ propertyName: "sort", first: true, predicate: MatSort, descendants: true, isSignal: true }], ngImport: i0, template: "@if(!embeddedMode()){\n<lib-back-button></lib-back-button>\n}\n\n<div class=\"container\">\n <lib-list-header style=\"width:100%\"\n [itemType]=\"itemType()\" \n [canCreate]=\"canCreate()\" \n [showControls]=\"showControls()\"\n [sortFields]=\"sortFields()\"\n (searchChanged)=\"onSearchChange($event)\"></lib-list-header>\n\n <div class=\"content_container\" style=\"width:100%\">\n @if(dataSource)\n {\n <div class=\"search_result_container\" [style.width]=\"resolvedItemWidth\">\n\n @if (dataSource.loading()) {\n <div class=\"spinner-container\">\n <mat-spinner></mat-spinner>\n </div>\n }\n\n @if(!embeddedMode()){\n <div [hidden]=\"!dataSource.sourceIsEmpty()\">\n @if(isSelfList())\n {\n @if(noSelfItemsMessage())\n {\n <p>{{noSelfItemsMessage()}}</p>\n }\n @else {\n <p>You do not have any {{itemType()}}.</p>\n }\n }\n @else{\n @if(canCreate()){\n @if(noItemsCanCreateMessage())\n {\n <p>{{noItemsCanCreateMessage()}}</p>\n }\n @else{\n <p>There are currently no {{itemType()}}, click above to add one.</p>\n }\n }\n @else{\n @if(noItemsMessage())\n {\n <p>{{noItemsMessage()}}</p>\n }\n @else\n {\n <p>There are currently no {{itemType()}}.</p>\n }\n }\n }\n </div>\n }\n\n <div style=\"width: 100%\" [hidden]=\"dataSource.sourceIsEmpty()\">\n @if(isTableView()) {\n <lib-list-table-view [itemType]=\"itemType()\" [columns]=\"columns()\" [dataSource]=\"dataSource\">\n </lib-list-table-view>\n }\n @else {\n <h2 style=\"margin-bottom:5px; margin-top: 0px; padding: 0px;\">Results: {{dataSource.length()}}</h2>\n <lib-list-scroll-view [listItemTemplate]=\"listItemTemplate()\" \n [itemHeight]=\"itemHeight()\" \n [itemWidth]=\"itemWidth().toString()\"\n [dataSource]=\"dataSource\" \n (selected)=\"onSelection($event)\"></lib-list-scroll-view>\n }\n </div>\n </div>\n @if(itemDetailTemplate()){\n <div class=\"detail-container\" style=\"width:100%; min-width: 400px;\">\n <ng-container *ngTemplateOutlet=\"itemDetailTemplate()\">\n </ng-container>\n </div>\n }\n }\n </div>\n</div>", styles: [":host{flex-grow:1}.container{display:flex;padding-left:10px;padding-right:10px;flex-direction:column;justify-content:center;text-align:center;align-items:center}.content_container{display:flex;flex-direction:row;justify-content:left;text-align:left;align-items:left}.hide-element{display:none}\n"], dependencies: [{ kind: "component", type: ListTableViewComponent, selector: "lib-list-table-view", inputs: ["itemType", "columns", "dataSource", "searchFilter"] }, { kind: "component", type: ListScrollViewComponent, selector: "lib-list-scroll-view", inputs: ["searchTerm", "pageSize", "itemHeight", "itemWidth", "dataSource", "listItemTemplate", "routerMode"], outputs: ["selected"] }, { kind: "component", type: BackButtonComponent, selector: "lib-back-button" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i1$5.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: ListHeaderComponent, selector: "lib-list-header", inputs: ["itemType", "canCreate", "showControls", "sortFields"], outputs: ["searchChanged"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
2006
2038
  }
2007
2039
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: ListViewComponent, decorators: [{
2008
2040
  type: Component,
@@ -2019,8 +2051,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
2019
2051
  MatTooltipModule,
2020
2052
  MatButtonModule,
2021
2053
  ListHeaderComponent,
2022
- NgTemplateOutlet], template: "@if(!embeddedMode()){\n<lib-back-button style=\"position: absolute;\"></lib-back-button>\n}\n\n<div class=\"container\">\n <lib-list-header style=\"width:100%\"\n [itemType]=\"itemType()\" \n [canCreate]=\"canCreate()\" \n [showControls]=\"showControls()\"\n [sortFields]=\"sortFields()\"\n (searchChanged)=\"onSearchChange($event)\"></lib-list-header>\n\n <div class=\"content_container\" style=\"width:100%\">\n @if(dataSource)\n {\n <div class=\"search_result_container\" style=\"width:350px\">\n\n @if (dataSource.loading()) {\n <div class=\"spinner-container\">\n <mat-spinner></mat-spinner>\n </div>\n }\n\n @if(!embeddedMode()){\n <div [hidden]=\"!dataSource.sourceIsEmpty()\">\n @if(isSelfList())\n {\n @if(noSelfItemsMessage())\n {\n <p>{{noSelfItemsMessage()}}</p>\n }\n @else {\n <p>You do not have any {{itemType()}}.</p>\n }\n }\n @else{\n @if(canCreate()){\n @if(noItemsCanCreateMessage())\n {\n <p>{{noItemsCanCreateMessage()}}</p>\n }\n @else{\n <p>There are currently no {{itemType()}}, click above to add one.</p>\n }\n }\n @else{\n @if(noItemsMessage())\n {\n <p>{{noItemsMessage()}}</p>\n }\n @else\n {\n <p>There are currently no {{itemType()}}.</p>\n }\n }\n }\n </div>\n }\n\n <div style=\"width: 100%\" [hidden]=\"dataSource.sourceIsEmpty()\">\n @if(isTableView()) {\n <lib-list-table-view [itemType]=\"itemType()\" [columns]=\"columns()\" [dataSource]=\"dataSource\">\n </lib-list-table-view>\n }\n @else {\n <h2 style=\"margin-bottom:5px; margin-top: 0px; padding: 0px;\">Results: {{dataSource.length()}}</h2>\n <lib-list-scroll-view [listItemTemplate]=\"listItemTemplate()\" [itemHeight]=\"itemHeight()\" [dataSource]=\"dataSource\" (selected)=\"onSelection($event)\"></lib-list-scroll-view>\n }\n </div>\n </div>\n <div class=\"detail-container\" style=\"width:100%; min-width: 400px;\">\n <ng-container *ngTemplateOutlet=\"itemDetailTemplate()\">\n </ng-container>\n </div>\n }\n </div>\n</div>", styles: [":host{flex-grow:1}.container{display:flex;padding-left:10px;padding-right:10px;flex-direction:column;justify-content:center;text-align:center;align-items:center}.content_container{display:flex;flex-direction:row;justify-content:left;text-align:left;align-items:left}.hide-element{display:none}\n"] }]
2023
- }], propDecorators: { viewType: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewType", required: false }] }], itemService: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemService", required: false }] }], listItemTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "listItemTemplate", required: false }] }], itemDetailTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemDetailTemplate", required: false }] }], itemHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemHeight", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], sortFields: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortFields", required: false }] }], noSelfItemsMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "noSelfItemsMessage", required: false }] }], noItemsCanCreateMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "noItemsCanCreateMessage", required: false }] }], noItemsMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "noItemsMessage", required: false }] }], defaultQueries: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultQueries", required: false }] }], embeddedMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "embeddedMode", required: false }] }], selected: [{ type: i0.Output, args: ["selected"] }], sort: [{ type: i0.ViewChild, args: [i0.forwardRef(() => MatSort), { isSignal: true }] }] } });
2054
+ NgTemplateOutlet], template: "@if(!embeddedMode()){\n<lib-back-button></lib-back-button>\n}\n\n<div class=\"container\">\n <lib-list-header style=\"width:100%\"\n [itemType]=\"itemType()\" \n [canCreate]=\"canCreate()\" \n [showControls]=\"showControls()\"\n [sortFields]=\"sortFields()\"\n (searchChanged)=\"onSearchChange($event)\"></lib-list-header>\n\n <div class=\"content_container\" style=\"width:100%\">\n @if(dataSource)\n {\n <div class=\"search_result_container\" [style.width]=\"resolvedItemWidth\">\n\n @if (dataSource.loading()) {\n <div class=\"spinner-container\">\n <mat-spinner></mat-spinner>\n </div>\n }\n\n @if(!embeddedMode()){\n <div [hidden]=\"!dataSource.sourceIsEmpty()\">\n @if(isSelfList())\n {\n @if(noSelfItemsMessage())\n {\n <p>{{noSelfItemsMessage()}}</p>\n }\n @else {\n <p>You do not have any {{itemType()}}.</p>\n }\n }\n @else{\n @if(canCreate()){\n @if(noItemsCanCreateMessage())\n {\n <p>{{noItemsCanCreateMessage()}}</p>\n }\n @else{\n <p>There are currently no {{itemType()}}, click above to add one.</p>\n }\n }\n @else{\n @if(noItemsMessage())\n {\n <p>{{noItemsMessage()}}</p>\n }\n @else\n {\n <p>There are currently no {{itemType()}}.</p>\n }\n }\n }\n </div>\n }\n\n <div style=\"width: 100%\" [hidden]=\"dataSource.sourceIsEmpty()\">\n @if(isTableView()) {\n <lib-list-table-view [itemType]=\"itemType()\" [columns]=\"columns()\" [dataSource]=\"dataSource\">\n </lib-list-table-view>\n }\n @else {\n <h2 style=\"margin-bottom:5px; margin-top: 0px; padding: 0px;\">Results: {{dataSource.length()}}</h2>\n <lib-list-scroll-view [listItemTemplate]=\"listItemTemplate()\" \n [itemHeight]=\"itemHeight()\" \n [itemWidth]=\"itemWidth().toString()\"\n [dataSource]=\"dataSource\" \n (selected)=\"onSelection($event)\"></lib-list-scroll-view>\n }\n </div>\n </div>\n @if(itemDetailTemplate()){\n <div class=\"detail-container\" style=\"width:100%; min-width: 400px;\">\n <ng-container *ngTemplateOutlet=\"itemDetailTemplate()\">\n </ng-container>\n </div>\n }\n }\n </div>\n</div>", styles: [":host{flex-grow:1}.container{display:flex;padding-left:10px;padding-right:10px;flex-direction:column;justify-content:center;text-align:center;align-items:center}.content_container{display:flex;flex-direction:row;justify-content:left;text-align:left;align-items:left}.hide-element{display:none}\n"] }]
2055
+ }], propDecorators: { viewType: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewType", required: false }] }], itemService: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemService", required: false }] }], listItemTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "listItemTemplate", required: false }] }], itemDetailTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemDetailTemplate", required: false }] }], itemHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemHeight", required: false }] }], itemWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemWidth", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], sortFields: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortFields", required: false }] }], noSelfItemsMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "noSelfItemsMessage", required: false }] }], noItemsCanCreateMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "noItemsCanCreateMessage", required: false }] }], noItemsMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "noItemsMessage", required: false }] }], defaultQueries: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultQueries", required: false }] }], embeddedMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "embeddedMode", required: false }] }], selected: [{ type: i0.Output, args: ["selected"] }], sort: [{ type: i0.ViewChild, args: [i0.forwardRef(() => MatSort), { isSignal: true }] }] } });
2024
2056
 
2025
2057
  class TopBarComponent {
2026
2058
  title = input(...(ngDevMode ? [undefined, { debugName: "title" }] : []));
@@ -2029,6 +2061,7 @@ class TopBarComponent {
2029
2061
  user = signal(null, ...(ngDevMode ? [{ debugName: "user" }] : []));
2030
2062
  loginRoute = input("home", ...(ngDevMode ? [{ debugName: "loginRoute" }] : []));
2031
2063
  userService = inject(UserService);
2064
+ leftNavService = inject(LeftNavService);
2032
2065
  constructor() {
2033
2066
  this.userService.loggedInUser.subscribe(user => this.user.set(user));
2034
2067
  }
@@ -2054,7 +2087,7 @@ class TopBarComponent {
2054
2087
  }
2055
2088
  }
2056
2089
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: TopBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2057
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: TopBarComponent, isStandalone: true, selector: "lib-top-bar", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, logo: { classPropertyName: "logo", publicName: "logo", isSignal: true, isRequired: false, transformFunction: null }, background: { classPropertyName: "background", publicName: "background", isSignal: true, isRequired: false, transformFunction: null }, loginRoute: { classPropertyName: "loginRoute", publicName: "loginRoute", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<mat-toolbar class=\"toolbar\" [style.background-image]=\"backgroundStyle\">\n\n @if(logo())\n {\n <a aria-label=\"Home\" [routerLink]=\"['home']\">\n <img src=\"{{logo()}}\" class=\"logo\" alt=\"Website logo\"/>\n </a>\n }\n @else {\n <a mat-icon-button aria-label=\"Home\" [routerLink]=\"['home']\">\n <mat-icon class=\"icon\">home</mat-icon>\n </a>\n <span>{{title()}}</span>\n }\n <span class=\"topbar-spacer\"></span>\n @if(user(); as user)\n {\n <span>{{user.username}}</span>\n \n <button mat-icon-button style=\"margin: 5px\" aria-label=\"User Profile\" [matMenuTriggerFor]=\"profile_menu\">\n <mat-icon class=\"icon\">person</mat-icon>\n </button>\n\n <mat-menu #profile_menu=\"matMenu\">\n <a mat-menu-item aria-label=\"My Profile\" [routerLink]=\"['/members/detail', user.id]\">\n <mat-icon>manage_accounts</mat-icon>\n <span>My Profile</span>\n </a> \n <a mat-menu-item aria-label=\"Get Support\" [routerLink]=\"['/feedback']\">\n <mat-icon>contact_support</mat-icon>\n <span>Get Support</span>\n </a> \n <button mat-menu-item (click)=\"onLogout()\">\n <mat-icon>logout</mat-icon>\n <span>Log Out</span>\n </button>\n\n </mat-menu>\n }\n @else {\n <span>Log In</span>\n <button matIconButton (click)=\"onLogin()\">\n <mat-icon class=\"icon\">login</mat-icon>\n </button>\n }\n</mat-toolbar>\n", styles: [".topbar-spacer{flex:1 1 auto}.toolbar{height:60px;background-size:cover;--mat-toolbar-container-background-color: var(--mat-sys-primary);--mat-toolbar-container-text-color: var(--mat-sys-on-primary)}.logo{height:50px;margin-top:5px}.icon{color:var(--mat-sys-on-primary)}\n"], dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$3.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: MatToolbarModule }, { kind: "component", type: i2$4.MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i5$1.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i5$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i5$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }] });
2090
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: TopBarComponent, isStandalone: true, selector: "lib-top-bar", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, logo: { classPropertyName: "logo", publicName: "logo", isSignal: true, isRequired: false, transformFunction: null }, background: { classPropertyName: "background", publicName: "background", isSignal: true, isRequired: false, transformFunction: null }, loginRoute: { classPropertyName: "loginRoute", publicName: "loginRoute", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<mat-toolbar class=\"toolbar\" [style.background-image]=\"backgroundStyle\">\n\n @if(logo())\n {\n <a aria-label=\"Home\" [routerLink]=\"['home']\">\n <img src=\"{{logo()}}\" class=\"logo\" alt=\"Website logo\"/>\n </a>\n }\n @else {\n <a mat-icon-button aria-label=\"Home\" [routerLink]=\"['home']\">\n <mat-icon class=\"icon\">home</mat-icon>\n </a>\n <span>{{title()}}</span>\n }\n <button mat-icon-button style=\"margin: 5px\" aria-label=\"Toggle Nav Bar\">\n <mat-icon class=\"icon\" (click)=\"leftNavService.toggle()\">\n @if(leftNavService.wide()){\n menu\n }\n @else {\n menu_open\n }\n </mat-icon>\n </button>\n\n <span class=\"topbar-spacer\"></span>\n @if(user(); as user)\n {\n <span>{{user.username}}</span>\n \n <button mat-icon-button style=\"margin: 5px\" aria-label=\"User Profile\" [matMenuTriggerFor]=\"profile_menu\">\n <mat-icon class=\"icon\">person</mat-icon>\n </button>\n\n <mat-menu #profile_menu=\"matMenu\">\n <a mat-menu-item aria-label=\"My Profile\" [routerLink]=\"['/members/detail', user.id]\">\n <mat-icon>manage_accounts</mat-icon>\n <span>My Profile</span>\n </a> \n <a mat-menu-item aria-label=\"Get Support\" [routerLink]=\"['/feedback']\">\n <mat-icon>contact_support</mat-icon>\n <span>Get Support</span>\n </a> \n <button mat-menu-item (click)=\"onLogout()\">\n <mat-icon>logout</mat-icon>\n <span>Log Out</span>\n </button>\n\n </mat-menu>\n }\n @else {\n <span>Log In</span>\n <button matIconButton (click)=\"onLogin()\">\n <mat-icon class=\"icon\">login</mat-icon>\n </button>\n }\n</mat-toolbar>\n", styles: [".topbar-spacer{flex:1 1 auto}.toolbar{height:60px;background-size:cover;--mat-toolbar-container-background-color: var(--mat-sys-primary);--mat-toolbar-container-text-color: var(--mat-sys-on-primary)}.logo{height:50px;margin-top:5px}.icon{color:var(--mat-sys-on-primary)}\n"], dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$3.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: MatToolbarModule }, { kind: "component", type: i2$4.MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i5$1.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i5$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i5$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }] });
2058
2091
  }
2059
2092
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: TopBarComponent, decorators: [{
2060
2093
  type: Component,
@@ -2062,15 +2095,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
2062
2095
  MatToolbarModule,
2063
2096
  MatIconModule,
2064
2097
  MatButtonModule,
2065
- MatMenuModule], template: "<mat-toolbar class=\"toolbar\" [style.background-image]=\"backgroundStyle\">\n\n @if(logo())\n {\n <a aria-label=\"Home\" [routerLink]=\"['home']\">\n <img src=\"{{logo()}}\" class=\"logo\" alt=\"Website logo\"/>\n </a>\n }\n @else {\n <a mat-icon-button aria-label=\"Home\" [routerLink]=\"['home']\">\n <mat-icon class=\"icon\">home</mat-icon>\n </a>\n <span>{{title()}}</span>\n }\n <span class=\"topbar-spacer\"></span>\n @if(user(); as user)\n {\n <span>{{user.username}}</span>\n \n <button mat-icon-button style=\"margin: 5px\" aria-label=\"User Profile\" [matMenuTriggerFor]=\"profile_menu\">\n <mat-icon class=\"icon\">person</mat-icon>\n </button>\n\n <mat-menu #profile_menu=\"matMenu\">\n <a mat-menu-item aria-label=\"My Profile\" [routerLink]=\"['/members/detail', user.id]\">\n <mat-icon>manage_accounts</mat-icon>\n <span>My Profile</span>\n </a> \n <a mat-menu-item aria-label=\"Get Support\" [routerLink]=\"['/feedback']\">\n <mat-icon>contact_support</mat-icon>\n <span>Get Support</span>\n </a> \n <button mat-menu-item (click)=\"onLogout()\">\n <mat-icon>logout</mat-icon>\n <span>Log Out</span>\n </button>\n\n </mat-menu>\n }\n @else {\n <span>Log In</span>\n <button matIconButton (click)=\"onLogin()\">\n <mat-icon class=\"icon\">login</mat-icon>\n </button>\n }\n</mat-toolbar>\n", styles: [".topbar-spacer{flex:1 1 auto}.toolbar{height:60px;background-size:cover;--mat-toolbar-container-background-color: var(--mat-sys-primary);--mat-toolbar-container-text-color: var(--mat-sys-on-primary)}.logo{height:50px;margin-top:5px}.icon{color:var(--mat-sys-on-primary)}\n"] }]
2098
+ MatMenuModule], template: "<mat-toolbar class=\"toolbar\" [style.background-image]=\"backgroundStyle\">\n\n @if(logo())\n {\n <a aria-label=\"Home\" [routerLink]=\"['home']\">\n <img src=\"{{logo()}}\" class=\"logo\" alt=\"Website logo\"/>\n </a>\n }\n @else {\n <a mat-icon-button aria-label=\"Home\" [routerLink]=\"['home']\">\n <mat-icon class=\"icon\">home</mat-icon>\n </a>\n <span>{{title()}}</span>\n }\n <button mat-icon-button style=\"margin: 5px\" aria-label=\"Toggle Nav Bar\">\n <mat-icon class=\"icon\" (click)=\"leftNavService.toggle()\">\n @if(leftNavService.wide()){\n menu\n }\n @else {\n menu_open\n }\n </mat-icon>\n </button>\n\n <span class=\"topbar-spacer\"></span>\n @if(user(); as user)\n {\n <span>{{user.username}}</span>\n \n <button mat-icon-button style=\"margin: 5px\" aria-label=\"User Profile\" [matMenuTriggerFor]=\"profile_menu\">\n <mat-icon class=\"icon\">person</mat-icon>\n </button>\n\n <mat-menu #profile_menu=\"matMenu\">\n <a mat-menu-item aria-label=\"My Profile\" [routerLink]=\"['/members/detail', user.id]\">\n <mat-icon>manage_accounts</mat-icon>\n <span>My Profile</span>\n </a> \n <a mat-menu-item aria-label=\"Get Support\" [routerLink]=\"['/feedback']\">\n <mat-icon>contact_support</mat-icon>\n <span>Get Support</span>\n </a> \n <button mat-menu-item (click)=\"onLogout()\">\n <mat-icon>logout</mat-icon>\n <span>Log Out</span>\n </button>\n\n </mat-menu>\n }\n @else {\n <span>Log In</span>\n <button matIconButton (click)=\"onLogin()\">\n <mat-icon class=\"icon\">login</mat-icon>\n </button>\n }\n</mat-toolbar>\n", styles: [".topbar-spacer{flex:1 1 auto}.toolbar{height:60px;background-size:cover;--mat-toolbar-container-background-color: var(--mat-sys-primary);--mat-toolbar-container-text-color: var(--mat-sys-on-primary)}.logo{height:50px;margin-top:5px}.icon{color:var(--mat-sys-on-primary)}\n"] }]
2066
2099
  }], ctorParameters: () => [], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], logo: [{ type: i0.Input, args: [{ isSignal: true, alias: "logo", required: false }] }], background: [{ type: i0.Input, args: [{ isSignal: true, alias: "background", required: false }] }], loginRoute: [{ type: i0.Input, args: [{ isSignal: true, alias: "loginRoute", required: false }] }] } });
2067
2100
 
2068
2101
  class LeftNavComponent {
2069
2102
  background = input(...(ngDevMode ? [undefined, { debugName: "background" }] : []));
2070
- _leftNavService = inject(LeftNavService);
2103
+ user = signal(null, ...(ngDevMode ? [{ debugName: "user" }] : []));
2104
+ width = computed(() => this.leftNavService.wide() ? "200px" : "100px", ...(ngDevMode ? [{ debugName: "width" }] : []));
2105
+ userService = inject(UserService);
2106
+ leftNavService = inject(LeftNavService);
2071
2107
  sideNavContent = viewChild(MatSidenavContent, ...(ngDevMode ? [{ debugName: "sideNavContent" }] : []));
2072
- getOptions() {
2073
- return this._leftNavService.activeOptions;
2108
+ constructor() {
2109
+ this.userService.loggedInUser.subscribe(user => this.user.set(user));
2110
+ }
2111
+ getGroupings() {
2112
+ return this.leftNavService.activeGroupings;
2074
2113
  }
2075
2114
  get backgroundStyle() {
2076
2115
  if (this.background()) {
@@ -2081,12 +2120,12 @@ class LeftNavComponent {
2081
2120
  }
2082
2121
  }
2083
2122
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: LeftNavComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2084
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: LeftNavComponent, isStandalone: true, selector: "lib-left-nav", inputs: { background: { classPropertyName: "background", publicName: "background", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "sideNavContent", first: true, predicate: MatSidenavContent, descendants: true, isSignal: true }], ngImport: i0, template: "<mat-sidenav-container class=\"leftnav-container\">\n <mat-sidenav mode=\"side\" class=\"leftnav-side\" opened>\n <mat-nav-list>\n <ul>\n @for (option of _leftNavService.activeOptions(); track option) {\n <li>\n <a mat-list-item \n [routerLink]=\"option.route\" \n routerLinkActive #rla=\"routerLinkActive\" \n [activated]=\"rla.isActive\">{{ option.name }}</a>\n </li>\n }\n </ul>\n </mat-nav-list>\n </mat-sidenav>\n <mat-sidenav-content class=\"leftnav-content\" [style.background-image]=\"backgroundStyle\"> \n <router-outlet />\n </mat-sidenav-content>\n</mat-sidenav-container>\n", styles: [":host{display:flex;flex-direction:column}.leftnav-container{flex-grow:1;display:flex}.leftnav-content{display:flex;flex-grow:1;height:90vh;background-blend-mode:lighten;background-color:#ffffffa6;background-size:cover}.leftnav-side{padding:5px;width:200px}ul,li{margin:0;padding:0}\n"], dependencies: [{ kind: "ngmodule", type: MatSidenavModule }, { kind: "component", type: i1$6.MatSidenav, selector: "mat-sidenav", inputs: ["fixedInViewport", "fixedTopGap", "fixedBottomGap"], exportAs: ["matSidenav"] }, { kind: "component", type: i1$6.MatSidenavContainer, selector: "mat-sidenav-container", exportAs: ["matSidenavContainer"] }, { kind: "component", type: i1$6.MatSidenavContent, selector: "mat-sidenav-content" }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i2$2.MatNavList, selector: "mat-nav-list", exportAs: ["matNavList"] }, { kind: "component", type: i2$2.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$3.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i1$3.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }] });
2123
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: LeftNavComponent, isStandalone: true, selector: "lib-left-nav", inputs: { background: { classPropertyName: "background", publicName: "background", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "sideNavContent", first: true, predicate: MatSidenavContent, descendants: true, isSignal: true }], ngImport: i0, template: "<mat-sidenav-container class=\"leftnav-container\">\n @if(leftNavService.wide()){\n <mat-sidenav mode=\"side\" class=\"leftnav-side\" [opened]=\"user()!== null\" style=\"width:200px; padding-top:0px\">\n <mat-nav-list>\n @for (grouping of leftNavService.activeGroupings(); track grouping) { \n <ul>\n @if(grouping.name)\n {\n <span>{{grouping.name}}</span>\n }\n @for (option of grouping.options; track option) {\n <li>\n <a mat-list-item \n [routerLink]=\"option.route\" \n routerLinkActive #rla=\"routerLinkActive\" \n [activated]=\"rla.isActive\">\n <div style=\"display:flex; vertical-align:middle;\">\n <mat-icon style=\"margin-right: 5px;\">{{option.icon}}</mat-icon><span>{{ option.name }}</span>\n </div>\n </a>\n </li>\n }\n </ul>\n }\n </mat-nav-list>\n </mat-sidenav>\n }\n @else{\n <mat-sidenav mode=\"side\" class=\"leftnav-side\" [opened]=\"user()!== null\" style=\"width: 64px;\">\n <mat-nav-list>\n @for (grouping of leftNavService.activeGroupings(); track grouping) { \n <ul>\n @if(grouping.name)\n {\n <span>{{grouping.name}}</span>\n }\n @for (option of grouping.options; track option) {\n <li>\n <a mat-list-item \n [routerLink]=\"option.route\" \n routerLinkActive #rla=\"routerLinkActive\" \n [activated]=\"rla.isActive\" matTooltip=\"{{option.name}}\">\n <div style=\"display:flex; vertical-align:middle;\">\n <mat-icon>{{option.icon}}</mat-icon>\n </div>\n </a>\n </li>\n }\n </ul>\n }\n </mat-nav-list>\n </mat-sidenav>\n }\n\n <mat-sidenav-content class=\"leftnav-content\" [style.background-image]=\"backgroundStyle\"> \n <router-outlet />\n </mat-sidenav-content>\n</mat-sidenav-container>\n", styles: [":host{display:flex;flex-direction:column}.leftnav-container{flex-grow:1;display:flex}.leftnav-content{display:flex;flex-grow:1;height:90vh;background-blend-mode:lighten;background-color:#ffffffa6;background-size:cover}.leftnav-side{padding:5px}ul,li{margin:0;padding:0;list-style-type:none;padding-inline-start:0;list-style:none}\n"], dependencies: [{ kind: "ngmodule", type: MatSidenavModule }, { kind: "component", type: i1$6.MatSidenav, selector: "mat-sidenav", inputs: ["fixedInViewport", "fixedTopGap", "fixedBottomGap"], exportAs: ["matSidenav"] }, { kind: "component", type: i1$6.MatSidenavContainer, selector: "mat-sidenav-container", exportAs: ["matSidenavContainer"] }, { kind: "component", type: i1$6.MatSidenavContent, selector: "mat-sidenav-content" }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i2$2.MatNavList, selector: "mat-nav-list", exportAs: ["matNavList"] }, { kind: "component", type: i2$2.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$3.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i1$3.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
2085
2124
  }
2086
2125
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: LeftNavComponent, decorators: [{
2087
2126
  type: Component,
2088
- args: [{ selector: 'lib-left-nav', imports: [MatSidenavModule, MatListModule, RouterOutlet, RouterModule], template: "<mat-sidenav-container class=\"leftnav-container\">\n <mat-sidenav mode=\"side\" class=\"leftnav-side\" opened>\n <mat-nav-list>\n <ul>\n @for (option of _leftNavService.activeOptions(); track option) {\n <li>\n <a mat-list-item \n [routerLink]=\"option.route\" \n routerLinkActive #rla=\"routerLinkActive\" \n [activated]=\"rla.isActive\">{{ option.name }}</a>\n </li>\n }\n </ul>\n </mat-nav-list>\n </mat-sidenav>\n <mat-sidenav-content class=\"leftnav-content\" [style.background-image]=\"backgroundStyle\"> \n <router-outlet />\n </mat-sidenav-content>\n</mat-sidenav-container>\n", styles: [":host{display:flex;flex-direction:column}.leftnav-container{flex-grow:1;display:flex}.leftnav-content{display:flex;flex-grow:1;height:90vh;background-blend-mode:lighten;background-color:#ffffffa6;background-size:cover}.leftnav-side{padding:5px;width:200px}ul,li{margin:0;padding:0}\n"] }]
2089
- }], propDecorators: { background: [{ type: i0.Input, args: [{ isSignal: true, alias: "background", required: false }] }], sideNavContent: [{ type: i0.ViewChild, args: [i0.forwardRef(() => MatSidenavContent), { isSignal: true }] }] } });
2127
+ args: [{ selector: 'lib-left-nav', imports: [MatSidenavModule, MatListModule, RouterOutlet, RouterModule, MatIconModule, MatTooltipModule, NgStyle], template: "<mat-sidenav-container class=\"leftnav-container\">\n @if(leftNavService.wide()){\n <mat-sidenav mode=\"side\" class=\"leftnav-side\" [opened]=\"user()!== null\" style=\"width:200px; padding-top:0px\">\n <mat-nav-list>\n @for (grouping of leftNavService.activeGroupings(); track grouping) { \n <ul>\n @if(grouping.name)\n {\n <span>{{grouping.name}}</span>\n }\n @for (option of grouping.options; track option) {\n <li>\n <a mat-list-item \n [routerLink]=\"option.route\" \n routerLinkActive #rla=\"routerLinkActive\" \n [activated]=\"rla.isActive\">\n <div style=\"display:flex; vertical-align:middle;\">\n <mat-icon style=\"margin-right: 5px;\">{{option.icon}}</mat-icon><span>{{ option.name }}</span>\n </div>\n </a>\n </li>\n }\n </ul>\n }\n </mat-nav-list>\n </mat-sidenav>\n }\n @else{\n <mat-sidenav mode=\"side\" class=\"leftnav-side\" [opened]=\"user()!== null\" style=\"width: 64px;\">\n <mat-nav-list>\n @for (grouping of leftNavService.activeGroupings(); track grouping) { \n <ul>\n @if(grouping.name)\n {\n <span>{{grouping.name}}</span>\n }\n @for (option of grouping.options; track option) {\n <li>\n <a mat-list-item \n [routerLink]=\"option.route\" \n routerLinkActive #rla=\"routerLinkActive\" \n [activated]=\"rla.isActive\" matTooltip=\"{{option.name}}\">\n <div style=\"display:flex; vertical-align:middle;\">\n <mat-icon>{{option.icon}}</mat-icon>\n </div>\n </a>\n </li>\n }\n </ul>\n }\n </mat-nav-list>\n </mat-sidenav>\n }\n\n <mat-sidenav-content class=\"leftnav-content\" [style.background-image]=\"backgroundStyle\"> \n <router-outlet />\n </mat-sidenav-content>\n</mat-sidenav-container>\n", styles: [":host{display:flex;flex-direction:column}.leftnav-container{flex-grow:1;display:flex}.leftnav-content{display:flex;flex-grow:1;height:90vh;background-blend-mode:lighten;background-color:#ffffffa6;background-size:cover}.leftnav-side{padding:5px}ul,li{margin:0;padding:0;list-style-type:none;padding-inline-start:0;list-style:none}\n"] }]
2128
+ }], ctorParameters: () => [], propDecorators: { background: [{ type: i0.Input, args: [{ isSignal: true, alias: "background", required: false }] }], sideNavContent: [{ type: i0.ViewChild, args: [i0.forwardRef(() => MatSidenavContent), { isSignal: true }] }] } });
2090
2129
 
2091
2130
  class FeedbackComponent {
2092
2131
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FeedbackComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -2125,11 +2164,11 @@ class UserDetailComponent extends DetailView {
2125
2164
  return super.canEdit();
2126
2165
  }
2127
2166
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: UserDetailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2128
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: UserDetailComponent, isStandalone: true, selector: "lib-user-detail", inputs: { showBack: { classPropertyName: "showBack", publicName: "showBack", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "@if(showBack())\n{\n<lib-back-button style=\"position: absolute;\"></lib-back-button>\n}\n\n<div class=\"content-container\">\n @if(item(); as item){\n <div class=\"item-detail-container\">\n\n <lib-detail-header\n [text]=\"item.username\"\n [id]=\"item.id\"\n [route]=\"itemService.typePlural()\"\n [canEdit]=\"canEdit()\"\n [canDelete]=\"canDelete()\"\n (onDelete)=\"onDelete()\"></lib-detail-header>\n\n @if(item.profile){\n <div class=\"image-holder\">\n <img alt=\"User Profile Image\" src=\"{{item.profile}}\" style=\"height:120px;\">\n </div> \n }\n \n <div class=\"item-field\">\n <span><b>Email: </b></span>\n {{item.email}}\n </div>\n \n <div class=\"item-field\">\n <span><b>First Name: </b></span>\n {{item.first_name}}\n </div>\n \n <div class=\"item-field\">\n <span><b>Last Name: </b></span>\n {{item.last_name}}\n </div>\n \n </div>\n }\n</div>\n", styles: [":host{flex-grow:1}\n"], dependencies: [{ kind: "component", type: BackButtonComponent, selector: "lib-back-button" }, { kind: "component", type: DetailHeaderComponent, selector: "lib-detail-header", inputs: ["id", "text", "route", "canEdit", "canDelete"], outputs: ["deleteClicked"] }] });
2167
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: UserDetailComponent, isStandalone: true, selector: "lib-user-detail", inputs: { showBack: { classPropertyName: "showBack", publicName: "showBack", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "@if(showBack())\n{\n<lib-back-button style=\"position: absolute;\"></lib-back-button>\n}\n\n<div class=\"content-container\">\n @if(item(); as item){\n <div class=\"item-detail-container\">\n\n <lib-detail-header\n [text]=\"item.username\"\n [id]=\"item.id\"\n [route]=\"itemService.typePlural()\"\n [canEdit]=\"canEdit()\"\n [canDelete]=\"canDelete()\"\n (onDelete)=\"onDelete()\"></lib-detail-header>\n\n @if(item.profile){\n <div class=\"image-holder\">\n <img alt=\"User Profile Image\" src=\"{{item.profile}}\" style=\"height:120px;\">\n </div> \n }\n \n <div class=\"form-card\">\n <div class=\"item-field\">\n <span><b>Email: </b></span>\n {{item.email}}\n </div>\n \n <div class=\"item-field\">\n <span><b>First Name: </b></span>\n {{item.first_name}}\n </div>\n \n <div class=\"item-field\">\n <span><b>Last Name: </b></span>\n {{item.last_name}}\n </div>\n </div>\n \n </div>\n }\n</div>\n", styles: [":host{flex-grow:1}\n"], dependencies: [{ kind: "component", type: BackButtonComponent, selector: "lib-back-button" }, { kind: "component", type: DetailHeaderComponent, selector: "lib-detail-header", inputs: ["id", "text", "route", "canEdit", "canDelete"], outputs: ["deleteClicked"] }] });
2129
2168
  }
2130
2169
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: UserDetailComponent, decorators: [{
2131
2170
  type: Component,
2132
- args: [{ selector: 'lib-user-detail', imports: [BackButtonComponent, DetailHeaderComponent], template: "@if(showBack())\n{\n<lib-back-button style=\"position: absolute;\"></lib-back-button>\n}\n\n<div class=\"content-container\">\n @if(item(); as item){\n <div class=\"item-detail-container\">\n\n <lib-detail-header\n [text]=\"item.username\"\n [id]=\"item.id\"\n [route]=\"itemService.typePlural()\"\n [canEdit]=\"canEdit()\"\n [canDelete]=\"canDelete()\"\n (onDelete)=\"onDelete()\"></lib-detail-header>\n\n @if(item.profile){\n <div class=\"image-holder\">\n <img alt=\"User Profile Image\" src=\"{{item.profile}}\" style=\"height:120px;\">\n </div> \n }\n \n <div class=\"item-field\">\n <span><b>Email: </b></span>\n {{item.email}}\n </div>\n \n <div class=\"item-field\">\n <span><b>First Name: </b></span>\n {{item.first_name}}\n </div>\n \n <div class=\"item-field\">\n <span><b>Last Name: </b></span>\n {{item.last_name}}\n </div>\n \n </div>\n }\n</div>\n", styles: [":host{flex-grow:1}\n"] }]
2171
+ args: [{ selector: 'lib-user-detail', imports: [BackButtonComponent, DetailHeaderComponent], template: "@if(showBack())\n{\n<lib-back-button style=\"position: absolute;\"></lib-back-button>\n}\n\n<div class=\"content-container\">\n @if(item(); as item){\n <div class=\"item-detail-container\">\n\n <lib-detail-header\n [text]=\"item.username\"\n [id]=\"item.id\"\n [route]=\"itemService.typePlural()\"\n [canEdit]=\"canEdit()\"\n [canDelete]=\"canDelete()\"\n (onDelete)=\"onDelete()\"></lib-detail-header>\n\n @if(item.profile){\n <div class=\"image-holder\">\n <img alt=\"User Profile Image\" src=\"{{item.profile}}\" style=\"height:120px;\">\n </div> \n }\n \n <div class=\"form-card\">\n <div class=\"item-field\">\n <span><b>Email: </b></span>\n {{item.email}}\n </div>\n \n <div class=\"item-field\">\n <span><b>First Name: </b></span>\n {{item.first_name}}\n </div>\n \n <div class=\"item-field\">\n <span><b>Last Name: </b></span>\n {{item.last_name}}\n </div>\n </div>\n \n </div>\n }\n</div>\n", styles: [":host{flex-grow:1}\n"] }]
2133
2172
  }], ctorParameters: () => [], propDecorators: { showBack: [{ type: i0.Input, args: [{ isSignal: true, alias: "showBack", required: false }] }] } });
2134
2173
 
2135
2174
  class UserForm {
@@ -2222,11 +2261,11 @@ class UserListDetailComponent {
2222
2261
  }
2223
2262
  }
2224
2263
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: UserListDetailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2225
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: UserListDetailComponent, isStandalone: true, selector: "lib-user-list-detail", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null }, even: { classPropertyName: "even", publicName: "even", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div mat-list-item class=\"container\" [class.even]=\"even() && !selected()\" [class.selected]=\"selected()\">\n @if(item().profile_thumbnail){\n <div class=\"image-holder\" style=\"width:35px;\">\n <img matListItemAvatar \n alt=\"User Avatar\" \n src=\"{{item().profile_thumbnail}}\" style=\"height:30px\">\n </div> \n }\n @else {\n <div class=\"image-holder\" style=\"width:35px;\">\n <mat-icon matListItemIcon>person</mat-icon>\n </div>\n }\n <div class=\"text-container\">\n <p matListItemTitle style=\"margin-bottom: 0px; margin-top: 0px\">{{title}}</p>\n <p matListItemLine>{{item().email}}</p>\n </div>\n</div>", styles: [":host{flex-grow:1}.container{height:60px;padding:5px;width:100%;display:flex;flex-direction:row;background-color:var(--mat-sys-surface-container-low)}.container:hover{background-color:var(--mat-sys-surface-container-high);cursor:pointer}.even{background-color:var(--mat-sys-surface-container-lowest)}.selected{background-color:var(--mat-sys-primary-container);color:var(--mat-sys-on-primary-container)}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatListModule }, { kind: "directive", type: i2$2.MatListItemAvatar, selector: "[matListItemAvatar]" }, { kind: "directive", type: i2$2.MatListItemIcon, selector: "[matListItemIcon]" }, { kind: "directive", type: i2$2.MatListItemLine, selector: "[matListItemLine]" }, { kind: "directive", type: i2$2.MatListItemTitle, selector: "[matListItemTitle]" }] });
2264
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: UserListDetailComponent, isStandalone: true, selector: "lib-user-list-detail", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null }, even: { classPropertyName: "even", publicName: "even", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div mat-list-item class=\"container\" [class.even]=\"even() && !selected()\" [class.selected]=\"selected()\">\n @if(item().profile_thumbnail){\n <div class=\"image-holder\" style=\"width:35px;\">\n <img matListItemAvatar \n alt=\"User Avatar\" \n src=\"{{item().profile_thumbnail}}\" style=\"height:30px\">\n </div> \n }\n @else {\n <div class=\"image-holder\" style=\"width:35px;\">\n <mat-icon matListItemIcon>person</mat-icon>\n </div>\n }\n <div class=\"text-container\">\n <p matListItemTitle style=\"margin-bottom: 0px; margin-top: 0px\">{{title}}</p>\n <p matListItemLine>{{item().email}}</p>\n </div>\n</div>", styles: [":host{flex-grow:1}.container{height:60px;padding:5px;width:100%;display:flex;flex-direction:row;background-color:var(--mat-sys-surface-container-lowest)}.container:hover{background-color:var(--mat-sys-surface-container-high);cursor:pointer}.even{background-color:var(--mat-sys-surface-container-low)}.selected{background-color:var(--mat-sys-primary-container);color:var(--mat-sys-on-primary-container)}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatListModule }, { kind: "directive", type: i2$2.MatListItemAvatar, selector: "[matListItemAvatar]" }, { kind: "directive", type: i2$2.MatListItemIcon, selector: "[matListItemIcon]" }, { kind: "directive", type: i2$2.MatListItemLine, selector: "[matListItemLine]" }, { kind: "directive", type: i2$2.MatListItemTitle, selector: "[matListItemTitle]" }] });
2226
2265
  }
2227
2266
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: UserListDetailComponent, decorators: [{
2228
2267
  type: Component,
2229
- args: [{ selector: 'lib-user-list-detail', imports: [MatIconModule, MatListModule], template: "<div mat-list-item class=\"container\" [class.even]=\"even() && !selected()\" [class.selected]=\"selected()\">\n @if(item().profile_thumbnail){\n <div class=\"image-holder\" style=\"width:35px;\">\n <img matListItemAvatar \n alt=\"User Avatar\" \n src=\"{{item().profile_thumbnail}}\" style=\"height:30px\">\n </div> \n }\n @else {\n <div class=\"image-holder\" style=\"width:35px;\">\n <mat-icon matListItemIcon>person</mat-icon>\n </div>\n }\n <div class=\"text-container\">\n <p matListItemTitle style=\"margin-bottom: 0px; margin-top: 0px\">{{title}}</p>\n <p matListItemLine>{{item().email}}</p>\n </div>\n</div>", styles: [":host{flex-grow:1}.container{height:60px;padding:5px;width:100%;display:flex;flex-direction:row;background-color:var(--mat-sys-surface-container-low)}.container:hover{background-color:var(--mat-sys-surface-container-high);cursor:pointer}.even{background-color:var(--mat-sys-surface-container-lowest)}.selected{background-color:var(--mat-sys-primary-container);color:var(--mat-sys-on-primary-container)}\n"] }]
2268
+ args: [{ selector: 'lib-user-list-detail', imports: [MatIconModule, MatListModule], template: "<div mat-list-item class=\"container\" [class.even]=\"even() && !selected()\" [class.selected]=\"selected()\">\n @if(item().profile_thumbnail){\n <div class=\"image-holder\" style=\"width:35px;\">\n <img matListItemAvatar \n alt=\"User Avatar\" \n src=\"{{item().profile_thumbnail}}\" style=\"height:30px\">\n </div> \n }\n @else {\n <div class=\"image-holder\" style=\"width:35px;\">\n <mat-icon matListItemIcon>person</mat-icon>\n </div>\n }\n <div class=\"text-container\">\n <p matListItemTitle style=\"margin-bottom: 0px; margin-top: 0px\">{{title}}</p>\n <p matListItemLine>{{item().email}}</p>\n </div>\n</div>", styles: [":host{flex-grow:1}.container{height:60px;padding:5px;width:100%;display:flex;flex-direction:row;background-color:var(--mat-sys-surface-container-lowest)}.container:hover{background-color:var(--mat-sys-surface-container-high);cursor:pointer}.even{background-color:var(--mat-sys-surface-container-low)}.selected{background-color:var(--mat-sys-primary-container);color:var(--mat-sys-on-primary-container)}\n"] }]
2230
2269
  }], propDecorators: { item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: true }] }], even: [{ type: i0.Input, args: [{ isSignal: true, alias: "even", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }] } });
2231
2270
 
2232
2271
  class UserComponent {
@@ -2238,13 +2277,13 @@ class UserComponent {
2238
2277
  }
2239
2278
  }
2240
2279
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: UserComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2241
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.0.3", type: UserComponent, isStandalone: true, selector: "lib-user", viewQueries: [{ propertyName: "detailView", first: true, predicate: UserDetailComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<lib-list-view\n [itemService]=\"itemService\"\n [listItemTemplate]=\"listItemTemplate\"\n [itemDetailTemplate]=\"itemDetailTemplate\"\n [viewType]=\"'list'\"\n [itemHeight]=\"60\"\n (selected)=\"onSelected($event)\"\n >\n <ng-template #listItemTemplate let-item=\"item\" let-even=\"even\" let-selected=\"selected\">\n <lib-user-list-detail [item]=\"item\" [even]=\"even\" [selected]=\"selected\"></lib-user-list-detail>\n </ng-template>\n\n <ng-template #itemDetailTemplate>\n <lib-user-detail [showBack]='false'></lib-user-detail>\n </ng-template>\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", "listItemTemplate", "itemDetailTemplate", "itemHeight", "columns", "sortFields", "noSelfItemsMessage", "noItemsCanCreateMessage", "noItemsMessage", "defaultQueries", "embeddedMode"], outputs: ["selected"] }, { kind: "component", type: UserListDetailComponent, selector: "lib-user-list-detail", inputs: ["item", "even", "selected"] }, { kind: "component", type: UserDetailComponent, selector: "lib-user-detail", inputs: ["showBack"] }] });
2280
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.0.3", type: UserComponent, isStandalone: true, selector: "lib-user", viewQueries: [{ propertyName: "detailView", first: true, predicate: UserDetailComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<lib-list-view\n [itemService]=\"itemService\"\n [listItemTemplate]=\"listItemTemplate\"\n [itemDetailTemplate]=\"itemDetailTemplate\"\n [viewType]=\"'list'\"\n [itemHeight]=\"60\"\n [itemWidth]=\"300\"\n (selected)=\"onSelected($event)\"\n >\n <ng-template #listItemTemplate let-item=\"item\" let-even=\"even\" let-selected=\"selected\">\n <lib-user-list-detail [item]=\"item\" [even]=\"even\" [selected]=\"selected\"></lib-user-list-detail>\n </ng-template>\n\n <ng-template #itemDetailTemplate>\n <lib-user-detail [showBack]='false'></lib-user-detail>\n </ng-template>\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", "listItemTemplate", "itemDetailTemplate", "itemHeight", "itemWidth", "columns", "sortFields", "noSelfItemsMessage", "noItemsCanCreateMessage", "noItemsMessage", "defaultQueries", "embeddedMode"], outputs: ["selected"] }, { kind: "component", type: UserListDetailComponent, selector: "lib-user-list-detail", inputs: ["item", "even", "selected"] }, { kind: "component", type: UserDetailComponent, selector: "lib-user-detail", inputs: ["showBack"] }] });
2242
2281
  }
2243
2282
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: UserComponent, decorators: [{
2244
2283
  type: Component,
2245
2284
  args: [{ selector: 'lib-user', imports: [ListViewComponent,
2246
2285
  UserListDetailComponent,
2247
- UserDetailComponent], template: "<lib-list-view\n [itemService]=\"itemService\"\n [listItemTemplate]=\"listItemTemplate\"\n [itemDetailTemplate]=\"itemDetailTemplate\"\n [viewType]=\"'list'\"\n [itemHeight]=\"60\"\n (selected)=\"onSelected($event)\"\n >\n <ng-template #listItemTemplate let-item=\"item\" let-even=\"even\" let-selected=\"selected\">\n <lib-user-list-detail [item]=\"item\" [even]=\"even\" [selected]=\"selected\"></lib-user-list-detail>\n </ng-template>\n\n <ng-template #itemDetailTemplate>\n <lib-user-detail [showBack]='false'></lib-user-detail>\n </ng-template>\n\n</lib-list-view>\n\n", styles: [":host{flex-grow:1}\n"] }]
2286
+ UserDetailComponent], template: "<lib-list-view\n [itemService]=\"itemService\"\n [listItemTemplate]=\"listItemTemplate\"\n [itemDetailTemplate]=\"itemDetailTemplate\"\n [viewType]=\"'list'\"\n [itemHeight]=\"60\"\n [itemWidth]=\"300\"\n (selected)=\"onSelected($event)\"\n >\n <ng-template #listItemTemplate let-item=\"item\" let-even=\"even\" let-selected=\"selected\">\n <lib-user-list-detail [item]=\"item\" [even]=\"even\" [selected]=\"selected\"></lib-user-list-detail>\n </ng-template>\n\n <ng-template #itemDetailTemplate>\n <lib-user-detail [showBack]='false'></lib-user-detail>\n </ng-template>\n\n</lib-list-view>\n\n", styles: [":host{flex-grow:1}\n"] }]
2248
2287
  }], propDecorators: { detailView: [{ type: i0.ViewChild, args: [i0.forwardRef(() => UserDetailComponent), { isSignal: true }] }] } });
2249
2288
 
2250
2289
  class GroupDetailComponent extends DetailView {
@@ -2273,7 +2312,7 @@ class GroupComponent {
2273
2312
  }
2274
2313
  }
2275
2314
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: GroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2276
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.0.3", type: GroupComponent, isStandalone: true, selector: "lib-group", viewQueries: [{ propertyName: "detailView", first: true, predicate: GroupDetailComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<lib-list-view\n [itemService]=\"itemService\"\n [listItemTemplate]=\"listItemTemplate\"\n [itemDetailTemplate]=\"itemDetailTemplate\"\n [viewType]=\"'list'\"\n [itemHeight]=\"60\"\n (selected)=\"onSelected($event)\"\n >\n <ng-template #listItemTemplate let-item=\"item\" let-even=\"even\" let-selected=\"selected\">\n\n <div mat-list-item class=\"container\" [class.even]=\"even && !selected\" [class.selected]=\"selected\">\n <div class=\"text-container\">\n <p matListItemTitle style=\"margin-bottom: 0px; margin-top: 0px\">{{item.name}}</p>\n </div>\n </div>\n\n </ng-template>\n\n <ng-template #itemDetailTemplate>\n <lib-group-detail [showBack]='false'></lib-group-detail>\n </ng-template>\n\n</lib-list-view>\n\n", styles: [":host{flex-grow:1}.container{height:60px;padding:5px;width:100%;display:flex;flex-direction:row;background-color:var(--mat-sys-surface-container-low)}.container:hover{background-color:var(--mat-sys-surface-container-high);cursor:pointer}.even{background-color:var(--mat-sys-surface-container-lowest)}.selected{background-color:var(--mat-sys-primary-container);color:var(--mat-sys-on-primary-container)}\n"], dependencies: [{ kind: "component", type: ListViewComponent, selector: "lib-list-view", inputs: ["viewType", "itemService", "listItemTemplate", "itemDetailTemplate", "itemHeight", "columns", "sortFields", "noSelfItemsMessage", "noItemsCanCreateMessage", "noItemsMessage", "defaultQueries", "embeddedMode"], outputs: ["selected"] }, { kind: "component", type: GroupDetailComponent, selector: "lib-group-detail", inputs: ["showBack"] }, { kind: "ngmodule", type: MatListModule }, { kind: "directive", type: i2$2.MatListItemTitle, selector: "[matListItemTitle]" }] });
2315
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.0.3", type: GroupComponent, isStandalone: true, selector: "lib-group", viewQueries: [{ propertyName: "detailView", first: true, predicate: GroupDetailComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<lib-list-view\n [itemService]=\"itemService\"\n [listItemTemplate]=\"listItemTemplate\"\n [itemDetailTemplate]=\"itemDetailTemplate\"\n [viewType]=\"'list'\"\n [itemHeight]=\"60\"\n (selected)=\"onSelected($event)\"\n >\n <ng-template #listItemTemplate let-item=\"item\" let-even=\"even\" let-selected=\"selected\">\n\n <div mat-list-item class=\"container\" [class.even]=\"even && !selected\" [class.selected]=\"selected\">\n <div class=\"text-container\">\n <p matListItemTitle style=\"margin-bottom: 0px; margin-top: 0px\">{{item.name}}</p>\n </div>\n </div>\n\n </ng-template>\n\n <ng-template #itemDetailTemplate>\n <lib-group-detail [showBack]='false'></lib-group-detail>\n </ng-template>\n\n</lib-list-view>\n\n", styles: [":host{flex-grow:1}.container{height:60px;padding:5px;width:100%;display:flex;flex-direction:row;background-color:var(--mat-sys-surface-container-low)}.container:hover{background-color:var(--mat-sys-surface-container-high);cursor:pointer}.even{background-color:var(--mat-sys-surface-container-lowest)}.selected{background-color:var(--mat-sys-primary-container);color:var(--mat-sys-on-primary-container)}\n"], dependencies: [{ kind: "component", type: ListViewComponent, selector: "lib-list-view", inputs: ["viewType", "itemService", "listItemTemplate", "itemDetailTemplate", "itemHeight", "itemWidth", "columns", "sortFields", "noSelfItemsMessage", "noItemsCanCreateMessage", "noItemsMessage", "defaultQueries", "embeddedMode"], outputs: ["selected"] }, { kind: "component", type: GroupDetailComponent, selector: "lib-group-detail", inputs: ["showBack"] }, { kind: "ngmodule", type: MatListModule }, { kind: "directive", type: i2$2.MatListItemTitle, selector: "[matListItemTitle]" }] });
2277
2316
  }
2278
2317
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: GroupComponent, decorators: [{
2279
2318
  type: Component,
@@ -2387,7 +2426,7 @@ class OrganizationComponent {
2387
2426
  }
2388
2427
  }
2389
2428
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: OrganizationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2390
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.0.3", type: OrganizationComponent, isStandalone: true, selector: "lib-organization", viewQueries: [{ propertyName: "detailView", first: true, predicate: OrganizationDetailComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<lib-list-view\n [itemService]=\"itemService\"\n [listItemTemplate]=\"listItemTemplate\"\n [itemDetailTemplate]=\"itemDetailTemplate\"\n [viewType]=\"'list'\"\n [itemHeight]=\"60\"\n (selected)=\"onSelected($event)\"\n >\n <ng-template #listItemTemplate let-item=\"item\" let-even=\"even\" let-selected=\"selected\">\n <div mat-list-item class=\"container\" [class.even]=\"even && !selected\" [class.selected]=\"selected\">\n <div class=\"text-container\">\n <p matListItemTitle style=\"margin-bottom: 0px; margin-top: 0px\">{{item.name}}</p>\n </div>\n </div>\n </ng-template>\n\n <ng-template #itemDetailTemplate>\n <lib-organization-detail [showBack]='false'></lib-organization-detail>\n </ng-template>\n\n</lib-list-view>\n\n\n\n", styles: [":host{flex-grow:1}.container{height:60px;padding:5px;width:100%;display:flex;flex-direction:row;background-color:var(--mat-sys-surface-container-low)}.container:hover{background-color:var(--mat-sys-surface-container-high);cursor:pointer}.even{background-color:var(--mat-sys-surface-container-lowest)}.selected{background-color:var(--mat-sys-primary-container);color:var(--mat-sys-on-primary-container)}\n"], dependencies: [{ kind: "component", type: ListViewComponent, selector: "lib-list-view", inputs: ["viewType", "itemService", "listItemTemplate", "itemDetailTemplate", "itemHeight", "columns", "sortFields", "noSelfItemsMessage", "noItemsCanCreateMessage", "noItemsMessage", "defaultQueries", "embeddedMode"], outputs: ["selected"] }, { kind: "component", type: OrganizationDetailComponent, selector: "lib-organization-detail", inputs: ["showBack"] }] });
2429
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.0.3", type: OrganizationComponent, isStandalone: true, selector: "lib-organization", viewQueries: [{ propertyName: "detailView", first: true, predicate: OrganizationDetailComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<lib-list-view\n [itemService]=\"itemService\"\n [listItemTemplate]=\"listItemTemplate\"\n [itemDetailTemplate]=\"itemDetailTemplate\"\n [viewType]=\"'list'\"\n [itemHeight]=\"60\"\n (selected)=\"onSelected($event)\"\n >\n <ng-template #listItemTemplate let-item=\"item\" let-even=\"even\" let-selected=\"selected\">\n <div mat-list-item class=\"container\" [class.even]=\"even && !selected\" [class.selected]=\"selected\">\n <div class=\"text-container\">\n <p matListItemTitle style=\"margin-bottom: 0px; margin-top: 0px\">{{item.name}}</p>\n </div>\n </div>\n </ng-template>\n\n <ng-template #itemDetailTemplate>\n <lib-organization-detail [showBack]='false'></lib-organization-detail>\n </ng-template>\n\n</lib-list-view>\n\n\n\n", styles: [":host{flex-grow:1}.container{height:60px;padding:5px;width:100%;display:flex;flex-direction:row;background-color:var(--mat-sys-surface-container-low)}.container:hover{background-color:var(--mat-sys-surface-container-high);cursor:pointer}.even{background-color:var(--mat-sys-surface-container-lowest)}.selected{background-color:var(--mat-sys-primary-container);color:var(--mat-sys-on-primary-container)}\n"], dependencies: [{ kind: "component", type: ListViewComponent, selector: "lib-list-view", inputs: ["viewType", "itemService", "listItemTemplate", "itemDetailTemplate", "itemHeight", "itemWidth", "columns", "sortFields", "noSelfItemsMessage", "noItemsCanCreateMessage", "noItemsMessage", "defaultQueries", "embeddedMode"], outputs: ["selected"] }, { kind: "component", type: OrganizationDetailComponent, selector: "lib-organization-detail", inputs: ["showBack"] }] });
2391
2430
  }
2392
2431
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: OrganizationComponent, decorators: [{
2393
2432
  type: Component,